From 216b93ad8d1087654f3a6881923306c4e81e0ed9 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Wed, 22 Apr 2026 23:35:19 +0530 Subject: [PATCH 01/88] Create @apps/ui-staff bootstrap app and compose initial staff route packages Fixes #212 --- apps/ui-staff/dist/assets/index-7FJd3hWI.css | 1 + apps/ui-staff/dist/assets/index-C8_umzkT.js | 157 ++++++++++++++++++ apps/ui-staff/dist/index.html | 14 ++ apps/ui-staff/index.html | 13 ++ apps/ui-staff/package.json | 51 ++++++ apps/ui-staff/src/App.css | 1 + apps/ui-staff/src/App.tsx | 14 ++ apps/ui-staff/src/config/oidc-config.tsx | 18 ++ apps/ui-staff/src/contexts/theme-context.tsx | 7 + apps/ui-staff/src/index.less | 6 + apps/ui-staff/src/main.tsx | 39 +++++ apps/ui-staff/src/types/react-helmet.d.ts | 6 + apps/ui-staff/src/vite-env.d.ts | 1 + apps/ui-staff/tsconfig.json | 12 ++ apps/ui-staff/vite.config.ts | 15 ++ knip.json | 9 + .../ocom/ui-staff-route-root/package.json | 33 ++++ .../ocom/ui-staff-route-root/src/index.ts | 4 + .../src/section-layout.tsx | 3 + .../ui-staff-route-root/src/vite-env.d.ts | 1 + pnpm-lock.yaml | 122 ++++++++++++++ 21 files changed, 527 insertions(+) create mode 100644 apps/ui-staff/dist/assets/index-7FJd3hWI.css create mode 100644 apps/ui-staff/dist/assets/index-C8_umzkT.js create mode 100644 apps/ui-staff/dist/index.html create mode 100644 apps/ui-staff/index.html create mode 100644 apps/ui-staff/package.json create mode 100644 apps/ui-staff/src/App.css create mode 100644 apps/ui-staff/src/App.tsx create mode 100644 apps/ui-staff/src/config/oidc-config.tsx create mode 100644 apps/ui-staff/src/contexts/theme-context.tsx create mode 100644 apps/ui-staff/src/index.less create mode 100644 apps/ui-staff/src/main.tsx create mode 100644 apps/ui-staff/src/types/react-helmet.d.ts create mode 100644 apps/ui-staff/src/vite-env.d.ts create mode 100644 apps/ui-staff/tsconfig.json create mode 100644 apps/ui-staff/vite.config.ts create mode 100644 packages/ocom/ui-staff-route-root/package.json create mode 100644 packages/ocom/ui-staff-route-root/src/index.ts create mode 100644 packages/ocom/ui-staff-route-root/src/section-layout.tsx create mode 100644 packages/ocom/ui-staff-route-root/src/vite-env.d.ts diff --git a/apps/ui-staff/dist/assets/index-7FJd3hWI.css b/apps/ui-staff/dist/assets/index-7FJd3hWI.css new file mode 100644 index 000000000..acd50b78f --- /dev/null +++ b/apps/ui-staff/dist/assets/index-7FJd3hWI.css @@ -0,0 +1 @@ +html,body,#root{height:100%;margin:0;padding:0}.App{text-align:center} diff --git a/apps/ui-staff/dist/assets/index-C8_umzkT.js b/apps/ui-staff/dist/assets/index-C8_umzkT.js new file mode 100644 index 000000000..9564574bf --- /dev/null +++ b/apps/ui-staff/dist/assets/index-C8_umzkT.js @@ -0,0 +1,157 @@ +var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),s=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;li[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},c=(n,r,a)=>(a=n==null?{}:e(i(n)),s(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var l=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.consumer`),s=Symbol.for(`react.context`),c=Symbol.for(`react.forward_ref`),l=Symbol.for(`react.suspense`),u=Symbol.for(`react.memo`),d=Symbol.for(`react.lazy`),f=Symbol.for(`react.activity`),p=Symbol.iterator;function m(e){return typeof e!=`object`||!e?null:(e=p&&e[p]||e[`@@iterator`],typeof e==`function`?e:null)}var h={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},g=Object.assign,_={};function v(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}v.prototype.isReactComponent={},v.prototype.setState=function(e,t){if(typeof e!=`object`&&typeof e!=`function`&&e!=null)throw Error(`takes an object of state variables to update or a function which returns an object of state variables.`);this.updater.enqueueSetState(this,e,t,`setState`)},v.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,`forceUpdate`)};function y(){}y.prototype=v.prototype;function b(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}var x=b.prototype=new y;x.constructor=b,g(x,v.prototype),x.isPureReactComponent=!0;var S=Array.isArray;function C(){}var w={H:null,A:null,T:null,S:null},T=Object.prototype.hasOwnProperty;function E(e,n,r){var i=r.ref;return{$$typeof:t,type:e,key:n,ref:i===void 0?null:i,props:r}}function D(e,t){return E(e.type,t,e.props)}function O(e){return typeof e==`object`&&!!e&&e.$$typeof===t}function k(e){var t={"=":`=0`,":":`=2`};return`$`+e.replace(/[=:]/g,function(e){return t[e]})}var A=/\/+/g;function j(e,t){return typeof e==`object`&&e&&e.key!=null?k(``+e.key):t.toString(36)}function ee(e){switch(e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason;default:switch(typeof e.status==`string`?e.then(C,C):(e.status=`pending`,e.then(function(t){e.status===`pending`&&(e.status=`fulfilled`,e.value=t)},function(t){e.status===`pending`&&(e.status=`rejected`,e.reason=t)})),e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason}}throw e}function te(e,r,i,a,o){var s=typeof e;(s===`undefined`||s===`boolean`)&&(e=null);var c=!1;if(e===null)c=!0;else switch(s){case`bigint`:case`string`:case`number`:c=!0;break;case`object`:switch(e.$$typeof){case t:case n:c=!0;break;case d:return c=e._init,te(c(e._payload),r,i,a,o)}}if(c)return o=o(e),c=a===``?`.`+j(e,0):a,S(o)?(i=``,c!=null&&(i=c.replace(A,`$&/`)+`/`),te(o,r,i,``,function(e){return e})):o!=null&&(O(o)&&(o=D(o,i+(o.key==null||e&&e.key===o.key?``:(``+o.key).replace(A,`$&/`)+`/`)+c)),r.push(o)),1;c=0;var l=a===``?`.`:a+`:`;if(S(e))for(var u=0;u{t.exports=l()})),d=c(u()),f=function(e){return e.CHARSET=`charset`,e.CSS_TEXT=`cssText`,e.HREF=`href`,e.HTTPEQUIV=`http-equiv`,e.INNER_HTML=`innerHTML`,e.ITEM_PROP=`itemprop`,e.NAME=`name`,e.PROPERTY=`property`,e.REL=`rel`,e.SRC=`src`,e}({}),p=function(e){return e.BASE=`base`,e.BODY=`body`,e.HEAD=`head`,e.HTML=`html`,e.LINK=`link`,e.META=`meta`,e.NOSCRIPT=`noscript`,e.SCRIPT=`script`,e.STYLE=`style`,e.TITLE=`title`,e.FRAGMENT=`Symbol(react.fragment)`,e}({}),m={link:{rel:[`amphtml`,`canonical`,`alternate`]},meta:{charset:``,name:[`generator`,`robots`,`description`],property:[`og:type`,`og:title`,`og:url`,`og:image`,`og:image:alt`,`og:description`,`twitter:url`,`twitter:title`,`twitter:description`,`twitter:image`,`twitter:image:alt`,`twitter:card`,`twitter:site`]},script:{type:[`application/ld+json`]}},h=Object.values(p),g={accesskey:`accessKey`,charset:`charSet`,class:`className`,contenteditable:`contentEditable`,contextmenu:`contextMenu`,"http-equiv":`httpEquiv`,itemprop:`itemProp`,tabindex:`tabIndex`},_=(()=>{let e={};for(let[t,n]of Object.entries(g))e[n]=t;return e})(),v=`data-rh`,y=!!(typeof window<`u`&&window.document.createElement);function b(e,t){for(let n=e.length-1;n>=0;--n){let r=e[n][1][t];if(r!==void 0)return r}}function x(e){let t=b(e,p.TITLE),n=b(e,`titleTemplate`);if(Array.isArray(t)&&(t=t.join(``)),n&&t)return n.replace(/%s/g,()=>t);let r=b(e,`defaultTitle`);return(t||r)??void 0}function S(e,t){let n={};for(let r of t){let t=r[1][e];t&&Object.assign(n,t)}return n}function C(e){for(let t=e.length-1;t>=0;--t){let n=e[t][1].base;if(n?.href)return n}}function w(e,t){let n;for(let r of Object.keys(e)){let i=r;t.includes(i)&&!(n===f.REL&&e[n].toLowerCase()===`canonical`)&&!(i===f.REL&&e[i].toLowerCase()===`stylesheet`)&&(n=i),t.includes(i)&&(i===f.INNER_HTML||i===f.CSS_TEXT||i===f.ITEM_PROP)&&(n=i)}return n??null}function T(e,t,n){let r={};return n.map(([,e])=>e).filter(t=>Array.isArray(t[e])?!0:(t[e]!==void 0&&console.warn(`Helmet: ${e} should be of type "Array". Instead found type "${typeof t[e]}"`),!1)).map(t=>t[e]).reverse().reduce((e,n)=>{let i={};n.filter(e=>{let n=w(e,t);if(!n||!e[n])return!1;let a=e[n].toLowerCase();return r[n]||(r[n]={}),i[n]||(i[n]={}),r[n][a]?!1:(i[n][a]=!0,!0)}).reverse().forEach(t=>e.push(t));let a=Object.keys(i);for(let e of a)r[e]={...r[e],...i[e]};return e},[]).reverse()}function E(e,t){for(let[,n]of e)if(n[t])return!0;return!1}function D(e){return Array.isArray(e)?e.join(``):e}function O(e,t){for(let n of Object.keys(e))if(t[n]?.includes(e[n]))return!0;return!1}function k(e,t){let n={default:[],priority:[]};if(e)for(let r of e)O(r,t)?n.priority.push(r):n.default.push(r);return n}function A(e){let t={};for(let[n,r]of Object.entries(e))t[n]=Array.isArray(r)?r.slice():r;return t}function j(e,t){let n=e;for(let[e,r]of Object.entries(t))if(Array.isArray(r)){let t=n[e];n[e]=t?t.concat(r):r}else n[e]=r}function ee(e,t,n){let r=e[t];r?r.push(n):e[t]=[n]}function te(e){let t=T(p.LINK,[f.REL,f.HREF],e),n=T(`meta`,[f.NAME,`charSet`,`httpEquiv`,f.PROPERTY,`itemProp`],e),r=T(`script`,[f.SRC,f.INNER_HTML],e),i=E(e,`prioritizeSeoTags`),a;if(i){let e=k(t,m.link);t=e.default;let i=k(n,m.meta);n=i.default;let o=k(r,m.script);r=o.default,a={links:e.priority,meta:i.priority,script:o.priority}}return{base:C(e),bodyAttributes:S(`bodyAttributes`,e),defer:b(e,`defer`),encodeSpecialCharacters:b(e,`encodeSpecialCharacters`)??!0,htmlAttributes:S(`htmlAttributes`,e),links:t,meta:n,noscript:T(`noscript`,[f.INNER_HTML],e),onChangeClientState:b(e,`onChangeClientState`),priority:a,script:r,style:T(`style`,[f.CSS_TEXT],e),title:x(e),titleAttributes:S(`titleAttributes`,e)}}function M(e){return _[e]??e}var N=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.fragment`);function r(e,n,r){var i=null;if(r!==void 0&&(i=``+r),n.key!==void 0&&(i=``+n.key),`key`in n)for(var a in r={},n)a!==`key`&&(r[a]=n[a]);else r=n;return n=r.ref,{$$typeof:t,type:e,key:i,ref:n===void 0?null:n,props:r}}e.Fragment=n,e.jsx=r,e.jsxs=r})),P=o(((e,t)=>{t.exports=N()}))(),ne=[p.NOSCRIPT,p.SCRIPT,p.STYLE],re=(e,t=!0)=>t?e.replace(/&/g,`&`).replace(//g,`>`).replace(/"/g,`"`).replace(/'/g,`'`):e;function F(e){let t=``;for(let[n,r]of Object.entries(e)){let e=M(n),i=r===void 0?e:`${e}="${r}"`;i&&t&&(t+=` `),t+=i}return t}var ie=(e,t,n)=>{let r=F(t);r&&=` ${r}`;let i=D(e);return`${re(i,n)}`};function I(e,t,n){let r=``;for(let i of t){let t=``,a=Object.entries(i);for(let[e,r]of a)if(!(e===f.INNER_HTML||e===f.CSS_TEXT)){let i=_[e]??e,a;a=r===void 0?i:`${i}="${re(typeof r==`string`?r:String(r),n)}"`,t?t+=` ${a}`:t=a}let o=i.innerHTML??i.cssText??``,s=!ne.includes(e);r+=`<${e} ${v}="true" ${t}${s?`/>`:`>${o}`}`}return r}function ae(e,t={}){let n={};t.addHelmetDataAttr&&(n[v]=!0),t.addKey!==void 0&&(n.key=t.addKey);for(let[t,r]of Object.entries(e)){let e=g[t]??t;switch(e){case`cssText`:case`innerHTML`:n.dangerouslySetInnerHTML={__html:r};break;default:n[e]=r}}return n}function oe(e,t){return[(0,P.jsx)(`title`,{...ae(t,{addHelmetDataAttr:!0}),children:e},e)]}function se(e,t,n){return(0,d.createElement)(e,ae(t,{addHelmetDataAttr:!0,addKey:n}))}function ce(e,t){let n=[];for(let r=0;r(e.state??=te(e.helmets),e.state);return{base:{toComponent(){let e=t().base;return e?ce(`base`,[e]):[]},toString(){let e=t();return e.base?I(`base`,[e.base],e.encodeSpecialCharacters):``}},bodyAttributes:{toComponent(){let e=t().bodyAttributes;return ae(e??{})},toString(){let e=t().bodyAttributes;return F(e??{})}},htmlAttributes:{toComponent(){let e=t().htmlAttributes;return ae(e??{})},toString(){let e=t().htmlAttributes;return F(e??{})}},link:{toComponent(){return ce(`link`,t().links??[])},toString(){let e=t();return I(`link`,e.links??[],e.encodeSpecialCharacters)}},meta:{toComponent(){return ce(`meta`,t().meta??[])},toString(){let e=t();return I(`meta`,e.meta??[],e.encodeSpecialCharacters)}},noscript:{toComponent(){return ce(`noscript`,t().noscript??[])},toString(){let e=t();return I(`noscript`,e.noscript??[],e.encodeSpecialCharacters)}},priority:{toComponent(){let e=t();return[...ce(`meta`,e.priority?.meta??[]),...ce(`link`,e.priority?.links??[]),...ce(`script`,e.priority?.script??[])]},toString(){let e=t(),n=I(`meta`,e.priority?.meta??[],e.encodeSpecialCharacters),r=I(`link`,e.priority?.links??[],e.encodeSpecialCharacters),i=I(`script`,e.priority?.script??[],e.encodeSpecialCharacters),a=n;return r&&(a&&(a+=` `),a+=r),i&&(a&&(a+=` `),a+=i),a}},script:{toComponent(){return ce(`script`,t().script??[])},toString(){let e=t();return I(`script`,e.script??[],e.encodeSpecialCharacters)}},style:{toComponent(){return ce(`style`,t().style??[])},toString(){let e=t();return I(`style`,e.style??[],e.encodeSpecialCharacters)}},title:{toComponent(){let e=t();return oe(e.title??``,e.titleAttributes??{})},toString(){let e=t();return ie(e.title??``,e.titleAttributes??{},e.encodeSpecialCharacters)}}}}function ue(e,t){let n=document.head||document.querySelector(p.HEAD),r=n.querySelectorAll(`${e}[${v}]`),i=[],a=[...r],o=[];for(let n of t){let t=document.createElement(e);for(let[e,r]of Object.entries(n))if(Object.prototype.hasOwnProperty.call(n,e)){let i=_[e]??e;i===f.INNER_HTML?t.innerHTML=r:i===f.CSS_TEXT?t.styleSheet?t.styleSheet.cssText=n.cssText:t.appendChild(document.createTextNode(n.cssText)):t.setAttribute(i,r??``)}t.setAttribute(v,`true`);let r={};for(let{name:e,value:n}of t.attributes)r[e]=n;i.push(r);for(let e=0;;++e){if(t.isEqualNode(a[e])){a.splice(e,1);break}if(e>=a.length){o.push(t);break}}}return a.forEach(e=>e.parentNode?.removeChild(e)),o.forEach(e=>n.appendChild(e)),{allTags:i,newTags:o,oldTags:a}}function de(e,t){let[n]=document.getElementsByTagName(e);if(!n)return;let r=n.getAttribute(v),i=r?r.split(`,`):[],a=[...i],o=[];for(let e of Object.keys(t))o.push(_[e]??e);for(let[e,r]of Object.entries(t)){let t=_[e]??e;n.getAttribute(t)!==r&&n.setAttribute(t,r??``),i.includes(t)||i.push(t);let o=a.indexOf(t);o!==-1&&a.splice(o,1)}for(let e=a.length-1;e>=0;--e)n.removeAttribute(a[e]);i.length===a.length?n.removeAttribute(v):n.getAttribute(`data-rh`)!==o.join(`,`)&&n.setAttribute(v,o.join(`,`))}function L(e,t){e!==void 0&&document.title!==e&&(document.title=D(e)),de(p.TITLE,t)}function fe(e,t){let{base:n,bodyAttributes:r,defer:i,htmlAttributes:a,links:o,meta:s,noscript:c,onChangeClientState:l,script:u,style:d,title:f,titleAttributes:m}=e;de(p.BODY,r??{}),de(p.HTML,a??{}),L(f,m);let h={baseTag:ue(p.BASE,n?[n]:[]),linkTags:ue(p.LINK,o??[]),metaTags:ue(p.META,s??[]),noscriptTags:ue(p.NOSCRIPT,c??[]),scriptTags:ue(p.SCRIPT,u??[]),styleTags:ue(p.STYLE,d??[])},g={baseTag:[],bodyAttributes:{},defer:i??!1,htmlAttributes:{},linkTags:[],metaTags:[],noscriptTags:[],onChangeClientState:l??(()=>void 0),scriptTags:[],styleTags:[],title:f??``,titleAttributes:{}},_={},v={};Object.keys(h).forEach(e=>{let{allTags:t,newTags:n,oldTags:r}=h[e];g[e]=t,n.length&&(_[e]=n),r.length&&(v[e]=h[e].oldTags)}),(t||Object.keys(_).length||Object.keys(v).length)&&l?.(g,_,v)}var pe=(0,d.createContext)(void 0),me=({children:e,context:t})=>{let{current:n}=(0,d.useRef)({firstRender:!0,helmets:[],state:void 0}),r=(0,d.useRef)(null);return r.current??={clientApply(){y&&!n.state&&(n.state=te(n.helmets),n.state.defer?n.nextAnimFrameId??=requestAnimationFrame(()=>{n.state??=te(n.helmets),fe(n.state,n.firstRender),n.firstRender=!1,delete n.nextAnimFrameId}):(n.nextAnimFrameId!==void 0&&(cancelAnimationFrame(n.nextAnimFrameId),delete n.nextAnimFrameId),fe(n.state,n.firstRender),n.firstRender=!1))},update(e,t){let r=n.helmets.findIndex(t=>t[0]===e);r>=0?(delete n.state,t?n.helmets[r][1]=t:n.helmets.splice(r,1)):t&&(delete n.state,n.helmets.push([e,t]))}},t&&(!t.helmet||t.helmet!==n.serverState)&&(n.serverState??=le(n),t.helmet=n.serverState),(0,P.jsx)(pe,{value:r.current,children:e})};function he(e,t){if(typeof e!=`string`)throw Error(`You may be attempting to nest components within each other, which is not allowed. Refer to our API for more information.`);if(!h.includes(e))throw Error(`Only elements types ${h.join(`, `)} are allowed. Helmet does not support rendering <${e}> elements. Refer to our API for more information.`);if(!(!t||typeof t==`string`||Array.isArray(t)))throw Error(`Helmet expects a string as a child of <${e}>. Did you forget to wrap your children in braces? ( <${e}>{\`\`} ) Refer to our API for more information.`)}function ge(e){let t=g[e];return t&&console.warn(`"${e}" is not a valid JSX prop, replace it by "${t}"`),t??e}function _e(e){let t=A(e);for(let t of Object.values(e))if(Array.isArray(t)){for(let e of t)if(e)for(let t of Object.keys(e)){let n=ge(t);n!==t&&(e[n]=e[t],delete e[t])}}else if(t&&typeof t==`object`){let e=t;for(let t of Object.keys(e)){let n=ge(t);n!==t&&(e[n]=e[t],delete e[t])}}return d.Children.forEach(e.children,e=>{if(e==null)return;if(typeof e!=`object`||!(`props`in e))throw Error(`"${typeof e}" is not a valid descendant`);let n,r={};if(e.props)for(let[t,i]of Object.entries(e.props))t===`children`?n=i:r[ge(t)]=i;let{type:i}=e;typeof i==`symbol`&&(i=i.toString()),he(i,n);function a(e){typeof e!=`string`&&console.error(`child of ${i} element should be a string`)}switch(i){case p.BASE:t.base=r;break;case p.BODY:t.bodyAttributes=r;break;case p.FRAGMENT:j(t,_e({children:n}));break;case p.HTML:t.htmlAttributes=r;break;case p.LINK:case p.META:if(n)throw Error(`<${i} /> elements are self-closing and can not contain children. Refer to our API for more information.`);ee(t,i,r);break;case p.NOSCRIPT:case p.SCRIPT:n!==void 0&&(a(n),r.innerHTML=n),ee(t,i,r);break;case p.STYLE:a(n),r.cssText=n,ee(t,i,r);break;case p.TITLE:t.titleAttributes=r,typeof n==`string`?t.title=n:Array.isArray(n)&&(t.title=n.join(``));break;case p.HEAD:default:}}),delete t.children,t}var ve=e=>{let t=(0,d.use)(pe);if(!t)throw Error(` component must be within a children tree`);let n=(0,d.useId)();return t.update(n,_e(e)),(0,d.useEffect)(()=>{t.update(n,_e(e)),t.clientApply()}),(0,d.useEffect)(()=>()=>{t.update(n,void 0),t.clientApply()},[t,n]),null},ye=(0,d.createContext)({description:``,title:``}),be=({children:e,description:t,extraMetaTags:n,image:r,siteName:i,socialDescription:a,socialTitle:o,title:s,url:c})=>{let l=o||s,u=a||t,f=(0,d.useMemo)(()=>({description:t,image:r,siteName:i,socialDescription:a,socialTitle:o,title:s,url:c}),[t,r,i,a,o,s,c]),p=[];if(n?.length)for(let e=0;e{let t=d.useRef(e);return t.current=e,d.useCallback((...e)=>t.current?.(...e),[])};function R(){return!!(typeof window<`u`&&window.document&&window.document.createElement)}var Se=R()?d.useLayoutEffect:d.useEffect,z=(e,t)=>{let n=d.useRef(!0);Se(()=>e(n.current),t),Se(()=>(n.current=!1,()=>{n.current=!0}),[])},Ce=e=>{let t=d.useRef(!1),[n,r]=d.useState(e);d.useEffect(()=>(t.current=!1,()=>{t.current=!0}),[]);function i(e,n){n&&t.current||r(e)}return[n,i]},we=o((e=>{var t=Symbol.for(`react.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.provider`),s=Symbol.for(`react.context`),c=Symbol.for(`react.server_context`),l=Symbol.for(`react.forward_ref`),u=Symbol.for(`react.suspense`),d=Symbol.for(`react.suspense_list`),f=Symbol.for(`react.memo`),p=Symbol.for(`react.lazy`);function m(e){if(typeof e==`object`&&e){var m=e.$$typeof;switch(m){case t:switch(e=e.type,e){case r:case a:case i:case u:case d:return e;default:switch(e&&=e.$$typeof,e){case c:case s:case l:case p:case f:case o:return e;default:return m}}case n:return m}}}e.ForwardRef=l,e.isMemo=function(e){return m(e)===f}})),Te=o(((e,t)=>{t.exports=we()}));function Ee(e,t,n){let r=d.useRef({});return(!(`value`in r.current)||n(r.current.condition,t))&&(r.current.value=e(),r.current.condition=t),r.current.value}var De=Symbol.for(`react.element`),Oe=Symbol.for(`react.transitional.element`),ke=Symbol.for(`react.fragment`);function Ae(e){return e&&typeof e==`object`&&(e.$$typeof===De||e.$$typeof===Oe)&&e.type===ke}var je=Te(),Me=Number(d.version.split(`.`)[0]),Ne=(e,t)=>{typeof e==`function`?e(t):typeof e==`object`&&e&&`current`in e&&(e.current=t)},Pe=(...e)=>{let t=e.filter(Boolean);return t.length<=1?t[0]:t=>{e.forEach(e=>{Ne(e,t)})}},Fe=(...e)=>Ee(()=>Pe(...e),e,(e,t)=>e.length!==t.length||e.every((e,n)=>e!==t[n])),Ie=e=>{if(!e)return!1;if(Le(e)&&Me>=19)return!0;let t=(0,je.isMemo)(e)?e.type.type:e.type;return!(typeof t==`function`&&!t.prototype?.render&&t.$$typeof!==je.ForwardRef||typeof e==`function`&&!e.prototype?.render&&e.$$typeof!==je.ForwardRef)};function Le(e){return(0,d.isValidElement)(e)&&!Ae(e)}var Re=e=>Le(e)&&Ie(e),ze=e=>{if(e&&Le(e)){let t=e;return t.props.propertyIsEnumerable(`ref`)?t.props.ref:t.ref}return null};function Be(e,t){let n=e;for(let e=0;e`u`?Object.keys:Reflect.ownKeys;function Ke(e,t={}){let{prepareArray:n}=t,r=n||(()=>[]),i=We(e[0]);return e.forEach(e=>{function t(n,a){let o=new Set(a),s=Be(e,n),c=Array.isArray(s);if(c||Ue(s)){if(!o.has(s)){o.add(s);let e=Be(i,n);c?i=He(i,n,r(e,s)):(!e||typeof e!=`object`)&&(i=He(i,n,We(s))),Ge(s).forEach(e=>{Object.getOwnPropertyDescriptor(s,e).enumerable&&t([...n,e],o)})}}else i=He(i,n,s)}t([])}),i}function qe(...e){return Ke(e)}var Je={},Ye=[],Xe=e=>{Ye.push(e)};function Ze(e,t){}function Qe(e,t){}function $e(){Je={}}function et(e,t,n){!t&&!Je[n]&&(e(!1,n),Je[n]=!0)}function tt(e,t){et(Ze,e,t)}function nt(e,t){et(Qe,e,t)}tt.preMessage=Xe,tt.resetWarned=$e,tt.noteOnce=nt;function rt(e,t){let n=Object.assign({},e);return Array.isArray(t)&&t.forEach(e=>{delete n[e]}),n}function it(e,t={}){let n=[];return d.Children.forEach(e,e=>{e==null&&!t.keepEmpty||(Array.isArray(e)?n=n.concat(it(e)):Ae(e)&&e.props?n=n.concat(it(e.props.children,t)):n.push(e))}),n}function at(){}var{resetWarned:ot}=tt,st=d.createContext({}),ct=()=>{let e=()=>{};return e.deprecated=at,e};function lt(e){return e instanceof HTMLElement||e instanceof SVGElement}function ut(e){return e&&typeof e==`object`&<(e.nativeElement)?e.nativeElement:lt(e)?e:null}var dt=d.createContext(null);function ft({children:e,onBatchResize:t}){let n=d.useRef(0),r=d.useRef([]),i=d.useContext(dt),a=d.useCallback((e,a,o)=>{n.current+=1;let s=n.current;r.current.push({size:e,element:a,data:o}),Promise.resolve().then(()=>{s===n.current&&(t?.(r.current),r.current=[])}),i?.(e,a,o)},[t,i]);return d.createElement(dt.Provider,{value:a},e)}var pt=new Map;function mt(e){e.forEach(e=>{let{target:t}=e;pt.get(t)?.forEach(e=>e(t))})}var ht;function gt(){return ht||=new ResizeObserver(mt),ht}function _t(e,t){pt.has(e)||(pt.set(e,new Set),gt().observe(e)),pt.get(e).add(t)}function vt(e,t){pt.has(e)&&(pt.get(e).delete(t),pt.get(e).size||(gt().unobserve(e),pt.delete(e)))}function yt(e,t,n,r){let i=d.useRef({width:-1,height:-1,offsetWidth:-1,offsetHeight:-1}),a=xe(e=>{let{width:t,height:a}=e.getBoundingClientRect(),{offsetWidth:o,offsetHeight:s}=e,c=Math.floor(t),l=Math.floor(a);if(i.current.width!==c||i.current.height!==l||i.current.offsetWidth!==o||i.current.offsetHeight!==s){let u={width:c,height:l,offsetWidth:o,offsetHeight:s};i.current=u;let d=o===Math.round(t)?t:o,f=s===Math.round(a)?a:s,p={...u,offsetWidth:d,offsetHeight:f};r?.(p,e),Promise.resolve().then(()=>{n?.(p,e)})}}),o=typeof t==`function`,s=d.useRef(0);d.useEffect(()=>{let n=o?t():t;return n&&e?_t(n,a):e&&o&&(s.current+=1),()=>{n&&vt(n,a)}},[e,o?s.current:t])}function bt(e,t){let{children:n,disabled:r,onResize:i,data:a}=e,o=d.useRef(null),s=d.useContext(dt),c=typeof n==`function`,l=c?n(o):n,u=!c&&d.isValidElement(l)&&Ie(l),f=Fe(u?ze(l):null,o),p=()=>ut(o.current);return d.useImperativeHandle(t,()=>p()),yt(!r,p,i,(e,t)=>{s?.(e,t,a)}),u?d.cloneElement(l,{ref:f}):l}var xt=d.forwardRef(bt);function St(){return St=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let i=n?.key||`${Ct}-${r}`;return d.createElement(xt,St({},e,{key:i,ref:r===0?t:void 0}),n)})}var Tt=d.forwardRef(wt);Tt.Collection=ft;function Et(e){var t,n,r=``;if(typeof e==`string`||typeof e==`number`)r+=e;else if(typeof e==`object`)if(Array.isArray(e)){var i=e.length;for(t=0;te.length)&&(t=e.length);for(var n=0,r=Array(t);n+setTimeout(e,16),Pt=e=>clearTimeout(e);typeof window<`u`&&`requestAnimationFrame`in window&&(Nt=e=>window.requestAnimationFrame(e),Pt=e=>window.cancelAnimationFrame(e));var Ft=0,It=new Map;function Lt(e){It.delete(e)}var Rt=(e,t=1)=>{Ft+=1;let n=Ft;function r(t){if(t===0)Lt(n),e();else{let e=Nt(()=>{r(t-1)});It.set(n,e)}}return r(t),n};Rt.cancel=e=>{let t=It.get(e);return Lt(e),Pt(t)};var zt=d.createContext({getPrefixCls:(e,t)=>t||(e?`ant-${e}`:`ant`),iconPrefixCls:`anticon`}),{Consumer:Bt}=zt,Vt={};function Ht(e){let t=d.useContext(zt),{getPrefixCls:n,direction:r,getPopupContainer:i,renderEmpty:a}=t;return{classNames:Vt,styles:Vt,...t[e],getPrefixCls:n,direction:r,getPopupContainer:i,renderEmpty:a}}function Ut(e){for(var t=0,n,r=0,i=e.length;i>=4;++r,i-=4)n=e.charCodeAt(r)&255|(e.charCodeAt(++r)&255)<<8|(e.charCodeAt(++r)&255)<<16|(e.charCodeAt(++r)&255)<<24,n=(n&65535)*1540483477+((n>>>16)*59797<<16),n^=n>>>24,t=(n&65535)*1540483477+((n>>>16)*59797<<16)^(t&65535)*1540483477+((t>>>16)*59797<<16);switch(i){case 3:t^=(e.charCodeAt(r+2)&255)<<16;case 2:t^=(e.charCodeAt(r+1)&255)<<8;case 1:t^=e.charCodeAt(r)&255,t=(t&65535)*1540483477+((t>>>16)*59797<<16)}return t^=t>>>13,t=(t&65535)*1540483477+((t>>>16)*59797<<16),((t^t>>>15)>>>0).toString(36)}function Wt(e,t){if(!e)return!1;if(e.contains)return e.contains(t);let n=t;for(;n;){if(n===e)return!0;n=n.parentNode}return!1}var Gt=`data-rc-order`,Kt=`data-rc-priority`,qt=`rc-util-key`,Jt=new Map;function Yt({mark:e}={}){return e?e.startsWith(`data-`)?e:`data-${e}`:qt}function Xt(e){return e.attachTo?e.attachTo:document.querySelector(`head`)||document.body}function Zt(e){return e===`queue`?`prependQueue`:e?`prepend`:`append`}function Qt(e){return Array.from((Jt.get(e)||e).children).filter(e=>e.tagName===`STYLE`)}function $t(e,t={}){if(!R())return null;let{csp:n,prepend:r,priority:i=0}=t,a=Zt(r),o=a===`prependQueue`,s=document.createElement(`style`);s.setAttribute(Gt,a),o&&i&&s.setAttribute(Kt,`${i}`),n?.nonce&&(s.nonce=n?.nonce),s.innerHTML=e;let c=Xt(t),{firstChild:l}=c;if(r){if(o){let e=(t.styles||Qt(c)).filter(e=>[`prepend`,`prependQueue`].includes(e.getAttribute(Gt))?i>=Number(e.getAttribute(Kt)||0):!1);if(e.length)return c.insertBefore(s,e[e.length-1].nextSibling),s}c.insertBefore(s,l)}else c.appendChild(s);return s}function en(e,t={}){let{styles:n}=t;return n||=Qt(Xt(t)),n.find(n=>n.getAttribute(Yt(t))===e)}function tn(e,t={}){let n=en(e,t);n&&Xt(t).removeChild(n)}function nn(e,t){let n=Jt.get(e);if(!n||!Wt(document,n)){let n=$t(``,t),{parentNode:r}=n;Jt.set(e,r),e.removeChild(n)}}function rn(e,t,n={}){let r=Xt(n),i=Qt(r),a={...n,styles:i};nn(r,a);let o=en(t,a);if(o)return a.csp?.nonce&&o.nonce!==a.csp?.nonce&&(o.nonce=a.csp?.nonce),o.innerHTML!==e&&(o.innerHTML=e),o;let s=$t(e,a);return s.setAttribute(Yt(a),t),s}function an(e,t,n=!1){let r=new Set;function i(e,t,a=1){let o=r.has(e);if(tt(!o,`Warning: There may be circular references`),o)return!1;if(e===t)return!0;if(n&&a>1)return!1;r.add(e);let s=a+1;if(Array.isArray(e)){if(!Array.isArray(t)||e.length!==t.length)return!1;for(let n=0;ni(e[n],t[n],s)):!1}return!1}return i(e,t)}var on=`%`;function sn(e){return e.join(on)}var cn=0,ln=class{instanceId;constructor(e){this.instanceId=e}cache=new Map;updateTimes=new Map;extracted=new Set;get(e){return this.opGet(sn(e))}opGet(e){return this.cache.get(e)||null}update(e,t){return this.opUpdate(sn(e),t)}opUpdate(e,t){let n=t(this.cache.get(e));n===null?(this.cache.delete(e),this.updateTimes.delete(e)):(this.cache.set(e,n),this.updateTimes.set(e,cn),cn+=1)}},un=`data-token-hash`,dn=`data-css-hash`,fn=`__cssinjs_instance__`;function pn(){let e=Math.random().toString(12).slice(2);if(typeof document<`u`&&document.head&&document.body){let t=document.body.querySelectorAll(`style[data-css-hash]`)||[],{firstChild:n}=document.head;Array.from(t).forEach(t=>{t[fn]||=e,t.__cssinjs_instance__===e&&document.head.insertBefore(t,n)});let r={};Array.from(document.querySelectorAll(`style[${dn}]`)).forEach(t=>{let n=t.getAttribute(dn);r[n]?t.__cssinjs_instance__===e&&t.parentNode?.removeChild(t):r[n]=!0})}return new ln(e)}var mn=d.createContext({hashPriority:`low`,cache:pn(),defaultCache:!0,autoPrefix:!1});function hn(e,t){if(e.length!==t.length)return!1;for(let n=0;n{n=n?n?.map?.get(e):void 0}),n?.value&&t&&(n.value[1]=this.cacheCallTimes++),n?.value}get(e){return this.internalGet(e,!0)?.[0]}has(e){return!!this.internalGet(e)}set(t,n){if(!this.has(t)){if(this.size()+1>e.MAX_CACHE_SIZE+e.MAX_CACHE_OFFSET){let[e]=this.keys.reduce((e,t)=>{let[,n]=e;return this.internalGet(t)[1]{if(i===t.length-1)r.set(e,{value:[n,this.cacheCallTimes++]});else{let t=r.get(e);t?t.map||=new Map:r.set(e,{map:new Map}),r=r.get(e).map}})}deleteByPath(e,t){let n=e.get(t[0]);if(t.length===1)return n.map?e.set(t[0],{map:n.map}):e.delete(t[0]),n.value?.[0];let r=this.deleteByPath(n.map,t.slice(1));return(!n.map||n.map.size===0)&&!n.value&&e.delete(t[0]),r}delete(e){if(this.has(e))return this.keys=this.keys.filter(t=>!hn(t,e)),this.deleteByPath(this.cache,e)}},_n=0,vn=class{derivatives;id;constructor(e){this.derivatives=Array.isArray(e)?e:[e],this.id=_n,e.length===0&&e.length,_n+=1}getDerivativeToken(e){return this.derivatives.reduce((t,n)=>n(e,t),void 0)}},yn=new gn;function bn(e){let t=Array.isArray(e)?e:[e];return yn.has(t)||yn.set(t,new vn(t)),yn.get(t)}var xn=new WeakMap,Sn={};function Cn(e,t){let n=xn;for(let e=0;e{let r=e[n];t+=n,r instanceof vn?t+=r.id:r&&typeof r==`object`?t+=Tn(r):t+=r}),t=Ut(t),wn.set(e,t)),t}function En(e,t){return Ut(`${t}_${Tn(e)}`)}`random-${Date.now()}-${Math.random()}`.replace(/\./g,``);var Dn=R();function V(e){return typeof e==`number`?`${e}px`:e}function On(e){let{hashCls:t,hashPriority:n=`low`}=e||{};if(!t)return``;let r=`.${t}`;return n===`low`?`:where(${r})`:r}var kn=e=>e!=null;function An(e,t){let n=typeof t==`function`?t():t;return n?{...e,csp:{...e.csp,nonce:n}}:e}var jn=(e,t=``)=>`--${t?`${t}-`:``}${e}`.replace(/([a-z0-9])([A-Z])/g,`$1-$2`).replace(/([A-Z]+)([A-Z][a-z0-9]+)/g,`$1-$2`).replace(/([a-z])([A-Z0-9])/g,`$1-$2`).toLowerCase(),Mn=(e,t,n)=>{let{hashCls:r,hashPriority:i=`low`,scope:a}=n||{};if(!Object.keys(e).length)return``;let o=`${On({hashCls:r,hashPriority:i})}.${t}`,s=[a].flat().filter(Boolean);return`${s.length?s.map(e=>`${o}.${e}`).join(`, `):o}{${Object.entries(e).map(([e,t])=>`${e}:${t};`).join(``)}}`},Nn=(e,t,n)=>{let{hashCls:r,hashPriority:i=`low`,prefix:a,unitless:o,ignore:s,preserve:c}=n||{},l={},u={};return Object.entries(e).forEach(([e,t])=>{if(c?.[e])u[e]=t;else if((typeof t==`string`||typeof t==`number`)&&!s?.[e]){let n=jn(e,a);l[n]=typeof t==`number`&&!o?.[e]?`${t}px`:String(t),u[e]=`var(${n})`}}),[u,Mn(l,t,{scope:n?.scope,hashCls:r,hashPriority:i})]},Pn=new Map;function Fn(e,t,n,r,i){let{cache:a}=d.useContext(mn),o=sn([e,...t]),s=e=>{a.opUpdate(o,t=>{let[r=0,i]=t||[void 0,void 0],a=[r,i||n()];return e?e(a):a})};d.useMemo(()=>{s()},[o]);let c=a.opGet(o)[1];return(0,d.useInsertionEffect)(()=>(s(([e,t])=>[e+1,t]),Pn.has(o)||(i?.(c),Pn.set(o,!0),Promise.resolve().then(()=>{Pn.delete(o)})),()=>{a.opUpdate(o,e=>{let[t=0,n]=e||[];return t-1==0?(r?.(n,!1),Pn.delete(o),null):[t-1,n]})}),[o]),c}var In={},Ln=`css`,Rn=new Map;function zn(e){Rn.set(e,(Rn.get(e)||0)+1)}function Bn(e,t){typeof document<`u`&&document.querySelectorAll(`style[${un}="${e}"]`).forEach(e=>{e.__cssinjs_instance__===t&&e.parentNode?.removeChild(e)})}var Vn=-1;function Hn(e,t){Rn.set(e,(Rn.get(e)||0)-1);let n=new Set;Rn.forEach((e,t)=>{e<=0&&n.add(t)}),Rn.size-n.size>Vn&&n.forEach(e=>{Bn(e,t),Rn.delete(e)})}var Un=(e,t,n,r)=>{let i={...n.getDerivativeToken(e),...t};return r&&(i=r(i)),i},Wn=`token`;function Gn(e,t,n){let{cache:{instanceId:r},container:i,hashPriority:a}=(0,d.useContext)(mn),{salt:o=``,override:s=In,formatToken:c,getComputedToken:l,cssVar:u,nonce:f}=n,p=Cn(()=>Object.assign({},...t),t),m=Tn(p),h=Tn(s),g=Tn(u);return Fn(Wn,[o,e.id,m,h,g],()=>{let t=l?l(p,s,e):Un(p,s,e,c),n={...t},r=`${o}_${u.prefix}`,i=Ut(r),d=`${Ln}-${i}`;n._tokenKey=En(n,r);let[f,m]=Nn(t,u.key,{prefix:u.prefix,ignore:u.ignore,unitless:u.unitless,preserve:u.preserve,hashPriority:a,hashCls:u.hashed?d:void 0});return f._hashId=i,zn(u.key),[f,d,n,m,u.key]},([,,,,e])=>{Hn(e,r)},([,,,e,t])=>{if(!e)return;let n={mark:dn,prepend:`queue`,attachTo:i,priority:-999};n=An(n,f);let a=rn(e,Ut(`css-var-${t}`),n);a[fn]=r,a.setAttribute(un,t)})}var Kn={animationIterationCount:1,borderImageOutset:1,borderImageSlice:1,borderImageWidth:1,boxFlex:1,boxFlexGroup:1,boxOrdinalGroup:1,columnCount:1,columns:1,flex:1,flexGrow:1,flexPositive:1,flexShrink:1,flexNegative:1,flexOrder:1,gridRow:1,gridRowEnd:1,gridRowSpan:1,gridRowStart:1,gridColumn:1,gridColumnEnd:1,gridColumnSpan:1,gridColumnStart:1,msGridRow:1,msGridRowSpan:1,msGridColumn:1,msGridColumnSpan:1,fontWeight:1,lineHeight:1,opacity:1,order:1,orphans:1,tabSize:1,widows:1,zIndex:1,zoom:1,WebkitLineClamp:1,fillOpacity:1,floodOpacity:1,stopOpacity:1,strokeDasharray:1,strokeDashoffset:1,strokeMiterlimit:1,strokeOpacity:1,strokeWidth:1},qn=`-ms-`,Jn=`-moz-`,H=`-webkit-`,Yn=`comm`,Xn=`rule`,Zn=`decl`,Qn=`@import`,$n=`@namespace`,er=`@keyframes`,tr=`@layer`,nr=Math.abs,rr=String.fromCharCode,ir=Object.assign;function ar(e,t){return lr(e,0)^45?(((t<<2^lr(e,0))<<2^lr(e,1))<<2^lr(e,2))<<2^lr(e,3):0}function or(e){return e.trim()}function sr(e,t){return(e=t.exec(e))?e[0]:e}function U(e,t,n){return e.replace(t,n)}function cr(e,t,n){return e.indexOf(t,n)}function lr(e,t){return e.charCodeAt(t)|0}function ur(e,t,n){return e.slice(t,n)}function dr(e){return e.length}function fr(e){return e.length}function pr(e,t){return t.push(e),e}function mr(e,t){return e.map(t).join(``)}function hr(e,t){return e.filter(function(e){return!sr(e,t)})}var gr=1,_r=1,vr=0,yr=0,br=0,xr=``;function Sr(e,t,n,r,i,a,o,s){return{value:e,root:t,parent:n,type:r,props:i,children:a,line:gr,column:_r,length:o,return:``,siblings:s}}function Cr(e,t){return ir(Sr(``,null,null,``,null,null,0,e.siblings),e,{length:-e.length},t)}function wr(e){for(;e.root;)e=Cr(e.root,{children:[e]});pr(e,e.siblings)}function Tr(){return br}function Er(){return br=yr>0?lr(xr,--yr):0,_r--,br===10&&(_r=1,gr--),br}function Dr(){return br=yr2||jr(br)>3?``:` `}function Ir(e,t){for(;--t&&Dr()&&!(br<48||br>102||br>57&&br<65||br>70&&br<97););return Ar(e,kr()+(t<6&&Or()==32&&Dr()==32))}function Lr(e){for(;Dr();)switch(br){case e:return yr;case 34:case 39:e!==34&&e!==39&&Lr(br);break;case 40:e===41&&Lr(e);break;case 92:Dr();break}return yr}function Rr(e,t){for(;Dr()&&e+br!==57&&!(e+br===84&&Or()===47););return`/*`+Ar(t,yr-1)+`*`+rr(e===47?e:Dr())}function zr(e){for(;!jr(Or());)Dr();return Ar(e,yr)}function Br(e){return Nr(Vr(``,null,null,null,[``],e=Mr(e),0,[0],e))}function Vr(e,t,n,r,i,a,o,s,c){for(var l=0,u=0,d=o,f=0,p=0,m=0,h=1,g=1,_=1,v=0,y=``,b=i,x=a,S=r,C=y;g;)switch(m=v,v=Dr()){case 40:if(m!=108&&lr(C,d-1)==58){cr(C+=U(Pr(v),`&`,`&\f`),`&\f`,nr(l?s[l-1]:0))!=-1&&(_=-1);break}case 34:case 39:case 91:C+=Pr(v);break;case 9:case 10:case 13:case 32:C+=Fr(m);break;case 92:C+=Ir(kr()-1,7);continue;case 47:switch(Or()){case 42:case 47:pr(Ur(Rr(Dr(),kr()),t,n,c),c),(jr(m||1)==5||jr(Or()||1)==5)&&dr(C)&&ur(C,-1,void 0)!==` `&&(C+=` `);break;default:C+=`/`}break;case 123*h:s[l++]=dr(C)*_;case 125*h:case 59:case 0:switch(v){case 0:case 125:g=0;case 59+u:_==-1&&(C=U(C,/\f/g,``)),p>0&&(dr(C)-d||h===0&&m===47)&&pr(p>32?Wr(C+`;`,r,n,d-1,c):Wr(U(C,` `,``)+`;`,r,n,d-2,c),c);break;case 59:C+=`;`;default:if(pr(S=Hr(C,t,n,l,u,i,s,y,b=[],x=[],d,a),a),v===123)if(u===0)Vr(C,t,S,S,b,a,d,s,x);else{switch(f){case 99:if(lr(C,3)===110)break;case 108:if(lr(C,2)===97)break;default:u=0;case 100:case 109:case 115:}u?Vr(e,S,S,r&&pr(Hr(e,S,S,0,0,i,s,y,i,b=[],d,x),x),i,x,d,s,r?b:x):Vr(C,S,S,S,[``],x,0,s,x)}}l=u=p=0,h=_=1,y=C=``,d=o;break;case 58:d=1+dr(C),p=m;default:if(h<1){if(v==123)--h;else if(v==125&&h++==0&&Er()==125)continue}switch(C+=rr(v),v*h){case 38:_=u>0?1:(C+=`\f`,-1);break;case 44:s[l++]=(dr(C)-1)*_,_=1;break;case 64:Or()===45&&(C+=Pr(Dr())),f=Or(),u=d=dr(y=C+=zr(kr())),v++;break;case 45:m===45&&dr(C)==2&&(h=0)}}return a}function Hr(e,t,n,r,i,a,o,s,c,l,u,d){for(var f=i-1,p=i===0?a:[``],m=fr(p),h=0,g=0,_=0;h0?p[v]+` `+y:U(y,/&\f/g,p[v])))&&(c[_++]=b);return Sr(e,t,n,i===0?Xn:s,c,l,u,d)}function Ur(e,t,n,r){return Sr(e,t,n,Yn,rr(Tr()),ur(e,2,-2),0,r)}function Wr(e,t,n,r,i){return Sr(e,t,n,Zn,ur(e,0,r),ur(e,r+1,-1),r,i)}function Gr(e,t,n){switch(ar(e,t)){case 5103:return H+`print-`+e+e;case 5737:case 4201:case 3177:case 3433:case 1641:case 4457:case 2921:case 5572:case 6356:case 5844:case 3191:case 6645:case 3005:case 4215:case 6389:case 5109:case 5365:case 5621:case 3829:case 6391:case 5879:case 5623:case 6135:case 4599:return H+e+e;case 4855:return H+e.replace(`add`,`source-over`).replace(`substract`,`source-out`).replace(`intersect`,`source-in`).replace(`exclude`,`xor`)+e;case 4789:return Jn+e+e;case 5349:case 4246:case 4810:case 6968:case 2756:return H+e+Jn+e+qn+e+e;case 5936:switch(lr(e,t+11)){case 114:return H+e+qn+U(e,/[svh]\w+-[tblr]{2}/,`tb`)+e;case 108:return H+e+qn+U(e,/[svh]\w+-[tblr]{2}/,`tb-rl`)+e;case 45:return H+e+qn+U(e,/[svh]\w+-[tblr]{2}/,`lr`)+e}case 6828:case 4268:case 2903:return H+e+qn+e+e;case 6165:return H+e+qn+`flex-`+e+e;case 5187:return H+e+U(e,/(\w+).+(:[^]+)/,H+`box-$1$2`+qn+`flex-$1$2`)+e;case 5443:return H+e+qn+`flex-item-`+U(e,/flex-|-self/g,``)+(sr(e,/flex-|baseline/)?``:qn+`grid-row-`+U(e,/flex-|-self/g,``))+e;case 4675:return H+e+qn+`flex-line-pack`+U(e,/align-content|flex-|-self/g,``)+e;case 5548:return H+e+qn+U(e,`shrink`,`negative`)+e;case 5292:return H+e+qn+U(e,`basis`,`preferred-size`)+e;case 6060:return H+`box-`+U(e,`-grow`,``)+H+e+qn+U(e,`grow`,`positive`)+e;case 4554:return H+U(e,/([^-])(transform)/g,`$1`+H+`$2`)+e;case 6187:return U(U(U(e,/(zoom-|grab)/,H+`$1`),/(image-set)/,H+`$1`),e,``)+e;case 5495:case 3959:return U(e,/(image-set\([^]*)/,H+"$1$`$1");case 4968:return U(U(e,/(.+:)(flex-)?(.*)/,H+`box-pack:$3`+qn+`flex-pack:$3`),/space-between/,`justify`)+H+e+e;case 4200:if(!sr(e,/flex-|baseline/))return qn+`grid-column-align`+ur(e,t)+e;break;case 2592:case 3360:return qn+U(e,`template-`,``)+e;case 4384:case 3616:return n&&n.some(function(e,n){return t=n,sr(e.props,/grid-\w+-end/)})?~cr(e+(n=n[t].value),`span`,0)?e:qn+U(e,`-start`,``)+e+qn+`grid-row-span:`+(~cr(n,`span`,0)?sr(n,/\d+/):sr(n,/\d+/)-+sr(e,/\d+/))+`;`:qn+U(e,`-start`,``)+e;case 4896:case 4128:return n&&n.some(function(e){return sr(e.props,/grid-\w+-start/)})?e:qn+U(U(e,`-end`,`-span`),`span `,``)+e;case 4095:case 3583:case 4068:case 2532:return U(e,/(.+)-inline(.+)/,H+`$1$2`)+e;case 8116:case 7059:case 5753:case 5535:case 5445:case 5701:case 4933:case 4677:case 5533:case 5789:case 5021:case 4765:if(dr(e)-1-t>6)switch(lr(e,t+1)){case 109:if(lr(e,t+4)!==45)break;case 102:return U(e,/(.+:)(.+)-([^]+)/,`$1`+H+`$2-$3$1`+Jn+(lr(e,t+3)==108?`$3`:`$2-$3`))+e;case 115:return~cr(e,`stretch`,0)?Gr(U(e,`stretch`,`fill-available`),t,n)+e:e}break;case 5152:case 5920:return U(e,/(.+?):(\d+)(\s*\/\s*(span)?\s*(\d+))?(.*)/,function(t,n,r,i,a,o,s){return qn+n+`:`+r+s+(i?qn+n+`-span:`+(a?o:o-+r)+s:``)+e});case 4949:if(lr(e,t+6)===121)return U(e,`:`,`:`+H)+e;break;case 6444:switch(lr(e,lr(e,14)===45?18:11)){case 120:return U(e,/(.+:)([^;\s!]+)(;|(\s+)?!.+)?/,`$1`+H+(lr(e,14)===45?`inline-`:``)+`box$3$1`+H+`$2$3$1`+qn+`$2box$3`)+e;case 100:return U(e,`:`,`:`+qn)+e}break;case 5719:case 2647:case 2135:case 3927:case 2391:return U(e,`scroll-`,`scroll-snap-`)+e}return e}function Kr(e,t){for(var n=``,r=0;r-1&&!e.return)switch(e.type){case Zn:e.return=Gr(e.value,e.length,n);return;case er:return Kr([Cr(e,{value:U(e.value,`@`,`@`+H)})],r);case Xn:if(e.length)return mr(n=e.props,function(t){switch(sr(t,r=/(::plac\w+|:read-\w+)/)){case`:read-only`:case`:read-write`:wr(Cr(e,{props:[U(t,/:(read-\w+)/,`:`+Jn+`$1`)]})),wr(Cr(e,{props:[t]})),ir(e,{props:hr(n,r)});break;case`::placeholder`:wr(Cr(e,{props:[U(t,/:(plac\w+)/,`:`+H+`input-$1`)]})),wr(Cr(e,{props:[U(t,/:(plac\w+)/,`:`+Jn+`$1`)]})),wr(Cr(e,{props:[U(t,/:(plac\w+)/,qn+`input-$1`)]})),wr(Cr(e,{props:[t]})),ir(e,{props:hr(n,r)});break}return``})}}var Xr=`data-ant-cssinjs-cache-path`,Zr=`_FILE_STYLE__`,Qr,$r=!0;function ei(){if(!Qr&&(Qr={},R())){let e=document.createElement(`div`);e.className=Xr,e.style.position=`fixed`,e.style.visibility=`hidden`,e.style.top=`-9999px`,document.body.appendChild(e);let t=getComputedStyle(e).content||``;t=t.replace(/^"/,``).replace(/"$/,``),t.split(`;`).forEach(e=>{let[t,n]=e.split(`:`);Qr[t]=n});let n=document.querySelector(`style[${Xr}]`);n&&($r=!1,n.parentNode?.removeChild(n)),document.body.removeChild(e)}}function ti(e){return ei(),!!Qr[e]}function ni(e){let t=Qr[e],n=null;if(t&&R())if($r)n=Zr;else{let t=document.querySelector(`style[${dn}="${Qr[e]}"]`);t?n=t.innerHTML:delete Qr[e]}return[n,t]}var ri=`_skip_check_`,ii=`_multi_value_`;function ai(e,t){return(t?Kr(Br(e),Jr([Yr,qr])):Kr(Br(e),qr)).replace(/\{%%%\:[^;];}/g,`;`)}function oi(e){return typeof e==`object`&&e&&(ri in e||ii in e)}function si(e,t,n=`high`){if(!t)return e;let r=On({hashCls:t,hashPriority:n});return e.split(`,`).map(e=>{let t=e.trim().split(/\s+/),n=t[0]||``,i=n.match(/^\w+/)?.[0]||``;return n=`${i}${r}${n.slice(i.length)}`,[n,...t.slice(1)].join(` `)}).join(`,`)}var ci=(e,t={},{root:n,injectHash:r,parentSelectors:i}={root:!0,parentSelectors:[]})=>{let{hashId:a,layer:o,path:s,hashPriority:c,transformers:l=[],linters:u=[]}=t,d=``,f={};function p(e){let n=e.getName(a);if(!f[n]){let[r]=ci(e.style,t,{root:!1,parentSelectors:i});f[n]=`@keyframes ${e.getName(a)}${r}`}}function m(e,t=[]){return e.forEach(e=>{Array.isArray(e)?m(e,t):e&&t.push(e)}),t}return m(Array.isArray(e)?e:[e]).forEach(e=>{let o=typeof e==`string`&&!n?{}:e;if(typeof o==`string`)d+=`${o}\n`;else if(o._keyframe)p(o);else{let e=l.reduce((e,t)=>t?.visit?.(e)||e,o);Object.keys(e).forEach(o=>{let s=e[o];if(typeof s==`object`&&s&&(o!==`animationName`||!s._keyframe)&&!oi(s)){let e=!1,l=o.trim(),u=!1;(n||r)&&a?l.startsWith(`@`)?e=!0:l=si(l===`&`?``:o,a,c):n&&!a&&(l===`&`||l===``)&&(l=``,u=!0);let[p,m]=ci(s,t,{root:u,injectHash:e,parentSelectors:[...i,l]});f={...f,...m},d+=`${l}${p}`}else{function e(e,t){let n=e.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`),r=t;!Kn[e]&&typeof r==`number`&&r!==0&&(r=`${r}px`),e===`animationName`&&t?._keyframe&&(p(t),r=t.getName(a)),d+=`${n}:${r};`}let t=s?.value??s;typeof s==`object`&&s?.[ii]&&Array.isArray(t)?t.forEach(t=>{e(o,t)}):kn(t)&&e(o,t)}})}}),n?o&&(d&&=`@layer ${o.name} {${d}}`,o.dependencies&&(f[`@layer ${o.name}`]=o.dependencies.map(e=>`@layer ${e}, ${o.name};`).join(` +`))):d=`{${d}}`,[d,f]};function li(e,t){return Ut(`${e.join(`%`)}${t}`)}var ui=`style`;function di(e,t){let{path:n,hashId:r,layer:i,nonce:a,clientOnly:o,order:s=0}=e,{mock:c,hashPriority:l,container:u,transformers:f,linters:p,cache:m,layer:h,autoPrefix:g}=d.useContext(mn),_=[r||``];h&&_.push(`layer`),_.push(...n);let v=Dn;Fn(ui,_,()=>{let e=_.join(`|`);if(ti(e)){let[t,n]=ni(e);if(t)return[t,n,{},o,s]}let[a,c]=ci(t(),{hashId:r,hashPriority:l,layer:h?i:void 0,path:n.join(`-`),transformers:f,linters:p}),u=ai(a,g||!1);return[u,li(_,u),c,o,s]},(e,t)=>{let[,n]=e;t&&Dn&&tn(n,{mark:dn,attachTo:u})},e=>{let[t,n,r,,i]=e;if(v&&t!==`_FILE_STYLE__`){let e={mark:dn,prepend:h?!1:`queue`,attachTo:u,priority:i};e=An(e,a);let o=[],s=[];Object.keys(r).forEach(e=>{e.startsWith(`@layer`)?o.push(e):s.push(e)}),o.forEach(t=>{rn(ai(r[t],g||!1),`_layer-${t}`,{...e,prepend:!0})});let c=rn(t,n,e);c[fn]=m.instanceId,s.forEach(t=>{rn(ai(r[t],g||!1),`_effect-${t}`,e)})}})}var fi=`cssVar`,pi=(e,t)=>{let{key:n,prefix:r,unitless:i,ignore:a,token:o,hashId:s,scope:c,nonce:l}=e,{cache:{instanceId:u},container:f,hashPriority:p}=(0,d.useContext)(mn),{_tokenKey:m}=o,h=Array.isArray(c)?c.join(`@@`):c,g=[...e.path,n,h,m];return Fn(fi,g,()=>{let[e,o]=Nn(t(),n,{prefix:r,unitless:i,ignore:a,scope:c,hashPriority:p,hashCls:s});return[e,o,li(g,o),n]},([,,e])=>{Dn&&tn(e,{mark:dn,attachTo:f})},([,e,t])=>{if(!e)return;let r={mark:dn,prepend:`queue`,attachTo:f,priority:-999};r=An(r,l);let i=rn(e,t,r);i[fn]=u,i.setAttribute(un,n)})},mi=class{name;style;constructor(e,t){this.name=e,this.style=t}getName(e=``){return e?`${e}-${this.name}`:this.name}_keyframe=!0};function hi(e){return e.notSplit=!0,e}hi([`borderTop`,`borderBottom`]),hi([`borderTop`]),hi([`borderBottom`]),hi([`borderLeft`,`borderRight`]),hi([`borderLeft`]),hi([`borderRight`]);function gi(e){"@babel/helpers - typeof";return gi=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},gi(e)}function _i(e){if(Array.isArray(e))return e}function vi(e,t){var n=e==null?null:typeof Symbol<`u`&&e[Symbol.iterator]||e[`@@iterator`];if(n!=null){var r,i,a,o,s=[],c=!0,l=!1;try{if(a=(n=n.call(e)).next,t===0){if(Object(n)!==n)return;c=!1}else for(;!(c=(r=a.call(n)).done)&&(s.push(r.value),s.length!==t);c=!0);}catch(e){l=!0,i=e}finally{try{if(!c&&n.return!=null&&(o=n.return(),Object(o)!==o))return}finally{if(l)throw i}}return s}}function yi(){throw TypeError(`Invalid attempt to destructure non-iterable instance. +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function bi(e,t){return _i(e)||vi(e,t)||At(e,t)||yi()}function xi(e,t){if(gi(e)!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(gi(r)!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}function Si(e){var t=xi(e,`string`);return gi(t)==`symbol`?t:t+``}function Ci(e,t,n){return(t=Si(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function wi(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function Ti(e){for(var t=1;t1e4){var t=Date.now();this.lastAccessBeat.forEach(function(n,r){t-n>Qi&&(e.map.delete(r),e.lastAccessBeat.delete(r))}),this.accessBeat=0}}}]),e}());function ea(e,t){return d.useMemo(function(){var n=$i.get(t);if(n)return n;var r=e();return $i.set(t,r),r},t)}var ta=function(){return{}};function na(e){var t=e.useCSP,n=t===void 0?ta:t,r=e.useToken,i=e.usePrefix,a=e.getResetStyles,o=e.getCommonStyle,s=e.getCompUnitless;function c(e,t,n,r){var i=Array.isArray(e)?e[0]:e;function a(e){return`${String(i)}${e.slice(0,1).toUpperCase()}${e.slice(1)}`}var o=r?.unitless||{},c=Ti(Ti({},typeof s==`function`?s(e):{}),{},Ci({},a(`zIndexPopup`),!0));Object.keys(o).forEach(function(e){c[a(e)]=o[e]});var d=Ti(Ti({},r),{},{unitless:c,prefixToken:a}),f=u(e,t,n,d),p=l(i,n,d);return function(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:e,n=f(e,t),i=r?.extraCssVarPrefixCls,a=typeof i==`function`?i({prefixCls:e,rootCls:t}):i;return[n,p(a!=null&&a.length?[t].concat(Mt(a)):t)]}}function l(e,t,i){var a=i.unitless,o=i.prefixToken,s=i.ignore;return function(c){var l=r(),u=l.cssVar,d=l.realToken,f=n();return pi({path:[e],prefix:u.prefix,key:u.key,unitless:a,ignore:s,token:d,scope:c,nonce:function(){return f.nonce}},function(){var n=Xi(e,d,t),r=Ui(e,d,n,{deprecatedTokens:i?.deprecatedTokens});return n&&Object.keys(n).forEach(function(e){r[o(e)]=r[e],delete r[e]}),r}),u?.key}}function u(t,s,c){var l=arguments.length>3&&arguments[3]!==void 0?arguments[3]:{},u=Array.isArray(t)?t:[t,t],f=bi(u,1)[0],p=u.join(`-`),m=e.layer||{name:`antd`};return function(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:e,u=r(),h=u.theme,g=u.realToken,_=u.hashId,v=u.token,y=u.cssVar,b=u.zeroRuntime;if((0,d.useMemo)(function(){return b},[]))return _;var x=i(),S=x.rootPrefixCls,C=x.iconPrefixCls,w=n(),T=`css`,E=ea(function(){var e=new Set;return Object.keys(l.unitless||{}).forEach(function(t){e.add(jn(t,y.prefix)),e.add(jn(t,Hi(f,y.prefix)))}),Vi(T,e)},[T,f,y?.prefix]),D=Zi(T),O=D.max,k=D.min,A={theme:h,token:v,hashId:_,nonce:function(){return w.nonce},clientOnly:l.clientOnly,layer:m,order:l.order||-999};return typeof a==`function`&&di(Ti(Ti({},A),{},{clientOnly:!1,path:[`Shared`,S]}),function(){return a(v,{prefix:{rootPrefixCls:S,iconPrefixCls:C},csp:w})}),di(Ti(Ti({},A),{},{path:[p,e,C]}),function(){if(l.injectStyle===!1)return[];var n=Yi(v),r=n.token,i=n.flush,a=Xi(f,g,c),u=`.${e}`,d=Ui(f,g,a,{deprecatedTokens:l.deprecatedTokens});a&&gi(a)===`object`&&Object.keys(a).forEach(function(e){a[e]=`var(${jn(e,Hi(f,y.prefix))})`});var p=Ki(r,{componentCls:u,prefixCls:e,iconCls:`.${C}`,antCls:`.${S}`,calc:E,max:O,min:k},a),m=s(p,{hashId:_,prefixCls:e,rootPrefixCls:S,iconPrefixCls:C});i(f,d);var h=typeof o==`function`?o(p,e,t,l.resetFont):null;return[l.resetStyle===!1?null:h,m]}),_}}function f(e,t,n){var r=u(e,t,n,Ti({resetStyle:!1,order:-998},arguments.length>3&&arguments[3]!==void 0?arguments[3]:{}));return function(e){var t=e.prefixCls,n=e.rootCls;return r(t,n===void 0?t:n),null}}return{genStyleHooks:c,genSubStyleComponent:f,genComponentStyleHook:u}}var ra=[`blue`,`purple`,`cyan`,`green`,`magenta`,`pink`,`red`,`orange`,`yellow`,`volcano`,`geekblue`,`lime`,`gold`];function ia(e){return(e+8)/e}function aa(e){let t=Array.from({length:10}).map((t,n)=>{let r=n-1,i=e*Math.E**(r/5);return Math.floor((n>1?Math.floor(i):Math.ceil(i))/2)*2});return t[1]=e,t.map(e=>({size:e,lineHeight:ia(e)}))}var oa=`6.3.5`,sa={blue:`#1677FF`,purple:`#722ED1`,cyan:`#13C2C2`,green:`#52C41A`,magenta:`#EB2F96`,pink:`#EB2F96`,red:`#F5222D`,orange:`#FA8C16`,yellow:`#FADB14`,volcano:`#FA541C`,geekblue:`#2F54EB`,gold:`#FAAD14`,lime:`#A0D911`},ca={...sa,colorPrimary:`#1677ff`,colorSuccess:`#52c41a`,colorWarning:`#faad14`,colorError:`#ff4d4f`,colorInfo:`#1677ff`,colorLink:``,colorTextBase:``,colorBgBase:``,fontFamily:`-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, +'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', +'Noto Color Emoji'`,fontFamilyCode:`'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace`,fontSize:14,lineWidth:1,lineType:`solid`,motionUnit:.1,motionBase:0,motionEaseOutCirc:`cubic-bezier(0.08, 0.82, 0.17, 1)`,motionEaseInOutCirc:`cubic-bezier(0.78, 0.14, 0.15, 0.86)`,motionEaseOut:`cubic-bezier(0.215, 0.61, 0.355, 1)`,motionEaseInOut:`cubic-bezier(0.645, 0.045, 0.355, 1)`,motionEaseOutBack:`cubic-bezier(0.12, 0.4, 0.29, 1.46)`,motionEaseInBack:`cubic-bezier(0.71, -0.46, 0.88, 0.6)`,motionEaseInQuint:`cubic-bezier(0.755, 0.05, 0.855, 0.06)`,motionEaseOutQuint:`cubic-bezier(0.23, 1, 0.32, 1)`,borderRadius:6,sizeUnit:4,sizeStep:4,sizePopupArrow:16,controlHeight:32,zIndexBase:0,zIndexPopupBase:1e3,opacityImage:1,wireframe:!1,motion:!0},la={aliceblue:`9ehhb`,antiquewhite:`9sgk7`,aqua:`1ekf`,aquamarine:`4zsno`,azure:`9eiv3`,beige:`9lhp8`,bisque:`9zg04`,black:`0`,blanchedalmond:`9zhe5`,blue:`73`,blueviolet:`5e31e`,brown:`6g016`,burlywood:`8ouiv`,cadetblue:`3qba8`,chartreuse:`4zshs`,chocolate:`87k0u`,coral:`9yvyo`,cornflowerblue:`3xael`,cornsilk:`9zjz0`,crimson:`8l4xo`,cyan:`1ekf`,darkblue:`3v`,darkcyan:`rkb`,darkgoldenrod:`776yz`,darkgray:`6mbhl`,darkgreen:`jr4`,darkgrey:`6mbhl`,darkkhaki:`7ehkb`,darkmagenta:`5f91n`,darkolivegreen:`3bzfz`,darkorange:`9yygw`,darkorchid:`5z6x8`,darkred:`5f8xs`,darksalmon:`9441m`,darkseagreen:`5lwgf`,darkslateblue:`2th1n`,darkslategray:`1ugcv`,darkslategrey:`1ugcv`,darkturquoise:`14up`,darkviolet:`5rw7n`,deeppink:`9yavn`,deepskyblue:`11xb`,dimgray:`442g9`,dimgrey:`442g9`,dodgerblue:`16xof`,firebrick:`6y7tu`,floralwhite:`9zkds`,forestgreen:`1cisi`,fuchsia:`9y70f`,gainsboro:`8m8kc`,ghostwhite:`9pq0v`,goldenrod:`8j4f4`,gold:`9zda8`,gray:`50i2o`,green:`pa8`,greenyellow:`6senj`,grey:`50i2o`,honeydew:`9eiuo`,hotpink:`9yrp0`,indianred:`80gnw`,indigo:`2xcoy`,ivory:`9zldc`,khaki:`9edu4`,lavenderblush:`9ziet`,lavender:`90c8q`,lawngreen:`4vk74`,lemonchiffon:`9zkct`,lightblue:`6s73a`,lightcoral:`9dtog`,lightcyan:`8s1rz`,lightgoldenrodyellow:`9sjiq`,lightgray:`89jo3`,lightgreen:`5nkwg`,lightgrey:`89jo3`,lightpink:`9z6wx`,lightsalmon:`9z2ii`,lightseagreen:`19xgq`,lightskyblue:`5arju`,lightslategray:`4nwk9`,lightslategrey:`4nwk9`,lightsteelblue:`6wau6`,lightyellow:`9zlcw`,lime:`1edc`,limegreen:`1zcxe`,linen:`9shk6`,magenta:`9y70f`,maroon:`4zsow`,mediumaquamarine:`40eju`,mediumblue:`5p`,mediumorchid:`79qkz`,mediumpurple:`5r3rv`,mediumseagreen:`2d9ip`,mediumslateblue:`4tcku`,mediumspringgreen:`1di2`,mediumturquoise:`2uabw`,mediumvioletred:`7rn9h`,midnightblue:`z980`,mintcream:`9ljp6`,mistyrose:`9zg0x`,moccasin:`9zfzp`,navajowhite:`9zest`,navy:`3k`,oldlace:`9wq92`,olive:`50hz4`,olivedrab:`472ub`,orange:`9z3eo`,orangered:`9ykg0`,orchid:`8iu3a`,palegoldenrod:`9bl4a`,palegreen:`5yw0o`,paleturquoise:`6v4ku`,palevioletred:`8k8lv`,papayawhip:`9zi6t`,peachpuff:`9ze0p`,peru:`80oqn`,pink:`9z8wb`,plum:`8nba5`,powderblue:`6wgdi`,purple:`4zssg`,rebeccapurple:`3zk49`,red:`9y6tc`,rosybrown:`7cv4f`,royalblue:`2jvtt`,saddlebrown:`5fmkz`,salmon:`9rvci`,sandybrown:`9jn1c`,seagreen:`1tdnb`,seashell:`9zje6`,sienna:`6973h`,silver:`7ir40`,skyblue:`5arjf`,slateblue:`45e4t`,slategray:`4e100`,slategrey:`4e100`,snow:`9zke2`,springgreen:`1egv`,steelblue:`2r1kk`,tan:`87yx8`,teal:`pds`,thistle:`8ggk8`,tomato:`9yqfb`,turquoise:`2j4r4`,violet:`9b10u`,wheat:`9ld4j`,white:`9zldr`,whitesmoke:`9lhpx`,yellow:`9zl6o`,yellowgreen:`61fzm`},ua=Math.round;function da(e,t){let n=e.replace(/^[^(]*\((.*)/,`$1`).replace(/\).*/,``).match(/\d*\.?\d+%?/g)||[],r=n.map(e=>parseFloat(e));for(let e=0;e<3;e+=1)r[e]=t(r[e]||0,n[e]||``,e);return n[3]?r[3]=n[3].includes(`%`)?r[3]/100:r[3]:r[3]=1,r}var fa=(e,t,n)=>n===0?e:e/100;function pa(e,t){let n=t||255;return e>n?n:e<0?0:e}var ma=class e{isValid=!0;r=0;g=0;b=0;a=1;_h;_hsl_s;_hsv_s;_l;_v;_max;_min;_brightness;constructor(t){function n(e){return e[0]in t&&e[1]in t&&e[2]in t}if(t)if(typeof t==`string`){let e=t.trim();function n(t){return e.startsWith(t)}if(/^#?[A-F\d]{3,8}$/i.test(e))this.fromHexString(e);else if(n(`rgb`))this.fromRgbString(e);else if(n(`hsl`))this.fromHslString(e);else if(n(`hsv`)||n(`hsb`))this.fromHsvString(e);else{let t=la[e.toLowerCase()];t&&this.fromHexString(parseInt(t,36).toString(16).padStart(6,`0`))}}else if(t instanceof e)this.r=t.r,this.g=t.g,this.b=t.b,this.a=t.a,this._h=t._h,this._hsl_s=t._hsl_s,this._hsv_s=t._hsv_s,this._l=t._l,this._v=t._v;else if(n(`rgb`))this.r=pa(t.r),this.g=pa(t.g),this.b=pa(t.b),this.a=typeof t.a==`number`?pa(t.a,1):1;else if(n(`hsl`))this.fromHsl(t);else if(n(`hsv`))this.fromHsv(t);else throw Error(`@ant-design/fast-color: unsupported input `+JSON.stringify(t))}setR(e){return this._sc(`r`,e)}setG(e){return this._sc(`g`,e)}setB(e){return this._sc(`b`,e)}setA(e){return this._sc(`a`,e,1)}setHue(e){let t=this.toHsv();return t.h=e,this._c(t)}getLuminance(){function e(e){let t=e/255;return t<=.03928?t/12.92:((t+.055)/1.055)**2.4}let t=e(this.r),n=e(this.g),r=e(this.b);return .2126*t+.7152*n+.0722*r}getHue(){if(this._h===void 0){let e=this.getMax()-this.getMin();e===0?this._h=0:this._h=ua(60*(this.r===this.getMax()?(this.g-this.b)/e+(this.g1&&(r=1),this._c({h:t,s:n,l:r,a:this.a})}mix(e,t=50){let n=this._c(e),r=t/100,i=e=>(n[e]-this[e])*r+this[e],a={r:ua(i(`r`)),g:ua(i(`g`)),b:ua(i(`b`)),a:ua(i(`a`)*100)/100};return this._c(a)}tint(e=10){return this.mix({r:255,g:255,b:255,a:1},e)}shade(e=10){return this.mix({r:0,g:0,b:0,a:1},e)}onBackground(e){let t=this._c(e),n=this.a+t.a*(1-this.a),r=e=>ua((this[e]*this.a+t[e]*t.a*(1-this.a))/n);return this._c({r:r(`r`),g:r(`g`),b:r(`b`),a:n})}isDark(){return this.getBrightness()<128}isLight(){return this.getBrightness()>=128}equals(e){return this.r===e.r&&this.g===e.g&&this.b===e.b&&this.a===e.a}clone(){return this._c(this)}toHexString(){let e=`#`,t=(this.r||0).toString(16);e+=t.length===2?t:`0`+t;let n=(this.g||0).toString(16);e+=n.length===2?n:`0`+n;let r=(this.b||0).toString(16);if(e+=r.length===2?r:`0`+r,typeof this.a==`number`&&this.a>=0&&this.a<1){let t=ua(this.a*255).toString(16);e+=t.length===2?t:`0`+t}return e}toHsl(){return{h:this.getHue(),s:this.getHSLSaturation(),l:this.getLightness(),a:this.a}}toHslString(){let e=this.getHue(),t=ua(this.getHSLSaturation()*100),n=ua(this.getLightness()*100);return this.a===1?`hsl(${e},${t}%,${n}%)`:`hsla(${e},${t}%,${n}%,${this.a})`}toHsv(){return{h:this.getHue(),s:this.getHSVSaturation(),v:this.getValue(),a:this.a}}toRgb(){return{r:this.r,g:this.g,b:this.b,a:this.a}}toRgbString(){return this.a===1?`rgb(${this.r},${this.g},${this.b})`:`rgba(${this.r},${this.g},${this.b},${this.a})`}toString(){return this.toRgbString()}_sc(e,t,n){let r=this.clone();return r[e]=pa(t,n),r}_c(e){return new this.constructor(e)}getMax(){return this._max===void 0&&(this._max=Math.max(this.r,this.g,this.b)),this._max}getMin(){return this._min===void 0&&(this._min=Math.min(this.r,this.g,this.b)),this._min}fromHexString(e){let t=e.replace(`#`,``);function n(e,n){return parseInt(t[e]+t[n||e],16)}t.length<6?(this.r=n(0),this.g=n(1),this.b=n(2),this.a=t[3]?n(3)/255:1):(this.r=n(0,1),this.g=n(2,3),this.b=n(4,5),this.a=t[6]?n(6,7)/255:1)}fromHsl({h:e,s:t,l:n,a:r}){let i=(e%360+360)%360;if(this._h=i,this._hsl_s=t,this._l=n,this.a=typeof r==`number`?r:1,t<=0){let e=ua(n*255);this.r=e,this.g=e,this.b=e;return}let a=0,o=0,s=0,c=i/60,l=(1-Math.abs(2*n-1))*t,u=l*(1-Math.abs(c%2-1));c>=0&&c<1?(a=l,o=u):c>=1&&c<2?(a=u,o=l):c>=2&&c<3?(o=l,s=u):c>=3&&c<4?(o=u,s=l):c>=4&&c<5?(a=u,s=l):c>=5&&c<6&&(a=l,s=u);let d=n-l/2;this.r=ua((a+d)*255),this.g=ua((o+d)*255),this.b=ua((s+d)*255)}fromHsv({h:e,s:t,v:n,a:r}){let i=(e%360+360)%360;this._h=i,this._hsv_s=t,this._v=n,this.a=typeof r==`number`?r:1;let a=ua(n*255);if(this.r=a,this.g=a,this.b=a,t<=0)return;let o=i/60,s=Math.floor(o),c=o-s,l=ua(n*(1-t)*255),u=ua(n*(1-t*c)*255),d=ua(n*(1-t*(1-c))*255);switch(s){case 0:this.g=d,this.b=l;break;case 1:this.r=u,this.b=l;break;case 2:this.r=l,this.b=d;break;case 3:this.r=l,this.g=u;break;case 4:this.r=d,this.g=l;break;default:this.g=l,this.b=u;break}}fromHsvString(e){let t=da(e,fa);this.fromHsv({h:t[0],s:t[1],v:t[2],a:t[3]})}fromHslString(e){let t=da(e,fa);this.fromHsl({h:t[0],s:t[1],l:t[2],a:t[3]})}fromRgbString(e){let t=da(e,(e,t)=>t.includes(`%`)?ua(e/100*255):e);this.r=t[0],this.g=t[1],this.b=t[2],this.a=t[3]}},ha=2,ga=.16,_a=.05,va=.05,ya=.15,ba=5,xa=4,Sa=[{index:7,amount:15},{index:6,amount:25},{index:5,amount:30},{index:5,amount:45},{index:5,amount:65},{index:5,amount:85},{index:4,amount:90},{index:3,amount:95},{index:2,amount:97},{index:1,amount:98}];function Ca(e,t,n){let r;return r=Math.round(e.h)>=60&&Math.round(e.h)<=240?n?Math.round(e.h)-ha*t:Math.round(e.h)+ha*t:n?Math.round(e.h)+ha*t:Math.round(e.h)-ha*t,r<0?r+=360:r>=360&&(r-=360),r}function wa(e,t,n){if(e.h===0&&e.s===0)return e.s;let r;return r=n?e.s-ga*t:t===xa?e.s+ga:e.s+_a*t,r>1&&(r=1),n&&t===ba&&r>.1&&(r=.1),r<.06&&(r=.06),Math.round(r*100)/100}function Ta(e,t,n){let r;return r=n?e.v+va*t:e.v-ya*t,r=Math.max(0,Math.min(1,r)),Math.round(r*100)/100}function Ea(e,t={}){let n=[],r=new ma(e),i=r.toHsv();for(let e=ba;e>0;--e){let t=new ma({h:Ca(i,e,!0),s:wa(i,e,!0),v:Ta(i,e,!0)});n.push(t)}n.push(r);for(let e=1;e<=xa;e+=1){let t=new ma({h:Ca(i,e),s:wa(i,e),v:Ta(i,e)});n.push(t)}return t.theme===`dark`?Sa.map(({index:e,amount:r})=>new ma(t.backgroundColor||`#141414`).mix(n[e],r).toHexString()):n.map(e=>e.toHexString())}var Da={red:`#F5222D`,volcano:`#FA541C`,orange:`#FA8C16`,gold:`#FAAD14`,yellow:`#FADB14`,lime:`#A0D911`,green:`#52C41A`,cyan:`#13C2C2`,blue:`#1677FF`,geekblue:`#2F54EB`,purple:`#722ED1`,magenta:`#EB2F96`,grey:`#666666`},Oa=[`#fff1f0`,`#ffccc7`,`#ffa39e`,`#ff7875`,`#ff4d4f`,`#f5222d`,`#cf1322`,`#a8071a`,`#820014`,`#5c0011`];Oa.primary=Oa[5];var ka=[`#fff2e8`,`#ffd8bf`,`#ffbb96`,`#ff9c6e`,`#ff7a45`,`#fa541c`,`#d4380d`,`#ad2102`,`#871400`,`#610b00`];ka.primary=ka[5];var Aa=[`#fff7e6`,`#ffe7ba`,`#ffd591`,`#ffc069`,`#ffa940`,`#fa8c16`,`#d46b08`,`#ad4e00`,`#873800`,`#612500`];Aa.primary=Aa[5];var ja=[`#fffbe6`,`#fff1b8`,`#ffe58f`,`#ffd666`,`#ffc53d`,`#faad14`,`#d48806`,`#ad6800`,`#874d00`,`#613400`];ja.primary=ja[5];var Ma=[`#feffe6`,`#ffffb8`,`#fffb8f`,`#fff566`,`#ffec3d`,`#fadb14`,`#d4b106`,`#ad8b00`,`#876800`,`#614700`];Ma.primary=Ma[5];var Na=[`#fcffe6`,`#f4ffb8`,`#eaff8f`,`#d3f261`,`#bae637`,`#a0d911`,`#7cb305`,`#5b8c00`,`#3f6600`,`#254000`];Na.primary=Na[5];var Pa=[`#f6ffed`,`#d9f7be`,`#b7eb8f`,`#95de64`,`#73d13d`,`#52c41a`,`#389e0d`,`#237804`,`#135200`,`#092b00`];Pa.primary=Pa[5];var Fa=[`#e6fffb`,`#b5f5ec`,`#87e8de`,`#5cdbd3`,`#36cfc9`,`#13c2c2`,`#08979c`,`#006d75`,`#00474f`,`#002329`];Fa.primary=Fa[5];var Ia=[`#e6f4ff`,`#bae0ff`,`#91caff`,`#69b1ff`,`#4096ff`,`#1677ff`,`#0958d9`,`#003eb3`,`#002c8c`,`#001d66`];Ia.primary=Ia[5];var La=[`#f0f5ff`,`#d6e4ff`,`#adc6ff`,`#85a5ff`,`#597ef7`,`#2f54eb`,`#1d39c4`,`#10239e`,`#061178`,`#030852`];La.primary=La[5];var Ra=[`#f9f0ff`,`#efdbff`,`#d3adf7`,`#b37feb`,`#9254de`,`#722ed1`,`#531dab`,`#391085`,`#22075e`,`#120338`];Ra.primary=Ra[5];var za=[`#fff0f6`,`#ffd6e7`,`#ffadd2`,`#ff85c0`,`#f759ab`,`#eb2f96`,`#c41d7f`,`#9e1068`,`#780650`,`#520339`];za.primary=za[5];var Ba=[`#a6a6a6`,`#999999`,`#8c8c8c`,`#808080`,`#737373`,`#666666`,`#404040`,`#1a1a1a`,`#000000`,`#000000`];Ba.primary=Ba[5];var Va={red:Oa,volcano:ka,orange:Aa,gold:ja,yellow:Ma,lime:Na,green:Pa,cyan:Fa,blue:Ia,geekblue:La,purple:Ra,magenta:za,grey:Ba},Ha=[`#2a1215`,`#431418`,`#58181c`,`#791a1f`,`#a61d24`,`#d32029`,`#e84749`,`#f37370`,`#f89f9a`,`#fac8c3`];Ha.primary=Ha[5];var Ua=[`#2b1611`,`#441d12`,`#592716`,`#7c3118`,`#aa3e19`,`#d84a1b`,`#e87040`,`#f3956a`,`#f8b692`,`#fad4bc`];Ua.primary=Ua[5];var Wa=[`#2b1d11`,`#442a11`,`#593815`,`#7c4a15`,`#aa6215`,`#d87a16`,`#e89a3c`,`#f3b765`,`#f8cf8d`,`#fae3b7`];Wa.primary=Wa[5];var Ga=[`#2b2111`,`#443111`,`#594214`,`#7c5914`,`#aa7714`,`#d89614`,`#e8b339`,`#f3cc62`,`#f8df8b`,`#faedb5`];Ga.primary=Ga[5];var Ka=[`#2b2611`,`#443b11`,`#595014`,`#7c6e14`,`#aa9514`,`#d8bd14`,`#e8d639`,`#f3ea62`,`#f8f48b`,`#fafab5`];Ka.primary=Ka[5];var qa=[`#1f2611`,`#2e3c10`,`#3e4f13`,`#536d13`,`#6f9412`,`#8bbb11`,`#a9d134`,`#c9e75d`,`#e4f88b`,`#f0fab5`];qa.primary=qa[5];var Ja=[`#162312`,`#1d3712`,`#274916`,`#306317`,`#3c8618`,`#49aa19`,`#6abe39`,`#8fd460`,`#b2e58b`,`#d5f2bb`];Ja.primary=Ja[5];var Ya=[`#112123`,`#113536`,`#144848`,`#146262`,`#138585`,`#13a8a8`,`#33bcb7`,`#58d1c9`,`#84e2d8`,`#b2f1e8`];Ya.primary=Ya[5];var Xa=[`#111a2c`,`#112545`,`#15325b`,`#15417e`,`#1554ad`,`#1668dc`,`#3c89e8`,`#65a9f3`,`#8dc5f8`,`#b7dcfa`];Xa.primary=Xa[5];var Za=[`#131629`,`#161d40`,`#1c2755`,`#203175`,`#263ea0`,`#2b4acb`,`#5273e0`,`#7f9ef3`,`#a8c1f8`,`#d2e0fa`];Za.primary=Za[5];var Qa=[`#1a1325`,`#24163a`,`#301c4d`,`#3e2069`,`#51258f`,`#642ab5`,`#854eca`,`#ab7ae0`,`#cda8f0`,`#ebd7fa`];Qa.primary=Qa[5];var $a=[`#291321`,`#40162f`,`#551c3b`,`#75204f`,`#a02669`,`#cb2b83`,`#e0529c`,`#f37fb7`,`#f8a8cc`,`#fad2e3`];$a.primary=$a[5];var eo=[`#151515`,`#1f1f1f`,`#2d2d2d`,`#393939`,`#494949`,`#5a5a5a`,`#6a6a6a`,`#7b7b7b`,`#888888`,`#969696`];eo.primary=eo[5];function to(e,{generateColorPalettes:t,generateNeutralColorPalettes:n}){let{colorSuccess:r,colorWarning:i,colorError:a,colorInfo:o,colorPrimary:s,colorBgBase:c,colorTextBase:l}=e,u=t(s),d=t(r),f=t(i),p=t(a),m=t(o),h=n(c,l),g=t(e.colorLink||e.colorInfo),_=new ma(p[1]).mix(new ma(p[3]),50).toHexString(),v={};return ra.forEach(n=>{let r=e[n];if(r){let e=t(r);v[`${n}Hover`]=e[5],v[`${n}Active`]=e[7]}}),{...h,colorPrimaryBg:u[1],colorPrimaryBgHover:u[2],colorPrimaryBorder:u[3],colorPrimaryBorderHover:u[4],colorPrimaryHover:u[5],colorPrimary:u[6],colorPrimaryActive:u[7],colorPrimaryTextHover:u[8],colorPrimaryText:u[9],colorPrimaryTextActive:u[10],colorSuccessBg:d[1],colorSuccessBgHover:d[2],colorSuccessBorder:d[3],colorSuccessBorderHover:d[4],colorSuccessHover:d[4],colorSuccess:d[6],colorSuccessActive:d[7],colorSuccessTextHover:d[8],colorSuccessText:d[9],colorSuccessTextActive:d[10],colorErrorBg:p[1],colorErrorBgHover:p[2],colorErrorBgFilledHover:_,colorErrorBgActive:p[3],colorErrorBorder:p[3],colorErrorBorderHover:p[4],colorErrorHover:p[5],colorError:p[6],colorErrorActive:p[7],colorErrorTextHover:p[8],colorErrorText:p[9],colorErrorTextActive:p[10],colorWarningBg:f[1],colorWarningBgHover:f[2],colorWarningBorder:f[3],colorWarningBorderHover:f[4],colorWarningHover:f[4],colorWarning:f[6],colorWarningActive:f[7],colorWarningTextHover:f[8],colorWarningText:f[9],colorWarningTextActive:f[10],colorInfoBg:m[1],colorInfoBgHover:m[2],colorInfoBorder:m[3],colorInfoBorderHover:m[4],colorInfoHover:m[4],colorInfo:m[6],colorInfoActive:m[7],colorInfoTextHover:m[8],colorInfoText:m[9],colorInfoTextActive:m[10],colorLinkHover:g[4],colorLink:g[6],colorLinkActive:g[7],...v,colorBgMask:new ma(`#000`).setA(.45).toRgbString(),colorWhite:`#fff`}}var no=e=>{let t=e,n=e,r=e,i=e;return e<6&&e>=5?t=e+1:e<16&&e>=6?t=e+2:e>=16&&(t=16),e<7&&e>=5?n=4:e<8&&e>=7?n=5:e<14&&e>=8?n=6:e<16&&e>=14?n=7:e>=16&&(n=8),e<6&&e>=2?r=1:e>=6&&(r=2),e>4&&e<8?i=4:e>=8&&(i=6),{borderRadius:e,borderRadiusXS:r,borderRadiusSM:n,borderRadiusLG:t,borderRadiusOuter:i}};function ro(e){let{motionUnit:t,motionBase:n,borderRadius:r,lineWidth:i}=e;return{motionDurationFast:`${(n+t).toFixed(1)}s`,motionDurationMid:`${(n+t*2).toFixed(1)}s`,motionDurationSlow:`${(n+t*3).toFixed(1)}s`,lineWidthBold:i+1,...no(r)}}var io=e=>{let{controlHeight:t}=e;return{controlHeightSM:t*.75,controlHeightXS:t*.5,controlHeightLG:t*1.25}},ao=e=>{let t=aa(e),n=t.map(e=>e.size),r=t.map(e=>e.lineHeight),i=n[1],a=n[0],o=n[2],s=r[1],c=r[0],l=r[2];return{fontSizeSM:a,fontSize:i,fontSizeLG:o,fontSizeXL:n[3],fontSizeHeading1:n[6],fontSizeHeading2:n[5],fontSizeHeading3:n[4],fontSizeHeading4:n[3],fontSizeHeading5:n[2],lineHeight:s,lineHeightLG:l,lineHeightSM:c,fontHeight:Math.round(s*i),fontHeightLG:Math.round(l*o),fontHeightSM:Math.round(c*a),lineHeightHeading1:r[6],lineHeightHeading2:r[5],lineHeightHeading3:r[4],lineHeightHeading4:r[3],lineHeightHeading5:r[2]}};function G(e){let{sizeUnit:t,sizeStep:n}=e;return{sizeXXL:t*(n+8),sizeXL:t*(n+4),sizeLG:t*(n+2),sizeMD:t*(n+1),sizeMS:t*n,size:t*n,sizeSM:t*(n-1),sizeXS:t*(n-2),sizeXXS:t*(n-3)}}var K=(e,t)=>new ma(e).setA(t).toRgbString(),oo=(e,t)=>new ma(e).darken(t).toHexString(),so=e=>{let t=Ea(e);return{1:t[0],2:t[1],3:t[2],4:t[3],5:t[4],6:t[5],7:t[6],8:t[4],9:t[5],10:t[6]}},co=(e,t)=>{let n=e||`#fff`,r=t||`#000`;return{colorBgBase:n,colorTextBase:r,colorText:K(r,.88),colorTextSecondary:K(r,.65),colorTextTertiary:K(r,.45),colorTextQuaternary:K(r,.25),colorFill:K(r,.15),colorFillSecondary:K(r,.06),colorFillTertiary:K(r,.04),colorFillQuaternary:K(r,.02),colorBgSolid:K(r,1),colorBgSolidHover:K(r,.75),colorBgSolidActive:K(r,.95),colorBgLayout:oo(n,4),colorBgContainer:oo(n,0),colorBgElevated:oo(n,0),colorBgSpotlight:K(r,.85),colorBgBlur:`transparent`,colorBorder:oo(n,15),colorBorderDisabled:oo(n,15),colorBorderSecondary:oo(n,6)}};function lo(e){Da.pink=Da.magenta,Va.pink=Va.magenta;let t=Object.keys(sa).map(t=>{let n=e[t]===Da[t]?Va[t]:Ea(e[t]);return Array.from({length:10},()=>1).reduce((e,r,i)=>(e[`${t}-${i+1}`]=n[i],e[`${t}${i+1}`]=n[i],e),{})}).reduce((e,t)=>(e={...e,...t},e),{});return{...e,...t,...to(e,{generateColorPalettes:so,generateNeutralColorPalettes:co}),...ao(e.fontSize),...G(e),...io(e),...ro(e)}}var uo=bn(lo),fo={token:ca,override:{override:ca},hashed:!0},po=d.createContext(fo);function mo(e){return e>=0&&e<=255}function ho(e,t){let{r:n,g:r,b:i,a}=new ma(e).toRgb();if(a<1)return e;let{r:o,g:s,b:c}=new ma(t).toRgb();for(let e=.01;e<=1;e+=.01){let t=Math.round((n-o*(1-e))/e),a=Math.round((r-s*(1-e))/e),l=Math.round((i-c*(1-e))/e);if(mo(t)&&mo(a)&&mo(l))return new ma({r:t,g:a,b:l,a:Math.round(e*100)/100}).toRgbString()}return new ma({r:n,g:r,b:i,a:1}).toRgbString()}function go(e){let{override:t,...n}=e,r={...t};Object.keys(ca).forEach(e=>{delete r[e]});let i={...n,...r},a=1200,o=1600,s=1920;return i.motion===!1&&(i.motionDurationFast=`0s`,i.motionDurationMid=`0s`,i.motionDurationSlow=`0s`),{...i,colorFillContent:i.colorFillSecondary,colorFillContentHover:i.colorFill,colorFillAlter:i.colorFillQuaternary,colorBgContainerDisabled:i.colorFillTertiary,colorBorderBg:i.colorBgContainer,colorSplit:ho(i.colorBorderSecondary,i.colorBgContainer),colorTextPlaceholder:i.colorTextQuaternary,colorTextDisabled:i.colorTextQuaternary,colorTextHeading:i.colorText,colorTextLabel:i.colorTextSecondary,colorTextDescription:i.colorTextTertiary,colorTextLightSolid:i.colorWhite,colorHighlight:i.colorError,colorBgTextHover:i.colorFillSecondary,colorBgTextActive:i.colorFill,colorIcon:i.colorTextTertiary,colorIconHover:i.colorText,colorErrorOutline:ho(i.colorErrorBg,i.colorBgContainer),colorWarningOutline:ho(i.colorWarningBg,i.colorBgContainer),fontSizeIcon:i.fontSizeSM,lineWidthFocus:i.lineWidth*3,lineWidth:i.lineWidth,controlOutlineWidth:i.lineWidth*2,controlInteractiveSize:i.controlHeight/2,controlItemBgHover:i.colorFillTertiary,controlItemBgActive:i.colorPrimaryBg,controlItemBgActiveHover:i.colorPrimaryBgHover,controlItemBgActiveDisabled:i.colorFill,controlTmpOutline:i.colorFillQuaternary,controlOutline:ho(i.colorPrimaryBg,i.colorBgContainer),lineType:i.lineType,borderRadius:i.borderRadius,borderRadiusXS:i.borderRadiusXS,borderRadiusSM:i.borderRadiusSM,borderRadiusLG:i.borderRadiusLG,fontWeightStrong:600,opacityLoading:.65,linkDecoration:`none`,linkHoverDecoration:`none`,linkFocusDecoration:`none`,controlPaddingHorizontal:12,controlPaddingHorizontalSM:8,paddingXXS:i.sizeXXS,paddingXS:i.sizeXS,paddingSM:i.sizeSM,padding:i.size,paddingMD:i.sizeMD,paddingLG:i.sizeLG,paddingXL:i.sizeXL,paddingContentHorizontalLG:i.sizeLG,paddingContentVerticalLG:i.sizeMS,paddingContentHorizontal:i.sizeMS,paddingContentVertical:i.sizeSM,paddingContentHorizontalSM:i.size,paddingContentVerticalSM:i.sizeXS,marginXXS:i.sizeXXS,marginXS:i.sizeXS,marginSM:i.sizeSM,margin:i.size,marginMD:i.sizeMD,marginLG:i.sizeLG,marginXL:i.sizeXL,marginXXL:i.sizeXXL,boxShadow:` + 0 6px 16px 0 rgba(0, 0, 0, 0.08), + 0 3px 6px -4px rgba(0, 0, 0, 0.12), + 0 9px 28px 8px rgba(0, 0, 0, 0.05) + `,boxShadowSecondary:` + 0 6px 16px 0 rgba(0, 0, 0, 0.08), + 0 3px 6px -4px rgba(0, 0, 0, 0.12), + 0 9px 28px 8px rgba(0, 0, 0, 0.05) + `,boxShadowTertiary:` + 0 1px 2px 0 rgba(0, 0, 0, 0.03), + 0 1px 6px -1px rgba(0, 0, 0, 0.02), + 0 2px 4px 0 rgba(0, 0, 0, 0.02) + `,screenXS:480,screenXSMin:480,screenXSMax:575,screenSM:576,screenSMMin:576,screenSMMax:767,screenMD:768,screenMDMin:768,screenMDMax:991,screenLG:992,screenLGMin:992,screenLGMax:a-1,screenXL:a,screenXLMin:a,screenXLMax:o-1,screenXXL:o,screenXXLMin:o,screenXXLMax:s-1,screenXXXL:s,screenXXXLMin:s,boxShadowPopoverArrow:`2px 2px 5px rgba(0, 0, 0, 0.05)`,boxShadowCard:` + 0 1px 2px -2px ${new ma(`rgba(0, 0, 0, 0.16)`).toRgbString()}, + 0 3px 6px 0 ${new ma(`rgba(0, 0, 0, 0.12)`).toRgbString()}, + 0 5px 12px 4px ${new ma(`rgba(0, 0, 0, 0.09)`).toRgbString()} + `,boxShadowDrawerRight:` + -6px 0 16px 0 rgba(0, 0, 0, 0.08), + -3px 0 6px -4px rgba(0, 0, 0, 0.12), + -9px 0 28px 8px rgba(0, 0, 0, 0.05) + `,boxShadowDrawerLeft:` + 6px 0 16px 0 rgba(0, 0, 0, 0.08), + 3px 0 6px -4px rgba(0, 0, 0, 0.12), + 9px 0 28px 8px rgba(0, 0, 0, 0.05) + `,boxShadowDrawerUp:` + 0 6px 16px 0 rgba(0, 0, 0, 0.08), + 0 3px 6px -4px rgba(0, 0, 0, 0.12), + 0 9px 28px 8px rgba(0, 0, 0, 0.05) + `,boxShadowDrawerDown:` + 0 -6px 16px 0 rgba(0, 0, 0, 0.08), + 0 -3px 6px -4px rgba(0, 0, 0, 0.12), + 0 -9px 28px 8px rgba(0, 0, 0, 0.05) + `,boxShadowTabsOverflowLeft:`inset 10px 0 8px -8px rgba(0, 0, 0, 0.08)`,boxShadowTabsOverflowRight:`inset -10px 0 8px -8px rgba(0, 0, 0, 0.08)`,boxShadowTabsOverflowTop:`inset 0 10px 8px -8px rgba(0, 0, 0, 0.08)`,boxShadowTabsOverflowBottom:`inset 0 -10px 8px -8px rgba(0, 0, 0, 0.08)`,...r}}var _o={lineHeight:!0,lineHeightSM:!0,lineHeightLG:!0,lineHeightHeading1:!0,lineHeightHeading2:!0,lineHeightHeading3:!0,lineHeightHeading4:!0,lineHeightHeading5:!0,opacityLoading:!0,fontWeightStrong:!0,zIndexPopupBase:!0,zIndexBase:!0,opacityImage:!0},vo={motionBase:!0,motionUnit:!0},yo={screenXS:!0,screenXSMin:!0,screenXSMax:!0,screenSM:!0,screenSMMin:!0,screenSMMax:!0,screenMD:!0,screenMDMin:!0,screenMDMax:!0,screenLG:!0,screenLGMin:!0,screenLGMax:!0,screenXL:!0,screenXLMin:!0,screenXLMax:!0,screenXXL:!0,screenXXLMin:!0,screenXXLMax:!0,screenXXXL:!0,screenXXXLMin:!0},bo=(e,t,n)=>{let r=n.getDerivativeToken(e),{override:i,...a}=t,o={...r,override:i};return o=go(o),a&&Object.entries(a).forEach(([e,t])=>{let{theme:n,...r}=t,i=r;n&&(i=bo({...o,...r},{override:r},n)),o[e]=i}),o};function xo(){let{token:e,hashed:t,theme:n,override:r,cssVar:i,zeroRuntime:a}=d.useContext(po),{csp:o}=d.useContext(zt),s={prefix:i?.prefix??`ant`,key:i?.key??`css-var-root`},c=`${oa}-${t||``}`,l=n||uo,[u,f,p]=Gn(l,[ca,e],{salt:c,override:r,getComputedToken:bo,cssVar:{...s,unitless:_o,ignore:vo,preserve:yo},nonce:o?.nonce});return[l,p,t?f:``,u,s,!!a]}var So=(e,t=!1)=>({boxSizing:`border-box`,margin:0,padding:0,color:e.colorText,fontSize:e.fontSize,lineHeight:e.lineHeight,listStyle:`none`,fontFamily:t?`inherit`:e.fontFamily}),Co=()=>({display:`inline-flex`,alignItems:`center`,color:`inherit`,fontStyle:`normal`,lineHeight:0,textAlign:`center`,textTransform:`none`,verticalAlign:`-0.125em`,textRendering:`optimizeLegibility`,"-webkit-font-smoothing":`antialiased`,"-moz-osx-font-smoothing":`grayscale`,"> *":{lineHeight:1},svg:{display:`inline-block`}}),wo=()=>({"&::before":{display:`table`,content:`""`},"&::after":{display:`table`,clear:`both`,content:`""`}}),To=(e,t)=>({outline:`${V(e.lineWidthFocus)} solid ${e.colorPrimaryBorder}`,outlineOffset:t??1,transition:[`outline-offset`,`outline`].map(e=>`${e} 0s`).join(`, `)}),Eo=(e,t)=>({"&:focus-visible":To(e,t)}),Do=e=>({a:{color:e.colorLink,textDecoration:e.linkDecoration,backgroundColor:`transparent`,outline:`none`,cursor:`pointer`,transition:`color ${e.motionDurationSlow}`,"-webkit-text-decoration-skip":`objects`,"&:hover":{color:e.colorLinkHover},"&:active":{color:e.colorLinkActive},"&:active, &:hover":{textDecoration:e.linkHoverDecoration,outline:0},"&:focus":{textDecoration:e.linkFocusDecoration,outline:0},...Eo(e),"&[disabled]":{color:e.colorTextDisabled,cursor:`not-allowed`}}}),Oo=(e,t,n,r)=>{let i=`[class^="${t}"], [class*=" ${t}"]`,a=n?`.${n}`:i,o={boxSizing:`border-box`,"&::before, &::after":{boxSizing:`border-box`}},s={};return r!==!1&&(s={fontFamily:e.fontFamily,fontSize:e.fontSize}),{[a]:{...s,...o,[i]:o}}},ko=e=>({[`.${e}`]:{...Co(),[`.${e} .${e}-icon`]:{display:`block`}}}),{genStyleHooks:Ao,genComponentStyleHook:jo,genSubStyleComponent:Mo}=na({usePrefix:()=>{let{getPrefixCls:e,iconPrefixCls:t}=(0,d.useContext)(zt);return{rootPrefixCls:e(),iconPrefixCls:t}},useToken:()=>{let[e,t,n,r,i,a]=xo();return{theme:e,realToken:t,hashId:n,token:r,cssVar:i,zeroRuntime:a}},useCSP:()=>{let{csp:e}=(0,d.useContext)(zt);return e??{}},getResetStyles:(e,t)=>{let n=Do(e);return[n,{"&":n},ko(t?.prefix.iconPrefixCls??`anticon`)]},getCommonStyle:Oo,getCompUnitless:()=>_o}),No=(e,t)=>{let n=`--${e.replace(/\./g,``)}-${t}-`;return[e=>`${n}${e}`,(e,t)=>t?`var(${n}${e}, ${t})`:`var(${n}${e})`]},Po=(e,t)=>{let[n,r]=xo();return di({theme:n,token:r,hashId:``,path:[`ant-design-icons`,e],nonce:()=>t?.nonce,layer:{name:`antd`}},()=>ko(e))},Fo={icon:{tag:`svg`,attrs:{viewBox:`64 64 896 896`,focusable:`false`},children:[{tag:`path`,attrs:{d:`M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm193.5 301.7l-210.6 292a31.8 31.8 0 01-51.7 0L318.5 484.9c-3.8-5.3 0-12.7 6.5-12.7h46.9c10.2 0 19.9 4.9 25.9 13.3l71.2 98.8 157.2-218c6-8.3 15.6-13.3 25.9-13.3H699c6.5 0 10.3 7.4 6.5 12.7z`}}]},name:`check-circle`,theme:`filled`},Io=(0,d.createContext)({});function Lo(e){return e?.getRootNode?.()}function Ro(e){return Lo(e)instanceof ShadowRoot}function zo(e){return Ro(e)?Lo(e):null}function Bo(e){return e.replace(/-(.)/g,(e,t)=>t.toUpperCase())}function Vo(e,t){tt(e,`[@ant-design/icons] ${t}`)}function Ho(e){return typeof e==`object`&&typeof e.name==`string`&&typeof e.theme==`string`&&(typeof e.icon==`object`||typeof e.icon==`function`)}function Uo(e={}){return Object.keys(e).reduce((t,n)=>{let r=e[n];switch(n){case`class`:t.className=r,delete t.class;break;default:delete t[n],t[Bo(n)]=r}return t},{})}function Wo(e,t,n){return n?d.createElement(e.tag,{key:t,...Uo(e.attrs),...n},(e.children||[]).map((n,r)=>Wo(n,`${t}-${e.tag}-${r}`))):d.createElement(e.tag,{key:t,...Uo(e.attrs)},(e.children||[]).map((n,r)=>Wo(n,`${t}-${e.tag}-${r}`)))}function Go(e){return Ea(e)[0]}function Ko(e){return e?Array.isArray(e)?e:[e]:[]}var qo=` +.anticon { + display: inline-flex; + align-items: center; + color: inherit; + font-style: normal; + line-height: 0; + text-align: center; + text-transform: none; + vertical-align: -0.125em; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.anticon > * { + line-height: 1; +} + +.anticon svg { + display: inline-block; + vertical-align: inherit; +} + +.anticon::before { + display: none; +} + +.anticon .anticon-icon { + display: block; +} + +.anticon[tabindex] { + cursor: pointer; +} + +.anticon-spin { + -webkit-animation: loadingCircle 1s infinite linear; + animation: loadingCircle 1s infinite linear; +} + +@-webkit-keyframes loadingCircle { + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@keyframes loadingCircle { + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +`,Jo=e=>{let{csp:t,prefixCls:n,layer:r}=(0,d.useContext)(Io),i=qo;n&&(i=i.replace(/anticon/g,n)),r&&(i=`@layer ${r} {\n${i}\n}`),(0,d.useEffect)(()=>{let n=e.current,a=zo(n);rn(i,`@ant-design-icons`,{prepend:!r,csp:t,attachTo:a})},[])},Yo={primaryColor:`#333`,secondaryColor:`#E6E6E6`,calculated:!1};function Xo({primaryColor:e,secondaryColor:t}){Yo.primaryColor=e,Yo.secondaryColor=t||Go(e),Yo.calculated=!!t}function Zo(){return{...Yo}}var Qo=e=>{let{icon:t,className:n,onClick:r,style:i,primaryColor:a,secondaryColor:o,...s}=e,c=d.useRef(null),l=Yo;if(a&&(l={primaryColor:a,secondaryColor:o||Go(a)}),Jo(c),Vo(Ho(t),`icon should be icon definiton, but got ${t}`),!Ho(t))return null;let u=t;return u&&typeof u.icon==`function`&&(u={...u,icon:u.icon(l.primaryColor,l.secondaryColor)}),Wo(u.icon,`svg-${u.name}`,{className:n,onClick:r,style:i,"data-icon":u.name,width:`1em`,height:`1em`,fill:`currentColor`,"aria-hidden":`true`,...s,ref:c})};Qo.displayName=`IconReact`,Qo.getTwoToneColors=Zo,Qo.setTwoToneColors=Xo;function $o(e){let[t,n]=Ko(e);return Qo.setTwoToneColors({primaryColor:t,secondaryColor:n})}function es(){let e=Qo.getTwoToneColors();return e.calculated?[e.primaryColor,e.secondaryColor]:e.primaryColor}function ts(){return ts=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{className:n,icon:r,spin:i,rotate:a,tabIndex:o,onClick:s,twoToneColor:c,...l}=e,{prefixCls:u=`anticon`,rootClassName:f}=d.useContext(Io),p=B(f,u,{[`${u}-${r.name}`]:!!r.name,[`${u}-spin`]:!!i||r.name===`loading`},n),m=o;m===void 0&&s&&(m=-1);let h=a?{msTransform:`rotate(${a}deg)`,transform:`rotate(${a}deg)`}:void 0,[g,_]=Ko(c);return d.createElement(`span`,ts({role:`img`,"aria-label":r.name},l,{ref:t,tabIndex:m,onClick:s,className:p}),d.createElement(Qo,{icon:r,primaryColor:g,secondaryColor:_,style:h}))});ns.getTwoToneColor=es,ns.setTwoToneColor=$o;function rs(){return rs=Object.assign?Object.assign.bind():function(e){for(var t=1;td.createElement(ns,rs({},e,{ref:t,icon:Fo}))),as={icon:{tag:`svg`,attrs:{"fill-rule":`evenodd`,viewBox:`64 64 896 896`,focusable:`false`},children:[{tag:`path`,attrs:{d:`M512 64c247.4 0 448 200.6 448 448S759.4 960 512 960 64 759.4 64 512 264.6 64 512 64zm127.98 274.82h-.04l-.08.06L512 466.75 384.14 338.88c-.04-.05-.06-.06-.08-.06a.12.12 0 00-.07 0c-.03 0-.05.01-.09.05l-45.02 45.02a.2.2 0 00-.05.09.12.12 0 000 .07v.02a.27.27 0 00.06.06L466.75 512 338.88 639.86c-.05.04-.06.06-.06.08a.12.12 0 000 .07c0 .03.01.05.05.09l45.02 45.02a.2.2 0 00.09.05.12.12 0 00.07 0c.02 0 .04-.01.08-.05L512 557.25l127.86 127.87c.04.04.06.05.08.05a.12.12 0 00.07 0c.03 0 .05-.01.09-.05l45.02-45.02a.2.2 0 00.05-.09.12.12 0 000-.07v-.02a.27.27 0 00-.05-.06L557.25 512l127.87-127.86c.04-.04.05-.06.05-.08a.12.12 0 000-.07c0-.03-.01-.05-.05-.09l-45.02-45.02a.2.2 0 00-.09-.05.12.12 0 00-.07 0z`}}]},name:`close-circle`,theme:`filled`};function os(){return os=Object.assign?Object.assign.bind():function(e){for(var t=1;td.createElement(ns,os({},e,{ref:t,icon:as}))),cs={icon:{tag:`svg`,attrs:{"fill-rule":`evenodd`,viewBox:`64 64 896 896`,focusable:`false`},children:[{tag:`path`,attrs:{d:`M799.86 166.31c.02 0 .04.02.08.06l57.69 57.7c.04.03.05.05.06.08a.12.12 0 010 .06c0 .03-.02.05-.06.09L569.93 512l287.7 287.7c.04.04.05.06.06.09a.12.12 0 010 .07c0 .02-.02.04-.06.08l-57.7 57.69c-.03.04-.05.05-.07.06a.12.12 0 01-.07 0c-.03 0-.05-.02-.09-.06L512 569.93l-287.7 287.7c-.04.04-.06.05-.09.06a.12.12 0 01-.07 0c-.02 0-.04-.02-.08-.06l-57.69-57.7c-.04-.03-.05-.05-.06-.07a.12.12 0 010-.07c0-.03.02-.05.06-.09L454.07 512l-287.7-287.7c-.04-.04-.05-.06-.06-.09a.12.12 0 010-.07c0-.02.02-.04.06-.08l57.7-57.69c.03-.04.05-.05.07-.06a.12.12 0 01.07 0c.03 0 .05.02.09.06L512 454.07l287.7-287.7c.04-.04.06-.05.09-.06a.12.12 0 01.07 0z`}}]},name:`close`,theme:`outlined`};function ls(){return ls=Object.assign?Object.assign.bind():function(e){for(var t=1;td.createElement(ns,ls({},e,{ref:t,icon:cs}))),ds={icon:{tag:`svg`,attrs:{viewBox:`64 64 896 896`,focusable:`false`},children:[{tag:`path`,attrs:{d:`M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z`}}]},name:`exclamation-circle`,theme:`filled`};function fs(){return fs=Object.assign?Object.assign.bind():function(e){for(var t=1;td.createElement(ns,fs({},e,{ref:t,icon:ds}))),ms={icon:{tag:`svg`,attrs:{viewBox:`64 64 896 896`,focusable:`false`},children:[{tag:`path`,attrs:{d:`M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm32 664c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V456c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272zm-32-344a48.01 48.01 0 010-96 48.01 48.01 0 010 96z`}}]},name:`info-circle`,theme:`filled`};function hs(){return hs=Object.assign?Object.assign.bind():function(e){for(var t=1;td.createElement(ns,hs({},e,{ref:t,icon:ms}))),_s=d.createContext({}),vs=e=>{let{children:t,...n}=e,r=d.useMemo(()=>({motion:n.motion}),[n.motion]);return d.createElement(_s.Provider,{value:r},t)};function ys(e){let[,t]=d.useReducer(e=>e+1,0),n=d.useRef(e);return[xe(()=>n.current),xe(e=>{n.current=typeof e==`function`?e(n.current):e,t()})]}var bs=`none`,xs=`appear`,Ss=`enter`,Cs=`leave`,ws=`none`,Ts=`prepare`,Es=`start`,Ds=`active`,Os=`prepared`;function ks(e,t){let n={};return n[e.toLowerCase()]=t.toLowerCase(),n[`Webkit${e}`]=`webkit${t}`,n[`Moz${e}`]=`moz${t}`,n[`ms${e}`]=`MS${t}`,n[`O${e}`]=`o${t.toLowerCase()}`,n}function As(e,t){let n={animationend:ks(`Animation`,`AnimationEnd`),transitionend:ks(`Transition`,`TransitionEnd`)};return e&&(`AnimationEvent`in t||delete n.animationend.animation,`TransitionEvent`in t||delete n.transitionend.transition),n}var js=As(R(),typeof window<`u`?window:{}),Ms={};R()&&({style:Ms}=document.createElement(`div`));var Ns={};function Ps(e){if(Ns[e])return Ns[e];let t=js[e];if(t){let n=Object.keys(t),r=n.length;for(let i=0;ie[1].toUpperCase())]:`${e}-${t}`:null}var Vs=(e=>{let t=(0,d.useRef)();function n(t){t&&(t.removeEventListener(zs,e),t.removeEventListener(Rs,e))}function r(r){t.current&&t.current!==r&&n(t.current),r&&r!==t.current&&(r.addEventListener(zs,e),r.addEventListener(Rs,e),t.current=r)}return d.useEffect(()=>()=>{n(t.current),t.current=null},[]),[r,n]}),Hs=R()?d.useLayoutEffect:d.useEffect,Us=(()=>{let e=d.useRef(null);function t(){Rt.cancel(e.current)}function n(r,i=2){t();let a=Rt(()=>{i<=1?r({isCanceled:()=>a!==e.current}):n(r,i-1)});e.current=a}return d.useEffect(()=>()=>{t()},[]),[n,t]}),Ws=[Ts,Es,Ds,`end`],Gs=[Ts,Os];function Ks(e){return e===`active`||e===`end`}var qs=((e,t,n)=>{let[r,i]=Ce(ws),[a,o]=Us();function s(){i(Ts,!0)}let c=t?Gs:Ws;return Hs(()=>{if(r!==`none`&&r!==`end`){let e=c[c.indexOf(r)+1],t=n(r);t===!1?i(e,!0):e&&a(n=>{function r(){n.isCanceled()||i(e,!0)}t===!0?r():Promise.resolve(t).then(r)})}},[e,r]),d.useEffect(()=>()=>{o()},[]),[s,r]});function Js(e,t,n,{motionEnter:r=!0,motionAppear:i=!0,motionLeave:a=!0,motionDeadline:o,motionLeaveImmediately:s,onAppearPrepare:c,onEnterPrepare:l,onLeavePrepare:u,onAppearStart:f,onEnterStart:p,onLeaveStart:m,onAppearActive:h,onEnterActive:g,onLeaveActive:_,onAppearEnd:v,onEnterEnd:y,onLeaveEnd:b,onVisibleChanged:x}){let[S,C]=d.useState(),[w,T]=ys(bs),[E,D]=d.useState([null,null]),O=w(),k=(0,d.useRef)(!1),A=(0,d.useRef)(null);function j(){return n()}let ee=(0,d.useRef)(!1);function te(){T(bs),D([null,null])}let M=xe(e=>{let t=w();if(t===`none`)return;let n=j();if(e&&!e.deadline&&e.target!==n)return;let r=ee.current,i;t===`appear`&&r?i=v?.(n,e):t===`enter`&&r?i=y?.(n,e):t===`leave`&&r&&(i=b?.(n,e)),r&&i!==!1&&te()}),[N]=Vs(M),P=e=>{switch(e){case xs:return{[Ts]:c,[Es]:f,[Ds]:h};case Ss:return{[Ts]:l,[Es]:p,[Ds]:g};case Cs:return{[Ts]:u,[Es]:m,[Ds]:_};default:return{}}},ne=d.useMemo(()=>P(O),[O]),[re,F]=qs(O,!e,e=>{if(e===`prepare`){let e=ne[Ts];return e?e(j()):!1}return e in ne&&D([ne[e]?.(j(),null)||null,e]),e===`active`&&O!==`none`&&(N(j()),o>0&&(clearTimeout(A.current),A.current=setTimeout(()=>{M({deadline:!0})},o))),e===`prepared`&&te(),!0});ee.current=Ks(F);let ie=(0,d.useRef)(null);Hs(()=>{if(k.current&&ie.current===t)return;C(t);let n=k.current;k.current=!0;let o;!n&&t&&i&&(o=xs),n&&t&&r&&(o=Ss),(n&&!t&&a||!n&&s&&!t&&a)&&(o=Cs);let c=P(o);o&&(e||c.prepare)?(T(o),re()):T(bs),ie.current=t},[t]),(0,d.useEffect)(()=>{(O===`appear`&&!i||O===`enter`&&!r||O===`leave`&&!a)&&T(bs)},[i,r,a]),(0,d.useEffect)(()=>()=>{k.current=!1,clearTimeout(A.current)},[]);let I=d.useRef(!1);(0,d.useEffect)(()=>{S&&(I.current=!0),S!==void 0&&O===`none`&&((I.current||S)&&x?.(S),I.current=!0)},[S,O]);let ae=E[0];ne.prepare&&F===`start`&&(ae={transition:`none`,...ae});let oe=E[1];return[w,F,ae,S??t,!k.current&&O===`none`&&e&&i?`NONE`:F===`start`||F===`active`?oe===F:!0]}function Ys(e){return e?.length<2}function Xs(e){let t=e;typeof e==`object`&&({transitionSupport:t}=e);function n(e,n){return!!(e.motionName&&t&&n!==!1)}let r=d.forwardRef((e,t)=>{let{visible:r=!0,removeOnLeave:i=!0,forceRender:a,children:o,motionName:s,leavedClassName:c,eventProps:l}=e,{motion:u}=d.useContext(_s),f=n(e,u),p=(0,d.useRef)();function m(){return ut(p.current)}let[h,g,_,v,y]=Js(f,r,m,e),b=h(),x=d.useRef(v);v&&(x.current=!0);let S=d.useMemo(()=>{let e={};return Object.defineProperties(e,{nativeElement:{enumerable:!0,get:m},inMotion:{enumerable:!0,get:()=>()=>h()!==bs},enableMotion:{enumerable:!0,get:()=>()=>f}}),e},[]);d.useImperativeHandle(t,()=>S,[]);let C=d.useRef(0);y&&(C.current+=1);let w=d.useMemo(()=>{if(y===`NONE`)return null;let e,t={...l,visible:r};if(!o)e=null;else if(b===`none`)e=v?o({...t},p):!i&&x.current&&c?o({...t,className:c},p):a||!i&&!c?o({...t,style:{display:`none`}},p):null;else{let n;g===`prepare`?n=`prepare`:Ks(g)?n=`active`:g===`start`&&(n=`start`);let r=Bs(s,`${b}-${n}`);e=o({...t,className:B(Bs(s,b),{[r]:r&&n,[s]:typeof s==`string`}),style:_},p)}return e},[C.current]);if(Ys(o)&&Re(w)){let e=ze(w);if(e!==p)return d.cloneElement(w,{ref:Pe(e,p)})}return w});return r.displayName=`CSSMotion`,r}var Zs=Xs(Ls),Qs=`keep`,$s=`remove`,ec=`removed`;function tc(e){let t;return t=e&&typeof e==`object`&&`key`in e?e:{key:e},{...t,key:String(t.key)}}function nc(e=[]){return e.map(tc)}function rc(e=[],t=[]){let n=[],r=0,i=t.length,a=nc(e),o=nc(t);a.forEach(e=>{let t=!1;for(let a=r;a({...e,status:`add`}))),r=a),n.push({...i,status:Qs}),r+=1,t=!0;break}}t||n.push({...e,status:$s})}),r({...e,status:`add`}))));let s={};return n.forEach(({key:e})=>{s[e]=(s[e]||0)+1}),Object.keys(s).filter(e=>s[e]>1).forEach(e=>{n=n.filter(({key:t,status:n})=>t!==e||n!==`remove`),n.forEach(t=>{t.key===e&&(t.status=Qs)})}),n}function ic(){return ic=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let n=t.find(({key:t})=>e.key===t);return!(n&&n.status===`removed`&&e.status===`remove`)})}}removeKey=e=>{this.setState(t=>({keyEntities:t.keyEntities.map(t=>t.key===e?{...t,status:ec}:t)}),()=>{let{keyEntities:e}=this.state;e.filter(({status:e})=>e!==`removed`).length===0&&this.props.onAllRemoved&&this.props.onAllRemoved()})};render(){let{keyEntities:e}=this.state,{component:n,children:r,onVisibleChanged:i,onAllRemoved:a,...o}=this.props,s=n||d.Fragment,c={};return ac.forEach(e=>{c[e]=o[e],delete o[e]}),delete o.keys,d.createElement(s,o,e.map(({status:e,...n},a)=>{let o=e===`add`||e===`keep`;return d.createElement(t,ic({},c,{key:n.key,visible:o,eventProps:n,onVisibleChanged:e=>{i?.(e,{key:n.key}),e||this.removeKey(n.key)}}),Ys(r)?e=>r({...e,index:a}):(e,t)=>r({...e,index:a},t))}))}}return n}var sc=oc(Ls),cc=Zs,lc=`accept acceptCharset accessKey action allowFullScreen allowTransparency + alt async autoComplete autoFocus autoPlay capture cellPadding cellSpacing challenge + charSet checked classID className colSpan cols content contentEditable contextMenu + controls coords crossOrigin data dateTime default defer dir disabled download draggable + encType form formAction formEncType formMethod formNoValidate formTarget frameBorder + headers height hidden high href hrefLang htmlFor httpEquiv icon id inputMode integrity + is keyParams keyType kind label lang list loop low manifest marginHeight marginWidth max maxLength media + mediaGroup method min minLength multiple muted name noValidate nonce open + optimum pattern placeholder poster preload radioGroup readOnly rel required + reversed role rowSpan rows sandbox scope scoped scrolling seamless selected + shape size sizes span spellCheck src srcDoc srcLang srcSet start step style + summary tabIndex target title type useMap value width wmode wrap onCopy onCut onPaste onCompositionEnd onCompositionStart onCompositionUpdate onKeyDown + onKeyPress onKeyUp onFocus onBlur onChange onInput onSubmit onClick onContextMenu onDoubleClick + onDrag onDragEnd onDragEnter onDragExit onDragLeave onDragOver onDragStart onDrop onMouseDown + onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUp onSelect onTouchCancel + onTouchEnd onTouchMove onTouchStart onScroll onWheel onAbort onCanPlay onCanPlayThrough + onDurationChange onEmptied onEncrypted onEnded onError onLoadedData onLoadedMetadata + onLoadStart onPause onPlay onPlaying onProgress onRateChange onSeeked onSeeking onStalled onSuspend onTimeUpdate onVolumeChange onWaiting onLoad onError`.split(/[\s\n]+/),uc=`aria-`,dc=`data-`;function fc(e,t){return e.indexOf(t)===0}function pc(e,t=!1){let n;n=t===!1?{aria:!0,data:!0,attr:!0}:t===!0?{aria:!0}:{...t};let r={};return Object.keys(e).forEach(t=>{(n.aria&&(t===`role`||fc(t,uc))||n.data&&fc(t,dc)||n.attr&&lc.includes(t))&&(r[t]=e[t])}),r}var mc={items_per_page:`/ page`,jump_to:`Go to`,jump_to_confirm:`confirm`,page:`Page`,prev_page:`Previous Page`,next_page:`Next Page`,prev_5:`Previous 5 Pages`,next_5:`Next 5 Pages`,prev_3:`Previous 3 Pages`,next_3:`Next 3 Pages`,page_size:`Page Size`},hc={yearFormat:`YYYY`,dayFormat:`D`,cellMeridiemFormat:`A`,monthBeforeYear:!0};function gc(e){"@babel/helpers - typeof";return gc=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},gc(e)}function _c(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function vc(e){for(var t=1;tkc.reduce((e,t)=>({...e,...t}),Dc.Modal);function jc(e){if(e){let t={...e};return kc.push(t),Oc=Ac(),()=>{kc=kc.filter(e=>e!==t),Oc=Ac()}}Oc={...Dc.Modal}}function Mc(){return Oc}var Nc=(0,d.createContext)(void 0),Pc=(e,t)=>{let n=d.useContext(Nc);return[d.useMemo(()=>{let r=t||Dc[e],i=n?.[e]??{};return{...typeof r==`function`?r():r,...i||{}}},[e,t,n]),d.useMemo(()=>{let e=n?.locale;return n?.exist&&!e?Dc.locale:e},[n])]},Fc=`internalMark`,Ic=e=>{let{locale:t={},children:n,_ANT_MARK__:r}=e;d.useEffect(()=>jc(t?.Modal),[t]);let i=d.useMemo(()=>({...t,exist:!0}),[t]);return d.createElement(Nc.Provider,{value:i},n)};function Lc(...e){let t={};return e.forEach(e=>{e&&Object.keys(e).forEach(n=>{e[n]!==void 0&&(t[n]=e[n])})}),t}var Rc=e=>e!=null,zc=e=>{if(!e)return;let{closable:t,closeIcon:n}=e;return{closable:t,closeIcon:n}},Bc={},Vc=(e,t)=>{if(!e&&(e===!1||t===!1||t===null))return!1;if(e===void 0&&t===void 0)return null;let n={closeIcon:typeof t!=`boolean`&&t!==null?t:void 0};return e&&typeof e==`object`&&(n={...n,...e}),n},Hc=(e,t,n)=>e===!1?!1:e?Lc(n,t,e):t===!1?!1:t?Lc(n,t):n.closable?n:!1,Uc=(e,t,n)=>{let{closeIconRender:r}=t,{closeIcon:i,...a}=e,o=i,s=pc(a,!0);return Rc(o)&&(r&&(o=r(o)),o=d.isValidElement(o)?d.cloneElement(o,{"aria-label":n,...o.props,...s}):d.createElement(`span`,{"aria-label":n,...s},o)),[o,s]},Wc=(e,t,n=Bc,r=`Close`)=>{let i=Vc(e?.closable,e?.closeIcon),a=Vc(t?.closable,t?.closeIcon),o={closeIcon:d.createElement(us,null),...n},s=Hc(i,a,o),c=typeof s==`boolean`?!1:!!s?.disabled;if(s===!1)return[!1,null,c,{}];let[l,u]=Uc(s,o,r);return[!0,l,c,u]},Gc=(e,t,n=Bc)=>{let[r]=Pc(`global`,Dc.global);return d.useMemo(()=>Wc(e,t,{closeIcon:d.createElement(us,null),...n},r.close),[e,t,n,r.close])},Kc=(e,t)=>{let n={};return e&&typeof e==`object`&&(n=e),typeof e==`boolean`&&(n={enabled:e}),n.closable===void 0&&t!==void 0&&(n.closable=t),n},qc=(e,t,n,r)=>(0,d.useMemo)(()=>{let i=Kc(e,r),a=Kc(t),o={blur:!1,...a,...i,closable:i.closable??r??a.closable??!0},s=o.blur?`${n}-mask-blur`:void 0;return[o.enabled!==!1,{mask:s},!!o.closable]},[e,t,n,r]),Jc=(e,...t)=>{let n=e||{};return t.filter(Boolean).reduce((e,t)=>(Object.keys(t||{}).forEach(r=>{let i=n[r],a=t[r];if(i&&typeof i==`object`)if(a&&typeof a==`object`)e[r]=Jc(i,e[r],a);else{let{_default:t}=i;t&&(e[r]=e[r]||{},e[r][t]=B(e[r][t],a))}else e[r]=B(e[r],a)}),e),{})},Yc=(e,...t)=>d.useMemo(()=>Jc.apply(void 0,[e].concat(t)),[e].concat(t)),Xc=(...e)=>e.filter(Boolean).reduce((e,t={})=>(Object.keys(t).forEach(n=>{e[n]={...e[n],...t[n]}}),e),{}),Zc=(...e)=>d.useMemo(()=>Xc.apply(void 0,e),[].concat(e)),Qc=(e,t)=>{let n={...e};return Object.keys(t).forEach(e=>{if(e!==`_default`){let r=t[e],i=n[e]||{};n[e]=r?Qc(i,r):i}}),n},$c=(e,t)=>typeof e==`function`?e(t):e,el=(e,t,n,r)=>{let i=e.map(e=>e?$c(e,n):void 0),a=t.map(e=>e?$c(e,n):void 0),o=Yc.apply(void 0,[r].concat(Mt(i))),s=Zc.apply(void 0,Mt(a));return d.useMemo(()=>r?[Qc(o,r),Qc(s,r)]:[o,s],[o,s,r])},tl=()=>{let[e,t]=d.useState([]);return[e,d.useCallback(e=>(t(t=>[].concat(Mt(t),[e])),()=>{t(t=>t.filter(t=>t!==e))}),[])]},nl=d.createContext(void 0),rl=100,il=rl*10;il+rl;var al={Modal:rl,Drawer:rl,Popover:rl,Popconfirm:rl,Tooltip:rl,Tour:rl,FloatButton:rl},ol={SelectLike:50,Dropdown:50,DatePicker:50,Menu:50,ImagePreview:1},sl=e=>e in al,cl=(e,t)=>{let[,n]=xo(),r=d.useContext(nl),i=sl(e),a;if(t!==void 0)a=[t,t];else{let o=r??0;i?o+=(r?0:n.zIndexPopupBase)+al[e]:o+=ol[e],a=[r===void 0?t:o,o]}return a},ll=e=>`${e}-css-var`,ul=(0,d.createContext)(void 0),dl=o((e=>{var t=u();function n(e){var t=`https://react.dev/errors/`+e;if(1{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=dl()})),pl=d.createContext(null),ml=!1;function hl(e){return typeof e==`boolean`&&(ml=e),ml}var gl=[];function _l(e,t){let[n]=d.useState(()=>R()?document.createElement(`div`):null),r=d.useRef(!1),i=d.useContext(pl),[a,o]=d.useState(gl),s=i||(r.current?void 0:e=>{o(t=>[e,...t])});function c(){n.parentElement||document.body.appendChild(n),r.current=!0}function l(){n.parentElement?.removeChild(n),r.current=!1}return z(()=>(e?i?i(c):c():l(),l),[e]),z(()=>{a.length&&(a.forEach(e=>e()),o(gl))},[a]),[n,s]}function vl(e){let t=`rc-scrollbar-measure-${Math.random().toString(36).substring(7)}`,n=document.createElement(`div`);n.id=t;let r=n.style;r.position=`absolute`,r.left=`0`,r.top=`0`,r.width=`100px`,r.height=`100px`,r.overflow=`scroll`;let i,a;if(e){let n=getComputedStyle(e);r.scrollbarColor=n.scrollbarColor,r.scrollbarWidth=n.scrollbarWidth;let o=getComputedStyle(e,`::-webkit-scrollbar`),s=parseInt(o.width,10),c=parseInt(o.height,10);try{rn(` +#${t}::-webkit-scrollbar { +${s?`width: ${o.width};`:``} +${c?`height: ${o.height};`:``} +}`,t)}catch(e){console.error(e),i=s,a=c}}document.body.appendChild(n);let o=e&&i&&!Number.isNaN(i)?i:n.offsetWidth-n.clientWidth,s=e&&a&&!Number.isNaN(a)?a:n.offsetHeight-n.clientHeight;return document.body.removeChild(n),tn(t),{width:o,height:s}}function yl(e){return typeof document>`u`||!e||!(e instanceof Element)?{width:0,height:0}:vl(e)}function bl(){return document.body.scrollHeight>(window.innerHeight||document.documentElement.clientHeight)&&window.innerWidth>document.body.offsetWidth}var xl=`rc-util-locker-${Date.now()}`,Sl=0;function Cl(e){let t=!!e,[n]=d.useState(()=>(Sl+=1,`${xl}_${Sl}`));z(()=>{if(t){let e=yl(document.body).width;rn(` +html body { + overflow-y: hidden; + ${bl()?`width: calc(100% - ${e}px);`:``} +}`,n)}else tn(n);return()=>{tn(n)}},[t,n])}function wl(){return{...d}.useId}var Tl=0,El=wl(),Dl=El?function(e){let t=El();return e||t}:function(e){let[t,n]=d.useState(`ssr-id`);return d.useEffect(()=>{let e=Tl;Tl+=1,n(`rc_unique_${e}`)},[]),e||t},Ol=[],kl=200,Al=0,jl=e=>{if(e.key===`Escape`&&!e.isComposing){if(Date.now()-Al=0;--n)Ol[n].onEsc({top:n===t-1,event:e})}},Ml=()=>{Al=Date.now()};function Nl(){window.addEventListener(`keydown`,jl),window.addEventListener(`compositionend`,Ml)}function Pl(){Ol.length===0&&(window.removeEventListener(`keydown`,jl),window.removeEventListener(`compositionend`,Ml))}function Fl(e,t){let n=Dl(),r=xe(t),i=()=>{Ol.find(e=>e.id===n)||Ol.push({id:n,onEsc:r})},a=()=>{Ol=Ol.filter(e=>e.id!==n)};(0,d.useMemo)(()=>{e?i():e||a()},[e]),(0,d.useEffect)(()=>{if(e)return i(),Nl(),()=>{a(),Pl()}},[e])}var Il=c(fl()),Ll=e=>e===!1?!1:!R()||!e?null:typeof e==`string`?document.querySelector(e):typeof e==`function`?e():e,Rl=d.forwardRef((e,t)=>{let{open:n,autoLock:r,getContainer:i,debug:a,autoDestroy:o=!0,children:s,onEsc:c}=e,[l,u]=d.useState(n),f=l||n;d.useEffect(()=>{(o||n)&&u(n)},[n,o]);let[p,m]=d.useState(()=>Ll(i));d.useEffect(()=>{let e=Ll(i);m(()=>e??null)});let[h,g]=_l(f&&!p,a),_=p??h;Cl(r&&n&&R()&&(_===h||_===document.body)),Fl(n,c);let v=null;s&&Ie(s)&&t&&(v=ze(s));let y=Fe(v,t);if(!f||!R()||p===void 0)return null;let b=_===!1||hl(),x=s;return t&&(x=d.cloneElement(s,{ref:y})),d.createElement(pl.Provider,{value:g},b?x:(0,Il.createPortal)(x,_))});function q(e){let{prefixCls:t,align:n,arrow:r,arrowPos:i}=e,{className:a,content:o,style:s}=r||{},{x:c=0,y:l=0}=i,u=d.useRef(null);if(!n||!n.points)return null;let f={position:`absolute`};if(n.autoArrow!==!1){let e=n.points[0],t=n.points[1],r=e[0],i=e[1],a=t[0],o=t[1];r===a||![`t`,`b`].includes(r)?f.top=l:r===`t`?f.top=0:f.bottom=0,i===o||![`l`,`r`].includes(i)?f.left=c:i===`l`?f.left=0:f.right=0}return d.createElement(`div`,{ref:u,className:B(`${t}-arrow`,a),style:{...f,...s}},o)}function J(){return J=Object.assign?Object.assign.bind():function(e){for(var t=1;td.createElement(`div`,{style:{zIndex:r},className:B(`${t}-mask`,o&&`${t}-mobile-mask`,e)})):null}var Bl=d.memo(({children:e})=>e,(e,t)=>t.cache);function Vl(e,t,n,r,i,a,o,s){let c=`auto`,l=e?{}:{left:`-1000vw`,top:`-1000vh`,right:c,bottom:c};if(!e&&(t||!n)){let{points:e}=r,t=r.dynamicInset||r._experimental?.dynamicInset,n=t&&e[0][1]===`r`,u=t&&e[0][0]===`b`;n?(l.right=i,l.left=c):(l.left=o,l.right=c),u?(l.bottom=a,l.top=c):(l.top=s,l.bottom=c)}return l}function Hl(){return Hl=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{onEsc:n,popup:r,className:i,prefixCls:a,style:o,target:s,onVisibleChanged:c,open:l,keepDom:u,fresh:f,onClick:p,mask:m,arrow:h,arrowPos:g,align:_,motion:v,maskMotion:y,mobile:b,forceRender:x,getPopupContainer:S,autoDestroy:C,portal:w,children:T,zIndex:E,onMouseEnter:D,onMouseLeave:O,onPointerEnter:k,onPointerDownCapture:A,ready:j,offsetX:ee,offsetY:te,offsetR:M,offsetB:N,onAlign:P,onPrepare:ne,onResize:re,stretch:F,targetWidth:ie,targetHeight:I}=e,ae=typeof r==`function`?r():r,oe=l||u,se=!!b,[ce,le,ue]=d.useMemo(()=>b?[b.mask,b.maskMotion,b.motion]:[m,y,v],[b,m,y,v]),de=S?.length>0,[L,fe]=d.useState(!S||!de);z(()=>{!L&&de&&s&&fe(!0)},[L,de,s]);let pe=xe((e,t)=>{re?.(e,t),P()}),me=Vl(se,j,l,_,M,N,ee,te);if(!L)return null;let he={};return F&&(F.includes(`height`)&&I?he.height=I:F.includes(`minHeight`)&&I&&(he.minHeight=I),F.includes(`width`)&&ie?he.width=ie:F.includes(`minWidth`)&&ie&&(he.minWidth=ie)),l||(he.pointerEvents=`none`),d.createElement(w,{open:x||oe,getContainer:S&&(()=>S(s)),autoDestroy:C,onEsc:n},d.createElement(zl,{prefixCls:a,open:l,zIndex:E,mask:ce,motion:le,mobile:se}),d.createElement(Tt,{onResize:pe,disabled:!l},e=>d.createElement(cc,Hl({motionAppear:!0,motionEnter:!0,motionLeave:!0,removeOnLeave:!1,forceRender:x,leavedClassName:`${a}-hidden`},ue,{onAppearPrepare:ne,onEnterPrepare:ne,visible:l,onVisibleChanged:e=>{v?.onVisibleChanged?.(e),c(e)}}),({className:n,style:r},s)=>{let c=B(a,n,i,{[`${a}-mobile`]:se});return d.createElement(`div`,{ref:Pe(e,t,s),className:c,style:{"--arrow-x":`${g.x||0}px`,"--arrow-y":`${g.y||0}px`,...me,...he,...r,boxSizing:`border-box`,zIndex:E,...o},onMouseEnter:D,onMouseLeave:O,onPointerEnter:k,onClick:p,onPointerDownCapture:A},h&&d.createElement(q,{prefixCls:a,arrow:h,arrowPos:g,align:_}),d.createElement(Bl,{cache:!l&&!f},ae))})),T)}),Wl=d.createContext(null),Gl=d.createContext(null),Kl=(e=>{if(!e)return!1;if(e instanceof Element){if(e.offsetParent)return!0;if(e.getBBox){let{width:t,height:n}=e.getBBox();if(t||n)return!0}if(e.getBoundingClientRect){let{width:t,height:n}=e.getBoundingClientRect();if(t||n)return!0}}return!1});function ql(e=[],t=[],n){let r=(e,t)=>e[t]||``;return n?r(e,0)===r(t,0):r(e,0)===r(t,0)&&r(e,1)===r(t,1)}function Jl(e,t,n,r){let{points:i}=n,a=Object.keys(e);for(let n=0;nr.includes(e))&&t.push(n),n=n.parentElement}return t}function Zl(e,t=1){return Number.isNaN(e)?t:e}function Ql(e){return Zl(parseFloat(e),0)}function $l(e,t){let n={...e};return(t||[]).forEach(e=>{if(e instanceof HTMLBodyElement||e instanceof HTMLHtmlElement)return;let{overflow:t,overflowClipMargin:r,borderTopWidth:i,borderBottomWidth:a,borderLeftWidth:o,borderRightWidth:s}=Yl(e).getComputedStyle(e),c=e.getBoundingClientRect(),{offsetHeight:l,clientHeight:u,offsetWidth:d,clientWidth:f}=e,p=Ql(i),m=Ql(a),h=Ql(o),g=Ql(s),_=Zl(Math.round(c.width/d*1e3)/1e3),v=Zl(Math.round(c.height/l*1e3)/1e3),y=(d-f-h-g)*_,b=(l-u-p-m)*v,x=p*v,S=m*v,C=h*_,w=g*_,T=0,E=0;if(t===`clip`){let e=Ql(r);T=e*_,E=e*v}let D=c.x+C-T,O=c.y+x-E,k=D+c.width+2*T-C-w-y,A=O+c.height+2*E-x-S-b;n.left=Math.max(n.left,D),n.top=Math.max(n.top,O),n.right=Math.min(n.right,k),n.bottom=Math.min(n.bottom,A)}),n}function eu(e,t=0){let n=`${t}`,r=n.match(/^(.*)\%$/);return r?e*(parseFloat(r[1])/100):parseFloat(n)}function tu(e,t){let[n,r]=t||[];return[eu(e.width,n),eu(e.height,r)]}function nu(e=``){return[e[0],e[1]]}function ru(e,t){let n=t[0],r=t[1],i,a;return a=n===`t`?e.y:n===`b`?e.y+e.height:e.y+e.height/2,i=r===`l`?e.x:r===`r`?e.x+e.width:e.x+e.width/2,{x:i,y:a}}function iu(e,t){let n={t:`b`,b:`t`,l:`r`,r:`l`},r=[...e];return r[t]=n[e[t]]||`c`,r}function au(e){return e.join(``)}function ou(e,t,n,r,i,a,o,s){let[c,l]=d.useState({ready:!1,offsetX:0,offsetY:0,offsetR:0,offsetB:0,arrowX:0,arrowY:0,scaleX:1,scaleY:1,align:i[r]||{}}),u=d.useRef(0),f=d.useMemo(()=>!t||s?[]:Xl(t),[t]),p=d.useRef({});e||(p.current={});let m=xe(()=>{if(t&&n&&e&&!s){let e=t,s=e.ownerDocument,c=Yl(e),{position:u}=c.getComputedStyle(e),d=e.style.left,m=e.style.top,h=e.style.right,g=e.style.bottom,_=e.style.overflow,v={...i[r],...a},y=s.createElement(`div`);e.parentElement?.appendChild(y),y.style.left=`${e.offsetLeft}px`,y.style.top=`${e.offsetTop}px`,y.style.position=u,y.style.height=`${e.offsetHeight}px`,y.style.width=`${e.offsetWidth}px`,e.style.left=`0`,e.style.top=`0`,e.style.right=`auto`,e.style.bottom=`auto`,e.style.overflow=`hidden`;let b;if(Array.isArray(n))b={x:n[0],y:n[1],width:0,height:0};else{let e=n.getBoundingClientRect();e.x=e.x??e.left,e.y=e.y??e.top,b={x:e.x,y:e.y,width:e.width,height:e.height}}let x=e.getBoundingClientRect(),{height:S,width:C}=c.getComputedStyle(e);x.x=x.x??x.left,x.y=x.y??x.top;let{clientWidth:w,clientHeight:T,scrollWidth:E,scrollHeight:D,scrollTop:O,scrollLeft:k}=s.documentElement,A=x.height,j=x.width,ee=b.height,te=b.width,M={left:0,top:0,right:w,bottom:T},N={left:-k,top:-O,right:E-k,bottom:D-O},{htmlRegion:P}=v,ne=`visible`,re=`visibleFirst`;P!==`scroll`&&P!==re&&(P=ne);let F=P===re,ie=$l(N,f),I=$l(M,f),ae=P===ne?I:ie,oe=F?I:ae;e.style.left=`auto`,e.style.top=`auto`,e.style.right=`0`,e.style.bottom=`0`;let se=e.getBoundingClientRect();e.style.left=d,e.style.top=m,e.style.right=h,e.style.bottom=g,e.style.overflow=_,e.parentElement?.removeChild(y);let ce=Zl(Math.round(j/parseFloat(C)*1e3)/1e3),le=Zl(Math.round(A/parseFloat(S)*1e3)/1e3);if(ce===0||le===0||lt(n)&&!Kl(n))return;let{offset:ue,targetOffset:de}=v,[L,fe]=tu(x,ue),[pe,me]=tu(b,de);b.x-=pe,b.y-=me;let[he,ge]=v.points||[],_e=nu(ge),ve=nu(he),ye=ru(b,_e),be=ru(x,ve),xe={...v},R=[ve,_e],Se=ye.x-be.x+L,z=ye.y-be.y+fe;function Ce(e,t,n=ae){let r=x.x+e,i=x.y+t,a=r+j,o=i+A,s=Math.max(r,n.left),c=Math.max(i,n.top),l=Math.min(a,n.right),u=Math.min(o,n.bottom);return Math.max(0,(l-s)*(u-c))}let we=Ce(Se,z),Te=Ce(Se,z,I),Ee=ru(b,[`t`,`l`]),De=ru(x,[`t`,`l`]),Oe=ru(b,[`b`,`r`]),ke=ru(x,[`b`,`r`]),{adjustX:Ae,adjustY:je,shiftX:Me,shiftY:Ne}=v.overflow||{},Pe=e=>typeof e==`boolean`?e:e>=0,Fe,Ie,Le,Re;function ze(){Fe=x.y+z,Ie=Fe+A,Le=x.x+Se,Re=Le+j}ze();let Be=Pe(je),Ve=ve[0]===_e[0];if(Be&&ve[0]===`t`&&(Ie>oe.bottom||p.current.bt)){let e=z;Ve?e-=A-ee:e=Ee.y-ke.y-fe;let t=Ce(Se,e),n=Ce(Se,e,I);t>we||t===we&&(!F||n>=Te)?(p.current.bt=!0,z=e,fe=-fe,R=[iu(R[0],0),iu(R[1],0)]):p.current.bt=!1}if(Be&&ve[0]===`b`&&(Fewe||t===we&&(!F||n>=Te)?(p.current.tb=!0,z=e,fe=-fe,R=[iu(R[0],0),iu(R[1],0)]):p.current.tb=!1}let He=Pe(Ae),Ue=ve[1]===_e[1];if(He&&ve[1]===`l`&&(Re>oe.right||p.current.rl)){let e=Se;Ue?e-=j-te:e=Ee.x-ke.x-L;let t=Ce(e,z),n=Ce(e,z,I);t>we||t===we&&(!F||n>=Te)?(p.current.rl=!0,Se=e,L=-L,R=[iu(R[0],1),iu(R[1],1)]):p.current.rl=!1}if(He&&ve[1]===`r`&&(Lewe||t===we&&(!F||n>=Te)?(p.current.lr=!0,Se=e,L=-L,R=[iu(R[0],1),iu(R[1],1)]):p.current.lr=!1}xe.points=[au(R[0]),au(R[1])],ze();let We=Me===!0?0:Me;typeof We==`number`&&(LeI.right&&(Se-=Re-I.right-L,b.x>I.right-We&&(Se+=b.x-I.right+We)));let Ge=Ne===!0?0:Ne;typeof Ge==`number`&&(FeI.bottom&&(z-=Ie-I.bottom-fe,b.y>I.bottom-Ge&&(z+=b.y-I.bottom+Ge)));let Ke=x.x+Se,qe=Ke+j,Je=x.y+z,Ye=Je+A,Xe=b.x,Ze=Xe+te,Qe=b.y,$e=Qe+ee,et=(Math.max(Ke,Xe)+Math.min(qe,Ze))/2-Ke,tt=(Math.max(Je,Qe)+Math.min(Ye,$e))/2-Je;o?.(t,xe);let nt=se.right-x.x-(Se+x.width),rt=se.bottom-x.y-(z+x.height);ce===1&&(Se=Math.floor(Se),nt=Math.floor(nt)),le===1&&(z=Math.floor(z),rt=Math.floor(rt)),l({ready:!0,offsetX:Se/ce,offsetY:z/le,offsetR:nt/ce,offsetB:rt/le,arrowX:et/ce,arrowY:tt/le,scaleX:ce,scaleY:le,align:xe})}}),h=()=>{u.current+=1;let e=u.current;Promise.resolve().then(()=>{u.current===e&&m()})},g=()=>{l(e=>({...e,ready:!1}))};return z(g,[r]),z(()=>{e||g()},[e]),[c.ready,c.offsetX,c.offsetY,c.offsetR,c.offsetB,c.arrowX,c.arrowY,c.scaleX,c.scaleY,c.align,h]}function su(){let e=d.useRef(null),t=()=>{e.current&&=(clearTimeout(e.current),null)};return d.useEffect(()=>()=>{t()},[]),(n,r)=>{t(),r===0?n():e.current=setTimeout(()=>{n()},r*1e3)}}function cu(){let[e,t]=d.useState(null),[n,r]=d.useState(!1),[i,a]=d.useState(!1),o=d.useRef(null);return[xe(e=>{e===!1?(o.current=null,r(!1)):i&&n?o.current=e:(r(!0),t(e),o.current=null,n||a(!0))}),n,e,xe(e=>{e?(a(!1),o.current&&=(t(o.current),null)):(a(!1),o.current=null)})]}function lu(){return lu=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{prefixCls:t,isMobile:n,ready:r,open:i,align:a,offsetR:o,offsetB:s,offsetX:c,offsetY:l,arrowPos:u,popupSize:f,motion:p,uniqueContainerClassName:m,uniqueContainerStyle:h}=e,g=`${t}-unique-container`,[_,v]=d.useState(!1),y=Vl(n,r,i,a,o,s,c,l),b=d.useRef(y);r&&(b.current=y);let x={};return f&&(x.width=f.width,x.height=f.height),d.createElement(cc,lu({motionAppear:!0,motionEnter:!0,motionLeave:!0,removeOnLeave:!1,leavedClassName:`${g}-hidden`},p,{visible:i,onVisibleChanged:e=>{v(e)}}),({className:e,style:t})=>{let n=B(g,e,m,{[`${g}-visible`]:_});return d.createElement(`div`,{className:n,style:{"--arrow-x":`${u?.x||0}px`,"--arrow-y":`${u?.y||0}px`,...b.current,...x,...t,...h}})})},du=({children:e,postTriggerProps:t})=>{let[n,r,i,a]=cu(),o=d.useMemo(()=>!i||!t?i:t(i),[i,t]),[s,c]=d.useState(null),[l,u]=d.useState(null),f=d.useRef(null),p=xe(e=>{f.current=e,lt(e)&&s!==e&&c(e)}),m=d.useRef(null),h=su(),g=xe((e,t)=>{m.current=t,h(()=>{n(e)},e.delay)}),_=e=>{h(()=>{m.current?.()||n(!1)},e)},v=xe(e=>{a(e)}),[y,b,x,S,C,w,T,,,E,D]=ou(r,s,o?.target,o?.popupPlacement,o?.builtinPlacements||{},o?.popupAlign,void 0,!1),O=d.useMemo(()=>o?B(Jl(o.builtinPlacements||{},o.prefixCls||``,E,!1),o.getPopupClassNameFromAlign?.(E)):``,[E,o?.getPopupClassNameFromAlign,o?.builtinPlacements,o?.prefixCls]),k=d.useMemo(()=>({show:g,hide:_}),[]);d.useEffect(()=>{D()},[o?.target]);let A=xe(()=>(D(),Promise.resolve())),j=d.useRef({}),ee=d.useContext(Wl),te=d.useMemo(()=>({registerSubPopup:(e,t)=>{j.current[e]=t,ee?.registerSubPopup(e,t)}}),[ee]),M=o?.prefixCls;return d.createElement(Gl.Provider,{value:k},e,o&&d.createElement(Wl.Provider,{value:te},d.createElement(Ul,{ref:p,portal:Rl,onEsc:o.onEsc,prefixCls:M,popup:o.popup,className:B(o.popupClassName,O,`${M}-unique-controlled`),style:o.popupStyle,target:o.target,open:r,keepDom:!0,fresh:!0,autoDestroy:!1,onVisibleChanged:v,ready:y,offsetX:b,offsetY:x,offsetR:S,offsetB:C,onAlign:D,onPrepare:A,onResize:e=>u({width:e.offsetWidth,height:e.offsetHeight}),arrowPos:{x:w,y:T},align:E,zIndex:o.zIndex,mask:o.mask,arrow:o.arrow,motion:o.popupMotion,maskMotion:o.maskMotion,getPopupContainer:o.getPopupContainer},d.createElement(uu,{prefixCls:M,isMobile:!1,ready:y,open:r,align:E,offsetR:S,offsetB:C,offsetX:b,offsetY:x,arrowPos:{x:w,y:T},popupSize:l,motion:o.popupMotion,uniqueContainerClassName:B(o.uniqueContainerClassName,O),uniqueContainerStyle:o.uniqueContainerStyle}))))};function fu(e){return e&&d.isValidElement(e)&&e.type===d.Fragment}var pu=(e,t,n)=>d.isValidElement(e)?d.cloneElement(e,typeof n==`function`?n(e.props||{}):n):t;function mu(e,t){return pu(e,e,t)}var hu=({children:e})=>{let{getPrefixCls:t}=d.useContext(zt),n=t();return d.isValidElement(e)?d.createElement(cc,{visible:!0,motionName:`${n}-fade`,motionAppear:!0,motionEnter:!0,motionLeave:!1,removeOnLeave:!1},({style:t,className:n})=>mu(e,e=>({className:B(e.className,n),style:{...e.style,...t}}))):e},gu=[null,null];function _u(e){if(gu[0]!==e){let t={};Object.keys(e).forEach(n=>{t[n]={...e[n],dynamicInset:!1}}),gu[0]=e,gu[1]=t}return gu[1]}var vu=({children:e})=>d.createElement(du,{postTriggerProps:e=>{let{id:t,builtinPlacements:n,popup:r}=e,i=typeof r==`function`?r():r,a=_u(n);return{...e,getPopupContainer:null,arrow:!1,popup:d.createElement(hu,{key:t},i),builtinPlacements:a}}},e),yu=d.createContext(!1),bu=({children:e,disabled:t})=>{let n=d.useContext(yu);return d.createElement(yu.Provider,{value:t??n},e)},xu=d.createContext(void 0),Su=({children:e,size:t})=>{let n=d.useContext(xu);return d.createElement(xu.Provider,{value:t||n},e)};function Cu(){return{componentDisabled:(0,d.useContext)(yu),componentSize:(0,d.useContext)(xu)}}function wu(e,t,n){ct(`ConfigProvider`);let r=e||{},i=r.inherit===!1||!t?{...fo,hashed:t?.hashed??fo.hashed,cssVar:t?.cssVar}:t,a=(0,d.useId)();return Ee(()=>{if(!e)return t;let o={...i.components};Object.keys(e.components||{}).forEach(t=>{o[t]={...o[t],...e.components[t]}});let s=`css-var-${a.replace(/:/g,``)}`,c={prefix:n?.prefixCls,...i.cssVar,...r.cssVar,key:r.cssVar?.key||s};return{...i,...r,token:{...i.token,...r.token},components:o,cssVar:c}},[r,i],(e,t)=>e.some((e,n)=>{let r=t[n];return!an(e,r,!0)}))}var Tu=d.createContext(!0);function Eu(e){let t=d.useContext(Tu),{children:n}=e,[,r]=xo(),{motion:i}=r,a=d.useRef(!1);return a.current||=t!==i,a.current?d.createElement(Tu.Provider,{value:i},d.createElement(vs,{motion:i},n)):n}var Du=()=>null,Ou=({iconPrefixCls:e,csp:t})=>(Po(e,t),null),ku=[`getTargetContainer`,`getPopupContainer`,`renderEmpty`,`input`,`pagination`,`form`,`select`,`button`],Au=e=>{let{prefixCls:t,iconPrefixCls:n,theme:r,holderRender:i}=e;`holderRender`in e},ju=e=>{let{children:t,csp:n,autoInsertSpaceInButton:r,alert:i,affix:a,anchor:o,app:s,form:c,locale:l,componentSize:u,direction:f,space:p,splitter:m,virtual:h,dropdownMatchSelectWidth:g,popupMatchSelectWidth:_,popupOverflow:v,legacyLocale:y,parentContext:b,iconPrefixCls:x,theme:S,componentDisabled:C,segmented:w,statistic:T,spin:E,calendar:D,carousel:O,cascader:k,collapse:A,typography:j,checkbox:ee,descriptions:te,divider:M,drawer:N,skeleton:P,steps:ne,image:re,layout:F,list:ie,mentions:I,modal:ae,progress:oe,result:se,slider:ce,breadcrumb:le,masonry:ue,menu:de,pagination:L,input:fe,textArea:pe,otp:me,empty:he,badge:ge,radio:_e,rate:ve,ribbon:ye,switch:be,transfer:xe,avatar:R,message:Se,tag:z,table:Ce,card:we,cardMeta:Te,tabs:De,timeline:Oe,timePicker:ke,upload:Ae,notification:je,tree:Me,colorPicker:Ne,datePicker:Pe,rangePicker:Fe,flex:Ie,wave:Le,dropdown:Re,warning:ze,tour:Be,tooltip:Ve,popover:He,popconfirm:Ue,qrcode:We,floatButton:Ge,floatButtonGroup:Ke,variant:Je,inputNumber:Ye,treeSelect:Xe,watermark:Ze}=e,Qe=d.useCallback((t,n)=>{let{prefixCls:r}=e;if(n)return n;let i=r||b.getPrefixCls(``);return t?`${i}-${t}`:i},[b.getPrefixCls,e.prefixCls]),$e=x||b.iconPrefixCls||`anticon`,et=n||b.csp,tt=wu(S,b.theme,{prefixCls:Qe(``)}),nt={csp:et,autoInsertSpaceInButton:r,alert:i,affix:a,anchor:o,app:s,locale:l||y,direction:f,space:p,splitter:m,virtual:h,popupMatchSelectWidth:_??g,popupOverflow:v,getPrefixCls:Qe,iconPrefixCls:$e,theme:tt,segmented:w,statistic:T,spin:E,calendar:D,carousel:O,cascader:k,collapse:A,typography:j,checkbox:ee,descriptions:te,divider:M,drawer:N,skeleton:P,steps:ne,image:re,input:fe,textArea:pe,otp:me,layout:F,list:ie,mentions:I,modal:ae,progress:oe,result:se,slider:ce,breadcrumb:le,masonry:ue,menu:de,pagination:L,empty:he,badge:ge,radio:_e,rate:ve,ribbon:ye,switch:be,transfer:xe,avatar:R,message:Se,tag:z,table:Ce,card:we,cardMeta:Te,tabs:De,timeline:Oe,timePicker:ke,upload:Ae,notification:je,tree:Me,colorPicker:Ne,datePicker:Pe,rangePicker:Fe,flex:Ie,wave:Le,dropdown:Re,warning:ze,tour:Be,tooltip:Ve,popover:He,popconfirm:Ue,qrcode:We,floatButton:Ge,floatButtonGroup:Ke,variant:Je,inputNumber:Ye,treeSelect:Xe,watermark:Ze},rt={...b};Object.keys(nt).forEach(e=>{nt[e]!==void 0&&(rt[e]=nt[e])}),ku.forEach(t=>{let n=e[t];n&&(rt[t]=n)}),r!==void 0&&(rt.button={autoInsertSpace:r,...rt.button});let it=Ee(()=>rt,rt,(e,t)=>{let n=Object.keys(e),r=Object.keys(t);return n.length!==r.length||n.some(n=>e[n]!==t[n])}),{layer:at}=d.useContext(mn),ot=d.useMemo(()=>({prefixCls:$e,csp:et,layer:at?`antd`:void 0}),[$e,et,at]),ct=d.createElement(d.Fragment,null,d.createElement(Ou,{iconPrefixCls:$e,csp:et}),d.createElement(Du,{dropdownMatchSelectWidth:g}),t),lt=d.useMemo(()=>qe(Dc.Form?.defaultValidateMessages||{},it.locale?.Form?.defaultValidateMessages||{},it.form?.validateMessages||{},c?.validateMessages||{}),[it,c?.validateMessages]);Object.keys(lt).length>0&&(ct=d.createElement(ul.Provider,{value:lt},ct)),l&&(ct=d.createElement(Ic,{locale:l,_ANT_MARK__:Fc},ct)),($e||et)&&(ct=d.createElement(Io.Provider,{value:ot},ct)),u&&(ct=d.createElement(Su,{size:u},ct)),ct=d.createElement(Eu,null,ct),Ve?.unique&&(ct=d.createElement(vu,null,ct));let ut=d.useMemo(()=>{let{algorithm:e,token:t,components:n,cssVar:r,...i}=tt||{},a=e&&(!Array.isArray(e)||e.length>0)?bn(e):uo,o={};Object.entries(n||{}).forEach(([e,t])=>{let n={...t};`algorithm`in n&&(n.algorithm===!0?n.theme=a:(Array.isArray(n.algorithm)||typeof n.algorithm==`function`)&&(n.theme=bn(n.algorithm)),delete n.algorithm),o[e]=n});let s={...ca,...t};return{...i,theme:a,token:s,components:o,override:{override:s,...o},cssVar:r}},[tt]);return S&&(ct=d.createElement(po.Provider,{value:ut},ct)),it.warning&&(ct=d.createElement(st.Provider,{value:it.warning},ct)),C!==void 0&&(ct=d.createElement(bu,{disabled:C},ct)),d.createElement(zt.Provider,{value:it},ct)},Mu=e=>{let t=d.useContext(zt),n=d.useContext(Nc);return d.createElement(ju,{parentContext:t,legacyLocale:n,...e})};Mu.ConfigContext=zt,Mu.SizeContext=xu,Mu.config=Au,Mu.useConfig=Cu,Object.defineProperty(Mu,`SizeContext`,{get:()=>xu});var Y={MAC_ENTER:3,BACKSPACE:8,TAB:9,NUM_CENTER:12,ENTER:13,SHIFT:16,CTRL:17,ALT:18,PAUSE:19,CAPS_LOCK:20,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,PRINT_SCREEN:44,INSERT:45,DELETE:46,ZERO:48,ONE:49,TWO:50,THREE:51,FOUR:52,FIVE:53,SIX:54,SEVEN:55,EIGHT:56,NINE:57,QUESTION_MARK:63,A:65,B:66,C:67,D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90,META:91,WIN_KEY_RIGHT:92,CONTEXT_MENU:93,NUM_ZERO:96,NUM_ONE:97,NUM_TWO:98,NUM_THREE:99,NUM_FOUR:100,NUM_FIVE:101,NUM_SIX:102,NUM_SEVEN:103,NUM_EIGHT:104,NUM_NINE:105,NUM_MULTIPLY:106,NUM_PLUS:107,NUM_MINUS:109,NUM_PERIOD:110,NUM_DIVISION:111,F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120,F10:121,F11:122,F12:123,NUMLOCK:144,SEMICOLON:186,DASH:189,EQUALS:187,COMMA:188,PERIOD:190,SLASH:191,APOSTROPHE:192,SINGLE_QUOTE:222,OPEN_SQUARE_BRACKET:219,BACKSLASH:220,CLOSE_SQUARE_BRACKET:221,WIN_KEY:224,MAC_FF_META:224,WIN_IME:229,isTextModifyingKeyEvent:function(e){let{keyCode:t}=e;if(e.altKey&&!e.ctrlKey||e.metaKey||t>=Y.F1&&t<=Y.F12)return!1;switch(t){case Y.ALT:case Y.CAPS_LOCK:case Y.CONTEXT_MENU:case Y.CTRL:case Y.DOWN:case Y.END:case Y.ESC:case Y.HOME:case Y.INSERT:case Y.LEFT:case Y.MAC_FF_META:case Y.META:case Y.NUMLOCK:case Y.NUM_CENTER:case Y.PAGE_DOWN:case Y.PAGE_UP:case Y.PAUSE:case Y.PRINT_SCREEN:case Y.RIGHT:case Y.SHIFT:case Y.UP:case Y.WIN_KEY:case Y.WIN_KEY_RIGHT:return!1;default:return!0}},isCharacterKey:function(e){if(e>=Y.ZERO&&e<=Y.NINE||e>=Y.NUM_ZERO&&e<=Y.NUM_MULTIPLY||e>=Y.A&&e<=Y.Z||window.navigator.userAgent.indexOf(`WebKit`)!==-1&&e===0)return!0;switch(e){case Y.SPACE:case Y.QUESTION_MARK:case Y.NUM_PLUS:case Y.NUM_MINUS:case Y.NUM_PERIOD:case Y.NUM_DIVISION:case Y.SEMICOLON:case Y.DASH:case Y.EQUALS:case Y.COMMA:case Y.PERIOD:case Y.SLASH:case Y.APOSTROPHE:case Y.SINGLE_QUOTE:case Y.OPEN_SQUARE_BRACKET:case Y.BACKSLASH:case Y.CLOSE_SQUARE_BRACKET:return!0;default:return!1}},isEditableTarget:function(e){let t=e.target;if(!(t instanceof HTMLElement))return!1;let n=t.tagName;return!!(n===`INPUT`||n===`TEXTAREA`||n===`SELECT`||t.isContentEditable)}};function Nu(){return Nu=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{prefixCls:n,style:r,className:i,duration:a=4.5,showProgress:o,pauseOnHover:s=!0,eventKey:c,content:l,closable:u,props:f,onClick:p,onNoticeClose:m,times:h,hovering:g}=e,[_,v]=d.useState(!1),[y,b]=d.useState(0),[x,S]=d.useState(0),C=g||_,w=typeof a==`number`?a:0,T=w>0&&o,E=()=>{m(c)},D=e=>{(e.key===`Enter`||e.code===`Enter`||e.keyCode===Y.ENTER)&&E()};d.useEffect(()=>{if(!C&&w>0){let e=Date.now()-x,t=setTimeout(()=>{E()},w*1e3-x);return()=>{s&&clearTimeout(t),S(Date.now()-e)}}},[w,C,h]),d.useEffect(()=>{if(!C&&T&&(s||x===0)){let e=performance.now(),t,n=()=>{cancelAnimationFrame(t),t=requestAnimationFrame(t=>{let r=t+x-e,i=Math.min(r/(w*1e3),1);b(i*100),i<1&&n()})};return n(),()=>{s&&cancelAnimationFrame(t)}}},[w,x,C,T,h]);let O=d.useMemo(()=>typeof u==`object`&&u?u:{},[u]),k=pc(O,!0),A=100-(!y||y<0?0:y>100?100:y),j=`${n}-notice`;return d.createElement(`div`,Nu({},f,{ref:t,className:B(j,i,{[`${j}-closable`]:u}),style:r,onMouseEnter:e=>{v(!0),f?.onMouseEnter?.(e)},onMouseLeave:e=>{v(!1),f?.onMouseLeave?.(e)},onClick:p}),d.createElement(`div`,{className:`${j}-content`},l),u&&d.createElement(`button`,Nu({className:`${j}-close`,onKeyDown:D,"aria-label":`Close`},k,{onClick:e=>{e.preventDefault(),e.stopPropagation(),E()}}),O.closeIcon??`x`),T&&d.createElement(`progress`,{className:`${j}-progress`,max:`100`,value:A},A+`%`))}),Fu=d.createContext({}),Iu=({children:e,classNames:t})=>d.createElement(Fu.Provider,{value:{classNames:t}},e),Lu=8,Ru=3,zu=16,Bu=e=>{let t={offset:Lu,threshold:Ru,gap:zu};return e&&typeof e==`object`&&(t.offset=e.offset??Lu,t.threshold=e.threshold??Ru,t.gap=e.gap??zu),[!!e,t]};function Vu(){return Vu=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{configList:t,placement:n,prefixCls:r,className:i,style:a,motion:o,onAllNoticeRemoved:s,onNoticeClose:c,stack:l}=e,{classNames:u}=(0,d.useContext)(Fu),f=(0,d.useRef)({}),[p,m]=(0,d.useState)(null),[h,g]=(0,d.useState)([]),_=t.map(e=>({config:e,key:String(e.key)})),[v,{offset:y,threshold:b,gap:x}]=Bu(l),S=v&&(h.length>0||_.length<=b),C=typeof o==`function`?o(n):o;return(0,d.useEffect)(()=>{v&&h.length>1&&g(e=>e.filter(e=>_.some(({key:t})=>e===t)))},[h,_,v]),(0,d.useEffect)(()=>{v&&f.current[_[_.length-1]?.key]&&m(f.current[_[_.length-1]?.key])},[_,v]),d.createElement(sc,Vu({key:n,className:B(r,`${r}-${n}`,u?.list,i,{[`${r}-stack`]:!!v,[`${r}-stack-expanded`]:S}),style:a,keys:_,motionAppear:!0},C,{onAllRemoved:()=>{s(n)}}),({config:e,className:t,style:i,index:a},o)=>{let{key:s,times:l}=e,m=String(s),{className:b,style:C,classNames:w,styles:T,...E}=e,D=_.findIndex(e=>e.key===m),O={};if(v){let e=_.length-1-(D>-1?D:a-1),t=n===`top`||n===`bottom`?`-50%`:`0`;if(e>0){O.height=S?f.current[m]?.offsetHeight:p?.offsetHeight;let r=0;for(let t=0;tg(e=>e.includes(m)?e:[...e,m]),onMouseLeave:()=>g(e=>e.filter(e=>e!==m))},d.createElement(Pu,Vu({},E,{ref:e=>{D>-1?f.current[m]=e:delete f.current[m]},prefixCls:r,classNames:w,styles:T,className:B(b,u?.notice),style:C,times:l,key:s,eventKey:s,onNoticeClose:c,hovering:v&&h.length>0})))})},Uu=d.forwardRef((e,t)=>{let{prefixCls:n=`rc-notification`,container:r,motion:i,maxCount:a,className:o,style:s,onAllRemoved:c,stack:l,renderNotifications:u}=e,[f,p]=d.useState([]),m=e=>{let t=f.find(t=>t.key===e),n=t?.closable,{onClose:r}=n&&typeof n==`object`?n:{};r?.(),t?.onClose?.(),p(t=>t.filter(t=>t.key!==e))};d.useImperativeHandle(t,()=>({open:e=>{p(t=>{let n=[...t],r=n.findIndex(t=>t.key===e.key),i={...e};return r>=0?(i.times=(t[r]?.times||0)+1,n[r]=i):(i.times=0,n.push(i)),a>0&&n.length>a&&(n=n.slice(-a)),n})},close:e=>{m(e)},destroy:()=>{p([])}}));let[h,g]=d.useState({});d.useEffect(()=>{let e={};f.forEach(t=>{let{placement:n=`topRight`}=t;n&&(e[n]=e[n]||[],e[n].push(t))}),Object.keys(h).forEach(t=>{e[t]=e[t]||[]}),g(e)},[f]);let _=e=>{g(t=>{let n={...t};return(n[e]||[]).length||delete n[e],n})},v=d.useRef(!1);if(d.useEffect(()=>{Object.keys(h).length>0?v.current=!0:v.current&&=(c?.(),!1)},[h]),!r)return null;let y=Object.keys(h);return(0,Il.createPortal)(d.createElement(d.Fragment,null,y.map(e=>{let t=h[e],r=d.createElement(Hu,{key:e,configList:t,placement:e,prefixCls:n,className:o?.(e),style:s?.(e),motion:i,onNoticeClose:m,onAllNoticeRemoved:_,stack:l});return u?u(r,{prefixCls:n,key:e}):r})),r)}),Wu=()=>document.body,Gu=0;function Ku(...e){let t={};return e.forEach(e=>{e&&Object.keys(e).forEach(n=>{let r=e[n];r!==void 0&&(t[n]=r)})}),t}function qu(e={}){let{getContainer:t=Wu,motion:n,prefixCls:r,maxCount:i,className:a,style:o,onAllRemoved:s,stack:c,renderNotifications:l,...u}=e,[f,p]=d.useState(),m=d.useRef(),h=d.createElement(Uu,{container:f,ref:m,prefixCls:r,motion:n,maxCount:i,className:a,style:o,onAllRemoved:s,stack:c,renderNotifications:l}),[g,_]=d.useState([]),v=xe(e=>{let t=Ku(u,e);(t.key===null||t.key===void 0)&&(t.key=`rc-notification-${Gu}`,Gu+=1),_(e=>[...e,{type:`open`,config:t}])}),y=d.useMemo(()=>({open:v,close:e=>{_(t=>[...t,{type:`close`,key:e}])},destroy:()=>{_(e=>[...e,{type:`destroy`}])}}),[]);return d.useEffect(()=>{p(t())}),d.useEffect(()=>{if(m.current&&g.length){g.forEach(e=>{switch(e.type){case`open`:m.current.open(e.config);break;case`close`:m.current.close(e.key);break;case`destroy`:m.current.destroy();break}});let e,t;_(n=>((e!==n||!t)&&(e=n,t=n.filter(e=>!g.includes(e))),t))}},[g]),[y,h]}var Ju={icon:{tag:`svg`,attrs:{viewBox:`0 0 1024 1024`,focusable:`false`},children:[{tag:`path`,attrs:{d:`M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 00-94.3-139.9 437.71 437.71 0 00-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z`}}]},name:`loading`,theme:`outlined`};function Yu(){return Yu=Object.assign?Object.assign.bind():function(e){for(var t=1;td.createElement(ns,Yu({},e,{ref:t,icon:Ju}))),Zu=e=>{let{componentCls:t,iconCls:n,boxShadow:r,colorText:i,colorSuccess:a,colorError:o,colorWarning:s,colorInfo:c,fontSizeLG:l,motionEaseInOutCirc:u,motionDurationSlow:d,marginXS:f,paddingXS:p,borderRadiusLG:m,zIndexPopup:h,contentPadding:g,contentBg:_}=e,v=`${t}-notice`,y=new mi(`MessageMoveIn`,{"0%":{padding:0,transform:`translateY(-100%)`,opacity:0},"100%":{padding:p,transform:`translateY(0)`,opacity:1}}),b=new mi(`MessageMoveOut`,{"0%":{maxHeight:e.height,padding:p,opacity:1},"100%":{maxHeight:0,padding:0,opacity:0}}),x={padding:p,textAlign:`center`,[`${t}-custom-content`]:{display:`flex`,alignItems:`center`},[`${t}-custom-content > ${n}`]:{marginInlineEnd:f,fontSize:l},[`${v}-content`]:{display:`inline-block`,padding:g,background:_,borderRadius:m,boxShadow:r,pointerEvents:`all`},[`${t}-success > ${n}`]:{color:a},[`${t}-error > ${n}`]:{color:o},[`${t}-warning > ${n}`]:{color:s},[`${t}-info > ${n}, + ${t}-loading > ${n}`]:{color:c}};return[{[t]:{...So(e),color:i,position:`fixed`,top:f,width:`100%`,pointerEvents:`none`,zIndex:h,[`${t}-move-up`]:{animationFillMode:`forwards`},[` + ${t}-move-up-appear, + ${t}-move-up-enter + `]:{animationName:y,animationDuration:d,animationPlayState:`paused`,animationTimingFunction:u},[` + ${t}-move-up-appear${t}-move-up-appear-active, + ${t}-move-up-enter${t}-move-up-enter-active + `]:{animationPlayState:`running`},[`${t}-move-up-leave`]:{animationName:b,animationDuration:d,animationPlayState:`paused`,animationTimingFunction:u},[`${t}-move-up-leave${t}-move-up-leave-active`]:{animationPlayState:`running`},"&-rtl":{direction:`rtl`,span:{direction:`rtl`}}}},{[t]:{[`${v}-wrapper`]:{...x}}},{[`${t}-notice-pure-panel`]:{...x,padding:0,textAlign:`start`}}]},Qu=Ao(`Message`,e=>Zu(Ki(e,{height:150})),e=>({zIndexPopup:e.zIndexPopupBase+il+10,contentBg:e.colorBgElevated,contentPadding:`${(e.controlHeightLG-e.fontSize*e.lineHeight)/2}px ${e.paddingSM}px`})),$u={info:d.createElement(gs,null),success:d.createElement(is,null),error:d.createElement(ss,null),warning:d.createElement(ps,null),loading:d.createElement(Xu,null)},ed=e=>{let{prefixCls:t,type:n,icon:r,children:i,classNames:a,styles:o}=e,s=mu(r||n&&$u[n],e=>{let t={...e?.style,...o?.icon};return{className:B(e.className,a?.icon),style:t}});return d.createElement(`div`,{className:B(`${t}-custom-content`,`${t}-${n}`)},s,d.createElement(`span`,{className:a?.content,style:o?.content},i))};function td(e,t){return{motionName:t??`${e}-move-up`}}function nd(e){let t,n=new Promise(n=>{t=e(()=>{n(!0)})}),r=()=>{t?.()};return r.then=(e,t)=>n.then(e,t),r.promise=n,r}var rd=8,id=3,ad=({children:e,prefixCls:t})=>{let n=ll(t),[r,i]=Qu(t,n);return d.createElement(Iu,{classNames:{list:B(r,i,n)}},e)},od=(e,{prefixCls:t,key:n})=>d.createElement(ad,{prefixCls:t,key:n},e),sd=d.forwardRef((e,t)=>{let{top:n,prefixCls:r,getContainer:i,maxCount:a,duration:o=id,rtl:s,transitionName:c,onAllRemoved:l,pauseOnHover:u=!0}=e,{getPrefixCls:f,direction:p,getPopupContainer:m}=Ht(`message`),{message:h}=d.useContext(zt),g=r||f(`message`),_=()=>({left:`50%`,transform:`translateX(-50%)`,top:n??rd}),v=()=>B({[`${g}-rtl`]:s??p===`rtl`}),y=()=>td(g,c),[b,x]=el([e?.classNames,h?.classNames],[e?.styles,h?.styles],{props:e}),[S,C]=qu({prefixCls:g,style:_,className:v,motion:y,closable:!1,duration:o,getContainer:()=>i?.()||m?.()||document.body,maxCount:a,onAllRemoved:l,renderNotifications:od,pauseOnHover:u});return d.useImperativeHandle(t,()=>({...S,prefixCls:g,message:h,classNames:b,styles:x})),C}),cd=0;function ld(e){let t=d.useRef(null);return ct(`Message`),[d.useMemo(()=>{let n=e=>{t.current?.close(e)},r=r=>{if(!t.current){let e=()=>{};return e.then=()=>{},e}let{open:i,prefixCls:a,message:o,classNames:s,styles:c}=t.current,l=o?.className||{},u=o?.style||{},f=o?.classNames||{},p=o?.styles||{},m=`${a}-notice`,{content:h,icon:g,type:_,key:v,className:y,style:b,onClose:x,classNames:S={},styles:C={},...w}=r,T=v;Rc(T)||(cd+=1,T=`antd-message-${cd}`);let E={...e,...r},D=$c(f,{props:E}),O=$c(S,{props:E}),k=$c(p,{props:E}),A=$c(C,{props:E}),j=Jc(void 0,D,O,s),ee=Xc(k,A,c);return nd(e=>(i({...w,key:T,content:d.createElement(ed,{prefixCls:a,type:_,icon:g,classNames:j,styles:ee},h),placement:`top`,className:B({[`${m}-${_}`]:_},y,l,j.root),style:{...ee.root,...u,...b},onClose:()=>{x?.(),e()}}),()=>{n(T)}))},i={open:r,destroy:e=>{e===void 0?t.current?.destroy():n(e)}};return[`info`,`success`,`warning`,`error`,`loading`].forEach(e=>{i[e]=(t,n,i)=>{let a;a=t&&typeof t==`object`&&`content`in t?t:{content:t};let o,s;return typeof n==`function`?s=n:(o=n,s=i),r({onClose:s,duration:o,...a,type:e})}}),i},[]),d.createElement(sd,{key:`message-holder`,...e,ref:t})]}function ud(e){return ld(e)}var dd=o((e=>{function t(e,t){var n=e.length;e.push(t);a:for(;0>>1,a=e[r];if(0>>1;ri(c,n))li(u,c)?(e[r]=u,e[l]=n,r=l):(e[r]=c,e[s]=n,r=s);else if(li(u,n))e[r]=u,e[l]=n,r=l;else break a}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return n===0?e.id-t.id:n}if(e.unstable_now=void 0,typeof performance==`object`&&typeof performance.now==`function`){var a=performance;e.unstable_now=function(){return a.now()}}else{var o=Date,s=o.now();e.unstable_now=function(){return o.now()-s}}var c=[],l=[],u=1,d=null,f=3,p=!1,m=!1,h=!1,g=!1,_=typeof setTimeout==`function`?setTimeout:null,v=typeof clearTimeout==`function`?clearTimeout:null,y=typeof setImmediate<`u`?setImmediate:null;function b(e){for(var i=n(l);i!==null;){if(i.callback===null)r(l);else if(i.startTime<=e)r(l),i.sortIndex=i.expirationTime,t(c,i);else break;i=n(l)}}function x(e){if(h=!1,b(e),!m)if(n(c)!==null)m=!0,S||(S=!0,O());else{var t=n(l);t!==null&&j(x,t.startTime-e)}}var S=!1,C=-1,w=5,T=-1;function E(){return g?!0:!(e.unstable_now()-Tt&&E());){var o=d.callback;if(typeof o==`function`){d.callback=null,f=d.priorityLevel;var s=o(d.expirationTime<=t);if(t=e.unstable_now(),typeof s==`function`){d.callback=s,b(t),i=!0;break b}d===n(c)&&r(c),b(t)}else r(c);d=n(c)}if(d!==null)i=!0;else{var u=n(l);u!==null&&j(x,u.startTime-t),i=!1}}break a}finally{d=null,f=a,p=!1}i=void 0}}finally{i?O():S=!1}}}var O;if(typeof y==`function`)O=function(){y(D)};else if(typeof MessageChannel<`u`){var k=new MessageChannel,A=k.port2;k.port1.onmessage=D,O=function(){A.postMessage(null)}}else O=function(){_(D,0)};function j(t,n){C=_(function(){t(e.unstable_now())},n)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(e){e.callback=null},e.unstable_forceFrameRate=function(e){0>e||125o?(r.sortIndex=a,t(l,r),n(c)===null&&r===n(l)&&(h?(v(C),C=-1):h=!0,j(x,a-o))):(r.sortIndex=s,t(c,r),m||p||(m=!0,S||(S=!0,O()))),r},e.unstable_shouldYield=E,e.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}})),fd=o(((e,t)=>{t.exports=dd()})),pd=o((e=>{var t=fd(),n=u(),r=fl();function i(e){var t=`https://react.dev/errors/`+e;if(1re||(e.current=ne[re],ne[re]=null,re--)}function I(e,t){re++,ne[re]=e.current,e.current=t}var ae=F(null),oe=F(null),se=F(null),ce=F(null);function le(e,t){switch(I(se,t),I(oe,e),I(ae,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Wd(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Wd(t),e=Gd(t,e);else switch(e){case`svg`:e=1;break;case`math`:e=2;break;default:e=0}}ie(ae),I(ae,e)}function ue(){ie(ae),ie(oe),ie(se)}function de(e){e.memoizedState!==null&&I(ce,e);var t=ae.current,n=Gd(t,e.type);t!==n&&(I(oe,e),I(ae,n))}function L(e){oe.current===e&&(ie(ae),ie(oe)),ce.current===e&&(ie(ce),tp._currentValue=P)}var fe,pe;function me(e){if(fe===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);fe=t&&t[1]||``,pe=-1)`:-1i||c[r]!==l[i]){var u=` +`+c[r].replace(` at new `,` at `);return e.displayName&&u.includes(``)&&(u=u.replace(``,e.displayName)),u}while(1<=r&&0<=i);break}}}finally{he=!1,Error.prepareStackTrace=n}return(n=e?e.displayName||e.name:``)?me(n):``}function _e(e,t){switch(e.tag){case 26:case 27:case 5:return me(e.type);case 16:return me(`Lazy`);case 13:return e.child!==t&&t!==null?me(`Suspense Fallback`):me(`Suspense`);case 19:return me(`SuspenseList`);case 0:case 15:return ge(e.type,!1);case 11:return ge(e.type.render,!1);case 1:return ge(e.type,!0);case 31:return me(`Activity`);default:return``}}function ve(e){try{var t=``,n=null;do t+=_e(e,n),n=e,e=e.return;while(e);return t}catch(e){return` +Error generating stack: `+e.message+` +`+e.stack}}var ye=Object.prototype.hasOwnProperty,be=t.unstable_scheduleCallback,xe=t.unstable_cancelCallback,R=t.unstable_shouldYield,Se=t.unstable_requestPaint,z=t.unstable_now,Ce=t.unstable_getCurrentPriorityLevel,we=t.unstable_ImmediatePriority,Te=t.unstable_UserBlockingPriority,Ee=t.unstable_NormalPriority,De=t.unstable_LowPriority,Oe=t.unstable_IdlePriority,ke=t.log,Ae=t.unstable_setDisableYieldValue,je=null,Me=null;function Ne(e){if(typeof ke==`function`&&Ae(e),Me&&typeof Me.setStrictMode==`function`)try{Me.setStrictMode(je,e)}catch{}}var Pe=Math.clz32?Math.clz32:Le,Fe=Math.log,Ie=Math.LN2;function Le(e){return e>>>=0,e===0?32:31-(Fe(e)/Ie|0)|0}var Re=256,ze=262144,Be=4194304;function Ve(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function He(e,t,n){var r=e.pendingLanes;if(r===0)return 0;var i=0,a=e.suspendedLanes,o=e.pingedLanes;e=e.warmLanes;var s=r&134217727;return s===0?(s=r&~a,s===0?o===0?n||(n=r&~e,n!==0&&(i=Ve(n))):i=Ve(o):i=Ve(s)):(r=s&~a,r===0?(o&=s,o===0?n||(n=s&~e,n!==0&&(i=Ve(n))):i=Ve(o)):i=Ve(r)),i===0?0:t!==0&&t!==i&&(t&a)===0&&(a=i&-i,n=t&-t,a>=n||a===32&&n&4194048)?t:i}function Ue(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function We(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function Ge(){var e=Be;return Be<<=1,!(Be&62914560)&&(Be=4194304),e}function Ke(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function qe(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function Je(e,t,n,r,i,a){var o=e.pendingLanes;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=n,e.entangledLanes&=n,e.errorRecoveryDisabledLanes&=n,e.shellSuspendCounter=0;var s=e.entanglements,c=e.expirationTimes,l=e.hiddenUpdates;for(n=o&~n;0`u`||window.document===void 0||window.document.createElement===void 0),on=!1;if(an)try{var sn={};Object.defineProperty(sn,`passive`,{get:function(){on=!0}}),window.addEventListener(`test`,sn,sn),window.removeEventListener(`test`,sn,sn)}catch{on=!1}var cn=null,ln=null,un=null;function dn(){if(un)return un;var e,t=ln,n=t.length,r,i=`value`in cn?cn.value:cn.textContent,a=i.length;for(e=0;e=Hn),Gn=` `,Kn=!1;function qn(e,t){switch(e){case`keyup`:return Bn.indexOf(t.keyCode)!==-1;case`keydown`:return t.keyCode!==229;case`keypress`:case`mousedown`:case`focusout`:return!0;default:return!1}}function Jn(e){return e=e.detail,typeof e==`object`&&`data`in e?e.data:null}var H=!1;function Yn(e,t){switch(e){case`compositionend`:return Jn(t);case`keypress`:return t.which===32?(Kn=!0,Gn):null;case`textInput`:return e=t.data,e===Gn&&Kn?null:e;default:return null}}function Xn(e,t){if(H)return e===`compositionend`||!Vn&&qn(e,t)?(e=dn(),un=ln=cn=null,H=!1,e):null;switch(e){case`paste`:return null;case`keypress`:if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}a:{for(;n;){if(n.nextSibling){n=n.nextSibling;break a}n=n.parentNode}n=void 0}n=_r(n)}}function yr(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?yr(e,t.parentNode):`contains`in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function br(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=Mt(e.document);t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href==`string`}catch{n=!1}if(n)e=t.contentWindow;else break;t=Mt(e.document)}return t}function xr(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t===`input`&&(e.type===`text`||e.type===`search`||e.type===`tel`||e.type===`url`||e.type===`password`)||t===`textarea`||e.contentEditable===`true`)}var Sr=an&&`documentMode`in document&&11>=document.documentMode,Cr=null,wr=null,Tr=null,Er=!1;function Dr(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;Er||Cr==null||Cr!==Mt(r)||(r=Cr,`selectionStart`in r&&xr(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),Tr&&gr(Tr,r)||(Tr=r,r=Od(wr,`onSelect`),0>=o,i-=o,yi=1<<32-Pe(t)+i|n<h?(g=d,d=null):g=d.sibling;var _=p(i,d,s[h],c);if(_===null){d===null&&(d=g);break}e&&d&&_.alternate===null&&t(i,d),a=o(_,a,h),u===null?l=_:u.sibling=_,u=_,d=g}if(h===s.length)return n(i,d),W&&xi(i,h),l;if(d===null){for(;hg?(_=h,h=null):_=h.sibling;var y=p(a,h,v.value,l);if(y===null){h===null&&(h=_);break}e&&h&&y.alternate===null&&t(a,h),s=o(y,s,g),d===null?u=y:d.sibling=y,d=y,h=_}if(v.done)return n(a,h),W&&xi(a,g),u;if(h===null){for(;!v.done;g++,v=c.next())v=f(a,v.value,l),v!==null&&(s=o(v,s,g),d===null?u=v:d.sibling=v,d=v);return W&&xi(a,g),u}for(h=r(h);!v.done;g++,v=c.next())v=m(h,a,g,v.value,l),v!==null&&(e&&v.alternate!==null&&h.delete(v.key===null?g:v.key),s=o(v,s,g),d===null?u=v:d.sibling=v,d=v);return e&&h.forEach(function(e){return t(a,e)}),W&&xi(a,g),u}function b(e,r,o,c){if(typeof o==`object`&&o&&o.type===_&&o.key===null&&(o=o.props.children),typeof o==`object`&&o){switch(o.$$typeof){case h:a:{for(var l=o.key;r!==null;){if(r.key===l){if(l=o.type,l===_){if(r.tag===7){n(e,r.sibling),c=a(r,o.props.children),c.return=e,e=c;break a}}else if(r.elementType===l||typeof l==`object`&&l&&l.$$typeof===E&&xa(l)===r.type){n(e,r.sibling),c=a(r,o.props),Oa(c,o),c.return=e,e=c;break a}n(e,r);break}else t(e,r);r=r.sibling}o.type===_?(c=oi(o.props.children,e.mode,c,o.key),c.return=e,e=c):(c=ai(o.type,o.key,o.props,null,e.mode,c),Oa(c,o),c.return=e,e=c)}return s(e);case g:a:{for(l=o.key;r!==null;){if(r.key===l)if(r.tag===4&&r.stateNode.containerInfo===o.containerInfo&&r.stateNode.implementation===o.implementation){n(e,r.sibling),c=a(r,o.children||[]),c.return=e,e=c;break a}else{n(e,r);break}else t(e,r);r=r.sibling}c=li(o,e.mode,c),c.return=e,e=c}return s(e);case E:return o=xa(o),b(e,r,o,c)}if(te(o))return v(e,r,o,c);if(A(o)){if(l=A(o),typeof l!=`function`)throw Error(i(150));return o=l.call(o),y(e,r,o,c)}if(typeof o.then==`function`)return b(e,r,Da(o),c);if(o.$$typeof===x)return b(e,r,Yi(e,o),c);ka(e,o)}return typeof o==`string`&&o!==``||typeof o==`number`||typeof o==`bigint`?(o=``+o,r!==null&&r.tag===6?(n(e,r.sibling),c=a(r,o),c.return=e,e=c):(n(e,r),c=si(o,e.mode,c),c.return=e,e=c),s(e)):n(e,r)}return function(e,t,n,r){try{Ea=0;var i=b(e,t,n,r);return Ta=null,i}catch(t){if(t===ha||t===_a)throw t;var a=ti(29,t,null,e.mode);return a.lanes=r,a.return=e,a}}}var ja=Aa(!0),Ma=Aa(!1),Na=!1;function Pa(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Fa(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function Ia(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function La(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,Ll&2){var i=r.pending;return i===null?t.next=t:(t.next=i.next,i.next=t),r.pending=t,t=Qr(e),Zr(e,null,n),t}return Jr(e,r,t,n),Qr(e)}function Ra(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,n&4194048)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,Xe(e,n)}}function za(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var i=null,a=null;if(n=n.firstBaseUpdate,n!==null){do{var o={lane:n.lane,tag:n.tag,payload:n.payload,callback:null,next:null};a===null?i=a=o:a=a.next=o,n=n.next}while(n!==null);a===null?i=a=t:a=a.next=t}else i=a=t;n={baseState:r.baseState,firstBaseUpdate:i,lastBaseUpdate:a,shared:r.shared,callbacks:r.callbacks},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}var Ba=!1;function Va(){if(Ba){var e=oa;if(e!==null)throw e}}function Ha(e,t,n,r){Ba=!1;var i=e.updateQueue;Na=!1;var a=i.firstBaseUpdate,o=i.lastBaseUpdate,s=i.shared.pending;if(s!==null){i.shared.pending=null;var c=s,l=c.next;c.next=null,o===null?a=l:o.next=l,o=c;var u=e.alternate;u!==null&&(u=u.updateQueue,s=u.lastBaseUpdate,s!==o&&(s===null?u.firstBaseUpdate=l:s.next=l,u.lastBaseUpdate=c))}if(a!==null){var d=i.baseState;o=0,u=l=c=null,s=a;do{var f=s.lane&-536870913,m=f!==s.lane;if(m?(J&f)===f:(r&f)===f){f!==0&&f===aa&&(Ba=!0),u!==null&&(u=u.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});a:{var h=e,g=s;f=t;var _=n;switch(g.tag){case 1:if(h=g.payload,typeof h==`function`){d=h.call(_,d,f);break a}d=h;break a;case 3:h.flags=h.flags&-65537|128;case 0:if(h=g.payload,f=typeof h==`function`?h.call(_,d,f):h,f==null)break a;d=p({},d,f);break a;case 2:Na=!0}}f=s.callback,f!==null&&(e.flags|=64,m&&(e.flags|=8192),m=i.callbacks,m===null?i.callbacks=[f]:m.push(f))}else m={lane:f,tag:s.tag,payload:s.payload,callback:s.callback,next:null},u===null?(l=u=m,c=d):u=u.next=m,o|=f;if(s=s.next,s===null){if(s=i.shared.pending,s===null)break;m=s,s=m.next,m.next=null,i.lastBaseUpdate=m,i.shared.pending=null}}while(1);u===null&&(c=d),i.baseState=c,i.firstBaseUpdate=l,i.lastBaseUpdate=u,a===null&&(i.shared.lanes=0),Kl|=o,e.lanes=o,e.memoizedState=d}}function Ua(e,t){if(typeof e!=`function`)throw Error(i(191,e));e.call(t)}function Wa(e,t){var n=e.callbacks;if(n!==null)for(e.callbacks=null,e=0;ea?a:8;var o=M.T,s={};M.T=s,ks(e,!1,t,n);try{var c=i(),l=M.S;l!==null&&l(s,c),typeof c==`object`&&c&&typeof c.then==`function`?Os(e,t,la(c,r),mu(e)):Os(e,t,r,mu(e))}catch(n){Os(e,t,{then:function(){},status:`rejected`,reason:n},mu())}finally{N.p=a,o!==null&&s.types!==null&&(o.types=s.types),M.T=o}}function vs(){}function ys(e,t,n,r){if(e.tag!==5)throw Error(i(476));var a=bs(e).queue;_s(e,a,t,P,n===null?vs:function(){return xs(e),n(r)})}function bs(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:P,baseState:P,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Ao,lastRenderedState:P},next:null};var n={};return t.next={memoizedState:n,baseState:n,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Ao,lastRenderedState:n},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function xs(e){var t=bs(e);t.next===null&&(t=e.alternate.memoizedState),Os(e,t.next.queue,{},mu())}function Ss(){return Ji(tp)}function Cs(){return To().memoizedState}function ws(){return To().memoizedState}function Ts(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var n=mu();e=Ia(n);var r=La(t,e,n);r!==null&&(gu(r,t,n),Ra(r,t,n)),t={cache:ta()},e.payload=t;return}t=t.return}}function Es(e,t,n){var r=mu();n={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null},As(e)?js(t,n):(n=Yr(e,t,n,r),n!==null&&(gu(n,e,r),Ms(n,t,r)))}function Ds(e,t,n){Os(e,t,n,mu())}function Os(e,t,n,r){var i={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null};if(As(e))js(t,i);else{var a=e.alternate;if(e.lanes===0&&(a===null||a.lanes===0)&&(a=t.lastRenderedReducer,a!==null))try{var o=t.lastRenderedState,s=a(o,n);if(i.hasEagerState=!0,i.eagerState=s,hr(s,o))return Jr(e,t,i,0),Rl===null&&qr(),!1}catch{}if(n=Yr(e,t,i,r),n!==null)return gu(n,e,r),Ms(n,t,r),!0}return!1}function ks(e,t,n,r){if(r={lane:2,revertLane:pd(),gesture:null,action:r,hasEagerState:!1,eagerState:null,next:null},As(e)){if(t)throw Error(i(479))}else t=Yr(e,n,r,2),t!==null&&gu(t,e,2)}function As(e){var t=e.alternate;return e===G||t!==null&&t===G}function js(e,t){co=so=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function Ms(e,t,n){if(n&4194048){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,Xe(e,n)}}var Ns={readContext:Ji,use:Oo,useCallback:ho,useContext:ho,useEffect:ho,useImperativeHandle:ho,useLayoutEffect:ho,useInsertionEffect:ho,useMemo:ho,useReducer:ho,useRef:ho,useState:ho,useDebugValue:ho,useDeferredValue:ho,useTransition:ho,useSyncExternalStore:ho,useId:ho,useHostTransitionStatus:ho,useFormState:ho,useActionState:ho,useOptimistic:ho,useMemoCache:ho,useCacheRefresh:ho};Ns.useEffectEvent=ho;var Ps={readContext:Ji,use:Oo,useCallback:function(e,t){return wo().memoizedState=[e,t===void 0?null:t],e},useContext:Ji,useEffect:is,useImperativeHandle:function(e,t,n){n=n==null?null:n.concat([e]),ns(4194308,4,us.bind(null,t,e),n)},useLayoutEffect:function(e,t){return ns(4194308,4,e,t)},useInsertionEffect:function(e,t){ns(4,2,e,t)},useMemo:function(e,t){var n=wo();t=t===void 0?null:t;var r=e();if(lo){Ne(!0);try{e()}finally{Ne(!1)}}return n.memoizedState=[r,t],r},useReducer:function(e,t,n){var r=wo();if(n!==void 0){var i=n(t);if(lo){Ne(!0);try{n(t)}finally{Ne(!1)}}}else i=t;return r.memoizedState=r.baseState=i,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:i},r.queue=e,e=e.dispatch=Es.bind(null,G,e),[r.memoizedState,e]},useRef:function(e){var t=wo();return e={current:e},t.memoizedState=e},useState:function(e){e=Bo(e);var t=e.queue,n=Ds.bind(null,G,t);return t.dispatch=n,[e.memoizedState,n]},useDebugValue:fs,useDeferredValue:function(e,t){return hs(wo(),e,t)},useTransition:function(){var e=Bo(!1);return e=_s.bind(null,G,e.queue,!0,!1),wo().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,n){var r=G,a=wo();if(W){if(n===void 0)throw Error(i(407));n=n()}else{if(n=t(),Rl===null)throw Error(i(349));J&127||Fo(r,t,n)}a.memoizedState=n;var o={value:n,getSnapshot:t};return a.queue=o,is(Lo.bind(null,r,o,e),[e]),r.flags|=2048,es(9,{destroy:void 0},Io.bind(null,r,o,n,t),null),n},useId:function(){var e=wo(),t=Rl.identifierPrefix;if(W){var n=bi,r=yi;n=(r&~(1<<32-Pe(r)-1)).toString(32)+n,t=`_`+t+`R_`+n,n=uo++,0<\/script>`,o=o.removeChild(o.firstChild);break;case`select`:o=typeof r.is==`string`?s.createElement(`select`,{is:r.is}):s.createElement(`select`),r.multiple?o.multiple=!0:r.size&&(o.size=r.size);break;default:o=typeof r.is==`string`?s.createElement(a,{is:r.is}):s.createElement(a)}}o[rt]=t,o[it]=r;a:for(s=t.child;s!==null;){if(s.tag===5||s.tag===6)o.appendChild(s.stateNode);else if(s.tag!==4&&s.tag!==27&&s.child!==null){s.child.return=s,s=s.child;continue}if(s===t)break a;for(;s.sibling===null;){if(s.return===null||s.return===t)break a;s=s.return}s.sibling.return=s.return,s=s.sibling}t.stateNode=o;a:switch(Ld(o,a,r),a){case`button`:case`input`:case`select`:case`textarea`:r=!!r.autoFocus;break a;case`img`:r=!0;break a;default:r=!1}r&&Oc(t)}}return Nc(t),kc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,n),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==r&&Oc(t);else{if(typeof r!=`string`&&t.stateNode===null)throw Error(i(166));if(e=se.current,Pi(t)){if(e=t.stateNode,n=t.memoizedProps,r=null,a=Ei,a!==null)switch(a.tag){case 27:case 5:r=a.memoizedProps}e[rt]=t,e=!!(e.nodeValue===n||r!==null&&!0===r.suppressHydrationWarning||Pd(e.nodeValue,n)),e||ji(t,!0)}else e=Ud(e).createTextNode(r),e[rt]=t,t.stateNode=e}return Nc(t),null;case 31:if(n=t.memoizedState,e===null||e.memoizedState!==null){if(r=Pi(t),n!==null){if(e===null){if(!r)throw Error(i(318));if(e=t.memoizedState,e=e===null?null:e.dehydrated,!e)throw Error(i(557));e[rt]=t}else Fi(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;Nc(t),e=!1}else n=Ii(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),e=!0;if(!e)return t.flags&256?(no(t),t):(no(t),null);if(t.flags&128)throw Error(i(558))}return Nc(t),null;case 13:if(r=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(a=Pi(t),r!==null&&r.dehydrated!==null){if(e===null){if(!a)throw Error(i(318));if(a=t.memoizedState,a=a===null?null:a.dehydrated,!a)throw Error(i(317));a[rt]=t}else Fi(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;Nc(t),a=!1}else a=Ii(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=a),a=!0;if(!a)return t.flags&256?(no(t),t):(no(t),null)}return no(t),t.flags&128?(t.lanes=n,t):(n=r!==null,e=e!==null&&e.memoizedState!==null,n&&(r=t.child,a=null,r.alternate!==null&&r.alternate.memoizedState!==null&&r.alternate.memoizedState.cachePool!==null&&(a=r.alternate.memoizedState.cachePool.pool),o=null,r.memoizedState!==null&&r.memoizedState.cachePool!==null&&(o=r.memoizedState.cachePool.pool),o!==a&&(r.flags|=2048)),n!==e&&n&&(t.child.flags|=8192),jc(t,t.updateQueue),Nc(t),null);case 4:return ue(),e===null&&wd(t.stateNode.containerInfo),Nc(t),null;case 10:return Hi(t.type),Nc(t),null;case 19:if(ie(ro),r=t.memoizedState,r===null)return Nc(t),null;if(a=(t.flags&128)!=0,o=r.rendering,o===null)if(a)Mc(r,!1);else{if(Gl!==0||e!==null&&e.flags&128)for(e=t.child;e!==null;){if(o=io(e),o!==null){for(t.flags|=128,Mc(r,!1),e=o.updateQueue,t.updateQueue=e,jc(t,e),t.subtreeFlags=0,e=n,n=t.child;n!==null;)ii(n,e),n=n.sibling;return I(ro,ro.current&1|2),W&&xi(t,r.treeForkCount),t.child}e=e.sibling}r.tail!==null&&z()>nu&&(t.flags|=128,a=!0,Mc(r,!1),t.lanes=4194304)}else{if(!a)if(e=io(o),e!==null){if(t.flags|=128,a=!0,e=e.updateQueue,t.updateQueue=e,jc(t,e),Mc(r,!0),r.tail===null&&r.tailMode===`hidden`&&!o.alternate&&!W)return Nc(t),null}else 2*z()-r.renderingStartTime>nu&&n!==536870912&&(t.flags|=128,a=!0,Mc(r,!1),t.lanes=4194304);r.isBackwards?(o.sibling=t.child,t.child=o):(e=r.last,e===null?t.child=o:e.sibling=o,r.last=o)}return r.tail===null?(Nc(t),null):(e=r.tail,r.rendering=e,r.tail=e.sibling,r.renderingStartTime=z(),e.sibling=null,n=ro.current,I(ro,a?n&1|2:n&1),W&&xi(t,r.treeForkCount),e);case 22:case 23:return no(t),Ya(),r=t.memoizedState!==null,e===null?r&&(t.flags|=8192):e.memoizedState!==null!==r&&(t.flags|=8192),r?n&536870912&&!(t.flags&128)&&(Nc(t),t.subtreeFlags&6&&(t.flags|=8192)):Nc(t),n=t.updateQueue,n!==null&&jc(t,n.retryQueue),n=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(n=e.memoizedState.cachePool.pool),r=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(r=t.memoizedState.cachePool.pool),r!==n&&(t.flags|=2048),e!==null&&ie(da),null;case 24:return n=null,e!==null&&(n=e.memoizedState.cache),t.memoizedState.cache!==n&&(t.flags|=2048),Hi(ea),Nc(t),null;case 25:return null;case 30:return null}throw Error(i(156,t.tag))}function Fc(e,t){switch(wi(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Hi(ea),ue(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return L(t),null;case 31:if(t.memoizedState!==null){if(no(t),t.alternate===null)throw Error(i(340));Fi()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(no(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(i(340));Fi()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return ie(ro),null;case 4:return ue(),null;case 10:return Hi(t.type),null;case 22:case 23:return no(t),Ya(),e!==null&&ie(da),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return Hi(ea),null;case 25:return null;default:return null}}function Ic(e,t){switch(wi(t),t.tag){case 3:Hi(ea),ue();break;case 26:case 27:case 5:L(t);break;case 4:ue();break;case 31:t.memoizedState!==null&&no(t);break;case 13:no(t);break;case 19:ie(ro);break;case 10:Hi(t.type);break;case 22:case 23:no(t),Ya(),e!==null&&ie(da);break;case 24:Hi(ea)}}function Lc(e,t){try{var n=t.updateQueue,r=n===null?null:n.lastEffect;if(r!==null){var i=r.next;n=i;do{if((n.tag&e)===e){r=void 0;var a=n.create,o=n.inst;r=a(),o.destroy=r}n=n.next}while(n!==i)}}catch(e){Gu(t,t.return,e)}}function Rc(e,t,n){try{var r=t.updateQueue,i=r===null?null:r.lastEffect;if(i!==null){var a=i.next;r=a;do{if((r.tag&e)===e){var o=r.inst,s=o.destroy;if(s!==void 0){o.destroy=void 0,i=t;var c=n,l=s;try{l()}catch(e){Gu(i,c,e)}}}r=r.next}while(r!==a)}}catch(e){Gu(t,t.return,e)}}function zc(e){var t=e.updateQueue;if(t!==null){var n=e.stateNode;try{Wa(t,n)}catch(t){Gu(e,e.return,t)}}}function Bc(e,t,n){n.props=Vs(e.type,e.memoizedProps),n.state=e.memoizedState;try{n.componentWillUnmount()}catch(n){Gu(e,t,n)}}function Vc(e,t){try{var n=e.ref;if(n!==null){switch(e.tag){case 26:case 27:case 5:var r=e.stateNode;break;case 30:r=e.stateNode;break;default:r=e.stateNode}typeof n==`function`?e.refCleanup=n(r):n.current=r}}catch(n){Gu(e,t,n)}}function Hc(e,t){var n=e.ref,r=e.refCleanup;if(n!==null)if(typeof r==`function`)try{r()}catch(n){Gu(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof n==`function`)try{n(null)}catch(n){Gu(e,t,n)}else n.current=null}function Uc(e){var t=e.type,n=e.memoizedProps,r=e.stateNode;try{a:switch(t){case`button`:case`input`:case`select`:case`textarea`:n.autoFocus&&r.focus();break a;case`img`:n.src?r.src=n.src:n.srcSet&&(r.srcset=n.srcSet)}}catch(t){Gu(e,e.return,t)}}function Wc(e,t,n){try{var r=e.stateNode;Rd(r,e.type,n,t),r[it]=t}catch(t){Gu(e,e.return,t)}}function Gc(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&ef(e.type)||e.tag===4}function Kc(e){a:for(;;){for(;e.sibling===null;){if(e.return===null||Gc(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&ef(e.type)||e.flags&2||e.child===null||e.tag===4)continue a;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function qc(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?(n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n).insertBefore(e,t):(t=n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n,t.appendChild(e),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=Yt));else if(r!==4&&(r===27&&ef(e.type)&&(n=e.stateNode,t=null),e=e.child,e!==null))for(qc(e,t,n),e=e.sibling;e!==null;)qc(e,t,n),e=e.sibling}function Jc(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(r!==4&&(r===27&&ef(e.type)&&(n=e.stateNode),e=e.child,e!==null))for(Jc(e,t,n),e=e.sibling;e!==null;)Jc(e,t,n),e=e.sibling}function Yc(e){var t=e.stateNode,n=e.memoizedProps;try{for(var r=e.type,i=t.attributes;i.length;)t.removeAttributeNode(i[0]);Ld(t,r,n),t[rt]=e,t[it]=n}catch(t){Gu(e,e.return,t)}}var Xc=!1,Zc=!1,Qc=!1,$c=typeof WeakSet==`function`?WeakSet:Set,el=null;function tl(e,t){if(e=e.containerInfo,Vd=up,e=br(e),xr(e)){if(`selectionStart`in e)var n={start:e.selectionStart,end:e.selectionEnd};else a:{n=(n=e.ownerDocument)&&n.defaultView||window;var r=n.getSelection&&n.getSelection();if(r&&r.rangeCount!==0){n=r.anchorNode;var a=r.anchorOffset,o=r.focusNode;r=r.focusOffset;try{n.nodeType,o.nodeType}catch{n=null;break a}var s=0,c=-1,l=-1,u=0,d=0,f=e,p=null;b:for(;;){for(var m;f!==n||a!==0&&f.nodeType!==3||(c=s+a),f!==o||r!==0&&f.nodeType!==3||(l=s+r),f.nodeType===3&&(s+=f.nodeValue.length),(m=f.firstChild)!==null;)p=f,f=m;for(;;){if(f===e)break b;if(p===n&&++u===a&&(c=s),p===o&&++d===r&&(l=s),(m=f.nextSibling)!==null)break;f=p,p=f.parentNode}f=m}n=c===-1||l===-1?null:{start:c,end:l}}else n=null}n||={start:0,end:0}}else n=null;for(Hd={focusedElem:e,selectionRange:n},up=!1,el=t;el!==null;)if(t=el,e=t.child,t.subtreeFlags&1028&&e!==null)e.return=t,el=e;else for(;el!==null;){switch(t=el,o=t.alternate,e=t.flags,t.tag){case 0:if(e&4&&(e=t.updateQueue,e=e===null?null:e.events,e!==null))for(n=0;n title`))),Ld(o,r,n),o[rt]=e,gt(o),r=o;break a;case`link`:var s=Wf(`link`,`href`,a).get(r+(n.href||``));if(s){for(var c=0;cg&&(o=g,g=h,h=o);var _=vr(s,h),v=vr(s,g);if(_&&v&&(p.rangeCount!==1||p.anchorNode!==_.node||p.anchorOffset!==_.offset||p.focusNode!==v.node||p.focusOffset!==v.offset)){var y=d.createRange();y.setStart(_.node,_.offset),p.removeAllRanges(),h>g?(p.addRange(y),p.extend(v.node,v.offset)):(y.setEnd(v.node,v.offset),p.addRange(y))}}}}for(d=[],p=s;p=p.parentNode;)p.nodeType===1&&d.push({element:p,left:p.scrollLeft,top:p.scrollTop});for(typeof s.focus==`function`&&s.focus(),s=0;sn?32:n,M.T=null,n=uu,uu=null;var o=ou,s=cu;if(au=0,su=ou=null,cu=0,Ll&6)throw Error(i(331));var c=Ll;if(Ll|=4,Ml(o.current),wl(o,o.current,s,n),Ll=c,ad(0,!1),Me&&typeof Me.onPostCommitFiberRoot==`function`)try{Me.onPostCommitFiberRoot(je,o)}catch{}return!0}finally{N.p=a,M.T=r,Vu(e,t)}}function Wu(e,t,n){t=di(n,t),t=qs(e.stateNode,t,2),e=La(e,t,2),e!==null&&(qe(e,2),id(e))}function Gu(e,t,n){if(e.tag===3)Wu(e,e,n);else for(;t!==null;){if(t.tag===3){Wu(t,e,n);break}else if(t.tag===1){var r=t.stateNode;if(typeof t.type.getDerivedStateFromError==`function`||typeof r.componentDidCatch==`function`&&(iu===null||!iu.has(r))){e=di(n,e),n=Js(2),r=La(t,n,2),r!==null&&(Ys(n,r,t,e),qe(r,2),id(r));break}}t=t.return}}function Ku(e,t,n){var r=e.pingCache;if(r===null){r=e.pingCache=new Il;var i=new Set;r.set(t,i)}else i=r.get(t),i===void 0&&(i=new Set,r.set(t,i));i.has(n)||(Ul=!0,i.add(n),e=qu.bind(null,e,t,n),t.then(e,e))}function qu(e,t,n){var r=e.pingCache;r!==null&&r.delete(t),e.pingedLanes|=e.suspendedLanes&n,e.warmLanes&=~n,Rl===e&&(J&n)===n&&(Gl===4||Gl===3&&(J&62914560)===J&&300>z()-eu?!(Ll&2)&&Cu(e,0):Jl|=n,Xl===J&&(Xl=0)),id(e)}function Ju(e,t){t===0&&(t=Ge()),e=Xr(e,t),e!==null&&(qe(e,t),id(e))}function Yu(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),Ju(e,n)}function Xu(e,t){var n=0;switch(e.tag){case 31:case 13:var r=e.stateNode,a=e.memoizedState;a!==null&&(n=a.retryLane);break;case 19:r=e.stateNode;break;case 22:r=e.stateNode._retryCache;break;default:throw Error(i(314))}r!==null&&r.delete(t),Ju(e,n)}function Zu(e,t){return be(e,t)}var Qu=null,$u=null,ed=!1,td=!1,nd=!1,rd=0;function id(e){e!==$u&&e.next===null&&($u===null?Qu=$u=e:$u=$u.next=e),td=!0,ed||(ed=!0,dd())}function ad(e,t){if(!nd&&td){nd=!0;do for(var n=!1,r=Qu;r!==null;){if(!t)if(e!==0){var i=r.pendingLanes;if(i===0)var a=0;else{var o=r.suspendedLanes,s=r.pingedLanes;a=(1<<31-Pe(42|e)+1)-1,a&=i&~(o&~s),a=a&201326741?a&201326741|1:a?a|2:0}a!==0&&(n=!0,ud(r,a))}else a=J,a=He(r,r===Rl?a:0,r.cancelPendingCommit!==null||r.timeoutHandle!==-1),!(a&3)||Ue(r,a)||(n=!0,ud(r,a));r=r.next}while(n);nd=!1}}function od(){sd()}function sd(){td=ed=!1;var e=0;rd!==0&&Jd()&&(e=rd);for(var t=z(),n=null,r=Qu;r!==null;){var i=r.next,a=cd(r,t);a===0?(r.next=null,n===null?Qu=i:n.next=i,i===null&&($u=n)):(n=r,(e!==0||a&3)&&(td=!0)),r=i}au!==0&&au!==5||ad(e,!1),rd!==0&&(rd=0)}function cd(e,t){for(var n=e.suspendedLanes,r=e.pingedLanes,i=e.expirationTimes,a=e.pendingLanes&-62914561;0s)break;var u=c.transferSize,d=c.initiatorType;u&&zd(d)&&(c=c.responseEnd,o+=u*(c`u`?null:document;function wf(e,t,n){var r=Cf;if(r&&typeof t==`string`&&t){var i=Pt(t);i=`link[rel="`+e+`"][href="`+i+`"]`,typeof n==`string`&&(i+=`[crossorigin="`+n+`"]`),vf.has(i)||(vf.add(i),e={rel:e,crossOrigin:n,href:t},r.querySelector(i)===null&&(t=r.createElement(`link`),Ld(t,`link`,e),gt(t),r.head.appendChild(t)))}}function Tf(e){bf.D(e),wf(`dns-prefetch`,e,null)}function Ef(e,t){bf.C(e,t),wf(`preconnect`,e,t)}function Df(e,t,n){bf.L(e,t,n);var r=Cf;if(r&&e&&t){var i=`link[rel="preload"][as="`+Pt(t)+`"]`;t===`image`&&n&&n.imageSrcSet?(i+=`[imagesrcset="`+Pt(n.imageSrcSet)+`"]`,typeof n.imageSizes==`string`&&(i+=`[imagesizes="`+Pt(n.imageSizes)+`"]`)):i+=`[href="`+Pt(e)+`"]`;var a=i;switch(t){case`style`:a=Nf(e);break;case`script`:a=Lf(e)}_f.has(a)||(e=p({rel:`preload`,href:t===`image`&&n&&n.imageSrcSet?void 0:e,as:t},n),_f.set(a,e),r.querySelector(i)!==null||t===`style`&&r.querySelector(Pf(a))||t===`script`&&r.querySelector(Rf(a))||(t=r.createElement(`link`),Ld(t,`link`,e),gt(t),r.head.appendChild(t)))}}function Of(e,t){bf.m(e,t);var n=Cf;if(n&&e){var r=t&&typeof t.as==`string`?t.as:`script`,i=`link[rel="modulepreload"][as="`+Pt(r)+`"][href="`+Pt(e)+`"]`,a=i;switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:a=Lf(e)}if(!_f.has(a)&&(e=p({rel:`modulepreload`,href:e},t),_f.set(a,e),n.querySelector(i)===null)){switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:if(n.querySelector(Rf(a)))return}r=n.createElement(`link`),Ld(r,`link`,e),gt(r),n.head.appendChild(r)}}}function kf(e,t,n){bf.S(e,t,n);var r=Cf;if(r&&e){var i=ht(r).hoistableStyles,a=Nf(e);t||=`default`;var o=i.get(a);if(!o){var s={loading:0,preload:null};if(o=r.querySelector(Pf(a)))s.loading=5;else{e=p({rel:`stylesheet`,href:e,"data-precedence":t},n),(n=_f.get(a))&&Vf(e,n);var c=o=r.createElement(`link`);gt(c),Ld(c,`link`,e),c._p=new Promise(function(e,t){c.onload=e,c.onerror=t}),c.addEventListener(`load`,function(){s.loading|=1}),c.addEventListener(`error`,function(){s.loading|=2}),s.loading|=4,Bf(o,t,r)}o={type:`stylesheet`,instance:o,count:1,state:s},i.set(a,o)}}}function Af(e,t){bf.X(e,t);var n=Cf;if(n&&e){var r=ht(n).hoistableScripts,i=Lf(e),a=r.get(i);a||(a=n.querySelector(Rf(i)),a||(e=p({src:e,async:!0},t),(t=_f.get(i))&&Hf(e,t),a=n.createElement(`script`),gt(a),Ld(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function jf(e,t){bf.M(e,t);var n=Cf;if(n&&e){var r=ht(n).hoistableScripts,i=Lf(e),a=r.get(i);a||(a=n.querySelector(Rf(i)),a||(e=p({src:e,async:!0,type:`module`},t),(t=_f.get(i))&&Hf(e,t),a=n.createElement(`script`),gt(a),Ld(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function Mf(e,t,n,r){var a=(a=se.current)?yf(a):null;if(!a)throw Error(i(446));switch(e){case`meta`:case`title`:return null;case`style`:return typeof n.precedence==`string`&&typeof n.href==`string`?(t=Nf(n.href),n=ht(a).hoistableStyles,r=n.get(t),r||(r={type:`style`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};case`link`:if(n.rel===`stylesheet`&&typeof n.href==`string`&&typeof n.precedence==`string`){e=Nf(n.href);var o=ht(a).hoistableStyles,s=o.get(e);if(s||(a=a.ownerDocument||a,s={type:`stylesheet`,instance:null,count:0,state:{loading:0,preload:null}},o.set(e,s),(o=a.querySelector(Pf(e)))&&!o._p&&(s.instance=o,s.state.loading=5),_f.has(e)||(n={rel:`preload`,as:`style`,href:n.href,crossOrigin:n.crossOrigin,integrity:n.integrity,media:n.media,hrefLang:n.hrefLang,referrerPolicy:n.referrerPolicy},_f.set(e,n),o||If(a,e,n,s.state))),t&&r===null)throw Error(i(528,``));return s}if(t&&r!==null)throw Error(i(529,``));return null;case`script`:return t=n.async,n=n.src,typeof n==`string`&&t&&typeof t!=`function`&&typeof t!=`symbol`?(t=Lf(n),n=ht(a).hoistableScripts,r=n.get(t),r||(r={type:`script`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};default:throw Error(i(444,e))}}function Nf(e){return`href="`+Pt(e)+`"`}function Pf(e){return`link[rel="stylesheet"][`+e+`]`}function Ff(e){return p({},e,{"data-precedence":e.precedence,precedence:null})}function If(e,t,n,r){e.querySelector(`link[rel="preload"][as="style"][`+t+`]`)?r.loading=1:(t=e.createElement(`link`),r.preload=t,t.addEventListener(`load`,function(){return r.loading|=1}),t.addEventListener(`error`,function(){return r.loading|=2}),Ld(t,`link`,n),gt(t),e.head.appendChild(t))}function Lf(e){return`[src="`+Pt(e)+`"]`}function Rf(e){return`script[async]`+e}function zf(e,t,n){if(t.count++,t.instance===null)switch(t.type){case`style`:var r=e.querySelector(`style[data-href~="`+Pt(n.href)+`"]`);if(r)return t.instance=r,gt(r),r;var a=p({},n,{"data-href":n.href,"data-precedence":n.precedence,href:null,precedence:null});return r=(e.ownerDocument||e).createElement(`style`),gt(r),Ld(r,`style`,a),Bf(r,n.precedence,e),t.instance=r;case`stylesheet`:a=Nf(n.href);var o=e.querySelector(Pf(a));if(o)return t.state.loading|=4,t.instance=o,gt(o),o;r=Ff(n),(a=_f.get(a))&&Vf(r,a),o=(e.ownerDocument||e).createElement(`link`),gt(o);var s=o;return s._p=new Promise(function(e,t){s.onload=e,s.onerror=t}),Ld(o,`link`,r),t.state.loading|=4,Bf(o,n.precedence,e),t.instance=o;case`script`:return o=Lf(n.src),(a=e.querySelector(Rf(o)))?(t.instance=a,gt(a),a):(r=n,(a=_f.get(o))&&(r=p({},n),Hf(r,a)),e=e.ownerDocument||e,a=e.createElement(`script`),gt(a),Ld(a,`link`,r),e.head.appendChild(a),t.instance=a);case`void`:return null;default:throw Error(i(443,t.type))}else t.type===`stylesheet`&&!(t.state.loading&4)&&(r=t.instance,t.state.loading|=4,Bf(r,n.precedence,e));return t.instance}function Bf(e,t,n){for(var r=n.querySelectorAll(`link[rel="stylesheet"][data-precedence],style[data-precedence]`),i=r.length?r[r.length-1]:null,a=i,o=0;o title`):null)}function Kf(e,t,n){if(n===1||t.itemProp!=null)return!1;switch(e){case`meta`:case`title`:return!0;case`style`:if(typeof t.precedence!=`string`||typeof t.href!=`string`||t.href===``)break;return!0;case`link`:if(typeof t.rel!=`string`||typeof t.href!=`string`||t.href===``||t.onLoad||t.onError)break;switch(t.rel){case`stylesheet`:return e=t.disabled,typeof t.precedence==`string`&&e==null;default:return!0}case`script`:if(t.async&&typeof t.async!=`function`&&typeof t.async!=`symbol`&&!t.onLoad&&!t.onError&&t.src&&typeof t.src==`string`)return!0}return!1}function qf(e){return!(e.type===`stylesheet`&&!(e.state.loading&3))}function Jf(e,t,n,r){if(n.type===`stylesheet`&&(typeof r.media!=`string`||!1!==matchMedia(r.media).matches)&&!(n.state.loading&4)){if(n.instance===null){var i=Nf(r.href),a=t.querySelector(Pf(i));if(a){t=a._p,typeof t==`object`&&t&&typeof t.then==`function`&&(e.count++,e=Zf.bind(e),t.then(e,e)),n.state.loading|=4,n.instance=a,gt(a);return}a=t.ownerDocument||t,r=Ff(r),(i=_f.get(i))&&Vf(r,i),a=a.createElement(`link`),gt(a);var o=a;o._p=new Promise(function(e,t){o.onload=e,o.onerror=t}),Ld(a,`link`,r),n.instance=a}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(n,t),(t=n.state.preload)&&!(n.state.loading&3)&&(e.count++,n=Zf.bind(e),t.addEventListener(`load`,n),t.addEventListener(`error`,n))}}var Yf=0;function Xf(e,t){return e.stylesheets&&e.count===0&&$f(e,e.stylesheets),0Yf?50:800)+t);return e.unsuspend=n,function(){e.unsuspend=null,clearTimeout(r),clearTimeout(i)}}:null}function Zf(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)$f(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var Qf=null;function $f(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,Qf=new Map,t.forEach(ep,e),Qf=null,Zf.call(e))}function ep(e,t){if(!(t.state.loading&4)){var n=Qf.get(e);if(n)var r=n.get(null);else{n=new Map,Qf.set(e,n);for(var i=e.querySelectorAll(`link[data-precedence],style[data-precedence]`),a=0;a{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=pd()}))(),hd=`__rc_react_root__`;function gd(e,t){let n=t[hd]||(0,md.createRoot)(t);n.render(e),t[hd]=n}async function _d(e){return Promise.resolve().then(()=>{e[hd]?.unmount(),delete e[hd]})}var vd=(e,t,n)=>n===void 0?`${e}-${t}`:n,yd=jo(`Wave`,e=>{let{componentCls:t,colorPrimary:n,motionDurationSlow:r,motionEaseInOut:i,motionEaseOutCirc:a,antCls:o}=e,[,s]=No(o,`wave`);return{[t]:{position:`absolute`,background:`transparent`,pointerEvents:`none`,boxSizing:`border-box`,color:s(`color`,n),boxShadow:`0 0 0 0 currentcolor`,opacity:.2,"&.wave-motion-appear":{transition:[`box-shadow 0.4s`,`opacity 2s`].map(e=>`${e} ${a}`).join(`,`),"&-active":{boxShadow:`0 0 0 6px currentcolor`,opacity:0},"&.wave-quick":{transition:[`box-shadow`,`opacity`].map(e=>`${e} ${r} ${i}`).join(`,`)}}}}}),bd=`ant-wave-target`;function xd(e){return e&&typeof e==`string`&&e!==`#fff`&&e!==`#ffffff`&&e!==`rgb(255, 255, 255)`&&e!==`rgba(255, 255, 255, 1)`&&!/rgba\((?:\d*, ){3}0\)/.test(e)&&e!==`transparent`&&e!==`canvastext`}function X(e,t=null){let n=getComputedStyle(e),{borderTopColor:r,borderColor:i,backgroundColor:a}=n;return t&&xd(n[t])?n[t]:[r,i,a].find(xd)??null}function Sd(e){return Number.isNaN(e)?0:e}var Cd=e=>{let{className:t,target:n,component:r,colorSource:i}=e,a=d.useRef(null),{getPrefixCls:o}=d.useContext(zt),[s]=No(o(),`wave`),[c,l]=d.useState(null),[u,f]=d.useState([]),[p,m]=d.useState(0),[h,g]=d.useState(0),[_,v]=d.useState(0),[y,b]=d.useState(0),[x,S]=d.useState(!1),C={left:p,top:h,width:_,height:y,borderRadius:u.map(e=>`${e}px`).join(` `)};c&&(C[s(`color`)]=c);function w(){let e=getComputedStyle(n);l(X(n,i));let t=e.position===`static`,{borderLeftWidth:r,borderTopWidth:a}=e;m(t?n.offsetLeft:Sd(-Number.parseFloat(r))),g(t?n.offsetTop:Sd(-Number.parseFloat(a))),v(n.offsetWidth),b(n.offsetHeight);let{borderTopLeftRadius:o,borderTopRightRadius:s,borderBottomLeftRadius:c,borderBottomRightRadius:u}=e;f([o,s,u,c].map(e=>Sd(Number.parseFloat(e))))}if(d.useEffect(()=>{if(n){let e=Rt(()=>{w(),S(!0)}),t;return typeof ResizeObserver<`u`&&(t=new ResizeObserver(w),t.observe(n)),()=>{Rt.cancel(e),t?.disconnect()}}},[n]),!x)return null;let T=(r===`Checkbox`||r===`Radio`)&&n?.classList.contains(bd);return d.createElement(cc,{visible:!0,motionAppear:!0,motionName:`wave-motion`,motionDeadline:5e3,onAppearEnd:(e,t)=>{if(t.deadline||t.propertyName===`opacity`){let e=a.current?.parentElement;_d(e).then(()=>{e?.remove()})}return!1}},({className:e},n)=>d.createElement(`div`,{ref:Pe(a,n),className:B(t,e,{"wave-quick":T}),style:C}))},wd=(e,t)=>{let{component:n}=t;if(n===`Checkbox`&&!e.querySelector(`input`)?.checked)return;let r=document.createElement(`div`);r.style.position=`absolute`,r.style.left=`0px`,r.style.top=`0px`,e?.insertBefore(r,e?.firstChild),gd(d.createElement(Cd,{...t,target:e}),r)},Td=(e,t,n,r)=>{let{wave:i}=d.useContext(zt),[,a,o]=xo(),s=xe(s=>{let c=e.current;if(i?.disabled||!c)return;let l=c.querySelector(`.${bd}`)||c,{showEffect:u}=i||{};(u||wd)(l,{className:t,token:a,component:n,event:s,hashId:o,colorSource:r})}),c=d.useRef(null);return d.useEffect(()=>()=>{Rt.cancel(c.current)},[]),e=>{Rt.cancel(c.current),c.current=Rt(()=>{s(e)})}},Ed=e=>{let{children:t,disabled:n,component:r,colorSource:i}=e,{getPrefixCls:a}=(0,d.useContext)(zt),o=(0,d.useRef)(null),s=a(`wave`),c=Td(o,B(s,yd(s)),r,i);return d.useEffect(()=>{let e=o.current;if(!e||e.nodeType!==window.Node.ELEMENT_NODE||n)return;let t=t=>{!Kl(t.target)||!e.getAttribute||e.getAttribute(`disabled`)||e.disabled||e.className.includes(`disabled`)&&!e.className.includes(`disabled:`)||e.getAttribute(`aria-disabled`)===`true`||e.className.includes(`-leave`)||c(t)};return e.addEventListener(`click`,t,!0),()=>{e.removeEventListener(`click`,t,!0)}},[n]),d.isValidElement(t)?mu(t,{ref:Ie(t)?Pe(ze(t),o):o}):t??null},Dd=e=>{let t=d.useContext(xu);return d.useMemo(()=>e?typeof e==`string`?e??t:typeof e==`function`?e(t):t:t,[e,t])},Od=d.createContext(null),kd=(e,t)=>{let n=d.useContext(Od),r=d.useMemo(()=>{if(!n)return``;let{compactDirection:r,isFirstItem:i,isLastItem:a}=n,o=r===`vertical`?`-vertical-`:`-`;return B(`${e}-compact${o}item`,{[`${e}-compact${o}first-item`]:i,[`${e}-compact${o}last-item`]:a,[`${e}-compact${o}item-rtl`]:t===`rtl`})},[e,t,n]);return{compactSize:n?.compactSize,compactDirection:n?.compactDirection,compactItemClassnames:r}},Ad=e=>{let{children:t}=e;return d.createElement(Od.Provider,{value:null},t)},jd=d.createContext(void 0),Md=e=>{let{getPrefixCls:t,direction:n}=d.useContext(zt),{prefixCls:r,size:i,className:a,...o}=e,s=t(`btn-group`,r),[,,c]=xo(),l=d.useMemo(()=>{switch(i){case`large`:return`lg`;case`small`:return`sm`;default:return``}},[i]),u=B(s,{[`${s}-${l}`]:l,[`${s}-rtl`]:n===`rtl`},a,c);return d.createElement(jd.Provider,{value:i},d.createElement(`div`,{...o,className:u}))},Nd=/^[\u4E00-\u9FA5]{2}$/,Pd=Nd.test.bind(Nd);function Fd(e){return e===`danger`?{danger:!0}:{type:e}}function Id(e){return typeof e==`string`}function Ld(e){return e===`text`||e===`link`}function Rd(e,t,n,r){if(!Rc(e)||e===``)return;let i=t?` `:``;return typeof e!=`string`&&typeof e!=`number`&&Id(e.type)&&Pd(e.props.children)?mu(e,e=>{let t=B(e.className,r)||void 0,a={...n,...e.style};return{...e,children:e.children.split(``).join(i),className:t,style:a}}):Id(e)?d.createElement(`span`,{className:r,style:n},Pd(e)?e.split(``).join(i):e):fu(e)?d.createElement(`span`,{className:r,style:n},e):mu(e,e=>({...e,className:B(e.className,r)||void 0,style:{...e.style,...n}}))}function zd(e,t,n,r){let i=!1,a=[];return d.Children.forEach(e,e=>{let t=typeof e,n=t===`string`||t===`number`;if(i&&n){let t=a.length-1;a[t]=`${a[t]}${e}`}else a.push(e);i=n}),d.Children.map(a,e=>Rd(e,t,n,r))}[`default`,`primary`,`danger`].concat(Mt(ra));var Bd=(0,d.forwardRef)((e,t)=>{let{className:n,style:r,children:i,prefixCls:a}=e,o=B(`${a}-icon`,n);return d.createElement(`span`,{ref:t,className:o,style:r},i)}),Vd=(0,d.forwardRef)((e,t)=>{let{prefixCls:n,className:r,style:i,iconClassName:a}=e,o=B(`${n}-loading-icon`,r);return d.createElement(Bd,{prefixCls:n,className:o,style:i,ref:t},d.createElement(Xu,{className:a}))}),Hd=()=>({width:0,opacity:0,transform:`scale(0)`}),Ud=e=>({width:e.scrollWidth,opacity:1,transform:`scale(1)`}),Wd=e=>{let{prefixCls:t,loading:n,existIcon:r,className:i,style:a,mount:o}=e,s=!!n;return r?d.createElement(Vd,{prefixCls:t,className:i,style:a}):d.createElement(cc,{visible:s,motionName:`${t}-loading-icon-motion`,motionAppear:!o,motionEnter:!o,motionLeave:!o,removeOnLeave:!0,onAppearStart:Hd,onAppearActive:Ud,onEnterStart:Hd,onEnterActive:Ud,onLeaveStart:Ud,onLeaveActive:Hd},({className:e,style:n},r)=>{let o={...a,...n};return d.createElement(Vd,{prefixCls:t,className:B(i,e),style:o,ref:r})})},Gd=e=>({animationDuration:e,animationFillMode:`both`}),Kd=(e,t,n,r,i=!1)=>{let a=i?`&`:``;return{[` + ${a}${e}-enter, + ${a}${e}-appear + `]:{...Gd(r),animationPlayState:`paused`},[`${a}${e}-leave`]:{...Gd(r),animationPlayState:`paused`},[` + ${a}${e}-enter${e}-enter-active, + ${a}${e}-appear${e}-appear-active + `]:{animationName:t,animationPlayState:`running`},[`${a}${e}-leave${e}-leave-active`]:{animationName:n,animationPlayState:`running`,pointerEvents:`none`}}},qd=new mi(`antFadeIn`,{"0%":{opacity:0},"100%":{opacity:1}}),Jd=new mi(`antFadeOut`,{"0%":{opacity:1},"100%":{opacity:0}}),Yd=(e,t=!1)=>{let{antCls:n}=e,r=`${n}-fade`,i=t?`&`:``;return[Kd(r,qd,Jd,e.motionDurationMid,t),{[` + ${i}${r}-enter, + ${i}${r}-appear + `]:{opacity:0,animationTimingFunction:`linear`},[`${i}${r}-leave`]:{animationTimingFunction:`linear`}}]},Xd=()=>({"@media (prefers-reduced-motion: reduce)":{transition:`none`,animation:`none`}}),Zd=new mi(`antZoomIn`,{"0%":{transform:`scale(0.2)`,opacity:0},"100%":{transform:`scale(1)`,opacity:1}}),Qd=new mi(`antZoomOut`,{"0%":{transform:`scale(1)`},"100%":{transform:`scale(0.2)`,opacity:0}}),$d=new mi(`antZoomBigIn`,{"0%":{transform:`scale(0.8)`,opacity:0},"100%":{transform:`scale(1)`,opacity:1}}),ef=new mi(`antZoomBigOut`,{"0%":{transform:`scale(1)`},"100%":{transform:`scale(0.8)`,opacity:0}}),tf=new mi(`antZoomUpIn`,{"0%":{transform:`scale(0.8)`,transformOrigin:`50% 0%`,opacity:0},"100%":{transform:`scale(1)`,transformOrigin:`50% 0%`}}),nf=new mi(`antZoomUpOut`,{"0%":{transform:`scale(1)`,transformOrigin:`50% 0%`},"100%":{transform:`scale(0.8)`,transformOrigin:`50% 0%`,opacity:0}}),rf=new mi(`antZoomLeftIn`,{"0%":{transform:`scale(0.8)`,transformOrigin:`0% 50%`,opacity:0},"100%":{transform:`scale(1)`,transformOrigin:`0% 50%`}}),af=new mi(`antZoomLeftOut`,{"0%":{transform:`scale(1)`,transformOrigin:`0% 50%`},"100%":{transform:`scale(0.8)`,transformOrigin:`0% 50%`,opacity:0}}),of=new mi(`antZoomRightIn`,{"0%":{transform:`scale(0.8)`,transformOrigin:`100% 50%`,opacity:0},"100%":{transform:`scale(1)`,transformOrigin:`100% 50%`}}),sf=new mi(`antZoomRightOut`,{"0%":{transform:`scale(1)`,transformOrigin:`100% 50%`},"100%":{transform:`scale(0.8)`,transformOrigin:`100% 50%`,opacity:0}}),cf=new mi(`antZoomDownIn`,{"0%":{transform:`scale(0.8)`,transformOrigin:`50% 100%`,opacity:0},"100%":{transform:`scale(1)`,transformOrigin:`50% 100%`}}),lf=new mi(`antZoomDownOut`,{"0%":{transform:`scale(1)`,transformOrigin:`50% 100%`},"100%":{transform:`scale(0.8)`,transformOrigin:`50% 100%`,opacity:0}}),uf={zoom:{inKeyframes:Zd,outKeyframes:Qd},"zoom-big":{inKeyframes:$d,outKeyframes:ef},"zoom-big-fast":{inKeyframes:$d,outKeyframes:ef},"zoom-left":{inKeyframes:rf,outKeyframes:af},"zoom-right":{inKeyframes:of,outKeyframes:sf},"zoom-up":{inKeyframes:tf,outKeyframes:nf},"zoom-down":{inKeyframes:cf,outKeyframes:lf}},df=(e,t)=>{let{antCls:n}=e,r=`${n}-${t}`,{inKeyframes:i,outKeyframes:a}=uf[t];return[Kd(r,i,a,t===`zoom-big-fast`?e.motionDurationFast:e.motionDurationMid),{[` + ${r}-enter, + ${r}-appear + `]:{transform:`scale(0)`,opacity:0,animationTimingFunction:e.motionEaseOutCirc,"&-prepare":{transform:`none`}},[`${r}-leave`]:{animationTimingFunction:e.motionEaseInOutCirc}}]},ff=(e,t)=>({[`> span, > ${e}`]:{"&:not(:last-child)":{[`&, & > ${e}`]:{"&:not(:disabled)":{borderInlineEndColor:t}}},"&:not(:first-child)":{[`&, & > ${e}`]:{"&:not(:disabled)":{borderInlineStartColor:t}}}}}),pf=e=>{let{componentCls:t,fontSize:n,lineWidth:r,groupBorderColor:i,colorErrorHover:a}=e;return{[`${t}-group`]:[{position:`relative`,display:`inline-flex`,[`> span, > ${t}`]:{"&:not(:last-child)":{[`&, & > ${t}`]:{borderStartEndRadius:0,borderEndEndRadius:0}},"&:not(:first-child)":{marginInlineStart:e.calc(r).mul(-1).equal(),[`&, & > ${t}`]:{borderStartStartRadius:0,borderEndStartRadius:0}}},[t]:{position:`relative`,zIndex:1,"&:hover, &:focus, &:active":{zIndex:2},"&[disabled]":{zIndex:0}},[`${t}-icon-only`]:{fontSize:n}},ff(`${t}-primary`,i),ff(`${t}-danger`,a)]}},mf=e=>Math.round(Number(e||0)),hf=e=>{if(e instanceof ma)return e;if(e&&typeof e==`object`&&`h`in e&&`b`in e){let{b:t,...n}=e;return{...n,v:t}}return typeof e==`string`&&/hsb/.test(e)?e.replace(/hsb/,`hsv`):e},gf=class extends ma{constructor(e){super(hf(e))}toHsbString(){let e=this.toHsb(),t=mf(e.s*100),n=mf(e.b*100),r=mf(e.h),i=e.a,a=`hsb(${r}, ${t}%, ${n}%)`,o=`hsba(${r}, ${t}%, ${n}%, ${i.toFixed(i===0?0:2)})`;return i===1?a:o}toHsb(){let{v:e,...t}=this.toHsv();return{...t,b:e,a:this.a}}};(e=>e instanceof gf?e:new gf(e))(`#1677ff`);var _f=(e,t)=>e?.replace(/[^0-9a-f]/gi,``).slice(0,t?8:6)||``,vf=(e,t)=>e?_f(e,t):``,yf=function(){function e(t){if(Ei(this,e),this.cleared=!1,t instanceof e){this.metaColor=t.metaColor.clone(),this.colors=t.colors?.map(t=>({color:new e(t.color),percent:t.percent})),this.cleared=t.cleared;return}let n=Array.isArray(t);n&&t.length?(this.colors=t.map(({color:t,percent:n})=>({color:new e(t),percent:n})),this.metaColor=new gf(this.colors[0].color.metaColor)):this.metaColor=new gf(n?``:t),(!t||n&&!this.colors)&&(this.metaColor=this.metaColor.setA(0),this.cleared=!0)}return W(e,[{key:`toHsb`,value:function(){return this.metaColor.toHsb()}},{key:`toHsbString`,value:function(){return this.metaColor.toHsbString()}},{key:`toHex`,value:function(){return vf(this.toHexString(),this.metaColor.a<1)}},{key:`toHexString`,value:function(){return this.metaColor.toHexString()}},{key:`toRgb`,value:function(){return this.metaColor.toRgb()}},{key:`toRgbString`,value:function(){return this.metaColor.toRgbString()}},{key:`isGradient`,value:function(){return!!this.colors&&!this.cleared}},{key:`getColors`,value:function(){return this.colors||[{color:this,percent:0}]}},{key:`toCssString`,value:function(){let{colors:e}=this;return e?`linear-gradient(90deg, ${e.map(e=>`${e.color.toRgbString()} ${e.percent}%`).join(`, `)})`:this.metaColor.toRgbString()}},{key:`equals`,value:function(e){return!e||this.isGradient()!==e.isGradient()?!1:this.isGradient()?this.colors.length===e.colors.length&&this.colors.every((t,n)=>{let r=e.colors[n];return t.percent===r.percent&&t.color.equals(r.color)}):this.toHexString()===e.toHexString()}}])}(),bf=(e,t)=>{let{r:n,g:r,b:i,a}=e.toRgb(),o=new gf(e.toRgbString()).onBackground(t).toHsv();return a<=.5?o.v>.5:n*.299+r*.587+i*.114>192},xf=e=>{let{paddingInline:t,onlyIconSize:n,borderColorDisabled:r}=e;return Ki(e,{buttonPaddingHorizontal:t,buttonPaddingVertical:0,buttonIconOnlyFontSize:n,colorBorderDisabled:r})},Sf=e=>{let t=e.contentFontSize??e.fontSize,n=e.contentFontSizeSM??e.fontSize,r=e.contentFontSizeLG??e.fontSizeLG,i=e.contentLineHeight??ia(t),a=e.contentLineHeightSM??ia(n),o=e.contentLineHeightLG??ia(r),s=bf(new yf(e.colorBgSolid),`#fff`)?`#000`:`#fff`,c=ra.reduce((t,n)=>({...t,[`${n}ShadowColor`]:`0 ${V(e.controlOutlineWidth)} 0 ${ho(e[`${n}1`],e.colorBgContainer)}`}),{}),l=e.colorBgContainerDisabled,u=e.colorBgContainerDisabled;return{...c,fontWeight:400,iconGap:e.marginXS,defaultShadow:`0 ${e.controlOutlineWidth}px 0 ${e.controlTmpOutline}`,primaryShadow:`0 ${e.controlOutlineWidth}px 0 ${e.controlOutline}`,dangerShadow:`0 ${e.controlOutlineWidth}px 0 ${e.colorErrorOutline}`,primaryColor:e.colorTextLightSolid,dangerColor:e.colorTextLightSolid,borderColorDisabled:e.colorBorderDisabled,defaultGhostColor:e.colorBgContainer,ghostBg:`transparent`,defaultGhostBorderColor:e.colorBgContainer,paddingInline:e.paddingContentHorizontal-e.lineWidth,paddingInlineLG:e.paddingContentHorizontal-e.lineWidth,paddingInlineSM:8-e.lineWidth,onlyIconSize:`inherit`,onlyIconSizeSM:`inherit`,onlyIconSizeLG:`inherit`,groupBorderColor:e.colorPrimaryHover,linkHoverBg:`transparent`,textTextColor:e.colorText,textTextHoverColor:e.colorText,textTextActiveColor:e.colorText,textHoverBg:e.colorFillTertiary,defaultColor:e.colorText,defaultBg:e.colorBgContainer,defaultBorderColor:e.colorBorder,defaultBorderColorDisabled:e.colorBorder,defaultHoverBg:e.colorBgContainer,defaultHoverColor:e.colorPrimaryHover,defaultHoverBorderColor:e.colorPrimaryHover,defaultActiveBg:e.colorBgContainer,defaultActiveColor:e.colorPrimaryActive,defaultActiveBorderColor:e.colorPrimaryActive,solidTextColor:s,contentFontSize:t,contentFontSizeSM:n,contentFontSizeLG:r,contentLineHeight:i,contentLineHeightSM:a,contentLineHeightLG:o,paddingBlock:Math.max((e.controlHeight-t*i)/2-e.lineWidth,0),paddingBlockSM:Math.max((e.controlHeightSM-n*a)/2-e.lineWidth,0),paddingBlockLG:Math.max((e.controlHeightLG-r*o)/2-e.lineWidth,0),defaultBgDisabled:l,dashedBgDisabled:u}},Cf=e=>{let{componentCls:t,antCls:n,lineWidth:r}=e,[i,a]=No(n,`btn`);return{[t]:[{[i(`border-width`)]:r,[i(`border-color`)]:`#000`,[i(`border-color-hover`)]:a(`border-color`),[i(`border-color-active`)]:a(`border-color`),[i(`border-color-disabled`)]:a(`border-color`),[i(`border-style`)]:`solid`,[i(`text-color`)]:`#000`,[i(`text-color-hover`)]:a(`text-color`),[i(`text-color-active`)]:a(`text-color`),[i(`text-color-disabled`)]:a(`text-color`),[i(`bg-color`)]:`#ddd`,[i(`bg-color-hover`)]:a(`bg-color`),[i(`bg-color-active`)]:a(`bg-color`),[i(`bg-color-disabled`)]:e.colorBgContainerDisabled,[i(`bg-color-container`)]:e.colorBgContainer,[i(`shadow`)]:`none`},{border:[a(`border-width`),a(`border-style`),a(`border-color`)].join(` `),color:a(`text-color`),backgroundColor:a(`bg-color`),[`&:not(:disabled):not(${t}-disabled)`]:{"&:hover":{border:[a(`border-width`),a(`border-style`),a(`border-color-hover`)].join(` `),color:a(`text-color-hover`),backgroundColor:a(`bg-color-hover`)},"&:active":{border:[a(`border-width`),a(`border-style`),a(`border-color-active`)].join(` `),color:a(`text-color-active`),backgroundColor:a(`bg-color-active`)}}},{[`&${t}-variant-solid`]:{[i(`solid-bg-color`)]:a(`color-base`),[i(`solid-bg-color-hover`)]:a(`color-hover`),[i(`solid-bg-color-active`)]:a(`color-active`),[i(`border-color`)]:`transparent`,[i(`text-color`)]:e.colorTextLightSolid,[i(`bg-color`)]:a(`solid-bg-color`),[i(`bg-color-hover`)]:a(`solid-bg-color-hover`),[i(`bg-color-active`)]:a(`solid-bg-color-active`),boxShadow:a(`shadow`)},[`&${t}-variant-outlined, &${t}-variant-dashed`]:{[i(`border-color`)]:a(`color-base`),[i(`border-color-hover`)]:a(`color-hover`),[i(`border-color-active`)]:a(`color-active`),[i(`bg-color`)]:a(`bg-color-container`),[i(`text-color`)]:a(`color-base`),[i(`text-color-hover`)]:a(`color-hover`),[i(`text-color-active`)]:a(`color-active`),boxShadow:a(`shadow`)},[`&${t}-variant-dashed`]:{[i(`border-style`)]:`dashed`,[i(`bg-color-disabled`)]:e.dashedBgDisabled},[`&${t}-variant-filled`]:{[i(`border-color`)]:`transparent`,[i(`text-color`)]:a(`color-base`),[i(`bg-color`)]:a(`color-light`),[i(`bg-color-hover`)]:a(`color-light-hover`),[i(`bg-color-active`)]:a(`color-light-active`)},[`&${t}-variant-text, &${t}-variant-link`]:{[i(`border-color`)]:`transparent`,[i(`text-color`)]:a(`color-base`),[i(`text-color-hover`)]:a(`color-hover`),[i(`text-color-active`)]:a(`color-active`),[i(`bg-color`)]:`transparent`,[i(`bg-color-hover`)]:`transparent`,[i(`bg-color-active`)]:`transparent`,[`&:disabled, &${e.componentCls}-disabled`]:{background:`transparent`,borderColor:`transparent`}},[`&${t}-variant-text`]:{[i(`bg-color-hover`)]:a(`color-light`),[i(`bg-color-active`)]:a(`color-light-active`)}},{[`&${t}-variant-link`]:{[i(`color-base`)]:e.colorLink,[i(`color-hover`)]:e.colorLinkHover,[i(`color-active`)]:e.colorLinkActive,[i(`bg-color-hover`)]:e.linkHoverBg},[`&${t}-color-primary`]:{[i(`color-base`)]:e.colorPrimary,[i(`color-hover`)]:e.colorPrimaryHover,[i(`color-active`)]:e.colorPrimaryActive,[i(`color-light`)]:e.colorPrimaryBg,[i(`color-light-hover`)]:e.colorPrimaryBgHover,[i(`color-light-active`)]:e.colorPrimaryBorder,[i(`shadow`)]:e.primaryShadow,[`&${t}-variant-solid`]:{[i(`text-color`)]:e.primaryColor,[i(`text-color-hover`)]:a(`text-color`),[i(`text-color-active`)]:a(`text-color`)}},[`&${t}-color-dangerous`]:{[i(`color-base`)]:e.colorError,[i(`color-hover`)]:e.colorErrorHover,[i(`color-active`)]:e.colorErrorActive,[i(`color-light`)]:e.colorErrorBg,[i(`color-light-hover`)]:e.colorErrorBgFilledHover,[i(`color-light-active`)]:e.colorErrorBgActive,[i(`shadow`)]:e.dangerShadow,[`&${t}-variant-solid`]:{[i(`text-color`)]:e.dangerColor,[i(`text-color-hover`)]:a(`text-color`),[i(`text-color-active`)]:a(`text-color`)}},[`&${t}-color-default`]:{[i(`solid-bg-color`)]:e.colorBgSolid,[i(`solid-bg-color-hover`)]:e.colorBgSolidHover,[i(`solid-bg-color-active`)]:e.colorBgSolidActive,[i(`color-base`)]:e.defaultBorderColor,[i(`color-hover`)]:e.defaultHoverBorderColor,[i(`color-active`)]:e.defaultActiveBorderColor,[i(`color-light`)]:e.colorFillTertiary,[i(`color-light-hover`)]:e.colorFillSecondary,[i(`color-light-active`)]:e.colorFill,[i(`text-color`)]:e.defaultColor,[i(`text-color-hover`)]:e.defaultHoverColor,[i(`text-color-active`)]:e.defaultActiveColor,[i(`shadow`)]:e.defaultShadow,[`&${t}-variant-outlined`]:{[i(`bg-color-disabled`)]:e.defaultBgDisabled},[`&${t}-variant-solid`]:{[i(`text-color`)]:e.solidTextColor,[i(`text-color-hover`)]:a(`text-color`),[i(`text-color-active`)]:a(`text-color`)},[`&${t}-variant-filled, &${t}-variant-text`]:{[i(`text-color-hover`)]:a(`text-color`),[i(`text-color-active`)]:a(`text-color`)},[`&${t}-variant-outlined, &${t}-variant-dashed`]:{[i(`text-color`)]:e.defaultColor,[i(`text-color-hover`)]:e.defaultHoverColor,[i(`text-color-active`)]:e.defaultActiveColor,[i(`bg-color-container`)]:e.defaultBg,[i(`bg-color-hover`)]:e.defaultHoverBg,[i(`bg-color-active`)]:e.defaultActiveBg},[`&${t}-variant-text`]:{[i(`text-color`)]:e.textTextColor,[i(`text-color-hover`)]:e.textTextHoverColor,[i(`text-color-active`)]:e.textTextActiveColor,[i(`bg-color-hover`)]:e.textHoverBg},[`&${t}-background-ghost`]:{[`&${t}-variant-outlined, &${t}-variant-dashed`]:{[i(`text-color`)]:e.defaultGhostColor,[i(`border-color`)]:e.defaultGhostBorderColor}}}},ra.map(n=>{let r=e[`${n}6`],a=e[`${n}1`],o=e[`${n}Hover`],s=e[`${n}2`],c=e[`${n}3`],l=e[`${n}Active`],u=e[`${n}ShadowColor`];return{[`&${t}-color-${n}`]:{[i(`color-base`)]:r,[i(`color-hover`)]:o,[i(`color-active`)]:l,[i(`color-light`)]:a,[i(`color-light-hover`)]:s,[i(`color-light-active`)]:c,[i(`shadow`)]:u}}}),{[`&:disabled, &${e.componentCls}-disabled`]:{cursor:`not-allowed`,borderColor:e.colorBorderDisabled,background:a(`bg-color-disabled`),color:e.colorTextDisabled,boxShadow:`none`}},{[`&${t}-background-ghost`]:{[i(`bg-color`)]:e.ghostBg,[i(`bg-color-hover`)]:e.ghostBg,[i(`bg-color-active`)]:e.ghostBg,[i(`shadow`)]:`none`,[`&${t}-variant-outlined, &${t}-variant-dashed`]:{[i(`bg-color-hover`)]:e.ghostBg,[i(`bg-color-active`)]:e.ghostBg}}}]}},wf=e=>{let{componentCls:t,iconCls:n,fontWeight:r,opacityLoading:i,motionDurationSlow:a,motionEaseInOut:o,iconGap:s,calc:c}=e;return{[t]:{outline:`none`,position:`relative`,display:`inline-flex`,gap:s,alignItems:`center`,justifyContent:`center`,fontWeight:r,whiteSpace:`nowrap`,textAlign:`center`,backgroundImage:`none`,cursor:`pointer`,transition:`all ${e.motionDurationMid} ${e.motionEaseInOut}`,userSelect:`none`,touchAction:`manipulation`,...Xd(),"&:disabled > *":{pointerEvents:`none`},[`${t}-icon > svg`]:Co(),"> a":{color:`currentColor`},"&:not(:disabled)":Eo(e),[`&${t}-two-chinese-chars::first-letter`]:{letterSpacing:`0.34em`},[`&${t}-two-chinese-chars > *:not(${n})`]:{marginInlineEnd:`-0.34em`,letterSpacing:`0.34em`},[`&${t}-icon-only`]:{paddingInline:0,[`&${t}-compact-item`]:{flex:`none`}},[`&${t}-loading`]:{opacity:i,cursor:`default`},[`${t}-loading-icon`]:{transition:[`width`,`opacity`,`margin`].map(e=>`${e} ${a} ${o}`).join(`,`)},[`&:not(${t}-icon-end)`]:{[`${t}-loading-icon-motion`]:{"&-appear-start, &-enter-start":{marginInlineEnd:c(s).mul(-1).equal()},"&-appear-active, &-enter-active":{marginInlineEnd:0},"&-leave-start":{marginInlineEnd:0},"&-leave-active":{marginInlineEnd:c(s).mul(-1).equal()}}},"&-icon-end":{flexDirection:`row-reverse`,[`${t}-loading-icon-motion`]:{"&-appear-start, &-enter-start":{marginInlineStart:c(s).mul(-1).equal()},"&-appear-active, &-enter-active":{marginInlineStart:0},"&-leave-start":{marginInlineStart:0},"&-leave-active":{marginInlineStart:c(s).mul(-1).equal()}}}}}},Tf=e=>({minWidth:e.controlHeight,paddingInline:0,borderRadius:`50%`}),Ef=(e,t=``)=>{let{componentCls:n,controlHeight:r,fontSize:i,borderRadius:a,buttonPaddingHorizontal:o,iconCls:s,buttonPaddingVertical:c,buttonIconOnlyFontSize:l}=e;return[{[t]:{fontSize:i,height:r,padding:`${V(c)} ${V(o)}`,borderRadius:a,[`&${n}-icon-only`]:{width:r,[s]:{fontSize:l}}}},{[`${n}${n}-circle${t}`]:Tf(e)},{[`${n}${n}-round${t}`]:{borderRadius:e.controlHeight,[`&:not(${n}-icon-only)`]:{paddingInline:e.buttonPaddingHorizontal}}}]},Df=e=>Ef(Ki(e,{fontSize:e.contentFontSize}),e.componentCls),Of=e=>Ef(Ki(e,{controlHeight:e.controlHeightSM,fontSize:e.contentFontSizeSM,padding:e.paddingXS,buttonPaddingHorizontal:e.paddingInlineSM,buttonPaddingVertical:0,borderRadius:e.borderRadiusSM,buttonIconOnlyFontSize:e.onlyIconSizeSM}),`${e.componentCls}-sm`),kf=e=>Ef(Ki(e,{controlHeight:e.controlHeightLG,fontSize:e.contentFontSizeLG,buttonPaddingHorizontal:e.paddingInlineLG,buttonPaddingVertical:0,borderRadius:e.borderRadiusLG,buttonIconOnlyFontSize:e.onlyIconSizeLG}),`${e.componentCls}-lg`),Af=e=>{let{componentCls:t}=e;return{[t]:{[`&${t}-block`]:{width:`100%`}}}},jf=Ao(`Button`,e=>{let t=xf(e);return[wf(t),Df(t),Of(t),kf(t),Af(t),Cf(t),pf(t)]},Sf,{unitless:{fontWeight:!0,contentLineHeight:!0,contentLineHeightSM:!0,contentLineHeightLG:!0}});function Mf(e,t,n,r){let{focusElCls:i,focus:a,borderElCls:o}=n,s=o?`> *`:``,c=[`hover`,a?`focus`:null,`active`].filter(Boolean).map(e=>`&:${e} ${s}`).join(`,`);return{[`&-item:not(${t}-last-item)`]:{marginInlineEnd:e.calc(e.lineWidth).mul(-1).equal()},[`&-item:not(${r}-status-success)`]:{zIndex:2},"&-item":{[c]:{zIndex:3},...i?{[`&${i}`]:{zIndex:3}}:{},[`&[disabled] ${s}`]:{zIndex:0}}}}function Nf(e,t,n){let{borderElCls:r}=n,i=r?`> ${r}`:``;return{[`&-item:not(${t}-first-item):not(${t}-last-item) ${i}`]:{borderRadius:0},[`&-item:not(${t}-last-item)${t}-first-item`]:{[`& ${i}, &${e}-sm ${i}, &${e}-lg ${i}`]:{borderStartEndRadius:0,borderEndEndRadius:0}},[`&-item:not(${t}-first-item)${t}-last-item`]:{[`& ${i}, &${e}-sm ${i}, &${e}-lg ${i}`]:{borderStartStartRadius:0,borderEndStartRadius:0}}}}function Pf(e,t={focus:!0}){let{componentCls:n}=e,{componentCls:r}=t,i=r||n,a=`${i}-compact`;return{[a]:{...Mf(e,a,t,i),...Nf(i,a,t)}}}function Ff(e,t,n){return{[`&-item:not(${t}-last-item)`]:{marginBottom:e.calc(e.lineWidth).mul(-1).equal()},[`&-item:not(${n}-status-success)`]:{zIndex:2},"&-item":{"&:hover,&:focus,&:active":{zIndex:3},"&[disabled]":{zIndex:0}}}}function If(e,t){return{[`&-item:not(${t}-first-item):not(${t}-last-item)`]:{borderRadius:0},[`&-item${t}-first-item:not(${t}-last-item)`]:{[`&, &${e}-sm, &${e}-lg`]:{borderEndEndRadius:0,borderEndStartRadius:0}},[`&-item${t}-last-item:not(${t}-first-item)`]:{[`&, &${e}-sm, &${e}-lg`]:{borderStartStartRadius:0,borderStartEndRadius:0}}}}function Lf(e){let t=`${e.componentCls}-compact-vertical`;return{[t]:{...Ff(e,t,e.componentCls),...If(e.componentCls,t)}}}var Rf=e=>{let{antCls:t,componentCls:n,lineWidth:r,calc:i,colorBgContainer:a}=e,o=`${n}-variant-solid:not([disabled])`,s=i(r).mul(-1).equal(),[c,l]=No(t,`btn`),u=e=>({[`${n}-compact${e?`-vertical`:``}-item`]:{[c(`compact-connect-border-color`)]:l(`bg-color-hover`),[`&${o}`]:{transition:`none`,[`& + ${o}:before`]:[{position:`absolute`,backgroundColor:l(`compact-connect-border-color`),content:`""`},e?{top:s,insetInline:s,height:r}:{insetBlock:s,insetInlineStart:s,width:r}],"&:hover:before":{display:`none`}}}});return[u(),u(!0),{[`${o}${n}-color-default`]:{[c(`compact-connect-border-color`)]:`color-mix(in srgb, ${l(`bg-color-hover`)} 75%, ${a})`}}]},zf=Mo([`Button`,`compact`],e=>{let t=xf(e);return[Pf(t),Lf(t),Rf(t)]},Sf);function Bf(e){if(typeof e==`object`&&e){let t=e?.delay;return t=!Number.isNaN(t)&&typeof t==`number`?t:0,{loading:t<=0,delay:t}}return{loading:!!e,delay:0}}var Vf={default:[`default`,`outlined`],primary:[`primary`,`solid`],dashed:[`default`,`dashed`],link:[`link`,`link`],text:[`default`,`text`]},Hf=d.forwardRef((e,t)=>{let{_skipSemantic:n,loading:r=!1,prefixCls:i,color:a,variant:o,type:s,danger:c=!1,shape:l,size:u,disabled:f,className:p,rootClassName:m,children:h,icon:g,iconPosition:_,iconPlacement:v,ghost:y=!1,block:b=!1,htmlType:x=`button`,classNames:S,styles:C,style:w,autoInsertSpace:T,autoFocus:E,...D}=e,O=it(h),k=s||`default`,{getPrefixCls:A,direction:j,autoInsertSpace:ee,className:te,style:M,classNames:N,styles:P,loadingIcon:ne,shape:re,color:F,variant:ie}=Ht(`button`),I=l||re||`default`,[ae,oe]=(0,d.useMemo)(()=>{if(a&&o)return[a,o];if(s||c){let e=Vf[k]||[];return c?[`danger`,e[1]]:e}return F&&ie?[F,ie]:[`default`,`outlined`]},[a,o,s,c,F,ie,k]),[se,ce]=(0,d.useMemo)(()=>y&&oe===`solid`?[ae,`outlined`]:[ae,oe],[ae,oe,y]),le=se===`danger`,ue=le?`dangerous`:se,de=T??ee??!0,L=A(`btn`,i),[fe,pe]=jf(L),me=(0,d.useContext)(yu),he=f??me,ge=(0,d.useContext)(jd),_e=(0,d.useMemo)(()=>Bf(r),[r]),[ve,ye]=(0,d.useState)(_e.loading),[be,xe]=(0,d.useState)(!1),R=(0,d.useRef)(null),Se=Fe(t,R),Ce=O.length===1&&!g&&!Ld(ce),we=(0,d.useRef)(!0);d.useEffect(()=>(we.current=!1,()=>{we.current=!0}),[]),z(()=>{let e=null;_e.delay>0?e=setTimeout(()=>{e=null,ye(!0)},_e.delay):ye(_e.loading);function t(){e&&=(clearTimeout(e),null)}return t},[_e.delay,_e.loading]),(0,d.useEffect)(()=>{if(!R.current||!de)return;let e=R.current.textContent||``;Ce&&Pd(e)?be||xe(!0):be&&xe(!1)}),(0,d.useEffect)(()=>{E&&R.current&&R.current.focus()},[]);let Te=d.useCallback(t=>{if(ve||he){t.preventDefault();return}e.onClick?.((`href`in e,t))},[e.onClick,ve,he]),{compactSize:Ee,compactItemClassnames:De}=kd(L,j),Oe=Dd(e=>u??Ee??ge??e),ke=ve?`loading`:g,Ae=v??_??`start`,je=rt(D,[`navigate`]),Me={...e,type:k,color:se,variant:ce,danger:le,shape:I,size:Oe,disabled:he,loading:ve,iconPlacement:Ae},[Ne,Pe]=el([n?void 0:N,S],[n?void 0:P,C],{props:Me}),Ie=B(L,fe,pe,{[`${L}-${I}`]:I!==`default`&&I!==`square`&&I,[`${L}-${k}`]:k,[`${L}-dangerous`]:c,[`${L}-color-${ue}`]:ue,[`${L}-variant-${ce}`]:ce,[`${L}-lg`]:Oe===`large`,[`${L}-sm`]:Oe===`small`,[`${L}-icon-only`]:!h&&h!==0&&!!ke,[`${L}-background-ghost`]:y&&!Ld(ce),[`${L}-loading`]:ve,[`${L}-two-chinese-chars`]:be&&de&&!ve,[`${L}-block`]:b,[`${L}-rtl`]:j===`rtl`,[`${L}-icon-end`]:Ae===`end`},De,p,m,te,Ne.root),Le={...Pe.root,...M,...w},Re={className:Ne.icon,style:Pe.icon},ze=e=>d.createElement(Bd,{prefixCls:L,...Re},e),Be=d.createElement(Wd,{existIcon:!!g,prefixCls:L,loading:ve,mount:we.current,...Re}),Ve=r&&typeof r==`object`&&r.icon||ne,He;He=g&&!ve?ze(g):r&&Ve?ze(Ve):Be;let Ue=Rc(h)?zd(h,Ce&&de,Pe.content,Ne.content):null;if(je.href!==void 0)return d.createElement(`a`,{...je,className:B(Ie,{[`${L}-disabled`]:he}),href:he?void 0:je.href,style:Le,onClick:Te,ref:Se,tabIndex:he?-1:0,"aria-disabled":he},He,Ue);let We=d.createElement(`button`,{...D,type:x,className:Ie,style:Le,onClick:Te,disabled:he,ref:Se},He,Ue,De&&d.createElement(zf,{prefixCls:L}));return Ld(ce)||(We=d.createElement(Ed,{component:`Button`,disabled:ve},We)),We});Hf.Group=Md,Hf.__ANT_BUTTON=!0;var Uf=e=>typeof e?.then==`function`,Wf=e=>{let{type:t,children:n,prefixCls:r,buttonProps:i,close:a,autoFocus:o,emitEvent:s,isSilent:c,quitOnNullishReturnValue:l,actionFn:u}=e,f=d.useRef(!1),p=d.useRef(null),[m,h]=Ce(!1),g=(...e)=>{a?.(...e)};d.useEffect(()=>{let e=null;return o&&(e=setTimeout(()=>{p.current?.focus({preventScroll:!0})})),()=>{e&&clearTimeout(e)}},[o]);let _=e=>{Uf(e)&&(h(!0),e.then((...e)=>{h(!1,!0),g.apply(void 0,e),f.current=!1},e=>{if(h(!1,!0),f.current=!1,!c?.())return Promise.reject(e)}))},v=e=>{if(f.current)return;if(f.current=!0,!u){g();return}let t;if(s){if(t=u(e),l&&!Uf(t)){f.current=!1,g(e);return}}else if(u.length)t=u(a),f.current=!1;else if(t=u(),!Uf(t)){g();return}_(t)};return d.createElement(Hf,{...Fd(t),onClick:v,loading:m,prefixCls:r,...i,ref:p},n)},Gf=d.createContext({}),{Provider:Kf}=Gf,qf=()=>{let{autoFocusButton:e,cancelButtonProps:t,cancelTextLocale:n,isSilent:r,mergedOkCancel:i,rootPrefixCls:a,close:o,onCancel:s,onConfirm:c,onClose:l}=(0,d.useContext)(Gf);return i?d.createElement(Wf,{isSilent:r,actionFn:s,close:(...e)=>{o?.(...e),c?.(!1),l?.()},autoFocus:e===`cancel`,buttonProps:t,prefixCls:`${a}-btn`},n):null},Jf=()=>{let{autoFocusButton:e,close:t,isSilent:n,okButtonProps:r,rootPrefixCls:i,okTextLocale:a,okType:o,onConfirm:s,onOk:c,onClose:l}=(0,d.useContext)(Gf);return d.createElement(Wf,{isSilent:n,type:o||`primary`,actionFn:c,close:(...e)=>{t?.(...e),s?.(!0),l?.()},autoFocus:e===`ok`,buttonProps:r,prefixCls:`${i}-btn`},a)},Yf=d.createContext({});function Xf(e,t,n){let r=t;return!r&&n&&(r=`${e}-${n}`),r}function Zf(e,t){let n=e[`page${t?`Y`:`X`}Offset`],r=`scroll${t?`Top`:`Left`}`;if(typeof n!=`number`){let t=e.document;n=t.documentElement[r],typeof n!=`number`&&(n=t.body[r])}return n}function Qf(e){let t=e.getBoundingClientRect(),n={left:t.left,top:t.top},r=e.ownerDocument,i=r.defaultView||r.parentWindow;return n.left+=Zf(i),n.top+=Zf(i,!0),n}function $f(e,t=!1){if(Kl(e)){let n=e.nodeName.toLowerCase(),r=[`input`,`select`,`textarea`,`button`].includes(n)||e.isContentEditable||n===`a`&&!!e.getAttribute(`href`),i=e.getAttribute(`tabindex`),a=Number(i),o=null;return i&&!Number.isNaN(a)?o=a:r&&o===null&&(o=0),r&&e.disabled&&(o=null),o!==null&&(o>=0||t&&o<0)}return!1}function ep(e,t=!1){let n=[...e.querySelectorAll(`*`)].filter(e=>$f(e,t));return $f(e,t)&&n.unshift(e),n}var tp=null,np=[],rp=new Map,ip=new Map;function ap(){return np[np.length-1]}function op(e){let t=ap();if(e&&t){let n;for(let[e,r]of rp.entries())if(r===t){n=e;break}let r=ip.get(n);return!!r&&(r===e||r.contains(e))}return!1}function sp(e){let{activeElement:t}=document;return e===t||e.contains(t)}function cp(){let e=ap(),{activeElement:t}=document;if(!op(t))if(e&&!sp(e)){let t=ep(e);(t.includes(tp)?tp:t[0])?.focus({preventScroll:!0})}else tp=t}function lp(e){if(e.key===`Tab`){let{activeElement:t}=document,n=ep(ap()),r=n[n.length-1];e.shiftKey&&t===n[0]?tp=r:!e.shiftKey&&t===r&&(tp=n[0])}}function up(e,t){return e&&(rp.set(t,e),np=np.filter(t=>t!==e),np.push(e),window.addEventListener(`focusin`,cp),window.addEventListener(`keydown`,lp,!0),cp()),()=>{tp=null,np=np.filter(t=>t!==e),rp.delete(t),ip.delete(t),np.length===0&&(window.removeEventListener(`focusin`,cp),window.removeEventListener(`keydown`,lp,!0))}}function dp(e,t){let n=Dl();return(0,d.useEffect)(()=>{if(e){let e=t();if(e)return up(e,n)}},[e,n]),[e=>{e&&ip.set(n,e)}]}var fp=d.memo(({children:e})=>e,(e,{shouldUpdate:t})=>!t);function pp(){return pp=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{prefixCls:n,className:r,style:i,title:a,ariaId:o,footer:s,closable:c,closeIcon:l,onClose:u,children:f,bodyStyle:p,bodyProps:m,modalRender:h,onMouseDown:g,onMouseUp:_,holderRef:v,visible:y,forceRender:b,width:x,height:S,classNames:C,styles:w,isFixedPos:T,focusTrap:E}=e,{panel:D}=d.useContext(Yf),O=(0,d.useRef)(null),k=Fe(v,D,O),[A]=dp(y&&T&&E!==!1,()=>O.current);d.useImperativeHandle(t,()=>({focus:()=>{O.current?.focus({preventScroll:!0})}}));let j={};x!==void 0&&(j.width=x),S!==void 0&&(j.height=S);let ee=s?d.createElement(`div`,{className:B(`${n}-footer`,C?.footer),style:{...w?.footer}},s):null,te=a?d.createElement(`div`,{className:B(`${n}-header`,C?.header),style:{...w?.header}},d.createElement(`div`,{className:B(`${n}-title`,C?.title),id:o,style:{...w?.title}},a)):null,M=(0,d.useMemo)(()=>typeof c==`object`&&c?c:c?{closeIcon:l??d.createElement(`span`,{className:`${n}-close-x`})}:{},[c,l,n]),N=pc(M,!0),P=typeof c==`object`&&c.disabled,ne=c?d.createElement(`button`,pp({type:`button`,onClick:u,"aria-label":`Close`},N,{className:`${n}-close`,disabled:P}),M.closeIcon):null,re=d.createElement(`div`,{className:B(`${n}-container`,C?.container),style:w?.container},ne,te,d.createElement(`div`,pp({className:B(`${n}-body`,C?.body),style:{...p,...w?.body}},m),f),ee);return d.createElement(`div`,{key:`dialog-element`,role:`dialog`,"aria-labelledby":a?o:null,"aria-modal":`true`,ref:k,style:{...i,...j},className:B(n,r),onMouseDown:g,onMouseUp:_,tabIndex:-1,onFocus:e=>{A(e.target)}},d.createElement(fp,{shouldUpdate:y||b},h?h(re):re))});function hp(){return hp=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{prefixCls:n,title:r,style:i,className:a,visible:o,forceRender:s,destroyOnHidden:c,motionName:l,ariaId:u,onVisibleChanged:f,mousePosition:p}=e,m=(0,d.useRef)(null),h=(0,d.useRef)(null);d.useImperativeHandle(t,()=>({...h.current,inMotion:m.current.inMotion,enableMotion:m.current.enableMotion}));let[g,_]=d.useState(),v={};g&&(v.transformOrigin=g);function y(){if(!m.current?.nativeElement)return;let e=Qf(m.current.nativeElement);_(p&&(p.x||p.y)?`${p.x-e.left}px ${p.y-e.top}px`:``)}return d.createElement(cc,{visible:o,onVisibleChanged:f,onAppearPrepare:y,onEnterPrepare:y,forceRender:s,motionName:l,removeOnLeave:c,ref:m},({className:t,style:o},s)=>d.createElement(mp,hp({},e,{ref:h,title:r,ariaId:u,prefixCls:n,holderRef:s,style:{...o,...i,...v},className:B(a,t)})))});function _p(){return _p=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{prefixCls:t,style:n,visible:r,maskProps:i,motionName:a,className:o}=e;return d.createElement(cc,{key:`mask`,visible:r,motionName:a,leavedClassName:`${t}-mask-hidden`},({className:e,style:r},a)=>d.createElement(`div`,_p({ref:a,style:{...r,...n},className:B(`${t}-mask`,e,o)},i)))};function yp(){return yp=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{prefixCls:t=`rc-dialog`,zIndex:n,visible:r=!1,focusTriggerAfterClose:i=!0,wrapStyle:a,wrapClassName:o,wrapProps:s,onClose:c,afterOpenChange:l,afterClose:u,transitionName:f,animation:p,closable:m=!0,mask:h=!0,maskTransitionName:g,maskAnimation:_,maskClosable:v=!0,maskStyle:y,maskProps:b,rootClassName:x,rootStyle:S,classNames:C,styles:w}=e,T=(0,d.useRef)(null),E=(0,d.useRef)(null),D=(0,d.useRef)(null),[O,k]=d.useState(r),[A,j]=d.useState(!1),ee=Dl();function te(){Wt(E.current,document.activeElement)||(T.current=document.activeElement)}function M(){Wt(E.current,document.activeElement)||D.current?.focus()}function N(){if(k(!1),h&&T.current&&i){try{T.current.focus({preventScroll:!0})}catch{}T.current=null}O&&u?.()}function P(e){e?M():N(),l?.(e)}function ne(e){c?.(e)}let re=(0,d.useRef)(!1),F=null;v&&(F=e=>{E.current===e.target&&re.current&&ne(e)});function ie(e){re.current=e.target===E.current}(0,d.useEffect)(()=>{r?(re.current=!1,k(!0),te(),E.current&&j(getComputedStyle(E.current).position===`fixed`)):O&&D.current.enableMotion()&&!D.current.inMotion()&&N()},[r]);let I={zIndex:n,...a,...w?.wrapper,display:O?null:`none`};return d.createElement(`div`,yp({className:B(`${t}-root`,x),style:S},pc(e,{data:!0})),d.createElement(vp,{prefixCls:t,visible:h&&r,motionName:Xf(t,g,_),style:{zIndex:n,...y,...w?.mask},maskProps:b,className:C?.mask}),d.createElement(`div`,yp({className:B(`${t}-wrap`,o,C?.wrapper),ref:E,onClick:F,onMouseDown:ie,style:I},s),d.createElement(gp,yp({},e,{isFixedPos:A,ref:D,closable:m,ariaId:ee,prefixCls:t,visible:r&&O,onClose:ne,onVisibleChanged:P,motionName:Xf(t,f,p)}))))};function xp(){return xp=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{visible:t,getContainer:n,forceRender:r,destroyOnHidden:i=!1,afterClose:a,closable:o,panelRef:s,keyboard:c=!0,onClose:l}=e,[u,f]=d.useState(t),p=d.useMemo(()=>({panel:s}),[s]);return d.useEffect(()=>{t&&f(!0)},[t]),!r&&i&&!u?null:d.createElement(Yf.Provider,{value:p},d.createElement(Rl,{open:t||r||u,onEsc:({top:e,event:t})=>{if(e&&c){t.stopPropagation(),l?.(t);return}},autoDestroy:!1,getContainer:n,autoLock:t||u},d.createElement(bp,xp({},e,{destroyOnHidden:i,afterClose:()=>{let{afterClose:e}=(o&&typeof o==`object`?o:{})||{};e?.(),a?.(),f(!1)}}))))},Cp=`RC_FORM_INTERNAL_HOOKS`,Z=()=>{tt(!1,`Can not find FormContext. Please make sure you wrap Field under Form.`)},wp=d.createContext({getFieldValue:Z,getFieldsValue:Z,getFieldError:Z,getFieldWarning:Z,getFieldsError:Z,isFieldsTouched:Z,isFieldTouched:Z,isFieldValidating:Z,isFieldsValidating:Z,resetFields:Z,setFields:Z,setFieldValue:Z,setFieldsValue:Z,validateFields:Z,submit:Z,getInternalHooks:()=>(Z(),{dispatch:Z,initEntityValue:Z,registerField:Z,useSubscribe:Z,setInitialValues:Z,destroyForm:Z,setCallbacks:Z,registerWatch:Z,getFields:Z,setValidateMessages:Z,setPreserve:Z,getInitialValue:Z})}),Tp=d.createContext(null);function Ep(e){return e==null?[]:Array.isArray(e)?e:[e]}function Dp(e){return e&&!!e._init}function Op(){return{default:`Validation error on field %s`,required:`%s is required`,enum:`%s must be one of %s`,whitespace:`%s cannot be empty`,date:{format:`%s date %s is invalid for format %s`,parse:`%s date could not be parsed, %s is invalid `,invalid:`%s date %s is invalid`},types:{string:`%s is not a %s`,method:`%s is not a %s (function)`,array:`%s is not an %s`,object:`%s is not an %s`,number:`%s is not a %s`,date:`%s is not a %s`,boolean:`%s is not a %s`,integer:`%s is not an %s`,float:`%s is not a %s`,regexp:`%s is not a valid %s`,email:`%s is not a valid %s`,tel:`%s is not a valid %s`,url:`%s is not a valid %s`,hex:`%s is not a valid %s`},string:{len:`%s must be exactly %s characters`,min:`%s must be at least %s characters`,max:`%s cannot be longer than %s characters`,range:`%s must be between %s and %s characters`},number:{len:`%s must equal %s`,min:`%s cannot be less than %s`,max:`%s cannot be greater than %s`,range:`%s must be between %s and %s`},array:{len:`%s must be exactly %s in length`,min:`%s cannot be less than %s in length`,max:`%s cannot be greater than %s in length`,range:`%s must be between %s and %s in length`},pattern:{mismatch:`%s value %s does not match pattern %s`},clone:function(){var e=JSON.parse(JSON.stringify(this));return e.clone=this.clone,e}}}var kp=Op();function Ap(e){try{return Function.toString.call(e).indexOf(`[native code]`)!==-1}catch{return typeof e==`function`}}function jp(e,t,n){if(Mi())return Reflect.construct.apply(null,arguments);var r=[null];r.push.apply(r,t);var i=new(e.bind.apply(e,r));return n&&ki(i,n.prototype),i}function Mp(e){var t=typeof Map==`function`?new Map:void 0;return Mp=function(e){if(e===null||!Ap(e))return e;if(typeof e!=`function`)throw TypeError(`Super expression must either be null or a function`);if(t!==void 0){if(t.has(e))return t.get(e);t.set(e,n)}function n(){return jp(e,arguments,ji(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),ki(n,e)},Mp(e)}var Np=/%[sdj%]/g,Pp=function(){};function Fp(e){if(!e||!e.length)return null;var t={};return e.forEach(function(e){var n=e.field;t[n]=t[n]||[],t[n].push(e)}),t}function Ip(e){var t=[...arguments].slice(1),n=0,r=t.length;return typeof e==`function`?e.apply(null,t):typeof e==`string`?e.replace(Np,function(e){if(e===`%%`)return`%`;if(n>=r)return e;switch(e){case`%s`:return String(t[n++]);case`%d`:return Number(t[n++]);case`%j`:try{return JSON.stringify(t[n++])}catch{return`[Circular]`}break;default:return e}}):e}function Lp(e){return e===`string`||e===`url`||e===`hex`||e===`email`||e===`date`||e===`pattern`||e===`tel`}function Rp(e,t){return!!(e==null||t===`array`&&Array.isArray(e)&&!e.length||Lp(t)&&typeof e==`string`&&!e)}function zp(e,t,n){var r=[],i=0,a=e.length;function o(e){r.push.apply(r,Mt(e||[])),i++,i===a&&n(r)}e.forEach(function(e){t(e,o)})}function Bp(e,t,n){var r=0,i=e.length;function a(o){if(o&&o.length){n(o);return}var s=r;r+=1,se.max?r.push(Ip(i.messages[u].max,e.fullField,e.max)):o&&s&&(le.max)&&r.push(Ip(i.messages[u].range,e.fullField,e.min,e.max))},Qp=function(e,t,n,r,i,a){e.required&&(!n.hasOwnProperty(e.field)||Rp(t,a||e.type))&&r.push(Ip(i.messages.required,e.fullField))},$p,em=(function(){if($p)return $p;var e=`[a-fA-F\\d:]`,t=function(t){return t&&t.includeBoundaries?`(?:(?<=\\s|^)(?=${e})|(?<=${e})(?=\\s|\$))`:``},n=`(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}`,r=`[a-fA-F\\d]{1,4}`,i=`(?:${[`(?:${r}:){7}(?:${r}|:)`,`(?:${r}:){6}(?:${n}|:${r}|:)`,`(?:${r}:){5}(?::${n}|(?::${r}){1,2}|:)`,`(?:${r}:){4}(?:(?::${r}){0,1}:${n}|(?::${r}){1,3}|:)`,`(?:${r}:){3}(?:(?::${r}){0,2}:${n}|(?::${r}){1,4}|:)`,`(?:${r}:){2}(?:(?::${r}){0,3}:${n}|(?::${r}){1,5}|:)`,`(?:${r}:){1}(?:(?::${r}){0,4}:${n}|(?::${r}){1,6}|:)`,`(?::(?:(?::${r}){0,5}:${n}|(?::${r}){1,7}|:))`].join(`|`)})(?:%[0-9a-zA-Z]{1,})?`,a=RegExp(`(?:^${n}\$)|(?:^${i}\$)`),o=RegExp(`^${n}\$`),s=RegExp(`^${i}\$`),c=function(e){return e&&e.exact?a:RegExp(`(?:${t(e)}${n}${t(e)})|(?:${t(e)}${i}${t(e)})`,`g`)};c.v4=function(e){return e&&e.exact?o:RegExp(`${t(e)}${n}${t(e)}`,`g`)},c.v6=function(e){return e&&e.exact?s:RegExp(`${t(e)}${i}${t(e)}`,`g`)};var l=`(?:(?:(?:[a-z]+:)?//)|www\\.)(?:\\S+(?::\\S*)?@)?(?:localhost|${c.v4().source}|${c.v6().source}|(?:(?:[a-z\\u00a1-\\uffff0-9][-_]*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:[/?#][^\\s"]*)?`;return $p=RegExp(`(?:^${l}\$)`,`i`),$p}),tm={email:/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+\.)+[a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]{2,}))$/,tel:/^(\+[0-9]{1,3}[-\s\u2011]?)?(\([0-9]{1,4}\)[-\s\u2011]?)?([0-9]+[-\s\u2011]?)*[0-9]+$/,hex:/^#?([a-f0-9]{6}|[a-f0-9]{3})$/i},nm={integer:function(e){return nm.number(e)&&parseInt(e,10)===e},float:function(e){return nm.number(e)&&!nm.integer(e)},array:function(e){return Array.isArray(e)},regexp:function(e){if(e instanceof RegExp)return!0;try{return!!new RegExp(e)}catch{return!1}},date:function(e){return typeof e.getTime==`function`&&typeof e.getMonth==`function`&&typeof e.getYear==`function`&&!isNaN(e.getTime())},number:function(e){return isNaN(e)?!1:typeof e==`number`},object:function(e){return gi(e)===`object`&&!nm.array(e)},method:function(e){return typeof e==`function`},email:function(e){return typeof e==`string`&&e.length<=320&&!!e.match(tm.email)},tel:function(e){return typeof e==`string`&&e.length<=32&&!!e.match(tm.tel)},url:function(e){return typeof e==`string`&&e.length<=2048&&!!e.match(em())},hex:function(e){return typeof e==`string`&&!!e.match(tm.hex)}},Q={required:Qp,whitespace:function(e,t,n,r,i){(/^\s+$/.test(t)||t===``)&&r.push(Ip(i.messages.whitespace,e.fullField))},type:function(e,t,n,r,i){if(e.required&&t===void 0){Qp(e,t,n,r,i);return}var a=[`integer`,`float`,`array`,`regexp`,`object`,`method`,`email`,`tel`,`number`,`date`,`url`,`hex`],o=e.type;a.indexOf(o)>-1?nm[o](t)||r.push(Ip(i.messages.types[o],e.fullField,e.type)):o&&gi(t)!==e.type&&r.push(Ip(i.messages.types[o],e.fullField,e.type))},range:Zp,enum:Yp,pattern:Xp},rm=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(Rp(t)&&!e.required)return n();Q.required(e,t,r,a,i)}n(a)},im=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(t==null&&!e.required)return n();Q.required(e,t,r,a,i,`array`),t!=null&&(Q.type(e,t,r,a,i),Q.range(e,t,r,a,i))}n(a)},am=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(Rp(t)&&!e.required)return n();Q.required(e,t,r,a,i),t!==void 0&&Q.type(e,t,r,a,i)}n(a)},om=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(Rp(t,`date`)&&!e.required)return n();if(Q.required(e,t,r,a,i),!Rp(t,`date`)){var o=t instanceof Date?t:new Date(t);Q.type(e,o,r,a,i),o&&Q.range(e,o.getTime(),r,a,i)}}n(a)},sm=`enum`,cm=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(Rp(t)&&!e.required)return n();Q.required(e,t,r,a,i),t!==void 0&&Q[sm](e,t,r,a,i)}n(a)},lm=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(Rp(t)&&!e.required)return n();Q.required(e,t,r,a,i),t!==void 0&&(Q.type(e,t,r,a,i),Q.range(e,t,r,a,i))}n(a)},um=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(Rp(t)&&!e.required)return n();Q.required(e,t,r,a,i),t!==void 0&&(Q.type(e,t,r,a,i),Q.range(e,t,r,a,i))}n(a)},dm=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(Rp(t)&&!e.required)return n();Q.required(e,t,r,a,i),t!==void 0&&Q.type(e,t,r,a,i)}n(a)},fm=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(t===``&&(t=void 0),Rp(t)&&!e.required)return n();Q.required(e,t,r,a,i),t!==void 0&&(Q.type(e,t,r,a,i),Q.range(e,t,r,a,i))}n(a)},pm=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(Rp(t)&&!e.required)return n();Q.required(e,t,r,a,i),t!==void 0&&Q.type(e,t,r,a,i)}n(a)},mm=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(Rp(t,`string`)&&!e.required)return n();Q.required(e,t,r,a,i),Rp(t,`string`)||Q.pattern(e,t,r,a,i)}n(a)},hm=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(Rp(t)&&!e.required)return n();Q.required(e,t,r,a,i),Rp(t)||Q.type(e,t,r,a,i)}n(a)},gm=function(e,t,n,r,i){var a=[],o=Array.isArray(t)?`array`:gi(t);Q.required(e,t,r,a,i,o),n(a)},_m=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(Rp(t,`string`)&&!e.required)return n();Q.required(e,t,r,a,i,`string`),Rp(t,`string`)||(Q.type(e,t,r,a,i),Q.range(e,t,r,a,i),Q.pattern(e,t,r,a,i),e.whitespace===!0&&Q.whitespace(e,t,r,a,i))}n(a)},vm=function(e,t,n,r,i){var a=e.type,o=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(Rp(t,a)&&!e.required)return n();Q.required(e,t,r,o,i,a),Rp(t,a)||Q.type(e,t,r,o,i)}n(o)},ym={string:_m,method:dm,number:fm,boolean:am,regexp:hm,integer:um,float:lm,array:im,object:pm,enum:cm,pattern:mm,date:om,url:vm,hex:vm,email:vm,tel:vm,required:gm,any:rm},bm=function(){function e(t){Ei(this,e),Ci(this,`rules`,null),Ci(this,`_messages`,kp),this.define(t)}return W(e,[{key:`define`,value:function(e){var t=this;if(!e)throw Error(`Cannot configure a schema with no rules`);if(gi(e)!==`object`||Array.isArray(e))throw Error(`Rules must be an object`);this.rules={},Object.keys(e).forEach(function(n){var r=e[n];t.rules[n]=Array.isArray(r)?r:[r]})}},{key:`messages`,value:function(e){return e&&(this._messages=qp(Op(),e)),this._messages}},{key:`validate`,value:function(t){var n=this,r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},i=arguments.length>2&&arguments[2]!==void 0?arguments[2]:function(){},a=t,o=r,s=i;if(typeof o==`function`&&(s=o,o={}),!this.rules||Object.keys(this.rules).length===0)return s&&s(null,a),Promise.resolve(a);function c(e){var t=[],n={};function r(e){if(Array.isArray(e)){var n;t=(n=t).concat.apply(n,Mt(e))}else t.push(e)}for(var i=0;i0&&arguments[0]!==void 0?arguments[0]:[],l=Array.isArray(c)?c:[c];!o.suppressWarning&&l.length&&e.warning(`async-validator:`,l),l.length&&r.message!==void 0&&r.message!==null&&(l=[].concat(r.message));var u=l.map(Kp(r,a));if(o.first&&u.length)return d[r.field]=1,n(u);if(!i)n(u);else{if(r.required&&!t.value)return r.message===void 0?o.error&&(u=[o.error(r,Ip(o.messages.required,r.field))]):u=[].concat(r.message).map(Kp(r,a)),n(u);var f={};r.defaultField&&Object.keys(t.value).map(function(e){f[e]=r.defaultField}),f=Ti(Ti({},f),t.rule.fields);var p={};Object.keys(f).forEach(function(e){var t=f[e];p[e]=(Array.isArray(t)?t:[t]).map(s.bind(null,e))});var m=new e(p);m.messages(o.messages),t.rule.options&&(t.rule.options.messages=o.messages,t.rule.options.error=o.error),m.validate(t.value,t.rule.options||o,function(e){var t=[];u&&u.length&&t.push.apply(t,Mt(u)),e&&e.length&&t.push.apply(t,Mt(e)),n(t.length?t:null)})}}var l;if(r.asyncValidator)l=r.asyncValidator(r,t.value,c,t.source,o);else if(r.validator){try{l=r.validator(r,t.value,c,t.source,o)}catch(e){var u,f;(u=(f=console).error)==null||u.call(f,e),o.suppressValidatorError||setTimeout(function(){throw e},0),c(e.message)}l===!0?c():l===!1?c(typeof r.message==`function`?r.message(r.fullField||r.field):r.message||`${r.fullField||r.field} fails`):l instanceof Array?c(l):l instanceof Error&&c(l.message)}l&&l.then&&l.then(function(){return c()},function(e){return c(e)})},function(e){c(e)},a)}},{key:`getType`,value:function(e){if(e.type===void 0&&e.pattern instanceof RegExp&&(e.type=`pattern`),typeof e.validator!=`function`&&e.type&&!ym.hasOwnProperty(e.type))throw Error(Ip(`Unknown rule type %s`,e.type));return e.type||`string`}},{key:`getValidationMethod`,value:function(e){if(typeof e.validator==`function`)return e.validator;var t=Object.keys(e),n=t.indexOf(`message`);return n!==-1&&t.splice(n,1),t.length===1&&t[0]===`required`?ym.required:ym[this.getType(e)]||void 0}}]),e}();Ci(bm,`register`,function(e,t){if(typeof t!=`function`)throw Error(`Cannot register a validator by type, validator is not a function`);ym[e]=t}),Ci(bm,`warning`,Pp),Ci(bm,`messages`,kp),Ci(bm,`validators`,ym);var xm="'${name}' is not a valid ${type}",Sm={default:"Validation error on field '${name}'",required:"'${name}' is required",enum:"'${name}' must be one of [${enum}]",whitespace:"'${name}' cannot be empty",date:{format:"'${name}' is invalid for format date",parse:"'${name}' could not be parsed as date",invalid:"'${name}' is invalid date"},types:{string:xm,method:xm,array:xm,object:xm,number:xm,date:xm,boolean:xm,integer:xm,float:xm,regexp:xm,email:xm,tel:xm,url:xm,hex:xm},string:{len:"'${name}' must be exactly ${len} characters",min:"'${name}' must be at least ${min} characters",max:"'${name}' cannot be longer than ${max} characters",range:"'${name}' must be between ${min} and ${max} characters"},number:{len:"'${name}' must equal ${len}",min:"'${name}' cannot be less than ${min}",max:"'${name}' cannot be greater than ${max}",range:"'${name}' must be between ${min} and ${max}"},array:{len:"'${name}' must be exactly ${len} in length",min:"'${name}' cannot be less than ${min} in length",max:"'${name}' cannot be greater than ${max} in length",range:"'${name}' must be between ${min} and ${max} in length"},pattern:{mismatch:"'${name}' does not match pattern ${pattern}"}},Cm=bm;function wm(e,t){return e.replace(/\\?\$\{\w+\}/g,e=>e.startsWith(`\\`)?e.slice(1):t[e.slice(2,-1)])}var Tm=`CODE_LOGIC_ERROR`;async function Em(e,t,n,r,i){let a={...n};if(delete a.ruleIndex,Cm.warning=()=>void 0,a.validator){let e=a.validator;a.validator=(...t)=>{try{return e(...t)}catch(e){return console.error(e),Promise.reject(Tm)}}}let o=null;a&&a.type===`array`&&a.defaultField&&(o=a.defaultField,delete a.defaultField);let s=new Cm({[e]:[a]}),c=qe(Sm,r.validateMessages);s.messages(c);let l=[];try{await Promise.resolve(s.validate({[e]:t},{...r}))}catch(e){e.errors&&(l=e.errors.map(({message:e},t)=>{let n=e===Tm?c.default:e;return d.isValidElement(n)?d.cloneElement(n,{key:`error_${t}`}):n}))}if(!l.length&&o&&Array.isArray(t)&&t.length>0)return(await Promise.all(t.map((t,n)=>Em(`${e}.${n}`,t,o,r,i)))).reduce((e,t)=>[...e,...t],[]);let u={...n,name:e,enum:(n.enum||[]).join(`, `),...i};return l.map(e=>typeof e==`string`?wm(e,u):e)}function Dm(e,t,n,r,i,a){let o=e.join(`.`),s=n.map((e,t)=>{let n=e.validator,r={...e,ruleIndex:t};return n&&(r.validator=(e,t,r)=>{let i=!1,a=n(e,t,(...e)=>{Promise.resolve().then(()=>{tt(!i,"Your validator function has already return a promise. `callback` will be ignored."),i||r(...e)})});i=a&&typeof a.then==`function`&&typeof a.catch==`function`,tt(i,"`callback` is deprecated. Please return a promise instead."),i&&a.then(()=>{r()}).catch(e=>{r(e||` `)})}),r}).sort(({warningOnly:e,ruleIndex:t},{warningOnly:n,ruleIndex:r})=>!!e==!!n?t-r:e?1:-1),c;if(i===!0)c=new Promise(async(e,n)=>{for(let e=0;eEm(o,t,e,r,a).then(t=>({errors:t,rule:e})));c=(i?km(e):Om(e)).then(e=>Promise.reject(e))}return c.catch(e=>e),c}async function Om(e){return Promise.all(e).then(e=>[].concat(...e))}async function km(e){let t=0;return new Promise(n=>{e.forEach(r=>{r.then(r=>{r.errors.length&&n([r]),t+=1,t===e.length&&n([])})})})}function Am(e){return Ep(e)}function jm(e,t){let n={};return t.forEach(t=>{let r=Be(e,t);n=He(n,t,r)}),n}function Mm(e,t,n=!1){return e&&e.some(e=>Nm(t,e,n))}function Nm(e,t,n=!1){return!e||!t||!n&&e.length!==t.length?!1:t.every((t,n)=>e[n]===t)}function Pm(e,t){if(e===t)return!0;if(!e&&t||e&&!t||!e||!t||typeof e!=`object`||typeof t!=`object`)return!1;let n=Object.keys(e),r=Object.keys(t);return[...new Set([...n,...r])].every(n=>{let r=e[n],i=t[n];return typeof r==`function`&&typeof i==`function`?!0:r===i})}function Fm(e,...t){let n=t[0];return n&&n.target&&typeof n.target==`object`&&e in n.target?n.target[e]:n}function Im(e,t,n){let{length:r}=e;if(t<0||t>=r||n<0||n>=r)return e;let i=e[t],a=t-n;return a>0?[...e.slice(0,n),i,...e.slice(n,t),...e.slice(t+1,r)]:a<0?[...e.slice(0,t),...e.slice(t+1,n+1),i,...e.slice(n+1,r)]:e}var Lm=e=>{let t=new MessageChannel;t.port1.onmessage=e,t.port2.postMessage(null)},Rm=class{namePathList=[];taskId=0;watcherList=new Set;form;constructor(e){this.form=e}register(e){return this.watcherList.add(e),()=>{this.watcherList.delete(e)}}notify(e){e.forEach(e=>{this.namePathList.every(t=>!Nm(t,e))&&this.namePathList.push(e)}),this.doBatch()}doBatch(){this.taskId+=1;let e=this.taskId;Lm(()=>{if(e===this.taskId&&this.watcherList.size){let e=this.form.getForm(),t=e.getFieldsValue(),n=e.getFieldsValue(!0);this.watcherList.forEach(e=>{e(t,n,this.namePathList)}),this.namePathList=[]}})}};async function zm(){return new Promise(e=>{Lm(()=>{Rt(()=>{e()})})})}function Bm(){return Bm=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{preserve:e,isListField:t,name:n}=this.props;this.cancelRegisterFunc&&this.cancelRegisterFunc(t,e,Am(n)),this.cancelRegisterFunc=null};getNamePath=()=>{let{name:e,fieldContext:t}=this.props,{prefixName:n=[]}=t;return e===void 0?[]:[...n,...e]};getRules=()=>{let{rules:e=[],fieldContext:t}=this.props;return e.map(e=>typeof e==`function`?e(t):e)};reRender(){this.mounted&&this.forceUpdate()}refresh=()=>{this.mounted&&this.setState(({resetCount:e})=>({resetCount:e+1}))};metaCache=null;triggerMetaEvent=e=>{let{onMetaChange:t}=this.props;if(t){let n={...this.getMeta(),destroy:e};an(this.metaCache,n)||t(n),this.metaCache=n}else this.metaCache=null};onStoreChange=(e,t,n)=>{let{shouldUpdate:r,dependencies:i=[],onReset:a}=this.props,{store:o}=n,s=this.getNamePath(),c=this.getValue(e),l=this.getValue(o),u=t&&Mm(t,s);switch(n.type===`valueUpdate`&&n.source===`external`&&!an(c,l)&&(this.touched=!0,this.dirty=!0,this.validatePromise=null,this.errors=Vm,this.warnings=Hm,this.triggerMetaEvent()),n.type){case`reset`:if(!t||u){this.touched=!1,this.dirty=!1,this.validatePromise=void 0,this.errors=Vm,this.warnings=Hm,this.triggerMetaEvent(),a?.(),this.refresh();return}break;case`remove`:if(r&&Um(r,e,o,c,l,n)){this.reRender();return}break;case`setField`:{let{data:i}=n;if(u){`touched`in i&&(this.touched=i.touched),`validating`in i&&!(`originRCField`in i)&&(this.validatePromise=i.validating?Promise.resolve([]):null),`errors`in i&&(this.errors=i.errors||Vm),`warnings`in i&&(this.warnings=i.warnings||Hm),this.dirty=!0,this.triggerMetaEvent(),this.reRender();return}else if(`value`in i&&Mm(t,s,!0)){this.reRender();return}if(r&&!s.length&&Um(r,e,o,c,l,n)){this.reRender();return}break}case`dependenciesUpdate`:if(i.map(Am).some(e=>Mm(n.relatedFields,e))){this.reRender();return}break;default:if(u||(!i.length||s.length||r)&&Um(r,e,o,c,l,n)){this.reRender();return}break}r===!0&&this.reRender()};validateRules=e=>{let t=this.getNamePath(),n=this.getValue(),{triggerName:r,validateOnly:i=!1,delayFrame:a}=e||{},o=Promise.resolve().then(async()=>{if(!this.mounted)return[];let{validateFirst:i=!1,messageVariables:s,validateDebounce:c}=this.props;a&&await zm();let l=this.getRules();if(r&&(l=l.filter(e=>e).filter(e=>{let{validateTrigger:t}=e;return t?Ep(t).includes(r):!0})),c&&r&&(await new Promise(e=>{setTimeout(e,c)}),this.validatePromise!==o))return[];let u=Dm(t,n,l,e,i,s);return u.catch(e=>e).then((e=Vm)=>{if(this.validatePromise===o){this.validatePromise=null;let t=[],n=[];e.forEach?.(({rule:{warningOnly:e},errors:r=Vm})=>{e?n.push(...r):t.push(...r)}),this.errors=t,this.warnings=n,this.triggerMetaEvent(),this.reRender()}}),u});return i?o:(this.validatePromise=o,this.dirty=!0,this.errors=Vm,this.warnings=Hm,this.triggerMetaEvent(),this.reRender(),o)};isFieldValidating=()=>!!this.validatePromise;isFieldTouched=()=>this.touched;isFieldDirty=()=>{if(this.dirty||this.props.initialValue!==void 0)return!0;let{fieldContext:e}=this.props,{getInitialValue:t}=e.getInternalHooks(Cp);return t(this.getNamePath())!==void 0};getErrors=()=>this.errors;getWarnings=()=>this.warnings;isListField=()=>this.props.isListField;isList=()=>this.props.isList;isPreserve=()=>this.props.preserve;getMeta=()=>(this.prevValidating=this.isFieldValidating(),{touched:this.isFieldTouched(),validating:this.prevValidating,errors:this.errors,warnings:this.warnings,name:this.getNamePath(),validated:this.validatePromise===null});getOnlyChild=e=>{if(typeof e==`function`){let t=this.getMeta();return{...this.getOnlyChild(e(this.getControlled(),t,this.props.fieldContext)),isFunction:!0}}let t=it(e);return t.length!==1||!d.isValidElement(t[0])?{child:t,isFunction:!1}:{child:t[0],isFunction:!1}};getValue=e=>{let{getFieldsValue:t}=this.props.fieldContext,n=this.getNamePath();return Be(e||t(!0),n)};getControlled=(e={})=>{let{name:t,trigger:n=`onChange`,validateTrigger:r,getValueFromEvent:i,normalize:a,valuePropName:o=`value`,getValueProps:s,fieldContext:c}=this.props,l=r===void 0?c.validateTrigger:r,u=this.getNamePath(),{getInternalHooks:d,getFieldsValue:f}=c,{dispatch:p}=d(Cp),m=this.getValue(),h=s||(e=>({[o]:e})),g=e[n],_=t===void 0?{}:h(m),v={...e,..._};return v[n]=(...e)=>{this.touched=!0,this.dirty=!0,this.triggerMetaEvent();let t;t=i?i(...e):Fm(o,...e),a&&(t=a(t,m,f(!0))),t!==m&&p({type:`updateValue`,namePath:u,value:t}),g&&g(...e)},Ep(l||[]).forEach(e=>{let t=v[e];v[e]=(...n)=>{t&&t(...n);let{rules:r}=this.props;r&&r.length&&p({type:`validateField`,namePath:u,triggerName:e})}}),v};render(){let{resetCount:e}=this.state,{children:t}=this.props,{child:n,isFunction:r}=this.getOnlyChild(t),i;return r?i=n:d.isValidElement(n)?i=d.cloneElement(n,this.getControlled(n.props)):(tt(!n,"`children` of Field is not validate ReactElement."),i=n),d.createElement(d.Fragment,{key:e},i)}};function Gm({name:e,...t}){let n=d.useContext(wp),r=d.useContext(Tp),i=e===void 0?void 0:Am(e),a=t.isListField??!!r,o=`keep`;return a||(o=`_${(i||[]).join(`_`)}`),d.createElement(Wm,Bm({key:o,name:i,isListField:a},t,{fieldContext:n}))}function Km({name:e,initialValue:t,children:n,rules:r,validateTrigger:i,isListField:a}){let o=d.useContext(wp),s=d.useContext(Tp),c=d.useRef({keys:[],id:0}).current,l=d.useMemo(()=>[...Am(o.prefixName)||[],...Am(e)],[o.prefixName,e]),u=d.useMemo(()=>({...o,prefixName:l}),[o,l]),f=d.useMemo(()=>({getKey:e=>{let t=l.length,n=e[t];return[c.keys[n],e.slice(t+1)]}}),[c,l]);return typeof n==`function`?d.createElement(Tp.Provider,{value:f},d.createElement(wp.Provider,{value:u},d.createElement(Gm,{name:[],shouldUpdate:(e,t,{source:n})=>n===`internal`?!1:e!==t,rules:r,validateTrigger:i,initialValue:t,isList:!0,isListField:a??!!s},({value:e=[],onChange:t},r)=>{let{getFieldValue:i}=o,a=()=>i(l||[])||[],s={add:(e,n)=>{let r=a();n>=0&&n<=r.length?(c.keys=[...c.keys.slice(0,n),c.id,...c.keys.slice(n)],t([...r.slice(0,n),e,...r.slice(n)])):(c.keys=[...c.keys,c.id],t([...r,e])),c.id+=1},remove:e=>{let n=a(),r=new Set(Array.isArray(e)?e:[e]);r.size<=0||(c.keys=c.keys.filter((e,t)=>!r.has(t)),t(n.filter((e,t)=>!r.has(t))))},move(e,n){if(e===n)return;let r=a();e<0||e>=r.length||n<0||n>=r.length||(c.keys=Im(c.keys,e,n),t(Im(r,e,n)))}},u=e||[];return Array.isArray(u)||(u=[]),n(u.map((e,t)=>{let n=c.keys[t];return n===void 0&&(c.keys[t]=c.id,n=c.keys[t],c.id+=1),{name:t,key:n,isListField:!0}}),s,r)}))):(tt(!1,`Form.List only accepts function as children.`),null)}function qm(e){let t=!1,n=e.length,r=[];return e.length?new Promise((i,a)=>{e.forEach((e,o)=>{e.catch(e=>(t=!0,e)).then(e=>{--n,r[o]=e,!(n>0)&&(t&&a(r),i(r))})})}):Promise.resolve([])}var Jm=`__@field_split__`;function Ym(e){return e.map(e=>`${typeof e}:${e}`).join(Jm)}var Xm=class{kvs=new Map;set(e,t){this.kvs.set(Ym(e),t)}get(e){return this.kvs.get(Ym(e))}getAsPrefix(e){let t=Ym(e),n=t+Jm,r=[],i=this.kvs.get(t);return i!==void 0&&r.push(i),this.kvs.forEach((e,t)=>{t.startsWith(n)&&r.push(e)}),r}update(e,t){let n=t(this.get(e));n?this.set(e,n):this.delete(e)}delete(e){this.kvs.delete(Ym(e))}map(e){return[...this.kvs.entries()].map(([t,n])=>e({key:t.split(Jm).map(e=>{let[,t,n]=e.match(/^([^:]*):(.*)$/);return t===`number`?Number(n):n}),value:n}))}toJSON(){let e={};return this.map(({key:t,value:n})=>(e[t.join(`.`)]=n,null)),e}},Zm=class{formHooked=!1;forceRootUpdate;subscribable=!0;store={};fieldEntities=[];initialValues={};callbacks={};validateMessages=null;preserve=null;lastValidatePromise=null;watcherCenter=new Rm(this);constructor(e){this.forceRootUpdate=e}getForm=()=>({getFieldValue:this.getFieldValue,getFieldsValue:this.getFieldsValue,getFieldError:this.getFieldError,getFieldWarning:this.getFieldWarning,getFieldsError:this.getFieldsError,isFieldsTouched:this.isFieldsTouched,isFieldTouched:this.isFieldTouched,isFieldValidating:this.isFieldValidating,isFieldsValidating:this.isFieldsValidating,resetFields:this.resetFields,setFields:this.setFields,setFieldValue:this.setFieldValue,setFieldsValue:this.setFieldsValue,validateFields:this.validateFields,submit:this.submit,_init:!0,getInternalHooks:this.getInternalHooks});getInternalHooks=e=>e===`RC_FORM_INTERNAL_HOOKS`?(this.formHooked=!0,{dispatch:this.dispatch,initEntityValue:this.initEntityValue,registerField:this.registerField,useSubscribe:this.useSubscribe,setInitialValues:this.setInitialValues,destroyForm:this.destroyForm,setCallbacks:this.setCallbacks,setValidateMessages:this.setValidateMessages,getFields:this.getFields,setPreserve:this.setPreserve,getInitialValue:this.getInitialValue,registerWatch:this.registerWatch}):(tt(!1,"`getInternalHooks` is internal usage. Should not call directly."),null);useSubscribe=e=>{this.subscribable=e};prevWithoutPreserves=null;setInitialValues=(e,t)=>{if(this.initialValues=e||{},t){let t=qe(e,this.store);this.prevWithoutPreserves?.map(({key:n})=>{t=He(t,n,Be(e,n))}),this.prevWithoutPreserves=null,this.updateStore(t)}};destroyForm=e=>{if(e)this.updateStore({});else{let e=new Xm;this.getFieldEntities(!0).forEach(t=>{this.isMergedPreserve(t.isPreserve())||e.set(t.getNamePath(),!0)}),this.prevWithoutPreserves=e}};getInitialValue=e=>{let t=Be(this.initialValues,e);return e.length?qe(t):t};setCallbacks=e=>{this.callbacks=e};setValidateMessages=e=>{this.validateMessages=e};setPreserve=e=>{this.preserve=e};registerWatch=e=>this.watcherCenter.register(e);notifyWatch=(e=[])=>{this.watcherCenter.notify(e)};timeoutId=null;warningUnhooked=()=>{};updateStore=e=>{this.store=e};getFieldEntities=(e=!1)=>e?this.fieldEntities.filter(e=>e.getNamePath().length):this.fieldEntities;getFieldsMap=(e=!1)=>{let t=new Xm;return this.getFieldEntities(e).forEach(e=>{let n=e.getNamePath();t.set(n,e)}),t};getFieldEntitiesForNamePathList=(e,t=!1)=>{if(!e)return this.getFieldEntities(!0);let n=this.getFieldsMap(!0);return t?e.flatMap(e=>{let t=Am(e),r=n.getAsPrefix(t);return r.length?r:[{INVALIDATE_NAME_PATH:t}]}):e.map(e=>{let t=Am(e);return n.get(t)||{INVALIDATE_NAME_PATH:Am(e)}})};getFieldsValue=(e,t)=>{this.warningUnhooked();let n,r;if(e===!0||Array.isArray(e)?(n=e,r=t):e&&typeof e==`object`&&(r=e.filter),n===!0&&!r)return this.store;let i=this.getFieldEntitiesForNamePathList(Array.isArray(n)?n:null,!0),a=[],o=[];i.forEach(e=>{let t=e.INVALIDATE_NAME_PATH||e.getNamePath();if(e.isList?.()){o.push(t);return}if(!r)a.push(t);else{let n=`getMeta`in e?e.getMeta():null;r(n)&&a.push(t)}});let s=jm(this.store,a.map(Am));return o.forEach(e=>{Be(s,e)||(s=He(s,e,[]))}),s};getFieldValue=e=>{this.warningUnhooked();let t=Am(e);return Be(this.store,t)};getFieldsError=e=>(this.warningUnhooked(),this.getFieldEntitiesForNamePathList(e).map((t,n)=>t&&!t.INVALIDATE_NAME_PATH?{name:t.getNamePath(),errors:t.getErrors(),warnings:t.getWarnings()}:{name:Am(e[n]),errors:[],warnings:[]}));getFieldError=e=>{this.warningUnhooked();let t=Am(e);return this.getFieldsError([t])[0].errors};getFieldWarning=e=>{this.warningUnhooked();let t=Am(e);return this.getFieldsError([t])[0].warnings};isFieldsTouched=(...e)=>{this.warningUnhooked();let[t,n]=e,r,i=!1;e.length===0?r=null:e.length===1?Array.isArray(t)?(r=t.map(Am),i=!1):(r=null,i=t):(r=t.map(Am),i=n);let a=this.getFieldEntities(!0),o=e=>e.isFieldTouched();if(!r)return i?a.every(e=>o(e)||e.isList()):a.some(o);let s=new Xm;r.forEach(e=>{s.set(e,[])}),a.forEach(e=>{let t=e.getNamePath();r.forEach(n=>{n.every((e,n)=>t[n]===e)&&s.update(n,t=>[...t,e])})});let c=e=>e.some(o),l=s.map(({value:e})=>e);return i?l.every(c):l.some(c)};isFieldTouched=e=>(this.warningUnhooked(),this.isFieldsTouched([e]));isFieldsValidating=e=>{this.warningUnhooked();let t=this.getFieldEntities();if(!e)return t.some(e=>e.isFieldValidating());let n=e.map(Am);return t.some(e=>Mm(n,e.getNamePath())&&e.isFieldValidating())};isFieldValidating=e=>(this.warningUnhooked(),this.isFieldsValidating([e]));resetWithFieldInitialValue=(e={})=>{let t=new Xm,n=this.getFieldEntities(!0);n.forEach(e=>{let{initialValue:n}=e.props,r=e.getNamePath();if(n!==void 0){let i=t.get(r)||new Set;i.add({entity:e,value:n}),t.set(r,i)}});let r=n=>{n.forEach(n=>{let{initialValue:r}=n.props;if(r!==void 0){let r=n.getNamePath();if(this.getInitialValue(r)!==void 0)tt(!1,`Form already set 'initialValues' with path '${r.join(`.`)}'. Field can not overwrite it.`);else{let i=t.get(r);if(i&&i.size>1)tt(!1,`Multiple Field with path '${r.join(`.`)}' set 'initialValue'. Can not decide which one to pick.`);else if(i){let t=this.getFieldValue(r);!n.isListField()&&(!e.skipExist||t===void 0)&&this.updateStore(He(this.store,r,[...i][0].value))}}}})},i;e.entities?i=e.entities:e.namePathList?(i=[],e.namePathList.forEach(e=>{let n=t.get(e);n&&i.push(...[...n].map(e=>e.entity))})):i=n,r(i)};resetFields=e=>{this.warningUnhooked();let t=this.store;if(!e){this.updateStore(qe(this.initialValues)),this.resetWithFieldInitialValue(),this.notifyObservers(t,null,{type:`reset`}),this.notifyWatch();return}let n=e.map(Am);n.forEach(e=>{let t=this.getInitialValue(e);this.updateStore(He(this.store,e,t))}),this.resetWithFieldInitialValue({namePathList:n}),this.notifyObservers(t,n,{type:`reset`}),this.notifyWatch(n)};setFields=e=>{this.warningUnhooked();let t=this.store,n=[];e.forEach(e=>{let{name:r,...i}=e,a=Am(r);n.push(a),`value`in i&&this.updateStore(He(this.store,a,i.value)),this.notifyObservers(t,[a],{type:`setField`,data:e})}),this.notifyWatch(n)};getFields=()=>this.getFieldEntities(!0).map(e=>{let t=e.getNamePath(),n={...e.getMeta(),name:t,value:this.getFieldValue(t)};return Object.defineProperty(n,`originRCField`,{value:!0}),n});initEntityValue=e=>{let{initialValue:t}=e.props;if(t!==void 0){let n=e.getNamePath();Be(this.store,n)===void 0&&this.updateStore(He(this.store,n,t))}};isMergedPreserve=e=>(e===void 0?this.preserve:e)??!0;registerField=e=>{this.fieldEntities.push(e);let t=e.getNamePath();if(this.notifyWatch([t]),e.props.initialValue!==void 0){let t=this.store;this.resetWithFieldInitialValue({entities:[e],skipExist:!0}),this.notifyObservers(t,[e.getNamePath()],{type:`valueUpdate`,source:`internal`})}return(n,r,i=[])=>{if(this.fieldEntities=this.fieldEntities.filter(t=>t!==e),!this.isMergedPreserve(r)&&(!n||i.length>1)){let e=n?void 0:this.getInitialValue(t);if(t.length&&this.getFieldValue(t)!==e&&this.fieldEntities.every(e=>!Nm(e.getNamePath(),t))){let n=this.store;this.updateStore(He(n,t,e,!0)),this.notifyObservers(n,[t],{type:`remove`}),this.triggerDependenciesUpdate(n,t)}}this.notifyWatch([t])}};dispatch=e=>{switch(e.type){case`updateValue`:{let{namePath:t,value:n}=e;this.updateValue(t,n);break}case`validateField`:{let{namePath:t,triggerName:n}=e;this.validateFields([t],{triggerName:n});break}default:}};notifyObservers=(e,t,n)=>{if(this.subscribable){let r={...n,store:this.getFieldsValue(!0)};this.getFieldEntities().forEach(({onStoreChange:n})=>{n(e,t,r)})}else this.forceRootUpdate()};triggerDependenciesUpdate=(e,t)=>{let n=this.getDependencyChildrenFields(t);return n.length&&this.validateFields(n,{delayFrame:!0}),this.notifyObservers(e,n,{type:`dependenciesUpdate`,relatedFields:[t,...n]}),n};updateValue=(e,t)=>{let n=Am(e),r=this.store;this.updateStore(He(this.store,n,t)),this.notifyObservers(r,[n],{type:`valueUpdate`,source:`internal`}),this.notifyWatch([n]);let i=this.triggerDependenciesUpdate(r,n),{onValuesChange:a}=this.callbacks;if(a){let e=jm(this.store,[n]);a(e,He(this.getFieldsValue(),n,Be(e,n)))}this.triggerOnFieldsChange([n,...i])};setFieldsValue=e=>{this.warningUnhooked();let t=this.store;if(e){let t=qe(this.store,e);this.updateStore(t)}this.notifyObservers(t,null,{type:`valueUpdate`,source:`external`}),this.notifyWatch()};setFieldValue=(e,t)=>{this.setFields([{name:e,value:t,errors:[],warnings:[],touched:!0}])};getDependencyChildrenFields=e=>{let t=new Set,n=[],r=new Xm;this.getFieldEntities().forEach(e=>{let{dependencies:t}=e.props;(t||[]).forEach(t=>{let n=Am(t);r.update(n,(t=new Set)=>(t.add(e),t))})});let i=e=>{(r.get(e)||new Set).forEach(e=>{if(!t.has(e)){t.add(e);let r=e.getNamePath();e.isFieldDirty()&&r.length&&(n.push(r),i(r))}})};return i(e),n};triggerOnFieldsChange=(e,t)=>{let{onFieldsChange:n}=this.callbacks;if(n){let r=this.getFields();if(t){let e=new Xm;t.forEach(({name:t,errors:n})=>{e.set(t,n)}),r.forEach(t=>{t.errors=e.get(t.name)||t.errors})}let i=r.filter(({name:t})=>Mm(e,t));i.length&&n(i,r)}};validateFields=(e,t)=>{this.warningUnhooked();let n,r;Array.isArray(e)||typeof e==`string`||typeof t==`string`?(n=e,r=t):r=e;let i=!!n,a=i?n.map(Am):[],o=[...a],s=[],c=String(Date.now()),l=new Set,{recursive:u,dirty:d}=r||{};this.getFieldEntities(!0).forEach(e=>{let t=e.getNamePath();if(i||((!e.isList()||!a.some(e=>Nm(e,t,!0)))&&o.push(t),a.push(t)),!(!e.props.rules||!e.props.rules.length)&&!(d&&!e.isFieldDirty())&&(l.add(t.join(c)),!i||Mm(a,t,u))){let n=e.validateRules({validateMessages:{...Sm,...this.validateMessages},...r});s.push(n.then(()=>({name:t,errors:[],warnings:[]})).catch(e=>{let n=[],r=[];return e.forEach?.(({rule:{warningOnly:e},errors:t})=>{e?r.push(...t):n.push(...t)}),n.length?Promise.reject({name:t,errors:n,warnings:r}):{name:t,errors:n,warnings:r}}))}});let f=qm(s);this.lastValidatePromise=f,f.catch(e=>e).then(e=>{let t=e.map(({name:e})=>e);this.notifyObservers(this.store,t,{type:`validateFinish`}),this.triggerOnFieldsChange(t,e)});let p=f.then(()=>this.lastValidatePromise===f?Promise.resolve(this.getFieldsValue(o)):Promise.reject([])).catch(e=>{let t=e.filter(e=>e&&e.errors.length),n=t[0]?.errors?.[0];return Promise.reject({message:n,values:this.getFieldsValue(a),errorFields:t,outOfDate:this.lastValidatePromise!==f})});p.catch(e=>e);let m=a.filter(e=>l.has(e.join(c)));return this.triggerOnFieldsChange(m),p};submit=()=>{this.warningUnhooked(),this.validateFields().then(e=>{let{onFinish:t}=this.callbacks;if(t)try{t(e)}catch(e){console.error(e)}}).catch(e=>{let{onFinishFailed:t}=this.callbacks;t&&t(e)})}};function Qm(e){let t=d.useRef(null),[,n]=d.useState({});return t.current||(e?t.current=e:t.current=new Zm(()=>{n({})}).getForm()),[t.current]}var $m=d.createContext({triggerFormChange:()=>{},triggerFormFinish:()=>{},registerForm:()=>{},unregisterForm:()=>{}}),eh=({validateMessages:e,onFormChange:t,onFormFinish:n,children:r})=>{let i=d.useContext($m),a=d.useRef({});return d.createElement($m.Provider,{value:{...i,validateMessages:{...i.validateMessages,...e},triggerFormChange:(e,n)=>{t&&t(e,{changedFields:n,forms:a.current}),i.triggerFormChange(e,n)},triggerFormFinish:(e,t)=>{n&&n(e,{values:t,forms:a.current}),i.triggerFormFinish(e,t)},registerForm:(e,t)=>{e&&(a.current={...a.current,[e]:t}),i.registerForm(e,t)},unregisterForm:e=>{let t={...a.current};delete t[e],a.current=t,i.unregisterForm(e)}}},r)};function th(){return th=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let _=d.useRef(null),v=d.useContext($m),[y]=Qm(r),{useSubscribe:b,setInitialValues:x,setCallbacks:S,setValidateMessages:C,setPreserve:w,destroyForm:T}=y.getInternalHooks(Cp);d.useImperativeHandle(g,()=>({...y,nativeElement:_.current})),d.useEffect(()=>(v.registerForm(e,y),()=>{v.unregisterForm(e)}),[v,y,e]),C({...v.validateMessages,...s}),S({onValuesChange:l,onFieldsChange:(t,...n)=>{v.triggerFormChange(e,t),u&&u(t,...n)},onFinish:t=>{v.triggerFormFinish(e,t),f&&f(t)},onFinishFailed:p}),w(i);let E=d.useRef(null);x(t,!E.current),E.current||=!0,d.useEffect(()=>()=>T(m),[]);let D,O=typeof a==`function`;D=O?a(y.getFieldsValue(!0),y):a,b(!O);let k=d.useRef(null);d.useEffect(()=>{Pm(k.current||[],n||[])||y.setFields(n||[]),k.current=n},[n,y]);let A=d.useMemo(()=>({...y,validateTrigger:c}),[y,c]),j=d.createElement(Tp.Provider,{value:null},d.createElement(wp.Provider,{value:A},D));return o===!1?j:d.createElement(o,th({},h,{ref:_,onSubmit:e=>{e.preventDefault(),e.stopPropagation(),y.submit()},onReset:e=>{e.preventDefault(),y.resetFields(),h.onReset?.(e)}}),j)};function rh(e){try{return JSON.stringify(e)}catch{return Math.random()}}function ih(...e){let[t,n={}]=e,r=Dp(n)?{form:n}:n,i=r.form,[a,o]=(0,d.useState)(()=>typeof t==`function`?t({}):void 0),s=(0,d.useMemo)(()=>rh(a),[a]),c=(0,d.useRef)(s);c.current=s;let l=(0,d.useContext)(wp),u=i||l,f=u&&u._init,{getFieldsValue:p,getInternalHooks:m}=u,{registerWatch:h}=m(Cp),g=xe((e,n)=>{let i=r.preserve?n??p(!0):e??p(),s=typeof t==`function`?t(i):Be(i,Am(t));rh(a)!==rh(s)&&o(s)});return(0,d.useEffect)(()=>{f&&g()},[f,typeof t==`function`?t:JSON.stringify(t)]),(0,d.useEffect)(()=>{if(f)return h((e,t)=>{g(e,t)})},[f]),a}var ah=d.forwardRef(nh);ah.FormProvider=eh,ah.Field=Gm,ah.List=Km,ah.useForm=Qm,ah.useWatch=ih;var oh=d.createContext({}),sh=({children:e,status:t,override:n})=>{let r=d.useContext(oh),i=d.useMemo(()=>{let e={...r};return n&&delete e.isFormItemInput,t&&(delete e.status,delete e.hasFeedback,delete e.feedbackIcon),e},[t,n,r]);return d.createElement(oh.Provider,{value:i},e)},ch=e=>{let{space:t,form:n,children:r}=e;if(!Rc(r))return null;let i=r;return n&&(i=d.createElement(sh,{override:!0,status:!0},i)),t&&(i=d.createElement(Ad,null,i)),i},lh=()=>R()&&window.document.documentElement;function uh(e,t,n){return(0,d.useMemo)(()=>({trap:t??!0,focusTriggerAfterClose:n??!0,...e}),[e,t,n])}var dh=e=>{let{prefixCls:t,className:n,style:r,size:i,shape:a}=e,o=B({[`${t}-lg`]:i===`large`,[`${t}-sm`]:i===`small`}),s=B({[`${t}-circle`]:a===`circle`,[`${t}-square`]:a===`square`,[`${t}-round`]:a===`round`}),c=d.useMemo(()=>typeof i==`number`?{width:i,height:i,lineHeight:`${i}px`}:{},[i]);return d.createElement(`span`,{className:B(t,o,s,n),style:{...c,...r}})},fh=new mi(`ant-skeleton-loading`,{"0%":{backgroundPosition:`100% 50%`},"100%":{backgroundPosition:`0 50%`}}),ph=e=>({height:e,lineHeight:V(e)}),mh=e=>({width:e,...ph(e)}),hh=e=>({background:e.skeletonLoadingBackground,backgroundSize:`400% 100%`,animationName:fh,animationDuration:e.skeletonLoadingMotionDuration,animationTimingFunction:`ease`,animationIterationCount:`infinite`}),gh=(e,t)=>({width:t(e).mul(5).equal(),minWidth:t(e).mul(5).equal(),...ph(e)}),_h=e=>{let{skeletonAvatarCls:t,gradientFromColor:n,controlHeight:r,controlHeightLG:i,controlHeightSM:a}=e;return{[t]:{display:`inline-block`,verticalAlign:`top`,background:n,...mh(r)},[`${t}${t}-circle`]:{borderRadius:`50%`},[`${t}${t}-lg`]:{...mh(i)},[`${t}${t}-sm`]:{...mh(a)}}},vh=e=>{let{controlHeight:t,borderRadiusSM:n,skeletonInputCls:r,controlHeightLG:i,controlHeightSM:a,gradientFromColor:o,calc:s}=e;return{[r]:{display:`inline-block`,verticalAlign:`top`,background:o,borderRadius:n,...gh(t,s)},[`${r}-lg`]:{...gh(i,s)},[`${r}-sm`]:{...gh(a,s)}}},yh=e=>{let{gradientFromColor:t,borderRadiusSM:n,imageSizeBase:r,calc:i}=e;return{display:`inline-flex`,alignItems:`center`,justifyContent:`center`,verticalAlign:`middle`,background:t,borderRadius:n,...mh(i(r).mul(2).equal())}},bh=e=>({[e.skeletonNodeCls]:{...yh(e)}}),xh=e=>{let{skeletonImageCls:t,imageSizeBase:n,calc:r}=e;return{[t]:{...yh(e),[`${t}-path`]:{fill:`#bfbfbf`},[`${t}-svg`]:{...mh(n),maxWidth:r(n).mul(4).equal(),maxHeight:r(n).mul(4).equal()},[`${t}-svg${t}-svg-circle`]:{borderRadius:`50%`}},[`${t}${t}-circle`]:{borderRadius:`50%`}}},Sh=(e,t,n)=>{let{skeletonButtonCls:r}=e;return{[`${n}${r}-circle`]:{width:t,minWidth:t,borderRadius:`50%`},[`${n}${r}-round`]:{borderRadius:t}}},Ch=(e,t)=>({width:t(e).mul(2).equal(),minWidth:t(e).mul(2).equal(),...ph(e)}),wh=e=>{let{borderRadiusSM:t,skeletonButtonCls:n,controlHeight:r,controlHeightLG:i,controlHeightSM:a,gradientFromColor:o,calc:s}=e;return{[n]:{display:`inline-block`,verticalAlign:`top`,background:o,borderRadius:t,width:s(r).mul(2).equal(),minWidth:s(r).mul(2).equal(),...Ch(r,s)},...Sh(e,r,n),[`${n}-lg`]:{...Ch(i,s)},...Sh(e,i,`${n}-lg`),[`${n}-sm`]:{...Ch(a,s)},...Sh(e,a,`${n}-sm`)}},Th=e=>{let{componentCls:t,skeletonAvatarCls:n,skeletonTitleCls:r,skeletonParagraphCls:i,skeletonButtonCls:a,skeletonInputCls:o,skeletonNodeCls:s,skeletonImageCls:c,controlHeight:l,controlHeightLG:u,controlHeightSM:d,gradientFromColor:f,padding:p,marginSM:m,borderRadius:h,titleHeight:g,blockRadius:_,paragraphLiHeight:v,controlHeightXS:y,paragraphMarginTop:b}=e;return{[t]:{display:`table`,width:`100%`,[`${t}-header`]:{display:`table-cell`,paddingInlineEnd:p,verticalAlign:`top`,[n]:{display:`inline-block`,verticalAlign:`top`,background:f,...mh(l)},[`${n}-circle`]:{borderRadius:`50%`},[`${n}-lg`]:{...mh(u)},[`${n}-sm`]:{...mh(d)}},[`${t}-section`]:{display:`table-cell`,width:`100%`,verticalAlign:`top`,[r]:{width:`100%`,height:g,background:f,borderRadius:_,[`+ ${i}`]:{marginBlockStart:d}},[i]:{padding:0,"> li":{width:`100%`,height:v,listStyle:`none`,background:f,borderRadius:_,"+ li":{marginBlockStart:y}}},[`${i}> li:last-child:not(:first-child):not(:nth-child(2))`]:{width:`61%`}},[`&-round ${t}-section`]:{[`${r}, ${i} > li`]:{borderRadius:h}}},[`${t}-with-avatar ${t}-section`]:{[r]:{marginBlockStart:m,[`+ ${i}`]:{marginBlockStart:b}}},[`${t}${t}-element`]:{display:`inline-block`,width:`auto`,...wh(e),..._h(e),...vh(e),...bh(e),...xh(e)},[`${t}${t}-block`]:{width:`100%`,[a]:{width:`100%`},[o]:{width:`100%`}},[`${t}${t}-active`]:{[` + ${r}, + ${i} > li, + ${n}, + ${a}, + ${o}, + ${s}, + ${c} + `]:{...hh(e)}}}},Eh=Ao(`Skeleton`,e=>{let{componentCls:t,calc:n}=e;return Th(Ki(e,{skeletonAvatarCls:`${t}-avatar`,skeletonTitleCls:`${t}-title`,skeletonParagraphCls:`${t}-paragraph`,skeletonButtonCls:`${t}-button`,skeletonInputCls:`${t}-input`,skeletonNodeCls:`${t}-node`,skeletonImageCls:`${t}-image`,imageSizeBase:n(e.controlHeight).mul(1.5).equal(),borderRadius:100,skeletonLoadingBackground:`linear-gradient(90deg, ${e.gradientFromColor} 25%, ${e.gradientToColor} 37%, ${e.gradientFromColor} 63%)`,skeletonLoadingMotionDuration:`1.4s`}))},e=>{let{colorFillContent:t,colorFill:n}=e,r=t,i=n;return{color:r,colorGradientEnd:i,gradientFromColor:r,gradientToColor:i,titleHeight:e.controlHeight/2,blockRadius:e.borderRadiusSM,paragraphMarginTop:e.marginLG+e.marginXXS,paragraphLiHeight:e.controlHeight/2}},{deprecatedTokens:[[`color`,`gradientFromColor`],[`colorGradientEnd`,`gradientToColor`]]}),Dh=e=>{let{prefixCls:t,className:n,classNames:r,rootClassName:i,active:a,style:o,styles:s,shape:c=`circle`,size:l,...u}=e,{getPrefixCls:f}=d.useContext(zt),p=f(`skeleton`,t),[m,h]=Eh(p),g=Dd(e=>l??e),_=B(p,`${p}-element`,{[`${p}-active`]:a},r?.root,n,i,m,h);return d.createElement(`div`,{className:_,style:s?.root},d.createElement(dh,{prefixCls:`${p}-avatar`,className:r?.content,style:{...s?.content,...o},shape:c,size:g,...u}))},Oh=e=>{let{prefixCls:t,className:n,rootClassName:r,classNames:i,active:a,style:o,styles:s,block:c=!1,size:l,...u}=e,{getPrefixCls:f}=d.useContext(zt),p=f(`skeleton`,t),[m,h]=Eh(p),g=Dd(e=>l??e),_=B(p,`${p}-element`,{[`${p}-active`]:a,[`${p}-block`]:c},i?.root,n,r,m,h);return d.createElement(`div`,{className:_,style:s?.root},d.createElement(dh,{prefixCls:`${p}-button`,className:i?.content,style:{...s?.content,...o},size:g,...u}))},kh=e=>{let{prefixCls:t,className:n,classNames:r,rootClassName:i,internalClassName:a,style:o,styles:s,active:c,children:l}=e,{getPrefixCls:u}=d.useContext(zt),f=u(`skeleton`,t),[p,m]=Eh(f),h=B(f,`${f}-element`,{[`${f}-active`]:c},p,r?.root,n,i,m);return d.createElement(`div`,{className:h,style:s?.root},d.createElement(`div`,{className:B(r?.content,a||`${f}-node`),style:{...s?.content,...o}},l))},Ah=e=>{let{getPrefixCls:t}=d.useContext(zt),n=t(`skeleton`,e.prefixCls);return d.createElement(kh,{...e,internalClassName:`${n}-image`},d.createElement(`svg`,{viewBox:`0 0 1098 1024`,xmlns:`http://www.w3.org/2000/svg`,className:`${n}-image-svg`},d.createElement(`title`,null,`Image placeholder`),d.createElement(`path`,{d:`M365.7 329.1q0 45.8-32 77.7t-77.7 32-77.7-32-32-77.7 32-77.6 77.7-32 77.7 32 32 77.6M951 548.6v256H146.3V694.9L329 512l91.5 91.4L713 311zm54.8-402.3H91.4q-7.4 0-12.8 5.4T73 164.6v694.8q0 7.5 5.5 12.9t12.8 5.4h914.3q7.5 0 12.9-5.4t5.4-12.9V164.6q0-7.5-5.4-12.9t-12.9-5.4m91.4 18.3v694.8q0 37.8-26.8 64.6t-64.6 26.9H91.4q-37.7 0-64.6-26.9T0 859.4V164.6q0-37.8 26.8-64.6T91.4 73h914.3q37.8 0 64.6 26.9t26.8 64.6`,className:`${n}-image-path`})))},jh=e=>{let{prefixCls:t,className:n,classNames:r,rootClassName:i,active:a,block:o,style:s,styles:c,size:l,...u}=e,{getPrefixCls:f}=d.useContext(zt),p=f(`skeleton`,t),[m,h]=Eh(p),g=Dd(e=>l??e),_=B(p,`${p}-element`,{[`${p}-active`]:a,[`${p}-block`]:o},r?.root,n,i,m,h);return d.createElement(`div`,{className:_,style:c?.root},d.createElement(dh,{prefixCls:`${p}-input`,className:r?.content,style:{...c?.content,...s},size:g,...u}))},Mh=(e,t)=>{let{width:n,rows:r=2}=t;if(Array.isArray(n))return n[e];if(r-1===e)return n},Nh=e=>{let{prefixCls:t,className:n,style:r,rows:i=0}=e,a=Array.from({length:i}).map((t,n)=>d.createElement(`li`,{key:n,style:{width:Mh(n,e)}}));return d.createElement(`ul`,{className:B(t,n),style:r},a)},Ph=({prefixCls:e,className:t,width:n,style:r})=>d.createElement(`h3`,{className:B(e,t),style:{width:n,...r}});function Fh(e){return e&&typeof e==`object`?e:{}}function Ih(e,t){return e&&!t?{size:`large`,shape:`square`}:{size:`large`,shape:`circle`}}function Lh(e,t){return!e&&t?{width:`38%`}:e&&t?{width:`50%`}:{}}function Rh(e,t){let n={};return(!e||!t)&&(n.width=`61%`),!e&&t?n.rows=3:n.rows=2,n}var zh=e=>{let{prefixCls:t,loading:n,className:r,rootClassName:i,classNames:a,style:o,styles:s,children:c,avatar:l=!1,title:u=!0,paragraph:f=!0,active:p,round:m}=e,{getPrefixCls:h,direction:g,className:_,style:v,classNames:y,styles:b}=Ht(`skeleton`),x=h(`skeleton`,t),[S,C]=Eh(x),w={...e,avatar:l,title:u,paragraph:f},[T,E]=el([y,a],[b,s],{props:w});if(n||!(`loading`in e)){let e=!!l,t=!!u,n=!!f,a;if(e){let e={className:T.avatar,prefixCls:`${x}-avatar`,...Ih(t,n),...Fh(l),style:E.avatar};a=d.createElement(`div`,{className:B(T.header,`${x}-header`),style:E.header},d.createElement(dh,{...e}))}let s;if(t||n){let r;if(t){let t={className:T.title,prefixCls:`${x}-title`,...Lh(e,n),...Fh(u),style:E.title};r=d.createElement(Ph,{...t})}let i;if(n){let n={className:T.paragraph,prefixCls:`${x}-paragraph`,...Rh(e,t),...Fh(f),style:E.paragraph};i=d.createElement(Nh,{...n})}s=d.createElement(`div`,{className:B(T.section,`${x}-section`),style:E.section},r,i)}let c=B(x,{[`${x}-with-avatar`]:e,[`${x}-active`]:p,[`${x}-rtl`]:g===`rtl`,[`${x}-round`]:m},T.root,_,r,i,S,C);return d.createElement(`div`,{className:c,style:{...E.root,...v,...o}},a,s)}return c??null};zh.Button=Oh,zh.Avatar=Dh,zh.Input=jh,zh.Image=Ah,zh.Node=kh;var Bh=zh;function Vh(){}var Hh=d.createContext({add:Vh,remove:Vh});function Uh(e){let t=d.useContext(Hh),n=d.useRef(null);return xe(r=>{if(r){let i=e?r.querySelector(e):r;i&&(t.add(i),n.current=i)}else t.remove(n.current)})}var Wh=()=>{let{cancelButtonProps:e,cancelTextLocale:t,onCancel:n}=(0,d.useContext)(Gf);return d.createElement(Hf,{onClick:n,...e},t)},Gh=()=>{let{confirmLoading:e,okButtonProps:t,okType:n,okTextLocale:r,onOk:i}=(0,d.useContext)(Gf);return d.createElement(Hf,{...Fd(n),loading:e,onClick:i,...t},r)};function Kh(e,t){return d.createElement(`span`,{className:`${e}-close-x`},t||d.createElement(us,{className:`${e}-close-icon`}))}var qh=e=>{let{okText:t,okType:n=`primary`,cancelText:r,confirmLoading:i,onOk:a,onCancel:o,okButtonProps:s,cancelButtonProps:c,footer:l}=e,[u]=Pc(`Modal`,Mc()),f=t||u?.okText,p=r||u?.cancelText,m=d.useMemo(()=>({confirmLoading:i,okButtonProps:s,cancelButtonProps:c,okTextLocale:f,cancelTextLocale:p,okType:n,onOk:a,onCancel:o}),[i,s,c,f,p,n,a,o]),h;return typeof l==`function`||l===void 0?(h=d.createElement(d.Fragment,null,d.createElement(Wh,null),d.createElement(Gh,null)),typeof l==`function`&&(h=l(h,{OkBtn:Gh,CancelBtn:Wh})),h=d.createElement(Kf,{value:m},h)):h=l,d.createElement(bu,{disabled:!1},h)},Jh=e=>{let{componentCls:t}=e;return{[t]:{display:`flex`,flexFlow:`row wrap`,minWidth:0,"&::before, &::after":{display:`flex`},"&-no-wrap":{flexWrap:`nowrap`},"&-start":{justifyContent:`flex-start`},"&-center":{justifyContent:`center`},"&-end":{justifyContent:`flex-end`},"&-space-between":{justifyContent:`space-between`},"&-space-around":{justifyContent:`space-around`},"&-space-evenly":{justifyContent:`space-evenly`},"&-top":{alignItems:`flex-start`},"&-middle":{alignItems:`center`},"&-bottom":{alignItems:`flex-end`}}}},Yh=e=>{let{componentCls:t}=e;return{[t]:{position:`relative`,maxWidth:`100%`,minHeight:1}}},Xh=(e,t)=>{let{componentCls:n,gridColumns:r,antCls:i}=e,[a,o]=No(i,`grid`),[,s]=No(i,`col`),c={};for(let e=r;e>=0;e--)e===0?(c[`${n}${t}-${e}`]={display:`none`},c[`${n}-push-${e}`]={insetInlineStart:`auto`},c[`${n}-pull-${e}`]={insetInlineEnd:`auto`},c[`${n}${t}-push-${e}`]={insetInlineStart:`auto`},c[`${n}${t}-pull-${e}`]={insetInlineEnd:`auto`},c[`${n}${t}-offset-${e}`]={marginInlineStart:0},c[`${n}${t}-order-${e}`]={order:0}):(c[`${n}${t}-${e}`]=[{[a(`display`)]:`block`,display:`block`},{display:o(`display`),flex:`0 0 ${e/r*100}%`,maxWidth:`${e/r*100}%`}],c[`${n}${t}-push-${e}`]={insetInlineStart:`${e/r*100}%`},c[`${n}${t}-pull-${e}`]={insetInlineEnd:`${e/r*100}%`},c[`${n}${t}-offset-${e}`]={marginInlineStart:`${e/r*100}%`},c[`${n}${t}-order-${e}`]={order:e});return c[`${n}${t}-flex`]={flex:s(`${t.replace(/-/,``)}-flex`)},c},Zh=(e,t)=>Xh(e,t),Qh=(e,t,n)=>({[`@media (min-width: ${V(t)})`]:{...Zh(e,n)}}),$h=()=>({}),eg=()=>({});Ao(`Grid`,Jh,$h);var tg=e=>({xs:e.screenXSMin,sm:e.screenSMMin,md:e.screenMDMin,lg:e.screenLGMin,xl:e.screenXLMin,xxl:e.screenXXLMin,xxxl:e.screenXXXLMin});Ao(`Grid`,e=>{let t=Ki(e,{gridColumns:24}),n=tg(t);return delete n.xs,[Yh(t),Zh(t,``),Zh(t,`-xs`),Object.keys(n).map(e=>Qh(t,n[e],`-${e}`)).reduce((e,t)=>({...e,...t}),{})]},eg);function ng(e){return{position:e,inset:0}}var rg=e=>{let{componentCls:t,antCls:n}=e;return[{[`${t}-root`]:{[`${t}${n}-zoom-enter, ${t}${n}-zoom-appear`]:{transform:`none`,opacity:0,animationDuration:e.motionDurationSlow,userSelect:`none`},[`${t}${n}-zoom-leave ${t}-container`]:{pointerEvents:`none`},[`${t}-mask`]:{...ng(`fixed`),zIndex:e.zIndexPopupBase,height:`100%`,backgroundColor:e.colorBgMask,pointerEvents:`none`,[`&${t}-mask-blur`]:{backdropFilter:`blur(4px)`},[`${t}-hidden`]:{display:`none`}},[`${t}-wrap`]:{...ng(`fixed`),zIndex:e.zIndexPopupBase,overflow:`auto`,outline:0,WebkitOverflowScrolling:`touch`}}},{[`${t}-root`]:Yd(e)}]},ig=e=>{let{componentCls:t,motionDurationMid:n}=e;return[{[`${t}-root`]:{[`${t}-wrap-rtl`]:{direction:`rtl`},[`${t}-centered`]:{textAlign:`center`,"&::before":{display:`inline-block`,width:0,height:`100%`,verticalAlign:`middle`,content:`""`},[t]:{top:0,display:`inline-block`,paddingBottom:0,textAlign:`start`,verticalAlign:`middle`}},[`@media (max-width: ${e.screenSMMax}px)`]:{[t]:{maxWidth:`calc(100vw - 16px)`,margin:`${V(e.marginXS)} auto`},[`${t}-centered`]:{[t]:{flex:1}}}}},{[t]:{...So(e),pointerEvents:`none`,position:`relative`,top:100,width:`auto`,maxWidth:`calc(100vw - ${V(e.calc(e.margin).mul(2).equal())})`,margin:`0 auto`,"&:focus-visible":{borderRadius:e.borderRadiusLG,...To(e)},[`${t}-title`]:{margin:0,color:e.titleColor,fontWeight:e.fontWeightStrong,fontSize:e.titleFontSize,lineHeight:e.titleLineHeight,wordWrap:`break-word`},[`${t}-container`]:{position:`relative`,backgroundColor:e.contentBg,backgroundClip:`padding-box`,border:0,borderRadius:e.borderRadiusLG,boxShadow:e.boxShadow,pointerEvents:`auto`,padding:e.contentPadding},[`${t}-close`]:{position:`absolute`,top:e.calc(e.modalHeaderHeight).sub(e.modalCloseBtnSize).div(2).equal(),insetInlineEnd:e.calc(e.modalHeaderHeight).sub(e.modalCloseBtnSize).div(2).equal(),zIndex:e.calc(e.zIndexPopupBase).add(10).equal(),padding:0,color:e.modalCloseIconColor,fontWeight:e.fontWeightStrong,lineHeight:1,textDecoration:`none`,background:`transparent`,borderRadius:e.borderRadiusSM,width:e.modalCloseBtnSize,height:e.modalCloseBtnSize,border:0,outline:0,cursor:`pointer`,transition:[`color`,`background-color`].map(e=>`${e} ${n}`).join(`, `),"&-x":{display:`flex`,fontSize:e.fontSizeLG,fontStyle:`normal`,lineHeight:V(e.modalCloseBtnSize),justifyContent:`center`,textTransform:`none`,textRendering:`auto`},"&:disabled":{pointerEvents:`none`},"&:hover":{color:e.modalCloseIconHoverColor,backgroundColor:e.colorBgTextHover,textDecoration:`none`},"&:active":{backgroundColor:e.colorBgTextActive},...Eo(e)},[`${t}-header`]:{color:e.colorText,background:e.headerBg,borderRadius:`${V(e.borderRadiusLG)} ${V(e.borderRadiusLG)} 0 0`,marginBottom:e.headerMarginBottom,padding:e.headerPadding,borderBottom:e.headerBorderBottom},[`${t}-body`]:{fontSize:e.fontSize,lineHeight:e.lineHeight,wordWrap:`break-word`,padding:e.bodyPadding,[`${t}-body-skeleton`]:{width:`100%`,height:`100%`,display:`flex`,justifyContent:`center`,alignItems:`center`,margin:`${V(e.margin)} auto`}},[`${t}-footer`]:{textAlign:`end`,background:e.footerBg,marginTop:e.footerMarginTop,padding:e.footerPadding,borderTop:e.footerBorderTop,borderRadius:e.footerBorderRadius,[`> ${e.antCls}-btn + ${e.antCls}-btn`]:{marginInlineStart:e.marginXS}},[`${t}-open`]:{overflow:`hidden`}}},{[`${t}-pure-panel`]:{top:`auto`,padding:0,display:`flex`,flexDirection:`column`,[`${t}-container, + ${t}-body, + ${t}-confirm-body-wrapper`]:{display:`flex`,flexDirection:`column`,flex:`auto`},[`${t}-confirm-body`]:{marginBottom:`auto`}}}]},ag=e=>{let{componentCls:t}=e;return{[`${t}-root`]:{[`${t}-wrap-rtl`]:{direction:`rtl`,[`${t}-confirm-body`]:{direction:`rtl`}}}}},og=e=>{let{componentCls:t}=e,n=tg(e),r={...n};delete r.xs;let i=`--${t.replace(`.`,``)}-`,a=Object.keys(r).map(e=>({[`@media (min-width: ${V(r[e])})`]:{width:`var(${i}${e}-width)`}}));return{[`${t}-root`]:{[t]:[].concat(Mt(Object.keys(n).map((e,t)=>{let r=Object.keys(n)[t-1];return r?{[`${i}${e}-width`]:`var(${i}${r}-width)`}:null})),[{width:`var(${i}xs-width)`}],Mt(a))}}},sg=e=>{let t=e.padding,n=e.fontSizeHeading5,r=e.lineHeightHeading5;return Ki(e,{modalHeaderHeight:e.calc(e.calc(r).mul(n).equal()).add(e.calc(t).mul(2).equal()).equal(),modalFooterBorderColorSplit:e.colorSplit,modalFooterBorderStyle:e.lineType,modalFooterBorderWidth:e.lineWidth,modalCloseIconColor:e.colorIcon,modalCloseIconHoverColor:e.colorIconHover,modalCloseBtnSize:e.controlHeight,modalConfirmIconSize:e.fontHeight,modalTitleHeight:e.calc(e.titleFontSize).mul(e.titleLineHeight).equal()})},cg=e=>({footerBg:`transparent`,headerBg:`transparent`,titleLineHeight:e.lineHeightHeading5,titleFontSize:e.fontSizeHeading5,contentBg:e.colorBgElevated,titleColor:e.colorTextHeading,contentPadding:e.wireframe?0:`${V(e.paddingMD)} ${V(e.paddingContentHorizontalLG)}`,headerPadding:e.wireframe?`${V(e.padding)} ${V(e.paddingLG)}`:0,headerBorderBottom:e.wireframe?`${V(e.lineWidth)} ${e.lineType} ${e.colorSplit}`:`none`,headerMarginBottom:e.wireframe?0:e.marginXS,bodyPadding:e.wireframe?e.paddingLG:0,footerPadding:e.wireframe?`${V(e.paddingXS)} ${V(e.padding)}`:0,footerBorderTop:e.wireframe?`${V(e.lineWidth)} ${e.lineType} ${e.colorSplit}`:`none`,footerBorderRadius:e.wireframe?`0 0 ${V(e.borderRadiusLG)} ${V(e.borderRadiusLG)}`:0,footerMarginTop:e.wireframe?0:e.marginSM,confirmBodyPadding:e.wireframe?`${V(e.padding*2)} ${V(e.padding*2)} ${V(e.paddingLG)}`:0,confirmIconMarginInlineEnd:e.wireframe?e.margin:e.marginSM,confirmBtnsMarginTop:e.wireframe?e.marginLG:e.marginSM,mask:!0}),lg=Ao(`Modal`,e=>{let t=sg(e);return[ig(t),ag(t),rg(t),df(t,`zoom`),og(t)]},cg,{unitless:{titleLineHeight:!0}}),ug;lh()&&document.documentElement.addEventListener(`click`,e=>{ug={x:e.pageX,y:e.pageY},setTimeout(()=>{ug=null},100)},!0);var dg=e=>{let{prefixCls:t,className:n,rootClassName:r,open:i,wrapClassName:a,centered:o,getContainer:s,style:c,width:l=520,footer:u,classNames:f,styles:p,children:m,loading:h,confirmLoading:g,zIndex:_,mousePosition:v,onOk:y,onCancel:b,okButtonProps:x,cancelButtonProps:S,destroyOnHidden:C,destroyOnClose:w,panelRef:T=null,closable:E,mask:D,modalRender:O,maskClosable:k,focusTriggerAfterClose:A,focusable:j,...ee}=e,{getPopupContainer:te,getPrefixCls:M,direction:N,className:P,style:ne,classNames:re,styles:F,centered:ie,cancelButtonProps:I,okButtonProps:ae,mask:oe}=Ht(`modal`),{modal:se}=d.useContext(zt),[ce,le]=d.useMemo(()=>typeof E==`boolean`?[void 0,void 0]:[E?.afterClose,E?.onClose],[E]),ue=M(`modal`,t),de=M(),[L,fe,pe]=qc(D,oe,ue,k),me=uh(j,L,A),he=e=>{g||(b?.(e),le?.())},ge=e=>{y?.(e),le?.()},_e=ll(ue),[ve,ye]=lg(ue,_e),be=B(a,{[`${ue}-centered`]:o??ie,[`${ue}-wrap-rtl`]:N===`rtl`}),xe=u!==null&&!h?d.createElement(qh,{...e,okButtonProps:{...ae,...x},onOk:ge,cancelButtonProps:{...I,...S},onCancel:he}):null,[R,Se,z,Ce]=Gc(zc(e),zc(se),{closable:!0,closeIcon:d.createElement(us,{className:`${ue}-close-icon`}),closeIconRender:e=>Kh(ue,e)}),we=R?{disabled:z,closeIcon:Se,afterClose:ce,...Ce}:!1,Te=O?e=>d.createElement(`div`,{className:`${ue}-render`},O(e)):void 0,Ee=Pe(T,Uh(`.${ue}-${O?`render`:`container`}`)),[De,Oe]=cl(`Modal`,_),ke={...e,width:l,panelRef:T,focusTriggerAfterClose:me.focusTriggerAfterClose,focusable:me,mask:L,maskClosable:pe,zIndex:De},[Ae,je]=el([re,f,fe],[F,p],{props:ke}),[Me,Ne]=d.useMemo(()=>l&&typeof l==`object`?[void 0,l]:[l,void 0],[l]),Fe=d.useMemo(()=>{let e={};return Ne&&Object.keys(Ne).forEach(t=>{let n=Ne[t];n!==void 0&&(e[`--${ue}-${t}-width`]=typeof n==`number`?`${n}px`:n)}),e},[ue,Ne]);return d.createElement(ch,{form:!0,space:!0},d.createElement(nl.Provider,{value:Oe},d.createElement(Sp,{width:Me,...ee,zIndex:De,getContainer:s===void 0?te:s,prefixCls:ue,rootClassName:B(ve,r,ye,_e,Ae.root),rootStyle:je.root,footer:xe,visible:i,mousePosition:v??ug,onClose:he,closable:we,closeIcon:Se,transitionName:vd(de,`zoom`,e.transitionName),maskTransitionName:vd(de,`fade`,e.maskTransitionName),mask:L,maskClosable:pe,className:B(ve,n,P),style:{...ne,...c,...Fe},classNames:{...Ae,wrapper:B(Ae.wrapper,be)},styles:je,panelRef:Ee,destroyOnHidden:C??w,modalRender:Te,focusTriggerAfterClose:me.focusTriggerAfterClose,focusTrap:me.trap},h?d.createElement(Bh,{active:!0,title:!1,paragraph:{rows:4},className:`${ue}-body-skeleton`}):m)))},fg=e=>{let{componentCls:t,titleFontSize:n,titleLineHeight:r,modalConfirmIconSize:i,fontSize:a,lineHeight:o,modalTitleHeight:s,fontHeight:c,confirmBodyPadding:l}=e,u=`${t}-confirm`;return{[u]:{"&-rtl":{direction:`rtl`},[`${e.antCls}-modal-header`]:{display:`none`},[`${u}-body-wrapper`]:{...wo()},[`&${t} ${t}-body`]:{padding:l},[`${u}-body`]:{display:`flex`,flexWrap:`nowrap`,alignItems:`start`,[`> ${e.iconCls}`]:{flex:`none`,fontSize:i,marginInlineEnd:e.confirmIconMarginInlineEnd,marginTop:e.calc(e.calc(c).sub(i).equal()).div(2).equal()},[`&-has-title > ${e.iconCls}`]:{marginTop:e.calc(e.calc(s).sub(i).equal()).div(2).equal()}},[`${u}-paragraph`]:{display:`flex`,flexDirection:`column`,flex:`auto`,rowGap:e.marginXS,maxWidth:`calc(100% - ${V(e.marginSM)})`},[`${u}-body-no-icon ${u}-paragraph`]:{maxWidth:`100%`},[`${e.iconCls} + ${u}-paragraph`]:{maxWidth:`calc(100% - ${V(e.calc(e.modalConfirmIconSize).add(e.marginSM).equal())})`},[`${u}-title`]:{color:e.colorTextHeading,fontWeight:e.fontWeightStrong,fontSize:n,lineHeight:r},[`${u}-container`]:{color:e.colorText,fontSize:a,lineHeight:o},[`${u}-btns`]:{textAlign:`end`,marginTop:e.confirmBtnsMarginTop,[`${e.antCls}-btn + ${e.antCls}-btn`]:{marginBottom:0,marginInlineStart:e.marginXS}}},[`${u}-error ${u}-body > ${e.iconCls}`]:{color:e.colorError},[`${u}-warning ${u}-body > ${e.iconCls}, + ${u}-confirm ${u}-body > ${e.iconCls}`]:{color:e.colorWarning},[`${u}-info ${u}-body > ${e.iconCls}`]:{color:e.colorInfo},[`${u}-success ${u}-body > ${e.iconCls}`]:{color:e.colorSuccess}}},pg=Mo([`Modal`,`confirm`],e=>fg(sg(e)),cg,{order:-1e3}),mg=e=>{let{prefixCls:t,icon:n,okText:r,cancelText:i,confirmPrefixCls:a,type:o,okCancel:s,footer:c,locale:l,autoFocusButton:u,focusable:f,...p}=e,m=n;if(!n&&n!==null)switch(o){case`info`:m=d.createElement(gs,null);break;case`success`:m=d.createElement(is,null);break;case`error`:m=d.createElement(ss,null);break;default:m=d.createElement(ps,null)}let h=s??o===`confirm`,g=d.useMemo(()=>{let e=f?.autoFocusButton||u;return e||e===null?e:`ok`},[u,f?.autoFocusButton]),[_]=Pc(`Modal`),v=l||_,y=r||(h?v?.okText:v?.justOkText),b=i||v?.cancelText,{closable:x}=p,{onClose:S}=x&&typeof x==`object`?x:{},C=d.useMemo(()=>({autoFocusButton:g,cancelTextLocale:b,okTextLocale:y,mergedOkCancel:h,onClose:S,...p}),[g,b,y,h,S,p]),w=d.createElement(d.Fragment,null,d.createElement(qf,null),d.createElement(Jf,null)),T=Rc(e.title)&&e.title!==``,E=Rc(m),D=`${a}-body`;return d.createElement(`div`,{className:`${a}-body-wrapper`},d.createElement(`div`,{className:B(D,{[`${D}-has-title`]:T,[`${D}-no-icon`]:!E})},m,d.createElement(`div`,{className:`${a}-paragraph`},T&&d.createElement(`span`,{className:`${a}-title`},e.title),d.createElement(`div`,{className:`${a}-content`},e.content))),c===void 0||typeof c==`function`?d.createElement(Kf,{value:C},d.createElement(`div`,{className:`${a}-btns`},typeof c==`function`?c(w,{OkBtn:Jf,CancelBtn:qf}):w)):c,d.createElement(pg,{prefixCls:t}))},hg=e=>{let{close:t,zIndex:n,maskStyle:r,direction:i,prefixCls:a,wrapClassName:o,rootPrefixCls:s,bodyStyle:c,closable:l=!1,onConfirm:u,styles:f,title:p,mask:m,maskClosable:h,okButtonProps:g,cancelButtonProps:_}=e,{cancelButtonProps:v,okButtonProps:y}=Ht(`modal`),b=`${a}-confirm`,x=e.width||416,S=e.style||{},C=B(b,`${b}-${e.type}`,{[`${b}-rtl`]:i===`rtl`},e.className),w=d.useMemo(()=>{let e=Kc(m,h);return e.closable??=!1,e},[m,h]),[,T]=xo(),E=d.useMemo(()=>n===void 0?T.zIndexPopupBase+il:n,[n,T]);return d.createElement(dg,{...e,className:C,wrapClassName:B({[`${b}-centered`]:!!e.centered},o),onCancel:()=>{t?.({triggerCancel:!0}),u?.(!1)},title:p,footer:null,transitionName:vd(s||``,`zoom`,e.transitionName),maskTransitionName:vd(s||``,`fade`,e.maskTransitionName),mask:w,style:S,styles:{body:c,mask:r,...f},width:x,zIndex:E,closable:l},d.createElement(mg,{...e,confirmPrefixCls:b,okButtonProps:{...y,...g},cancelButtonProps:{...v,..._}}))},gg=e=>{let{rootPrefixCls:t,iconPrefixCls:n,direction:r,theme:i}=e;return d.createElement(Mu,{prefixCls:t,iconPrefixCls:n,direction:r,theme:i},d.createElement(hg,{...e}))},_g=[];function vg(e){return{...e,type:`warning`}}function yg(e){return{...e,type:`info`}}function bg(e){return{...e,type:`success`}}function xg(e){return{...e,type:`error`}}function Sg(e){return{...e,type:`confirm`}}var Cg=d.forwardRef((e,t)=>{let{afterClose:n,config:r,...i}=e,[a,o]=d.useState(!0),[s,c]=d.useState(r),{direction:l,getPrefixCls:u}=d.useContext(zt),f=u(`modal`),p=u(),m=()=>{n(),s.afterClose?.()},h=(...e)=>{o(!1),e.some(e=>e?.triggerCancel)&&s.onCancel?.(()=>{},...e.slice(1))};d.useImperativeHandle(t,()=>({destroy:h,update:e=>{c(t=>{let n=typeof e==`function`?e(t):e;return{...t,...n}})}}));let g=s.okCancel??s.type===`confirm`,[_]=Pc(`Modal`,Dc.Modal);return d.createElement(gg,{prefixCls:f,rootPrefixCls:p,...s,close:h,open:a,afterClose:m,okText:s.okText||(g?_?.okText:_?.justOkText),direction:s.direction||l,cancelText:s.cancelText||_?.cancelText,...i})}),wg=0,Tg=d.memo(d.forwardRef((e,t)=>{let[n,r]=tl();return d.useImperativeHandle(t,()=>({patchElement:r}),[r]),d.createElement(d.Fragment,null,n)}));function Eg(){let e=d.useRef(null),[t,n]=d.useState([]);d.useEffect(()=>{t.length&&(Mt(t).forEach(e=>{e()}),n([]))},[t]);let r=d.useCallback(t=>function(r){wg+=1;let i=d.createRef(),a,o=new Promise(e=>{a=e}),s=!1,c,l=d.createElement(Cg,{key:`modal-${wg}`,config:t(r),ref:i,afterClose:()=>{c?.()},isSilent:()=>s,onConfirm:e=>{a(e)}});return c=e.current?.patchElement(l),c&&_g.push(c),{destroy:()=>{function e(){i.current?.destroy()}i.current?e():n(t=>[].concat(Mt(t),[e]))},update:e=>{function t(){i.current?.update(e)}i.current?t():n(e=>[].concat(Mt(e),[t]))},then:e=>(s=!0,o.then(e))}},[]);return[d.useMemo(()=>({info:r(yg),success:r(bg),error:r(xg),warning:r(vg),confirm:r(Sg)}),[r]),d.createElement(Tg,{key:`modal-holder`,ref:e})]}var Dg=e=>{let{componentCls:t,notificationMarginEdge:n,animationMaxHeight:r}=e,i=`${t}-notice`,a=new mi(`antNotificationFadeIn`,{"0%":{transform:`translate3d(100%, 0, 0)`,opacity:0},"100%":{transform:`translate3d(0, 0, 0)`,opacity:1}}),o=new mi(`antNotificationTopFadeIn`,{"0%":{top:-r,opacity:0},"100%":{top:0,opacity:1}}),s=new mi(`antNotificationBottomFadeIn`,{"0%":{bottom:e.calc(r).mul(-1).equal(),opacity:0},"100%":{bottom:0,opacity:1}}),c=new mi(`antNotificationLeftFadeIn`,{"0%":{transform:`translate3d(-100%, 0, 0)`,opacity:0},"100%":{transform:`translate3d(0, 0, 0)`,opacity:1}});return{[t]:{[`&${t}-top, &${t}-bottom`]:{marginInline:0,[i]:{marginInline:`auto auto`}},[`&${t}-top`]:{[`${t}-fade-enter${t}-fade-enter-active, ${t}-fade-appear${t}-fade-appear-active`]:{animationName:o}},[`&${t}-bottom`]:{[`${t}-fade-enter${t}-fade-enter-active, ${t}-fade-appear${t}-fade-appear-active`]:{animationName:s}},[`&${t}-topRight, &${t}-bottomRight`]:{[`${t}-fade-enter${t}-fade-enter-active, ${t}-fade-appear${t}-fade-appear-active`]:{animationName:a}},[`&${t}-topLeft, &${t}-bottomLeft`]:{marginRight:{value:0,_skip_check_:!0},marginLeft:{value:n,_skip_check_:!0},[i]:{marginInlineEnd:`auto`,marginInlineStart:0},[`${t}-fade-enter${t}-fade-enter-active, ${t}-fade-appear${t}-fade-appear-active`]:{animationName:c}}}}},Og=[`top`,`topLeft`,`topRight`,`bottom`,`bottomLeft`,`bottomRight`],kg={topLeft:`left`,topRight:`right`,bottomLeft:`left`,bottomRight:`right`,top:`left`,bottom:`left`},Ag=(e,t)=>{let{componentCls:n}=e;return{[`${n}-${t}`]:{[`&${n}-stack > ${n}-notice-wrapper`]:{[t.startsWith(`top`)?`top`:`bottom`]:0,[kg[t]]:{value:0,_skip_check_:!0}}}}},jg=e=>{let t={};for(let n=1;n ${e.componentCls}-notice`]:{opacity:0,transition:`opacity ${e.motionDurationMid}`}};return{[`&:not(:nth-last-child(-n+${e.notificationStackLayer}))`]:{opacity:0,overflow:`hidden`,color:`transparent`,pointerEvents:`none`},...t}},Mg=e=>{let t={};for(let n=1;n{let{componentCls:t}=e;return{[`${t}-stack`]:{[`& > ${t}-notice-wrapper`]:{transition:`transform ${e.motionDurationSlow}, backdrop-filter 0s`,willChange:`transform, opacity`,position:`absolute`,...jg(e)}},[`${t}-stack:not(${t}-stack-expanded)`]:{[`& > ${t}-notice-wrapper`]:{...Mg(e)}},[`${t}-stack${t}-stack-expanded`]:{[`& > ${t}-notice-wrapper`]:{"&:not(:nth-last-child(-n + 1))":{opacity:1,overflow:`unset`,color:`inherit`,pointerEvents:`auto`,[`& > ${e.componentCls}-notice`]:{opacity:1}},"&:after":{content:`""`,position:`absolute`,height:e.margin,width:`100%`,insetInline:0,bottom:e.calc(e.margin).mul(-1).equal(),background:`transparent`,pointerEvents:`auto`}}},...Og.map(t=>Ag(e,t)).reduce((e,t)=>({...e,...t}),{})}},Pg=e=>{let{iconCls:t,componentCls:n,boxShadow:r,fontSizeLG:i,notificationMarginBottom:a,borderRadiusLG:o,colorSuccess:s,colorInfo:c,colorWarning:l,colorError:u,colorTextHeading:d,notificationBg:f,notificationPadding:p,notificationMarginEdge:m,progressBg:h,notificationProgressHeight:g,fontSize:_,lineHeight:v,width:y,notificationIconSize:b,colorText:x,colorSuccessBg:S,colorErrorBg:C,colorInfoBg:w,colorWarningBg:T,motionDurationMid:E}=e,D=`${n}-notice`;return{position:`relative`,marginBottom:a,marginInlineStart:`auto`,background:f,borderRadius:o,boxShadow:r,[D]:{padding:p,width:y,maxWidth:`calc(100vw - ${V(e.calc(m).mul(2).equal())})`,lineHeight:v,wordWrap:`break-word`,borderRadius:o,overflow:`hidden`,"&-success":S?{background:S}:{},"&-error":C?{background:C}:{},"&-info":w?{background:w}:{},"&-warning":T?{background:T}:{}},[`${D}-title`]:{marginBottom:e.marginXS,color:d,fontSize:i,lineHeight:e.lineHeightLG},[`${D}-description`]:{fontSize:_,color:x,marginTop:e.marginXS},[`${D}-closable ${D}-title`]:{paddingInlineEnd:e.paddingLG},[`${D}-with-icon ${D}-title`]:{marginBottom:e.marginXS,marginInlineStart:e.calc(e.marginSM).add(b).equal(),fontSize:i},[`${D}-with-icon ${D}-description`]:{marginInlineStart:e.calc(e.marginSM).add(b).equal(),fontSize:_},[`${D}-icon`]:{position:`absolute`,fontSize:b,lineHeight:1,[`&-success${t}`]:{color:s},[`&-info${t}`]:{color:c},[`&-warning${t}`]:{color:l},[`&-error${t}`]:{color:u}},[`${D}-close`]:{position:`absolute`,top:e.notificationPaddingVertical,insetInlineEnd:e.notificationPaddingHorizontal,color:e.colorIcon,outline:`none`,width:e.notificationCloseButtonSize,height:e.notificationCloseButtonSize,borderRadius:e.borderRadiusSM,transition:[`color`,`background-color`].map(e=>`${e} ${E}`).join(`, `),display:`flex`,alignItems:`center`,justifyContent:`center`,background:`none`,border:`none`,"&:hover":{color:e.colorIconHover,backgroundColor:e.colorBgTextHover},"&:active":{backgroundColor:e.colorBgTextActive},...Eo(e)},[`${D}-progress`]:{position:`absolute`,display:`block`,appearance:`none`,inlineSize:`calc(100% - ${V(o)} * 2)`,left:{_skip_check_:!0,value:o},right:{_skip_check_:!0,value:o},bottom:0,blockSize:g,border:0,"&, &::-webkit-progress-bar":{borderRadius:o,backgroundColor:`rgba(0, 0, 0, 0.04)`},"&::-moz-progress-bar":{background:h},"&::-webkit-progress-value":{borderRadius:o,background:h}},[`${D}-actions`]:{float:`right`,marginTop:e.marginSM}}},Fg=e=>{let{componentCls:t,notificationMarginBottom:n,notificationMarginEdge:r,motionDurationMid:i,motionEaseInOut:a}=e,o=`${t}-notice`,s=new mi(`antNotificationFadeOut`,{"0%":{maxHeight:e.animationMaxHeight,marginBottom:n},"100%":{maxHeight:0,marginBottom:0,paddingTop:0,paddingBottom:0,opacity:0}});return[{[t]:{...So(e),position:`fixed`,zIndex:e.zIndexPopup,marginRight:{value:r,_skip_check_:!0},[`${t}-hook-holder`]:{position:`relative`},[`${t}-fade-appear-prepare`]:{opacity:`0 !important`},[`${t}-fade-enter, ${t}-fade-appear`]:{animationDuration:e.motionDurationMid,animationTimingFunction:a,animationFillMode:`both`,opacity:0,animationPlayState:`paused`},[`${t}-fade-leave`]:{animationTimingFunction:a,animationFillMode:`both`,animationDuration:i,animationPlayState:`paused`},[`${t}-fade-enter${t}-fade-enter-active, ${t}-fade-appear${t}-fade-appear-active`]:{animationPlayState:`running`},[`${t}-fade-leave${t}-fade-leave-active`]:{animationName:s,animationPlayState:`running`},"&-rtl":{direction:`rtl`,[`${o}-actions`]:{float:`left`}}}},{[t]:{[`${o}-wrapper`]:Pg(e)}}]},Ig=e=>({zIndexPopup:e.zIndexPopupBase+il+50,width:384,progressBg:`linear-gradient(90deg, ${e.colorPrimaryBorderHover}, ${e.colorPrimary})`,colorSuccessBg:void 0,colorErrorBg:void 0,colorInfoBg:void 0,colorWarningBg:void 0}),Lg=e=>{let t=e.paddingMD,n=e.paddingLG;return Ki(e,{notificationBg:e.colorBgElevated,notificationPaddingVertical:t,notificationPaddingHorizontal:n,notificationIconSize:e.calc(e.fontSizeLG).mul(e.lineHeightLG).equal(),notificationCloseButtonSize:e.calc(e.controlHeightLG).mul(.55).equal(),notificationMarginBottom:e.margin,notificationPadding:`${V(e.paddingMD)} ${V(e.paddingContentHorizontalLG)}`,notificationMarginEdge:e.marginLG,animationMaxHeight:150,notificationStackLayer:3,notificationProgressHeight:2})},Rg=Ao(`Notification`,e=>{let t=Lg(e);return[Fg(t),Dg(t),Ng(t)]},Ig);function zg(e,t){return t===null||t===!1?null:t||d.createElement(us,{className:`${e}-close-icon`})}var Bg={success:is,info:gs,error:ss,warning:ps},Vg=e=>{let{prefixCls:t,icon:n,type:r,title:i,description:a,actions:o,role:s=`alert`,styles:c,classNames:l}=e,u=null;return n?u=d.createElement(`span`,{className:B(`${t}-icon`,l.icon),style:c.icon},n):r&&(u=d.createElement(Bg[r]||null,{className:B(`${t}-icon`,l.icon,`${t}-icon-${r}`),style:c.icon})),d.createElement(`div`,{className:B({[`${t}-with-icon`]:u}),role:s},u,d.createElement(`div`,{className:B(`${t}-title`,l.title),style:c.title},i),a&&d.createElement(`div`,{className:B(`${t}-description`,l.description),style:c.description},a),o&&d.createElement(`div`,{className:B(`${t}-actions`,l.actions),style:c.actions},o))};function Hg(e,t,n){let r;switch(e){case`top`:r={left:`50%`,transform:`translateX(-50%)`,right:`auto`,top:t,bottom:`auto`};break;case`topLeft`:r={left:0,top:t,bottom:`auto`};break;case`topRight`:r={right:0,top:t,bottom:`auto`};break;case`bottom`:r={left:`50%`,transform:`translateX(-50%)`,right:`auto`,top:`auto`,bottom:n};break;case`bottomLeft`:r={left:0,top:`auto`,bottom:n};break;default:r={right:0,top:`auto`,bottom:n};break}return r}function Ug(e){return{motionName:`${e}-fade`}}function Wg(e,t,n){return e===void 0?t?.closeIcon===void 0?n?.closeIcon:t.closeIcon:e}var Gg=24,Kg=4.5,qg=`topRight`,Jg=({children:e,prefixCls:t})=>{let n=ll(t),[r,i]=Rg(t,n);return d.createElement(Iu,{classNames:{list:B(r,i,n)}},e)},Yg=(e,{prefixCls:t,key:n})=>d.createElement(Jg,{prefixCls:t,key:n},e),Xg=d.forwardRef((e,t)=>{let{top:n,bottom:r,prefixCls:i,getContainer:a,maxCount:o,rtl:s,onAllRemoved:c,stack:l,duration:u=Kg,pauseOnHover:f=!0,showProgress:p}=e,{getPrefixCls:m,getPopupContainer:h,direction:g}=Ht(`notification`),{notification:_}=(0,d.useContext)(zt),[,v]=xo(),y=i||m(`notification`),b=(0,d.useMemo)(()=>typeof u==`number`&&u>0?u:!1,[u]),[x,S]=qu({prefixCls:y,style:e=>Hg(e,n??Gg,r??Gg),className:()=>B({[`${y}-rtl`]:s??g===`rtl`}),motion:()=>Ug(y),closable:{closeIcon:zg(y)},duration:b,getContainer:()=>a?.()||h?.()||document.body,maxCount:o,pauseOnHover:f,showProgress:p,onAllRemoved:c,renderNotifications:Yg,stack:l===!1?!1:{threshold:typeof l==`object`?l?.threshold:void 0,offset:8,gap:v.margin}}),[C,w]=el([_?.classNames,e?.classNames],[_?.styles,e?.styles],{props:e});return d.useImperativeHandle(t,()=>({...x,prefixCls:y,notification:_,classNames:C,styles:w})),S});function Zg(e){let t=d.useRef(null);ct(`Notification`);let{notification:n}=d.useContext(zt);return[d.useMemo(()=>{let r=r=>{if(!t.current)return;let{open:i,prefixCls:a,notification:o,classNames:s,styles:c}=t.current,l=o?.className||{},u=o?.style||{},f=`${a}-notice`,{title:p,message:m,description:h,icon:g,type:_,btn:v,actions:y,className:b,style:x,role:S=`alert`,closeIcon:C,closable:w,classNames:T={},styles:E={},...D}=r,O=p??m,k=y??v,A=zg(f,Wg(C,e,o)),[j,ee,,te]=Wc(zc({...e||{},...r}),zc(n),{closable:!0,closeIcon:A}),M=j?{onClose:w&&typeof w==`object`?w.onClose:void 0,closeIcon:ee,...te}:!1,N=$c(T,{props:r}),P=$c(E,{props:r}),ne=Jc(void 0,s,N),re=Xc(c,P);return i({placement:e?.placement??qg,...D,content:d.createElement(Vg,{prefixCls:f,icon:g,type:_,title:O,description:h,actions:k,role:S,classNames:ne,styles:re}),className:B({[`${f}-${_}`]:_},b,l,ne.root),style:{...u,...re.root,...x},closable:M})},i={open:r,destroy:e=>{e===void 0?t.current?.destroy():t.current?.close(e)}};return[`success`,`info`,`warning`,`error`].forEach(e=>{i[e]=t=>r({...t,type:e})}),i},[e,n]),d.createElement(Xg,{key:`notification-holder`,...e,ref:t})]}function Qg(e){return Zg(e)}var $g=d.createContext({}),e_=d.createContext({message:{},notification:{},modal:{}}),t_=Ao(`App`,e=>{let{componentCls:t,colorText:n,fontSize:r,lineHeight:i,fontFamily:a}=e;return{[t]:{color:n,fontSize:r,lineHeight:i,fontFamily:a,[`&${t}-rtl`]:{direction:`rtl`}}}},()=>({})),n_=e=>{let{prefixCls:t,children:n,className:r,rootClassName:i,message:a,notification:o,style:s,component:c=`div`}=e,{direction:l,getPrefixCls:u,className:f,style:p}=Ht(`app`),m=u(`app`,t),[h,g]=t_(m),_=B(h,m,r,i,g,{[`${m}-rtl`]:l===`rtl`}),v=(0,d.useContext)($g),y=d.useMemo(()=>({message:{...v.message,...a},notification:{...v.notification,...o}}),[a,o,v.message,v.notification]),[b,x]=ud(y.message),[S,C]=Qg(y.notification),[w,T]=Eg(),E=d.useMemo(()=>({message:b,notification:S,modal:w}),[b,S,w]);ct(`App`)(!(g&&c===!1),`usage`,"When using cssVar, ensure `component` is assigned a valid React component string.");let D=c===!1?d.Fragment:c,O={className:B(f,_),style:{...p,...s}};return d.createElement(e_.Provider,{value:E},d.createElement($g.Provider,{value:y},d.createElement(D,{...c===!1?void 0:O},T,x,C,n)))},r_=()=>d.useContext(e_),i_=n_;i_.useApp=r_;var a_=class extends Error{};a_.prototype.name=`InvalidTokenError`;function o_(e){return decodeURIComponent(atob(e).replace(/(.)/g,(e,t)=>{let n=t.charCodeAt(0).toString(16).toUpperCase();return n.length<2&&(n=`0`+n),`%`+n}))}function s_(e){let t=e.replace(/-/g,`+`).replace(/_/g,`/`);switch(t.length%4){case 0:break;case 2:t+=`==`;break;case 3:t+=`=`;break;default:throw Error(`base64 string is not of the correct length`)}try{return o_(t)}catch{return atob(t)}}function c_(e,t){if(typeof e!=`string`)throw new a_(`Invalid token specified: must be a string`);t||={};let n=t.header===!0?0:1,r=e.split(`.`)[n];if(typeof r!=`string`)throw new a_(`Invalid token specified: missing part #${n+1}`);let i;try{i=s_(r)}catch(e){throw new a_(`Invalid token specified: invalid base64 for part #${n+1} (${e.message})`)}try{return JSON.parse(i)}catch(e){throw new a_(`Invalid token specified: invalid json for part #${n+1} (${e.message})`)}}var l_={debug:()=>void 0,info:()=>void 0,warn:()=>void 0,error:()=>void 0},u_,d_,f_=(e=>(e[e.NONE=0]=`NONE`,e[e.ERROR=1]=`ERROR`,e[e.WARN=2]=`WARN`,e[e.INFO=3]=`INFO`,e[e.DEBUG=4]=`DEBUG`,e))(f_||{});(e=>{function t(){u_=3,d_=l_}e.reset=t;function n(e){if(!(0<=e&&e<=4))throw Error(`Invalid log level`);u_=e}e.setLevel=n;function r(e){d_=e}e.setLogger=r})(f_||={});var $=class e{constructor(e){this._name=e}debug(...t){u_>=4&&d_.debug(e._format(this._name,this._method),...t)}info(...t){u_>=3&&d_.info(e._format(this._name,this._method),...t)}warn(...t){u_>=2&&d_.warn(e._format(this._name,this._method),...t)}error(...t){u_>=1&&d_.error(e._format(this._name,this._method),...t)}throw(e){throw this.error(e),e}create(e){let t=Object.create(this);return t._method=e,t.debug(`begin`),t}static createStatic(t,n){let r=new e(`${t}.${n}`);return r.debug(`begin`),r}static _format(e,t){let n=`[${e}]`;return t?`${n} ${t}:`:n}static debug(t,...n){u_>=4&&d_.debug(e._format(t),...n)}static info(t,...n){u_>=3&&d_.info(e._format(t),...n)}static warn(t,...n){u_>=2&&d_.warn(e._format(t),...n)}static error(t,...n){u_>=1&&d_.error(e._format(t),...n)}};f_.reset();var p_=class{static decode(e){try{return c_(e)}catch(e){throw $.error(`JwtUtils.decode`,e),e}}static async generateSignedJwt(e,t,n){let r=`${__.encodeBase64Url(new TextEncoder().encode(JSON.stringify(e)))}.${__.encodeBase64Url(new TextEncoder().encode(JSON.stringify(t)))}`,i=await window.crypto.subtle.sign({name:`ECDSA`,hash:{name:`SHA-256`}},n,new TextEncoder().encode(r));return`${r}.${__.encodeBase64Url(new Uint8Array(i))}`}static async generateSignedJwtWithHmac(e,t,n){let r=`${__.encodeBase64Url(new TextEncoder().encode(JSON.stringify(e)))}.${__.encodeBase64Url(new TextEncoder().encode(JSON.stringify(t)))}`,i=await window.crypto.subtle.sign(`HMAC`,n,new TextEncoder().encode(r));return`${r}.${__.encodeBase64Url(new Uint8Array(i))}`}},m_=`10000000-1000-4000-8000-100000000000`,h_=e=>btoa([...new Uint8Array(e)].map(e=>String.fromCharCode(e)).join(``)),g_=class e{static _randomWord(){let e=new Uint32Array(1);return crypto.getRandomValues(e),e[0]}static generateUUIDv4(){return m_.replace(/[018]/g,t=>(t^e._randomWord()&15>>t/4).toString(16)).replace(/-/g,``)}static generateCodeVerifier(){return e.generateUUIDv4()+e.generateUUIDv4()+e.generateUUIDv4()}static async generateCodeChallenge(e){if(!crypto.subtle)throw Error(`Crypto.subtle is available only in secure contexts (HTTPS).`);try{let t=new TextEncoder().encode(e);return h_(await crypto.subtle.digest(`SHA-256`,t)).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}catch(e){throw $.error(`CryptoUtils.generateCodeChallenge`,e),e}}static generateBasicAuth(e,t){return h_(new TextEncoder().encode([e,t].join(`:`)))}static async hash(e,t){let n=new TextEncoder().encode(t),r=await crypto.subtle.digest(e,n);return new Uint8Array(r)}static async customCalculateJwkThumbprint(t){let n;switch(t.kty){case`RSA`:n={e:t.e,kty:t.kty,n:t.n};break;case`EC`:n={crv:t.crv,kty:t.kty,x:t.x,y:t.y};break;case`OKP`:n={crv:t.crv,kty:t.kty,x:t.x};break;case`oct`:n={crv:t.k,kty:t.kty};break;default:throw Error(`Unknown jwk type`)}let r=await e.hash(`SHA-256`,JSON.stringify(n));return e.encodeBase64Url(r)}static async generateDPoPProof({url:t,accessToken:n,httpMethod:r,keyPair:i,nonce:a}){let o,s,c={jti:window.crypto.randomUUID(),htm:r??`GET`,htu:t,iat:Math.floor(Date.now()/1e3)};n&&(o=await e.hash(`SHA-256`,n),s=e.encodeBase64Url(o),c.ath=s),a&&(c.nonce=a);try{let e=await crypto.subtle.exportKey(`jwk`,i.publicKey),t={alg:`ES256`,typ:`dpop+jwt`,jwk:{crv:e.crv,kty:e.kty,x:e.x,y:e.y}};return await p_.generateSignedJwt(t,c,i.privateKey)}catch(e){throw e instanceof TypeError?Error(`Error exporting dpop public key: ${e.message}`):e}}static async generateDPoPJkt(t){try{let n=await crypto.subtle.exportKey(`jwk`,t.publicKey);return await e.customCalculateJwkThumbprint(n)}catch(e){throw e instanceof TypeError?Error(`Could not retrieve dpop keys from storage: ${e.message}`):e}}static async generateDPoPKeys(){return await window.crypto.subtle.generateKey({name:`ECDSA`,namedCurve:`P-256`},!1,[`sign`,`verify`])}static async generateClientAssertionJwt(t,n,r,i=`HS256`){let a=Math.floor(Date.now()/1e3),o={alg:i,typ:`JWT`},s={iss:t,sub:t,aud:r,jti:e.generateUUIDv4(),exp:a+300,iat:a},c={HS256:`SHA-256`,HS384:`SHA-384`,HS512:`SHA-512`}[i];if(!c)throw Error(`Unsupported algorithm: ${i}. Supported algorithms are: HS256, HS384, HS512`);let l=new TextEncoder,u=await crypto.subtle.importKey(`raw`,l.encode(n),{name:`HMAC`,hash:c},!1,[`sign`]);return await p_.generateSignedJwtWithHmac(o,s,u)}};g_.encodeBase64Url=e=>h_(e).replace(/=/g,``).replace(/\+/g,`-`).replace(/\//g,`_`);var __=g_,v_=class{constructor(e){this._name=e,this._callbacks=[],this._logger=new $(`Event('${this._name}')`)}addHandler(e){return this._callbacks.push(e),()=>this.removeHandler(e)}removeHandler(e){let t=this._callbacks.lastIndexOf(e);t>=0&&this._callbacks.splice(t,1)}async raise(...e){this._logger.debug(`raise:`,...e);for(let t of this._callbacks)await t(...e)}},y_=class{static center({...e}){return e.width??=[800,720,600,480].find(e=>e<=window.outerWidth/1.618)??360,e.left??=Math.max(0,Math.round(window.screenX+(window.outerWidth-e.width)/2)),e.height!=null&&(e.top??=Math.max(0,Math.round(window.screenY+(window.outerHeight-e.height)/2))),e}static serialize(e){return Object.entries(e).filter(([,e])=>e!=null).map(([e,t])=>`${e}=${typeof t==`boolean`?t?`yes`:`no`:t}`).join(`,`)}},b_=class e extends v_{constructor(){super(...arguments),this._logger=new $(`Timer('${this._name}')`),this._timerHandle=null,this._expiration=0,this._callback=()=>{let t=this._expiration-e.getEpochTime();this._logger.debug(`timer completes in`,t),this._expiration<=e.getEpochTime()&&(this.cancel(),super.raise())}}static getEpochTime(){return Math.floor(Date.now()/1e3)}init(t){let n=this._logger.create(`init`);t=Math.max(Math.floor(t),1);let r=e.getEpochTime()+t;if(this.expiration===r&&this._timerHandle){n.debug(`skipping since already initialized for expiration at`,this.expiration);return}this.cancel(),n.debug(`using duration`,t),this._expiration=r;let i=Math.min(t,5);this._timerHandle=setInterval(this._callback,i*1e3)}get expiration(){return this._expiration}cancel(){this._logger.create(`cancel`),this._timerHandle&&=(clearInterval(this._timerHandle),null)}},x_=class{static readParams(e,t=`query`){if(!e)throw TypeError(`Invalid URL`);let n=new URL(e,`http://127.0.0.1`)[t===`fragment`?`hash`:`search`];return new URLSearchParams(n.slice(1))}},S_=`;`,C_=class extends Error{constructor(e,t){if(super(e.error_description||e.error||``),this.form=t,this.name=`ErrorResponse`,!e.error)throw $.error(`ErrorResponse`,`No error passed`),Error(`No error passed`);this.error=e.error,this.error_description=e.error_description??null,this.error_uri=e.error_uri??null,this.state=e.userState,this.session_state=e.session_state??null,this.url_state=e.url_state}},w_=class extends Error{constructor(e){super(e),this.name=`ErrorTimeout`}},T_=class{constructor(e){this._logger=new $(`AccessTokenEvents`),this._expiringTimer=new b_(`Access token expiring`),this._expiredTimer=new b_(`Access token expired`),this._expiringNotificationTimeInSeconds=e.expiringNotificationTimeInSeconds}async load(e){let t=this._logger.create(`load`);if(e.access_token&&e.expires_in!==void 0){let n=e.expires_in;if(t.debug(`access token present, remaining duration:`,n),n>0){let e=n-this._expiringNotificationTimeInSeconds;e<=0&&(e=1),t.debug(`registering expiring timer, raising in`,e,`seconds`),this._expiringTimer.init(e)}else t.debug(`canceling existing expiring timer because we're past expiration.`),this._expiringTimer.cancel();let r=n+1;t.debug(`registering expired timer, raising in`,r,`seconds`),this._expiredTimer.init(r)}else this._expiringTimer.cancel(),this._expiredTimer.cancel()}async unload(){this._logger.debug(`unload: canceling existing access token timers`),this._expiringTimer.cancel(),this._expiredTimer.cancel()}addAccessTokenExpiring(e){return this._expiringTimer.addHandler(e)}removeAccessTokenExpiring(e){this._expiringTimer.removeHandler(e)}addAccessTokenExpired(e){return this._expiredTimer.addHandler(e)}removeAccessTokenExpired(e){this._expiredTimer.removeHandler(e)}},E_=class{constructor(e,t,n,r,i){this._callback=e,this._client_id=t,this._intervalInSeconds=r,this._stopOnError=i,this._logger=new $(`CheckSessionIFrame`),this._timer=null,this._session_state=null,this._message=e=>{e.origin===this._frame_origin&&e.source===this._frame.contentWindow&&(e.data===`error`?(this._logger.error(`error message from check session op iframe`),this._stopOnError&&this.stop()):e.data===`changed`?(this._logger.debug(`changed message from check session op iframe`),this.stop(),this._callback()):this._logger.debug(e.data+` message from check session op iframe`))};let a=new URL(n);this._frame_origin=a.origin,this._frame=window.document.createElement(`iframe`),this._frame.style.visibility=`hidden`,this._frame.style.position=`fixed`,this._frame.style.left=`-1000px`,this._frame.style.top=`0`,this._frame.width=`0`,this._frame.height=`0`,this._frame.src=a.href}load(){return new Promise(e=>{this._frame.onload=()=>{e()},window.document.body.appendChild(this._frame),window.addEventListener(`message`,this._message,!1)})}start(e){if(this._session_state===e)return;this._logger.create(`start`),this.stop(),this._session_state=e;let t=()=>{!this._frame.contentWindow||!this._session_state||this._frame.contentWindow.postMessage(this._client_id+` `+this._session_state,this._frame_origin)};t(),this._timer=setInterval(t,this._intervalInSeconds*1e3)}stop(){this._logger.create(`stop`),this._session_state=null,this._timer&&=(clearInterval(this._timer),null)}},D_=class{constructor(){this._logger=new $(`InMemoryWebStorage`),this._data={}}clear(){this._logger.create(`clear`),this._data={}}getItem(e){return this._logger.create(`getItem('${e}')`),this._data[e]}setItem(e,t){this._logger.create(`setItem('${e}')`),this._data[e]=t}removeItem(e){this._logger.create(`removeItem('${e}')`),delete this._data[e]}get length(){return Object.getOwnPropertyNames(this._data).length}key(e){return Object.getOwnPropertyNames(this._data)[e]}},O_=class extends Error{constructor(e,t){super(t),this.name=`ErrorDPoPNonce`,this.nonce=e}},k_=class{constructor(e=[],t=null,n={}){this._jwtHandler=t,this._extraHeaders=n,this._logger=new $(`JsonService`),this._contentTypes=[],this._contentTypes.push(...e,`application/json`),t&&this._contentTypes.push(`application/jwt`)}async fetchWithTimeout(e,t={}){let{timeoutInSeconds:n,...r}=t;if(!n)return await fetch(e,r);let i=new AbortController,a=setTimeout(()=>i.abort(),n*1e3);try{return await fetch(e,{...t,signal:i.signal})}catch(e){throw e instanceof DOMException&&e.name===`AbortError`?new w_(`Network timed out`):e}finally{clearTimeout(a)}}async getJson(e,{token:t,credentials:n,timeoutInSeconds:r}={}){let i=this._logger.create(`getJson`),a={Accept:this._contentTypes.join(`, `)};t&&(i.debug(`token passed, setting Authorization header`),a.Authorization=`Bearer `+t),this._appendExtraHeaders(a);let o;try{i.debug(`url:`,e),o=await this.fetchWithTimeout(e,{method:`GET`,headers:a,timeoutInSeconds:r,credentials:n})}catch(e){throw i.error(`Network Error`),e}i.debug(`HTTP response received, status`,o.status);let s=o.headers.get(`Content-Type`);if(s&&!this._contentTypes.find(e=>s.startsWith(e))&&i.throw(Error(`Invalid response Content-Type: ${s??`undefined`}, from URL: ${e}`)),o.ok&&this._jwtHandler&&s?.startsWith(`application/jwt`))return await this._jwtHandler(await o.text());let c;try{c=await o.json()}catch(e){throw i.error(`Error parsing JSON response`,e),o.ok?e:Error(`${o.statusText} (${o.status})`)}if(!o.ok)throw i.error(`Error from server:`,c),c.error?new C_(c):Error(`${o.statusText} (${o.status}): ${JSON.stringify(c)}`);return c}async postForm(e,{body:t,basicAuth:n,timeoutInSeconds:r,initCredentials:i,extraHeaders:a}){let o=this._logger.create(`postForm`),s={Accept:this._contentTypes.join(`, `),"Content-Type":`application/x-www-form-urlencoded`,...a};n!==void 0&&(s.Authorization=`Basic `+n),this._appendExtraHeaders(s);let c;try{o.debug(`url:`,e),c=await this.fetchWithTimeout(e,{method:`POST`,headers:s,body:t,timeoutInSeconds:r,credentials:i})}catch(e){throw o.error(`Network error`),e}o.debug(`HTTP response received, status`,c.status);let l=c.headers.get(`Content-Type`);if(l&&!this._contentTypes.find(e=>l.startsWith(e)))throw Error(`Invalid response Content-Type: ${l??`undefined`}, from URL: ${e}`);let u=await c.text(),d={};if(u)try{d=JSON.parse(u)}catch(e){throw o.error(`Error parsing JSON response`,e),c.ok?e:Error(`${c.statusText} (${c.status})`)}if(!c.ok)throw o.error(`Error from server:`,d),c.headers.has(`dpop-nonce`)?new O_(c.headers.get(`dpop-nonce`),`${JSON.stringify(d)}`):d.error?new C_(d,t):Error(`${c.statusText} (${c.status}): ${JSON.stringify(d)}`);return d}_appendExtraHeaders(e){let t=this._logger.create(`appendExtraHeaders`),n=Object.keys(this._extraHeaders),r=[`accept`,`content-type`],i=[`authorization`];n.length!==0&&n.forEach(n=>{if(r.includes(n.toLocaleLowerCase())){t.warn(`Protected header could not be set`,n,r);return}if(i.includes(n.toLocaleLowerCase())&&Object.keys(e).includes(n)){t.warn(`Header could not be overridden`,n,i);return}let a=typeof this._extraHeaders[n]==`function`?this._extraHeaders[n]():this._extraHeaders[n];a&&a!==``&&(e[n]=a)})}},A_=class{constructor(e){this._settings=e,this._logger=new $(`MetadataService`),this._signingKeys=null,this._metadata=null,this._metadataUrl=this._settings.metadataUrl,this._jsonService=new k_([`application/jwk-set+json`],null,this._settings.extraHeaders),this._settings.signingKeys&&(this._logger.debug(`using signingKeys from settings`),this._signingKeys=this._settings.signingKeys),this._settings.metadata&&(this._logger.debug(`using metadata from settings`),this._metadata=this._settings.metadata),this._settings.fetchRequestCredentials&&(this._logger.debug(`using fetchRequestCredentials from settings`),this._fetchRequestCredentials=this._settings.fetchRequestCredentials)}resetSigningKeys(){this._signingKeys=null}async getMetadata(){let e=this._logger.create(`getMetadata`);if(this._metadata)return e.debug(`using cached values`),this._metadata;if(!this._metadataUrl)throw e.throw(Error(`No authority or metadataUrl configured on settings`)),null;e.debug(`getting metadata from`,this._metadataUrl);let t=await this._jsonService.getJson(this._metadataUrl,{credentials:this._fetchRequestCredentials,timeoutInSeconds:this._settings.requestTimeoutInSeconds});return e.debug(`merging remote JSON with seed metadata`),this._metadata=Object.assign({},t,this._settings.metadataSeed),this._metadata}getIssuer(){return this._getMetadataProperty(`issuer`)}getAuthorizationEndpoint(){return this._getMetadataProperty(`authorization_endpoint`)}getUserInfoEndpoint(){return this._getMetadataProperty(`userinfo_endpoint`)}getTokenEndpoint(e=!0){return this._getMetadataProperty(`token_endpoint`,e)}getCheckSessionIframe(){return this._getMetadataProperty(`check_session_iframe`,!0)}getEndSessionEndpoint(){return this._getMetadataProperty(`end_session_endpoint`,!0)}getRevocationEndpoint(e=!0){return this._getMetadataProperty(`revocation_endpoint`,e)}getKeysEndpoint(e=!0){return this._getMetadataProperty(`jwks_uri`,e)}async _getMetadataProperty(e,t=!1){let n=this._logger.create(`_getMetadataProperty('${e}')`),r=await this.getMetadata();if(n.debug(`resolved`),r[e]===void 0){if(t===!0){n.warn(`Metadata does not contain optional property`);return}n.throw(Error(`Metadata does not contain property `+e))}return r[e]}async getSigningKeys(){let e=this._logger.create(`getSigningKeys`);if(this._signingKeys)return e.debug(`returning signingKeys from cache`),this._signingKeys;let t=await this.getKeysEndpoint(!1);e.debug(`got jwks_uri`,t);let n=await this._jsonService.getJson(t,{timeoutInSeconds:this._settings.requestTimeoutInSeconds});if(e.debug(`got key set`,n),!Array.isArray(n.keys))throw e.throw(Error(`Missing keys on keyset`)),null;return this._signingKeys=n.keys,this._signingKeys}},j_=class{constructor({prefix:e=`oidc.`,store:t=localStorage}={}){this._logger=new $(`WebStorageStateStore`),this._store=t,this._prefix=e}async set(e,t){this._logger.create(`set('${e}')`),e=this._prefix+e,await this._store.setItem(e,t)}async get(e){return this._logger.create(`get('${e}')`),e=this._prefix+e,await this._store.getItem(e)}async remove(e){this._logger.create(`remove('${e}')`),e=this._prefix+e;let t=await this._store.getItem(e);return await this._store.removeItem(e),t}async getAllKeys(){this._logger.create(`getAllKeys`);let e=await this._store.length,t=[];for(let n=0;n{let t=this._logger.create(`_getClaimsFromJwt`);try{let n=p_.decode(e);return t.debug(`JWT decoding successful`),n}catch(e){throw t.error(`Error parsing JWT response`),e}},this._jsonService=new k_(void 0,this._getClaimsFromJwt,this._settings.extraHeaders)}async getClaims(e){let t=this._logger.create(`getClaims`);e||this._logger.throw(Error(`No token passed`));let n=await this._metadataService.getUserInfoEndpoint();t.debug(`got userinfo url`,n);let r=await this._jsonService.getJson(n,{token:e,credentials:this._settings.fetchRequestCredentials,timeoutInSeconds:this._settings.requestTimeoutInSeconds});return t.debug(`got claims`,r),r}},R_=class{constructor(e,t){this._settings=e,this._metadataService=t,this._logger=new $(`TokenClient`),this._jsonService=new k_(this._settings.revokeTokenAdditionalContentTypes,null,this._settings.extraHeaders)}async exchangeCode({grant_type:e=`authorization_code`,redirect_uri:t=this._settings.redirect_uri,client_id:n=this._settings.client_id,client_secret:r=this._settings.client_secret,extraHeaders:i,...a}){let o=this._logger.create(`exchangeCode`);n||o.throw(Error(`A client_id is required`)),t||o.throw(Error(`A redirect_uri is required`)),a.code||o.throw(Error(`A code is required`));let s=new URLSearchParams({grant_type:e,redirect_uri:t});for(let[e,t]of Object.entries(a))t!=null&&s.set(e,t);if((this._settings.client_authentication===`client_secret_basic`||this._settings.client_authentication===`client_secret_jwt`)&&r==null)throw o.throw(Error(`A client_secret is required`)),null;let c,l=await this._metadataService.getTokenEndpoint(!1);switch(this._settings.client_authentication){case`client_secret_basic`:c=__.generateBasicAuth(n,r);break;case`client_secret_post`:s.append(`client_id`,n),r&&s.append(`client_secret`,r);break;case`client_secret_jwt`:{let e=await __.generateClientAssertionJwt(n,r,l,this._settings.token_endpoint_auth_signing_alg);s.append(`client_id`,n),s.append(`client_assertion_type`,`urn:ietf:params:oauth:client-assertion-type:jwt-bearer`),s.append(`client_assertion`,e);break}}o.debug(`got token endpoint`);let u=await this._jsonService.postForm(l,{body:s,basicAuth:c,timeoutInSeconds:this._settings.requestTimeoutInSeconds,initCredentials:this._settings.fetchRequestCredentials,extraHeaders:i});return o.debug(`got response`),u}async exchangeCredentials({grant_type:e=`password`,client_id:t=this._settings.client_id,client_secret:n=this._settings.client_secret,scope:r=this._settings.scope,...i}){let a=this._logger.create(`exchangeCredentials`);t||a.throw(Error(`A client_id is required`));let o=new URLSearchParams({grant_type:e});this._settings.omitScopeWhenRequesting||o.set(`scope`,r);for(let[e,t]of Object.entries(i))t!=null&&o.set(e,t);if((this._settings.client_authentication===`client_secret_basic`||this._settings.client_authentication===`client_secret_jwt`)&&n==null)throw a.throw(Error(`A client_secret is required`)),null;let s,c=await this._metadataService.getTokenEndpoint(!1);switch(this._settings.client_authentication){case`client_secret_basic`:s=__.generateBasicAuth(t,n);break;case`client_secret_post`:o.append(`client_id`,t),n&&o.append(`client_secret`,n);break;case`client_secret_jwt`:{let e=await __.generateClientAssertionJwt(t,n,c,this._settings.token_endpoint_auth_signing_alg);o.append(`client_id`,t),o.append(`client_assertion_type`,`urn:ietf:params:oauth:client-assertion-type:jwt-bearer`),o.append(`client_assertion`,e);break}}a.debug(`got token endpoint`);let l=await this._jsonService.postForm(c,{body:o,basicAuth:s,timeoutInSeconds:this._settings.requestTimeoutInSeconds,initCredentials:this._settings.fetchRequestCredentials});return a.debug(`got response`),l}async exchangeRefreshToken({grant_type:e=`refresh_token`,client_id:t=this._settings.client_id,client_secret:n=this._settings.client_secret,timeoutInSeconds:r,extraHeaders:i,...a}){let o=this._logger.create(`exchangeRefreshToken`);t||o.throw(Error(`A client_id is required`)),a.refresh_token||o.throw(Error(`A refresh_token is required`));let s=new URLSearchParams({grant_type:e});for(let[e,t]of Object.entries(a))Array.isArray(t)?t.forEach(t=>s.append(e,t)):t!=null&&s.set(e,t);if((this._settings.client_authentication===`client_secret_basic`||this._settings.client_authentication===`client_secret_jwt`)&&n==null)throw o.throw(Error(`A client_secret is required`)),null;let c,l=await this._metadataService.getTokenEndpoint(!1);switch(this._settings.client_authentication){case`client_secret_basic`:c=__.generateBasicAuth(t,n);break;case`client_secret_post`:s.append(`client_id`,t),n&&s.append(`client_secret`,n);break;case`client_secret_jwt`:{let e=await __.generateClientAssertionJwt(t,n,l,this._settings.token_endpoint_auth_signing_alg);s.append(`client_id`,t),s.append(`client_assertion_type`,`urn:ietf:params:oauth:client-assertion-type:jwt-bearer`),s.append(`client_assertion`,e);break}}o.debug(`got token endpoint`);let u=await this._jsonService.postForm(l,{body:s,basicAuth:c,timeoutInSeconds:r,initCredentials:this._settings.fetchRequestCredentials,extraHeaders:i});return o.debug(`got response`),u}async revoke(e){let t=this._logger.create(`revoke`);e.token||t.throw(Error(`A token is required`));let n=await this._metadataService.getRevocationEndpoint(!1);t.debug(`got revocation endpoint, revoking ${e.token_type_hint??`default token type`}`);let r=new URLSearchParams;for(let[t,n]of Object.entries(e))n!=null&&r.set(t,n);r.set(`client_id`,this._settings.client_id),this._settings.client_secret&&r.set(`client_secret`,this._settings.client_secret),await this._jsonService.postForm(n,{body:r,timeoutInSeconds:this._settings.requestTimeoutInSeconds}),t.debug(`got response`)}},z_=class{constructor(e,t,n){this._settings=e,this._metadataService=t,this._claimsService=n,this._logger=new $(`ResponseValidator`),this._userInfoService=new L_(this._settings,this._metadataService),this._tokenClient=new R_(this._settings,this._metadataService)}async validateSigninResponse(e,t,n){let r=this._logger.create(`validateSigninResponse`);this._processSigninState(e,t),r.debug(`state processed`),await this._processCode(e,t,n),r.debug(`code processed`),e.isOpenId&&this._validateIdTokenAttributes(e),r.debug(`tokens validated`),await this._processClaims(e,t?.skipUserInfo,e.isOpenId),r.debug(`claims processed`)}async validateCredentialsResponse(e,t){let n=this._logger.create(`validateCredentialsResponse`),r=e.isOpenId&&!!e.id_token;r&&this._validateIdTokenAttributes(e),n.debug(`tokens validated`),await this._processClaims(e,t,r),n.debug(`claims processed`)}async validateRefreshResponse(e,t){let n=this._logger.create(`validateRefreshResponse`);e.userState=t.data,e.session_state??=t.session_state,e.scope??=t.scope,e.isOpenId&&e.id_token&&(this._validateIdTokenAttributes(e,t.id_token),n.debug(`ID Token validated`)),e.id_token||(e.id_token=t.id_token,e.profile=t.profile);let r=e.isOpenId&&!!e.id_token;await this._processClaims(e,!1,r),n.debug(`claims processed`)}validateSignoutResponse(e,t){let n=this._logger.create(`validateSignoutResponse`);if(t.id!==e.state&&n.throw(Error(`State does not match`)),n.debug(`state validated`),e.userState=t.data,e.error)throw n.warn(`Response was error`,e.error),new C_(e)}_processSigninState(e,t){let n=this._logger.create(`_processSigninState`);if(t.id!==e.state&&n.throw(Error(`State does not match`)),t.client_id||n.throw(Error(`No client_id on state`)),t.authority||n.throw(Error(`No authority on state`)),this._settings.authority!==t.authority&&n.throw(Error(`authority mismatch on settings vs. signin state`)),this._settings.client_id&&this._settings.client_id!==t.client_id&&n.throw(Error(`client_id mismatch on settings vs. signin state`)),n.debug(`state validated`),e.userState=t.data,e.url_state=t.url_state,e.scope??=t.scope,e.error)throw n.warn(`Response was error`,e.error),new C_(e);t.code_verifier&&!e.code&&n.throw(Error(`Expected code in response`))}async _processClaims(e,t=!1,n=!0){let r=this._logger.create(`_processClaims`);if(e.profile=this._claimsService.filterProtocolClaims(e.profile),t||!this._settings.loadUserInfo||!e.access_token){r.debug(`not loading user info`);return}r.debug(`loading user info`);let i=await this._userInfoService.getClaims(e.access_token);r.debug(`user info claims received from user info endpoint`),n&&i.sub!==e.profile.sub&&r.throw(Error(`subject from UserInfo response does not match subject in ID Token`)),e.profile=this._claimsService.mergeClaims(e.profile,this._claimsService.filterProtocolClaims(i)),r.debug(`user info claims received, updated profile:`,e.profile)}async _processCode(e,t,n){let r=this._logger.create(`_processCode`);if(e.code){r.debug(`Validating code`);let i=await this._tokenClient.exchangeCode({client_id:t.client_id,client_secret:t.client_secret,code:e.code,redirect_uri:t.redirect_uri,code_verifier:t.code_verifier,extraHeaders:n,...t.extraTokenParams});Object.assign(e,i)}else r.debug(`No code to process`)}_validateIdTokenAttributes(e,t){let n=this._logger.create(`_validateIdTokenAttributes`);n.debug(`decoding ID Token JWT`);let r=p_.decode(e.id_token??``);if(r.sub||n.throw(Error(`ID Token is missing a subject claim`)),t){let e=p_.decode(t);r.sub!==e.sub&&n.throw(Error(`sub in id_token does not match current sub`)),r.auth_time&&r.auth_time!==e.auth_time&&n.throw(Error(`auth_time in id_token does not match original auth_time`)),r.azp&&r.azp!==e.azp&&n.throw(Error(`azp in id_token does not match original azp`)),!r.azp&&e.azp&&n.throw(Error(`azp not in id_token, but present in original id_token`))}e.profile=r}},B_=class e{constructor(e){this.id=e.id||__.generateUUIDv4(),this.data=e.data,e.created&&e.created>0?this.created=e.created:this.created=b_.getEpochTime(),this.request_type=e.request_type,this.url_state=e.url_state}toStorageString(){return new $(`State`).create(`toStorageString`),JSON.stringify({id:this.id,data:this.data,created:this.created,request_type:this.request_type,url_state:this.url_state})}static fromStorageString(t){return $.createStatic(`State`,`fromStorageString`),Promise.resolve(new e(JSON.parse(t)))}static async clearStaleState(t,n){let r=$.createStatic(`State`,`clearStaleState`),i=b_.getEpochTime()-n,a=await t.getAllKeys();r.debug(`got keys`,a);for(let n=0;nS.searchParams.append(`resource`,e));for(let[e,t]of Object.entries({response_mode:c,...b,...h}))t!=null&&S.searchParams.append(e,t.toString());return new e({url:S.href,state:x})}};H_._logger=new $(`SigninRequest`);var U_=H_,W_=`openid`,G_=class{constructor(e){if(this.access_token=``,this.token_type=``,this.profile={},this.state=e.get(`state`),this.session_state=e.get(`session_state`),this.state){let e=decodeURIComponent(this.state).split(S_);this.state=e[0],e.length>1&&(this.url_state=e.slice(1).join(S_))}this.error=e.get(`error`),this.error_description=e.get(`error_description`),this.error_uri=e.get(`error_uri`),this.code=e.get(`code`)}get expires_in(){if(this.expires_at!==void 0)return this.expires_at-b_.getEpochTime()}set expires_in(e){typeof e==`string`&&(e=Number(e)),e!==void 0&&e>=0&&(this.expires_at=Math.floor(e)+b_.getEpochTime())}get isOpenId(){return this.scope?.split(` `).includes(W_)||!!this.id_token}},K_=class{constructor({url:e,state_data:t,id_token_hint:n,post_logout_redirect_uri:r,extraQueryParams:i,request_type:a,client_id:o,url_state:s}){if(this._logger=new $(`SignoutRequest`),!e)throw this._logger.error(`ctor: No url passed`),Error(`url`);let c=new URL(e);if(n&&c.searchParams.append(`id_token_hint`,n),o&&c.searchParams.append(`client_id`,o),r&&(c.searchParams.append(`post_logout_redirect_uri`,r),t||s)){this.state=new B_({data:t,request_type:a,url_state:s});let e=this.state.id;s&&(e=`${e}${S_}${s}`),c.searchParams.append(`state`,e)}for(let[e,t]of Object.entries({...i}))t!=null&&c.searchParams.append(e,t.toString());this.url=c.href}},q_=class{constructor(e){if(this.state=e.get(`state`),this.state){let e=decodeURIComponent(this.state).split(S_);this.state=e[0],e.length>1&&(this.url_state=e.slice(1).join(S_))}this.error=e.get(`error`),this.error_description=e.get(`error_description`),this.error_uri=e.get(`error_uri`)}},J_=[`nbf`,`jti`,`auth_time`,`nonce`,`acr`,`amr`,`azp`,`at_hash`],Y_=[`sub`,`iss`,`aud`,`exp`,`iat`],X_=class{constructor(e){this._settings=e,this._logger=new $(`ClaimsService`)}filterProtocolClaims(e){let t={...e};if(this._settings.filterProtocolClaims){let e;e=Array.isArray(this._settings.filterProtocolClaims)?this._settings.filterProtocolClaims:J_;for(let n of e)Y_.includes(n)||delete t[n]}return t}mergeClaims(e,t){let n={...e};for(let[e,r]of Object.entries(t))if(n[e]!==r)if(Array.isArray(n[e])||Array.isArray(r))if(this._settings.mergeClaimsStrategy.array==`replace`)n[e]=r;else{let t=Array.isArray(n[e])?n[e]:[n[e]];for(let e of Array.isArray(r)?r:[r])t.includes(e)||t.push(e);n[e]=t}else typeof n[e]==`object`&&typeof r==`object`?n[e]=this.mergeClaims(n[e],r):n[e]=r;return n}},Z_=class{constructor(e,t){this.keys=e,this.nonce=t}},Q_=class{constructor(e,t){this._logger=new $(`OidcClient`),this.settings=e instanceof I_?e:new I_(e),this.metadataService=t??new A_(this.settings),this._claimsService=new X_(this.settings),this._validator=new z_(this.settings,this.metadataService,this._claimsService),this._tokenClient=new R_(this.settings,this.metadataService)}async createSigninRequest({state:e,request:t,request_uri:n,request_type:r,id_token_hint:i,login_hint:a,skipUserInfo:o,nonce:s,url_state:c,response_type:l=this.settings.response_type,scope:u=this.settings.scope,redirect_uri:d=this.settings.redirect_uri,prompt:f=this.settings.prompt,display:p=this.settings.display,max_age:m=this.settings.max_age,ui_locales:h=this.settings.ui_locales,acr_values:g=this.settings.acr_values,resource:_=this.settings.resource,response_mode:v=this.settings.response_mode,extraQueryParams:y=this.settings.extraQueryParams,extraTokenParams:b=this.settings.extraTokenParams,dpopJkt:x,omitScopeWhenRequesting:S=this.settings.omitScopeWhenRequesting}){let C=this._logger.create(`createSigninRequest`);if(l!==`code`)throw Error(`Only the Authorization Code flow (with PKCE) is supported`);let w=await this.metadataService.getAuthorizationEndpoint();C.debug(`Received authorization endpoint`,w);let T=await U_.create({url:w,authority:this.settings.authority,client_id:this.settings.client_id,redirect_uri:d,response_type:l,scope:u,state_data:e,url_state:c,prompt:f,display:p,max_age:m,ui_locales:h,id_token_hint:i,login_hint:a,acr_values:g,dpopJkt:x,resource:_,request:t,request_uri:n,extraQueryParams:y,extraTokenParams:b,request_type:r,response_mode:v,client_secret:this.settings.client_secret,skipUserInfo:o,nonce:s,disablePKCE:this.settings.disablePKCE,omitScopeWhenRequesting:S});await this.clearStaleState();let E=T.state;return await this.settings.stateStore.set(E.id,E.toStorageString()),T}async readSigninResponseState(e,t=!1){let n=this._logger.create(`readSigninResponseState`),r=new G_(x_.readParams(e,this.settings.response_mode));if(!r.state)throw n.throw(Error(`No state in response`)),null;let i=await this.settings.stateStore[t?`remove`:`get`](r.state);if(!i)throw n.throw(Error(`No matching state found in storage`)),null;return{state:await V_.fromStorageString(i),response:r}}async processSigninResponse(e,t,n=!0){let r=this._logger.create(`processSigninResponse`),{state:i,response:a}=await this.readSigninResponseState(e,n);if(r.debug(`received state from storage; validating response`),this.settings.dpop&&this.settings.dpop.store){let e=await this.getDpopProof(this.settings.dpop.store);t={...t,DPoP:e}}try{await this._validator.validateSigninResponse(a,i,t)}catch(e){if(e instanceof O_&&this.settings.dpop){let n=await this.getDpopProof(this.settings.dpop.store,e.nonce);t.DPoP=n,await this._validator.validateSigninResponse(a,i,t)}else throw e}return a}async getDpopProof(e,t){let n,r;return(await e.getAllKeys()).includes(this.settings.client_id)?(r=await e.get(this.settings.client_id),r.nonce!==t&&t&&(r.nonce=t,await e.set(this.settings.client_id,r))):(n=await __.generateDPoPKeys(),r=new Z_(n,t),await e.set(this.settings.client_id,r)),await __.generateDPoPProof({url:await this.metadataService.getTokenEndpoint(!1),httpMethod:`POST`,keyPair:r.keys,nonce:r.nonce})}async processResourceOwnerPasswordCredentials({username:e,password:t,skipUserInfo:n=!1,extraTokenParams:r={}}){let i=await this._tokenClient.exchangeCredentials({username:e,password:t,...r}),a=new G_(new URLSearchParams);return Object.assign(a,i),await this._validator.validateCredentialsResponse(a,n),a}async useRefreshToken({state:e,redirect_uri:t,resource:n,timeoutInSeconds:r,extraHeaders:i,extraTokenParams:a}){let o=this._logger.create(`useRefreshToken`),s;if(this.settings.refreshTokenAllowedScope===void 0)s=e.scope;else{let t=this.settings.refreshTokenAllowedScope.split(` `);s=(e.scope?.split(` `)||[]).filter(e=>t.includes(e)).join(` `)}if(this.settings.dpop&&this.settings.dpop.store){let e=await this.getDpopProof(this.settings.dpop.store);i={...i,DPoP:e}}let c;try{c=await this._tokenClient.exchangeRefreshToken({refresh_token:e.refresh_token,scope:s,redirect_uri:t,resource:n,timeoutInSeconds:r,extraHeaders:i,...a})}catch(o){if(o instanceof O_&&this.settings.dpop)i.DPoP=await this.getDpopProof(this.settings.dpop.store,o.nonce),c=await this._tokenClient.exchangeRefreshToken({refresh_token:e.refresh_token,scope:s,redirect_uri:t,resource:n,timeoutInSeconds:r,extraHeaders:i,...a});else throw o}let l=new G_(new URLSearchParams);return Object.assign(l,c),o.debug(`validating response`,l),await this._validator.validateRefreshResponse(l,{...e,scope:s}),l}async createSignoutRequest({state:e,id_token_hint:t,client_id:n,request_type:r,url_state:i,post_logout_redirect_uri:a=this.settings.post_logout_redirect_uri,extraQueryParams:o=this.settings.extraQueryParams}={}){let s=this._logger.create(`createSignoutRequest`),c=await this.metadataService.getEndSessionEndpoint();if(!c)throw s.throw(Error(`No end session endpoint`)),null;s.debug(`Received end session endpoint`,c),!n&&a&&!t&&(n=this.settings.client_id);let l=new K_({url:c,id_token_hint:t,client_id:n,post_logout_redirect_uri:a,state_data:e,extraQueryParams:o,request_type:r,url_state:i});await this.clearStaleState();let u=l.state;return u&&(s.debug(`Signout request has state to persist`),await this.settings.stateStore.set(u.id,u.toStorageString())),l}async readSignoutResponseState(e,t=!1){let n=this._logger.create(`readSignoutResponseState`),r=new q_(x_.readParams(e,this.settings.response_mode));if(!r.state){if(n.debug(`No state in response`),r.error)throw n.warn(`Response was error:`,r.error),new C_(r);return{state:void 0,response:r}}let i=await this.settings.stateStore[t?`remove`:`get`](r.state);if(!i)throw n.throw(Error(`No matching state found in storage`)),null;return{state:await B_.fromStorageString(i),response:r}}async processSignoutResponse(e){let t=this._logger.create(`processSignoutResponse`),{state:n,response:r}=await this.readSignoutResponseState(e,!0);return n?(t.debug(`Received state from storage; validating response`),this._validator.validateSignoutResponse(r,n)):t.debug(`No state from storage; skipping response validation`),r}clearStaleState(){return this._logger.create(`clearStaleState`),B_.clearStaleState(this.settings.stateStore,this.settings.staleStateAgeInSeconds)}async revokeToken(e,t){return this._logger.create(`revokeToken`),await this._tokenClient.revoke({token:e,token_type_hint:t})}},$_=class{constructor(e){this._userManager=e,this._logger=new $(`SessionMonitor`),this._start=async e=>{let t=e.session_state;if(!t)return;let n=this._logger.create(`_start`);if(e.profile?(this._sub=e.profile.sub,n.debug(`session_state`,t,`, sub`,this._sub)):(this._sub=void 0,n.debug(`session_state`,t,`, anonymous user`)),this._checkSessionIFrame){this._checkSessionIFrame.start(t);return}try{let e=await this._userManager.metadataService.getCheckSessionIframe();if(e){n.debug(`initializing check session iframe`);let r=this._userManager.settings.client_id,i=this._userManager.settings.checkSessionIntervalInSeconds,a=this._userManager.settings.stopCheckSessionOnError,o=new E_(this._callback,r,e,i,a);await o.load(),this._checkSessionIFrame=o,o.start(t)}else n.warn(`no check session iframe found in the metadata`)}catch(e){n.error(`Error from getCheckSessionIframe:`,e instanceof Error?e.message:e)}},this._stop=()=>{let e=this._logger.create(`_stop`);if(this._sub=void 0,this._checkSessionIFrame&&this._checkSessionIFrame.stop(),this._userManager.settings.monitorAnonymousSession){let t=setInterval(async()=>{clearInterval(t);try{let e=await this._userManager.querySessionStatus();if(e){let t={session_state:e.session_state,profile:e.sub?{sub:e.sub}:null};this._start(t)}}catch(t){e.error(`error from querySessionStatus`,t instanceof Error?t.message:t)}},1e3)}},this._callback=async()=>{let e=this._logger.create(`_callback`);try{let t=await this._userManager.querySessionStatus(),n=!0;t&&this._checkSessionIFrame?t.sub===this._sub?(n=!1,this._checkSessionIFrame.start(t.session_state),e.debug(`same sub still logged in at OP, session state has changed, restarting check session iframe; session_state`,t.session_state),await this._userManager.events._raiseUserSessionChanged()):e.debug(`different subject signed into OP`,t.sub):e.debug(`subject no longer signed into OP`),n?this._sub?await this._userManager.events._raiseUserSignedOut():await this._userManager.events._raiseUserSignedIn():e.debug(`no change in session detected, no event to raise`)}catch(t){this._sub&&(e.debug(`Error calling queryCurrentSigninSession; raising signed out event`,t),await this._userManager.events._raiseUserSignedOut())}},e||this._logger.throw(Error(`No user manager passed`)),this._userManager.events.addUserLoaded(this._start),this._userManager.events.addUserUnloaded(this._stop),this._init().catch(e=>{this._logger.error(e)})}async _init(){this._logger.create(`_init`);let e=await this._userManager.getUser();if(e)this._start(e);else if(this._userManager.settings.monitorAnonymousSession){let e=await this._userManager.querySessionStatus();if(e){let t={session_state:e.session_state,profile:e.sub?{sub:e.sub}:null};this._start(t)}}}},ev=class e{constructor(e){this.id_token=e.id_token,this.session_state=e.session_state??null,this.access_token=e.access_token,this.refresh_token=e.refresh_token,this.token_type=e.token_type,this.scope=e.scope,this.profile=e.profile,this.expires_at=e.expires_at,this.state=e.userState,this.url_state=e.url_state}get expires_in(){if(this.expires_at!==void 0)return this.expires_at-b_.getEpochTime()}set expires_in(e){e!==void 0&&(this.expires_at=Math.floor(e)+b_.getEpochTime())}get expired(){let e=this.expires_in;if(e!==void 0)return e<=0}get scopes(){return this.scope?.split(` `)??[]}toStorageString(){return new $(`User`).create(`toStorageString`),JSON.stringify({id_token:this.id_token,session_state:this.session_state,access_token:this.access_token,refresh_token:this.refresh_token,token_type:this.token_type,scope:this.scope,profile:this.profile,expires_at:this.expires_at})}static fromStorageString(t){return $.createStatic(`User`,`fromStorageString`),new e(JSON.parse(t))}},tv=`oidc-client`,nv=class{constructor(){this._abort=new v_(`Window navigation aborted`),this._disposeHandlers=new Set,this._window=null}async navigate(e){let t=this._logger.create(`navigate`);if(!this._window)throw Error(`Attempted to navigate on a disposed window`);t.debug(`setting URL in window`),this._window.location.replace(e.url);let{url:n,keepOpen:r}=await new Promise((n,r)=>{let i=i=>{let a=i.data,o=e.scriptOrigin??window.location.origin;if(!(i.origin!==o||a?.source!==tv)){try{let n=x_.readParams(a.url,e.response_mode).get(`state`);if(n||t.warn(`no state found in response url`),i.source!==this._window&&n!==e.state)return}catch{this._dispose(),r(Error(`Invalid response from window`))}n(a)}};window.addEventListener(`message`,i,!1),this._disposeHandlers.add(()=>window.removeEventListener(`message`,i,!1));let a=new BroadcastChannel(`oidc-client-popup-${e.state}`);a.addEventListener(`message`,i,!1),this._disposeHandlers.add(()=>a.close()),this._disposeHandlers.add(this._abort.addHandler(e=>{this._dispose(),r(e)}))});return t.debug(`got response from window`),this._dispose(),r||this.close(),{url:n}}_dispose(){this._logger.create(`_dispose`);for(let e of this._disposeHandlers)e();this._disposeHandlers.clear()}static _notifyParent(e,t,n=!1,r=window.location.origin){let i={source:tv,url:t,keepOpen:n},a=new $(`_notifyParent`);if(e)a.debug(`With parent. Using parent.postMessage.`),e.postMessage(i,r);else{a.debug(`No parent. Using BroadcastChannel.`);let e=new URL(t).searchParams.get(`state`);if(!e)throw Error(`No parent and no state in URL. Can't complete notification.`);let n=new BroadcastChannel(`oidc-client-popup-${e}`);n.postMessage(i),n.close()}}},rv={location:!1,toolbar:!1,height:640,closePopupWindowAfterInSeconds:-1},iv=`_blank`,av=60,ov=2,sv=10,cv=class extends I_{constructor(e){let{popup_redirect_uri:t=e.redirect_uri,popup_post_logout_redirect_uri:n=e.post_logout_redirect_uri,popupWindowFeatures:r=rv,popupWindowTarget:i=iv,redirectMethod:a=`assign`,redirectTarget:o=`self`,iframeNotifyParentOrigin:s=e.iframeNotifyParentOrigin,iframeScriptOrigin:c=e.iframeScriptOrigin,requestTimeoutInSeconds:l,silent_redirect_uri:u=e.redirect_uri,silentRequestTimeoutInSeconds:d,automaticSilentRenew:f=!0,validateSubOnSilentRenew:p=!0,includeIdTokenInSilentRenew:m=!1,monitorSession:h=!1,monitorAnonymousSession:g=!1,checkSessionIntervalInSeconds:_=ov,query_status_response_type:v=`code`,stopCheckSessionOnError:y=!0,revokeTokenTypes:b=[`access_token`,`refresh_token`],revokeTokensOnSignout:x=!1,includeIdTokenInSilentSignout:S=!1,accessTokenExpiringNotificationTimeInSeconds:C=av,userStore:w}=e;super(e),this.popup_redirect_uri=t,this.popup_post_logout_redirect_uri=n,this.popupWindowFeatures=r,this.popupWindowTarget=i,this.redirectMethod=a,this.redirectTarget=o,this.iframeNotifyParentOrigin=s,this.iframeScriptOrigin=c,this.silent_redirect_uri=u,this.silentRequestTimeoutInSeconds=d||l||sv,this.automaticSilentRenew=f,this.validateSubOnSilentRenew=p,this.includeIdTokenInSilentRenew=m,this.monitorSession=h,this.monitorAnonymousSession=g,this.checkSessionIntervalInSeconds=_,this.stopCheckSessionOnError=y,this.query_status_response_type=v,this.revokeTokenTypes=b,this.revokeTokensOnSignout=x,this.includeIdTokenInSilentSignout=S,this.accessTokenExpiringNotificationTimeInSeconds=C,w?this.userStore=w:this.userStore=new j_({store:typeof window<`u`?window.sessionStorage:new D_})}},lv=class e extends nv{constructor({silentRequestTimeoutInSeconds:t=sv}){super(),this._logger=new $(`IFrameWindow`),this._timeoutInSeconds=t,this._frame=e.createHiddenIframe(),this._window=this._frame.contentWindow}static createHiddenIframe(){let e=window.document.createElement(`iframe`);return e.style.visibility=`hidden`,e.style.position=`fixed`,e.style.left=`-1000px`,e.style.top=`0`,e.width=`0`,e.height=`0`,window.document.body.appendChild(e),e}async navigate(e){this._logger.debug(`navigate: Using timeout of:`,this._timeoutInSeconds);let t=setTimeout(()=>void this._abort.raise(new w_(`IFrame timed out without a response`)),this._timeoutInSeconds*1e3);return this._disposeHandlers.add(()=>clearTimeout(t)),await super.navigate(e)}close(){var e;this._frame&&=(this._frame.parentNode&&(this._frame.addEventListener(`load`,e=>{var t;let n=e.target;(t=n.parentNode)==null||t.removeChild(n),this._abort.raise(Error(`IFrame removed from DOM`))},!0),(e=this._frame.contentWindow)==null||e.location.replace(`about:blank`)),null),this._window=null}static notifyParent(e,t){return super._notifyParent(window.parent,e,!1,t)}},uv=class{constructor(e){this._settings=e,this._logger=new $(`IFrameNavigator`)}async prepare({silentRequestTimeoutInSeconds:e=this._settings.silentRequestTimeoutInSeconds}){return new lv({silentRequestTimeoutInSeconds:e})}async callback(e){this._logger.create(`callback`),lv.notifyParent(e,this._settings.iframeNotifyParentOrigin)}},dv=500,fv=1e3,pv=class extends nv{constructor({popupWindowTarget:e=iv,popupWindowFeatures:t={},popupSignal:n,popupAbortOnClose:r}){super(),this._logger=new $(`PopupWindow`);let i=y_.center({...rv,...t});this._window=window.open(void 0,e,y_.serialize(i)),this.abortOnClose=!!r,n&&n.addEventListener(`abort`,()=>{this._abort.raise(Error(n.reason??`Popup aborted`))}),t.closePopupWindowAfterInSeconds&&t.closePopupWindowAfterInSeconds>0&&setTimeout(()=>{if(!this._window||typeof this._window.closed!=`boolean`||this._window.closed){this._abort.raise(Error(`Popup blocked by user`));return}this.close()},t.closePopupWindowAfterInSeconds*fv)}async navigate(e){var t;(t=this._window)==null||t.focus();let n=setInterval(()=>{(!this._window||this._window.closed)&&(this._logger.debug(`Popup closed by user or isolated by redirect`),r(),this._disposeHandlers.delete(r),this.abortOnClose&&this._abort.raise(Error(`Popup closed by user`)))},dv),r=()=>clearInterval(n);return this._disposeHandlers.add(r),await super.navigate(e)}close(){this._window&&(this._window.closed||(this._window.close(),this._abort.raise(Error(`Popup closed`)))),this._window=null}static notifyOpener(e,t){super._notifyParent(window.opener,e,t),!t&&!window.opener&&window.close()}},mv=class{constructor(e){this._settings=e,this._logger=new $(`PopupNavigator`)}async prepare({popupWindowFeatures:e=this._settings.popupWindowFeatures,popupWindowTarget:t=this._settings.popupWindowTarget,popupSignal:n,popupAbortOnClose:r}){return new pv({popupWindowFeatures:e,popupWindowTarget:t,popupSignal:n,popupAbortOnClose:r})}async callback(e,{keepOpen:t=!1}){this._logger.create(`callback`),pv.notifyOpener(e,t)}},hv=class{constructor(e){this._settings=e,this._logger=new $(`RedirectNavigator`)}async prepare({redirectMethod:e=this._settings.redirectMethod,redirectTarget:t=this._settings.redirectTarget}){this._logger.create(`prepare`);let n=window.self;t===`top`&&(n=window.top??window.self);let r=n.location[e].bind(n.location),i;return{navigate:async e=>(this._logger.create(`navigate`),await new Promise((t,n)=>{i=n,window.addEventListener(`pageshow`,()=>t(window.location.href)),r(e.url)})),close:()=>{this._logger.create(`close`),i?.(Error(`Redirect aborted`)),n.stop()}}}async callback(){}},gv=class extends T_{constructor(e){super({expiringNotificationTimeInSeconds:e.accessTokenExpiringNotificationTimeInSeconds}),this._logger=new $(`UserManagerEvents`),this._userLoaded=new v_(`User loaded`),this._userUnloaded=new v_(`User unloaded`),this._silentRenewError=new v_(`Silent renew error`),this._userSignedIn=new v_(`User signed in`),this._userSignedOut=new v_(`User signed out`),this._userSessionChanged=new v_(`User session changed`)}async load(e,t=!0){await super.load(e),t&&await this._userLoaded.raise(e)}async unload(){await super.unload(),await this._userUnloaded.raise()}addUserLoaded(e){return this._userLoaded.addHandler(e)}removeUserLoaded(e){return this._userLoaded.removeHandler(e)}addUserUnloaded(e){return this._userUnloaded.addHandler(e)}removeUserUnloaded(e){return this._userUnloaded.removeHandler(e)}addSilentRenewError(e){return this._silentRenewError.addHandler(e)}removeSilentRenewError(e){return this._silentRenewError.removeHandler(e)}async _raiseSilentRenewError(e){await this._silentRenewError.raise(e)}addUserSignedIn(e){return this._userSignedIn.addHandler(e)}removeUserSignedIn(e){this._userSignedIn.removeHandler(e)}async _raiseUserSignedIn(){await this._userSignedIn.raise()}addUserSignedOut(e){return this._userSignedOut.addHandler(e)}removeUserSignedOut(e){this._userSignedOut.removeHandler(e)}async _raiseUserSignedOut(){await this._userSignedOut.raise()}addUserSessionChanged(e){return this._userSessionChanged.addHandler(e)}removeUserSessionChanged(e){this._userSessionChanged.removeHandler(e)}async _raiseUserSessionChanged(){await this._userSessionChanged.raise()}},_v=class{constructor(e){this._userManager=e,this._logger=new $(`SilentRenewService`),this._isStarted=!1,this._retryTimer=new b_(`Retry Silent Renew`),this._tokenExpiring=async()=>{let e=this._logger.create(`_tokenExpiring`);try{await this._userManager.signinSilent(),e.debug(`silent token renewal successful`)}catch(t){if(t instanceof w_){e.warn(`ErrorTimeout from signinSilent:`,t,`retry in 5s`),this._retryTimer.init(5);return}e.error(`Error from signinSilent:`,t),await this._userManager.events._raiseSilentRenewError(t)}}}async start(){let e=this._logger.create(`start`);if(!this._isStarted){this._isStarted=!0,this._userManager.events.addAccessTokenExpiring(this._tokenExpiring),this._retryTimer.addHandler(this._tokenExpiring);try{await this._userManager.getUser()}catch(t){e.error(`getUser error`,t)}}}stop(){this._isStarted&&=(this._retryTimer.cancel(),this._retryTimer.removeHandler(this._tokenExpiring),this._userManager.events.removeAccessTokenExpiring(this._tokenExpiring),!1)}},vv=class{constructor(e){this.refresh_token=e.refresh_token,this.id_token=e.id_token,this.session_state=e.session_state,this.scope=e.scope,this.profile=e.profile,this.data=e.state}},yv=class{constructor(e,t,n,r){this._logger=new $(`UserManager`),this.settings=new cv(e),this._client=new Q_(e),this._redirectNavigator=t??new hv(this.settings),this._popupNavigator=n??new mv(this.settings),this._iframeNavigator=r??new uv(this.settings),this._events=new gv(this.settings),this._silentRenewService=new _v(this),this.settings.automaticSilentRenew&&this.startSilentRenew(),this._sessionMonitor=null,this.settings.monitorSession&&(this._sessionMonitor=new $_(this))}get events(){return this._events}get metadataService(){return this._client.metadataService}async getUser(e=!1){let t=this._logger.create(`getUser`),n=await this._loadUser();return n?(t.info(`user loaded`),await this._events.load(n,e),n):(t.info(`user not found in storage`),null)}async removeUser(){let e=this._logger.create(`removeUser`);await this.storeUser(null),e.info(`user removed from storage`),await this._events.unload()}async signinRedirect(e={}){this._logger.create(`signinRedirect`);let{redirectMethod:t,...n}=e,r;this.settings.dpop?.bind_authorization_code&&(r=await this.generateDPoPJkt(this.settings.dpop));let i=await this._redirectNavigator.prepare({redirectMethod:t});await this._signinStart({request_type:`si:r`,dpopJkt:r,...n},i)}async signinRedirectCallback(e=window.location.href){let t=this._logger.create(`signinRedirectCallback`),n=await this._signinEnd(e);return n.profile&&n.profile.sub?t.info(`success, signed in subject`,n.profile.sub):t.info(`no subject`),n}async signinResourceOwnerCredentials({username:e,password:t,skipUserInfo:n=!1}){let r=this._logger.create(`signinResourceOwnerCredential`),i=await this._client.processResourceOwnerPasswordCredentials({username:e,password:t,skipUserInfo:n,extraTokenParams:this.settings.extraTokenParams});r.debug(`got signin response`);let a=await this._buildUser(i);return a.profile&&a.profile.sub?r.info(`success, signed in subject`,a.profile.sub):r.info(`no subject`),a}async signinPopup(e={}){let t=this._logger.create(`signinPopup`),n;this.settings.dpop?.bind_authorization_code&&(n=await this.generateDPoPJkt(this.settings.dpop));let{popupWindowFeatures:r,popupWindowTarget:i,popupSignal:a,popupAbortOnClose:o,...s}=e,c=this.settings.popup_redirect_uri;c||t.throw(Error(`No popup_redirect_uri configured`));let l=await this._popupNavigator.prepare({popupWindowFeatures:r,popupWindowTarget:i,popupSignal:a,popupAbortOnClose:o}),u=await this._signin({request_type:`si:p`,redirect_uri:c,display:`popup`,dpopJkt:n,...s},l);return u&&(u.profile&&u.profile.sub?t.info(`success, signed in subject`,u.profile.sub):t.info(`no subject`)),u}async signinPopupCallback(e=window.location.href,t=!1){let n=this._logger.create(`signinPopupCallback`);await this._popupNavigator.callback(e,{keepOpen:t}),n.info(`success`)}async signinSilent(e={}){let t=this._logger.create(`signinSilent`),{silentRequestTimeoutInSeconds:n,...r}=e,i=await this._loadUser();if(!e.forceIframeAuth&&i?.refresh_token){t.debug(`using refresh token`);let e=new vv(i);return await this._useRefreshToken({state:e,redirect_uri:r.redirect_uri,resource:r.resource,extraTokenParams:r.extraTokenParams,timeoutInSeconds:n})}let a;this.settings.dpop?.bind_authorization_code&&(a=await this.generateDPoPJkt(this.settings.dpop));let o=this.settings.silent_redirect_uri;o||t.throw(Error(`No silent_redirect_uri configured`));let s;i&&this.settings.validateSubOnSilentRenew&&(t.debug(`subject prior to silent renew:`,i.profile.sub),s=i.profile.sub);let c=await this._iframeNavigator.prepare({silentRequestTimeoutInSeconds:n});return i=await this._signin({request_type:`si:s`,redirect_uri:o,prompt:`none`,id_token_hint:this.settings.includeIdTokenInSilentRenew?i?.id_token:void 0,dpopJkt:a,...r},c,s),i&&(i.profile?.sub?t.info(`success, signed in subject`,i.profile.sub):t.info(`no subject`)),i}async _useRefreshToken(e){let t=await this._client.useRefreshToken({timeoutInSeconds:this.settings.silentRequestTimeoutInSeconds,...e}),n=new ev({...e.state,...t});return await this.storeUser(n),await this._events.load(n),n}async signinSilentCallback(e=window.location.href){let t=this._logger.create(`signinSilentCallback`);await this._iframeNavigator.callback(e),t.info(`success`)}async signinCallback(e=window.location.href){let{state:t}=await this._client.readSigninResponseState(e);switch(t.request_type){case`si:r`:return await this.signinRedirectCallback(e);case`si:p`:await this.signinPopupCallback(e);break;case`si:s`:await this.signinSilentCallback(e);break;default:throw Error(`invalid response_type in state`)}}async signoutCallback(e=window.location.href,t=!1){let{state:n}=await this._client.readSignoutResponseState(e);if(n)switch(n.request_type){case`so:r`:return await this.signoutRedirectCallback(e);case`so:p`:await this.signoutPopupCallback(e,t);break;case`so:s`:await this.signoutSilentCallback(e);break;default:throw Error(`invalid response_type in state`)}}async querySessionStatus(e={}){let t=this._logger.create(`querySessionStatus`),{silentRequestTimeoutInSeconds:n,...r}=e,i=this.settings.silent_redirect_uri;i||t.throw(Error(`No silent_redirect_uri configured`));let a=await this._loadUser(),o=await this._iframeNavigator.prepare({silentRequestTimeoutInSeconds:n}),s=await this._signinStart({request_type:`si:s`,redirect_uri:i,prompt:`none`,id_token_hint:this.settings.includeIdTokenInSilentRenew?a?.id_token:void 0,response_type:this.settings.query_status_response_type,scope:`openid`,skipUserInfo:!0,...r},o);try{let e=await this._client.processSigninResponse(s.url,{});return t.debug(`got signin response`),e.session_state&&e.profile.sub?(t.info(`success for subject`,e.profile.sub),{session_state:e.session_state,sub:e.profile.sub}):(t.info(`success, user not authenticated`),null)}catch(e){if(this.settings.monitorAnonymousSession&&e instanceof C_)switch(e.error){case`login_required`:case`consent_required`:case`interaction_required`:case`account_selection_required`:return t.info(`success for anonymous user`),{session_state:e.session_state}}throw e}}async _signin(e,t,n){let r=await this._signinStart(e,t);return await this._signinEnd(r.url,n)}async _signinStart(e,t){let n=this._logger.create(`_signinStart`);try{let r=await this._client.createSigninRequest(e);return n.debug(`got signin request`),await t.navigate({url:r.url,state:r.state.id,response_mode:r.state.response_mode,scriptOrigin:this.settings.iframeScriptOrigin})}catch(e){throw n.debug(`error after preparing navigator, closing navigator window`),t.close(),e}}async _signinEnd(e,t){let n=this._logger.create(`_signinEnd`),r=await this._client.processSigninResponse(e,{});return n.debug(`got signin response`),await this._buildUser(r,t)}async _buildUser(e,t){let n=this._logger.create(`_buildUser`),r=new ev(e);if(t){if(t!==r.profile.sub)throw n.debug(`current user does not match user returned from signin. sub from signin:`,r.profile.sub),new C_({...e,error:`login_required`});n.debug(`current user matches user returned from signin`)}return await this.storeUser(r),n.debug(`user stored`),await this._events.load(r),r}async signoutRedirect(e={}){let t=this._logger.create(`signoutRedirect`),{redirectMethod:n,...r}=e,i=await this._redirectNavigator.prepare({redirectMethod:n});await this._signoutStart({request_type:`so:r`,post_logout_redirect_uri:this.settings.post_logout_redirect_uri,...r},i),t.info(`success`)}async signoutRedirectCallback(e=window.location.href){let t=this._logger.create(`signoutRedirectCallback`),n=await this._signoutEnd(e);return t.info(`success`),n}async signoutPopup(e={}){let t=this._logger.create(`signoutPopup`),{popupWindowFeatures:n,popupWindowTarget:r,popupSignal:i,...a}=e,o=this.settings.popup_post_logout_redirect_uri,s=await this._popupNavigator.prepare({popupWindowFeatures:n,popupWindowTarget:r,popupSignal:i});await this._signout({request_type:`so:p`,post_logout_redirect_uri:o,state:o==null?void 0:{},...a},s),t.info(`success`)}async signoutPopupCallback(e=window.location.href,t=!1){let n=this._logger.create(`signoutPopupCallback`);await this._popupNavigator.callback(e,{keepOpen:t}),n.info(`success`)}async _signout(e,t){let n=await this._signoutStart(e,t);return await this._signoutEnd(n.url)}async _signoutStart(e={},t){let n=this._logger.create(`_signoutStart`);try{let r=await this._loadUser();n.debug(`loaded current user from storage`),this.settings.revokeTokensOnSignout&&await this._revokeInternal(r);let i=e.id_token_hint||r&&r.id_token;i&&(n.debug(`setting id_token_hint in signout request`),e.id_token_hint=i),await this.removeUser(),n.debug(`user removed, creating signout request`);let a=await this._client.createSignoutRequest(e);return n.debug(`got signout request`),await t.navigate({url:a.url,state:a.state?.id,scriptOrigin:this.settings.iframeScriptOrigin})}catch(e){throw n.debug(`error after preparing navigator, closing navigator window`),t.close(),e}}async _signoutEnd(e){let t=this._logger.create(`_signoutEnd`),n=await this._client.processSignoutResponse(e);return t.debug(`got signout response`),n}async signoutSilent(e={}){let t=this._logger.create(`signoutSilent`),{silentRequestTimeoutInSeconds:n,...r}=e,i=this.settings.includeIdTokenInSilentSignout?(await this._loadUser())?.id_token:void 0,a=this.settings.popup_post_logout_redirect_uri,o=await this._iframeNavigator.prepare({silentRequestTimeoutInSeconds:n});await this._signout({request_type:`so:s`,post_logout_redirect_uri:a,id_token_hint:i,...r},o),t.info(`success`)}async signoutSilentCallback(e=window.location.href){let t=this._logger.create(`signoutSilentCallback`);await this._iframeNavigator.callback(e),t.info(`success`)}async revokeTokens(e){let t=await this._loadUser();await this._revokeInternal(t,e)}async _revokeInternal(e,t=this.settings.revokeTokenTypes){let n=this._logger.create(`_revokeInternal`);if(!e)return;let r=t.filter(t=>typeof e[t]==`string`);if(!r.length){n.debug(`no need to revoke due to no token(s)`);return}for(let t of r)await this._client.revokeToken(e[t],t),n.info(`${t} revoked successfully`),t!==`access_token`&&(e[t]=null);await this.storeUser(e),n.debug(`user stored`),await this._events.load(e)}startSilentRenew(){this._logger.create(`startSilentRenew`),this._silentRenewService.start()}stopSilentRenew(){this._silentRenewService.stop()}get _userStoreKey(){return`user:${this.settings.authority}:${this.settings.client_id}`}async _loadUser(){let e=this._logger.create(`_loadUser`),t=await this.settings.userStore.get(this._userStoreKey);return t?(e.debug(`user storageString loaded`),ev.fromStorageString(t)):(e.debug(`no user storageString`),null)}async storeUser(e){let t=this._logger.create(`storeUser`);if(e){t.debug(`storing user`);let n=e.toStorageString();await this.settings.userStore.set(this._userStoreKey,n)}else this._logger.debug(`removing user`),await this.settings.userStore.remove(this._userStoreKey),this.settings.dpop&&await this.settings.dpop.store.remove(this.settings.client_id)}async clearStaleState(){await this._client.clearStaleState()}async dpopProof(e,t,n,r){let i=await(this.settings.dpop?.store)?.get(this.settings.client_id);if(i)return await __.generateDPoPProof({url:e,accessToken:t?.access_token,httpMethod:n,keyPair:i.keys,nonce:r})}async generateDPoPJkt(e){let t=await e.store.get(this.settings.client_id);return t||(t=new Z_(await __.generateDPoPKeys()),await e.store.set(this.settings.client_id,t)),await __.generateDPoPJkt(t.keys)}},bv=d.createContext(void 0);bv.displayName=`AuthContext`;var xv={isLoading:!0,isAuthenticated:!1},Sv=(e,t)=>{switch(t.type){case`INITIALISED`:case`USER_LOADED`:return{...e,user:t.user,isLoading:!1,isAuthenticated:t.user?!t.user.expired:!1,error:void 0};case`USER_SIGNED_OUT`:case`USER_UNLOADED`:return{...e,user:void 0,isAuthenticated:!1};case`NAVIGATOR_INIT`:return{...e,isLoading:!0,activeNavigator:t.method};case`NAVIGATOR_CLOSE`:return{...e,isLoading:!1,activeNavigator:void 0};case`ERROR`:{let n=t.error;return n.toString=()=>`${n.name}: ${n.message}`,{...e,isLoading:!1,error:n}}default:{let n=TypeError(`unknown type ${t.type}`),r={name:n.name,message:n.message,innerError:n,stack:n.stack,source:`unknown`};return r.toString=()=>`${r.name}: ${r.message}`,{...e,isLoading:!1,error:r}}}},Cv=(e=window.location)=>{let t=new URLSearchParams(e.search);return!!((t.get(`code`)||t.get(`error`))&&t.get(`state`)||(t=new URLSearchParams(e.hash.replace(`#`,`?`)),(t.get(`code`)||t.get(`error`))&&t.get(`state`)))},wv=Ov(`signinCallback`,`Sign-in failed`),Tv=Ov(`signoutCallback`,`Sign-out failed`),Ev=Ov(`renewSilent`,`Renew silent failed`);function Dv(e,t){return{name:kv(e,`name`,()=>`Error`),message:kv(e,`message`,()=>t),stack:kv(e,`stack`,()=>Error().stack),innerError:e}}function Ov(e,t){return n=>({...Dv(n,t),source:e})}function kv(e,t,n){if(e&&typeof e==`object`){let n=e[t];if(typeof n==`string`)return n}return n()}var Av=[`clearStaleState`,`querySessionStatus`,`revokeTokens`,`startSilentRenew`,`stopSilentRenew`],jv=[`signinPopup`,`signinSilent`,`signinRedirect`,`signinResourceOwnerCredentials`,`signoutPopup`,`signoutRedirect`,`signoutSilent`],Mv=e=>()=>{throw Error(`UserManager#${e} was called from an unsupported context. If this is a server-rendered page, defer this call with useEffect() or pass a custom UserManager implementation.`)},Nv=typeof window>`u`?null:yv,Pv=e=>{let{children:t,onSigninCallback:n,skipSigninCallback:r,matchSignoutCallback:i,onSignoutCallback:a,onRemoveUser:o,userManager:s=null,...c}=e,[l]=d.useState(()=>s??(Nv?new Nv(c):{settings:c})),[u,f]=d.useReducer(Sv,xv),p=d.useMemo(()=>Object.assign({settings:l.settings,events:l.events},Object.fromEntries(Av.map(e=>[e,l[e]?.bind(l)??Mv(e)])),Object.fromEntries(jv.map(e=>[e,l[e]?async t=>{f({type:`NAVIGATOR_INIT`,method:e});try{return await l[e](t)}catch(n){return f({type:`ERROR`,error:{...Dv(n,`Unknown error while executing ${e}(...).`),source:e,args:t}}),null}finally{f({type:`NAVIGATOR_CLOSE`})}}:Mv(e)]))),[l]),m=d.useRef(!1);d.useEffect(()=>{!l||m.current||(m.current=!0,(async()=>{try{let e=null;Cv()&&!r&&(e=await l.signinCallback(),n&&await n(e)),e||=await l.getUser(),f({type:`INITIALISED`,user:e})}catch(e){f({type:`ERROR`,error:wv(e)})}try{if(i&&i(l.settings)){let e=await l.signoutCallback();a&&await a(e)}}catch(e){f({type:`ERROR`,error:Tv(e)})}})())},[l,r,n,a,i]),d.useEffect(()=>{if(!l)return;let e=e=>{f({type:`USER_LOADED`,user:e})};l.events.addUserLoaded(e);let t=()=>{f({type:`USER_UNLOADED`})};l.events.addUserUnloaded(t);let n=()=>{f({type:`USER_SIGNED_OUT`})};l.events.addUserSignedOut(n);let r=e=>{f({type:`ERROR`,error:Ev(e)})};return l.events.addSilentRenewError(r),()=>{l.events.removeUserLoaded(e),l.events.removeUserUnloaded(t),l.events.removeUserSignedOut(n),l.events.removeSilentRenewError(r)}},[l]);let h=d.useCallback(async()=>{await l.removeUser(),o&&await o()},[l,o]),g=d.useMemo(()=>({...u,...p,removeUser:h}),[u,p,h]);return d.createElement(bv.Provider,{value:g},t)},Fv=`modulepreload`,Iv=function(e){return`/`+e},Lv={},Rv=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}r=o(t.map(t=>{if(t=Iv(t,n),t in Lv)return;Lv[t]=!0;let r=t.endsWith(`.css`),i=r?`[rel="stylesheet"]`:``;if(n)for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}else if(document.querySelector(`link[href="${t}"]${i}`))return;let o=document.createElement(`link`);if(o.rel=r?`stylesheet`:Fv,r||(o.as=`script`),o.crossOrigin=``,o.href=t,a&&o.setAttribute(`nonce`,a),document.head.appendChild(o),r)return new Promise((e,n)=>{o.addEventListener(`load`,e),o.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},zv=`popstate`;function Bv(e={}){function t(e,t){let{pathname:n,search:r,hash:i}=e.location;return Gv(``,{pathname:n,search:r,hash:i},t.state&&t.state.usr||null,t.state&&t.state.key||`default`)}function n(e,t){return typeof t==`string`?t:Kv(t)}return Jv(t,n,null,e)}function Vv(e,t){if(e===!1||e==null)throw Error(t)}function Hv(e,t){if(!e){typeof console<`u`&&console.warn(t);try{throw Error(t)}catch{}}}function Uv(){return Math.random().toString(36).substring(2,10)}function Wv(e,t){return{usr:e.state,key:e.key,idx:t}}function Gv(e,t,n=null,r){return{pathname:typeof e==`string`?e:e.pathname,search:``,hash:``,...typeof t==`string`?qv(t):t,state:n,key:t&&t.key||r||Uv()}}function Kv({pathname:e=`/`,search:t=``,hash:n=``}){return t&&t!==`?`&&(e+=t.charAt(0)===`?`?t:`?`+t),n&&n!==`#`&&(e+=n.charAt(0)===`#`?n:`#`+n),e}function qv(e){let t={};if(e){let n=e.indexOf(`#`);n>=0&&(t.hash=e.substring(n),e=e.substring(0,n));let r=e.indexOf(`?`);r>=0&&(t.search=e.substring(r),e=e.substring(0,r)),e&&(t.pathname=e)}return t}function Jv(e,t,n,r={}){let{window:i=document.defaultView,v5Compat:a=!1}=r,o=i.history,s=`POP`,c=null,l=u();l??(l=0,o.replaceState({...o.state,idx:l},``));function u(){return(o.state||{idx:null}).idx}function d(){s=`POP`;let e=u(),t=e==null?null:e-l;l=e,c&&c({action:s,location:h.location,delta:t})}function f(e,t){s=`PUSH`;let r=Gv(h.location,e,t);n&&n(r,e),l=u()+1;let d=Wv(r,l),f=h.createHref(r);try{o.pushState(d,``,f)}catch(e){if(e instanceof DOMException&&e.name===`DataCloneError`)throw e;i.location.assign(f)}a&&c&&c({action:s,location:h.location,delta:1})}function p(e,t){s=`REPLACE`;let r=Gv(h.location,e,t);n&&n(r,e),l=u();let i=Wv(r,l),d=h.createHref(r);o.replaceState(i,``,d),a&&c&&c({action:s,location:h.location,delta:0})}function m(e){return Yv(e)}let h={get action(){return s},get location(){return e(i,o)},listen(e){if(c)throw Error(`A history only accepts one active listener`);return i.addEventListener(zv,d),c=e,()=>{i.removeEventListener(zv,d),c=null}},createHref(e){return t(i,e)},createURL:m,encodeLocation(e){let t=m(e);return{pathname:t.pathname,search:t.search,hash:t.hash}},push:f,replace:p,go(e){return o.go(e)}};return h}function Yv(e,t=!1){let n=`http://localhost`;typeof window<`u`&&(n=window.location.origin===`null`?window.location.href:window.location.origin),Vv(n,`No window.location.(origin|href) available to create URL`);let r=typeof e==`string`?e:Kv(e);return r=r.replace(/ $/,`%20`),!t&&r.startsWith(`//`)&&(r=n+r),new URL(r,n)}function Xv(e,t,n=`/`){return Zv(e,t,n,!1)}function Zv(e,t,n,r){let i=hy((typeof t==`string`?qv(t):t).pathname||`/`,n);if(i==null)return null;let a=$v(e);ty(a);let o=null;for(let e=0;o==null&&e{let c={relativePath:s===void 0?e.path||``:s,caseSensitive:e.caseSensitive===!0,childrenIndex:a,route:e};if(c.relativePath.startsWith(`/`)){if(!c.relativePath.startsWith(r)&&o)return;Vv(c.relativePath.startsWith(r),`Absolute route path "${c.relativePath}" nested under path "${r}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),c.relativePath=c.relativePath.slice(r.length)}let l=wy([r,c.relativePath]),u=n.concat(c);e.children&&e.children.length>0&&(Vv(e.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${l}".`),$v(e.children,t,u,l,o)),!(e.path==null&&!e.index)&&t.push({path:l,score:ly(l,e.index),routesMeta:u})};return e.forEach((e,t)=>{if(e.path===``||!e.path?.includes(`?`))a(e,t);else for(let n of ey(e.path))a(e,t,!0,n)}),t}function ey(e){let t=e.split(`/`);if(t.length===0)return[];let[n,...r]=t,i=n.endsWith(`?`),a=n.replace(/\?$/,``);if(r.length===0)return i?[a,``]:[a];let o=ey(r.join(`/`)),s=[];return s.push(...o.map(e=>e===``?a:[a,e].join(`/`))),i&&s.push(...o),s.map(t=>e.startsWith(`/`)&&t===``?`/`:t)}function ty(e){e.sort((e,t)=>e.score===t.score?uy(e.routesMeta.map(e=>e.childrenIndex),t.routesMeta.map(e=>e.childrenIndex)):t.score-e.score)}var ny=/^:[\w-]+$/,ry=3,iy=2,ay=1,oy=10,sy=-2,cy=e=>e===`*`;function ly(e,t){let n=e.split(`/`),r=n.length;return n.some(cy)&&(r+=sy),t&&(r+=iy),n.filter(e=>!cy(e)).reduce((e,t)=>e+(ny.test(t)?ry:t===``?ay:oy),r)}function uy(e,t){return e.length===t.length&&e.slice(0,-1).every((e,n)=>e===t[n])?e[e.length-1]-t[t.length-1]:0}function dy(e,t,n=!1){let{routesMeta:r}=e,i={},a=`/`,o=[];for(let e=0;e{if(t===`*`){let e=s[r]||``;o=a.slice(0,a.length-e.length).replace(/(.)\/+$/,`$1`)}let i=s[r];return n&&!i?e[t]=void 0:e[t]=(i||``).replace(/%2F/g,`/`),e},{}),pathname:a,pathnameBase:o,pattern:e}}function py(e,t=!1,n=!0){Hv(e===`*`||!e.endsWith(`*`)||e.endsWith(`/*`),`Route path "${e}" will be treated as if it were "${e.replace(/\*$/,`/*`)}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${e.replace(/\*$/,`/*`)}".`);let r=[],i=`^`+e.replace(/\/*\*?$/,``).replace(/^\/*/,`/`).replace(/[\\.*+^${}|()[\]]/g,`\\$&`).replace(/\/:([\w-]+)(\?)?/g,(e,t,n)=>(r.push({paramName:t,isOptional:n!=null}),n?`/?([^\\/]+)?`:`/([^\\/]+)`)).replace(/\/([\w-]+)\?(\/|$)/g,`(/$1)?$2`);return e.endsWith(`*`)?(r.push({paramName:`*`}),i+=e===`*`||e===`/*`?`(.*)$`:`(?:\\/(.+)|\\/*)$`):n?i+=`\\/*$`:e!==``&&e!==`/`&&(i+=`(?:(?=\\/|$))`),[new RegExp(i,t?void 0:`i`),r]}function my(e){try{return e.split(`/`).map(e=>decodeURIComponent(e).replace(/\//g,`%2F`)).join(`/`)}catch(t){return Hv(!1,`The URL path "${e}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${t}).`),e}}function hy(e,t){if(t===`/`)return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let n=t.endsWith(`/`)?t.length-1:t.length,r=e.charAt(n);return r&&r!==`/`?null:e.slice(n)||`/`}var gy=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,_y=e=>gy.test(e);function vy(e,t=`/`){let{pathname:n,search:r=``,hash:i=``}=typeof e==`string`?qv(e):e,a;if(n)if(_y(n))a=n;else{if(n.includes(`//`)){let e=n;n=n.replace(/\/\/+/g,`/`),Hv(!1,`Pathnames cannot have embedded double slashes - normalizing ${e} -> ${n}`)}a=n.startsWith(`/`)?yy(n.substring(1),`/`):yy(n,t)}else a=t;return{pathname:a,search:Ey(r),hash:Dy(i)}}function yy(e,t){let n=t.replace(/\/+$/,``).split(`/`);return e.split(`/`).forEach(e=>{e===`..`?n.length>1&&n.pop():e!==`.`&&n.push(e)}),n.length>1?n.join(`/`):`/`}function by(e,t,n,r){return`Cannot include a '${e}' character in a manually specified \`to.${t}\` field [${JSON.stringify(r)}]. Please separate it out to the \`to.${n}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function xy(e){return e.filter((e,t)=>t===0||e.route.path&&e.route.path.length>0)}function Sy(e){let t=xy(e);return t.map((e,n)=>n===t.length-1?e.pathname:e.pathnameBase)}function Cy(e,t,n,r=!1){let i;typeof e==`string`?i=qv(e):(i={...e},Vv(!i.pathname||!i.pathname.includes(`?`),by(`?`,`pathname`,`search`,i)),Vv(!i.pathname||!i.pathname.includes(`#`),by(`#`,`pathname`,`hash`,i)),Vv(!i.search||!i.search.includes(`#`),by(`#`,`search`,`hash`,i)));let a=e===``||i.pathname===``,o=a?`/`:i.pathname,s;if(o==null)s=n;else{let e=t.length-1;if(!r&&o.startsWith(`..`)){let t=o.split(`/`);for(;t[0]===`..`;)t.shift(),--e;i.pathname=t.join(`/`)}s=e>=0?t[e]:`/`}let c=vy(i,s),l=o&&o!==`/`&&o.endsWith(`/`),u=(a||o===`.`)&&n.endsWith(`/`);return!c.pathname.endsWith(`/`)&&(l||u)&&(c.pathname+=`/`),c}var wy=e=>e.join(`/`).replace(/\/\/+/g,`/`),Ty=e=>e.replace(/\/+$/,``).replace(/^\/*/,`/`),Ey=e=>!e||e===`?`?``:e.startsWith(`?`)?e:`?`+e,Dy=e=>!e||e===`#`?``:e.startsWith(`#`)?e:`#`+e,Oy=class{constructor(e,t,n,r=!1){this.status=e,this.statusText=t||``,this.internal=r,n instanceof Error?(this.data=n.toString(),this.error=n):this.data=n}};function ky(e){return e!=null&&typeof e.status==`number`&&typeof e.statusText==`string`&&typeof e.internal==`boolean`&&`data`in e}function Ay(e){return e.map(e=>e.route.path).filter(Boolean).join(`/`).replace(/\/\/*/g,`/`)||`/`}var jy=typeof window<`u`&&window.document!==void 0&&window.document.createElement!==void 0;function My(e,t){let n=e;if(typeof n!=`string`||!gy.test(n))return{absoluteURL:void 0,isExternal:!1,to:n};let r=n,i=!1;if(jy)try{let e=new URL(window.location.href),r=n.startsWith(`//`)?new URL(e.protocol+n):new URL(n),a=hy(r.pathname,t);r.origin===e.origin&&a!=null?n=a+r.search+r.hash:i=!0}catch{Hv(!1,` contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}return{absoluteURL:r,isExternal:i,to:n}}Object.getOwnPropertyNames(Object.prototype).sort().join(`\0`);var Ny=[`POST`,`PUT`,`PATCH`,`DELETE`];new Set(Ny);var Py=[`GET`,...Ny];new Set(Py);var Fy=d.createContext(null);Fy.displayName=`DataRouter`;var Iy=d.createContext(null);Iy.displayName=`DataRouterState`;var Ly=d.createContext(!1),Ry=d.createContext({isTransitioning:!1});Ry.displayName=`ViewTransition`;var zy=d.createContext(new Map);zy.displayName=`Fetchers`;var By=d.createContext(null);By.displayName=`Await`;var Vy=d.createContext(null);Vy.displayName=`Navigation`;var Hy=d.createContext(null);Hy.displayName=`Location`;var Uy=d.createContext({outlet:null,matches:[],isDataRoute:!1});Uy.displayName=`Route`;var Wy=d.createContext(null);Wy.displayName=`RouteError`;var Gy=`REACT_ROUTER_ERROR`,Ky=`REDIRECT`,qy=`ROUTE_ERROR_RESPONSE`;function Jy(e){if(e.startsWith(`${Gy}:${Ky}:{`))try{let t=JSON.parse(e.slice(28));if(typeof t==`object`&&t&&typeof t.status==`number`&&typeof t.statusText==`string`&&typeof t.location==`string`&&typeof t.reloadDocument==`boolean`&&typeof t.replace==`boolean`)return t}catch{}}function Yy(e){if(e.startsWith(`${Gy}:${qy}:{`))try{let t=JSON.parse(e.slice(40));if(typeof t==`object`&&t&&typeof t.status==`number`&&typeof t.statusText==`string`)return new Oy(t.status,t.statusText,t.data)}catch{}}function Xy(e,{relative:t}={}){Vv(Zy(),`useHref() may be used only in the context of a component.`);let{basename:n,navigator:r}=d.useContext(Vy),{hash:i,pathname:a,search:o}=rb(e,{relative:t}),s=a;return n!==`/`&&(s=a===`/`?n:wy([n,a])),r.createHref({pathname:s,search:o,hash:i})}function Zy(){return d.useContext(Hy)!=null}function Qy(){return Vv(Zy(),`useLocation() may be used only in the context of a component.`),d.useContext(Hy).location}var $y=`You should call navigate() in a React.useEffect(), not when your component is first rendered.`;function eb(e){d.useContext(Vy).static||d.useLayoutEffect(e)}function tb(){let{isDataRoute:e}=d.useContext(Uy);return e?Sb():nb()}function nb(){Vv(Zy(),`useNavigate() may be used only in the context of a component.`);let e=d.useContext(Fy),{basename:t,navigator:n}=d.useContext(Vy),{matches:r}=d.useContext(Uy),{pathname:i}=Qy(),a=JSON.stringify(Sy(r)),o=d.useRef(!1);return eb(()=>{o.current=!0}),d.useCallback((r,s={})=>{if(Hv(o.current,$y),!o.current)return;if(typeof r==`number`){n.go(r);return}let c=Cy(r,JSON.parse(a),i,s.relative===`path`);e==null&&t!==`/`&&(c.pathname=c.pathname===`/`?t:wy([t,c.pathname])),(s.replace?n.replace:n.push)(c,s.state,s)},[t,n,a,i,e])}d.createContext(null);function rb(e,{relative:t}={}){let{matches:n}=d.useContext(Uy),{pathname:r}=Qy(),i=JSON.stringify(Sy(n));return d.useMemo(()=>Cy(e,JSON.parse(i),r,t===`path`),[e,i,r,t])}function ib(e,t){return ab(e,t)}function ab(e,t,n,r,i){Vv(Zy(),`useRoutes() may be used only in the context of a component.`);let{navigator:a}=d.useContext(Vy),{matches:o}=d.useContext(Uy),s=o[o.length-1],c=s?s.params:{},l=s?s.pathname:`/`,u=s?s.pathnameBase:`/`,f=s&&s.route;{let e=f&&f.path||``;wb(l,!f||e.endsWith(`*`)||e.endsWith(`*?`),`You rendered descendant (or called \`useRoutes()\`) at "${l}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. + +Please change the parent to .`)}let p=Qy(),m;if(t){let e=typeof t==`string`?qv(t):t;Vv(u===`/`||e.pathname?.startsWith(u),`When overriding the location using \`\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${u}" but pathname "${e.pathname}" was given in the \`location\` prop.`),m=e}else m=p;let h=m.pathname||`/`,g=h;if(u!==`/`){let e=u.replace(/^\//,``).split(`/`);g=`/`+h.replace(/^\//,``).split(`/`).slice(e.length).join(`/`)}let _=Xv(e,{pathname:g});Hv(f||_!=null,`No routes matched location "${m.pathname}${m.search}${m.hash}" `),Hv(_==null||_[_.length-1].route.element!==void 0||_[_.length-1].route.Component!==void 0||_[_.length-1].route.lazy!==void 0,`Matched leaf route at location "${m.pathname}${m.search}${m.hash}" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page.`);let v=fb(_&&_.map(e=>Object.assign({},e,{params:Object.assign({},c,e.params),pathname:wy([u,a.encodeLocation?a.encodeLocation(e.pathname.replace(/\?/g,`%3F`).replace(/#/g,`%23`)).pathname:e.pathname]),pathnameBase:e.pathnameBase===`/`?u:wy([u,a.encodeLocation?a.encodeLocation(e.pathnameBase.replace(/\?/g,`%3F`).replace(/#/g,`%23`)).pathname:e.pathnameBase])})),o,n,r,i);return t&&v?d.createElement(Hy.Provider,{value:{location:{pathname:`/`,search:``,hash:``,state:null,key:`default`,...m},navigationType:`POP`}},v):v}function ob(){let e=xb(),t=ky(e)?`${e.status} ${e.statusText}`:e instanceof Error?e.message:JSON.stringify(e),n=e instanceof Error?e.stack:null,r=`rgba(200,200,200, 0.5)`,i={padding:`0.5rem`,backgroundColor:r},a={padding:`2px 4px`,backgroundColor:r},o=null;return console.error(`Error handled by React Router default ErrorBoundary:`,e),o=d.createElement(d.Fragment,null,d.createElement(`p`,null,`💿 Hey developer 👋`),d.createElement(`p`,null,`You can provide a way better UX than this when your app throws errors by providing your own `,d.createElement(`code`,{style:a},`ErrorBoundary`),` or`,` `,d.createElement(`code`,{style:a},`errorElement`),` prop on your route.`)),d.createElement(d.Fragment,null,d.createElement(`h2`,null,`Unexpected Application Error!`),d.createElement(`h3`,{style:{fontStyle:`italic`}},t),n?d.createElement(`pre`,{style:i},n):null,o)}var sb=d.createElement(ob,null),cb=class extends d.Component{constructor(e){super(e),this.state={location:e.location,revalidation:e.revalidation,error:e.error}}static getDerivedStateFromError(e){return{error:e}}static getDerivedStateFromProps(e,t){return t.location!==e.location||t.revalidation!==`idle`&&e.revalidation===`idle`?{error:e.error,location:e.location,revalidation:e.revalidation}:{error:e.error===void 0?t.error:e.error,location:t.location,revalidation:e.revalidation||t.revalidation}}componentDidCatch(e,t){this.props.onError?this.props.onError(e,t):console.error(`React Router caught the following error during render`,e)}render(){let e=this.state.error;if(this.context&&typeof e==`object`&&e&&`digest`in e&&typeof e.digest==`string`){let t=Yy(e.digest);t&&(e=t)}let t=e===void 0?this.props.children:d.createElement(Uy.Provider,{value:this.props.routeContext},d.createElement(Wy.Provider,{value:e,children:this.props.component}));return this.context?d.createElement(ub,{error:e},t):t}};cb.contextType=Ly;var lb=new WeakMap;function ub({children:e,error:t}){let{basename:n}=d.useContext(Vy);if(typeof t==`object`&&t&&`digest`in t&&typeof t.digest==`string`){let e=Jy(t.digest);if(e){let r=lb.get(t);if(r)throw r;let i=My(e.location,n);if(jy&&!lb.get(t))if(i.isExternal||e.reloadDocument)window.location.href=i.absoluteURL||i.to;else{let n=Promise.resolve().then(()=>window.__reactRouterDataRouter.navigate(i.to,{replace:e.replace}));throw lb.set(t,n),n}return d.createElement(`meta`,{httpEquiv:`refresh`,content:`0;url=${i.absoluteURL||i.to}`})}}return e}function db({routeContext:e,match:t,children:n}){let r=d.useContext(Fy);return r&&r.static&&r.staticContext&&(t.route.errorElement||t.route.ErrorBoundary)&&(r.staticContext._deepestRenderedBoundaryId=t.route.id),d.createElement(Uy.Provider,{value:e},n)}function fb(e,t=[],n=null,r=null,i=null){if(e==null){if(!n)return null;if(n.errors)e=n.matches;else if(t.length===0&&!n.initialized&&n.matches.length>0)e=n.matches;else return null}let a=e,o=n?.errors;if(o!=null){let e=a.findIndex(e=>e.route.id&&o?.[e.route.id]!==void 0);Vv(e>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(o).join(`,`)}`),a=a.slice(0,Math.min(a.length,e+1))}let s=!1,c=-1;if(n)for(let e=0;e=0?a.slice(0,c+1):[a[0]];break}}}let l=n&&r?(e,t)=>{r(e,{location:n.location,params:n.matches?.[0]?.params??{},unstable_pattern:Ay(n.matches),errorInfo:t})}:void 0;return a.reduceRight((e,r,i)=>{let u,f=!1,p=null,m=null;n&&(u=o&&r.route.id?o[r.route.id]:void 0,p=r.route.errorElement||sb,s&&(c<0&&i===0?(wb(`route-fallback`,!1,"No `HydrateFallback` element provided to render during initial hydration"),f=!0,m=null):c===i&&(f=!0,m=r.route.hydrateFallbackElement||null)));let h=t.concat(a.slice(0,i+1)),g=()=>{let t;return t=u?p:f?m:r.route.Component?d.createElement(r.route.Component,null):r.route.element?r.route.element:e,d.createElement(db,{match:r,routeContext:{outlet:e,matches:h,isDataRoute:n!=null},children:t})};return n&&(r.route.ErrorBoundary||r.route.errorElement||i===0)?d.createElement(cb,{location:n.location,revalidation:n.revalidation,component:p,error:u,children:g(),routeContext:{outlet:null,matches:h,isDataRoute:!0},onError:l}):g()},null)}function pb(e){return`${e} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function mb(e){let t=d.useContext(Fy);return Vv(t,pb(e)),t}function hb(e){let t=d.useContext(Iy);return Vv(t,pb(e)),t}function gb(e){let t=d.useContext(Uy);return Vv(t,pb(e)),t}function _b(e){let t=gb(e),n=t.matches[t.matches.length-1];return Vv(n.route.id,`${e} can only be used on routes that contain a unique "id"`),n.route.id}function vb(){return _b(`useRouteId`)}function yb(){return hb(`useNavigation`).navigation}function bb(){let{matches:e,loaderData:t}=hb(`useMatches`);return d.useMemo(()=>e.map(e=>Qv(e,t)),[e,t])}function xb(){let e=d.useContext(Wy),t=hb(`useRouteError`),n=_b(`useRouteError`);return e===void 0?t.errors?.[n]:e}function Sb(){let{router:e}=mb(`useNavigate`),t=_b(`useNavigate`),n=d.useRef(!1);return eb(()=>{n.current=!0}),d.useCallback(async(r,i={})=>{Hv(n.current,$y),n.current&&(typeof r==`number`?await e.navigate(r):await e.navigate(r,{fromRouteId:t,...i}))},[e,t])}var Cb={};function wb(e,t,n){!t&&!Cb[e]&&(Cb[e]=!0,Hv(!1,n))}d.useOptimistic,d.memo(Tb);function Tb({routes:e,future:t,state:n,onError:r}){return ab(e,void 0,n,r,t)}function Eb(e){Vv(!1,`A is only ever to be used as the child of element, never rendered directly. Please wrap your in a .`)}function Db({basename:e=`/`,children:t=null,location:n,navigationType:r=`POP`,navigator:i,static:a=!1,unstable_useTransitions:o}){Vv(!Zy(),`You cannot render a inside another . You should never have more than one in your app.`);let s=e.replace(/^\/*/,`/`),c=d.useMemo(()=>({basename:s,navigator:i,static:a,unstable_useTransitions:o,future:{}}),[s,i,a,o]);typeof n==`string`&&(n=qv(n));let{pathname:l=`/`,search:u=``,hash:f=``,state:p=null,key:m=`default`}=n,h=d.useMemo(()=>{let e=hy(l,s);return e==null?null:{location:{pathname:e,search:u,hash:f,state:p,key:m},navigationType:r}},[s,l,u,f,p,m,r]);return Hv(h!=null,` is not able to match the URL "${l}${u}${f}" because it does not start with the basename, so the won't render anything.`),h==null?null:d.createElement(Vy.Provider,{value:c},d.createElement(Hy.Provider,{children:t,value:h}))}function Ob({children:e,location:t}){return ib(kb(e),t)}d.Component;function kb(e,t=[]){let n=[];return d.Children.forEach(e,(e,r)=>{if(!d.isValidElement(e))return;let i=[...t,r];if(e.type===d.Fragment){n.push.apply(n,kb(e.props.children,i));return}Vv(e.type===Eb,`[${typeof e.type==`string`?e.type:e.type.name}] is not a component. All component children of must be a or `),Vv(!e.props.index||!e.props.children,`An index route cannot have child routes.`);let a={id:e.props.id||i.join(`-`),caseSensitive:e.props.caseSensitive,element:e.props.element,Component:e.props.Component,index:e.props.index,path:e.props.path,middleware:e.props.middleware,loader:e.props.loader,action:e.props.action,hydrateFallbackElement:e.props.hydrateFallbackElement,HydrateFallback:e.props.HydrateFallback,errorElement:e.props.errorElement,ErrorBoundary:e.props.ErrorBoundary,hasErrorBoundary:e.props.hasErrorBoundary===!0||e.props.ErrorBoundary!=null||e.props.errorElement!=null,shouldRevalidate:e.props.shouldRevalidate,handle:e.props.handle,lazy:e.props.lazy};e.props.children&&(a.children=kb(e.props.children,i)),n.push(a)}),n}var Ab=`get`,jb=`application/x-www-form-urlencoded`;function Mb(e){return typeof HTMLElement<`u`&&e instanceof HTMLElement}function Nb(e){return Mb(e)&&e.tagName.toLowerCase()===`button`}function Pb(e){return Mb(e)&&e.tagName.toLowerCase()===`form`}function Fb(e){return Mb(e)&&e.tagName.toLowerCase()===`input`}function Ib(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}function Lb(e,t){return e.button===0&&(!t||t===`_self`)&&!Ib(e)}var Rb=null;function zb(){if(Rb===null)try{new FormData(document.createElement(`form`),0),Rb=!1}catch{Rb=!0}return Rb}var Bb=new Set([`application/x-www-form-urlencoded`,`multipart/form-data`,`text/plain`]);function Vb(e){return e!=null&&!Bb.has(e)?(Hv(!1,`"${e}" is not a valid \`encType\` for \`
\`/\`\` and will default to "${jb}"`),null):e}function Hb(e,t){let n,r,i,a,o;if(Pb(e)){let o=e.getAttribute(`action`);r=o?hy(o,t):null,n=e.getAttribute(`method`)||Ab,i=Vb(e.getAttribute(`enctype`))||jb,a=new FormData(e)}else if(Nb(e)||Fb(e)&&(e.type===`submit`||e.type===`image`)){let o=e.form;if(o==null)throw Error(`Cannot submit a + + + ); +}; diff --git a/knip.json b/knip.json index 616f758cc..95663f9ea 100644 --- a/knip.json +++ b/knip.json @@ -100,7 +100,14 @@ ".github/**" ], "ignoreIssues": { - "codegen.yml": ["unlisted"] + "codegen.yml": ["unlisted"], + "apps/ui-staff/package.json": ["dependencies","devDependencies"], + "packages/ocom/ui-staff-route-root/package.json": ["dependencies","devDependencies"], + "packages/ocom/ui-staff-route-community-management/package.json": ["dependencies","devDependencies"], + "packages/ocom/ui-staff-route-tech-admin/package.json": ["dependencies","devDependencies"], + "packages/ocom/ui-staff-route-finance/package.json": ["dependencies","devDependencies"], + "packages/ocom/ui-staff-route-user-management/package.json": ["dependencies","devDependencies"], + "apps/ui-staff/src/apollo-connection.tsx": ["types"] }, "ignoreDependencies": [ "@types/*", @@ -115,7 +122,9 @@ "@graphql-typed-document-node/core", "@vitest/coverage-v8", "ts-scope-trimmer-plugin", - "chrome-devtools-mcp" + "chrome-devtools-mcp", + "storybook-addon-apollo-client", + "tailwindcss" ], "ignoreBinaries": ["func"] } diff --git a/packages/ocom/ui-staff-route-root/package.json b/packages/ocom/ui-staff-route-root/package.json index 6c4a8aefc..c90d70478 100644 --- a/packages/ocom/ui-staff-route-root/package.json +++ b/packages/ocom/ui-staff-route-root/package.json @@ -15,7 +15,10 @@ "test:watch": "vitest" }, "dependencies": { - "antd": "catalog:", + "@ocom/ui-staff-route-community-management": "workspace:*", + "@ocom/ui-staff-route-finance": "workspace:*", + "@ocom/ui-staff-route-tech-admin": "workspace:*", + "@ocom/ui-staff-route-user-management": "workspace:*", "react": "^19.1.1", "react-dom": "^19.1.1" }, diff --git a/packages/ocom/ui-staff-route-root/src/section-layout.tsx b/packages/ocom/ui-staff-route-root/src/section-layout.tsx index b9dbbba43..1046f95b1 100644 --- a/packages/ocom/ui-staff-route-root/src/section-layout.tsx +++ b/packages/ocom/ui-staff-route-root/src/section-layout.tsx @@ -1,3 +1,19 @@ -export const SectionLayout: React.FC = () => { - return
Staff Root Placeholder
; +import type { FC } from 'react'; + +export const SectionLayout: FC = () => { + return ( +
+ +
+
Welcome to Staff area. Select a section from the menu.
+
+
+ ); }; diff --git a/packages/ocom/ui-staff-route-shared/package.json b/packages/ocom/ui-staff-route-shared/package.json index bf7e8c317..edeecb223 100644 --- a/packages/ocom/ui-staff-route-shared/package.json +++ b/packages/ocom/ui-staff-route-shared/package.json @@ -15,9 +15,7 @@ "test:watch": "vitest" }, "dependencies": { - "antd": "catalog:", - "react": "^19.1.1", - "react-dom": "^19.1.1" + "react": "^19.1.1" }, "devDependencies": { "@cellix/config-typescript": "workspace:*", @@ -25,7 +23,6 @@ "@types/react": "^19.1.11", "@types/react-dom": "^19.1.6", "jsdom": "catalog:", - "storybook": "catalog:", "vite": "catalog:", "vitest": "catalog:", "typescript": "catalog:" diff --git a/packages/ocom/ui-staff-route-tech-admin/package.json b/packages/ocom/ui-staff-route-tech-admin/package.json index d1fe24129..e3bed5e33 100644 --- a/packages/ocom/ui-staff-route-tech-admin/package.json +++ b/packages/ocom/ui-staff-route-tech-admin/package.json @@ -16,8 +16,7 @@ }, "dependencies": { "antd": "catalog:", - "react": "^19.1.1", - "react-dom": "^19.1.1" + "react": "^19.1.1" }, "devDependencies": { "@cellix/config-typescript": "workspace:*", diff --git a/packages/ocom/ui-staff-route-user-management/package.json b/packages/ocom/ui-staff-route-user-management/package.json index 2c1d7a50a..79fe087b8 100644 --- a/packages/ocom/ui-staff-route-user-management/package.json +++ b/packages/ocom/ui-staff-route-user-management/package.json @@ -15,9 +15,7 @@ "test:watch": "vitest" }, "dependencies": { - "antd": "catalog:", - "react": "^19.1.1", - "react-dom": "^19.1.1" + "react": "^19.1.1" }, "devDependencies": { "@cellix/config-typescript": "workspace:*", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4de3b1bbb..08988f18f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -493,12 +493,30 @@ importers: '@graphql-typed-document-node/core': specifier: ^3.2.0 version: 3.2.0(graphql@16.12.0) + '@ocom/ui-staff-route-community-management': + specifier: workspace:* + version: link:../../packages/ocom/ui-staff-route-community-management + '@ocom/ui-staff-route-finance': + specifier: workspace:* + version: link:../../packages/ocom/ui-staff-route-finance '@ocom/ui-staff-route-root': specifier: workspace:* version: link:../../packages/ocom/ui-staff-route-root + '@ocom/ui-staff-route-shared': + specifier: workspace:* + version: link:../../packages/ocom/ui-staff-route-shared + '@ocom/ui-staff-route-tech-admin': + specifier: workspace:* + version: link:../../packages/ocom/ui-staff-route-tech-admin + '@ocom/ui-staff-route-user-management': + specifier: workspace:* + version: link:../../packages/ocom/ui-staff-route-user-management antd: specifier: 'catalog:' version: 6.3.5(luxon@3.6.1)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + apollo-link-rest: + specifier: ^0.9.0 + version: 0.9.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(qs@6.15.0) less: specifier: ^4.4.0 version: 4.4.2 @@ -1806,16 +1824,16 @@ importers: version: 26.1.0 storybook: specifier: 'catalog:' - version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) typescript: specifier: 'catalog:' version: 6.0.2 vite: specifier: 8.0.5 - version: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + version: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) vitest: specifier: 'catalog:' - version: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/ui-staff-route-finance: dependencies: @@ -1859,6 +1877,18 @@ importers: packages/ocom/ui-staff-route-root: dependencies: + '@ocom/ui-staff-route-community-management': + specifier: workspace:* + version: link:../ui-staff-route-community-management + '@ocom/ui-staff-route-finance': + specifier: workspace:* + version: link:../ui-staff-route-finance + '@ocom/ui-staff-route-tech-admin': + specifier: workspace:* + version: link:../ui-staff-route-tech-admin + '@ocom/ui-staff-route-user-management': + specifier: workspace:* + version: link:../ui-staff-route-user-management antd: specifier: 'catalog:' version: 6.3.5(luxon@3.6.1)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -1868,6 +1898,9 @@ importers: react-dom: specifier: ^19.1.1 version: 19.2.0(react@19.2.0) + react-router-dom: + specifier: 'catalog:' + version: 7.12.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) devDependencies: '@cellix/config-typescript': specifier: workspace:* @@ -18147,20 +18180,6 @@ snapshots: - vite optional: true - '@vitest/browser-playwright@4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': - dependencies: - '@vitest/browser': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) - '@vitest/mocker': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - playwright: 1.59.0 - tinyrainbow: 3.1.0 - vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - transitivePeerDependencies: - - bufferutil - - msw - - utf-8-validate - - vite - optional: true - '@vitest/browser-playwright@4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': dependencies: '@vitest/browser': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) @@ -18192,24 +18211,6 @@ snapshots: - vite optional: true - '@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': - dependencies: - '@blazediff/core': 1.9.1 - '@vitest/mocker': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@vitest/utils': 4.1.2 - magic-string: 0.30.21 - pngjs: 7.0.0 - sirv: 3.0.2 - tinyrainbow: 3.1.0 - vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - ws: 8.20.0 - transitivePeerDependencies: - - bufferutil - - msw - - utf-8-validate - - vite - optional: true - '@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': dependencies: '@blazediff/core': 1.9.1 @@ -18260,14 +18261,6 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@3.2.4(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': - dependencies: - '@vitest/spy': 3.2.4 - estree-walker: 3.0.3 - magic-string: 0.30.21 - optionalDependencies: - vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) - '@vitest/mocker@3.2.4(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@vitest/spy': 3.2.4 @@ -18284,14 +18277,6 @@ snapshots: optionalDependencies: vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@22.19.15)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) - '@vitest/mocker@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': - dependencies: - '@vitest/spy': 4.1.2 - estree-walker: 3.0.3 - magic-string: 0.30.21 - optionalDependencies: - vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) - '@vitest/mocker@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@vitest/spy': 4.1.2 @@ -24513,28 +24498,6 @@ snapshots: graphql: 16.12.0 react: 19.2.0 - storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): - dependencies: - '@storybook/global': 5.0.0 - '@testing-library/jest-dom': 6.9.1 - '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1) - '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@vitest/spy': 3.2.4 - better-opn: 3.0.2 - esbuild: 0.25.12 - esbuild-register: 3.6.0(esbuild@0.25.12) - recast: 0.23.11 - semver: 7.7.3 - ws: 8.20.0 - transitivePeerDependencies: - - '@testing-library/dom' - - bufferutil - - msw - - supports-color - - utf-8-validate - - vite - storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): dependencies: '@storybook/global': 5.0.0 @@ -25261,26 +25224,6 @@ snapshots: - '@emnapi/core' - '@emnapi/runtime' - vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3): - dependencies: - lightningcss: 1.32.0 - picomatch: 4.0.4 - postcss: 8.5.8 - rolldown: 1.0.0-rc.12(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1) - tinyglobby: 0.2.15 - optionalDependencies: - '@types/node': 24.10.1 - esbuild: 0.25.12 - fsevents: 2.3.3 - jiti: 2.6.1 - less: 4.4.2 - terser: 5.44.1 - tsx: 4.21.0 - yaml: 2.8.3 - transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' - vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3): dependencies: lightningcss: 1.32.0 @@ -25331,36 +25274,6 @@ snapshots: transitivePeerDependencies: - msw - vitest@4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): - dependencies: - '@vitest/expect': 4.1.2 - '@vitest/mocker': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@vitest/pretty-format': 4.1.2 - '@vitest/runner': 4.1.2 - '@vitest/snapshot': 4.1.2 - '@vitest/spy': 4.1.2 - '@vitest/utils': 4.1.2 - es-module-lexer: 2.0.0 - expect-type: 1.3.0 - magic-string: 0.30.21 - obug: 2.1.1 - pathe: 2.0.3 - picomatch: 4.0.4 - std-env: 4.0.0 - tinybench: 2.9.0 - tinyexec: 1.0.4 - tinyglobby: 0.2.15 - tinyrainbow: 3.1.0 - vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) - why-is-node-running: 2.3.0 - optionalDependencies: - '@opentelemetry/api': 1.9.0 - '@types/node': 24.10.1 - '@vitest/browser-playwright': 4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) - jsdom: 26.1.0 - transitivePeerDependencies: - - msw - vitest@4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): dependencies: '@vitest/expect': 4.1.2 From 2c502392f5cb2709674426fe8577f8dd2b1f52a5 Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Thu, 23 Apr 2026 11:26:40 -0400 Subject: [PATCH 05/88] add pnpm-lock.yaml --- pnpm-lock.yaml | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 08988f18f..026a687b6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1889,18 +1889,12 @@ importers: '@ocom/ui-staff-route-user-management': specifier: workspace:* version: link:../ui-staff-route-user-management - antd: - specifier: 'catalog:' - version: 6.3.5(luxon@3.6.1)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: specifier: ^19.1.1 version: 19.2.0 react-dom: specifier: ^19.1.1 version: 19.2.0(react@19.2.0) - react-router-dom: - specifier: 'catalog:' - version: 7.12.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) devDependencies: '@cellix/config-typescript': specifier: workspace:* @@ -1932,15 +1926,9 @@ importers: packages/ocom/ui-staff-route-shared: dependencies: - antd: - specifier: 'catalog:' - version: 6.3.5(luxon@3.6.1)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: specifier: ^19.1.1 version: 19.2.0 - react-dom: - specifier: ^19.1.1 - version: 19.2.0(react@19.2.0) devDependencies: '@cellix/config-typescript': specifier: workspace:* @@ -1957,9 +1945,6 @@ importers: jsdom: specifier: 'catalog:' version: 26.1.0 - storybook: - specifier: 'catalog:' - version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) typescript: specifier: 'catalog:' version: 6.0.2 @@ -1978,9 +1963,6 @@ importers: react: specifier: ^19.1.1 version: 19.2.0 - react-dom: - specifier: ^19.1.1 - version: 19.2.0(react@19.2.0) devDependencies: '@cellix/config-typescript': specifier: workspace:* @@ -2012,15 +1994,9 @@ importers: packages/ocom/ui-staff-route-user-management: dependencies: - antd: - specifier: 'catalog:' - version: 6.3.5(luxon@3.6.1)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: specifier: ^19.1.1 version: 19.2.0 - react-dom: - specifier: ^19.1.1 - version: 19.2.0(react@19.2.0) devDependencies: '@cellix/config-typescript': specifier: workspace:* From cfa2563b6a7ffea8339999aa3b28818d25a87523 Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Thu, 23 Apr 2026 12:43:38 -0400 Subject: [PATCH 06/88] feat: add uuid dependency to package.json and update pnpm-lock.yaml --- package.json | 3 ++- pnpm-lock.yaml | 63 ++++++++++++++++++++++---------------------------- 2 files changed, 29 insertions(+), 37 deletions(-) diff --git a/package.json b/package.json index d7975099f..dbd9903e1 100644 --- a/package.json +++ b/package.json @@ -117,7 +117,8 @@ "webpack": "^5.105.4", "playwright-core": "1.59.0", "playwright": "1.59.0", - "protobufjs": "7.5.5" + "protobufjs": "7.5.5", + "uuid": "^14.0.0" }, "patchedDependencies": { "@azure/functions@4.11.0": "patches/@azure__functions@4.11.0.patch" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 026a687b6..d81b0b29b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -82,6 +82,7 @@ overrides: playwright-core: 1.59.0 playwright: 1.59.0 protobufjs: 7.5.5 + uuid: ^14.0.0 patchedDependencies: '@azure/functions@4.11.0': @@ -1797,6 +1798,9 @@ importers: packages/ocom/ui-staff-route-community-management: dependencies: + '@ocom/ui-staff-route-shared': + specifier: workspace:* + version: link:../ui-staff-route-shared antd: specifier: 'catalog:' version: 6.3.5(luxon@3.6.1)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -1837,6 +1841,9 @@ importers: packages/ocom/ui-staff-route-finance: dependencies: + '@ocom/ui-staff-route-shared': + specifier: workspace:* + version: link:../ui-staff-route-shared antd: specifier: 'catalog:' version: 6.3.5(luxon@3.6.1)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -1883,6 +1890,9 @@ importers: '@ocom/ui-staff-route-finance': specifier: workspace:* version: link:../ui-staff-route-finance + '@ocom/ui-staff-route-shared': + specifier: workspace:* + version: link:../ui-staff-route-shared '@ocom/ui-staff-route-tech-admin': specifier: workspace:* version: link:../ui-staff-route-tech-admin @@ -1957,6 +1967,9 @@ importers: packages/ocom/ui-staff-route-tech-admin: dependencies: + '@ocom/ui-staff-route-shared': + specifier: workspace:* + version: link:../ui-staff-route-shared antd: specifier: 'catalog:' version: 6.3.5(luxon@3.6.1)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -1994,6 +2007,9 @@ importers: packages/ocom/ui-staff-route-user-management: dependencies: + '@ocom/ui-staff-route-shared': + specifier: workspace:* + version: link:../ui-staff-route-shared react: specifier: ^19.1.1 version: 19.2.0 @@ -12263,25 +12279,8 @@ packages: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} - uuid@10.0.0: - resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} - hasBin: true - - uuid@11.0.5: - resolution: {integrity: sha512-508e6IcKLrhxKdBbcA2b4KQZlLVp2+J5UwQ6F7Drckkc5N9ZJwFa4TgWtsww9UG8fGHbm6gbV19TdM5pQ4GaIA==} - hasBin: true - - uuid@11.1.0: - resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} - hasBin: true - - uuid@3.4.0: - resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} - deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. - hasBin: true - - uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + uuid@14.0.0: + resolution: {integrity: sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==} hasBin: true validate-npm-package-license@3.0.4: @@ -13059,7 +13058,7 @@ snapshots: loglevel: 1.9.2 lru-cache: 11.2.4 negotiator: 1.0.0 - uuid: 11.1.0 + uuid: 14.0.0 whatwg-mimetype: 4.0.0 transitivePeerDependencies: - supports-color @@ -13342,7 +13341,7 @@ snapshots: tough-cookie: 2.5.0 tslib: 1.14.1 tunnel: 0.0.6 - uuid: 3.4.0 + uuid: 14.0.0 xml2js: 0.4.23 transitivePeerDependencies: - debug @@ -13358,7 +13357,7 @@ snapshots: dependencies: '@azure/msal-common': 14.16.1 jsonwebtoken: 9.0.2 - uuid: 8.3.2 + uuid: 14.0.0 '@azure/opentelemetry-instrumentation-azure-sdk@1.0.0-beta.9': dependencies: @@ -14597,14 +14596,14 @@ snapshots: '@types/uuid': 10.0.0 class-transformer: 0.5.1 reflect-metadata: 0.2.2 - uuid: 10.0.0 + uuid: 14.0.0 '@cucumber/messages@27.2.0': dependencies: '@types/uuid': 10.0.0 class-transformer: 0.5.1 reflect-metadata: 0.2.2 - uuid: 11.0.5 + uuid: 14.0.0 '@cucumber/node@0.4.0': dependencies: @@ -18777,7 +18776,7 @@ snapshots: to-readable-stream: 2.1.0 tslib: 2.8.1 uri-templates: 0.2.0 - uuid: 3.4.0 + uuid: 14.0.0 winston: 3.18.3 xml2js: 0.6.2 transitivePeerDependencies: @@ -24170,7 +24169,7 @@ snapshots: semver: 7.7.3 sequelize-pool: 7.1.0 toposort-class: 1.0.1 - uuid: 8.3.2 + uuid: 14.0.0 validator: 13.15.23 wkx: 0.5.0 optionalDependencies: @@ -24366,7 +24365,7 @@ snapshots: sockjs@0.3.24: dependencies: faye-websocket: 0.11.4 - uuid: 8.3.2 + uuid: 14.0.0 websocket-driver: 0.7.4 sort-css-media-queries@2.2.0: {} @@ -25140,15 +25139,7 @@ snapshots: utils-merge@1.0.1: {} - uuid@10.0.0: {} - - uuid@11.0.5: {} - - uuid@11.1.0: {} - - uuid@3.4.0: {} - - uuid@8.3.2: {} + uuid@14.0.0: {} validate-npm-package-license@3.0.4: dependencies: From d92e9357c2ace2cee5f97720fbb470036682f38b Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Thu, 23 Apr 2026 14:42:21 -0400 Subject: [PATCH 07/88] feat: add AuthLanding component for navigation and Apollo client setup --- .../apollo-connection/apollo-client-links.tsx | 11 +- .../{index-BLplskbw.js => index-D51pPdcv.js} | 90 +++++----- apps/ui-staff/dist/index.html | 2 +- apps/ui-staff/src/App.tsx | 4 +- apps/ui-staff/src/apollo-connection.tsx | 5 +- .../ui/molecules/auth-landing}/index.tsx | 0 .../apollo-client-links.spec.ts | 52 ++++++ .../apollo-client-links.tsx | 11 +- .../ui/organisms/apollo-connection/index.tsx | 64 +++++++ .../src/contexts/theme-context.test.tsx | 20 +++ apps/ui-staff/src/contexts/theme-context.tsx | 169 +++++++++++++++++- apps/ui-staff/src/main.tsx | 16 +- .../package.json | 1 + .../src/section-layout.tsx | 12 +- .../ocom/ui-staff-route-finance/package.json | 1 + .../src/section-layout.tsx | 12 +- .../ocom/ui-staff-route-root/package.json | 1 + .../src/section-layout.tsx | 18 +- .../ocom/ui-staff-route-shared/src/index.tsx | 1 + .../src/section-layout.tsx | 12 +- .../src/staff-route-shell.tsx | 56 ++++++ .../ui-staff-route-tech-admin/package.json | 1 + .../src/section-layout.tsx | 12 +- .../package.json | 1 + .../src/section-layout.tsx | 12 +- 25 files changed, 501 insertions(+), 83 deletions(-) rename apps/ui-staff/dist/assets/{index-BLplskbw.js => index-D51pPdcv.js} (84%) rename apps/ui-staff/src/{ => components/ui/molecules/auth-landing}/index.tsx (100%) create mode 100644 apps/ui-staff/src/components/ui/organisms/apollo-connection/apollo-client-links.spec.ts rename apps/ui-staff/src/{ => components/ui/organisms/apollo-connection}/apollo-client-links.tsx (91%) create mode 100644 apps/ui-staff/src/components/ui/organisms/apollo-connection/index.tsx create mode 100644 apps/ui-staff/src/contexts/theme-context.test.tsx create mode 100644 packages/ocom/ui-staff-route-shared/src/staff-route-shell.tsx diff --git a/apps/ui-community/src/components/ui/organisms/apollo-connection/apollo-client-links.tsx b/apps/ui-community/src/components/ui/organisms/apollo-connection/apollo-client-links.tsx index f4a8ec5dc..6afb66bab 100644 --- a/apps/ui-community/src/components/ui/organisms/apollo-connection/apollo-client-links.tsx +++ b/apps/ui-community/src/components/ui/organisms/apollo-connection/apollo-client-links.tsx @@ -89,9 +89,16 @@ export const ApolloLinkToAddCustomHeader = (headerName: string, headerValue: str return forward(operation); } operation.setContext((prevContext: DefaultContext) => { + // Avoid mutating prevContext or prevContext.headers. Return a new context object instead. // biome-ignore lint:useLiteralKeys - prevContext['headers'][headerName] = headerValue; - return prevContext; + const prevHeaders = (prevContext && (prevContext as Record)['headers']) ?? {}; + return { + ...prevContext, + headers: { + ...prevHeaders, + [headerName]: headerValue, + }, + }; }); return forward(operation); }); diff --git a/apps/ui-staff/dist/assets/index-BLplskbw.js b/apps/ui-staff/dist/assets/index-D51pPdcv.js similarity index 84% rename from apps/ui-staff/dist/assets/index-BLplskbw.js rename to apps/ui-staff/dist/assets/index-D51pPdcv.js index c9479eba3..e264c4f55 100644 --- a/apps/ui-staff/dist/assets/index-BLplskbw.js +++ b/apps/ui-staff/dist/assets/index-D51pPdcv.js @@ -179,34 +179,34 @@ Error generating stack: `+e.message+` `,wy=[`letter-spacing`,`line-height`,`padding-top`,`padding-bottom`,`font-family`,`font-weight`,`font-size`,`font-variant`,`text-rendering`,`text-transform`,`width`,`text-indent`,`padding-left`,`padding-right`,`border-width`,`box-sizing`,`word-break`,`white-space`],Ty={},Ey;function Dy(e,t=!1){let n=e.getAttribute(`id`)||e.getAttribute(`data-reactid`)||e.getAttribute(`name`);if(t&&Ty[n])return Ty[n];let r=window.getComputedStyle(e),i=r.getPropertyValue(`box-sizing`)||r.getPropertyValue(`-moz-box-sizing`)||r.getPropertyValue(`-webkit-box-sizing`),a=parseFloat(r.getPropertyValue(`padding-bottom`))+parseFloat(r.getPropertyValue(`padding-top`)),o=parseFloat(r.getPropertyValue(`border-bottom-width`))+parseFloat(r.getPropertyValue(`border-top-width`)),s={sizingStyle:wy.map(e=>`${e}:${r.getPropertyValue(e)}`).join(`;`),paddingSize:a,borderSize:o,boxSizing:i};return t&&n&&(Ty[n]=s),s}function Oy(e,t=!1,n=null,r=null){Ey||(Ey=document.createElement(`textarea`),Ey.setAttribute(`tab-index`,`-1`),Ey.setAttribute(`aria-hidden`,`true`),Ey.setAttribute(`name`,`hiddenTextarea`),document.body.appendChild(Ey)),e.getAttribute(`wrap`)?Ey.setAttribute(`wrap`,e.getAttribute(`wrap`)):Ey.removeAttribute(`wrap`);let{paddingSize:i,borderSize:a,boxSizing:o,sizingStyle:s}=Dy(e,t);Ey.setAttribute(`style`,`${s};${Cy}`),Ey.value=e.value||e.placeholder||``;let c,l,u,d=Ey.scrollHeight;if(o===`border-box`?d+=a:o===`content-box`&&(d-=i),n!==null||r!==null){Ey.value=` `;let e=Ey.scrollHeight-i;n!==null&&(c=e*n,o===`border-box`&&(c=c+i+a),d=Math.max(c,d)),r!==null&&(l=e*r,o===`border-box`&&(l=l+i+a),u=d>l?``:`hidden`,d=Math.min(l,d))}let f={height:d,overflowY:u,resize:`none`};return c&&(f.minHeight=c),l&&(f.maxHeight=l),f}function ky(){return ky=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{prefixCls:n,defaultValue:r,value:i,autoSize:a,onResize:o,className:s,style:c,disabled:l,onChange:u,onInternalAutoSize:d,...f}=e,[p,h]=xe(r,i),g=p??``,_=e=>{h(e.target.value),u?.(e)},v=m.useRef();m.useImperativeHandle(t,()=>({textArea:v.current}));let[y,b]=m.useMemo(()=>a&&typeof a==`object`?[a.minRows,a.maxRows]:[],[a]),x=!!a,[S,C]=m.useState(My),[w,T]=m.useState(),E=()=>{C(Ay)};G(()=>{x&&E()},[i,y,b,x]),G(()=>{if(S===Ay)C(jy);else if(S===jy){let e=Oy(v.current,!1,y,b);C(My),T(e)}},[S]);let D=m.useRef(),O=()=>{It.cancel(D.current)},k=e=>{S===My&&(o?.(e),a&&(O(),D.current=It(()=>{E()})))};m.useEffect(()=>O,[]);let A=x?w:null,j={...c,...A};return(S===Ay||S===jy)&&(j.overflowY=`hidden`,j.overflowX=`hidden`),m.createElement(Ct,{onResize:k,disabled:!(a||o)},m.createElement(`textarea`,ky({},f,{ref:v,style:j,className:K(n,s,{[`${n}-disabled`]:l}),disabled:l,value:g,onChange:_})))});function Py(){return Py=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let[O,k]=xe(e,t),A=O==null?``:String(O),[j,M]=m.useState(!1),N=m.useRef(!1),[P,F]=m.useState(null),I=(0,m.useRef)(null),L=(0,m.useRef)(null),ee=()=>L.current?.textArea,R=()=>{ee().focus()};(0,m.useImperativeHandle)(D,()=>({resizableTextArea:L.current,focus:R,blur:()=>{ee().blur()},nativeElement:I.current?.nativeElement||ee()})),(0,m.useEffect)(()=>{M(e=>!g&&e)},[g]);let[z,B]=m.useState(null);m.useEffect(()=>{z&&ee().setSelectionRange(...z)},[z]);let V=fy(f,d),te=V.max??o,ne=Number(te)>0,re=V.strategy(A),ie=!!te&&re>te,ae=(e,t)=>{let n=t;!N.current&&V.exceedFormatter&&V.max&&V.strategy(t)>V.max&&(n=V.exceedFormatter(t,{max:V.max}),t!==n&&B([ee().selectionStart||0,ee().selectionEnd||0])),k(n),ly(e.currentTarget,e,i,n)},oe=e=>{N.current=!0,s?.(e)},H=e=>{N.current=!1,ae(e,e.currentTarget.value),c?.(e)},se=e=>{ae(e,e.target.value)},ce=e=>{e.key===`Enter`&&S&&!e.nativeEvent.isComposing&&S(e),T?.(e)},le=e=>{M(!0),n?.(e)},U=e=>{M(!1),r?.(e)},ue=e=>{k(``),R(),ly(ee(),e,i)},de=l,fe;V.show&&(fe=V.showFormatter?V.showFormatter({value:A,count:re,maxLength:te}):`${re}${ne?` / ${te}`:``}`,de=m.createElement(m.Fragment,null,de,m.createElement(`span`,{className:K(`${u}-data-count`,v?.count),style:y?.count},fe)));let pe=e=>{b?.(e),ee()?.style.height&&F(!0)},me=!w&&!d&&!a;return m.createElement(dy,{ref:I,value:A,allowClear:a,handleReset:ue,suffix:de,prefixCls:u,classNames:{...v,affixWrapper:K(v?.affixWrapper,{[`${u}-show-count`]:d,[`${u}-textarea-allow-clear`]:a})},disabled:g,focused:j,className:K(p,ie&&`${u}-out-of-range`),style:{...h,...P&&!me?{height:`auto`}:{}},dataAttrs:{affixWrapper:{"data-count":typeof fe==`string`?fe:void 0}},hidden:_,readOnly:C,onClear:x},m.createElement(Ny,Py({},E,{autoSize:w,maxLength:o,onKeyDown:ce,onChange:se,onFocus:le,onBlur:U,onCompositionStart:oe,onCompositionEnd:H,className:K(v?.textarea),style:{resize:h?.resize,...y?.textarea},disabled:g,prefixCls:u,onResize:pe,ref:L,readOnly:C})))}),Iy=e=>{let{componentCls:t,paddingLG:n}=e,r=`${t}-textarea`;return{[`textarea${t}`]:{maxWidth:`100%`,height:`auto`,minHeight:e.controlHeight,lineHeight:e.lineHeight,verticalAlign:`bottom`,transition:`all ${e.motionDurationSlow}`,resize:`vertical`,[`&${t}-mouse-active`]:{transition:`all ${e.motionDurationSlow}, height 0s, width 0s`}},[`${t}-textarea-affix-wrapper-resize-dirty`]:{width:`auto`},[r]:{position:`relative`,"&-show-count":{[`${t}-data-count`]:{position:`absolute`,bottom:e.calc(e.fontSize).mul(e.lineHeight).mul(-1).equal(),insetInlineEnd:0,color:e.colorTextDescription,whiteSpace:`nowrap`,pointerEvents:`none`}},[` &-allow-clear > ${t}, &-affix-wrapper${r}-has-feedback ${t} - `]:{paddingInlineEnd:n},[`&-affix-wrapper${t}-affix-wrapper`]:{padding:0,[`> textarea${t}`]:{fontSize:`inherit`,border:`none`,outline:`none`,background:`transparent`,minHeight:e.calc(e.controlHeight).sub(e.calc(e.lineWidth).mul(2)).equal(),"&:focus":{boxShadow:`none !important`}},[`${t}-suffix`]:{margin:0,"> *:not(:last-child)":{marginInline:0},[`${t}-clear-icon`]:{position:`absolute`,insetInlineEnd:e.paddingInline,insetBlockStart:e.paddingXS},[`${r}-suffix`]:{position:`absolute`,top:0,insetInlineEnd:e.paddingInline,bottom:0,zIndex:1,display:`inline-flex`,alignItems:`center`,margin:`auto`,pointerEvents:`none`}}},[`&-affix-wrapper${t}-affix-wrapper-rtl`]:{[`${t}-suffix`]:{[`${t}-data-count`]:{direction:`ltr`,insetInlineStart:0}}},[`&-affix-wrapper${t}-affix-wrapper-sm`]:{[`${t}-suffix`]:{[`${t}-clear-icon`]:{insetInlineEnd:e.paddingInlineSM}}}}}},Ly=Io([`Input`,`TextArea`],e=>Iy(Yi(e,Sv(e))),Cv,{resetFont:!1}),Ry=(0,m.forwardRef)((e,t)=>{let{prefixCls:n,bordered:r=!0,size:i,disabled:a,status:o,allowClear:s,classNames:c,rootClassName:l,className:u,style:d,styles:f,variant:p,showCount:h,onMouseDown:g,onResize:_,...v}=e,{getPrefixCls:y,direction:b,allowClear:x,autoComplete:S,className:C,style:w,classNames:T,styles:E}=Ht(`textArea`),D=m.useContext(Lu),O=a??D,{status:k,hasFeedback:A,feedbackIcon:j}=m.useContext(Mh),M=L_(k,o),[N,P]=cl([T,c],[E,f],{props:e}),F=m.useRef(null);m.useImperativeHandle(t,()=>({resizableTextArea:F.current?.resizableTextArea,focus:e=>{wp(F.current?.resizableTextArea?.textArea,e)},blur:()=>F.current?.blur(),nativeElement:F.current?.nativeElement||null}));let I=y(`input`,n),L=yl(I),[ee,R]=Xv(I,l);Ly(I,L);let{compactSize:z,compactItemClassnames:B}=Yd(I,b),V=Kd(e=>i??z??e),[te,ne]=R_(`textArea`,p,r),re=py(s??x),[ie,ae]=m.useState(!1),[oe,H]=m.useState(!1),se=e=>{ae(!0),g?.(e);let t=()=>{ae(!1),document.removeEventListener(`mouseup`,t)};document.addEventListener(`mouseup`,t)},ce=e=>{if(_?.(e),ie&&typeof getComputedStyle==`function`){let e=F.current?.nativeElement?.querySelector(`textarea`);e&&getComputedStyle(e).resize===`both`&&H(!0)}};return m.createElement(Fy,{autoComplete:S,...v,style:{...P.root,...w,...d},styles:P,disabled:O,allowClear:re,className:K(R,L,u,l,B,C,N.root,{[`${I}-textarea-affix-wrapper-resize-dirty`]:oe}),classNames:{...N,textarea:K({[`${I}-sm`]:V===`small`,[`${I}-lg`]:V===`large`},ee,N.textarea,ie&&`${I}-mouse-active`),variant:K({[`${I}-${te}`]:ne},I_(I,M)),affixWrapper:K(`${I}-textarea-affix-wrapper`,{[`${I}-affix-wrapper-rtl`]:b===`rtl`,[`${I}-affix-wrapper-sm`]:V===`small`,[`${I}-affix-wrapper-lg`]:V===`large`,[`${I}-textarea-show-count`]:h||e.count?.show},ee)},prefixCls:I,suffix:A&&m.createElement(`span`,{className:`${I}-textarea-suffix`},j),showCount:h,ref:F,onResize:ce,onMouseDown:se})}),zy=100,By=zy/5,Vy=zy/2-By/2,Hy=Vy*2*Math.PI,Uy=50,Wy=e=>{let{dotClassName:t,style:n,hasCircleCls:r}=e;return m.createElement(`circle`,{className:K(`${t}-circle`,{[`${t}-circle-bg`]:r}),r:Vy,cx:Uy,cy:Uy,strokeWidth:By,style:n})},Gy=({percent:e,prefixCls:t})=>{let n=`${t}-dot`,r=`${n}-holder`,i=`${r}-hidden`,[a,o]=m.useState(!1);G(()=>{e!==0&&o(!0)},[e!==0]);let s=Math.max(Math.min(e,100),0);if(!a)return null;let c={strokeDashoffset:`${Hy/4}`,strokeDasharray:`${Hy*s/100} ${Hy*(100-s)/100}`};return m.createElement(`span`,{className:K(r,`${n}-progress`,s<=0&&i)},m.createElement(`svg`,{viewBox:`0 0 ${zy} ${zy}`,role:`progressbar`,"aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":s},m.createElement(Wy,{dotClassName:n,hasCircleCls:!0}),m.createElement(Wy,{dotClassName:n,style:c})))};function Ky(e){let{prefixCls:t,percent:n=0,className:r,style:i}=e,a=`${t}-dot`,o=`${a}-holder`,s=`${o}-hidden`;return m.createElement(m.Fragment,null,m.createElement(`span`,{className:K(o,r,n>0&&s),style:i},m.createElement(`span`,{className:K(a,`${t}-dot-spin`)},[1,2,3,4].map(e=>m.createElement(`i`,{className:`${t}-dot-item`,key:e})))),m.createElement(Gy,{prefixCls:t,percent:n}))}function qy(e){let{prefixCls:t,indicator:n,percent:r,className:i,style:a}=e,o=`${t}-dot`;return n&&m.isValidElement(n)?Mu(n,e=>({className:K(e.className,o,i),style:{...e.style,...a},percent:r})):m.createElement(Ky,{prefixCls:t,percent:r,className:i,style:a})}var Jy=new gi(`antSpinMove`,{to:{opacity:1}}),Yy=new gi(`antRotate`,{to:{transform:`rotate(405deg)`}}),Xy=e=>{let{componentCls:t}=e,n=`${t}-section`;return{[t]:{...Do(e),position:`relative`,"&-rtl":{direction:`rtl`},[`&${n}, ${n}`]:{display:`flex`,alignItems:`center`,flexDirection:`column`,gap:e.paddingSM,color:e.colorPrimary},[`&${n}`]:{display:`inline-flex`},[n]:{position:`absolute`,top:`50%`,left:{_skip_check_:!0,value:`50%`},transform:`translate(-50%, -50%)`,zIndex:1},[`${t}-description`]:{fontSize:e.fontSize,lineHeight:1},[`${t}-container`]:{position:`relative`,transition:`opacity ${e.motionDurationSlow}`,"&::after":{position:`absolute`,top:0,insetInlineEnd:0,bottom:0,insetInlineStart:0,zIndex:10,width:`100%`,height:`100%`,background:e.colorBgContainer,opacity:0,transition:`all ${e.motionDurationSlow}`,content:`""`,pointerEvents:`none`}},"&-spinning":{[`${t}-description`]:{textShadow:`0 0px 5px ${e.colorBgContainer}`},[`${t}-container`]:{clear:`both`,opacity:.5,userSelect:`none`,pointerEvents:`none`,"&::after":{opacity:.4,pointerEvents:`auto`}}},"&-fullscreen":{position:`fixed`,inset:0,backgroundColor:e.colorBgMask,zIndex:e.zIndexPopupBase,opacity:0,pointerEvents:`none`,transition:`all ${e.motionDurationMid}`,[`&${t}-spinning`]:{opacity:1,pointerEvents:`auto`},[n]:{color:e.colorWhite,[`${t}-description`]:{color:e.colorTextLightSolid}}}}}},Zy=e=>{let{componentCls:t,antCls:n,motionDurationSlow:r}=e,[i,a]=zo(n,`spin`);return{[t]:{[i(`dot-holder-size`)]:e.dotSize,[i(`dot-item-size`)]:`calc((${a(`dot-holder-size`)} - ${e.marginXXS} / 2) / 2)`,[`${t}-dot`]:{"&-holder":{width:`1em`,height:`1em`,fontSize:a(`dot-holder-size`),display:`inline-block`,transition:[`transform`,`opacity`].map(e=>`${e} ${r} ease`).join(`, `),transformOrigin:`50% 50%`,lineHeight:1,"&-hidden":{transform:`scale(0.3)`,opacity:0}},position:`relative`,display:`inline-block`,fontSize:a(`dot-holder-size`),width:`1em`,height:`1em`,"&-spin":{transform:`rotate(45deg)`,animationName:Yy,animationDuration:`1.2s`,animationIterationCount:`infinite`,animationTimingFunction:`linear`},"&-item":{position:`absolute`,display:`block`,width:a(`dot-item-size`),height:a(`dot-item-size`),background:`currentColor`,borderRadius:`100%`,transform:`scale(0.75)`,transformOrigin:`50% 50%`,opacity:.3,animationName:Jy,animationDuration:`1s`,animationIterationCount:`infinite`,animationTimingFunction:`linear`,animationDirection:`alternate`,"&:nth-child(1)":{top:0,insetInlineStart:0,animationDelay:`0s`},"&:nth-child(2)":{top:0,insetInlineEnd:0,animationDelay:`0.4s`},"&:nth-child(3)":{insetInlineEnd:0,bottom:0,animationDelay:`0.8s`},"&:nth-child(4)":{bottom:0,insetInlineStart:0,animationDelay:`1.2s`}},"&-progress":{position:`absolute`,left:`50%`,top:0,transform:`translateX(-50%)`},"&-circle":{strokeLinecap:`round`,transition:[`stroke-dashoffset`,`stroke-dasharray`,`stroke`,`stroke-width`,`opacity`].map(e=>`${e} ${r} ease`).join(`,`),fillOpacity:0,stroke:`currentcolor`},"&-circle-bg":{stroke:e.colorFillSecondary}}}}},Qy=e=>{let{componentCls:t}=e,[n]=zo(e.antCls,`spin`);return{[t]:{"&-sm":{[n(`dot-holder-size`)]:e.dotSizeSM},"&-lg":{[n(`dot-holder-size`)]:e.dotSizeLG}}}},$y=Io(`Spin`,e=>{let t=Yi(e,{spinDotDefault:e.colorTextDescription});return[Xy(t),Zy(t),Qy(t)]},e=>{let{controlHeightLG:t,controlHeight:n}=e;return{contentHeight:400,dotSize:t/2,dotSizeSM:t*.35,dotSizeLG:n}}),eb=200,tb=[[30,.05],[70,.03],[96,.01]];function nb(e,t){let[n,r]=m.useState(0),i=m.useRef(null),a=t===`auto`;return m.useEffect(()=>(a&&e&&(r(0),i.current=setInterval(()=>{r(e=>{let t=100-e;for(let n=0;n{i.current&&=(clearInterval(i.current),null)}),[a,e]),a?n:t}var rb;function ib(e,t){return!!e&&!!t&&!Number.isNaN(Number(t))}var ab=e=>{let{prefixCls:t,spinning:n=!0,delay:r=0,className:i,rootClassName:a,size:o,tip:s,description:c,wrapperClassName:l,style:u,children:d,fullscreen:f=!1,indicator:p,percent:h,classNames:g,styles:_,...v}=e,{getPrefixCls:y,direction:b,indicator:x,className:S,style:C,classNames:w,styles:T}=Ht(`spin`),E=y(`spin`,t),[D,O]=$y(E),[k,A]=m.useState(()=>n&&!ib(n,r)),j=nb(k,h);m.useEffect(()=>{if(n){let e=Qv(r,()=>{A(!0)});return e(),()=>{e?.cancel?.()}}A(!1)},[r,n]);let M=Kd(e=>o??e),N=c??s,P={...e,size:M,spinning:k,tip:N,description:N,fullscreen:f,children:d,percent:j},[F,I]=cl([w,g],[T,_],{props:P}),L=p??x??rb,ee=d!==void 0,R=ee||f,z=m.createElement(m.Fragment,null,m.createElement(qy,{className:K(F.indicator),style:I.indicator,prefixCls:E,indicator:L,percent:j}),N&&m.createElement(`div`,{className:K(`${E}-description`,F.tip,F.description),style:{...I.tip,...I.description}},N));return m.createElement(`div`,{className:K(E,{[`${E}-sm`]:M===`small`,[`${E}-lg`]:M===`large`,[`${E}-spinning`]:k,[`${E}-rtl`]:b===`rtl`,[`${E}-fullscreen`]:f},a,F.root,f&&F.mask,R?l:[`${E}-section`,F.section],S,i,D,O),style:{...I.root,...R?{}:I.section,...f?I.mask:{},...C,...u},"aria-live":`polite`,"aria-busy":k,...v},k&&(R?m.createElement(`div`,{className:K(`${E}-section`,F.section),style:I.section},z):z),ee&&m.createElement(`div`,{className:K(`${E}-container`,F.container),style:I.container},d))};ab.setDefaultIndicator=e=>{rb=e};var ob=(e,t={})=>!Gc(e)&&t?.skipEmpty?[]:Array.isArray(e)?e:[e],sb=ny,cb={icon:{tag:`svg`,attrs:{viewBox:`64 64 896 896`,focusable:`false`},children:[{tag:`path`,attrs:{d:`M257.7 752c2 0 4-.2 6-.5L431.9 722c2-.4 3.9-1.3 5.3-2.8l423.9-423.9a9.96 9.96 0 000-14.1L694.9 114.9c-1.9-1.9-4.4-2.9-7.1-2.9s-5.2 1-7.1 2.9L256.8 538.8c-1.5 1.5-2.4 3.3-2.8 5.3l-29.5 168.2a33.5 33.5 0 009.4 29.8c6.6 6.4 14.9 9.9 23.8 9.9zm67.4-174.4L687.8 215l73.3 73.3-362.7 362.6-88.9 15.7 15.6-89zM880 836H144c-17.7 0-32 14.3-32 32v36c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-36c0-17.7-14.3-32-32-32z`}}]},name:`edit`,theme:`outlined`};function lb(){return lb=Object.assign?Object.assign.bind():function(e){for(var t=1;tm.createElement(ls,lb({},e,{ref:t,icon:cb}))),db={icon:{tag:`svg`,attrs:{viewBox:`64 64 896 896`,focusable:`false`},children:[{tag:`path`,attrs:{d:`M864 170h-60c-4.4 0-8 3.6-8 8v518H310v-73c0-6.7-7.8-10.5-13-6.3l-141.9 112a8 8 0 000 12.6l141.9 112c5.3 4.2 13 .4 13-6.3v-75h498c35.3 0 64-28.7 64-64V178c0-4.4-3.6-8-8-8z`}}]},name:`enter`,theme:`outlined`};function fb(){return fb=Object.assign?Object.assign.bind():function(e){for(var t=1;tm.createElement(ls,fb({},e,{ref:t,icon:db}))),mb=(e,t,n,r)=>{let{titleMarginBottom:i,fontWeightStrong:a}=r;return{marginBottom:i,color:n,fontWeight:a,fontSize:e,lineHeight:t}},hb=e=>{let t=[1,2,3,4,5],n={};return t.forEach(t=>{n[` + `]:{paddingInlineEnd:n},[`&-affix-wrapper${t}-affix-wrapper`]:{padding:0,[`> textarea${t}`]:{fontSize:`inherit`,border:`none`,outline:`none`,background:`transparent`,minHeight:e.calc(e.controlHeight).sub(e.calc(e.lineWidth).mul(2)).equal(),"&:focus":{boxShadow:`none !important`}},[`${t}-suffix`]:{margin:0,"> *:not(:last-child)":{marginInline:0},[`${t}-clear-icon`]:{position:`absolute`,insetInlineEnd:e.paddingInline,insetBlockStart:e.paddingXS},[`${r}-suffix`]:{position:`absolute`,top:0,insetInlineEnd:e.paddingInline,bottom:0,zIndex:1,display:`inline-flex`,alignItems:`center`,margin:`auto`,pointerEvents:`none`}}},[`&-affix-wrapper${t}-affix-wrapper-rtl`]:{[`${t}-suffix`]:{[`${t}-data-count`]:{direction:`ltr`,insetInlineStart:0}}},[`&-affix-wrapper${t}-affix-wrapper-sm`]:{[`${t}-suffix`]:{[`${t}-clear-icon`]:{insetInlineEnd:e.paddingInlineSM}}}}}},Ly=Io([`Input`,`TextArea`],e=>Iy(Yi(e,Sv(e))),Cv,{resetFont:!1}),Ry=(0,m.forwardRef)((e,t)=>{let{prefixCls:n,bordered:r=!0,size:i,disabled:a,status:o,allowClear:s,classNames:c,rootClassName:l,className:u,style:d,styles:f,variant:p,showCount:h,onMouseDown:g,onResize:_,...v}=e,{getPrefixCls:y,direction:b,allowClear:x,autoComplete:S,className:C,style:w,classNames:T,styles:E}=Ht(`textArea`),D=m.useContext(Lu),O=a??D,{status:k,hasFeedback:A,feedbackIcon:j}=m.useContext(Mh),M=L_(k,o),[N,P]=cl([T,c],[E,f],{props:e}),F=m.useRef(null);m.useImperativeHandle(t,()=>({resizableTextArea:F.current?.resizableTextArea,focus:e=>{wp(F.current?.resizableTextArea?.textArea,e)},blur:()=>F.current?.blur(),nativeElement:F.current?.nativeElement||null}));let I=y(`input`,n),L=yl(I),[ee,R]=Xv(I,l);Ly(I,L);let{compactSize:z,compactItemClassnames:B}=Yd(I,b),V=Kd(e=>i??z??e),[te,ne]=R_(`textArea`,p,r),re=py(s??x),[ie,ae]=m.useState(!1),[oe,H]=m.useState(!1),se=e=>{ae(!0),g?.(e);let t=()=>{ae(!1),document.removeEventListener(`mouseup`,t)};document.addEventListener(`mouseup`,t)},ce=e=>{if(_?.(e),ie&&typeof getComputedStyle==`function`){let e=F.current?.nativeElement?.querySelector(`textarea`);e&&getComputedStyle(e).resize===`both`&&H(!0)}};return m.createElement(Fy,{autoComplete:S,...v,style:{...P.root,...w,...d},styles:P,disabled:O,allowClear:re,className:K(R,L,u,l,B,C,N.root,{[`${I}-textarea-affix-wrapper-resize-dirty`]:oe}),classNames:{...N,textarea:K({[`${I}-sm`]:V===`small`,[`${I}-lg`]:V===`large`},ee,N.textarea,ie&&`${I}-mouse-active`),variant:K({[`${I}-${te}`]:ne},I_(I,M)),affixWrapper:K(`${I}-textarea-affix-wrapper`,{[`${I}-affix-wrapper-rtl`]:b===`rtl`,[`${I}-affix-wrapper-sm`]:V===`small`,[`${I}-affix-wrapper-lg`]:V===`large`,[`${I}-textarea-show-count`]:h||e.count?.show},ee)},prefixCls:I,suffix:A&&m.createElement(`span`,{className:`${I}-textarea-suffix`},j),showCount:h,ref:F,onResize:ce,onMouseDown:se})}),zy=100,By=zy/5,Vy=zy/2-By/2,Hy=Vy*2*Math.PI,Uy=50,Wy=e=>{let{dotClassName:t,style:n,hasCircleCls:r}=e;return m.createElement(`circle`,{className:K(`${t}-circle`,{[`${t}-circle-bg`]:r}),r:Vy,cx:Uy,cy:Uy,strokeWidth:By,style:n})},Gy=({percent:e,prefixCls:t})=>{let n=`${t}-dot`,r=`${n}-holder`,i=`${r}-hidden`,[a,o]=m.useState(!1);G(()=>{e!==0&&o(!0)},[e!==0]);let s=Math.max(Math.min(e,100),0);if(!a)return null;let c={strokeDashoffset:`${Hy/4}`,strokeDasharray:`${Hy*s/100} ${Hy*(100-s)/100}`};return m.createElement(`span`,{className:K(r,`${n}-progress`,s<=0&&i)},m.createElement(`svg`,{viewBox:`0 0 ${zy} ${zy}`,role:`progressbar`,"aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":s},m.createElement(Wy,{dotClassName:n,hasCircleCls:!0}),m.createElement(Wy,{dotClassName:n,style:c})))};function Ky(e){let{prefixCls:t,percent:n=0,className:r,style:i}=e,a=`${t}-dot`,o=`${a}-holder`,s=`${o}-hidden`;return m.createElement(m.Fragment,null,m.createElement(`span`,{className:K(o,r,n>0&&s),style:i},m.createElement(`span`,{className:K(a,`${t}-dot-spin`)},[1,2,3,4].map(e=>m.createElement(`i`,{className:`${t}-dot-item`,key:e})))),m.createElement(Gy,{prefixCls:t,percent:n}))}function qy(e){let{prefixCls:t,indicator:n,percent:r,className:i,style:a}=e,o=`${t}-dot`;return n&&m.isValidElement(n)?Mu(n,e=>({className:K(e.className,o,i),style:{...e.style,...a},percent:r})):m.createElement(Ky,{prefixCls:t,percent:r,className:i,style:a})}var Jy=new gi(`antSpinMove`,{to:{opacity:1}}),Yy=new gi(`antRotate`,{to:{transform:`rotate(405deg)`}}),Xy=e=>{let{componentCls:t}=e,n=`${t}-section`;return{[t]:{...Do(e),position:`relative`,"&-rtl":{direction:`rtl`},[`&${n}, ${n}`]:{display:`flex`,alignItems:`center`,flexDirection:`column`,gap:e.paddingSM,color:e.colorPrimary},[`&${n}`]:{display:`inline-flex`},[n]:{position:`absolute`,top:`50%`,left:{_skip_check_:!0,value:`50%`},transform:`translate(-50%, -50%)`,zIndex:1},[`${t}-description`]:{fontSize:e.fontSize,lineHeight:1},[`${t}-container`]:{position:`relative`,transition:`opacity ${e.motionDurationSlow}`,"&::after":{position:`absolute`,top:0,insetInlineEnd:0,bottom:0,insetInlineStart:0,zIndex:10,width:`100%`,height:`100%`,background:e.colorBgContainer,opacity:0,transition:`all ${e.motionDurationSlow}`,content:`""`,pointerEvents:`none`}},"&-spinning":{[`${t}-description`]:{textShadow:`0 0px 5px ${e.colorBgContainer}`},[`${t}-container`]:{clear:`both`,opacity:.5,userSelect:`none`,pointerEvents:`none`,"&::after":{opacity:.4,pointerEvents:`auto`}}},"&-fullscreen":{position:`fixed`,inset:0,backgroundColor:e.colorBgMask,zIndex:e.zIndexPopupBase,opacity:0,pointerEvents:`none`,transition:`all ${e.motionDurationMid}`,[`&${t}-spinning`]:{opacity:1,pointerEvents:`auto`},[n]:{color:e.colorWhite,[`${t}-description`]:{color:e.colorTextLightSolid}}}}}},Zy=e=>{let{componentCls:t,antCls:n,motionDurationSlow:r}=e,[i,a]=zo(n,`spin`);return{[t]:{[i(`dot-holder-size`)]:e.dotSize,[i(`dot-item-size`)]:`calc((${a(`dot-holder-size`)} - ${e.marginXXS} / 2) / 2)`,[`${t}-dot`]:{"&-holder":{width:`1em`,height:`1em`,fontSize:a(`dot-holder-size`),display:`inline-block`,transition:[`transform`,`opacity`].map(e=>`${e} ${r} ease`).join(`, `),transformOrigin:`50% 50%`,lineHeight:1,"&-hidden":{transform:`scale(0.3)`,opacity:0}},position:`relative`,display:`inline-block`,fontSize:a(`dot-holder-size`),width:`1em`,height:`1em`,"&-spin":{transform:`rotate(45deg)`,animationName:Yy,animationDuration:`1.2s`,animationIterationCount:`infinite`,animationTimingFunction:`linear`},"&-item":{position:`absolute`,display:`block`,width:a(`dot-item-size`),height:a(`dot-item-size`),background:`currentColor`,borderRadius:`100%`,transform:`scale(0.75)`,transformOrigin:`50% 50%`,opacity:.3,animationName:Jy,animationDuration:`1s`,animationIterationCount:`infinite`,animationTimingFunction:`linear`,animationDirection:`alternate`,"&:nth-child(1)":{top:0,insetInlineStart:0,animationDelay:`0s`},"&:nth-child(2)":{top:0,insetInlineEnd:0,animationDelay:`0.4s`},"&:nth-child(3)":{insetInlineEnd:0,bottom:0,animationDelay:`0.8s`},"&:nth-child(4)":{bottom:0,insetInlineStart:0,animationDelay:`1.2s`}},"&-progress":{position:`absolute`,left:`50%`,top:0,transform:`translateX(-50%)`},"&-circle":{strokeLinecap:`round`,transition:[`stroke-dashoffset`,`stroke-dasharray`,`stroke`,`stroke-width`,`opacity`].map(e=>`${e} ${r} ease`).join(`,`),fillOpacity:0,stroke:`currentcolor`},"&-circle-bg":{stroke:e.colorFillSecondary}}}}},Qy=e=>{let{componentCls:t}=e,[n]=zo(e.antCls,`spin`);return{[t]:{"&-sm":{[n(`dot-holder-size`)]:e.dotSizeSM},"&-lg":{[n(`dot-holder-size`)]:e.dotSizeLG}}}},$y=Io(`Spin`,e=>{let t=Yi(e,{spinDotDefault:e.colorTextDescription});return[Xy(t),Zy(t),Qy(t)]},e=>{let{controlHeightLG:t,controlHeight:n}=e;return{contentHeight:400,dotSize:t/2,dotSizeSM:t*.35,dotSizeLG:n}}),eb=200,tb=[[30,.05],[70,.03],[96,.01]];function nb(e,t){let[n,r]=m.useState(0),i=m.useRef(null),a=t===`auto`;return m.useEffect(()=>(a&&e&&(r(0),i.current=setInterval(()=>{r(e=>{let t=100-e;for(let n=0;n{i.current&&=(clearInterval(i.current),null)}),[a,e]),a?n:t}var rb;function ib(e,t){return!!e&&!!t&&!Number.isNaN(Number(t))}var ab=e=>{let{prefixCls:t,spinning:n=!0,delay:r=0,className:i,rootClassName:a,size:o,tip:s,description:c,wrapperClassName:l,style:u,children:d,fullscreen:f=!1,indicator:p,percent:h,classNames:g,styles:_,...v}=e,{getPrefixCls:y,direction:b,indicator:x,className:S,style:C,classNames:w,styles:T}=Ht(`spin`),E=y(`spin`,t),[D,O]=$y(E),[k,A]=m.useState(()=>n&&!ib(n,r)),j=nb(k,h);m.useEffect(()=>{if(n){let e=Qv(r,()=>{A(!0)});return e(),()=>{e?.cancel?.()}}A(!1)},[r,n]);let M=Kd(e=>o??e),N=c??s,P={...e,size:M,spinning:k,tip:N,description:N,fullscreen:f,children:d,percent:j},[F,I]=cl([w,g],[T,_],{props:P}),L=p??x??rb,ee=d!==void 0,R=ee||f,z=m.createElement(m.Fragment,null,m.createElement(qy,{className:K(F.indicator),style:I.indicator,prefixCls:E,indicator:L,percent:j}),N&&m.createElement(`div`,{className:K(`${E}-description`,F.tip,F.description),style:{...I.tip,...I.description}},N));return m.createElement(`div`,{className:K(E,{[`${E}-sm`]:M===`small`,[`${E}-lg`]:M===`large`,[`${E}-spinning`]:k,[`${E}-rtl`]:b===`rtl`,[`${E}-fullscreen`]:f},a,F.root,f&&F.mask,R?l:[`${E}-section`,F.section],S,i,D,O),style:{...I.root,...R?{}:I.section,...f?I.mask:{},...C,...u},"aria-live":`polite`,"aria-busy":k,...v},k&&(R?m.createElement(`div`,{className:K(`${E}-section`,F.section),style:I.section},z):z),ee&&m.createElement(`div`,{className:K(`${E}-container`,F.container),style:I.container},d))};ab.setDefaultIndicator=e=>{rb=e};var ob=(e,t={})=>!Gc(e)&&t?.skipEmpty?[]:Array.isArray(e)?e:[e],sb=ny,cb=e=>{let t=e?.algorithm?bn(e.algorithm):go;return Un({...da,...e?.token},{override:e?.token},t,xo)};function lb(e){let{sizeUnit:t,sizeStep:n}=e,r=n-2;return{sizeXXL:t*(r+10),sizeXL:t*(r+6),sizeLG:t*(r+2),sizeMD:t*(r+2),sizeMS:t*(r+1),size:t*r,sizeSM:t*r,sizeXS:t*(r-1),sizeXXS:t*(r-1)}}var ub=(e,t)=>{let n=t??ho(e),r=n.fontSizeSM,i=n.controlHeight-4;return{...n,...lb(t??e),...co(r),controlHeight:i,...so({...n,controlHeight:i})}},db=(e,t)=>new _a(e).setA(t).toRgbString(),fb=(e,t)=>new _a(e).lighten(t).toHexString(),pb=e=>{let t=ka(e,{theme:`dark`});return{1:t[0],2:t[1],3:t[2],4:t[3],5:t[6],6:t[5],7:t[4],8:t[6],9:t[5],10:t[4]}},mb=(e,t)=>{let n=e||`#000`,r=t||`#fff`;return{colorBgBase:n,colorTextBase:r,colorText:db(r,.85),colorTextSecondary:db(r,.65),colorTextTertiary:db(r,.45),colorTextQuaternary:db(r,.25),colorFill:db(r,.18),colorFillSecondary:db(r,.12),colorFillTertiary:db(r,.08),colorFillQuaternary:db(r,.04),colorBgSolid:db(r,.95),colorBgSolidHover:db(r,1),colorBgSolidActive:db(r,.9),colorBgElevated:fb(n,12),colorBgContainer:fb(n,8),colorBgLayout:fb(n,0),colorBgSpotlight:fb(n,26),colorBgBlur:db(r,.04),colorBorder:fb(n,26),colorBorderDisabled:fb(n,26),colorBorderSecondary:fb(n,19)}},hb=(e,t)=>{let n=Object.keys(ua).map(t=>{let n=ka(e[t],{theme:`dark`});return Array.from({length:10},()=>1).reduce((e,r,i)=>(e[`${t}-${i+1}`]=n[i],e[`${t}${i+1}`]=n[i],e),{})}).reduce((e,t)=>(e={...e,...t},e),{}),r=t??ho(e),i=io(e,{generateColorPalettes:pb,generateNeutralColorPalettes:mb}),a=oa.reduce((t,n)=>{let r=e[n];if(r){let e=pb(r);t[`${n}Hover`]=e[7],t[`${n}Active`]=e[5]}return t},{});return{...r,...n,...i,...a,colorPrimaryBg:i.colorPrimaryBorder,colorPrimaryBgHover:i.colorPrimaryBorderHover}};function gb(){let[e,t,n,r]=Eo();return{theme:e,token:t,hashId:n,cssVar:r}}var _b={defaultSeed:_o.token,useToken:gb,defaultAlgorithm:ho,darkAlgorithm:hb,compactAlgorithm:ub,getDesignToken:cb,defaultConfig:_o,_internalContext:vo},vb={icon:{tag:`svg`,attrs:{viewBox:`64 64 896 896`,focusable:`false`},children:[{tag:`path`,attrs:{d:`M257.7 752c2 0 4-.2 6-.5L431.9 722c2-.4 3.9-1.3 5.3-2.8l423.9-423.9a9.96 9.96 0 000-14.1L694.9 114.9c-1.9-1.9-4.4-2.9-7.1-2.9s-5.2 1-7.1 2.9L256.8 538.8c-1.5 1.5-2.4 3.3-2.8 5.3l-29.5 168.2a33.5 33.5 0 009.4 29.8c6.6 6.4 14.9 9.9 23.8 9.9zm67.4-174.4L687.8 215l73.3 73.3-362.7 362.6-88.9 15.7 15.6-89zM880 836H144c-17.7 0-32 14.3-32 32v36c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-36c0-17.7-14.3-32-32-32z`}}]},name:`edit`,theme:`outlined`};function yb(){return yb=Object.assign?Object.assign.bind():function(e){for(var t=1;tm.createElement(ls,yb({},e,{ref:t,icon:vb}))),xb={icon:{tag:`svg`,attrs:{viewBox:`64 64 896 896`,focusable:`false`},children:[{tag:`path`,attrs:{d:`M864 170h-60c-4.4 0-8 3.6-8 8v518H310v-73c0-6.7-7.8-10.5-13-6.3l-141.9 112a8 8 0 000 12.6l141.9 112c5.3 4.2 13 .4 13-6.3v-75h498c35.3 0 64-28.7 64-64V178c0-4.4-3.6-8-8-8z`}}]},name:`enter`,theme:`outlined`};function Sb(){return Sb=Object.assign?Object.assign.bind():function(e){for(var t=1;tm.createElement(ls,Sb({},e,{ref:t,icon:xb}))),wb=(e,t,n,r)=>{let{titleMarginBottom:i,fontWeightStrong:a}=r;return{marginBottom:i,color:n,fontWeight:a,fontSize:e,lineHeight:t}},Tb=e=>{let t=[1,2,3,4,5],n={};return t.forEach(t=>{n[` h${t}&, div&-h${t}, div&-h${t} > textarea, h${t} - `]=mb(e[`fontSizeHeading${t}`],e[`lineHeightHeading${t}`],e.colorTextHeading,e)}),n},gb=e=>{let{componentCls:t}=e;return{[`&${`${t}-link`}`]:{...Fo(e),userSelect:`text`,[`&[disabled], &${t}-disabled`]:{color:e.colorTextDisabled,cursor:`not-allowed`,"&:active, &:hover":{color:e.colorTextDisabled},"&:active":{pointerEvents:`none`}}}}},_b=e=>({code:{margin:`0 0.2em`,paddingInline:`0.4em`,paddingBlock:`0.2em 0.1em`,fontSize:`85%`,fontFamily:e.fontFamilyCode,background:`rgba(150, 150, 150, 0.1)`,border:`1px solid rgba(100, 100, 100, 0.2)`,borderRadius:3},kbd:{margin:`0 0.2em`,paddingInline:`0.4em`,paddingBlock:`0.15em 0.1em`,fontSize:`90%`,fontFamily:e.fontFamilyCode,background:`rgba(150, 150, 150, 0.06)`,border:`1px solid rgba(100, 100, 100, 0.2)`,borderBottomWidth:2,borderRadius:3},mark:{padding:0,backgroundColor:Pa[2]},"u, ins":{textDecoration:`underline`,textDecorationSkipInk:`auto`},"s, del":{textDecoration:`line-through`},strong:{fontWeight:e.fontWeightStrong},"ul, ol":{marginInline:0,marginBlock:`0 1em`,padding:0,li:{marginInline:`20px 0`,marginBlock:0,paddingInline:`4px 0`,paddingBlock:0}},ul:{listStyleType:`circle`,ul:{listStyleType:`disc`}},ol:{listStyleType:`decimal`},"pre, blockquote":{margin:`1em 0`},pre:{padding:`0.4em 0.6em`,whiteSpace:`pre-wrap`,wordWrap:`break-word`,background:`rgba(150, 150, 150, 0.1)`,border:`1px solid rgba(100, 100, 100, 0.2)`,borderRadius:3,fontFamily:e.fontFamilyCode,code:{display:`inline`,margin:0,padding:0,fontSize:`inherit`,fontFamily:`inherit`,background:`transparent`,border:0}},blockquote:{paddingInline:`0.6em 0`,paddingBlock:0,borderInlineStart:`4px solid rgba(100, 100, 100, 0.2)`,opacity:.85}}),vb=e=>{let{componentCls:t,paddingSM:n}=e,r=n;return{"&-edit-content":{position:`relative`,"div&":{insetInlineStart:e.calc(e.paddingSM).mul(-1).equal(),insetBlockStart:e.calc(r).div(-2).add(1).equal(),marginBottom:e.calc(r).div(2).sub(2).equal()},[`${t}-edit-content-confirm`]:{position:`absolute`,insetInlineEnd:e.calc(e.marginXS).add(2).equal(),insetBlockEnd:e.marginXS,color:e.colorIcon,fontWeight:`normal`,fontSize:e.fontSize,fontStyle:`normal`,pointerEvents:`none`},textarea:{margin:`0!important`,MozTransition:`none`,height:`1em`}}}},yb=e=>({[`${e.componentCls}-copy-success`]:{"\n &,\n &:hover,\n &:focus":{color:e.colorSuccess}},[`${e.componentCls}-copy-icon-only`]:{marginInlineStart:0}}),bb=()=>({"\n a&-ellipsis,\n span&-ellipsis\n ":{display:`inline-block`,maxWidth:`100%`},"&-ellipsis-single-line":{whiteSpace:`nowrap`,overflow:`hidden`,textOverflow:`ellipsis`,"a&, span&":{verticalAlign:`bottom`},"> code":{paddingBlock:0,maxWidth:`calc(100% - 1.2em)`,display:`inline-block`,overflow:`hidden`,textOverflow:`ellipsis`,verticalAlign:`bottom`,boxSizing:`content-box`}},"&-ellipsis-multiple-line":{display:`-webkit-box`,overflow:`hidden`,WebkitLineClamp:3,WebkitBoxOrient:`vertical`}}),xb=Io(`Typography`,e=>{let{componentCls:t,titleMarginTop:n}=e;return{[t]:{color:e.colorText,wordBreak:`break-word`,lineHeight:e.lineHeight,[`&${t}-secondary, &${t}-link${t}-secondary`]:{color:e.colorTextDescription},[`&${t}-success, &${t}-link${t}-success`]:{color:e.colorSuccessText},[`&${t}-warning, &${t}-link${t}-warning`]:{color:e.colorWarningText},[`&${t}-danger, &${t}-link${t}-danger`]:{color:e.colorErrorText,[`&${t}-link:active, &${t}-link:focus`]:{color:e.colorErrorTextActive},[`&${t}-link:hover`]:{color:e.colorErrorTextHover}},[`&${t}-disabled`]:{color:e.colorTextDisabled,cursor:`not-allowed`,userSelect:`none`},"\n div&,\n p\n ":{marginBottom:`1em`},...hb(e),[` + `]=wb(e[`fontSizeHeading${t}`],e[`lineHeightHeading${t}`],e.colorTextHeading,e)}),n},Eb=e=>{let{componentCls:t}=e;return{[`&${`${t}-link`}`]:{...Fo(e),userSelect:`text`,[`&[disabled], &${t}-disabled`]:{color:e.colorTextDisabled,cursor:`not-allowed`,"&:active, &:hover":{color:e.colorTextDisabled},"&:active":{pointerEvents:`none`}}}}},Db=e=>({code:{margin:`0 0.2em`,paddingInline:`0.4em`,paddingBlock:`0.2em 0.1em`,fontSize:`85%`,fontFamily:e.fontFamilyCode,background:`rgba(150, 150, 150, 0.1)`,border:`1px solid rgba(100, 100, 100, 0.2)`,borderRadius:3},kbd:{margin:`0 0.2em`,paddingInline:`0.4em`,paddingBlock:`0.15em 0.1em`,fontSize:`90%`,fontFamily:e.fontFamilyCode,background:`rgba(150, 150, 150, 0.06)`,border:`1px solid rgba(100, 100, 100, 0.2)`,borderBottomWidth:2,borderRadius:3},mark:{padding:0,backgroundColor:Pa[2]},"u, ins":{textDecoration:`underline`,textDecorationSkipInk:`auto`},"s, del":{textDecoration:`line-through`},strong:{fontWeight:e.fontWeightStrong},"ul, ol":{marginInline:0,marginBlock:`0 1em`,padding:0,li:{marginInline:`20px 0`,marginBlock:0,paddingInline:`4px 0`,paddingBlock:0}},ul:{listStyleType:`circle`,ul:{listStyleType:`disc`}},ol:{listStyleType:`decimal`},"pre, blockquote":{margin:`1em 0`},pre:{padding:`0.4em 0.6em`,whiteSpace:`pre-wrap`,wordWrap:`break-word`,background:`rgba(150, 150, 150, 0.1)`,border:`1px solid rgba(100, 100, 100, 0.2)`,borderRadius:3,fontFamily:e.fontFamilyCode,code:{display:`inline`,margin:0,padding:0,fontSize:`inherit`,fontFamily:`inherit`,background:`transparent`,border:0}},blockquote:{paddingInline:`0.6em 0`,paddingBlock:0,borderInlineStart:`4px solid rgba(100, 100, 100, 0.2)`,opacity:.85}}),Ob=e=>{let{componentCls:t,paddingSM:n}=e,r=n;return{"&-edit-content":{position:`relative`,"div&":{insetInlineStart:e.calc(e.paddingSM).mul(-1).equal(),insetBlockStart:e.calc(r).div(-2).add(1).equal(),marginBottom:e.calc(r).div(2).sub(2).equal()},[`${t}-edit-content-confirm`]:{position:`absolute`,insetInlineEnd:e.calc(e.marginXS).add(2).equal(),insetBlockEnd:e.marginXS,color:e.colorIcon,fontWeight:`normal`,fontSize:e.fontSize,fontStyle:`normal`,pointerEvents:`none`},textarea:{margin:`0!important`,MozTransition:`none`,height:`1em`}}}},kb=e=>({[`${e.componentCls}-copy-success`]:{"\n &,\n &:hover,\n &:focus":{color:e.colorSuccess}},[`${e.componentCls}-copy-icon-only`]:{marginInlineStart:0}}),Ab=()=>({"\n a&-ellipsis,\n span&-ellipsis\n ":{display:`inline-block`,maxWidth:`100%`},"&-ellipsis-single-line":{whiteSpace:`nowrap`,overflow:`hidden`,textOverflow:`ellipsis`,"a&, span&":{verticalAlign:`bottom`},"> code":{paddingBlock:0,maxWidth:`calc(100% - 1.2em)`,display:`inline-block`,overflow:`hidden`,textOverflow:`ellipsis`,verticalAlign:`bottom`,boxSizing:`content-box`}},"&-ellipsis-multiple-line":{display:`-webkit-box`,overflow:`hidden`,WebkitLineClamp:3,WebkitBoxOrient:`vertical`}}),jb=Io(`Typography`,e=>{let{componentCls:t,titleMarginTop:n}=e;return{[t]:{color:e.colorText,wordBreak:`break-word`,lineHeight:e.lineHeight,[`&${t}-secondary, &${t}-link${t}-secondary`]:{color:e.colorTextDescription},[`&${t}-success, &${t}-link${t}-success`]:{color:e.colorSuccessText},[`&${t}-warning, &${t}-link${t}-warning`]:{color:e.colorWarningText},[`&${t}-danger, &${t}-link${t}-danger`]:{color:e.colorErrorText,[`&${t}-link:active, &${t}-link:focus`]:{color:e.colorErrorTextActive},[`&${t}-link:hover`]:{color:e.colorErrorTextHover}},[`&${t}-disabled`]:{color:e.colorTextDisabled,cursor:`not-allowed`,userSelect:`none`},"\n div&,\n p\n ":{marginBottom:`1em`},...Tb(e),[` & + h1${t}, & + h2${t}, & + h3${t}, & + h4${t}, & + h5${t} - `]:{marginTop:n},"\n div,\n ul,\n li,\n p,\n h1,\n h2,\n h3,\n h4,\n h5":{"\n + h1,\n + h2,\n + h3,\n + h4,\n + h5\n ":{marginTop:n}},..._b(e),...gb(e),[`${t}-actions`]:{display:`inline`},[` + `]:{marginTop:n},"\n div,\n ul,\n li,\n p,\n h1,\n h2,\n h3,\n h4,\n h5":{"\n + h1,\n + h2,\n + h3,\n + h4,\n + h5\n ":{marginTop:n}},...Db(e),...Eb(e),[`${t}-actions`]:{display:`inline`},[` ${t}-expand, ${t}-collapse, ${t}-edit, ${t}-copy - `]:{...Fo(e),marginInlineStart:e.marginXXS},...vb(e),...yb(e),...bb(),"&-rtl":{direction:`rtl`}}}},()=>({titleMarginTop:`1.2em`,titleMarginBottom:`0.5em`})),Sb=e=>{let{prefixCls:t,"aria-label":n,className:r,style:i,direction:a,maxLength:o,autoSize:s=!0,value:c,onSave:l,onCancel:u,onEnd:d,component:f,enterIcon:p=m.createElement(pb,null)}=e,h=m.useRef(null),g=m.useRef(!1),_=m.useRef(null),[v,y]=m.useState(c);m.useEffect(()=>{y(c)},[c]),m.useEffect(()=>{if(h.current?.resizableTextArea){let{textArea:e}=h.current.resizableTextArea;e.focus();let{length:t}=e.value;e.setSelectionRange(t,t)}},[]);let b=({target:e})=>{y(e.value.replace(/[\n\r]/g,``))},x=()=>{g.current=!0},S=()=>{g.current=!1},C=({keyCode:e})=>{g.current||(_.current=e)},w=()=>{l(v.trim())},T=({keyCode:e,ctrlKey:t,altKey:n,metaKey:r,shiftKey:i})=>{_.current!==e||g.current||t||n||r||i||(e===J.ENTER?(w(),d?.()):e===J.ESC&&u())},E=()=>{w()},[D,O]=xb(t),k=K(t,`${t}-edit-content`,{[`${t}-rtl`]:a===`rtl`,[`${t}-${f}`]:!!f},r,D,O);return m.createElement(`div`,{className:k,style:i},m.createElement(Ry,{ref:h,maxLength:o,value:v,onChange:b,onKeyDown:C,onKeyUp:T,onCompositionStart:x,onCompositionEnd:S,onBlur:E,"aria-label":n,rows:1,autoSize:s}),p===null?null:Mu(p,{className:`${t}-edit-content-confirm`}))},Cb=(e,t)=>{let n=!1,r=r=>{r.stopPropagation(),r.preventDefault(),r.clipboardData?.clearData(),r.clipboardData?.setData(`text/plain`,e),t&&r.clipboardData?.setData(`text/html`,e),n=!0};try{return document.addEventListener(`copy`,r,{capture:!0}),document.execCommand(`copy`),n}catch{return!1}finally{document.removeEventListener(`copy`,r,{capture:!0})}},wb=async(e,t)=>{try{return t?await navigator.clipboard.write([new ClipboardItem({"text/html":new Blob([e],{type:`text/html`}),"text/plain":new Blob([e],{type:`text/plain`})})]):await navigator.clipboard.writeText(e),!0}catch{return!1}};async function Tb(e,t){if(typeof e!=`string`)return!1;let n=t?.format===`text/html`;return!!(await wb(e,n)||Cb(e,n))}var Eb=({copyConfig:e,children:t})=>{let[n,r]=m.useState(!1),[i,a]=m.useState(!1),o=m.useRef(null),s=()=>{o.current&&clearTimeout(o.current)},c={};return e.format&&(c.format=e.format),m.useEffect(()=>s,[]),{copied:n,copyLoading:i,onClick:W(async n=>{n?.preventDefault(),n?.stopPropagation(),a(!0);try{await Tb((typeof e.text==`function`?await e.text():e.text)||ob(t,{skipEmpty:!0}).join(``)||``,c),a(!1),r(!0),s(),o.current=setTimeout(()=>{r(!1)},3e3),e.onCopy?.(n)}catch(e){throw a(!1),e}})}};function Db(e,t){return m.useMemo(()=>{let n=!!e;return[n,{...t,...n&&typeof e==`object`?e:null}]},[e])}var Ob=e=>{let t=(0,m.useRef)(void 0);return(0,m.useEffect)(()=>{t.current=e}),t.current},kb=(e,t,n)=>(0,m.useMemo)(()=>e===!0?{title:t??n}:(0,m.isValidElement)(e)?{title:e}:typeof e==`object`?{title:t??n,...e}:{title:e},[e,t,n]),Ab=m.forwardRef((e,t)=>{let{prefixCls:n,component:r=`article`,className:i,rootClassName:a,children:o,direction:s,style:c,...l}=e,{getPrefixCls:u,direction:d,className:f,style:p}=Ht(`typography`),h=s??d,g=u(`typography`,n),[_,v]=xb(g),y=K(g,f,{[`${g}-rtl`]:h===`rtl`},i,a,_,v),b={...p,...c};return m.createElement(r,{className:y,style:b,ref:t,...l},o)}),jb={icon:{tag:`svg`,attrs:{viewBox:`64 64 896 896`,focusable:`false`},children:[{tag:`path`,attrs:{d:`M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z`}}]},name:`copy`,theme:`outlined`};function Mb(){return Mb=Object.assign?Object.assign.bind():function(e){for(var t=1;tm.createElement(ls,Mb({},e,{ref:t,icon:jb}))),Pb=e=>e===!1?[!1,!1]:ob(e);function Fb(e,t,n){return e===!0||e===void 0?t:e||n&&t}function Ib(e){let t=document.createElement(`em`);e.appendChild(t);let n=e.getBoundingClientRect(),r=t.getBoundingClientRect();return e.removeChild(t),n.left>r.left||r.right>n.right||n.top>r.top||r.bottom>n.bottom}var Lb=e=>[`string`,`number`].includes(typeof e),Rb=e=>{let{prefixCls:t,copied:n,locale:r,iconOnly:i,tooltips:a,icon:o,tabIndex:s,onCopy:c,loading:l}=e,u=Pb(a),d=Pb(o),{copied:f,copy:p}=r??{},h=n?f:p,g=Fb(u[n?1:0],h),_=typeof g==`string`?g:h;return m.createElement(bv,{title:g},m.createElement(`button`,{type:`button`,className:K(`${t}-copy`,{[`${t}-copy-success`]:n,[`${t}-copy-icon-only`]:i}),onClick:c,"aria-label":_,tabIndex:s},n?Fb(d[1],m.createElement(V_,null),!0):Fb(d[0],l?m.createElement(md,null):m.createElement(Nb,null),!0)))},zb=m.forwardRef(({style:e,children:t},n)=>{let r=m.useRef(null);return m.useImperativeHandle(n,()=>({isExceed:()=>{let e=r.current;return e.scrollHeight>e.clientHeight},getHeight:()=>r.current.clientHeight})),m.createElement(`span`,{"aria-hidden":!0,ref:r,style:{position:`fixed`,display:`block`,left:0,top:0,pointerEvents:`none`,backgroundColor:`rgba(255, 0, 0, 0.65)`,...e}},t)}),Bb=e=>e.reduce((e,t)=>e+(Lb(t)?String(t).length:1),0);function Vb(e,t){let n=0,r=[];for(let i=0;it){let e=t-n;return r.push(String(a).slice(0,e)),r}r.push(a),n=s}return e}var Hb=0,Ub=1,Wb=2,Gb=3,Kb=4,qb={display:`-webkit-box`,overflow:`hidden`,WebkitBoxOrient:`vertical`};function Jb(e){let{enableMeasure:t,width:n,text:r,children:i,rows:a,expanded:o,miscDeps:s,onEllipsis:c}=e,l=m.useMemo(()=>nt(r),[r]),u=m.useMemo(()=>Bb(l),[r]),d=m.useMemo(()=>i(l,!1),[r]),[f,p]=m.useState(null),h=m.useRef(null),g=m.useRef(null),_=m.useRef(null),v=m.useRef(null),y=m.useRef(null),[b,x]=m.useState(!1),[S,C]=m.useState(Hb),[w,T]=m.useState(0),[E,D]=m.useState(null);G(()=>{C(t&&n&&u?Ub:Hb)},[n,r,a,t,l]),G(()=>{if(S===Ub)C(Wb),D(g.current&&getComputedStyle(g.current).whiteSpace);else if(S===Wb){let e=!!_.current?.isExceed();C(e?Gb:Kb),p(e?[0,u]:null),x(e);let t=_.current?.getHeight()||0,n=a===1?0:v.current?.getHeight()||0,r=y.current?.getHeight()||0;T(Math.max(t,n+r)+1),c(e)}},[S]);let O=f?Math.ceil((f[0]+f[1])/2):0;G(()=>{let[e,t]=f||[0,0];if(e!==t){let n=(h.current?.getHeight()||0)>w,r=O;t-e===1&&(r=n?e:t),p(n?[e,r]:[r,t])}},[f,O]);let k=m.useMemo(()=>{if(!t)return i(l,!1);if(S!==Gb||!f||f[0]!==f[1]){let e=i(l,!1);return[Kb,Hb].includes(S)?e:m.createElement(`span`,{style:{...qb,WebkitLineClamp:a}},e)}return i(o?l:Vb(l,f[0]),b)},[o,S,f,l].concat(At(s))),A={width:n,margin:0,padding:0,whiteSpace:E===`nowrap`?`normal`:`inherit`};return m.createElement(m.Fragment,null,k,S===Wb&&m.createElement(m.Fragment,null,m.createElement(zb,{style:{...A,...qb,WebkitLineClamp:a},ref:_},d),m.createElement(zb,{style:{...A,...qb,WebkitLineClamp:a-1},ref:v},d),m.createElement(zb,{style:{...A,...qb,WebkitLineClamp:1},ref:y},i([],!0))),S===Gb&&f&&f[0]!==f[1]&&m.createElement(zb,{style:{...A,top:400},ref:h},i(Vb(l,O),!0)),S===Ub&&m.createElement(`span`,{style:{whiteSpace:`inherit`},ref:g}))}var Yb=({enableEllipsis:e,isEllipsis:t,open:n,children:r,tooltipProps:i})=>{if(!i?.title||!e)return r;let a=n&&t;return m.createElement(bv,{open:a,...i},r)};function Xb({mark:e,code:t,underline:n,delete:r,strong:i,keyboard:a,italic:o},s){let c=s;function l(e,t){t&&(c=m.createElement(e,{},c))}return l(`strong`,i),l(`u`,n),l(`del`,r),l(`code`,t),l(`mark`,e),l(`kbd`,a),l(`i`,o),c}var Zb=`...`,Qb=[`delete`,`mark`,`code`,`underline`,`strong`,`keyboard`,`italic`],$b=m.forwardRef((e,t)=>{let{prefixCls:n,className:r,style:i,type:a,disabled:o,children:s,ellipsis:c,editable:l,copyable:u,component:d,title:f,onMouseEnter:p,onMouseLeave:h,...g}=e,{getPrefixCls:_,direction:v}=m.useContext(zt),[y]=Vc(`Text`),b=m.useRef(null),x=m.useRef(null),S=_(`typography`,n),C=tt(g,Qb),[w,T]=Db(l),[E,D]=xe(!1,T.editing),{triggerType:O=[`icon`]}=T,k=e=>{e&&T.onStart?.(),D(e)},A=Ob(E);G(()=>{!E&&A&&x.current?.focus()},[E]);let j=e=>{e?.preventDefault(),k(!0)},M=e=>{T.onChange?.(e),k(!1)},N=()=>{T.onCancel?.(),k(!1)},[P,F]=Db(u),{copied:I,copyLoading:L,onClick:ee}=Eb({copyConfig:F,children:s}),[R,z]=m.useState(!1),[B,V]=m.useState(!1),[te,ne]=m.useState(!1),[re,ie]=m.useState(!1),[ae,oe]=m.useState(!0),[H,se]=Db(c,{expandable:!1,symbol:e=>e?y?.collapse:y?.expand}),[ce,le]=xe(se.defaultExpanded||!1,se.expanded),U=H&&(!ce||se.expandable===`collapsible`),{rows:ue=1}=se,de=m.useMemo(()=>U&&(se.suffix!==void 0||se.onEllipsis||se.expandable||w||P),[U,se,w,P]);G(()=>{H&&!de&&(z(Rh(`webkitLineClamp`)),V(Rh(`textOverflow`)))},[de,H]);let[fe,pe]=m.useState(U),me=m.useMemo(()=>de?!1:ue===1?B:R,[de,B,R]);G(()=>{pe(me&&U)},[me,U]);let he=U&&(fe?re:te),ge=U&&ue===1&&fe,_e=U&&ue>1&&fe,W=(e,t)=>{le(t.expanded),se.onExpand?.(e,t)},[ve,ye]=m.useState(0),[be,Se]=m.useState(!1),[Ce,we]=m.useState(!1),Te=({offsetWidth:e})=>{ye(e)},Ee=e=>{ne(e),te!==e&&se.onEllipsis?.(e)};m.useEffect(()=>{let e=b.current;if(H&&fe&&e){let t=Ib(e);re!==t&&ie(t)}},[H,fe,s,_e,ae,ve]),m.useEffect(()=>{let e=b.current;if(typeof IntersectionObserver>`u`||!e||!fe||!U)return;let t=new IntersectionObserver(()=>{oe(!!e.offsetParent)});return t.observe(e),()=>{t.disconnect()}},[fe,U]);let De=kb(se.tooltip,T.text,s),Oe=m.useMemo(()=>{if(!(!H||fe))return[T.text,s,f,De.title].find(Lb)},[H,fe,f,De.title,he]);if(E)return m.createElement(Sb,{value:T.text??(typeof s==`string`?s:``),onSave:M,onCancel:N,onEnd:T.onEnd,prefixCls:S,className:r,style:i,direction:v,component:d,maxLength:T.maxLength,autoSize:T.autoSize,enterIcon:T.enterIcon});let ke=()=>{let{expandable:e,symbol:t}=se;return e?m.createElement(`button`,{type:`button`,key:`expand`,className:`${S}-${ce?`collapse`:`expand`}`,onClick:e=>W(e,{expanded:!ce}),"aria-label":ce?y.collapse:y?.expand},typeof t==`function`?t(ce):t):null},Ae=()=>{if(!w)return;let{icon:e,tooltip:t,tabIndex:n}=T,r=nt(t)[0]||y?.edit,i=typeof r==`string`?r:``;return O.includes(`icon`)?m.createElement(bv,{key:`edit`,title:t===!1?``:r},m.createElement(`button`,{type:`button`,ref:x,className:`${S}-edit`,onClick:j,"aria-label":i,tabIndex:n},e||m.createElement(ub,{role:`button`}))):null},je=()=>P?m.createElement(Rb,{key:`copy`,...F,prefixCls:S,copied:I,locale:y,onCopy:ee,loading:L,iconOnly:!Gc(s)}):null,Ne=e=>{let t=e&&ke(),n=Ae(),r=je();return!t&&!n&&!r?null:m.createElement(`span`,{key:`operations`,className:`${S}-actions`,onMouseEnter:()=>Se(!0),onMouseLeave:()=>Se(!1)},t,n,r)},Pe=e=>[e&&!ce&&m.createElement(`span`,{"aria-hidden":!0,key:`ellipsis`},Zb),se.suffix,Ne(e)];return m.createElement(Ct,{onResize:Te,disabled:!U},c=>m.createElement(Yb,{tooltipProps:De,enableEllipsis:U,isEllipsis:he,open:Ce&&!be},m.createElement(Ab,{onMouseEnter:e=>{we(!0),p?.(e)},onMouseLeave:e=>{we(!1),h?.(e)},className:K({[`${S}-${a}`]:a,[`${S}-disabled`]:o,[`${S}-ellipsis`]:H,[`${S}-ellipsis-single-line`]:ge,[`${S}-ellipsis-multiple-line`]:_e,[`${S}-link`]:d===`a`},r),prefixCls:n,style:{...i,WebkitLineClamp:_e?ue:void 0},component:d,ref:Me(c,b,t),direction:v,onClick:O.includes(`text`)?j:void 0,"aria-label":Oe?.toString(),title:f,...C},m.createElement(Jb,{enableMeasure:U&&!fe,text:s,rows:ue,width:ve,onEllipsis:Ee,expanded:ce,miscDeps:[I,ce,L,w,P,y].concat(At(Qb.map(t=>e[t])))},(t,n)=>Xb(e,m.createElement(m.Fragment,null,t.length>0&&n&&!ce&&Oe?m.createElement(`span`,{key:`show-content`,"aria-hidden":!0},t):t,Pe(n)))))))}),ex=m.forwardRef((e,t)=>{let{ellipsis:n,rel:r,children:i,navigate:a,...o}=e,s={...o,rel:r===void 0&&o.target===`_blank`?`noopener noreferrer`:r};return m.createElement($b,{...s,ref:t,ellipsis:!!n,component:`a`},i)}),tx=m.forwardRef((e,t)=>{let{children:n,...r}=e;return m.createElement($b,{ref:t,...r,component:`div`},n)}),nx=m.forwardRef((e,t)=>{let{ellipsis:n,children:r,...i}=e,a=m.useMemo(()=>n&&typeof n==`object`?tt(n,[`expandable`,`rows`]):n,[n]);return m.createElement($b,{ref:t,...i,ellipsis:a,component:`span`},r)}),rx=[1,2,3,4,5],ix=m.forwardRef((e,t)=>{let{level:n=1,children:r,...i}=e,a=rx.includes(n)?`h${n}`:`h1`;return m.createElement($b,{ref:t,...i,component:a},r)}),ax=Ab;ax.Text=nx,ax.Link=ex,ax.Title=ix,ax.Paragraph=tx;var ox=class extends Error{};ox.prototype.name=`InvalidTokenError`;function sx(e){return decodeURIComponent(atob(e).replace(/(.)/g,(e,t)=>{let n=t.charCodeAt(0).toString(16).toUpperCase();return n.length<2&&(n=`0`+n),`%`+n}))}function cx(e){let t=e.replace(/-/g,`+`).replace(/_/g,`/`);switch(t.length%4){case 0:break;case 2:t+=`==`;break;case 3:t+=`=`;break;default:throw Error(`base64 string is not of the correct length`)}try{return sx(t)}catch{return atob(t)}}function lx(e,t){if(typeof e!=`string`)throw new ox(`Invalid token specified: must be a string`);t||={};let n=t.header===!0?0:1,r=e.split(`.`)[n];if(typeof r!=`string`)throw new ox(`Invalid token specified: missing part #${n+1}`);let i;try{i=cx(r)}catch(e){throw new ox(`Invalid token specified: invalid base64 for part #${n+1} (${e.message})`)}try{return JSON.parse(i)}catch(e){throw new ox(`Invalid token specified: invalid json for part #${n+1} (${e.message})`)}}var ux={debug:()=>void 0,info:()=>void 0,warn:()=>void 0,error:()=>void 0},dx,fx,px=(e=>(e[e.NONE=0]=`NONE`,e[e.ERROR=1]=`ERROR`,e[e.WARN=2]=`WARN`,e[e.INFO=3]=`INFO`,e[e.DEBUG=4]=`DEBUG`,e))(px||{});(e=>{function t(){dx=3,fx=ux}e.reset=t;function n(e){if(!(0<=e&&e<=4))throw Error(`Invalid log level`);dx=e}e.setLevel=n;function r(e){fx=e}e.setLogger=r})(px||={});var mx=class e{constructor(e){this._name=e}debug(...t){dx>=4&&fx.debug(e._format(this._name,this._method),...t)}info(...t){dx>=3&&fx.info(e._format(this._name,this._method),...t)}warn(...t){dx>=2&&fx.warn(e._format(this._name,this._method),...t)}error(...t){dx>=1&&fx.error(e._format(this._name,this._method),...t)}throw(e){throw this.error(e),e}create(e){let t=Object.create(this);return t._method=e,t.debug(`begin`),t}static createStatic(t,n){let r=new e(`${t}.${n}`);return r.debug(`begin`),r}static _format(e,t){let n=`[${e}]`;return t?`${n} ${t}:`:n}static debug(t,...n){dx>=4&&fx.debug(e._format(t),...n)}static info(t,...n){dx>=3&&fx.info(e._format(t),...n)}static warn(t,...n){dx>=2&&fx.warn(e._format(t),...n)}static error(t,...n){dx>=1&&fx.error(e._format(t),...n)}};px.reset();var hx=class{static decode(e){try{return lx(e)}catch(e){throw mx.error(`JwtUtils.decode`,e),e}}static async generateSignedJwt(e,t,n){let r=`${yx.encodeBase64Url(new TextEncoder().encode(JSON.stringify(e)))}.${yx.encodeBase64Url(new TextEncoder().encode(JSON.stringify(t)))}`,i=await window.crypto.subtle.sign({name:`ECDSA`,hash:{name:`SHA-256`}},n,new TextEncoder().encode(r));return`${r}.${yx.encodeBase64Url(new Uint8Array(i))}`}static async generateSignedJwtWithHmac(e,t,n){let r=`${yx.encodeBase64Url(new TextEncoder().encode(JSON.stringify(e)))}.${yx.encodeBase64Url(new TextEncoder().encode(JSON.stringify(t)))}`,i=await window.crypto.subtle.sign(`HMAC`,n,new TextEncoder().encode(r));return`${r}.${yx.encodeBase64Url(new Uint8Array(i))}`}},gx=`10000000-1000-4000-8000-100000000000`,_x=e=>btoa([...new Uint8Array(e)].map(e=>String.fromCharCode(e)).join(``)),vx=class e{static _randomWord(){let e=new Uint32Array(1);return crypto.getRandomValues(e),e[0]}static generateUUIDv4(){return gx.replace(/[018]/g,t=>(t^e._randomWord()&15>>t/4).toString(16)).replace(/-/g,``)}static generateCodeVerifier(){return e.generateUUIDv4()+e.generateUUIDv4()+e.generateUUIDv4()}static async generateCodeChallenge(e){if(!crypto.subtle)throw Error(`Crypto.subtle is available only in secure contexts (HTTPS).`);try{let t=new TextEncoder().encode(e);return _x(await crypto.subtle.digest(`SHA-256`,t)).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}catch(e){throw mx.error(`CryptoUtils.generateCodeChallenge`,e),e}}static generateBasicAuth(e,t){return _x(new TextEncoder().encode([e,t].join(`:`)))}static async hash(e,t){let n=new TextEncoder().encode(t),r=await crypto.subtle.digest(e,n);return new Uint8Array(r)}static async customCalculateJwkThumbprint(t){let n;switch(t.kty){case`RSA`:n={e:t.e,kty:t.kty,n:t.n};break;case`EC`:n={crv:t.crv,kty:t.kty,x:t.x,y:t.y};break;case`OKP`:n={crv:t.crv,kty:t.kty,x:t.x};break;case`oct`:n={crv:t.k,kty:t.kty};break;default:throw Error(`Unknown jwk type`)}let r=await e.hash(`SHA-256`,JSON.stringify(n));return e.encodeBase64Url(r)}static async generateDPoPProof({url:t,accessToken:n,httpMethod:r,keyPair:i,nonce:a}){let o,s,c={jti:window.crypto.randomUUID(),htm:r??`GET`,htu:t,iat:Math.floor(Date.now()/1e3)};n&&(o=await e.hash(`SHA-256`,n),s=e.encodeBase64Url(o),c.ath=s),a&&(c.nonce=a);try{let e=await crypto.subtle.exportKey(`jwk`,i.publicKey),t={alg:`ES256`,typ:`dpop+jwt`,jwk:{crv:e.crv,kty:e.kty,x:e.x,y:e.y}};return await hx.generateSignedJwt(t,c,i.privateKey)}catch(e){throw e instanceof TypeError?Error(`Error exporting dpop public key: ${e.message}`):e}}static async generateDPoPJkt(t){try{let n=await crypto.subtle.exportKey(`jwk`,t.publicKey);return await e.customCalculateJwkThumbprint(n)}catch(e){throw e instanceof TypeError?Error(`Could not retrieve dpop keys from storage: ${e.message}`):e}}static async generateDPoPKeys(){return await window.crypto.subtle.generateKey({name:`ECDSA`,namedCurve:`P-256`},!1,[`sign`,`verify`])}static async generateClientAssertionJwt(t,n,r,i=`HS256`){let a=Math.floor(Date.now()/1e3),o={alg:i,typ:`JWT`},s={iss:t,sub:t,aud:r,jti:e.generateUUIDv4(),exp:a+300,iat:a},c={HS256:`SHA-256`,HS384:`SHA-384`,HS512:`SHA-512`}[i];if(!c)throw Error(`Unsupported algorithm: ${i}. Supported algorithms are: HS256, HS384, HS512`);let l=new TextEncoder,u=await crypto.subtle.importKey(`raw`,l.encode(n),{name:`HMAC`,hash:c},!1,[`sign`]);return await hx.generateSignedJwtWithHmac(o,s,u)}};vx.encodeBase64Url=e=>_x(e).replace(/=/g,``).replace(/\+/g,`-`).replace(/\//g,`_`);var yx=vx,bx=class{constructor(e){this._name=e,this._callbacks=[],this._logger=new mx(`Event('${this._name}')`)}addHandler(e){return this._callbacks.push(e),()=>this.removeHandler(e)}removeHandler(e){let t=this._callbacks.lastIndexOf(e);t>=0&&this._callbacks.splice(t,1)}async raise(...e){this._logger.debug(`raise:`,...e);for(let t of this._callbacks)await t(...e)}},xx=class{static center({...e}){return e.width??=[800,720,600,480].find(e=>e<=window.outerWidth/1.618)??360,e.left??=Math.max(0,Math.round(window.screenX+(window.outerWidth-e.width)/2)),e.height!=null&&(e.top??=Math.max(0,Math.round(window.screenY+(window.outerHeight-e.height)/2))),e}static serialize(e){return Object.entries(e).filter(([,e])=>e!=null).map(([e,t])=>`${e}=${typeof t==`boolean`?t?`yes`:`no`:t}`).join(`,`)}},Sx=class e extends bx{constructor(){super(...arguments),this._logger=new mx(`Timer('${this._name}')`),this._timerHandle=null,this._expiration=0,this._callback=()=>{let t=this._expiration-e.getEpochTime();this._logger.debug(`timer completes in`,t),this._expiration<=e.getEpochTime()&&(this.cancel(),super.raise())}}static getEpochTime(){return Math.floor(Date.now()/1e3)}init(t){let n=this._logger.create(`init`);t=Math.max(Math.floor(t),1);let r=e.getEpochTime()+t;if(this.expiration===r&&this._timerHandle){n.debug(`skipping since already initialized for expiration at`,this.expiration);return}this.cancel(),n.debug(`using duration`,t),this._expiration=r;let i=Math.min(t,5);this._timerHandle=setInterval(this._callback,i*1e3)}get expiration(){return this._expiration}cancel(){this._logger.create(`cancel`),this._timerHandle&&=(clearInterval(this._timerHandle),null)}},Cx=class{static readParams(e,t=`query`){if(!e)throw TypeError(`Invalid URL`);let n=new URL(e,`http://127.0.0.1`)[t===`fragment`?`hash`:`search`];return new URLSearchParams(n.slice(1))}},wx=`;`,Tx=class extends Error{constructor(e,t){if(super(e.error_description||e.error||``),this.form=t,this.name=`ErrorResponse`,!e.error)throw mx.error(`ErrorResponse`,`No error passed`),Error(`No error passed`);this.error=e.error,this.error_description=e.error_description??null,this.error_uri=e.error_uri??null,this.state=e.userState,this.session_state=e.session_state??null,this.url_state=e.url_state}},Ex=class extends Error{constructor(e){super(e),this.name=`ErrorTimeout`}},Dx=class{constructor(e){this._logger=new mx(`AccessTokenEvents`),this._expiringTimer=new Sx(`Access token expiring`),this._expiredTimer=new Sx(`Access token expired`),this._expiringNotificationTimeInSeconds=e.expiringNotificationTimeInSeconds}async load(e){let t=this._logger.create(`load`);if(e.access_token&&e.expires_in!==void 0){let n=e.expires_in;if(t.debug(`access token present, remaining duration:`,n),n>0){let e=n-this._expiringNotificationTimeInSeconds;e<=0&&(e=1),t.debug(`registering expiring timer, raising in`,e,`seconds`),this._expiringTimer.init(e)}else t.debug(`canceling existing expiring timer because we're past expiration.`),this._expiringTimer.cancel();let r=n+1;t.debug(`registering expired timer, raising in`,r,`seconds`),this._expiredTimer.init(r)}else this._expiringTimer.cancel(),this._expiredTimer.cancel()}async unload(){this._logger.debug(`unload: canceling existing access token timers`),this._expiringTimer.cancel(),this._expiredTimer.cancel()}addAccessTokenExpiring(e){return this._expiringTimer.addHandler(e)}removeAccessTokenExpiring(e){this._expiringTimer.removeHandler(e)}addAccessTokenExpired(e){return this._expiredTimer.addHandler(e)}removeAccessTokenExpired(e){this._expiredTimer.removeHandler(e)}},Ox=class{constructor(e,t,n,r,i){this._callback=e,this._client_id=t,this._intervalInSeconds=r,this._stopOnError=i,this._logger=new mx(`CheckSessionIFrame`),this._timer=null,this._session_state=null,this._message=e=>{e.origin===this._frame_origin&&e.source===this._frame.contentWindow&&(e.data===`error`?(this._logger.error(`error message from check session op iframe`),this._stopOnError&&this.stop()):e.data===`changed`?(this._logger.debug(`changed message from check session op iframe`),this.stop(),this._callback()):this._logger.debug(e.data+` message from check session op iframe`))};let a=new URL(n);this._frame_origin=a.origin,this._frame=window.document.createElement(`iframe`),this._frame.style.visibility=`hidden`,this._frame.style.position=`fixed`,this._frame.style.left=`-1000px`,this._frame.style.top=`0`,this._frame.width=`0`,this._frame.height=`0`,this._frame.src=a.href}load(){return new Promise(e=>{this._frame.onload=()=>{e()},window.document.body.appendChild(this._frame),window.addEventListener(`message`,this._message,!1)})}start(e){if(this._session_state===e)return;this._logger.create(`start`),this.stop(),this._session_state=e;let t=()=>{!this._frame.contentWindow||!this._session_state||this._frame.contentWindow.postMessage(this._client_id+` `+this._session_state,this._frame_origin)};t(),this._timer=setInterval(t,this._intervalInSeconds*1e3)}stop(){this._logger.create(`stop`),this._session_state=null,this._timer&&=(clearInterval(this._timer),null)}},kx=class{constructor(){this._logger=new mx(`InMemoryWebStorage`),this._data={}}clear(){this._logger.create(`clear`),this._data={}}getItem(e){return this._logger.create(`getItem('${e}')`),this._data[e]}setItem(e,t){this._logger.create(`setItem('${e}')`),this._data[e]=t}removeItem(e){this._logger.create(`removeItem('${e}')`),delete this._data[e]}get length(){return Object.getOwnPropertyNames(this._data).length}key(e){return Object.getOwnPropertyNames(this._data)[e]}},Ax=class extends Error{constructor(e,t){super(t),this.name=`ErrorDPoPNonce`,this.nonce=e}},jx=class{constructor(e=[],t=null,n={}){this._jwtHandler=t,this._extraHeaders=n,this._logger=new mx(`JsonService`),this._contentTypes=[],this._contentTypes.push(...e,`application/json`),t&&this._contentTypes.push(`application/jwt`)}async fetchWithTimeout(e,t={}){let{timeoutInSeconds:n,...r}=t;if(!n)return await fetch(e,r);let i=new AbortController,a=setTimeout(()=>i.abort(),n*1e3);try{return await fetch(e,{...t,signal:i.signal})}catch(e){throw e instanceof DOMException&&e.name===`AbortError`?new Ex(`Network timed out`):e}finally{clearTimeout(a)}}async getJson(e,{token:t,credentials:n,timeoutInSeconds:r}={}){let i=this._logger.create(`getJson`),a={Accept:this._contentTypes.join(`, `)};t&&(i.debug(`token passed, setting Authorization header`),a.Authorization=`Bearer `+t),this._appendExtraHeaders(a);let o;try{i.debug(`url:`,e),o=await this.fetchWithTimeout(e,{method:`GET`,headers:a,timeoutInSeconds:r,credentials:n})}catch(e){throw i.error(`Network Error`),e}i.debug(`HTTP response received, status`,o.status);let s=o.headers.get(`Content-Type`);if(s&&!this._contentTypes.find(e=>s.startsWith(e))&&i.throw(Error(`Invalid response Content-Type: ${s??`undefined`}, from URL: ${e}`)),o.ok&&this._jwtHandler&&s?.startsWith(`application/jwt`))return await this._jwtHandler(await o.text());let c;try{c=await o.json()}catch(e){throw i.error(`Error parsing JSON response`,e),o.ok?e:Error(`${o.statusText} (${o.status})`)}if(!o.ok)throw i.error(`Error from server:`,c),c.error?new Tx(c):Error(`${o.statusText} (${o.status}): ${JSON.stringify(c)}`);return c}async postForm(e,{body:t,basicAuth:n,timeoutInSeconds:r,initCredentials:i,extraHeaders:a}){let o=this._logger.create(`postForm`),s={Accept:this._contentTypes.join(`, `),"Content-Type":`application/x-www-form-urlencoded`,...a};n!==void 0&&(s.Authorization=`Basic `+n),this._appendExtraHeaders(s);let c;try{o.debug(`url:`,e),c=await this.fetchWithTimeout(e,{method:`POST`,headers:s,body:t,timeoutInSeconds:r,credentials:i})}catch(e){throw o.error(`Network error`),e}o.debug(`HTTP response received, status`,c.status);let l=c.headers.get(`Content-Type`);if(l&&!this._contentTypes.find(e=>l.startsWith(e)))throw Error(`Invalid response Content-Type: ${l??`undefined`}, from URL: ${e}`);let u=await c.text(),d={};if(u)try{d=JSON.parse(u)}catch(e){throw o.error(`Error parsing JSON response`,e),c.ok?e:Error(`${c.statusText} (${c.status})`)}if(!c.ok)throw o.error(`Error from server:`,d),c.headers.has(`dpop-nonce`)?new Ax(c.headers.get(`dpop-nonce`),`${JSON.stringify(d)}`):d.error?new Tx(d,t):Error(`${c.statusText} (${c.status}): ${JSON.stringify(d)}`);return d}_appendExtraHeaders(e){let t=this._logger.create(`appendExtraHeaders`),n=Object.keys(this._extraHeaders),r=[`accept`,`content-type`],i=[`authorization`];n.length!==0&&n.forEach(n=>{if(r.includes(n.toLocaleLowerCase())){t.warn(`Protected header could not be set`,n,r);return}if(i.includes(n.toLocaleLowerCase())&&Object.keys(e).includes(n)){t.warn(`Header could not be overridden`,n,i);return}let a=typeof this._extraHeaders[n]==`function`?this._extraHeaders[n]():this._extraHeaders[n];a&&a!==``&&(e[n]=a)})}},Mx=class{constructor(e){this._settings=e,this._logger=new mx(`MetadataService`),this._signingKeys=null,this._metadata=null,this._metadataUrl=this._settings.metadataUrl,this._jsonService=new jx([`application/jwk-set+json`],null,this._settings.extraHeaders),this._settings.signingKeys&&(this._logger.debug(`using signingKeys from settings`),this._signingKeys=this._settings.signingKeys),this._settings.metadata&&(this._logger.debug(`using metadata from settings`),this._metadata=this._settings.metadata),this._settings.fetchRequestCredentials&&(this._logger.debug(`using fetchRequestCredentials from settings`),this._fetchRequestCredentials=this._settings.fetchRequestCredentials)}resetSigningKeys(){this._signingKeys=null}async getMetadata(){let e=this._logger.create(`getMetadata`);if(this._metadata)return e.debug(`using cached values`),this._metadata;if(!this._metadataUrl)throw e.throw(Error(`No authority or metadataUrl configured on settings`)),null;e.debug(`getting metadata from`,this._metadataUrl);let t=await this._jsonService.getJson(this._metadataUrl,{credentials:this._fetchRequestCredentials,timeoutInSeconds:this._settings.requestTimeoutInSeconds});return e.debug(`merging remote JSON with seed metadata`),this._metadata=Object.assign({},t,this._settings.metadataSeed),this._metadata}getIssuer(){return this._getMetadataProperty(`issuer`)}getAuthorizationEndpoint(){return this._getMetadataProperty(`authorization_endpoint`)}getUserInfoEndpoint(){return this._getMetadataProperty(`userinfo_endpoint`)}getTokenEndpoint(e=!0){return this._getMetadataProperty(`token_endpoint`,e)}getCheckSessionIframe(){return this._getMetadataProperty(`check_session_iframe`,!0)}getEndSessionEndpoint(){return this._getMetadataProperty(`end_session_endpoint`,!0)}getRevocationEndpoint(e=!0){return this._getMetadataProperty(`revocation_endpoint`,e)}getKeysEndpoint(e=!0){return this._getMetadataProperty(`jwks_uri`,e)}async _getMetadataProperty(e,t=!1){let n=this._logger.create(`_getMetadataProperty('${e}')`),r=await this.getMetadata();if(n.debug(`resolved`),r[e]===void 0){if(t===!0){n.warn(`Metadata does not contain optional property`);return}n.throw(Error(`Metadata does not contain property `+e))}return r[e]}async getSigningKeys(){let e=this._logger.create(`getSigningKeys`);if(this._signingKeys)return e.debug(`returning signingKeys from cache`),this._signingKeys;let t=await this.getKeysEndpoint(!1);e.debug(`got jwks_uri`,t);let n=await this._jsonService.getJson(t,{timeoutInSeconds:this._settings.requestTimeoutInSeconds});if(e.debug(`got key set`,n),!Array.isArray(n.keys))throw e.throw(Error(`Missing keys on keyset`)),null;return this._signingKeys=n.keys,this._signingKeys}},Nx=class{constructor({prefix:e=`oidc.`,store:t=localStorage}={}){this._logger=new mx(`WebStorageStateStore`),this._store=t,this._prefix=e}async set(e,t){this._logger.create(`set('${e}')`),e=this._prefix+e,await this._store.setItem(e,t)}async get(e){return this._logger.create(`get('${e}')`),e=this._prefix+e,await this._store.getItem(e)}async remove(e){this._logger.create(`remove('${e}')`),e=this._prefix+e;let t=await this._store.getItem(e);return await this._store.removeItem(e),t}async getAllKeys(){this._logger.create(`getAllKeys`);let e=await this._store.length,t=[];for(let n=0;n{let t=this._logger.create(`_getClaimsFromJwt`);try{let n=hx.decode(e);return t.debug(`JWT decoding successful`),n}catch(e){throw t.error(`Error parsing JWT response`),e}},this._jsonService=new jx(void 0,this._getClaimsFromJwt,this._settings.extraHeaders)}async getClaims(e){let t=this._logger.create(`getClaims`);e||this._logger.throw(Error(`No token passed`));let n=await this._metadataService.getUserInfoEndpoint();t.debug(`got userinfo url`,n);let r=await this._jsonService.getJson(n,{token:e,credentials:this._settings.fetchRequestCredentials,timeoutInSeconds:this._settings.requestTimeoutInSeconds});return t.debug(`got claims`,r),r}},Bx=class{constructor(e,t){this._settings=e,this._metadataService=t,this._logger=new mx(`TokenClient`),this._jsonService=new jx(this._settings.revokeTokenAdditionalContentTypes,null,this._settings.extraHeaders)}async exchangeCode({grant_type:e=`authorization_code`,redirect_uri:t=this._settings.redirect_uri,client_id:n=this._settings.client_id,client_secret:r=this._settings.client_secret,extraHeaders:i,...a}){let o=this._logger.create(`exchangeCode`);n||o.throw(Error(`A client_id is required`)),t||o.throw(Error(`A redirect_uri is required`)),a.code||o.throw(Error(`A code is required`));let s=new URLSearchParams({grant_type:e,redirect_uri:t});for(let[e,t]of Object.entries(a))t!=null&&s.set(e,t);if((this._settings.client_authentication===`client_secret_basic`||this._settings.client_authentication===`client_secret_jwt`)&&r==null)throw o.throw(Error(`A client_secret is required`)),null;let c,l=await this._metadataService.getTokenEndpoint(!1);switch(this._settings.client_authentication){case`client_secret_basic`:c=yx.generateBasicAuth(n,r);break;case`client_secret_post`:s.append(`client_id`,n),r&&s.append(`client_secret`,r);break;case`client_secret_jwt`:{let e=await yx.generateClientAssertionJwt(n,r,l,this._settings.token_endpoint_auth_signing_alg);s.append(`client_id`,n),s.append(`client_assertion_type`,`urn:ietf:params:oauth:client-assertion-type:jwt-bearer`),s.append(`client_assertion`,e);break}}o.debug(`got token endpoint`);let u=await this._jsonService.postForm(l,{body:s,basicAuth:c,timeoutInSeconds:this._settings.requestTimeoutInSeconds,initCredentials:this._settings.fetchRequestCredentials,extraHeaders:i});return o.debug(`got response`),u}async exchangeCredentials({grant_type:e=`password`,client_id:t=this._settings.client_id,client_secret:n=this._settings.client_secret,scope:r=this._settings.scope,...i}){let a=this._logger.create(`exchangeCredentials`);t||a.throw(Error(`A client_id is required`));let o=new URLSearchParams({grant_type:e});this._settings.omitScopeWhenRequesting||o.set(`scope`,r);for(let[e,t]of Object.entries(i))t!=null&&o.set(e,t);if((this._settings.client_authentication===`client_secret_basic`||this._settings.client_authentication===`client_secret_jwt`)&&n==null)throw a.throw(Error(`A client_secret is required`)),null;let s,c=await this._metadataService.getTokenEndpoint(!1);switch(this._settings.client_authentication){case`client_secret_basic`:s=yx.generateBasicAuth(t,n);break;case`client_secret_post`:o.append(`client_id`,t),n&&o.append(`client_secret`,n);break;case`client_secret_jwt`:{let e=await yx.generateClientAssertionJwt(t,n,c,this._settings.token_endpoint_auth_signing_alg);o.append(`client_id`,t),o.append(`client_assertion_type`,`urn:ietf:params:oauth:client-assertion-type:jwt-bearer`),o.append(`client_assertion`,e);break}}a.debug(`got token endpoint`);let l=await this._jsonService.postForm(c,{body:o,basicAuth:s,timeoutInSeconds:this._settings.requestTimeoutInSeconds,initCredentials:this._settings.fetchRequestCredentials});return a.debug(`got response`),l}async exchangeRefreshToken({grant_type:e=`refresh_token`,client_id:t=this._settings.client_id,client_secret:n=this._settings.client_secret,timeoutInSeconds:r,extraHeaders:i,...a}){let o=this._logger.create(`exchangeRefreshToken`);t||o.throw(Error(`A client_id is required`)),a.refresh_token||o.throw(Error(`A refresh_token is required`));let s=new URLSearchParams({grant_type:e});for(let[e,t]of Object.entries(a))Array.isArray(t)?t.forEach(t=>s.append(e,t)):t!=null&&s.set(e,t);if((this._settings.client_authentication===`client_secret_basic`||this._settings.client_authentication===`client_secret_jwt`)&&n==null)throw o.throw(Error(`A client_secret is required`)),null;let c,l=await this._metadataService.getTokenEndpoint(!1);switch(this._settings.client_authentication){case`client_secret_basic`:c=yx.generateBasicAuth(t,n);break;case`client_secret_post`:s.append(`client_id`,t),n&&s.append(`client_secret`,n);break;case`client_secret_jwt`:{let e=await yx.generateClientAssertionJwt(t,n,l,this._settings.token_endpoint_auth_signing_alg);s.append(`client_id`,t),s.append(`client_assertion_type`,`urn:ietf:params:oauth:client-assertion-type:jwt-bearer`),s.append(`client_assertion`,e);break}}o.debug(`got token endpoint`);let u=await this._jsonService.postForm(l,{body:s,basicAuth:c,timeoutInSeconds:r,initCredentials:this._settings.fetchRequestCredentials,extraHeaders:i});return o.debug(`got response`),u}async revoke(e){let t=this._logger.create(`revoke`);e.token||t.throw(Error(`A token is required`));let n=await this._metadataService.getRevocationEndpoint(!1);t.debug(`got revocation endpoint, revoking ${e.token_type_hint??`default token type`}`);let r=new URLSearchParams;for(let[t,n]of Object.entries(e))n!=null&&r.set(t,n);r.set(`client_id`,this._settings.client_id),this._settings.client_secret&&r.set(`client_secret`,this._settings.client_secret),await this._jsonService.postForm(n,{body:r,timeoutInSeconds:this._settings.requestTimeoutInSeconds}),t.debug(`got response`)}},Vx=class{constructor(e,t,n){this._settings=e,this._metadataService=t,this._claimsService=n,this._logger=new mx(`ResponseValidator`),this._userInfoService=new zx(this._settings,this._metadataService),this._tokenClient=new Bx(this._settings,this._metadataService)}async validateSigninResponse(e,t,n){let r=this._logger.create(`validateSigninResponse`);this._processSigninState(e,t),r.debug(`state processed`),await this._processCode(e,t,n),r.debug(`code processed`),e.isOpenId&&this._validateIdTokenAttributes(e),r.debug(`tokens validated`),await this._processClaims(e,t?.skipUserInfo,e.isOpenId),r.debug(`claims processed`)}async validateCredentialsResponse(e,t){let n=this._logger.create(`validateCredentialsResponse`),r=e.isOpenId&&!!e.id_token;r&&this._validateIdTokenAttributes(e),n.debug(`tokens validated`),await this._processClaims(e,t,r),n.debug(`claims processed`)}async validateRefreshResponse(e,t){let n=this._logger.create(`validateRefreshResponse`);e.userState=t.data,e.session_state??=t.session_state,e.scope??=t.scope,e.isOpenId&&e.id_token&&(this._validateIdTokenAttributes(e,t.id_token),n.debug(`ID Token validated`)),e.id_token||(e.id_token=t.id_token,e.profile=t.profile);let r=e.isOpenId&&!!e.id_token;await this._processClaims(e,!1,r),n.debug(`claims processed`)}validateSignoutResponse(e,t){let n=this._logger.create(`validateSignoutResponse`);if(t.id!==e.state&&n.throw(Error(`State does not match`)),n.debug(`state validated`),e.userState=t.data,e.error)throw n.warn(`Response was error`,e.error),new Tx(e)}_processSigninState(e,t){let n=this._logger.create(`_processSigninState`);if(t.id!==e.state&&n.throw(Error(`State does not match`)),t.client_id||n.throw(Error(`No client_id on state`)),t.authority||n.throw(Error(`No authority on state`)),this._settings.authority!==t.authority&&n.throw(Error(`authority mismatch on settings vs. signin state`)),this._settings.client_id&&this._settings.client_id!==t.client_id&&n.throw(Error(`client_id mismatch on settings vs. signin state`)),n.debug(`state validated`),e.userState=t.data,e.url_state=t.url_state,e.scope??=t.scope,e.error)throw n.warn(`Response was error`,e.error),new Tx(e);t.code_verifier&&!e.code&&n.throw(Error(`Expected code in response`))}async _processClaims(e,t=!1,n=!0){let r=this._logger.create(`_processClaims`);if(e.profile=this._claimsService.filterProtocolClaims(e.profile),t||!this._settings.loadUserInfo||!e.access_token){r.debug(`not loading user info`);return}r.debug(`loading user info`);let i=await this._userInfoService.getClaims(e.access_token);r.debug(`user info claims received from user info endpoint`),n&&i.sub!==e.profile.sub&&r.throw(Error(`subject from UserInfo response does not match subject in ID Token`)),e.profile=this._claimsService.mergeClaims(e.profile,this._claimsService.filterProtocolClaims(i)),r.debug(`user info claims received, updated profile:`,e.profile)}async _processCode(e,t,n){let r=this._logger.create(`_processCode`);if(e.code){r.debug(`Validating code`);let i=await this._tokenClient.exchangeCode({client_id:t.client_id,client_secret:t.client_secret,code:e.code,redirect_uri:t.redirect_uri,code_verifier:t.code_verifier,extraHeaders:n,...t.extraTokenParams});Object.assign(e,i)}else r.debug(`No code to process`)}_validateIdTokenAttributes(e,t){let n=this._logger.create(`_validateIdTokenAttributes`);n.debug(`decoding ID Token JWT`);let r=hx.decode(e.id_token??``);if(r.sub||n.throw(Error(`ID Token is missing a subject claim`)),t){let e=hx.decode(t);r.sub!==e.sub&&n.throw(Error(`sub in id_token does not match current sub`)),r.auth_time&&r.auth_time!==e.auth_time&&n.throw(Error(`auth_time in id_token does not match original auth_time`)),r.azp&&r.azp!==e.azp&&n.throw(Error(`azp in id_token does not match original azp`)),!r.azp&&e.azp&&n.throw(Error(`azp not in id_token, but present in original id_token`))}e.profile=r}},Hx=class e{constructor(e){this.id=e.id||yx.generateUUIDv4(),this.data=e.data,e.created&&e.created>0?this.created=e.created:this.created=Sx.getEpochTime(),this.request_type=e.request_type,this.url_state=e.url_state}toStorageString(){return new mx(`State`).create(`toStorageString`),JSON.stringify({id:this.id,data:this.data,created:this.created,request_type:this.request_type,url_state:this.url_state})}static fromStorageString(t){return mx.createStatic(`State`,`fromStorageString`),Promise.resolve(new e(JSON.parse(t)))}static async clearStaleState(t,n){let r=mx.createStatic(`State`,`clearStaleState`),i=Sx.getEpochTime()-n,a=await t.getAllKeys();r.debug(`got keys`,a);for(let n=0;nS.searchParams.append(`resource`,e));for(let[e,t]of Object.entries({response_mode:c,...b,...h}))t!=null&&S.searchParams.append(e,t.toString());return new e({url:S.href,state:x})}};Wx._logger=new mx(`SigninRequest`);var Gx=Wx,Kx=`openid`,qx=class{constructor(e){if(this.access_token=``,this.token_type=``,this.profile={},this.state=e.get(`state`),this.session_state=e.get(`session_state`),this.state){let e=decodeURIComponent(this.state).split(wx);this.state=e[0],e.length>1&&(this.url_state=e.slice(1).join(wx))}this.error=e.get(`error`),this.error_description=e.get(`error_description`),this.error_uri=e.get(`error_uri`),this.code=e.get(`code`)}get expires_in(){if(this.expires_at!==void 0)return this.expires_at-Sx.getEpochTime()}set expires_in(e){typeof e==`string`&&(e=Number(e)),e!==void 0&&e>=0&&(this.expires_at=Math.floor(e)+Sx.getEpochTime())}get isOpenId(){return this.scope?.split(` `).includes(Kx)||!!this.id_token}},Jx=class{constructor({url:e,state_data:t,id_token_hint:n,post_logout_redirect_uri:r,extraQueryParams:i,request_type:a,client_id:o,url_state:s}){if(this._logger=new mx(`SignoutRequest`),!e)throw this._logger.error(`ctor: No url passed`),Error(`url`);let c=new URL(e);if(n&&c.searchParams.append(`id_token_hint`,n),o&&c.searchParams.append(`client_id`,o),r&&(c.searchParams.append(`post_logout_redirect_uri`,r),t||s)){this.state=new Hx({data:t,request_type:a,url_state:s});let e=this.state.id;s&&(e=`${e}${wx}${s}`),c.searchParams.append(`state`,e)}for(let[e,t]of Object.entries({...i}))t!=null&&c.searchParams.append(e,t.toString());this.url=c.href}},Yx=class{constructor(e){if(this.state=e.get(`state`),this.state){let e=decodeURIComponent(this.state).split(wx);this.state=e[0],e.length>1&&(this.url_state=e.slice(1).join(wx))}this.error=e.get(`error`),this.error_description=e.get(`error_description`),this.error_uri=e.get(`error_uri`)}},Xx=[`nbf`,`jti`,`auth_time`,`nonce`,`acr`,`amr`,`azp`,`at_hash`],Zx=[`sub`,`iss`,`aud`,`exp`,`iat`],Qx=class{constructor(e){this._settings=e,this._logger=new mx(`ClaimsService`)}filterProtocolClaims(e){let t={...e};if(this._settings.filterProtocolClaims){let e;e=Array.isArray(this._settings.filterProtocolClaims)?this._settings.filterProtocolClaims:Xx;for(let n of e)Zx.includes(n)||delete t[n]}return t}mergeClaims(e,t){let n={...e};for(let[e,r]of Object.entries(t))if(n[e]!==r)if(Array.isArray(n[e])||Array.isArray(r))if(this._settings.mergeClaimsStrategy.array==`replace`)n[e]=r;else{let t=Array.isArray(n[e])?n[e]:[n[e]];for(let e of Array.isArray(r)?r:[r])t.includes(e)||t.push(e);n[e]=t}else typeof n[e]==`object`&&typeof r==`object`?n[e]=this.mergeClaims(n[e],r):n[e]=r;return n}},$x=class{constructor(e,t){this.keys=e,this.nonce=t}},eS=class{constructor(e,t){this._logger=new mx(`OidcClient`),this.settings=e instanceof Rx?e:new Rx(e),this.metadataService=t??new Mx(this.settings),this._claimsService=new Qx(this.settings),this._validator=new Vx(this.settings,this.metadataService,this._claimsService),this._tokenClient=new Bx(this.settings,this.metadataService)}async createSigninRequest({state:e,request:t,request_uri:n,request_type:r,id_token_hint:i,login_hint:a,skipUserInfo:o,nonce:s,url_state:c,response_type:l=this.settings.response_type,scope:u=this.settings.scope,redirect_uri:d=this.settings.redirect_uri,prompt:f=this.settings.prompt,display:p=this.settings.display,max_age:m=this.settings.max_age,ui_locales:h=this.settings.ui_locales,acr_values:g=this.settings.acr_values,resource:_=this.settings.resource,response_mode:v=this.settings.response_mode,extraQueryParams:y=this.settings.extraQueryParams,extraTokenParams:b=this.settings.extraTokenParams,dpopJkt:x,omitScopeWhenRequesting:S=this.settings.omitScopeWhenRequesting}){let C=this._logger.create(`createSigninRequest`);if(l!==`code`)throw Error(`Only the Authorization Code flow (with PKCE) is supported`);let w=await this.metadataService.getAuthorizationEndpoint();C.debug(`Received authorization endpoint`,w);let T=await Gx.create({url:w,authority:this.settings.authority,client_id:this.settings.client_id,redirect_uri:d,response_type:l,scope:u,state_data:e,url_state:c,prompt:f,display:p,max_age:m,ui_locales:h,id_token_hint:i,login_hint:a,acr_values:g,dpopJkt:x,resource:_,request:t,request_uri:n,extraQueryParams:y,extraTokenParams:b,request_type:r,response_mode:v,client_secret:this.settings.client_secret,skipUserInfo:o,nonce:s,disablePKCE:this.settings.disablePKCE,omitScopeWhenRequesting:S});await this.clearStaleState();let E=T.state;return await this.settings.stateStore.set(E.id,E.toStorageString()),T}async readSigninResponseState(e,t=!1){let n=this._logger.create(`readSigninResponseState`),r=new qx(Cx.readParams(e,this.settings.response_mode));if(!r.state)throw n.throw(Error(`No state in response`)),null;let i=await this.settings.stateStore[t?`remove`:`get`](r.state);if(!i)throw n.throw(Error(`No matching state found in storage`)),null;return{state:await Ux.fromStorageString(i),response:r}}async processSigninResponse(e,t,n=!0){let r=this._logger.create(`processSigninResponse`),{state:i,response:a}=await this.readSigninResponseState(e,n);if(r.debug(`received state from storage; validating response`),this.settings.dpop&&this.settings.dpop.store){let e=await this.getDpopProof(this.settings.dpop.store);t={...t,DPoP:e}}try{await this._validator.validateSigninResponse(a,i,t)}catch(e){if(e instanceof Ax&&this.settings.dpop){let n=await this.getDpopProof(this.settings.dpop.store,e.nonce);t.DPoP=n,await this._validator.validateSigninResponse(a,i,t)}else throw e}return a}async getDpopProof(e,t){let n,r;return(await e.getAllKeys()).includes(this.settings.client_id)?(r=await e.get(this.settings.client_id),r.nonce!==t&&t&&(r.nonce=t,await e.set(this.settings.client_id,r))):(n=await yx.generateDPoPKeys(),r=new $x(n,t),await e.set(this.settings.client_id,r)),await yx.generateDPoPProof({url:await this.metadataService.getTokenEndpoint(!1),httpMethod:`POST`,keyPair:r.keys,nonce:r.nonce})}async processResourceOwnerPasswordCredentials({username:e,password:t,skipUserInfo:n=!1,extraTokenParams:r={}}){let i=await this._tokenClient.exchangeCredentials({username:e,password:t,...r}),a=new qx(new URLSearchParams);return Object.assign(a,i),await this._validator.validateCredentialsResponse(a,n),a}async useRefreshToken({state:e,redirect_uri:t,resource:n,timeoutInSeconds:r,extraHeaders:i,extraTokenParams:a}){let o=this._logger.create(`useRefreshToken`),s;if(this.settings.refreshTokenAllowedScope===void 0)s=e.scope;else{let t=this.settings.refreshTokenAllowedScope.split(` `);s=(e.scope?.split(` `)||[]).filter(e=>t.includes(e)).join(` `)}if(this.settings.dpop&&this.settings.dpop.store){let e=await this.getDpopProof(this.settings.dpop.store);i={...i,DPoP:e}}let c;try{c=await this._tokenClient.exchangeRefreshToken({refresh_token:e.refresh_token,scope:s,redirect_uri:t,resource:n,timeoutInSeconds:r,extraHeaders:i,...a})}catch(o){if(o instanceof Ax&&this.settings.dpop)i.DPoP=await this.getDpopProof(this.settings.dpop.store,o.nonce),c=await this._tokenClient.exchangeRefreshToken({refresh_token:e.refresh_token,scope:s,redirect_uri:t,resource:n,timeoutInSeconds:r,extraHeaders:i,...a});else throw o}let l=new qx(new URLSearchParams);return Object.assign(l,c),o.debug(`validating response`,l),await this._validator.validateRefreshResponse(l,{...e,scope:s}),l}async createSignoutRequest({state:e,id_token_hint:t,client_id:n,request_type:r,url_state:i,post_logout_redirect_uri:a=this.settings.post_logout_redirect_uri,extraQueryParams:o=this.settings.extraQueryParams}={}){let s=this._logger.create(`createSignoutRequest`),c=await this.metadataService.getEndSessionEndpoint();if(!c)throw s.throw(Error(`No end session endpoint`)),null;s.debug(`Received end session endpoint`,c),!n&&a&&!t&&(n=this.settings.client_id);let l=new Jx({url:c,id_token_hint:t,client_id:n,post_logout_redirect_uri:a,state_data:e,extraQueryParams:o,request_type:r,url_state:i});await this.clearStaleState();let u=l.state;return u&&(s.debug(`Signout request has state to persist`),await this.settings.stateStore.set(u.id,u.toStorageString())),l}async readSignoutResponseState(e,t=!1){let n=this._logger.create(`readSignoutResponseState`),r=new Yx(Cx.readParams(e,this.settings.response_mode));if(!r.state){if(n.debug(`No state in response`),r.error)throw n.warn(`Response was error:`,r.error),new Tx(r);return{state:void 0,response:r}}let i=await this.settings.stateStore[t?`remove`:`get`](r.state);if(!i)throw n.throw(Error(`No matching state found in storage`)),null;return{state:await Hx.fromStorageString(i),response:r}}async processSignoutResponse(e){let t=this._logger.create(`processSignoutResponse`),{state:n,response:r}=await this.readSignoutResponseState(e,!0);return n?(t.debug(`Received state from storage; validating response`),this._validator.validateSignoutResponse(r,n)):t.debug(`No state from storage; skipping response validation`),r}clearStaleState(){return this._logger.create(`clearStaleState`),Hx.clearStaleState(this.settings.stateStore,this.settings.staleStateAgeInSeconds)}async revokeToken(e,t){return this._logger.create(`revokeToken`),await this._tokenClient.revoke({token:e,token_type_hint:t})}},tS=class{constructor(e){this._userManager=e,this._logger=new mx(`SessionMonitor`),this._start=async e=>{let t=e.session_state;if(!t)return;let n=this._logger.create(`_start`);if(e.profile?(this._sub=e.profile.sub,n.debug(`session_state`,t,`, sub`,this._sub)):(this._sub=void 0,n.debug(`session_state`,t,`, anonymous user`)),this._checkSessionIFrame){this._checkSessionIFrame.start(t);return}try{let e=await this._userManager.metadataService.getCheckSessionIframe();if(e){n.debug(`initializing check session iframe`);let r=this._userManager.settings.client_id,i=this._userManager.settings.checkSessionIntervalInSeconds,a=this._userManager.settings.stopCheckSessionOnError,o=new Ox(this._callback,r,e,i,a);await o.load(),this._checkSessionIFrame=o,o.start(t)}else n.warn(`no check session iframe found in the metadata`)}catch(e){n.error(`Error from getCheckSessionIframe:`,e instanceof Error?e.message:e)}},this._stop=()=>{let e=this._logger.create(`_stop`);if(this._sub=void 0,this._checkSessionIFrame&&this._checkSessionIFrame.stop(),this._userManager.settings.monitorAnonymousSession){let t=setInterval(async()=>{clearInterval(t);try{let e=await this._userManager.querySessionStatus();if(e){let t={session_state:e.session_state,profile:e.sub?{sub:e.sub}:null};this._start(t)}}catch(t){e.error(`error from querySessionStatus`,t instanceof Error?t.message:t)}},1e3)}},this._callback=async()=>{let e=this._logger.create(`_callback`);try{let t=await this._userManager.querySessionStatus(),n=!0;t&&this._checkSessionIFrame?t.sub===this._sub?(n=!1,this._checkSessionIFrame.start(t.session_state),e.debug(`same sub still logged in at OP, session state has changed, restarting check session iframe; session_state`,t.session_state),await this._userManager.events._raiseUserSessionChanged()):e.debug(`different subject signed into OP`,t.sub):e.debug(`subject no longer signed into OP`),n?this._sub?await this._userManager.events._raiseUserSignedOut():await this._userManager.events._raiseUserSignedIn():e.debug(`no change in session detected, no event to raise`)}catch(t){this._sub&&(e.debug(`Error calling queryCurrentSigninSession; raising signed out event`,t),await this._userManager.events._raiseUserSignedOut())}},e||this._logger.throw(Error(`No user manager passed`)),this._userManager.events.addUserLoaded(this._start),this._userManager.events.addUserUnloaded(this._stop),this._init().catch(e=>{this._logger.error(e)})}async _init(){this._logger.create(`_init`);let e=await this._userManager.getUser();if(e)this._start(e);else if(this._userManager.settings.monitorAnonymousSession){let e=await this._userManager.querySessionStatus();if(e){let t={session_state:e.session_state,profile:e.sub?{sub:e.sub}:null};this._start(t)}}}},nS=class e{constructor(e){this.id_token=e.id_token,this.session_state=e.session_state??null,this.access_token=e.access_token,this.refresh_token=e.refresh_token,this.token_type=e.token_type,this.scope=e.scope,this.profile=e.profile,this.expires_at=e.expires_at,this.state=e.userState,this.url_state=e.url_state}get expires_in(){if(this.expires_at!==void 0)return this.expires_at-Sx.getEpochTime()}set expires_in(e){e!==void 0&&(this.expires_at=Math.floor(e)+Sx.getEpochTime())}get expired(){let e=this.expires_in;if(e!==void 0)return e<=0}get scopes(){return this.scope?.split(` `)??[]}toStorageString(){return new mx(`User`).create(`toStorageString`),JSON.stringify({id_token:this.id_token,session_state:this.session_state,access_token:this.access_token,refresh_token:this.refresh_token,token_type:this.token_type,scope:this.scope,profile:this.profile,expires_at:this.expires_at})}static fromStorageString(t){return mx.createStatic(`User`,`fromStorageString`),new e(JSON.parse(t))}},rS=`oidc-client`,iS=class{constructor(){this._abort=new bx(`Window navigation aborted`),this._disposeHandlers=new Set,this._window=null}async navigate(e){let t=this._logger.create(`navigate`);if(!this._window)throw Error(`Attempted to navigate on a disposed window`);t.debug(`setting URL in window`),this._window.location.replace(e.url);let{url:n,keepOpen:r}=await new Promise((n,r)=>{let i=i=>{let a=i.data,o=e.scriptOrigin??window.location.origin;if(!(i.origin!==o||a?.source!==rS)){try{let n=Cx.readParams(a.url,e.response_mode).get(`state`);if(n||t.warn(`no state found in response url`),i.source!==this._window&&n!==e.state)return}catch{this._dispose(),r(Error(`Invalid response from window`))}n(a)}};window.addEventListener(`message`,i,!1),this._disposeHandlers.add(()=>window.removeEventListener(`message`,i,!1));let a=new BroadcastChannel(`oidc-client-popup-${e.state}`);a.addEventListener(`message`,i,!1),this._disposeHandlers.add(()=>a.close()),this._disposeHandlers.add(this._abort.addHandler(e=>{this._dispose(),r(e)}))});return t.debug(`got response from window`),this._dispose(),r||this.close(),{url:n}}_dispose(){this._logger.create(`_dispose`);for(let e of this._disposeHandlers)e();this._disposeHandlers.clear()}static _notifyParent(e,t,n=!1,r=window.location.origin){let i={source:rS,url:t,keepOpen:n},a=new mx(`_notifyParent`);if(e)a.debug(`With parent. Using parent.postMessage.`),e.postMessage(i,r);else{a.debug(`No parent. Using BroadcastChannel.`);let e=new URL(t).searchParams.get(`state`);if(!e)throw Error(`No parent and no state in URL. Can't complete notification.`);let n=new BroadcastChannel(`oidc-client-popup-${e}`);n.postMessage(i),n.close()}}},aS={location:!1,toolbar:!1,height:640,closePopupWindowAfterInSeconds:-1},oS=`_blank`,sS=60,cS=2,lS=10,uS=class extends Rx{constructor(e){let{popup_redirect_uri:t=e.redirect_uri,popup_post_logout_redirect_uri:n=e.post_logout_redirect_uri,popupWindowFeatures:r=aS,popupWindowTarget:i=oS,redirectMethod:a=`assign`,redirectTarget:o=`self`,iframeNotifyParentOrigin:s=e.iframeNotifyParentOrigin,iframeScriptOrigin:c=e.iframeScriptOrigin,requestTimeoutInSeconds:l,silent_redirect_uri:u=e.redirect_uri,silentRequestTimeoutInSeconds:d,automaticSilentRenew:f=!0,validateSubOnSilentRenew:p=!0,includeIdTokenInSilentRenew:m=!1,monitorSession:h=!1,monitorAnonymousSession:g=!1,checkSessionIntervalInSeconds:_=cS,query_status_response_type:v=`code`,stopCheckSessionOnError:y=!0,revokeTokenTypes:b=[`access_token`,`refresh_token`],revokeTokensOnSignout:x=!1,includeIdTokenInSilentSignout:S=!1,accessTokenExpiringNotificationTimeInSeconds:C=sS,userStore:w}=e;super(e),this.popup_redirect_uri=t,this.popup_post_logout_redirect_uri=n,this.popupWindowFeatures=r,this.popupWindowTarget=i,this.redirectMethod=a,this.redirectTarget=o,this.iframeNotifyParentOrigin=s,this.iframeScriptOrigin=c,this.silent_redirect_uri=u,this.silentRequestTimeoutInSeconds=d||l||lS,this.automaticSilentRenew=f,this.validateSubOnSilentRenew=p,this.includeIdTokenInSilentRenew=m,this.monitorSession=h,this.monitorAnonymousSession=g,this.checkSessionIntervalInSeconds=_,this.stopCheckSessionOnError=y,this.query_status_response_type=v,this.revokeTokenTypes=b,this.revokeTokensOnSignout=x,this.includeIdTokenInSilentSignout=S,this.accessTokenExpiringNotificationTimeInSeconds=C,w?this.userStore=w:this.userStore=new Nx({store:typeof window<`u`?window.sessionStorage:new kx})}},dS=class e extends iS{constructor({silentRequestTimeoutInSeconds:t=lS}){super(),this._logger=new mx(`IFrameWindow`),this._timeoutInSeconds=t,this._frame=e.createHiddenIframe(),this._window=this._frame.contentWindow}static createHiddenIframe(){let e=window.document.createElement(`iframe`);return e.style.visibility=`hidden`,e.style.position=`fixed`,e.style.left=`-1000px`,e.style.top=`0`,e.width=`0`,e.height=`0`,window.document.body.appendChild(e),e}async navigate(e){this._logger.debug(`navigate: Using timeout of:`,this._timeoutInSeconds);let t=setTimeout(()=>void this._abort.raise(new Ex(`IFrame timed out without a response`)),this._timeoutInSeconds*1e3);return this._disposeHandlers.add(()=>clearTimeout(t)),await super.navigate(e)}close(){var e;this._frame&&=(this._frame.parentNode&&(this._frame.addEventListener(`load`,e=>{var t;let n=e.target;(t=n.parentNode)==null||t.removeChild(n),this._abort.raise(Error(`IFrame removed from DOM`))},!0),(e=this._frame.contentWindow)==null||e.location.replace(`about:blank`)),null),this._window=null}static notifyParent(e,t){return super._notifyParent(window.parent,e,!1,t)}},fS=class{constructor(e){this._settings=e,this._logger=new mx(`IFrameNavigator`)}async prepare({silentRequestTimeoutInSeconds:e=this._settings.silentRequestTimeoutInSeconds}){return new dS({silentRequestTimeoutInSeconds:e})}async callback(e){this._logger.create(`callback`),dS.notifyParent(e,this._settings.iframeNotifyParentOrigin)}},pS=500,mS=1e3,hS=class extends iS{constructor({popupWindowTarget:e=oS,popupWindowFeatures:t={},popupSignal:n,popupAbortOnClose:r}){super(),this._logger=new mx(`PopupWindow`);let i=xx.center({...aS,...t});this._window=window.open(void 0,e,xx.serialize(i)),this.abortOnClose=!!r,n&&n.addEventListener(`abort`,()=>{this._abort.raise(Error(n.reason??`Popup aborted`))}),t.closePopupWindowAfterInSeconds&&t.closePopupWindowAfterInSeconds>0&&setTimeout(()=>{if(!this._window||typeof this._window.closed!=`boolean`||this._window.closed){this._abort.raise(Error(`Popup blocked by user`));return}this.close()},t.closePopupWindowAfterInSeconds*mS)}async navigate(e){var t;(t=this._window)==null||t.focus();let n=setInterval(()=>{(!this._window||this._window.closed)&&(this._logger.debug(`Popup closed by user or isolated by redirect`),r(),this._disposeHandlers.delete(r),this.abortOnClose&&this._abort.raise(Error(`Popup closed by user`)))},pS),r=()=>clearInterval(n);return this._disposeHandlers.add(r),await super.navigate(e)}close(){this._window&&(this._window.closed||(this._window.close(),this._abort.raise(Error(`Popup closed`)))),this._window=null}static notifyOpener(e,t){super._notifyParent(window.opener,e,t),!t&&!window.opener&&window.close()}},gS=class{constructor(e){this._settings=e,this._logger=new mx(`PopupNavigator`)}async prepare({popupWindowFeatures:e=this._settings.popupWindowFeatures,popupWindowTarget:t=this._settings.popupWindowTarget,popupSignal:n,popupAbortOnClose:r}){return new hS({popupWindowFeatures:e,popupWindowTarget:t,popupSignal:n,popupAbortOnClose:r})}async callback(e,{keepOpen:t=!1}){this._logger.create(`callback`),hS.notifyOpener(e,t)}},_S=class{constructor(e){this._settings=e,this._logger=new mx(`RedirectNavigator`)}async prepare({redirectMethod:e=this._settings.redirectMethod,redirectTarget:t=this._settings.redirectTarget}){this._logger.create(`prepare`);let n=window.self;t===`top`&&(n=window.top??window.self);let r=n.location[e].bind(n.location),i;return{navigate:async e=>(this._logger.create(`navigate`),await new Promise((t,n)=>{i=n,window.addEventListener(`pageshow`,()=>t(window.location.href)),r(e.url)})),close:()=>{this._logger.create(`close`),i?.(Error(`Redirect aborted`)),n.stop()}}}async callback(){}},vS=class extends Dx{constructor(e){super({expiringNotificationTimeInSeconds:e.accessTokenExpiringNotificationTimeInSeconds}),this._logger=new mx(`UserManagerEvents`),this._userLoaded=new bx(`User loaded`),this._userUnloaded=new bx(`User unloaded`),this._silentRenewError=new bx(`Silent renew error`),this._userSignedIn=new bx(`User signed in`),this._userSignedOut=new bx(`User signed out`),this._userSessionChanged=new bx(`User session changed`)}async load(e,t=!0){await super.load(e),t&&await this._userLoaded.raise(e)}async unload(){await super.unload(),await this._userUnloaded.raise()}addUserLoaded(e){return this._userLoaded.addHandler(e)}removeUserLoaded(e){return this._userLoaded.removeHandler(e)}addUserUnloaded(e){return this._userUnloaded.addHandler(e)}removeUserUnloaded(e){return this._userUnloaded.removeHandler(e)}addSilentRenewError(e){return this._silentRenewError.addHandler(e)}removeSilentRenewError(e){return this._silentRenewError.removeHandler(e)}async _raiseSilentRenewError(e){await this._silentRenewError.raise(e)}addUserSignedIn(e){return this._userSignedIn.addHandler(e)}removeUserSignedIn(e){this._userSignedIn.removeHandler(e)}async _raiseUserSignedIn(){await this._userSignedIn.raise()}addUserSignedOut(e){return this._userSignedOut.addHandler(e)}removeUserSignedOut(e){this._userSignedOut.removeHandler(e)}async _raiseUserSignedOut(){await this._userSignedOut.raise()}addUserSessionChanged(e){return this._userSessionChanged.addHandler(e)}removeUserSessionChanged(e){this._userSessionChanged.removeHandler(e)}async _raiseUserSessionChanged(){await this._userSessionChanged.raise()}},yS=class{constructor(e){this._userManager=e,this._logger=new mx(`SilentRenewService`),this._isStarted=!1,this._retryTimer=new Sx(`Retry Silent Renew`),this._tokenExpiring=async()=>{let e=this._logger.create(`_tokenExpiring`);try{await this._userManager.signinSilent(),e.debug(`silent token renewal successful`)}catch(t){if(t instanceof Ex){e.warn(`ErrorTimeout from signinSilent:`,t,`retry in 5s`),this._retryTimer.init(5);return}e.error(`Error from signinSilent:`,t),await this._userManager.events._raiseSilentRenewError(t)}}}async start(){let e=this._logger.create(`start`);if(!this._isStarted){this._isStarted=!0,this._userManager.events.addAccessTokenExpiring(this._tokenExpiring),this._retryTimer.addHandler(this._tokenExpiring);try{await this._userManager.getUser()}catch(t){e.error(`getUser error`,t)}}}stop(){this._isStarted&&=(this._retryTimer.cancel(),this._retryTimer.removeHandler(this._tokenExpiring),this._userManager.events.removeAccessTokenExpiring(this._tokenExpiring),!1)}},bS=class{constructor(e){this.refresh_token=e.refresh_token,this.id_token=e.id_token,this.session_state=e.session_state,this.scope=e.scope,this.profile=e.profile,this.data=e.state}},xS=class{constructor(e,t,n,r){this._logger=new mx(`UserManager`),this.settings=new uS(e),this._client=new eS(e),this._redirectNavigator=t??new _S(this.settings),this._popupNavigator=n??new gS(this.settings),this._iframeNavigator=r??new fS(this.settings),this._events=new vS(this.settings),this._silentRenewService=new yS(this),this.settings.automaticSilentRenew&&this.startSilentRenew(),this._sessionMonitor=null,this.settings.monitorSession&&(this._sessionMonitor=new tS(this))}get events(){return this._events}get metadataService(){return this._client.metadataService}async getUser(e=!1){let t=this._logger.create(`getUser`),n=await this._loadUser();return n?(t.info(`user loaded`),await this._events.load(n,e),n):(t.info(`user not found in storage`),null)}async removeUser(){let e=this._logger.create(`removeUser`);await this.storeUser(null),e.info(`user removed from storage`),await this._events.unload()}async signinRedirect(e={}){this._logger.create(`signinRedirect`);let{redirectMethod:t,...n}=e,r;this.settings.dpop?.bind_authorization_code&&(r=await this.generateDPoPJkt(this.settings.dpop));let i=await this._redirectNavigator.prepare({redirectMethod:t});await this._signinStart({request_type:`si:r`,dpopJkt:r,...n},i)}async signinRedirectCallback(e=window.location.href){let t=this._logger.create(`signinRedirectCallback`),n=await this._signinEnd(e);return n.profile&&n.profile.sub?t.info(`success, signed in subject`,n.profile.sub):t.info(`no subject`),n}async signinResourceOwnerCredentials({username:e,password:t,skipUserInfo:n=!1}){let r=this._logger.create(`signinResourceOwnerCredential`),i=await this._client.processResourceOwnerPasswordCredentials({username:e,password:t,skipUserInfo:n,extraTokenParams:this.settings.extraTokenParams});r.debug(`got signin response`);let a=await this._buildUser(i);return a.profile&&a.profile.sub?r.info(`success, signed in subject`,a.profile.sub):r.info(`no subject`),a}async signinPopup(e={}){let t=this._logger.create(`signinPopup`),n;this.settings.dpop?.bind_authorization_code&&(n=await this.generateDPoPJkt(this.settings.dpop));let{popupWindowFeatures:r,popupWindowTarget:i,popupSignal:a,popupAbortOnClose:o,...s}=e,c=this.settings.popup_redirect_uri;c||t.throw(Error(`No popup_redirect_uri configured`));let l=await this._popupNavigator.prepare({popupWindowFeatures:r,popupWindowTarget:i,popupSignal:a,popupAbortOnClose:o}),u=await this._signin({request_type:`si:p`,redirect_uri:c,display:`popup`,dpopJkt:n,...s},l);return u&&(u.profile&&u.profile.sub?t.info(`success, signed in subject`,u.profile.sub):t.info(`no subject`)),u}async signinPopupCallback(e=window.location.href,t=!1){let n=this._logger.create(`signinPopupCallback`);await this._popupNavigator.callback(e,{keepOpen:t}),n.info(`success`)}async signinSilent(e={}){let t=this._logger.create(`signinSilent`),{silentRequestTimeoutInSeconds:n,...r}=e,i=await this._loadUser();if(!e.forceIframeAuth&&i?.refresh_token){t.debug(`using refresh token`);let e=new bS(i);return await this._useRefreshToken({state:e,redirect_uri:r.redirect_uri,resource:r.resource,extraTokenParams:r.extraTokenParams,timeoutInSeconds:n})}let a;this.settings.dpop?.bind_authorization_code&&(a=await this.generateDPoPJkt(this.settings.dpop));let o=this.settings.silent_redirect_uri;o||t.throw(Error(`No silent_redirect_uri configured`));let s;i&&this.settings.validateSubOnSilentRenew&&(t.debug(`subject prior to silent renew:`,i.profile.sub),s=i.profile.sub);let c=await this._iframeNavigator.prepare({silentRequestTimeoutInSeconds:n});return i=await this._signin({request_type:`si:s`,redirect_uri:o,prompt:`none`,id_token_hint:this.settings.includeIdTokenInSilentRenew?i?.id_token:void 0,dpopJkt:a,...r},c,s),i&&(i.profile?.sub?t.info(`success, signed in subject`,i.profile.sub):t.info(`no subject`)),i}async _useRefreshToken(e){let t=await this._client.useRefreshToken({timeoutInSeconds:this.settings.silentRequestTimeoutInSeconds,...e}),n=new nS({...e.state,...t});return await this.storeUser(n),await this._events.load(n),n}async signinSilentCallback(e=window.location.href){let t=this._logger.create(`signinSilentCallback`);await this._iframeNavigator.callback(e),t.info(`success`)}async signinCallback(e=window.location.href){let{state:t}=await this._client.readSigninResponseState(e);switch(t.request_type){case`si:r`:return await this.signinRedirectCallback(e);case`si:p`:await this.signinPopupCallback(e);break;case`si:s`:await this.signinSilentCallback(e);break;default:throw Error(`invalid response_type in state`)}}async signoutCallback(e=window.location.href,t=!1){let{state:n}=await this._client.readSignoutResponseState(e);if(n)switch(n.request_type){case`so:r`:return await this.signoutRedirectCallback(e);case`so:p`:await this.signoutPopupCallback(e,t);break;case`so:s`:await this.signoutSilentCallback(e);break;default:throw Error(`invalid response_type in state`)}}async querySessionStatus(e={}){let t=this._logger.create(`querySessionStatus`),{silentRequestTimeoutInSeconds:n,...r}=e,i=this.settings.silent_redirect_uri;i||t.throw(Error(`No silent_redirect_uri configured`));let a=await this._loadUser(),o=await this._iframeNavigator.prepare({silentRequestTimeoutInSeconds:n}),s=await this._signinStart({request_type:`si:s`,redirect_uri:i,prompt:`none`,id_token_hint:this.settings.includeIdTokenInSilentRenew?a?.id_token:void 0,response_type:this.settings.query_status_response_type,scope:`openid`,skipUserInfo:!0,...r},o);try{let e=await this._client.processSigninResponse(s.url,{});return t.debug(`got signin response`),e.session_state&&e.profile.sub?(t.info(`success for subject`,e.profile.sub),{session_state:e.session_state,sub:e.profile.sub}):(t.info(`success, user not authenticated`),null)}catch(e){if(this.settings.monitorAnonymousSession&&e instanceof Tx)switch(e.error){case`login_required`:case`consent_required`:case`interaction_required`:case`account_selection_required`:return t.info(`success for anonymous user`),{session_state:e.session_state}}throw e}}async _signin(e,t,n){let r=await this._signinStart(e,t);return await this._signinEnd(r.url,n)}async _signinStart(e,t){let n=this._logger.create(`_signinStart`);try{let r=await this._client.createSigninRequest(e);return n.debug(`got signin request`),await t.navigate({url:r.url,state:r.state.id,response_mode:r.state.response_mode,scriptOrigin:this.settings.iframeScriptOrigin})}catch(e){throw n.debug(`error after preparing navigator, closing navigator window`),t.close(),e}}async _signinEnd(e,t){let n=this._logger.create(`_signinEnd`),r=await this._client.processSigninResponse(e,{});return n.debug(`got signin response`),await this._buildUser(r,t)}async _buildUser(e,t){let n=this._logger.create(`_buildUser`),r=new nS(e);if(t){if(t!==r.profile.sub)throw n.debug(`current user does not match user returned from signin. sub from signin:`,r.profile.sub),new Tx({...e,error:`login_required`});n.debug(`current user matches user returned from signin`)}return await this.storeUser(r),n.debug(`user stored`),await this._events.load(r),r}async signoutRedirect(e={}){let t=this._logger.create(`signoutRedirect`),{redirectMethod:n,...r}=e,i=await this._redirectNavigator.prepare({redirectMethod:n});await this._signoutStart({request_type:`so:r`,post_logout_redirect_uri:this.settings.post_logout_redirect_uri,...r},i),t.info(`success`)}async signoutRedirectCallback(e=window.location.href){let t=this._logger.create(`signoutRedirectCallback`),n=await this._signoutEnd(e);return t.info(`success`),n}async signoutPopup(e={}){let t=this._logger.create(`signoutPopup`),{popupWindowFeatures:n,popupWindowTarget:r,popupSignal:i,...a}=e,o=this.settings.popup_post_logout_redirect_uri,s=await this._popupNavigator.prepare({popupWindowFeatures:n,popupWindowTarget:r,popupSignal:i});await this._signout({request_type:`so:p`,post_logout_redirect_uri:o,state:o==null?void 0:{},...a},s),t.info(`success`)}async signoutPopupCallback(e=window.location.href,t=!1){let n=this._logger.create(`signoutPopupCallback`);await this._popupNavigator.callback(e,{keepOpen:t}),n.info(`success`)}async _signout(e,t){let n=await this._signoutStart(e,t);return await this._signoutEnd(n.url)}async _signoutStart(e={},t){let n=this._logger.create(`_signoutStart`);try{let r=await this._loadUser();n.debug(`loaded current user from storage`),this.settings.revokeTokensOnSignout&&await this._revokeInternal(r);let i=e.id_token_hint||r&&r.id_token;i&&(n.debug(`setting id_token_hint in signout request`),e.id_token_hint=i),await this.removeUser(),n.debug(`user removed, creating signout request`);let a=await this._client.createSignoutRequest(e);return n.debug(`got signout request`),await t.navigate({url:a.url,state:a.state?.id,scriptOrigin:this.settings.iframeScriptOrigin})}catch(e){throw n.debug(`error after preparing navigator, closing navigator window`),t.close(),e}}async _signoutEnd(e){let t=this._logger.create(`_signoutEnd`),n=await this._client.processSignoutResponse(e);return t.debug(`got signout response`),n}async signoutSilent(e={}){let t=this._logger.create(`signoutSilent`),{silentRequestTimeoutInSeconds:n,...r}=e,i=this.settings.includeIdTokenInSilentSignout?(await this._loadUser())?.id_token:void 0,a=this.settings.popup_post_logout_redirect_uri,o=await this._iframeNavigator.prepare({silentRequestTimeoutInSeconds:n});await this._signout({request_type:`so:s`,post_logout_redirect_uri:a,id_token_hint:i,...r},o),t.info(`success`)}async signoutSilentCallback(e=window.location.href){let t=this._logger.create(`signoutSilentCallback`);await this._iframeNavigator.callback(e),t.info(`success`)}async revokeTokens(e){let t=await this._loadUser();await this._revokeInternal(t,e)}async _revokeInternal(e,t=this.settings.revokeTokenTypes){let n=this._logger.create(`_revokeInternal`);if(!e)return;let r=t.filter(t=>typeof e[t]==`string`);if(!r.length){n.debug(`no need to revoke due to no token(s)`);return}for(let t of r)await this._client.revokeToken(e[t],t),n.info(`${t} revoked successfully`),t!==`access_token`&&(e[t]=null);await this.storeUser(e),n.debug(`user stored`),await this._events.load(e)}startSilentRenew(){this._logger.create(`startSilentRenew`),this._silentRenewService.start()}stopSilentRenew(){this._silentRenewService.stop()}get _userStoreKey(){return`user:${this.settings.authority}:${this.settings.client_id}`}async _loadUser(){let e=this._logger.create(`_loadUser`),t=await this.settings.userStore.get(this._userStoreKey);return t?(e.debug(`user storageString loaded`),nS.fromStorageString(t)):(e.debug(`no user storageString`),null)}async storeUser(e){let t=this._logger.create(`storeUser`);if(e){t.debug(`storing user`);let n=e.toStorageString();await this.settings.userStore.set(this._userStoreKey,n)}else this._logger.debug(`removing user`),await this.settings.userStore.remove(this._userStoreKey),this.settings.dpop&&await this.settings.dpop.store.remove(this.settings.client_id)}async clearStaleState(){await this._client.clearStaleState()}async dpopProof(e,t,n,r){let i=await(this.settings.dpop?.store)?.get(this.settings.client_id);if(i)return await yx.generateDPoPProof({url:e,accessToken:t?.access_token,httpMethod:n,keyPair:i.keys,nonce:r})}async generateDPoPJkt(e){let t=await e.store.get(this.settings.client_id);return t||(t=new $x(await yx.generateDPoPKeys()),await e.store.set(this.settings.client_id,t)),await yx.generateDPoPJkt(t.keys)}},SS=m.createContext(void 0);SS.displayName=`AuthContext`;var CS={isLoading:!0,isAuthenticated:!1},wS=(e,t)=>{switch(t.type){case`INITIALISED`:case`USER_LOADED`:return{...e,user:t.user,isLoading:!1,isAuthenticated:t.user?!t.user.expired:!1,error:void 0};case`USER_SIGNED_OUT`:case`USER_UNLOADED`:return{...e,user:void 0,isAuthenticated:!1};case`NAVIGATOR_INIT`:return{...e,isLoading:!0,activeNavigator:t.method};case`NAVIGATOR_CLOSE`:return{...e,isLoading:!1,activeNavigator:void 0};case`ERROR`:{let n=t.error;return n.toString=()=>`${n.name}: ${n.message}`,{...e,isLoading:!1,error:n}}default:{let n=TypeError(`unknown type ${t.type}`),r={name:n.name,message:n.message,innerError:n,stack:n.stack,source:`unknown`};return r.toString=()=>`${r.name}: ${r.message}`,{...e,isLoading:!1,error:r}}}},TS=(e=window.location)=>{let t=new URLSearchParams(e.search);return!!((t.get(`code`)||t.get(`error`))&&t.get(`state`)||(t=new URLSearchParams(e.hash.replace(`#`,`?`)),(t.get(`code`)||t.get(`error`))&&t.get(`state`)))},ES=AS(`signinCallback`,`Sign-in failed`),DS=AS(`signoutCallback`,`Sign-out failed`),OS=AS(`renewSilent`,`Renew silent failed`);function kS(e,t){return{name:jS(e,`name`,()=>`Error`),message:jS(e,`message`,()=>t),stack:jS(e,`stack`,()=>Error().stack),innerError:e}}function AS(e,t){return n=>({...kS(n,t),source:e})}function jS(e,t,n){if(e&&typeof e==`object`){let n=e[t];if(typeof n==`string`)return n}return n()}var MS=[`clearStaleState`,`querySessionStatus`,`revokeTokens`,`startSilentRenew`,`stopSilentRenew`],NS=[`signinPopup`,`signinSilent`,`signinRedirect`,`signinResourceOwnerCredentials`,`signoutPopup`,`signoutRedirect`,`signoutSilent`],PS=e=>()=>{throw Error(`UserManager#${e} was called from an unsupported context. If this is a server-rendered page, defer this call with useEffect() or pass a custom UserManager implementation.`)},FS=typeof window>`u`?null:xS,IS=e=>{let{children:t,onSigninCallback:n,skipSigninCallback:r,matchSignoutCallback:i,onSignoutCallback:a,onRemoveUser:o,userManager:s=null,...c}=e,[l]=m.useState(()=>s??(FS?new FS(c):{settings:c})),[u,d]=m.useReducer(wS,CS),f=m.useMemo(()=>Object.assign({settings:l.settings,events:l.events},Object.fromEntries(MS.map(e=>[e,l[e]?.bind(l)??PS(e)])),Object.fromEntries(NS.map(e=>[e,l[e]?async t=>{d({type:`NAVIGATOR_INIT`,method:e});try{return await l[e](t)}catch(n){return d({type:`ERROR`,error:{...kS(n,`Unknown error while executing ${e}(...).`),source:e,args:t}}),null}finally{d({type:`NAVIGATOR_CLOSE`})}}:PS(e)]))),[l]),p=m.useRef(!1);m.useEffect(()=>{!l||p.current||(p.current=!0,(async()=>{try{let e=null;TS()&&!r&&(e=await l.signinCallback(),n&&await n(e)),e||=await l.getUser(),d({type:`INITIALISED`,user:e})}catch(e){d({type:`ERROR`,error:ES(e)})}try{if(i&&i(l.settings)){let e=await l.signoutCallback();a&&await a(e)}}catch(e){d({type:`ERROR`,error:DS(e)})}})())},[l,r,n,a,i]),m.useEffect(()=>{if(!l)return;let e=e=>{d({type:`USER_LOADED`,user:e})};l.events.addUserLoaded(e);let t=()=>{d({type:`USER_UNLOADED`})};l.events.addUserUnloaded(t);let n=()=>{d({type:`USER_SIGNED_OUT`})};l.events.addUserSignedOut(n);let r=e=>{d({type:`ERROR`,error:OS(e)})};return l.events.addSilentRenewError(r),()=>{l.events.removeUserLoaded(e),l.events.removeUserUnloaded(t),l.events.removeUserSignedOut(n),l.events.removeSilentRenewError(r)}},[l]);let h=m.useCallback(async()=>{await l.removeUser(),o&&await o()},[l,o]),g=m.useMemo(()=>({...u,...f,removeUser:h}),[u,f,h]);return m.createElement(SS.Provider,{value:g},t)},LS=()=>{let e=m.useContext(SS);return e||console.warn(`AuthProvider context is undefined, please verify you are calling useAuth() as child of a component.`),e},RS=`modulepreload`,zS=function(e){return`/`+e},BS={},VS=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}r=o(t.map(t=>{if(t=zS(t,n),t in BS)return;BS[t]=!0;let r=t.endsWith(`.css`),i=r?`[rel="stylesheet"]`:``;if(n)for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}else if(document.querySelector(`link[href="${t}"]${i}`))return;let o=document.createElement(`link`);if(o.rel=r?`stylesheet`:RS,r||(o.as=`script`),o.crossOrigin=``,o.href=t,a&&o.setAttribute(`nonce`,a),document.head.appendChild(o),r)return new Promise((e,n)=>{o.addEventListener(`load`,e),o.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},HS=`popstate`;function US(e={}){function t(e,t){let{pathname:n,search:r,hash:i}=e.location;return JS(``,{pathname:n,search:r,hash:i},t.state&&t.state.usr||null,t.state&&t.state.key||`default`)}function n(e,t){return typeof t==`string`?t:YS(t)}return ZS(t,n,null,e)}function WS(e,t){if(e===!1||e==null)throw Error(t)}function GS(e,t){if(!e){typeof console<`u`&&console.warn(t);try{throw Error(t)}catch{}}}function KS(){return Math.random().toString(36).substring(2,10)}function qS(e,t){return{usr:e.state,key:e.key,idx:t}}function JS(e,t,n=null,r){return{pathname:typeof e==`string`?e:e.pathname,search:``,hash:``,...typeof t==`string`?XS(t):t,state:n,key:t&&t.key||r||KS()}}function YS({pathname:e=`/`,search:t=``,hash:n=``}){return t&&t!==`?`&&(e+=t.charAt(0)===`?`?t:`?`+t),n&&n!==`#`&&(e+=n.charAt(0)===`#`?n:`#`+n),e}function XS(e){let t={};if(e){let n=e.indexOf(`#`);n>=0&&(t.hash=e.substring(n),e=e.substring(0,n));let r=e.indexOf(`?`);r>=0&&(t.search=e.substring(r),e=e.substring(0,r)),e&&(t.pathname=e)}return t}function ZS(e,t,n,r={}){let{window:i=document.defaultView,v5Compat:a=!1}=r,o=i.history,s=`POP`,c=null,l=u();l??(l=0,o.replaceState({...o.state,idx:l},``));function u(){return(o.state||{idx:null}).idx}function d(){s=`POP`;let e=u(),t=e==null?null:e-l;l=e,c&&c({action:s,location:h.location,delta:t})}function f(e,t){s=`PUSH`;let r=JS(h.location,e,t);n&&n(r,e),l=u()+1;let d=qS(r,l),f=h.createHref(r);try{o.pushState(d,``,f)}catch(e){if(e instanceof DOMException&&e.name===`DataCloneError`)throw e;i.location.assign(f)}a&&c&&c({action:s,location:h.location,delta:1})}function p(e,t){s=`REPLACE`;let r=JS(h.location,e,t);n&&n(r,e),l=u();let i=qS(r,l),d=h.createHref(r);o.replaceState(i,``,d),a&&c&&c({action:s,location:h.location,delta:0})}function m(e){return QS(e)}let h={get action(){return s},get location(){return e(i,o)},listen(e){if(c)throw Error(`A history only accepts one active listener`);return i.addEventListener(HS,d),c=e,()=>{i.removeEventListener(HS,d),c=null}},createHref(e){return t(i,e)},createURL:m,encodeLocation(e){let t=m(e);return{pathname:t.pathname,search:t.search,hash:t.hash}},push:f,replace:p,go(e){return o.go(e)}};return h}function QS(e,t=!1){let n=`http://localhost`;typeof window<`u`&&(n=window.location.origin===`null`?window.location.href:window.location.origin),WS(n,`No window.location.(origin|href) available to create URL`);let r=typeof e==`string`?e:YS(e);return r=r.replace(/ $/,`%20`),!t&&r.startsWith(`//`)&&(r=n+r),new URL(r,n)}function $S(e,t,n=`/`){return eC(e,t,n,!1)}function eC(e,t,n,r){let i=vC((typeof t==`string`?XS(t):t).pathname||`/`,n);if(i==null)return null;let a=nC(e);iC(a);let o=null;for(let e=0;o==null&&e{let c={relativePath:s===void 0?e.path||``:s,caseSensitive:e.caseSensitive===!0,childrenIndex:a,route:e};if(c.relativePath.startsWith(`/`)){if(!c.relativePath.startsWith(r)&&o)return;WS(c.relativePath.startsWith(r),`Absolute route path "${c.relativePath}" nested under path "${r}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),c.relativePath=c.relativePath.slice(r.length)}let l=DC([r,c.relativePath]),u=n.concat(c);e.children&&e.children.length>0&&(WS(e.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${l}".`),nC(e.children,t,u,l,o)),!(e.path==null&&!e.index)&&t.push({path:l,score:fC(l,e.index),routesMeta:u})};return e.forEach((e,t)=>{if(e.path===``||!e.path?.includes(`?`))a(e,t);else for(let n of rC(e.path))a(e,t,!0,n)}),t}function rC(e){let t=e.split(`/`);if(t.length===0)return[];let[n,...r]=t,i=n.endsWith(`?`),a=n.replace(/\?$/,``);if(r.length===0)return i?[a,``]:[a];let o=rC(r.join(`/`)),s=[];return s.push(...o.map(e=>e===``?a:[a,e].join(`/`))),i&&s.push(...o),s.map(t=>e.startsWith(`/`)&&t===``?`/`:t)}function iC(e){e.sort((e,t)=>e.score===t.score?pC(e.routesMeta.map(e=>e.childrenIndex),t.routesMeta.map(e=>e.childrenIndex)):t.score-e.score)}var aC=/^:[\w-]+$/,oC=3,sC=2,cC=1,lC=10,uC=-2,dC=e=>e===`*`;function fC(e,t){let n=e.split(`/`),r=n.length;return n.some(dC)&&(r+=uC),t&&(r+=sC),n.filter(e=>!dC(e)).reduce((e,t)=>e+(aC.test(t)?oC:t===``?cC:lC),r)}function pC(e,t){return e.length===t.length&&e.slice(0,-1).every((e,n)=>e===t[n])?e[e.length-1]-t[t.length-1]:0}function mC(e,t,n=!1){let{routesMeta:r}=e,i={},a=`/`,o=[];for(let e=0;e{if(t===`*`){let e=s[r]||``;o=a.slice(0,a.length-e.length).replace(/(.)\/+$/,`$1`)}let i=s[r];return n&&!i?e[t]=void 0:e[t]=(i||``).replace(/%2F/g,`/`),e},{}),pathname:a,pathnameBase:o,pattern:e}}function gC(e,t=!1,n=!0){GS(e===`*`||!e.endsWith(`*`)||e.endsWith(`/*`),`Route path "${e}" will be treated as if it were "${e.replace(/\*$/,`/*`)}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${e.replace(/\*$/,`/*`)}".`);let r=[],i=`^`+e.replace(/\/*\*?$/,``).replace(/^\/*/,`/`).replace(/[\\.*+^${}|()[\]]/g,`\\$&`).replace(/\/:([\w-]+)(\?)?/g,(e,t,n)=>(r.push({paramName:t,isOptional:n!=null}),n?`/?([^\\/]+)?`:`/([^\\/]+)`)).replace(/\/([\w-]+)\?(\/|$)/g,`(/$1)?$2`);return e.endsWith(`*`)?(r.push({paramName:`*`}),i+=e===`*`||e===`/*`?`(.*)$`:`(?:\\/(.+)|\\/*)$`):n?i+=`\\/*$`:e!==``&&e!==`/`&&(i+=`(?:(?=\\/|$))`),[new RegExp(i,t?void 0:`i`),r]}function _C(e){try{return e.split(`/`).map(e=>decodeURIComponent(e).replace(/\//g,`%2F`)).join(`/`)}catch(t){return GS(!1,`The URL path "${e}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${t}).`),e}}function vC(e,t){if(t===`/`)return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let n=t.endsWith(`/`)?t.length-1:t.length,r=e.charAt(n);return r&&r!==`/`?null:e.slice(n)||`/`}var yC=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,bC=e=>yC.test(e);function xC(e,t=`/`){let{pathname:n,search:r=``,hash:i=``}=typeof e==`string`?XS(e):e,a;if(n)if(bC(n))a=n;else{if(n.includes(`//`)){let e=n;n=n.replace(/\/\/+/g,`/`),GS(!1,`Pathnames cannot have embedded double slashes - normalizing ${e} -> ${n}`)}a=n.startsWith(`/`)?SC(n.substring(1),`/`):SC(n,t)}else a=t;return{pathname:a,search:kC(r),hash:AC(i)}}function SC(e,t){let n=t.replace(/\/+$/,``).split(`/`);return e.split(`/`).forEach(e=>{e===`..`?n.length>1&&n.pop():e!==`.`&&n.push(e)}),n.length>1?n.join(`/`):`/`}function CC(e,t,n,r){return`Cannot include a '${e}' character in a manually specified \`to.${t}\` field [${JSON.stringify(r)}]. Please separate it out to the \`to.${n}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function wC(e){return e.filter((e,t)=>t===0||e.route.path&&e.route.path.length>0)}function TC(e){let t=wC(e);return t.map((e,n)=>n===t.length-1?e.pathname:e.pathnameBase)}function EC(e,t,n,r=!1){let i;typeof e==`string`?i=XS(e):(i={...e},WS(!i.pathname||!i.pathname.includes(`?`),CC(`?`,`pathname`,`search`,i)),WS(!i.pathname||!i.pathname.includes(`#`),CC(`#`,`pathname`,`hash`,i)),WS(!i.search||!i.search.includes(`#`),CC(`#`,`search`,`hash`,i)));let a=e===``||i.pathname===``,o=a?`/`:i.pathname,s;if(o==null)s=n;else{let e=t.length-1;if(!r&&o.startsWith(`..`)){let t=o.split(`/`);for(;t[0]===`..`;)t.shift(),--e;i.pathname=t.join(`/`)}s=e>=0?t[e]:`/`}let c=xC(i,s),l=o&&o!==`/`&&o.endsWith(`/`),u=(a||o===`.`)&&n.endsWith(`/`);return!c.pathname.endsWith(`/`)&&(l||u)&&(c.pathname+=`/`),c}var DC=e=>e.join(`/`).replace(/\/\/+/g,`/`),OC=e=>e.replace(/\/+$/,``).replace(/^\/*/,`/`),kC=e=>!e||e===`?`?``:e.startsWith(`?`)?e:`?`+e,AC=e=>!e||e===`#`?``:e.startsWith(`#`)?e:`#`+e,jC=class{constructor(e,t,n,r=!1){this.status=e,this.statusText=t||``,this.internal=r,n instanceof Error?(this.data=n.toString(),this.error=n):this.data=n}};function MC(e){return e!=null&&typeof e.status==`number`&&typeof e.statusText==`string`&&typeof e.internal==`boolean`&&`data`in e}function NC(e){return e.map(e=>e.route.path).filter(Boolean).join(`/`).replace(/\/\/*/g,`/`)||`/`}var PC=typeof window<`u`&&window.document!==void 0&&window.document.createElement!==void 0;function FC(e,t){let n=e;if(typeof n!=`string`||!yC.test(n))return{absoluteURL:void 0,isExternal:!1,to:n};let r=n,i=!1;if(PC)try{let e=new URL(window.location.href),r=n.startsWith(`//`)?new URL(e.protocol+n):new URL(n),a=vC(r.pathname,t);r.origin===e.origin&&a!=null?n=a+r.search+r.hash:i=!0}catch{GS(!1,` contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}return{absoluteURL:r,isExternal:i,to:n}}Object.getOwnPropertyNames(Object.prototype).sort().join(`\0`);var IC=[`POST`,`PUT`,`PATCH`,`DELETE`];new Set(IC);var LC=[`GET`,...IC];new Set(LC);var RC=m.createContext(null);RC.displayName=`DataRouter`;var zC=m.createContext(null);zC.displayName=`DataRouterState`;var BC=m.createContext(!1),VC=m.createContext({isTransitioning:!1});VC.displayName=`ViewTransition`;var HC=m.createContext(new Map);HC.displayName=`Fetchers`;var UC=m.createContext(null);UC.displayName=`Await`;var WC=m.createContext(null);WC.displayName=`Navigation`;var GC=m.createContext(null);GC.displayName=`Location`;var KC=m.createContext({outlet:null,matches:[],isDataRoute:!1});KC.displayName=`Route`;var qC=m.createContext(null);qC.displayName=`RouteError`;var JC=`REACT_ROUTER_ERROR`,YC=`REDIRECT`,XC=`ROUTE_ERROR_RESPONSE`;function ZC(e){if(e.startsWith(`${JC}:${YC}:{`))try{let t=JSON.parse(e.slice(28));if(typeof t==`object`&&t&&typeof t.status==`number`&&typeof t.statusText==`string`&&typeof t.location==`string`&&typeof t.reloadDocument==`boolean`&&typeof t.replace==`boolean`)return t}catch{}}function QC(e){if(e.startsWith(`${JC}:${XC}:{`))try{let t=JSON.parse(e.slice(40));if(typeof t==`object`&&t&&typeof t.status==`number`&&typeof t.statusText==`string`)return new jC(t.status,t.statusText,t.data)}catch{}}function $C(e,{relative:t}={}){WS(ew(),`useHref() may be used only in the context of a component.`);let{basename:n,navigator:r}=m.useContext(WC),{hash:i,pathname:a,search:o}=ow(e,{relative:t}),s=a;return n!==`/`&&(s=a===`/`?n:DC([n,a])),r.createHref({pathname:s,search:o,hash:i})}function ew(){return m.useContext(GC)!=null}function tw(){return WS(ew(),`useLocation() may be used only in the context of a component.`),m.useContext(GC).location}var nw=`You should call navigate() in a React.useEffect(), not when your component is first rendered.`;function rw(e){m.useContext(WC).static||m.useLayoutEffect(e)}function iw(){let{isDataRoute:e}=m.useContext(KC);return e?Tw():aw()}function aw(){WS(ew(),`useNavigate() may be used only in the context of a component.`);let e=m.useContext(RC),{basename:t,navigator:n}=m.useContext(WC),{matches:r}=m.useContext(KC),{pathname:i}=tw(),a=JSON.stringify(TC(r)),o=m.useRef(!1);return rw(()=>{o.current=!0}),m.useCallback((r,s={})=>{if(GS(o.current,nw),!o.current)return;if(typeof r==`number`){n.go(r);return}let c=EC(r,JSON.parse(a),i,s.relative===`path`);e==null&&t!==`/`&&(c.pathname=c.pathname===`/`?t:DC([t,c.pathname])),(s.replace?n.replace:n.push)(c,s.state,s)},[t,n,a,i,e])}m.createContext(null);function ow(e,{relative:t}={}){let{matches:n}=m.useContext(KC),{pathname:r}=tw(),i=JSON.stringify(TC(n));return m.useMemo(()=>EC(e,JSON.parse(i),r,t===`path`),[e,i,r,t])}function sw(e,t){return cw(e,t)}function cw(e,t,n,r,i){WS(ew(),`useRoutes() may be used only in the context of a component.`);let{navigator:a}=m.useContext(WC),{matches:o}=m.useContext(KC),s=o[o.length-1],c=s?s.params:{},l=s?s.pathname:`/`,u=s?s.pathnameBase:`/`,d=s&&s.route;{let e=d&&d.path||``;Dw(l,!d||e.endsWith(`*`)||e.endsWith(`*?`),`You rendered descendant (or called \`useRoutes()\`) at "${l}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. + `]:{...Fo(e),marginInlineStart:e.marginXXS},...Ob(e),...kb(e),...Ab(),"&-rtl":{direction:`rtl`}}}},()=>({titleMarginTop:`1.2em`,titleMarginBottom:`0.5em`})),Mb=e=>{let{prefixCls:t,"aria-label":n,className:r,style:i,direction:a,maxLength:o,autoSize:s=!0,value:c,onSave:l,onCancel:u,onEnd:d,component:f,enterIcon:p=m.createElement(Cb,null)}=e,h=m.useRef(null),g=m.useRef(!1),_=m.useRef(null),[v,y]=m.useState(c);m.useEffect(()=>{y(c)},[c]),m.useEffect(()=>{if(h.current?.resizableTextArea){let{textArea:e}=h.current.resizableTextArea;e.focus();let{length:t}=e.value;e.setSelectionRange(t,t)}},[]);let b=({target:e})=>{y(e.value.replace(/[\n\r]/g,``))},x=()=>{g.current=!0},S=()=>{g.current=!1},C=({keyCode:e})=>{g.current||(_.current=e)},w=()=>{l(v.trim())},T=({keyCode:e,ctrlKey:t,altKey:n,metaKey:r,shiftKey:i})=>{_.current!==e||g.current||t||n||r||i||(e===J.ENTER?(w(),d?.()):e===J.ESC&&u())},E=()=>{w()},[D,O]=jb(t),k=K(t,`${t}-edit-content`,{[`${t}-rtl`]:a===`rtl`,[`${t}-${f}`]:!!f},r,D,O);return m.createElement(`div`,{className:k,style:i},m.createElement(Ry,{ref:h,maxLength:o,value:v,onChange:b,onKeyDown:C,onKeyUp:T,onCompositionStart:x,onCompositionEnd:S,onBlur:E,"aria-label":n,rows:1,autoSize:s}),p===null?null:Mu(p,{className:`${t}-edit-content-confirm`}))},Nb=(e,t)=>{let n=!1,r=r=>{r.stopPropagation(),r.preventDefault(),r.clipboardData?.clearData(),r.clipboardData?.setData(`text/plain`,e),t&&r.clipboardData?.setData(`text/html`,e),n=!0};try{return document.addEventListener(`copy`,r,{capture:!0}),document.execCommand(`copy`),n}catch{return!1}finally{document.removeEventListener(`copy`,r,{capture:!0})}},Pb=async(e,t)=>{try{return t?await navigator.clipboard.write([new ClipboardItem({"text/html":new Blob([e],{type:`text/html`}),"text/plain":new Blob([e],{type:`text/plain`})})]):await navigator.clipboard.writeText(e),!0}catch{return!1}};async function Fb(e,t){if(typeof e!=`string`)return!1;let n=t?.format===`text/html`;return!!(await Pb(e,n)||Nb(e,n))}var Ib=({copyConfig:e,children:t})=>{let[n,r]=m.useState(!1),[i,a]=m.useState(!1),o=m.useRef(null),s=()=>{o.current&&clearTimeout(o.current)},c={};return e.format&&(c.format=e.format),m.useEffect(()=>s,[]),{copied:n,copyLoading:i,onClick:W(async n=>{n?.preventDefault(),n?.stopPropagation(),a(!0);try{await Fb((typeof e.text==`function`?await e.text():e.text)||ob(t,{skipEmpty:!0}).join(``)||``,c),a(!1),r(!0),s(),o.current=setTimeout(()=>{r(!1)},3e3),e.onCopy?.(n)}catch(e){throw a(!1),e}})}};function Lb(e,t){return m.useMemo(()=>{let n=!!e;return[n,{...t,...n&&typeof e==`object`?e:null}]},[e])}var Rb=e=>{let t=(0,m.useRef)(void 0);return(0,m.useEffect)(()=>{t.current=e}),t.current},zb=(e,t,n)=>(0,m.useMemo)(()=>e===!0?{title:t??n}:(0,m.isValidElement)(e)?{title:e}:typeof e==`object`?{title:t??n,...e}:{title:e},[e,t,n]),Bb=m.forwardRef((e,t)=>{let{prefixCls:n,component:r=`article`,className:i,rootClassName:a,children:o,direction:s,style:c,...l}=e,{getPrefixCls:u,direction:d,className:f,style:p}=Ht(`typography`),h=s??d,g=u(`typography`,n),[_,v]=jb(g),y=K(g,f,{[`${g}-rtl`]:h===`rtl`},i,a,_,v),b={...p,...c};return m.createElement(r,{className:y,style:b,ref:t,...l},o)}),Vb={icon:{tag:`svg`,attrs:{viewBox:`64 64 896 896`,focusable:`false`},children:[{tag:`path`,attrs:{d:`M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z`}}]},name:`copy`,theme:`outlined`};function Hb(){return Hb=Object.assign?Object.assign.bind():function(e){for(var t=1;tm.createElement(ls,Hb({},e,{ref:t,icon:Vb}))),Wb=e=>e===!1?[!1,!1]:ob(e);function Gb(e,t,n){return e===!0||e===void 0?t:e||n&&t}function Kb(e){let t=document.createElement(`em`);e.appendChild(t);let n=e.getBoundingClientRect(),r=t.getBoundingClientRect();return e.removeChild(t),n.left>r.left||r.right>n.right||n.top>r.top||r.bottom>n.bottom}var qb=e=>[`string`,`number`].includes(typeof e),Jb=e=>{let{prefixCls:t,copied:n,locale:r,iconOnly:i,tooltips:a,icon:o,tabIndex:s,onCopy:c,loading:l}=e,u=Wb(a),d=Wb(o),{copied:f,copy:p}=r??{},h=n?f:p,g=Gb(u[n?1:0],h),_=typeof g==`string`?g:h;return m.createElement(bv,{title:g},m.createElement(`button`,{type:`button`,className:K(`${t}-copy`,{[`${t}-copy-success`]:n,[`${t}-copy-icon-only`]:i}),onClick:c,"aria-label":_,tabIndex:s},n?Gb(d[1],m.createElement(V_,null),!0):Gb(d[0],l?m.createElement(md,null):m.createElement(Ub,null),!0)))},Yb=m.forwardRef(({style:e,children:t},n)=>{let r=m.useRef(null);return m.useImperativeHandle(n,()=>({isExceed:()=>{let e=r.current;return e.scrollHeight>e.clientHeight},getHeight:()=>r.current.clientHeight})),m.createElement(`span`,{"aria-hidden":!0,ref:r,style:{position:`fixed`,display:`block`,left:0,top:0,pointerEvents:`none`,backgroundColor:`rgba(255, 0, 0, 0.65)`,...e}},t)}),Xb=e=>e.reduce((e,t)=>e+(qb(t)?String(t).length:1),0);function Zb(e,t){let n=0,r=[];for(let i=0;it){let e=t-n;return r.push(String(a).slice(0,e)),r}r.push(a),n=s}return e}var Qb=0,$b=1,ex=2,tx=3,nx=4,rx={display:`-webkit-box`,overflow:`hidden`,WebkitBoxOrient:`vertical`};function ix(e){let{enableMeasure:t,width:n,text:r,children:i,rows:a,expanded:o,miscDeps:s,onEllipsis:c}=e,l=m.useMemo(()=>nt(r),[r]),u=m.useMemo(()=>Xb(l),[r]),d=m.useMemo(()=>i(l,!1),[r]),[f,p]=m.useState(null),h=m.useRef(null),g=m.useRef(null),_=m.useRef(null),v=m.useRef(null),y=m.useRef(null),[b,x]=m.useState(!1),[S,C]=m.useState(Qb),[w,T]=m.useState(0),[E,D]=m.useState(null);G(()=>{C(t&&n&&u?$b:Qb)},[n,r,a,t,l]),G(()=>{if(S===$b)C(ex),D(g.current&&getComputedStyle(g.current).whiteSpace);else if(S===ex){let e=!!_.current?.isExceed();C(e?tx:nx),p(e?[0,u]:null),x(e);let t=_.current?.getHeight()||0,n=a===1?0:v.current?.getHeight()||0,r=y.current?.getHeight()||0;T(Math.max(t,n+r)+1),c(e)}},[S]);let O=f?Math.ceil((f[0]+f[1])/2):0;G(()=>{let[e,t]=f||[0,0];if(e!==t){let n=(h.current?.getHeight()||0)>w,r=O;t-e===1&&(r=n?e:t),p(n?[e,r]:[r,t])}},[f,O]);let k=m.useMemo(()=>{if(!t)return i(l,!1);if(S!==tx||!f||f[0]!==f[1]){let e=i(l,!1);return[nx,Qb].includes(S)?e:m.createElement(`span`,{style:{...rx,WebkitLineClamp:a}},e)}return i(o?l:Zb(l,f[0]),b)},[o,S,f,l].concat(At(s))),A={width:n,margin:0,padding:0,whiteSpace:E===`nowrap`?`normal`:`inherit`};return m.createElement(m.Fragment,null,k,S===ex&&m.createElement(m.Fragment,null,m.createElement(Yb,{style:{...A,...rx,WebkitLineClamp:a},ref:_},d),m.createElement(Yb,{style:{...A,...rx,WebkitLineClamp:a-1},ref:v},d),m.createElement(Yb,{style:{...A,...rx,WebkitLineClamp:1},ref:y},i([],!0))),S===tx&&f&&f[0]!==f[1]&&m.createElement(Yb,{style:{...A,top:400},ref:h},i(Zb(l,O),!0)),S===$b&&m.createElement(`span`,{style:{whiteSpace:`inherit`},ref:g}))}var ax=({enableEllipsis:e,isEllipsis:t,open:n,children:r,tooltipProps:i})=>{if(!i?.title||!e)return r;let a=n&&t;return m.createElement(bv,{open:a,...i},r)};function ox({mark:e,code:t,underline:n,delete:r,strong:i,keyboard:a,italic:o},s){let c=s;function l(e,t){t&&(c=m.createElement(e,{},c))}return l(`strong`,i),l(`u`,n),l(`del`,r),l(`code`,t),l(`mark`,e),l(`kbd`,a),l(`i`,o),c}var sx=`...`,cx=[`delete`,`mark`,`code`,`underline`,`strong`,`keyboard`,`italic`],lx=m.forwardRef((e,t)=>{let{prefixCls:n,className:r,style:i,type:a,disabled:o,children:s,ellipsis:c,editable:l,copyable:u,component:d,title:f,onMouseEnter:p,onMouseLeave:h,...g}=e,{getPrefixCls:_,direction:v}=m.useContext(zt),[y]=Vc(`Text`),b=m.useRef(null),x=m.useRef(null),S=_(`typography`,n),C=tt(g,cx),[w,T]=Lb(l),[E,D]=xe(!1,T.editing),{triggerType:O=[`icon`]}=T,k=e=>{e&&T.onStart?.(),D(e)},A=Rb(E);G(()=>{!E&&A&&x.current?.focus()},[E]);let j=e=>{e?.preventDefault(),k(!0)},M=e=>{T.onChange?.(e),k(!1)},N=()=>{T.onCancel?.(),k(!1)},[P,F]=Lb(u),{copied:I,copyLoading:L,onClick:ee}=Ib({copyConfig:F,children:s}),[R,z]=m.useState(!1),[B,V]=m.useState(!1),[te,ne]=m.useState(!1),[re,ie]=m.useState(!1),[ae,oe]=m.useState(!0),[H,se]=Lb(c,{expandable:!1,symbol:e=>e?y?.collapse:y?.expand}),[ce,le]=xe(se.defaultExpanded||!1,se.expanded),U=H&&(!ce||se.expandable===`collapsible`),{rows:ue=1}=se,de=m.useMemo(()=>U&&(se.suffix!==void 0||se.onEllipsis||se.expandable||w||P),[U,se,w,P]);G(()=>{H&&!de&&(z(Rh(`webkitLineClamp`)),V(Rh(`textOverflow`)))},[de,H]);let[fe,pe]=m.useState(U),me=m.useMemo(()=>de?!1:ue===1?B:R,[de,B,R]);G(()=>{pe(me&&U)},[me,U]);let he=U&&(fe?re:te),ge=U&&ue===1&&fe,_e=U&&ue>1&&fe,W=(e,t)=>{le(t.expanded),se.onExpand?.(e,t)},[ve,ye]=m.useState(0),[be,Se]=m.useState(!1),[Ce,we]=m.useState(!1),Te=({offsetWidth:e})=>{ye(e)},Ee=e=>{ne(e),te!==e&&se.onEllipsis?.(e)};m.useEffect(()=>{let e=b.current;if(H&&fe&&e){let t=Kb(e);re!==t&&ie(t)}},[H,fe,s,_e,ae,ve]),m.useEffect(()=>{let e=b.current;if(typeof IntersectionObserver>`u`||!e||!fe||!U)return;let t=new IntersectionObserver(()=>{oe(!!e.offsetParent)});return t.observe(e),()=>{t.disconnect()}},[fe,U]);let De=zb(se.tooltip,T.text,s),Oe=m.useMemo(()=>{if(!(!H||fe))return[T.text,s,f,De.title].find(qb)},[H,fe,f,De.title,he]);if(E)return m.createElement(Mb,{value:T.text??(typeof s==`string`?s:``),onSave:M,onCancel:N,onEnd:T.onEnd,prefixCls:S,className:r,style:i,direction:v,component:d,maxLength:T.maxLength,autoSize:T.autoSize,enterIcon:T.enterIcon});let ke=()=>{let{expandable:e,symbol:t}=se;return e?m.createElement(`button`,{type:`button`,key:`expand`,className:`${S}-${ce?`collapse`:`expand`}`,onClick:e=>W(e,{expanded:!ce}),"aria-label":ce?y.collapse:y?.expand},typeof t==`function`?t(ce):t):null},Ae=()=>{if(!w)return;let{icon:e,tooltip:t,tabIndex:n}=T,r=nt(t)[0]||y?.edit,i=typeof r==`string`?r:``;return O.includes(`icon`)?m.createElement(bv,{key:`edit`,title:t===!1?``:r},m.createElement(`button`,{type:`button`,ref:x,className:`${S}-edit`,onClick:j,"aria-label":i,tabIndex:n},e||m.createElement(bb,{role:`button`}))):null},je=()=>P?m.createElement(Jb,{key:`copy`,...F,prefixCls:S,copied:I,locale:y,onCopy:ee,loading:L,iconOnly:!Gc(s)}):null,Ne=e=>{let t=e&&ke(),n=Ae(),r=je();return!t&&!n&&!r?null:m.createElement(`span`,{key:`operations`,className:`${S}-actions`,onMouseEnter:()=>Se(!0),onMouseLeave:()=>Se(!1)},t,n,r)},Pe=e=>[e&&!ce&&m.createElement(`span`,{"aria-hidden":!0,key:`ellipsis`},sx),se.suffix,Ne(e)];return m.createElement(Ct,{onResize:Te,disabled:!U},c=>m.createElement(ax,{tooltipProps:De,enableEllipsis:U,isEllipsis:he,open:Ce&&!be},m.createElement(Bb,{onMouseEnter:e=>{we(!0),p?.(e)},onMouseLeave:e=>{we(!1),h?.(e)},className:K({[`${S}-${a}`]:a,[`${S}-disabled`]:o,[`${S}-ellipsis`]:H,[`${S}-ellipsis-single-line`]:ge,[`${S}-ellipsis-multiple-line`]:_e,[`${S}-link`]:d===`a`},r),prefixCls:n,style:{...i,WebkitLineClamp:_e?ue:void 0},component:d,ref:Me(c,b,t),direction:v,onClick:O.includes(`text`)?j:void 0,"aria-label":Oe?.toString(),title:f,...C},m.createElement(ix,{enableMeasure:U&&!fe,text:s,rows:ue,width:ve,onEllipsis:Ee,expanded:ce,miscDeps:[I,ce,L,w,P,y].concat(At(cx.map(t=>e[t])))},(t,n)=>ox(e,m.createElement(m.Fragment,null,t.length>0&&n&&!ce&&Oe?m.createElement(`span`,{key:`show-content`,"aria-hidden":!0},t):t,Pe(n)))))))}),ux=m.forwardRef((e,t)=>{let{ellipsis:n,rel:r,children:i,navigate:a,...o}=e,s={...o,rel:r===void 0&&o.target===`_blank`?`noopener noreferrer`:r};return m.createElement(lx,{...s,ref:t,ellipsis:!!n,component:`a`},i)}),dx=m.forwardRef((e,t)=>{let{children:n,...r}=e;return m.createElement(lx,{ref:t,...r,component:`div`},n)}),fx=m.forwardRef((e,t)=>{let{ellipsis:n,children:r,...i}=e,a=m.useMemo(()=>n&&typeof n==`object`?tt(n,[`expandable`,`rows`]):n,[n]);return m.createElement(lx,{ref:t,...i,ellipsis:a,component:`span`},r)}),px=[1,2,3,4,5],mx=m.forwardRef((e,t)=>{let{level:n=1,children:r,...i}=e,a=px.includes(n)?`h${n}`:`h1`;return m.createElement(lx,{ref:t,...i,component:a},r)}),hx=Bb;hx.Text=fx,hx.Link=ux,hx.Title=mx,hx.Paragraph=dx;var gx=class extends Error{};gx.prototype.name=`InvalidTokenError`;function _x(e){return decodeURIComponent(atob(e).replace(/(.)/g,(e,t)=>{let n=t.charCodeAt(0).toString(16).toUpperCase();return n.length<2&&(n=`0`+n),`%`+n}))}function vx(e){let t=e.replace(/-/g,`+`).replace(/_/g,`/`);switch(t.length%4){case 0:break;case 2:t+=`==`;break;case 3:t+=`=`;break;default:throw Error(`base64 string is not of the correct length`)}try{return _x(t)}catch{return atob(t)}}function yx(e,t){if(typeof e!=`string`)throw new gx(`Invalid token specified: must be a string`);t||={};let n=t.header===!0?0:1,r=e.split(`.`)[n];if(typeof r!=`string`)throw new gx(`Invalid token specified: missing part #${n+1}`);let i;try{i=vx(r)}catch(e){throw new gx(`Invalid token specified: invalid base64 for part #${n+1} (${e.message})`)}try{return JSON.parse(i)}catch(e){throw new gx(`Invalid token specified: invalid json for part #${n+1} (${e.message})`)}}var bx={debug:()=>void 0,info:()=>void 0,warn:()=>void 0,error:()=>void 0},xx,Sx,Cx=(e=>(e[e.NONE=0]=`NONE`,e[e.ERROR=1]=`ERROR`,e[e.WARN=2]=`WARN`,e[e.INFO=3]=`INFO`,e[e.DEBUG=4]=`DEBUG`,e))(Cx||{});(e=>{function t(){xx=3,Sx=bx}e.reset=t;function n(e){if(!(0<=e&&e<=4))throw Error(`Invalid log level`);xx=e}e.setLevel=n;function r(e){Sx=e}e.setLogger=r})(Cx||={});var wx=class e{constructor(e){this._name=e}debug(...t){xx>=4&&Sx.debug(e._format(this._name,this._method),...t)}info(...t){xx>=3&&Sx.info(e._format(this._name,this._method),...t)}warn(...t){xx>=2&&Sx.warn(e._format(this._name,this._method),...t)}error(...t){xx>=1&&Sx.error(e._format(this._name,this._method),...t)}throw(e){throw this.error(e),e}create(e){let t=Object.create(this);return t._method=e,t.debug(`begin`),t}static createStatic(t,n){let r=new e(`${t}.${n}`);return r.debug(`begin`),r}static _format(e,t){let n=`[${e}]`;return t?`${n} ${t}:`:n}static debug(t,...n){xx>=4&&Sx.debug(e._format(t),...n)}static info(t,...n){xx>=3&&Sx.info(e._format(t),...n)}static warn(t,...n){xx>=2&&Sx.warn(e._format(t),...n)}static error(t,...n){xx>=1&&Sx.error(e._format(t),...n)}};Cx.reset();var Tx=class{static decode(e){try{return yx(e)}catch(e){throw wx.error(`JwtUtils.decode`,e),e}}static async generateSignedJwt(e,t,n){let r=`${kx.encodeBase64Url(new TextEncoder().encode(JSON.stringify(e)))}.${kx.encodeBase64Url(new TextEncoder().encode(JSON.stringify(t)))}`,i=await window.crypto.subtle.sign({name:`ECDSA`,hash:{name:`SHA-256`}},n,new TextEncoder().encode(r));return`${r}.${kx.encodeBase64Url(new Uint8Array(i))}`}static async generateSignedJwtWithHmac(e,t,n){let r=`${kx.encodeBase64Url(new TextEncoder().encode(JSON.stringify(e)))}.${kx.encodeBase64Url(new TextEncoder().encode(JSON.stringify(t)))}`,i=await window.crypto.subtle.sign(`HMAC`,n,new TextEncoder().encode(r));return`${r}.${kx.encodeBase64Url(new Uint8Array(i))}`}},Ex=`10000000-1000-4000-8000-100000000000`,Dx=e=>btoa([...new Uint8Array(e)].map(e=>String.fromCharCode(e)).join(``)),Ox=class e{static _randomWord(){let e=new Uint32Array(1);return crypto.getRandomValues(e),e[0]}static generateUUIDv4(){return Ex.replace(/[018]/g,t=>(t^e._randomWord()&15>>t/4).toString(16)).replace(/-/g,``)}static generateCodeVerifier(){return e.generateUUIDv4()+e.generateUUIDv4()+e.generateUUIDv4()}static async generateCodeChallenge(e){if(!crypto.subtle)throw Error(`Crypto.subtle is available only in secure contexts (HTTPS).`);try{let t=new TextEncoder().encode(e);return Dx(await crypto.subtle.digest(`SHA-256`,t)).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}catch(e){throw wx.error(`CryptoUtils.generateCodeChallenge`,e),e}}static generateBasicAuth(e,t){return Dx(new TextEncoder().encode([e,t].join(`:`)))}static async hash(e,t){let n=new TextEncoder().encode(t),r=await crypto.subtle.digest(e,n);return new Uint8Array(r)}static async customCalculateJwkThumbprint(t){let n;switch(t.kty){case`RSA`:n={e:t.e,kty:t.kty,n:t.n};break;case`EC`:n={crv:t.crv,kty:t.kty,x:t.x,y:t.y};break;case`OKP`:n={crv:t.crv,kty:t.kty,x:t.x};break;case`oct`:n={crv:t.k,kty:t.kty};break;default:throw Error(`Unknown jwk type`)}let r=await e.hash(`SHA-256`,JSON.stringify(n));return e.encodeBase64Url(r)}static async generateDPoPProof({url:t,accessToken:n,httpMethod:r,keyPair:i,nonce:a}){let o,s,c={jti:window.crypto.randomUUID(),htm:r??`GET`,htu:t,iat:Math.floor(Date.now()/1e3)};n&&(o=await e.hash(`SHA-256`,n),s=e.encodeBase64Url(o),c.ath=s),a&&(c.nonce=a);try{let e=await crypto.subtle.exportKey(`jwk`,i.publicKey),t={alg:`ES256`,typ:`dpop+jwt`,jwk:{crv:e.crv,kty:e.kty,x:e.x,y:e.y}};return await Tx.generateSignedJwt(t,c,i.privateKey)}catch(e){throw e instanceof TypeError?Error(`Error exporting dpop public key: ${e.message}`):e}}static async generateDPoPJkt(t){try{let n=await crypto.subtle.exportKey(`jwk`,t.publicKey);return await e.customCalculateJwkThumbprint(n)}catch(e){throw e instanceof TypeError?Error(`Could not retrieve dpop keys from storage: ${e.message}`):e}}static async generateDPoPKeys(){return await window.crypto.subtle.generateKey({name:`ECDSA`,namedCurve:`P-256`},!1,[`sign`,`verify`])}static async generateClientAssertionJwt(t,n,r,i=`HS256`){let a=Math.floor(Date.now()/1e3),o={alg:i,typ:`JWT`},s={iss:t,sub:t,aud:r,jti:e.generateUUIDv4(),exp:a+300,iat:a},c={HS256:`SHA-256`,HS384:`SHA-384`,HS512:`SHA-512`}[i];if(!c)throw Error(`Unsupported algorithm: ${i}. Supported algorithms are: HS256, HS384, HS512`);let l=new TextEncoder,u=await crypto.subtle.importKey(`raw`,l.encode(n),{name:`HMAC`,hash:c},!1,[`sign`]);return await Tx.generateSignedJwtWithHmac(o,s,u)}};Ox.encodeBase64Url=e=>Dx(e).replace(/=/g,``).replace(/\+/g,`-`).replace(/\//g,`_`);var kx=Ox,Ax=class{constructor(e){this._name=e,this._callbacks=[],this._logger=new wx(`Event('${this._name}')`)}addHandler(e){return this._callbacks.push(e),()=>this.removeHandler(e)}removeHandler(e){let t=this._callbacks.lastIndexOf(e);t>=0&&this._callbacks.splice(t,1)}async raise(...e){this._logger.debug(`raise:`,...e);for(let t of this._callbacks)await t(...e)}},jx=class{static center({...e}){return e.width??=[800,720,600,480].find(e=>e<=window.outerWidth/1.618)??360,e.left??=Math.max(0,Math.round(window.screenX+(window.outerWidth-e.width)/2)),e.height!=null&&(e.top??=Math.max(0,Math.round(window.screenY+(window.outerHeight-e.height)/2))),e}static serialize(e){return Object.entries(e).filter(([,e])=>e!=null).map(([e,t])=>`${e}=${typeof t==`boolean`?t?`yes`:`no`:t}`).join(`,`)}},Mx=class e extends Ax{constructor(){super(...arguments),this._logger=new wx(`Timer('${this._name}')`),this._timerHandle=null,this._expiration=0,this._callback=()=>{let t=this._expiration-e.getEpochTime();this._logger.debug(`timer completes in`,t),this._expiration<=e.getEpochTime()&&(this.cancel(),super.raise())}}static getEpochTime(){return Math.floor(Date.now()/1e3)}init(t){let n=this._logger.create(`init`);t=Math.max(Math.floor(t),1);let r=e.getEpochTime()+t;if(this.expiration===r&&this._timerHandle){n.debug(`skipping since already initialized for expiration at`,this.expiration);return}this.cancel(),n.debug(`using duration`,t),this._expiration=r;let i=Math.min(t,5);this._timerHandle=setInterval(this._callback,i*1e3)}get expiration(){return this._expiration}cancel(){this._logger.create(`cancel`),this._timerHandle&&=(clearInterval(this._timerHandle),null)}},Nx=class{static readParams(e,t=`query`){if(!e)throw TypeError(`Invalid URL`);let n=new URL(e,`http://127.0.0.1`)[t===`fragment`?`hash`:`search`];return new URLSearchParams(n.slice(1))}},Px=`;`,Fx=class extends Error{constructor(e,t){if(super(e.error_description||e.error||``),this.form=t,this.name=`ErrorResponse`,!e.error)throw wx.error(`ErrorResponse`,`No error passed`),Error(`No error passed`);this.error=e.error,this.error_description=e.error_description??null,this.error_uri=e.error_uri??null,this.state=e.userState,this.session_state=e.session_state??null,this.url_state=e.url_state}},Ix=class extends Error{constructor(e){super(e),this.name=`ErrorTimeout`}},Lx=class{constructor(e){this._logger=new wx(`AccessTokenEvents`),this._expiringTimer=new Mx(`Access token expiring`),this._expiredTimer=new Mx(`Access token expired`),this._expiringNotificationTimeInSeconds=e.expiringNotificationTimeInSeconds}async load(e){let t=this._logger.create(`load`);if(e.access_token&&e.expires_in!==void 0){let n=e.expires_in;if(t.debug(`access token present, remaining duration:`,n),n>0){let e=n-this._expiringNotificationTimeInSeconds;e<=0&&(e=1),t.debug(`registering expiring timer, raising in`,e,`seconds`),this._expiringTimer.init(e)}else t.debug(`canceling existing expiring timer because we're past expiration.`),this._expiringTimer.cancel();let r=n+1;t.debug(`registering expired timer, raising in`,r,`seconds`),this._expiredTimer.init(r)}else this._expiringTimer.cancel(),this._expiredTimer.cancel()}async unload(){this._logger.debug(`unload: canceling existing access token timers`),this._expiringTimer.cancel(),this._expiredTimer.cancel()}addAccessTokenExpiring(e){return this._expiringTimer.addHandler(e)}removeAccessTokenExpiring(e){this._expiringTimer.removeHandler(e)}addAccessTokenExpired(e){return this._expiredTimer.addHandler(e)}removeAccessTokenExpired(e){this._expiredTimer.removeHandler(e)}},Rx=class{constructor(e,t,n,r,i){this._callback=e,this._client_id=t,this._intervalInSeconds=r,this._stopOnError=i,this._logger=new wx(`CheckSessionIFrame`),this._timer=null,this._session_state=null,this._message=e=>{e.origin===this._frame_origin&&e.source===this._frame.contentWindow&&(e.data===`error`?(this._logger.error(`error message from check session op iframe`),this._stopOnError&&this.stop()):e.data===`changed`?(this._logger.debug(`changed message from check session op iframe`),this.stop(),this._callback()):this._logger.debug(e.data+` message from check session op iframe`))};let a=new URL(n);this._frame_origin=a.origin,this._frame=window.document.createElement(`iframe`),this._frame.style.visibility=`hidden`,this._frame.style.position=`fixed`,this._frame.style.left=`-1000px`,this._frame.style.top=`0`,this._frame.width=`0`,this._frame.height=`0`,this._frame.src=a.href}load(){return new Promise(e=>{this._frame.onload=()=>{e()},window.document.body.appendChild(this._frame),window.addEventListener(`message`,this._message,!1)})}start(e){if(this._session_state===e)return;this._logger.create(`start`),this.stop(),this._session_state=e;let t=()=>{!this._frame.contentWindow||!this._session_state||this._frame.contentWindow.postMessage(this._client_id+` `+this._session_state,this._frame_origin)};t(),this._timer=setInterval(t,this._intervalInSeconds*1e3)}stop(){this._logger.create(`stop`),this._session_state=null,this._timer&&=(clearInterval(this._timer),null)}},zx=class{constructor(){this._logger=new wx(`InMemoryWebStorage`),this._data={}}clear(){this._logger.create(`clear`),this._data={}}getItem(e){return this._logger.create(`getItem('${e}')`),this._data[e]}setItem(e,t){this._logger.create(`setItem('${e}')`),this._data[e]=t}removeItem(e){this._logger.create(`removeItem('${e}')`),delete this._data[e]}get length(){return Object.getOwnPropertyNames(this._data).length}key(e){return Object.getOwnPropertyNames(this._data)[e]}},Bx=class extends Error{constructor(e,t){super(t),this.name=`ErrorDPoPNonce`,this.nonce=e}},Vx=class{constructor(e=[],t=null,n={}){this._jwtHandler=t,this._extraHeaders=n,this._logger=new wx(`JsonService`),this._contentTypes=[],this._contentTypes.push(...e,`application/json`),t&&this._contentTypes.push(`application/jwt`)}async fetchWithTimeout(e,t={}){let{timeoutInSeconds:n,...r}=t;if(!n)return await fetch(e,r);let i=new AbortController,a=setTimeout(()=>i.abort(),n*1e3);try{return await fetch(e,{...t,signal:i.signal})}catch(e){throw e instanceof DOMException&&e.name===`AbortError`?new Ix(`Network timed out`):e}finally{clearTimeout(a)}}async getJson(e,{token:t,credentials:n,timeoutInSeconds:r}={}){let i=this._logger.create(`getJson`),a={Accept:this._contentTypes.join(`, `)};t&&(i.debug(`token passed, setting Authorization header`),a.Authorization=`Bearer `+t),this._appendExtraHeaders(a);let o;try{i.debug(`url:`,e),o=await this.fetchWithTimeout(e,{method:`GET`,headers:a,timeoutInSeconds:r,credentials:n})}catch(e){throw i.error(`Network Error`),e}i.debug(`HTTP response received, status`,o.status);let s=o.headers.get(`Content-Type`);if(s&&!this._contentTypes.find(e=>s.startsWith(e))&&i.throw(Error(`Invalid response Content-Type: ${s??`undefined`}, from URL: ${e}`)),o.ok&&this._jwtHandler&&s?.startsWith(`application/jwt`))return await this._jwtHandler(await o.text());let c;try{c=await o.json()}catch(e){throw i.error(`Error parsing JSON response`,e),o.ok?e:Error(`${o.statusText} (${o.status})`)}if(!o.ok)throw i.error(`Error from server:`,c),c.error?new Fx(c):Error(`${o.statusText} (${o.status}): ${JSON.stringify(c)}`);return c}async postForm(e,{body:t,basicAuth:n,timeoutInSeconds:r,initCredentials:i,extraHeaders:a}){let o=this._logger.create(`postForm`),s={Accept:this._contentTypes.join(`, `),"Content-Type":`application/x-www-form-urlencoded`,...a};n!==void 0&&(s.Authorization=`Basic `+n),this._appendExtraHeaders(s);let c;try{o.debug(`url:`,e),c=await this.fetchWithTimeout(e,{method:`POST`,headers:s,body:t,timeoutInSeconds:r,credentials:i})}catch(e){throw o.error(`Network error`),e}o.debug(`HTTP response received, status`,c.status);let l=c.headers.get(`Content-Type`);if(l&&!this._contentTypes.find(e=>l.startsWith(e)))throw Error(`Invalid response Content-Type: ${l??`undefined`}, from URL: ${e}`);let u=await c.text(),d={};if(u)try{d=JSON.parse(u)}catch(e){throw o.error(`Error parsing JSON response`,e),c.ok?e:Error(`${c.statusText} (${c.status})`)}if(!c.ok)throw o.error(`Error from server:`,d),c.headers.has(`dpop-nonce`)?new Bx(c.headers.get(`dpop-nonce`),`${JSON.stringify(d)}`):d.error?new Fx(d,t):Error(`${c.statusText} (${c.status}): ${JSON.stringify(d)}`);return d}_appendExtraHeaders(e){let t=this._logger.create(`appendExtraHeaders`),n=Object.keys(this._extraHeaders),r=[`accept`,`content-type`],i=[`authorization`];n.length!==0&&n.forEach(n=>{if(r.includes(n.toLocaleLowerCase())){t.warn(`Protected header could not be set`,n,r);return}if(i.includes(n.toLocaleLowerCase())&&Object.keys(e).includes(n)){t.warn(`Header could not be overridden`,n,i);return}let a=typeof this._extraHeaders[n]==`function`?this._extraHeaders[n]():this._extraHeaders[n];a&&a!==``&&(e[n]=a)})}},Hx=class{constructor(e){this._settings=e,this._logger=new wx(`MetadataService`),this._signingKeys=null,this._metadata=null,this._metadataUrl=this._settings.metadataUrl,this._jsonService=new Vx([`application/jwk-set+json`],null,this._settings.extraHeaders),this._settings.signingKeys&&(this._logger.debug(`using signingKeys from settings`),this._signingKeys=this._settings.signingKeys),this._settings.metadata&&(this._logger.debug(`using metadata from settings`),this._metadata=this._settings.metadata),this._settings.fetchRequestCredentials&&(this._logger.debug(`using fetchRequestCredentials from settings`),this._fetchRequestCredentials=this._settings.fetchRequestCredentials)}resetSigningKeys(){this._signingKeys=null}async getMetadata(){let e=this._logger.create(`getMetadata`);if(this._metadata)return e.debug(`using cached values`),this._metadata;if(!this._metadataUrl)throw e.throw(Error(`No authority or metadataUrl configured on settings`)),null;e.debug(`getting metadata from`,this._metadataUrl);let t=await this._jsonService.getJson(this._metadataUrl,{credentials:this._fetchRequestCredentials,timeoutInSeconds:this._settings.requestTimeoutInSeconds});return e.debug(`merging remote JSON with seed metadata`),this._metadata=Object.assign({},t,this._settings.metadataSeed),this._metadata}getIssuer(){return this._getMetadataProperty(`issuer`)}getAuthorizationEndpoint(){return this._getMetadataProperty(`authorization_endpoint`)}getUserInfoEndpoint(){return this._getMetadataProperty(`userinfo_endpoint`)}getTokenEndpoint(e=!0){return this._getMetadataProperty(`token_endpoint`,e)}getCheckSessionIframe(){return this._getMetadataProperty(`check_session_iframe`,!0)}getEndSessionEndpoint(){return this._getMetadataProperty(`end_session_endpoint`,!0)}getRevocationEndpoint(e=!0){return this._getMetadataProperty(`revocation_endpoint`,e)}getKeysEndpoint(e=!0){return this._getMetadataProperty(`jwks_uri`,e)}async _getMetadataProperty(e,t=!1){let n=this._logger.create(`_getMetadataProperty('${e}')`),r=await this.getMetadata();if(n.debug(`resolved`),r[e]===void 0){if(t===!0){n.warn(`Metadata does not contain optional property`);return}n.throw(Error(`Metadata does not contain property `+e))}return r[e]}async getSigningKeys(){let e=this._logger.create(`getSigningKeys`);if(this._signingKeys)return e.debug(`returning signingKeys from cache`),this._signingKeys;let t=await this.getKeysEndpoint(!1);e.debug(`got jwks_uri`,t);let n=await this._jsonService.getJson(t,{timeoutInSeconds:this._settings.requestTimeoutInSeconds});if(e.debug(`got key set`,n),!Array.isArray(n.keys))throw e.throw(Error(`Missing keys on keyset`)),null;return this._signingKeys=n.keys,this._signingKeys}},Ux=class{constructor({prefix:e=`oidc.`,store:t=localStorage}={}){this._logger=new wx(`WebStorageStateStore`),this._store=t,this._prefix=e}async set(e,t){this._logger.create(`set('${e}')`),e=this._prefix+e,await this._store.setItem(e,t)}async get(e){return this._logger.create(`get('${e}')`),e=this._prefix+e,await this._store.getItem(e)}async remove(e){this._logger.create(`remove('${e}')`),e=this._prefix+e;let t=await this._store.getItem(e);return await this._store.removeItem(e),t}async getAllKeys(){this._logger.create(`getAllKeys`);let e=await this._store.length,t=[];for(let n=0;n{let t=this._logger.create(`_getClaimsFromJwt`);try{let n=Tx.decode(e);return t.debug(`JWT decoding successful`),n}catch(e){throw t.error(`Error parsing JWT response`),e}},this._jsonService=new Vx(void 0,this._getClaimsFromJwt,this._settings.extraHeaders)}async getClaims(e){let t=this._logger.create(`getClaims`);e||this._logger.throw(Error(`No token passed`));let n=await this._metadataService.getUserInfoEndpoint();t.debug(`got userinfo url`,n);let r=await this._jsonService.getJson(n,{token:e,credentials:this._settings.fetchRequestCredentials,timeoutInSeconds:this._settings.requestTimeoutInSeconds});return t.debug(`got claims`,r),r}},Xx=class{constructor(e,t){this._settings=e,this._metadataService=t,this._logger=new wx(`TokenClient`),this._jsonService=new Vx(this._settings.revokeTokenAdditionalContentTypes,null,this._settings.extraHeaders)}async exchangeCode({grant_type:e=`authorization_code`,redirect_uri:t=this._settings.redirect_uri,client_id:n=this._settings.client_id,client_secret:r=this._settings.client_secret,extraHeaders:i,...a}){let o=this._logger.create(`exchangeCode`);n||o.throw(Error(`A client_id is required`)),t||o.throw(Error(`A redirect_uri is required`)),a.code||o.throw(Error(`A code is required`));let s=new URLSearchParams({grant_type:e,redirect_uri:t});for(let[e,t]of Object.entries(a))t!=null&&s.set(e,t);if((this._settings.client_authentication===`client_secret_basic`||this._settings.client_authentication===`client_secret_jwt`)&&r==null)throw o.throw(Error(`A client_secret is required`)),null;let c,l=await this._metadataService.getTokenEndpoint(!1);switch(this._settings.client_authentication){case`client_secret_basic`:c=kx.generateBasicAuth(n,r);break;case`client_secret_post`:s.append(`client_id`,n),r&&s.append(`client_secret`,r);break;case`client_secret_jwt`:{let e=await kx.generateClientAssertionJwt(n,r,l,this._settings.token_endpoint_auth_signing_alg);s.append(`client_id`,n),s.append(`client_assertion_type`,`urn:ietf:params:oauth:client-assertion-type:jwt-bearer`),s.append(`client_assertion`,e);break}}o.debug(`got token endpoint`);let u=await this._jsonService.postForm(l,{body:s,basicAuth:c,timeoutInSeconds:this._settings.requestTimeoutInSeconds,initCredentials:this._settings.fetchRequestCredentials,extraHeaders:i});return o.debug(`got response`),u}async exchangeCredentials({grant_type:e=`password`,client_id:t=this._settings.client_id,client_secret:n=this._settings.client_secret,scope:r=this._settings.scope,...i}){let a=this._logger.create(`exchangeCredentials`);t||a.throw(Error(`A client_id is required`));let o=new URLSearchParams({grant_type:e});this._settings.omitScopeWhenRequesting||o.set(`scope`,r);for(let[e,t]of Object.entries(i))t!=null&&o.set(e,t);if((this._settings.client_authentication===`client_secret_basic`||this._settings.client_authentication===`client_secret_jwt`)&&n==null)throw a.throw(Error(`A client_secret is required`)),null;let s,c=await this._metadataService.getTokenEndpoint(!1);switch(this._settings.client_authentication){case`client_secret_basic`:s=kx.generateBasicAuth(t,n);break;case`client_secret_post`:o.append(`client_id`,t),n&&o.append(`client_secret`,n);break;case`client_secret_jwt`:{let e=await kx.generateClientAssertionJwt(t,n,c,this._settings.token_endpoint_auth_signing_alg);o.append(`client_id`,t),o.append(`client_assertion_type`,`urn:ietf:params:oauth:client-assertion-type:jwt-bearer`),o.append(`client_assertion`,e);break}}a.debug(`got token endpoint`);let l=await this._jsonService.postForm(c,{body:o,basicAuth:s,timeoutInSeconds:this._settings.requestTimeoutInSeconds,initCredentials:this._settings.fetchRequestCredentials});return a.debug(`got response`),l}async exchangeRefreshToken({grant_type:e=`refresh_token`,client_id:t=this._settings.client_id,client_secret:n=this._settings.client_secret,timeoutInSeconds:r,extraHeaders:i,...a}){let o=this._logger.create(`exchangeRefreshToken`);t||o.throw(Error(`A client_id is required`)),a.refresh_token||o.throw(Error(`A refresh_token is required`));let s=new URLSearchParams({grant_type:e});for(let[e,t]of Object.entries(a))Array.isArray(t)?t.forEach(t=>s.append(e,t)):t!=null&&s.set(e,t);if((this._settings.client_authentication===`client_secret_basic`||this._settings.client_authentication===`client_secret_jwt`)&&n==null)throw o.throw(Error(`A client_secret is required`)),null;let c,l=await this._metadataService.getTokenEndpoint(!1);switch(this._settings.client_authentication){case`client_secret_basic`:c=kx.generateBasicAuth(t,n);break;case`client_secret_post`:s.append(`client_id`,t),n&&s.append(`client_secret`,n);break;case`client_secret_jwt`:{let e=await kx.generateClientAssertionJwt(t,n,l,this._settings.token_endpoint_auth_signing_alg);s.append(`client_id`,t),s.append(`client_assertion_type`,`urn:ietf:params:oauth:client-assertion-type:jwt-bearer`),s.append(`client_assertion`,e);break}}o.debug(`got token endpoint`);let u=await this._jsonService.postForm(l,{body:s,basicAuth:c,timeoutInSeconds:r,initCredentials:this._settings.fetchRequestCredentials,extraHeaders:i});return o.debug(`got response`),u}async revoke(e){let t=this._logger.create(`revoke`);e.token||t.throw(Error(`A token is required`));let n=await this._metadataService.getRevocationEndpoint(!1);t.debug(`got revocation endpoint, revoking ${e.token_type_hint??`default token type`}`);let r=new URLSearchParams;for(let[t,n]of Object.entries(e))n!=null&&r.set(t,n);r.set(`client_id`,this._settings.client_id),this._settings.client_secret&&r.set(`client_secret`,this._settings.client_secret),await this._jsonService.postForm(n,{body:r,timeoutInSeconds:this._settings.requestTimeoutInSeconds}),t.debug(`got response`)}},Zx=class{constructor(e,t,n){this._settings=e,this._metadataService=t,this._claimsService=n,this._logger=new wx(`ResponseValidator`),this._userInfoService=new Yx(this._settings,this._metadataService),this._tokenClient=new Xx(this._settings,this._metadataService)}async validateSigninResponse(e,t,n){let r=this._logger.create(`validateSigninResponse`);this._processSigninState(e,t),r.debug(`state processed`),await this._processCode(e,t,n),r.debug(`code processed`),e.isOpenId&&this._validateIdTokenAttributes(e),r.debug(`tokens validated`),await this._processClaims(e,t?.skipUserInfo,e.isOpenId),r.debug(`claims processed`)}async validateCredentialsResponse(e,t){let n=this._logger.create(`validateCredentialsResponse`),r=e.isOpenId&&!!e.id_token;r&&this._validateIdTokenAttributes(e),n.debug(`tokens validated`),await this._processClaims(e,t,r),n.debug(`claims processed`)}async validateRefreshResponse(e,t){let n=this._logger.create(`validateRefreshResponse`);e.userState=t.data,e.session_state??=t.session_state,e.scope??=t.scope,e.isOpenId&&e.id_token&&(this._validateIdTokenAttributes(e,t.id_token),n.debug(`ID Token validated`)),e.id_token||(e.id_token=t.id_token,e.profile=t.profile);let r=e.isOpenId&&!!e.id_token;await this._processClaims(e,!1,r),n.debug(`claims processed`)}validateSignoutResponse(e,t){let n=this._logger.create(`validateSignoutResponse`);if(t.id!==e.state&&n.throw(Error(`State does not match`)),n.debug(`state validated`),e.userState=t.data,e.error)throw n.warn(`Response was error`,e.error),new Fx(e)}_processSigninState(e,t){let n=this._logger.create(`_processSigninState`);if(t.id!==e.state&&n.throw(Error(`State does not match`)),t.client_id||n.throw(Error(`No client_id on state`)),t.authority||n.throw(Error(`No authority on state`)),this._settings.authority!==t.authority&&n.throw(Error(`authority mismatch on settings vs. signin state`)),this._settings.client_id&&this._settings.client_id!==t.client_id&&n.throw(Error(`client_id mismatch on settings vs. signin state`)),n.debug(`state validated`),e.userState=t.data,e.url_state=t.url_state,e.scope??=t.scope,e.error)throw n.warn(`Response was error`,e.error),new Fx(e);t.code_verifier&&!e.code&&n.throw(Error(`Expected code in response`))}async _processClaims(e,t=!1,n=!0){let r=this._logger.create(`_processClaims`);if(e.profile=this._claimsService.filterProtocolClaims(e.profile),t||!this._settings.loadUserInfo||!e.access_token){r.debug(`not loading user info`);return}r.debug(`loading user info`);let i=await this._userInfoService.getClaims(e.access_token);r.debug(`user info claims received from user info endpoint`),n&&i.sub!==e.profile.sub&&r.throw(Error(`subject from UserInfo response does not match subject in ID Token`)),e.profile=this._claimsService.mergeClaims(e.profile,this._claimsService.filterProtocolClaims(i)),r.debug(`user info claims received, updated profile:`,e.profile)}async _processCode(e,t,n){let r=this._logger.create(`_processCode`);if(e.code){r.debug(`Validating code`);let i=await this._tokenClient.exchangeCode({client_id:t.client_id,client_secret:t.client_secret,code:e.code,redirect_uri:t.redirect_uri,code_verifier:t.code_verifier,extraHeaders:n,...t.extraTokenParams});Object.assign(e,i)}else r.debug(`No code to process`)}_validateIdTokenAttributes(e,t){let n=this._logger.create(`_validateIdTokenAttributes`);n.debug(`decoding ID Token JWT`);let r=Tx.decode(e.id_token??``);if(r.sub||n.throw(Error(`ID Token is missing a subject claim`)),t){let e=Tx.decode(t);r.sub!==e.sub&&n.throw(Error(`sub in id_token does not match current sub`)),r.auth_time&&r.auth_time!==e.auth_time&&n.throw(Error(`auth_time in id_token does not match original auth_time`)),r.azp&&r.azp!==e.azp&&n.throw(Error(`azp in id_token does not match original azp`)),!r.azp&&e.azp&&n.throw(Error(`azp not in id_token, but present in original id_token`))}e.profile=r}},Qx=class e{constructor(e){this.id=e.id||kx.generateUUIDv4(),this.data=e.data,e.created&&e.created>0?this.created=e.created:this.created=Mx.getEpochTime(),this.request_type=e.request_type,this.url_state=e.url_state}toStorageString(){return new wx(`State`).create(`toStorageString`),JSON.stringify({id:this.id,data:this.data,created:this.created,request_type:this.request_type,url_state:this.url_state})}static fromStorageString(t){return wx.createStatic(`State`,`fromStorageString`),Promise.resolve(new e(JSON.parse(t)))}static async clearStaleState(t,n){let r=wx.createStatic(`State`,`clearStaleState`),i=Mx.getEpochTime()-n,a=await t.getAllKeys();r.debug(`got keys`,a);for(let n=0;nS.searchParams.append(`resource`,e));for(let[e,t]of Object.entries({response_mode:c,...b,...h}))t!=null&&S.searchParams.append(e,t.toString());return new e({url:S.href,state:x})}};eS._logger=new wx(`SigninRequest`);var tS=eS,nS=`openid`,rS=class{constructor(e){if(this.access_token=``,this.token_type=``,this.profile={},this.state=e.get(`state`),this.session_state=e.get(`session_state`),this.state){let e=decodeURIComponent(this.state).split(Px);this.state=e[0],e.length>1&&(this.url_state=e.slice(1).join(Px))}this.error=e.get(`error`),this.error_description=e.get(`error_description`),this.error_uri=e.get(`error_uri`),this.code=e.get(`code`)}get expires_in(){if(this.expires_at!==void 0)return this.expires_at-Mx.getEpochTime()}set expires_in(e){typeof e==`string`&&(e=Number(e)),e!==void 0&&e>=0&&(this.expires_at=Math.floor(e)+Mx.getEpochTime())}get isOpenId(){return this.scope?.split(` `).includes(nS)||!!this.id_token}},iS=class{constructor({url:e,state_data:t,id_token_hint:n,post_logout_redirect_uri:r,extraQueryParams:i,request_type:a,client_id:o,url_state:s}){if(this._logger=new wx(`SignoutRequest`),!e)throw this._logger.error(`ctor: No url passed`),Error(`url`);let c=new URL(e);if(n&&c.searchParams.append(`id_token_hint`,n),o&&c.searchParams.append(`client_id`,o),r&&(c.searchParams.append(`post_logout_redirect_uri`,r),t||s)){this.state=new Qx({data:t,request_type:a,url_state:s});let e=this.state.id;s&&(e=`${e}${Px}${s}`),c.searchParams.append(`state`,e)}for(let[e,t]of Object.entries({...i}))t!=null&&c.searchParams.append(e,t.toString());this.url=c.href}},aS=class{constructor(e){if(this.state=e.get(`state`),this.state){let e=decodeURIComponent(this.state).split(Px);this.state=e[0],e.length>1&&(this.url_state=e.slice(1).join(Px))}this.error=e.get(`error`),this.error_description=e.get(`error_description`),this.error_uri=e.get(`error_uri`)}},oS=[`nbf`,`jti`,`auth_time`,`nonce`,`acr`,`amr`,`azp`,`at_hash`],sS=[`sub`,`iss`,`aud`,`exp`,`iat`],cS=class{constructor(e){this._settings=e,this._logger=new wx(`ClaimsService`)}filterProtocolClaims(e){let t={...e};if(this._settings.filterProtocolClaims){let e;e=Array.isArray(this._settings.filterProtocolClaims)?this._settings.filterProtocolClaims:oS;for(let n of e)sS.includes(n)||delete t[n]}return t}mergeClaims(e,t){let n={...e};for(let[e,r]of Object.entries(t))if(n[e]!==r)if(Array.isArray(n[e])||Array.isArray(r))if(this._settings.mergeClaimsStrategy.array==`replace`)n[e]=r;else{let t=Array.isArray(n[e])?n[e]:[n[e]];for(let e of Array.isArray(r)?r:[r])t.includes(e)||t.push(e);n[e]=t}else typeof n[e]==`object`&&typeof r==`object`?n[e]=this.mergeClaims(n[e],r):n[e]=r;return n}},lS=class{constructor(e,t){this.keys=e,this.nonce=t}},uS=class{constructor(e,t){this._logger=new wx(`OidcClient`),this.settings=e instanceof Jx?e:new Jx(e),this.metadataService=t??new Hx(this.settings),this._claimsService=new cS(this.settings),this._validator=new Zx(this.settings,this.metadataService,this._claimsService),this._tokenClient=new Xx(this.settings,this.metadataService)}async createSigninRequest({state:e,request:t,request_uri:n,request_type:r,id_token_hint:i,login_hint:a,skipUserInfo:o,nonce:s,url_state:c,response_type:l=this.settings.response_type,scope:u=this.settings.scope,redirect_uri:d=this.settings.redirect_uri,prompt:f=this.settings.prompt,display:p=this.settings.display,max_age:m=this.settings.max_age,ui_locales:h=this.settings.ui_locales,acr_values:g=this.settings.acr_values,resource:_=this.settings.resource,response_mode:v=this.settings.response_mode,extraQueryParams:y=this.settings.extraQueryParams,extraTokenParams:b=this.settings.extraTokenParams,dpopJkt:x,omitScopeWhenRequesting:S=this.settings.omitScopeWhenRequesting}){let C=this._logger.create(`createSigninRequest`);if(l!==`code`)throw Error(`Only the Authorization Code flow (with PKCE) is supported`);let w=await this.metadataService.getAuthorizationEndpoint();C.debug(`Received authorization endpoint`,w);let T=await tS.create({url:w,authority:this.settings.authority,client_id:this.settings.client_id,redirect_uri:d,response_type:l,scope:u,state_data:e,url_state:c,prompt:f,display:p,max_age:m,ui_locales:h,id_token_hint:i,login_hint:a,acr_values:g,dpopJkt:x,resource:_,request:t,request_uri:n,extraQueryParams:y,extraTokenParams:b,request_type:r,response_mode:v,client_secret:this.settings.client_secret,skipUserInfo:o,nonce:s,disablePKCE:this.settings.disablePKCE,omitScopeWhenRequesting:S});await this.clearStaleState();let E=T.state;return await this.settings.stateStore.set(E.id,E.toStorageString()),T}async readSigninResponseState(e,t=!1){let n=this._logger.create(`readSigninResponseState`),r=new rS(Nx.readParams(e,this.settings.response_mode));if(!r.state)throw n.throw(Error(`No state in response`)),null;let i=await this.settings.stateStore[t?`remove`:`get`](r.state);if(!i)throw n.throw(Error(`No matching state found in storage`)),null;return{state:await $x.fromStorageString(i),response:r}}async processSigninResponse(e,t,n=!0){let r=this._logger.create(`processSigninResponse`),{state:i,response:a}=await this.readSigninResponseState(e,n);if(r.debug(`received state from storage; validating response`),this.settings.dpop&&this.settings.dpop.store){let e=await this.getDpopProof(this.settings.dpop.store);t={...t,DPoP:e}}try{await this._validator.validateSigninResponse(a,i,t)}catch(e){if(e instanceof Bx&&this.settings.dpop){let n=await this.getDpopProof(this.settings.dpop.store,e.nonce);t.DPoP=n,await this._validator.validateSigninResponse(a,i,t)}else throw e}return a}async getDpopProof(e,t){let n,r;return(await e.getAllKeys()).includes(this.settings.client_id)?(r=await e.get(this.settings.client_id),r.nonce!==t&&t&&(r.nonce=t,await e.set(this.settings.client_id,r))):(n=await kx.generateDPoPKeys(),r=new lS(n,t),await e.set(this.settings.client_id,r)),await kx.generateDPoPProof({url:await this.metadataService.getTokenEndpoint(!1),httpMethod:`POST`,keyPair:r.keys,nonce:r.nonce})}async processResourceOwnerPasswordCredentials({username:e,password:t,skipUserInfo:n=!1,extraTokenParams:r={}}){let i=await this._tokenClient.exchangeCredentials({username:e,password:t,...r}),a=new rS(new URLSearchParams);return Object.assign(a,i),await this._validator.validateCredentialsResponse(a,n),a}async useRefreshToken({state:e,redirect_uri:t,resource:n,timeoutInSeconds:r,extraHeaders:i,extraTokenParams:a}){let o=this._logger.create(`useRefreshToken`),s;if(this.settings.refreshTokenAllowedScope===void 0)s=e.scope;else{let t=this.settings.refreshTokenAllowedScope.split(` `);s=(e.scope?.split(` `)||[]).filter(e=>t.includes(e)).join(` `)}if(this.settings.dpop&&this.settings.dpop.store){let e=await this.getDpopProof(this.settings.dpop.store);i={...i,DPoP:e}}let c;try{c=await this._tokenClient.exchangeRefreshToken({refresh_token:e.refresh_token,scope:s,redirect_uri:t,resource:n,timeoutInSeconds:r,extraHeaders:i,...a})}catch(o){if(o instanceof Bx&&this.settings.dpop)i.DPoP=await this.getDpopProof(this.settings.dpop.store,o.nonce),c=await this._tokenClient.exchangeRefreshToken({refresh_token:e.refresh_token,scope:s,redirect_uri:t,resource:n,timeoutInSeconds:r,extraHeaders:i,...a});else throw o}let l=new rS(new URLSearchParams);return Object.assign(l,c),o.debug(`validating response`,l),await this._validator.validateRefreshResponse(l,{...e,scope:s}),l}async createSignoutRequest({state:e,id_token_hint:t,client_id:n,request_type:r,url_state:i,post_logout_redirect_uri:a=this.settings.post_logout_redirect_uri,extraQueryParams:o=this.settings.extraQueryParams}={}){let s=this._logger.create(`createSignoutRequest`),c=await this.metadataService.getEndSessionEndpoint();if(!c)throw s.throw(Error(`No end session endpoint`)),null;s.debug(`Received end session endpoint`,c),!n&&a&&!t&&(n=this.settings.client_id);let l=new iS({url:c,id_token_hint:t,client_id:n,post_logout_redirect_uri:a,state_data:e,extraQueryParams:o,request_type:r,url_state:i});await this.clearStaleState();let u=l.state;return u&&(s.debug(`Signout request has state to persist`),await this.settings.stateStore.set(u.id,u.toStorageString())),l}async readSignoutResponseState(e,t=!1){let n=this._logger.create(`readSignoutResponseState`),r=new aS(Nx.readParams(e,this.settings.response_mode));if(!r.state){if(n.debug(`No state in response`),r.error)throw n.warn(`Response was error:`,r.error),new Fx(r);return{state:void 0,response:r}}let i=await this.settings.stateStore[t?`remove`:`get`](r.state);if(!i)throw n.throw(Error(`No matching state found in storage`)),null;return{state:await Qx.fromStorageString(i),response:r}}async processSignoutResponse(e){let t=this._logger.create(`processSignoutResponse`),{state:n,response:r}=await this.readSignoutResponseState(e,!0);return n?(t.debug(`Received state from storage; validating response`),this._validator.validateSignoutResponse(r,n)):t.debug(`No state from storage; skipping response validation`),r}clearStaleState(){return this._logger.create(`clearStaleState`),Qx.clearStaleState(this.settings.stateStore,this.settings.staleStateAgeInSeconds)}async revokeToken(e,t){return this._logger.create(`revokeToken`),await this._tokenClient.revoke({token:e,token_type_hint:t})}},dS=class{constructor(e){this._userManager=e,this._logger=new wx(`SessionMonitor`),this._start=async e=>{let t=e.session_state;if(!t)return;let n=this._logger.create(`_start`);if(e.profile?(this._sub=e.profile.sub,n.debug(`session_state`,t,`, sub`,this._sub)):(this._sub=void 0,n.debug(`session_state`,t,`, anonymous user`)),this._checkSessionIFrame){this._checkSessionIFrame.start(t);return}try{let e=await this._userManager.metadataService.getCheckSessionIframe();if(e){n.debug(`initializing check session iframe`);let r=this._userManager.settings.client_id,i=this._userManager.settings.checkSessionIntervalInSeconds,a=this._userManager.settings.stopCheckSessionOnError,o=new Rx(this._callback,r,e,i,a);await o.load(),this._checkSessionIFrame=o,o.start(t)}else n.warn(`no check session iframe found in the metadata`)}catch(e){n.error(`Error from getCheckSessionIframe:`,e instanceof Error?e.message:e)}},this._stop=()=>{let e=this._logger.create(`_stop`);if(this._sub=void 0,this._checkSessionIFrame&&this._checkSessionIFrame.stop(),this._userManager.settings.monitorAnonymousSession){let t=setInterval(async()=>{clearInterval(t);try{let e=await this._userManager.querySessionStatus();if(e){let t={session_state:e.session_state,profile:e.sub?{sub:e.sub}:null};this._start(t)}}catch(t){e.error(`error from querySessionStatus`,t instanceof Error?t.message:t)}},1e3)}},this._callback=async()=>{let e=this._logger.create(`_callback`);try{let t=await this._userManager.querySessionStatus(),n=!0;t&&this._checkSessionIFrame?t.sub===this._sub?(n=!1,this._checkSessionIFrame.start(t.session_state),e.debug(`same sub still logged in at OP, session state has changed, restarting check session iframe; session_state`,t.session_state),await this._userManager.events._raiseUserSessionChanged()):e.debug(`different subject signed into OP`,t.sub):e.debug(`subject no longer signed into OP`),n?this._sub?await this._userManager.events._raiseUserSignedOut():await this._userManager.events._raiseUserSignedIn():e.debug(`no change in session detected, no event to raise`)}catch(t){this._sub&&(e.debug(`Error calling queryCurrentSigninSession; raising signed out event`,t),await this._userManager.events._raiseUserSignedOut())}},e||this._logger.throw(Error(`No user manager passed`)),this._userManager.events.addUserLoaded(this._start),this._userManager.events.addUserUnloaded(this._stop),this._init().catch(e=>{this._logger.error(e)})}async _init(){this._logger.create(`_init`);let e=await this._userManager.getUser();if(e)this._start(e);else if(this._userManager.settings.monitorAnonymousSession){let e=await this._userManager.querySessionStatus();if(e){let t={session_state:e.session_state,profile:e.sub?{sub:e.sub}:null};this._start(t)}}}},fS=class e{constructor(e){this.id_token=e.id_token,this.session_state=e.session_state??null,this.access_token=e.access_token,this.refresh_token=e.refresh_token,this.token_type=e.token_type,this.scope=e.scope,this.profile=e.profile,this.expires_at=e.expires_at,this.state=e.userState,this.url_state=e.url_state}get expires_in(){if(this.expires_at!==void 0)return this.expires_at-Mx.getEpochTime()}set expires_in(e){e!==void 0&&(this.expires_at=Math.floor(e)+Mx.getEpochTime())}get expired(){let e=this.expires_in;if(e!==void 0)return e<=0}get scopes(){return this.scope?.split(` `)??[]}toStorageString(){return new wx(`User`).create(`toStorageString`),JSON.stringify({id_token:this.id_token,session_state:this.session_state,access_token:this.access_token,refresh_token:this.refresh_token,token_type:this.token_type,scope:this.scope,profile:this.profile,expires_at:this.expires_at})}static fromStorageString(t){return wx.createStatic(`User`,`fromStorageString`),new e(JSON.parse(t))}},pS=`oidc-client`,mS=class{constructor(){this._abort=new Ax(`Window navigation aborted`),this._disposeHandlers=new Set,this._window=null}async navigate(e){let t=this._logger.create(`navigate`);if(!this._window)throw Error(`Attempted to navigate on a disposed window`);t.debug(`setting URL in window`),this._window.location.replace(e.url);let{url:n,keepOpen:r}=await new Promise((n,r)=>{let i=i=>{let a=i.data,o=e.scriptOrigin??window.location.origin;if(!(i.origin!==o||a?.source!==pS)){try{let n=Nx.readParams(a.url,e.response_mode).get(`state`);if(n||t.warn(`no state found in response url`),i.source!==this._window&&n!==e.state)return}catch{this._dispose(),r(Error(`Invalid response from window`))}n(a)}};window.addEventListener(`message`,i,!1),this._disposeHandlers.add(()=>window.removeEventListener(`message`,i,!1));let a=new BroadcastChannel(`oidc-client-popup-${e.state}`);a.addEventListener(`message`,i,!1),this._disposeHandlers.add(()=>a.close()),this._disposeHandlers.add(this._abort.addHandler(e=>{this._dispose(),r(e)}))});return t.debug(`got response from window`),this._dispose(),r||this.close(),{url:n}}_dispose(){this._logger.create(`_dispose`);for(let e of this._disposeHandlers)e();this._disposeHandlers.clear()}static _notifyParent(e,t,n=!1,r=window.location.origin){let i={source:pS,url:t,keepOpen:n},a=new wx(`_notifyParent`);if(e)a.debug(`With parent. Using parent.postMessage.`),e.postMessage(i,r);else{a.debug(`No parent. Using BroadcastChannel.`);let e=new URL(t).searchParams.get(`state`);if(!e)throw Error(`No parent and no state in URL. Can't complete notification.`);let n=new BroadcastChannel(`oidc-client-popup-${e}`);n.postMessage(i),n.close()}}},hS={location:!1,toolbar:!1,height:640,closePopupWindowAfterInSeconds:-1},gS=`_blank`,_S=60,vS=2,yS=10,bS=class extends Jx{constructor(e){let{popup_redirect_uri:t=e.redirect_uri,popup_post_logout_redirect_uri:n=e.post_logout_redirect_uri,popupWindowFeatures:r=hS,popupWindowTarget:i=gS,redirectMethod:a=`assign`,redirectTarget:o=`self`,iframeNotifyParentOrigin:s=e.iframeNotifyParentOrigin,iframeScriptOrigin:c=e.iframeScriptOrigin,requestTimeoutInSeconds:l,silent_redirect_uri:u=e.redirect_uri,silentRequestTimeoutInSeconds:d,automaticSilentRenew:f=!0,validateSubOnSilentRenew:p=!0,includeIdTokenInSilentRenew:m=!1,monitorSession:h=!1,monitorAnonymousSession:g=!1,checkSessionIntervalInSeconds:_=vS,query_status_response_type:v=`code`,stopCheckSessionOnError:y=!0,revokeTokenTypes:b=[`access_token`,`refresh_token`],revokeTokensOnSignout:x=!1,includeIdTokenInSilentSignout:S=!1,accessTokenExpiringNotificationTimeInSeconds:C=_S,userStore:w}=e;super(e),this.popup_redirect_uri=t,this.popup_post_logout_redirect_uri=n,this.popupWindowFeatures=r,this.popupWindowTarget=i,this.redirectMethod=a,this.redirectTarget=o,this.iframeNotifyParentOrigin=s,this.iframeScriptOrigin=c,this.silent_redirect_uri=u,this.silentRequestTimeoutInSeconds=d||l||yS,this.automaticSilentRenew=f,this.validateSubOnSilentRenew=p,this.includeIdTokenInSilentRenew=m,this.monitorSession=h,this.monitorAnonymousSession=g,this.checkSessionIntervalInSeconds=_,this.stopCheckSessionOnError=y,this.query_status_response_type=v,this.revokeTokenTypes=b,this.revokeTokensOnSignout=x,this.includeIdTokenInSilentSignout=S,this.accessTokenExpiringNotificationTimeInSeconds=C,w?this.userStore=w:this.userStore=new Ux({store:typeof window<`u`?window.sessionStorage:new zx})}},xS=class e extends mS{constructor({silentRequestTimeoutInSeconds:t=yS}){super(),this._logger=new wx(`IFrameWindow`),this._timeoutInSeconds=t,this._frame=e.createHiddenIframe(),this._window=this._frame.contentWindow}static createHiddenIframe(){let e=window.document.createElement(`iframe`);return e.style.visibility=`hidden`,e.style.position=`fixed`,e.style.left=`-1000px`,e.style.top=`0`,e.width=`0`,e.height=`0`,window.document.body.appendChild(e),e}async navigate(e){this._logger.debug(`navigate: Using timeout of:`,this._timeoutInSeconds);let t=setTimeout(()=>void this._abort.raise(new Ix(`IFrame timed out without a response`)),this._timeoutInSeconds*1e3);return this._disposeHandlers.add(()=>clearTimeout(t)),await super.navigate(e)}close(){var e;this._frame&&=(this._frame.parentNode&&(this._frame.addEventListener(`load`,e=>{var t;let n=e.target;(t=n.parentNode)==null||t.removeChild(n),this._abort.raise(Error(`IFrame removed from DOM`))},!0),(e=this._frame.contentWindow)==null||e.location.replace(`about:blank`)),null),this._window=null}static notifyParent(e,t){return super._notifyParent(window.parent,e,!1,t)}},SS=class{constructor(e){this._settings=e,this._logger=new wx(`IFrameNavigator`)}async prepare({silentRequestTimeoutInSeconds:e=this._settings.silentRequestTimeoutInSeconds}){return new xS({silentRequestTimeoutInSeconds:e})}async callback(e){this._logger.create(`callback`),xS.notifyParent(e,this._settings.iframeNotifyParentOrigin)}},CS=500,wS=1e3,TS=class extends mS{constructor({popupWindowTarget:e=gS,popupWindowFeatures:t={},popupSignal:n,popupAbortOnClose:r}){super(),this._logger=new wx(`PopupWindow`);let i=jx.center({...hS,...t});this._window=window.open(void 0,e,jx.serialize(i)),this.abortOnClose=!!r,n&&n.addEventListener(`abort`,()=>{this._abort.raise(Error(n.reason??`Popup aborted`))}),t.closePopupWindowAfterInSeconds&&t.closePopupWindowAfterInSeconds>0&&setTimeout(()=>{if(!this._window||typeof this._window.closed!=`boolean`||this._window.closed){this._abort.raise(Error(`Popup blocked by user`));return}this.close()},t.closePopupWindowAfterInSeconds*wS)}async navigate(e){var t;(t=this._window)==null||t.focus();let n=setInterval(()=>{(!this._window||this._window.closed)&&(this._logger.debug(`Popup closed by user or isolated by redirect`),r(),this._disposeHandlers.delete(r),this.abortOnClose&&this._abort.raise(Error(`Popup closed by user`)))},CS),r=()=>clearInterval(n);return this._disposeHandlers.add(r),await super.navigate(e)}close(){this._window&&(this._window.closed||(this._window.close(),this._abort.raise(Error(`Popup closed`)))),this._window=null}static notifyOpener(e,t){super._notifyParent(window.opener,e,t),!t&&!window.opener&&window.close()}},ES=class{constructor(e){this._settings=e,this._logger=new wx(`PopupNavigator`)}async prepare({popupWindowFeatures:e=this._settings.popupWindowFeatures,popupWindowTarget:t=this._settings.popupWindowTarget,popupSignal:n,popupAbortOnClose:r}){return new TS({popupWindowFeatures:e,popupWindowTarget:t,popupSignal:n,popupAbortOnClose:r})}async callback(e,{keepOpen:t=!1}){this._logger.create(`callback`),TS.notifyOpener(e,t)}},DS=class{constructor(e){this._settings=e,this._logger=new wx(`RedirectNavigator`)}async prepare({redirectMethod:e=this._settings.redirectMethod,redirectTarget:t=this._settings.redirectTarget}){this._logger.create(`prepare`);let n=window.self;t===`top`&&(n=window.top??window.self);let r=n.location[e].bind(n.location),i;return{navigate:async e=>(this._logger.create(`navigate`),await new Promise((t,n)=>{i=n,window.addEventListener(`pageshow`,()=>t(window.location.href)),r(e.url)})),close:()=>{this._logger.create(`close`),i?.(Error(`Redirect aborted`)),n.stop()}}}async callback(){}},OS=class extends Lx{constructor(e){super({expiringNotificationTimeInSeconds:e.accessTokenExpiringNotificationTimeInSeconds}),this._logger=new wx(`UserManagerEvents`),this._userLoaded=new Ax(`User loaded`),this._userUnloaded=new Ax(`User unloaded`),this._silentRenewError=new Ax(`Silent renew error`),this._userSignedIn=new Ax(`User signed in`),this._userSignedOut=new Ax(`User signed out`),this._userSessionChanged=new Ax(`User session changed`)}async load(e,t=!0){await super.load(e),t&&await this._userLoaded.raise(e)}async unload(){await super.unload(),await this._userUnloaded.raise()}addUserLoaded(e){return this._userLoaded.addHandler(e)}removeUserLoaded(e){return this._userLoaded.removeHandler(e)}addUserUnloaded(e){return this._userUnloaded.addHandler(e)}removeUserUnloaded(e){return this._userUnloaded.removeHandler(e)}addSilentRenewError(e){return this._silentRenewError.addHandler(e)}removeSilentRenewError(e){return this._silentRenewError.removeHandler(e)}async _raiseSilentRenewError(e){await this._silentRenewError.raise(e)}addUserSignedIn(e){return this._userSignedIn.addHandler(e)}removeUserSignedIn(e){this._userSignedIn.removeHandler(e)}async _raiseUserSignedIn(){await this._userSignedIn.raise()}addUserSignedOut(e){return this._userSignedOut.addHandler(e)}removeUserSignedOut(e){this._userSignedOut.removeHandler(e)}async _raiseUserSignedOut(){await this._userSignedOut.raise()}addUserSessionChanged(e){return this._userSessionChanged.addHandler(e)}removeUserSessionChanged(e){this._userSessionChanged.removeHandler(e)}async _raiseUserSessionChanged(){await this._userSessionChanged.raise()}},kS=class{constructor(e){this._userManager=e,this._logger=new wx(`SilentRenewService`),this._isStarted=!1,this._retryTimer=new Mx(`Retry Silent Renew`),this._tokenExpiring=async()=>{let e=this._logger.create(`_tokenExpiring`);try{await this._userManager.signinSilent(),e.debug(`silent token renewal successful`)}catch(t){if(t instanceof Ix){e.warn(`ErrorTimeout from signinSilent:`,t,`retry in 5s`),this._retryTimer.init(5);return}e.error(`Error from signinSilent:`,t),await this._userManager.events._raiseSilentRenewError(t)}}}async start(){let e=this._logger.create(`start`);if(!this._isStarted){this._isStarted=!0,this._userManager.events.addAccessTokenExpiring(this._tokenExpiring),this._retryTimer.addHandler(this._tokenExpiring);try{await this._userManager.getUser()}catch(t){e.error(`getUser error`,t)}}}stop(){this._isStarted&&=(this._retryTimer.cancel(),this._retryTimer.removeHandler(this._tokenExpiring),this._userManager.events.removeAccessTokenExpiring(this._tokenExpiring),!1)}},AS=class{constructor(e){this.refresh_token=e.refresh_token,this.id_token=e.id_token,this.session_state=e.session_state,this.scope=e.scope,this.profile=e.profile,this.data=e.state}},jS=class{constructor(e,t,n,r){this._logger=new wx(`UserManager`),this.settings=new bS(e),this._client=new uS(e),this._redirectNavigator=t??new DS(this.settings),this._popupNavigator=n??new ES(this.settings),this._iframeNavigator=r??new SS(this.settings),this._events=new OS(this.settings),this._silentRenewService=new kS(this),this.settings.automaticSilentRenew&&this.startSilentRenew(),this._sessionMonitor=null,this.settings.monitorSession&&(this._sessionMonitor=new dS(this))}get events(){return this._events}get metadataService(){return this._client.metadataService}async getUser(e=!1){let t=this._logger.create(`getUser`),n=await this._loadUser();return n?(t.info(`user loaded`),await this._events.load(n,e),n):(t.info(`user not found in storage`),null)}async removeUser(){let e=this._logger.create(`removeUser`);await this.storeUser(null),e.info(`user removed from storage`),await this._events.unload()}async signinRedirect(e={}){this._logger.create(`signinRedirect`);let{redirectMethod:t,...n}=e,r;this.settings.dpop?.bind_authorization_code&&(r=await this.generateDPoPJkt(this.settings.dpop));let i=await this._redirectNavigator.prepare({redirectMethod:t});await this._signinStart({request_type:`si:r`,dpopJkt:r,...n},i)}async signinRedirectCallback(e=window.location.href){let t=this._logger.create(`signinRedirectCallback`),n=await this._signinEnd(e);return n.profile&&n.profile.sub?t.info(`success, signed in subject`,n.profile.sub):t.info(`no subject`),n}async signinResourceOwnerCredentials({username:e,password:t,skipUserInfo:n=!1}){let r=this._logger.create(`signinResourceOwnerCredential`),i=await this._client.processResourceOwnerPasswordCredentials({username:e,password:t,skipUserInfo:n,extraTokenParams:this.settings.extraTokenParams});r.debug(`got signin response`);let a=await this._buildUser(i);return a.profile&&a.profile.sub?r.info(`success, signed in subject`,a.profile.sub):r.info(`no subject`),a}async signinPopup(e={}){let t=this._logger.create(`signinPopup`),n;this.settings.dpop?.bind_authorization_code&&(n=await this.generateDPoPJkt(this.settings.dpop));let{popupWindowFeatures:r,popupWindowTarget:i,popupSignal:a,popupAbortOnClose:o,...s}=e,c=this.settings.popup_redirect_uri;c||t.throw(Error(`No popup_redirect_uri configured`));let l=await this._popupNavigator.prepare({popupWindowFeatures:r,popupWindowTarget:i,popupSignal:a,popupAbortOnClose:o}),u=await this._signin({request_type:`si:p`,redirect_uri:c,display:`popup`,dpopJkt:n,...s},l);return u&&(u.profile&&u.profile.sub?t.info(`success, signed in subject`,u.profile.sub):t.info(`no subject`)),u}async signinPopupCallback(e=window.location.href,t=!1){let n=this._logger.create(`signinPopupCallback`);await this._popupNavigator.callback(e,{keepOpen:t}),n.info(`success`)}async signinSilent(e={}){let t=this._logger.create(`signinSilent`),{silentRequestTimeoutInSeconds:n,...r}=e,i=await this._loadUser();if(!e.forceIframeAuth&&i?.refresh_token){t.debug(`using refresh token`);let e=new AS(i);return await this._useRefreshToken({state:e,redirect_uri:r.redirect_uri,resource:r.resource,extraTokenParams:r.extraTokenParams,timeoutInSeconds:n})}let a;this.settings.dpop?.bind_authorization_code&&(a=await this.generateDPoPJkt(this.settings.dpop));let o=this.settings.silent_redirect_uri;o||t.throw(Error(`No silent_redirect_uri configured`));let s;i&&this.settings.validateSubOnSilentRenew&&(t.debug(`subject prior to silent renew:`,i.profile.sub),s=i.profile.sub);let c=await this._iframeNavigator.prepare({silentRequestTimeoutInSeconds:n});return i=await this._signin({request_type:`si:s`,redirect_uri:o,prompt:`none`,id_token_hint:this.settings.includeIdTokenInSilentRenew?i?.id_token:void 0,dpopJkt:a,...r},c,s),i&&(i.profile?.sub?t.info(`success, signed in subject`,i.profile.sub):t.info(`no subject`)),i}async _useRefreshToken(e){let t=await this._client.useRefreshToken({timeoutInSeconds:this.settings.silentRequestTimeoutInSeconds,...e}),n=new fS({...e.state,...t});return await this.storeUser(n),await this._events.load(n),n}async signinSilentCallback(e=window.location.href){let t=this._logger.create(`signinSilentCallback`);await this._iframeNavigator.callback(e),t.info(`success`)}async signinCallback(e=window.location.href){let{state:t}=await this._client.readSigninResponseState(e);switch(t.request_type){case`si:r`:return await this.signinRedirectCallback(e);case`si:p`:await this.signinPopupCallback(e);break;case`si:s`:await this.signinSilentCallback(e);break;default:throw Error(`invalid response_type in state`)}}async signoutCallback(e=window.location.href,t=!1){let{state:n}=await this._client.readSignoutResponseState(e);if(n)switch(n.request_type){case`so:r`:return await this.signoutRedirectCallback(e);case`so:p`:await this.signoutPopupCallback(e,t);break;case`so:s`:await this.signoutSilentCallback(e);break;default:throw Error(`invalid response_type in state`)}}async querySessionStatus(e={}){let t=this._logger.create(`querySessionStatus`),{silentRequestTimeoutInSeconds:n,...r}=e,i=this.settings.silent_redirect_uri;i||t.throw(Error(`No silent_redirect_uri configured`));let a=await this._loadUser(),o=await this._iframeNavigator.prepare({silentRequestTimeoutInSeconds:n}),s=await this._signinStart({request_type:`si:s`,redirect_uri:i,prompt:`none`,id_token_hint:this.settings.includeIdTokenInSilentRenew?a?.id_token:void 0,response_type:this.settings.query_status_response_type,scope:`openid`,skipUserInfo:!0,...r},o);try{let e=await this._client.processSigninResponse(s.url,{});return t.debug(`got signin response`),e.session_state&&e.profile.sub?(t.info(`success for subject`,e.profile.sub),{session_state:e.session_state,sub:e.profile.sub}):(t.info(`success, user not authenticated`),null)}catch(e){if(this.settings.monitorAnonymousSession&&e instanceof Fx)switch(e.error){case`login_required`:case`consent_required`:case`interaction_required`:case`account_selection_required`:return t.info(`success for anonymous user`),{session_state:e.session_state}}throw e}}async _signin(e,t,n){let r=await this._signinStart(e,t);return await this._signinEnd(r.url,n)}async _signinStart(e,t){let n=this._logger.create(`_signinStart`);try{let r=await this._client.createSigninRequest(e);return n.debug(`got signin request`),await t.navigate({url:r.url,state:r.state.id,response_mode:r.state.response_mode,scriptOrigin:this.settings.iframeScriptOrigin})}catch(e){throw n.debug(`error after preparing navigator, closing navigator window`),t.close(),e}}async _signinEnd(e,t){let n=this._logger.create(`_signinEnd`),r=await this._client.processSigninResponse(e,{});return n.debug(`got signin response`),await this._buildUser(r,t)}async _buildUser(e,t){let n=this._logger.create(`_buildUser`),r=new fS(e);if(t){if(t!==r.profile.sub)throw n.debug(`current user does not match user returned from signin. sub from signin:`,r.profile.sub),new Fx({...e,error:`login_required`});n.debug(`current user matches user returned from signin`)}return await this.storeUser(r),n.debug(`user stored`),await this._events.load(r),r}async signoutRedirect(e={}){let t=this._logger.create(`signoutRedirect`),{redirectMethod:n,...r}=e,i=await this._redirectNavigator.prepare({redirectMethod:n});await this._signoutStart({request_type:`so:r`,post_logout_redirect_uri:this.settings.post_logout_redirect_uri,...r},i),t.info(`success`)}async signoutRedirectCallback(e=window.location.href){let t=this._logger.create(`signoutRedirectCallback`),n=await this._signoutEnd(e);return t.info(`success`),n}async signoutPopup(e={}){let t=this._logger.create(`signoutPopup`),{popupWindowFeatures:n,popupWindowTarget:r,popupSignal:i,...a}=e,o=this.settings.popup_post_logout_redirect_uri,s=await this._popupNavigator.prepare({popupWindowFeatures:n,popupWindowTarget:r,popupSignal:i});await this._signout({request_type:`so:p`,post_logout_redirect_uri:o,state:o==null?void 0:{},...a},s),t.info(`success`)}async signoutPopupCallback(e=window.location.href,t=!1){let n=this._logger.create(`signoutPopupCallback`);await this._popupNavigator.callback(e,{keepOpen:t}),n.info(`success`)}async _signout(e,t){let n=await this._signoutStart(e,t);return await this._signoutEnd(n.url)}async _signoutStart(e={},t){let n=this._logger.create(`_signoutStart`);try{let r=await this._loadUser();n.debug(`loaded current user from storage`),this.settings.revokeTokensOnSignout&&await this._revokeInternal(r);let i=e.id_token_hint||r&&r.id_token;i&&(n.debug(`setting id_token_hint in signout request`),e.id_token_hint=i),await this.removeUser(),n.debug(`user removed, creating signout request`);let a=await this._client.createSignoutRequest(e);return n.debug(`got signout request`),await t.navigate({url:a.url,state:a.state?.id,scriptOrigin:this.settings.iframeScriptOrigin})}catch(e){throw n.debug(`error after preparing navigator, closing navigator window`),t.close(),e}}async _signoutEnd(e){let t=this._logger.create(`_signoutEnd`),n=await this._client.processSignoutResponse(e);return t.debug(`got signout response`),n}async signoutSilent(e={}){let t=this._logger.create(`signoutSilent`),{silentRequestTimeoutInSeconds:n,...r}=e,i=this.settings.includeIdTokenInSilentSignout?(await this._loadUser())?.id_token:void 0,a=this.settings.popup_post_logout_redirect_uri,o=await this._iframeNavigator.prepare({silentRequestTimeoutInSeconds:n});await this._signout({request_type:`so:s`,post_logout_redirect_uri:a,id_token_hint:i,...r},o),t.info(`success`)}async signoutSilentCallback(e=window.location.href){let t=this._logger.create(`signoutSilentCallback`);await this._iframeNavigator.callback(e),t.info(`success`)}async revokeTokens(e){let t=await this._loadUser();await this._revokeInternal(t,e)}async _revokeInternal(e,t=this.settings.revokeTokenTypes){let n=this._logger.create(`_revokeInternal`);if(!e)return;let r=t.filter(t=>typeof e[t]==`string`);if(!r.length){n.debug(`no need to revoke due to no token(s)`);return}for(let t of r)await this._client.revokeToken(e[t],t),n.info(`${t} revoked successfully`),t!==`access_token`&&(e[t]=null);await this.storeUser(e),n.debug(`user stored`),await this._events.load(e)}startSilentRenew(){this._logger.create(`startSilentRenew`),this._silentRenewService.start()}stopSilentRenew(){this._silentRenewService.stop()}get _userStoreKey(){return`user:${this.settings.authority}:${this.settings.client_id}`}async _loadUser(){let e=this._logger.create(`_loadUser`),t=await this.settings.userStore.get(this._userStoreKey);return t?(e.debug(`user storageString loaded`),fS.fromStorageString(t)):(e.debug(`no user storageString`),null)}async storeUser(e){let t=this._logger.create(`storeUser`);if(e){t.debug(`storing user`);let n=e.toStorageString();await this.settings.userStore.set(this._userStoreKey,n)}else this._logger.debug(`removing user`),await this.settings.userStore.remove(this._userStoreKey),this.settings.dpop&&await this.settings.dpop.store.remove(this.settings.client_id)}async clearStaleState(){await this._client.clearStaleState()}async dpopProof(e,t,n,r){let i=await(this.settings.dpop?.store)?.get(this.settings.client_id);if(i)return await kx.generateDPoPProof({url:e,accessToken:t?.access_token,httpMethod:n,keyPair:i.keys,nonce:r})}async generateDPoPJkt(e){let t=await e.store.get(this.settings.client_id);return t||(t=new lS(await kx.generateDPoPKeys()),await e.store.set(this.settings.client_id,t)),await kx.generateDPoPJkt(t.keys)}},MS=m.createContext(void 0);MS.displayName=`AuthContext`;var NS={isLoading:!0,isAuthenticated:!1},PS=(e,t)=>{switch(t.type){case`INITIALISED`:case`USER_LOADED`:return{...e,user:t.user,isLoading:!1,isAuthenticated:t.user?!t.user.expired:!1,error:void 0};case`USER_SIGNED_OUT`:case`USER_UNLOADED`:return{...e,user:void 0,isAuthenticated:!1};case`NAVIGATOR_INIT`:return{...e,isLoading:!0,activeNavigator:t.method};case`NAVIGATOR_CLOSE`:return{...e,isLoading:!1,activeNavigator:void 0};case`ERROR`:{let n=t.error;return n.toString=()=>`${n.name}: ${n.message}`,{...e,isLoading:!1,error:n}}default:{let n=TypeError(`unknown type ${t.type}`),r={name:n.name,message:n.message,innerError:n,stack:n.stack,source:`unknown`};return r.toString=()=>`${r.name}: ${r.message}`,{...e,isLoading:!1,error:r}}}},FS=(e=window.location)=>{let t=new URLSearchParams(e.search);return!!((t.get(`code`)||t.get(`error`))&&t.get(`state`)||(t=new URLSearchParams(e.hash.replace(`#`,`?`)),(t.get(`code`)||t.get(`error`))&&t.get(`state`)))},IS=BS(`signinCallback`,`Sign-in failed`),LS=BS(`signoutCallback`,`Sign-out failed`),RS=BS(`renewSilent`,`Renew silent failed`);function zS(e,t){return{name:VS(e,`name`,()=>`Error`),message:VS(e,`message`,()=>t),stack:VS(e,`stack`,()=>Error().stack),innerError:e}}function BS(e,t){return n=>({...zS(n,t),source:e})}function VS(e,t,n){if(e&&typeof e==`object`){let n=e[t];if(typeof n==`string`)return n}return n()}var HS=[`clearStaleState`,`querySessionStatus`,`revokeTokens`,`startSilentRenew`,`stopSilentRenew`],US=[`signinPopup`,`signinSilent`,`signinRedirect`,`signinResourceOwnerCredentials`,`signoutPopup`,`signoutRedirect`,`signoutSilent`],WS=e=>()=>{throw Error(`UserManager#${e} was called from an unsupported context. If this is a server-rendered page, defer this call with useEffect() or pass a custom UserManager implementation.`)},GS=typeof window>`u`?null:jS,KS=e=>{let{children:t,onSigninCallback:n,skipSigninCallback:r,matchSignoutCallback:i,onSignoutCallback:a,onRemoveUser:o,userManager:s=null,...c}=e,[l]=m.useState(()=>s??(GS?new GS(c):{settings:c})),[u,d]=m.useReducer(PS,NS),f=m.useMemo(()=>Object.assign({settings:l.settings,events:l.events},Object.fromEntries(HS.map(e=>[e,l[e]?.bind(l)??WS(e)])),Object.fromEntries(US.map(e=>[e,l[e]?async t=>{d({type:`NAVIGATOR_INIT`,method:e});try{return await l[e](t)}catch(n){return d({type:`ERROR`,error:{...zS(n,`Unknown error while executing ${e}(...).`),source:e,args:t}}),null}finally{d({type:`NAVIGATOR_CLOSE`})}}:WS(e)]))),[l]),p=m.useRef(!1);m.useEffect(()=>{!l||p.current||(p.current=!0,(async()=>{try{let e=null;FS()&&!r&&(e=await l.signinCallback(),n&&await n(e)),e||=await l.getUser(),d({type:`INITIALISED`,user:e})}catch(e){d({type:`ERROR`,error:IS(e)})}try{if(i&&i(l.settings)){let e=await l.signoutCallback();a&&await a(e)}}catch(e){d({type:`ERROR`,error:LS(e)})}})())},[l,r,n,a,i]),m.useEffect(()=>{if(!l)return;let e=e=>{d({type:`USER_LOADED`,user:e})};l.events.addUserLoaded(e);let t=()=>{d({type:`USER_UNLOADED`})};l.events.addUserUnloaded(t);let n=()=>{d({type:`USER_SIGNED_OUT`})};l.events.addUserSignedOut(n);let r=e=>{d({type:`ERROR`,error:RS(e)})};return l.events.addSilentRenewError(r),()=>{l.events.removeUserLoaded(e),l.events.removeUserUnloaded(t),l.events.removeUserSignedOut(n),l.events.removeSilentRenewError(r)}},[l]);let h=m.useCallback(async()=>{await l.removeUser(),o&&await o()},[l,o]),g=m.useMemo(()=>({...u,...f,removeUser:h}),[u,f,h]);return m.createElement(MS.Provider,{value:g},t)},qS=()=>{let e=m.useContext(MS);return e||console.warn(`AuthProvider context is undefined, please verify you are calling useAuth() as child of a component.`),e},JS=`modulepreload`,YS=function(e){return`/`+e},XS={},ZS=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}r=o(t.map(t=>{if(t=YS(t,n),t in XS)return;XS[t]=!0;let r=t.endsWith(`.css`),i=r?`[rel="stylesheet"]`:``;if(n)for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}else if(document.querySelector(`link[href="${t}"]${i}`))return;let o=document.createElement(`link`);if(o.rel=r?`stylesheet`:JS,r||(o.as=`script`),o.crossOrigin=``,o.href=t,a&&o.setAttribute(`nonce`,a),document.head.appendChild(o),r)return new Promise((e,n)=>{o.addEventListener(`load`,e),o.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},QS=`popstate`;function $S(e={}){function t(e,t){let{pathname:n,search:r,hash:i}=e.location;return iC(``,{pathname:n,search:r,hash:i},t.state&&t.state.usr||null,t.state&&t.state.key||`default`)}function n(e,t){return typeof t==`string`?t:aC(t)}return sC(t,n,null,e)}function eC(e,t){if(e===!1||e==null)throw Error(t)}function tC(e,t){if(!e){typeof console<`u`&&console.warn(t);try{throw Error(t)}catch{}}}function nC(){return Math.random().toString(36).substring(2,10)}function rC(e,t){return{usr:e.state,key:e.key,idx:t}}function iC(e,t,n=null,r){return{pathname:typeof e==`string`?e:e.pathname,search:``,hash:``,...typeof t==`string`?oC(t):t,state:n,key:t&&t.key||r||nC()}}function aC({pathname:e=`/`,search:t=``,hash:n=``}){return t&&t!==`?`&&(e+=t.charAt(0)===`?`?t:`?`+t),n&&n!==`#`&&(e+=n.charAt(0)===`#`?n:`#`+n),e}function oC(e){let t={};if(e){let n=e.indexOf(`#`);n>=0&&(t.hash=e.substring(n),e=e.substring(0,n));let r=e.indexOf(`?`);r>=0&&(t.search=e.substring(r),e=e.substring(0,r)),e&&(t.pathname=e)}return t}function sC(e,t,n,r={}){let{window:i=document.defaultView,v5Compat:a=!1}=r,o=i.history,s=`POP`,c=null,l=u();l??(l=0,o.replaceState({...o.state,idx:l},``));function u(){return(o.state||{idx:null}).idx}function d(){s=`POP`;let e=u(),t=e==null?null:e-l;l=e,c&&c({action:s,location:h.location,delta:t})}function f(e,t){s=`PUSH`;let r=iC(h.location,e,t);n&&n(r,e),l=u()+1;let d=rC(r,l),f=h.createHref(r);try{o.pushState(d,``,f)}catch(e){if(e instanceof DOMException&&e.name===`DataCloneError`)throw e;i.location.assign(f)}a&&c&&c({action:s,location:h.location,delta:1})}function p(e,t){s=`REPLACE`;let r=iC(h.location,e,t);n&&n(r,e),l=u();let i=rC(r,l),d=h.createHref(r);o.replaceState(i,``,d),a&&c&&c({action:s,location:h.location,delta:0})}function m(e){return cC(e)}let h={get action(){return s},get location(){return e(i,o)},listen(e){if(c)throw Error(`A history only accepts one active listener`);return i.addEventListener(QS,d),c=e,()=>{i.removeEventListener(QS,d),c=null}},createHref(e){return t(i,e)},createURL:m,encodeLocation(e){let t=m(e);return{pathname:t.pathname,search:t.search,hash:t.hash}},push:f,replace:p,go(e){return o.go(e)}};return h}function cC(e,t=!1){let n=`http://localhost`;typeof window<`u`&&(n=window.location.origin===`null`?window.location.href:window.location.origin),eC(n,`No window.location.(origin|href) available to create URL`);let r=typeof e==`string`?e:aC(e);return r=r.replace(/ $/,`%20`),!t&&r.startsWith(`//`)&&(r=n+r),new URL(r,n)}function lC(e,t,n=`/`){return uC(e,t,n,!1)}function uC(e,t,n,r){let i=OC((typeof t==`string`?oC(t):t).pathname||`/`,n);if(i==null)return null;let a=fC(e);mC(a);let o=null;for(let e=0;o==null&&e{let c={relativePath:s===void 0?e.path||``:s,caseSensitive:e.caseSensitive===!0,childrenIndex:a,route:e};if(c.relativePath.startsWith(`/`)){if(!c.relativePath.startsWith(r)&&o)return;eC(c.relativePath.startsWith(r),`Absolute route path "${c.relativePath}" nested under path "${r}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),c.relativePath=c.relativePath.slice(r.length)}let l=LC([r,c.relativePath]),u=n.concat(c);e.children&&e.children.length>0&&(eC(e.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${l}".`),fC(e.children,t,u,l,o)),!(e.path==null&&!e.index)&&t.push({path:l,score:SC(l,e.index),routesMeta:u})};return e.forEach((e,t)=>{if(e.path===``||!e.path?.includes(`?`))a(e,t);else for(let n of pC(e.path))a(e,t,!0,n)}),t}function pC(e){let t=e.split(`/`);if(t.length===0)return[];let[n,...r]=t,i=n.endsWith(`?`),a=n.replace(/\?$/,``);if(r.length===0)return i?[a,``]:[a];let o=pC(r.join(`/`)),s=[];return s.push(...o.map(e=>e===``?a:[a,e].join(`/`))),i&&s.push(...o),s.map(t=>e.startsWith(`/`)&&t===``?`/`:t)}function mC(e){e.sort((e,t)=>e.score===t.score?CC(e.routesMeta.map(e=>e.childrenIndex),t.routesMeta.map(e=>e.childrenIndex)):t.score-e.score)}var hC=/^:[\w-]+$/,gC=3,_C=2,vC=1,yC=10,bC=-2,xC=e=>e===`*`;function SC(e,t){let n=e.split(`/`),r=n.length;return n.some(xC)&&(r+=bC),t&&(r+=_C),n.filter(e=>!xC(e)).reduce((e,t)=>e+(hC.test(t)?gC:t===``?vC:yC),r)}function CC(e,t){return e.length===t.length&&e.slice(0,-1).every((e,n)=>e===t[n])?e[e.length-1]-t[t.length-1]:0}function wC(e,t,n=!1){let{routesMeta:r}=e,i={},a=`/`,o=[];for(let e=0;e{if(t===`*`){let e=s[r]||``;o=a.slice(0,a.length-e.length).replace(/(.)\/+$/,`$1`)}let i=s[r];return n&&!i?e[t]=void 0:e[t]=(i||``).replace(/%2F/g,`/`),e},{}),pathname:a,pathnameBase:o,pattern:e}}function EC(e,t=!1,n=!0){tC(e===`*`||!e.endsWith(`*`)||e.endsWith(`/*`),`Route path "${e}" will be treated as if it were "${e.replace(/\*$/,`/*`)}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${e.replace(/\*$/,`/*`)}".`);let r=[],i=`^`+e.replace(/\/*\*?$/,``).replace(/^\/*/,`/`).replace(/[\\.*+^${}|()[\]]/g,`\\$&`).replace(/\/:([\w-]+)(\?)?/g,(e,t,n)=>(r.push({paramName:t,isOptional:n!=null}),n?`/?([^\\/]+)?`:`/([^\\/]+)`)).replace(/\/([\w-]+)\?(\/|$)/g,`(/$1)?$2`);return e.endsWith(`*`)?(r.push({paramName:`*`}),i+=e===`*`||e===`/*`?`(.*)$`:`(?:\\/(.+)|\\/*)$`):n?i+=`\\/*$`:e!==``&&e!==`/`&&(i+=`(?:(?=\\/|$))`),[new RegExp(i,t?void 0:`i`),r]}function DC(e){try{return e.split(`/`).map(e=>decodeURIComponent(e).replace(/\//g,`%2F`)).join(`/`)}catch(t){return tC(!1,`The URL path "${e}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${t}).`),e}}function OC(e,t){if(t===`/`)return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let n=t.endsWith(`/`)?t.length-1:t.length,r=e.charAt(n);return r&&r!==`/`?null:e.slice(n)||`/`}var kC=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,AC=e=>kC.test(e);function jC(e,t=`/`){let{pathname:n,search:r=``,hash:i=``}=typeof e==`string`?oC(e):e,a;if(n)if(AC(n))a=n;else{if(n.includes(`//`)){let e=n;n=n.replace(/\/\/+/g,`/`),tC(!1,`Pathnames cannot have embedded double slashes - normalizing ${e} -> ${n}`)}a=n.startsWith(`/`)?MC(n.substring(1),`/`):MC(n,t)}else a=t;return{pathname:a,search:zC(r),hash:BC(i)}}function MC(e,t){let n=t.replace(/\/+$/,``).split(`/`);return e.split(`/`).forEach(e=>{e===`..`?n.length>1&&n.pop():e!==`.`&&n.push(e)}),n.length>1?n.join(`/`):`/`}function NC(e,t,n,r){return`Cannot include a '${e}' character in a manually specified \`to.${t}\` field [${JSON.stringify(r)}]. Please separate it out to the \`to.${n}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function PC(e){return e.filter((e,t)=>t===0||e.route.path&&e.route.path.length>0)}function FC(e){let t=PC(e);return t.map((e,n)=>n===t.length-1?e.pathname:e.pathnameBase)}function IC(e,t,n,r=!1){let i;typeof e==`string`?i=oC(e):(i={...e},eC(!i.pathname||!i.pathname.includes(`?`),NC(`?`,`pathname`,`search`,i)),eC(!i.pathname||!i.pathname.includes(`#`),NC(`#`,`pathname`,`hash`,i)),eC(!i.search||!i.search.includes(`#`),NC(`#`,`search`,`hash`,i)));let a=e===``||i.pathname===``,o=a?`/`:i.pathname,s;if(o==null)s=n;else{let e=t.length-1;if(!r&&o.startsWith(`..`)){let t=o.split(`/`);for(;t[0]===`..`;)t.shift(),--e;i.pathname=t.join(`/`)}s=e>=0?t[e]:`/`}let c=jC(i,s),l=o&&o!==`/`&&o.endsWith(`/`),u=(a||o===`.`)&&n.endsWith(`/`);return!c.pathname.endsWith(`/`)&&(l||u)&&(c.pathname+=`/`),c}var LC=e=>e.join(`/`).replace(/\/\/+/g,`/`),RC=e=>e.replace(/\/+$/,``).replace(/^\/*/,`/`),zC=e=>!e||e===`?`?``:e.startsWith(`?`)?e:`?`+e,BC=e=>!e||e===`#`?``:e.startsWith(`#`)?e:`#`+e,VC=class{constructor(e,t,n,r=!1){this.status=e,this.statusText=t||``,this.internal=r,n instanceof Error?(this.data=n.toString(),this.error=n):this.data=n}};function HC(e){return e!=null&&typeof e.status==`number`&&typeof e.statusText==`string`&&typeof e.internal==`boolean`&&`data`in e}function UC(e){return e.map(e=>e.route.path).filter(Boolean).join(`/`).replace(/\/\/*/g,`/`)||`/`}var WC=typeof window<`u`&&window.document!==void 0&&window.document.createElement!==void 0;function GC(e,t){let n=e;if(typeof n!=`string`||!kC.test(n))return{absoluteURL:void 0,isExternal:!1,to:n};let r=n,i=!1;if(WC)try{let e=new URL(window.location.href),r=n.startsWith(`//`)?new URL(e.protocol+n):new URL(n),a=OC(r.pathname,t);r.origin===e.origin&&a!=null?n=a+r.search+r.hash:i=!0}catch{tC(!1,` contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}return{absoluteURL:r,isExternal:i,to:n}}Object.getOwnPropertyNames(Object.prototype).sort().join(`\0`);var KC=[`POST`,`PUT`,`PATCH`,`DELETE`];new Set(KC);var qC=[`GET`,...KC];new Set(qC);var JC=m.createContext(null);JC.displayName=`DataRouter`;var YC=m.createContext(null);YC.displayName=`DataRouterState`;var XC=m.createContext(!1),ZC=m.createContext({isTransitioning:!1});ZC.displayName=`ViewTransition`;var QC=m.createContext(new Map);QC.displayName=`Fetchers`;var $C=m.createContext(null);$C.displayName=`Await`;var ew=m.createContext(null);ew.displayName=`Navigation`;var tw=m.createContext(null);tw.displayName=`Location`;var nw=m.createContext({outlet:null,matches:[],isDataRoute:!1});nw.displayName=`Route`;var rw=m.createContext(null);rw.displayName=`RouteError`;var iw=`REACT_ROUTER_ERROR`,aw=`REDIRECT`,ow=`ROUTE_ERROR_RESPONSE`;function sw(e){if(e.startsWith(`${iw}:${aw}:{`))try{let t=JSON.parse(e.slice(28));if(typeof t==`object`&&t&&typeof t.status==`number`&&typeof t.statusText==`string`&&typeof t.location==`string`&&typeof t.reloadDocument==`boolean`&&typeof t.replace==`boolean`)return t}catch{}}function cw(e){if(e.startsWith(`${iw}:${ow}:{`))try{let t=JSON.parse(e.slice(40));if(typeof t==`object`&&t&&typeof t.status==`number`&&typeof t.statusText==`string`)return new VC(t.status,t.statusText,t.data)}catch{}}function lw(e,{relative:t}={}){eC(uw(),`useHref() may be used only in the context of a component.`);let{basename:n,navigator:r}=m.useContext(ew),{hash:i,pathname:a,search:o}=gw(e,{relative:t}),s=a;return n!==`/`&&(s=a===`/`?n:LC([n,a])),r.createHref({pathname:s,search:o,hash:i})}function uw(){return m.useContext(tw)!=null}function dw(){return eC(uw(),`useLocation() may be used only in the context of a component.`),m.useContext(tw).location}var fw=`You should call navigate() in a React.useEffect(), not when your component is first rendered.`;function pw(e){m.useContext(ew).static||m.useLayoutEffect(e)}function mw(){let{isDataRoute:e}=m.useContext(nw);return e?Fw():hw()}function hw(){eC(uw(),`useNavigate() may be used only in the context of a component.`);let e=m.useContext(JC),{basename:t,navigator:n}=m.useContext(ew),{matches:r}=m.useContext(nw),{pathname:i}=dw(),a=JSON.stringify(FC(r)),o=m.useRef(!1);return pw(()=>{o.current=!0}),m.useCallback((r,s={})=>{if(tC(o.current,fw),!o.current)return;if(typeof r==`number`){n.go(r);return}let c=IC(r,JSON.parse(a),i,s.relative===`path`);e==null&&t!==`/`&&(c.pathname=c.pathname===`/`?t:LC([t,c.pathname])),(s.replace?n.replace:n.push)(c,s.state,s)},[t,n,a,i,e])}m.createContext(null);function gw(e,{relative:t}={}){let{matches:n}=m.useContext(nw),{pathname:r}=dw(),i=JSON.stringify(FC(n));return m.useMemo(()=>IC(e,JSON.parse(i),r,t===`path`),[e,i,r,t])}function _w(e,t){return vw(e,t)}function vw(e,t,n,r,i){eC(uw(),`useRoutes() may be used only in the context of a component.`);let{navigator:a}=m.useContext(ew),{matches:o}=m.useContext(nw),s=o[o.length-1],c=s?s.params:{},l=s?s.pathname:`/`,u=s?s.pathnameBase:`/`,d=s&&s.route;{let e=d&&d.path||``;Lw(l,!d||e.endsWith(`*`)||e.endsWith(`*?`),`You rendered descendant (or called \`useRoutes()\`) at "${l}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. -Please change the parent to .`)}let f=tw(),p;if(t){let e=typeof t==`string`?XS(t):t;WS(u===`/`||e.pathname?.startsWith(u),`When overriding the location using \`\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${u}" but pathname "${e.pathname}" was given in the \`location\` prop.`),p=e}else p=f;let h=p.pathname||`/`,g=h;if(u!==`/`){let e=u.replace(/^\//,``).split(`/`);g=`/`+h.replace(/^\//,``).split(`/`).slice(e.length).join(`/`)}let _=$S(e,{pathname:g});GS(d||_!=null,`No routes matched location "${p.pathname}${p.search}${p.hash}" `),GS(_==null||_[_.length-1].route.element!==void 0||_[_.length-1].route.Component!==void 0||_[_.length-1].route.lazy!==void 0,`Matched leaf route at location "${p.pathname}${p.search}${p.hash}" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page.`);let v=hw(_&&_.map(e=>Object.assign({},e,{params:Object.assign({},c,e.params),pathname:DC([u,a.encodeLocation?a.encodeLocation(e.pathname.replace(/\?/g,`%3F`).replace(/#/g,`%23`)).pathname:e.pathname]),pathnameBase:e.pathnameBase===`/`?u:DC([u,a.encodeLocation?a.encodeLocation(e.pathnameBase.replace(/\?/g,`%3F`).replace(/#/g,`%23`)).pathname:e.pathnameBase])})),o,n,r,i);return t&&v?m.createElement(GC.Provider,{value:{location:{pathname:`/`,search:``,hash:``,state:null,key:`default`,...p},navigationType:`POP`}},v):v}function lw(){let e=ww(),t=MC(e)?`${e.status} ${e.statusText}`:e instanceof Error?e.message:JSON.stringify(e),n=e instanceof Error?e.stack:null,r=`rgba(200,200,200, 0.5)`,i={padding:`0.5rem`,backgroundColor:r},a={padding:`2px 4px`,backgroundColor:r},o=null;return console.error(`Error handled by React Router default ErrorBoundary:`,e),o=m.createElement(m.Fragment,null,m.createElement(`p`,null,`💿 Hey developer 👋`),m.createElement(`p`,null,`You can provide a way better UX than this when your app throws errors by providing your own `,m.createElement(`code`,{style:a},`ErrorBoundary`),` or`,` `,m.createElement(`code`,{style:a},`errorElement`),` prop on your route.`)),m.createElement(m.Fragment,null,m.createElement(`h2`,null,`Unexpected Application Error!`),m.createElement(`h3`,{style:{fontStyle:`italic`}},t),n?m.createElement(`pre`,{style:i},n):null,o)}var uw=m.createElement(lw,null),dw=class extends m.Component{constructor(e){super(e),this.state={location:e.location,revalidation:e.revalidation,error:e.error}}static getDerivedStateFromError(e){return{error:e}}static getDerivedStateFromProps(e,t){return t.location!==e.location||t.revalidation!==`idle`&&e.revalidation===`idle`?{error:e.error,location:e.location,revalidation:e.revalidation}:{error:e.error===void 0?t.error:e.error,location:t.location,revalidation:e.revalidation||t.revalidation}}componentDidCatch(e,t){this.props.onError?this.props.onError(e,t):console.error(`React Router caught the following error during render`,e)}render(){let e=this.state.error;if(this.context&&typeof e==`object`&&e&&`digest`in e&&typeof e.digest==`string`){let t=QC(e.digest);t&&(e=t)}let t=e===void 0?this.props.children:m.createElement(KC.Provider,{value:this.props.routeContext},m.createElement(qC.Provider,{value:e,children:this.props.component}));return this.context?m.createElement(pw,{error:e},t):t}};dw.contextType=BC;var fw=new WeakMap;function pw({children:e,error:t}){let{basename:n}=m.useContext(WC);if(typeof t==`object`&&t&&`digest`in t&&typeof t.digest==`string`){let e=ZC(t.digest);if(e){let r=fw.get(t);if(r)throw r;let i=FC(e.location,n);if(PC&&!fw.get(t))if(i.isExternal||e.reloadDocument)window.location.href=i.absoluteURL||i.to;else{let n=Promise.resolve().then(()=>window.__reactRouterDataRouter.navigate(i.to,{replace:e.replace}));throw fw.set(t,n),n}return m.createElement(`meta`,{httpEquiv:`refresh`,content:`0;url=${i.absoluteURL||i.to}`})}}return e}function mw({routeContext:e,match:t,children:n}){let r=m.useContext(RC);return r&&r.static&&r.staticContext&&(t.route.errorElement||t.route.ErrorBoundary)&&(r.staticContext._deepestRenderedBoundaryId=t.route.id),m.createElement(KC.Provider,{value:e},n)}function hw(e,t=[],n=null,r=null,i=null){if(e==null){if(!n)return null;if(n.errors)e=n.matches;else if(t.length===0&&!n.initialized&&n.matches.length>0)e=n.matches;else return null}let a=e,o=n?.errors;if(o!=null){let e=a.findIndex(e=>e.route.id&&o?.[e.route.id]!==void 0);WS(e>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(o).join(`,`)}`),a=a.slice(0,Math.min(a.length,e+1))}let s=!1,c=-1;if(n)for(let e=0;e=0?a.slice(0,c+1):[a[0]];break}}}let l=n&&r?(e,t)=>{r(e,{location:n.location,params:n.matches?.[0]?.params??{},unstable_pattern:NC(n.matches),errorInfo:t})}:void 0;return a.reduceRight((e,r,i)=>{let u,d=!1,f=null,p=null;n&&(u=o&&r.route.id?o[r.route.id]:void 0,f=r.route.errorElement||uw,s&&(c<0&&i===0?(Dw(`route-fallback`,!1,"No `HydrateFallback` element provided to render during initial hydration"),d=!0,p=null):c===i&&(d=!0,p=r.route.hydrateFallbackElement||null)));let h=t.concat(a.slice(0,i+1)),g=()=>{let t;return t=u?f:d?p:r.route.Component?m.createElement(r.route.Component,null):r.route.element?r.route.element:e,m.createElement(mw,{match:r,routeContext:{outlet:e,matches:h,isDataRoute:n!=null},children:t})};return n&&(r.route.ErrorBoundary||r.route.errorElement||i===0)?m.createElement(dw,{location:n.location,revalidation:n.revalidation,component:f,error:u,children:g(),routeContext:{outlet:null,matches:h,isDataRoute:!0},onError:l}):g()},null)}function gw(e){return`${e} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function _w(e){let t=m.useContext(RC);return WS(t,gw(e)),t}function vw(e){let t=m.useContext(zC);return WS(t,gw(e)),t}function yw(e){let t=m.useContext(KC);return WS(t,gw(e)),t}function bw(e){let t=yw(e),n=t.matches[t.matches.length-1];return WS(n.route.id,`${e} can only be used on routes that contain a unique "id"`),n.route.id}function xw(){return bw(`useRouteId`)}function Sw(){return vw(`useNavigation`).navigation}function Cw(){let{matches:e,loaderData:t}=vw(`useMatches`);return m.useMemo(()=>e.map(e=>tC(e,t)),[e,t])}function ww(){let e=m.useContext(qC),t=vw(`useRouteError`),n=bw(`useRouteError`);return e===void 0?t.errors?.[n]:e}function Tw(){let{router:e}=_w(`useNavigate`),t=bw(`useNavigate`),n=m.useRef(!1);return rw(()=>{n.current=!0}),m.useCallback(async(r,i={})=>{GS(n.current,nw),n.current&&(typeof r==`number`?await e.navigate(r):await e.navigate(r,{fromRouteId:t,...i}))},[e,t])}var Ew={};function Dw(e,t,n){!t&&!Ew[e]&&(Ew[e]=!0,GS(!1,n))}m.useOptimistic,m.memo(Ow);function Ow({routes:e,future:t,state:n,onError:r}){return cw(e,void 0,n,r,t)}function kw({to:e,replace:t,state:n,relative:r}){WS(ew(),` may be used only in the context of a component.`);let{static:i}=m.useContext(WC);GS(!i,` must not be used on the initial render in a . This is a no-op, but you should modify your code so the is only ever rendered in response to some user interaction or state change.`);let{matches:a}=m.useContext(KC),{pathname:o}=tw(),s=iw(),c=EC(e,TC(a),o,r===`path`),l=JSON.stringify(c);return m.useEffect(()=>{s(JSON.parse(l),{replace:t,state:n,relative:r})},[s,l,r,t,n]),null}function Aw(e){WS(!1,`A is only ever to be used as the child of element, never rendered directly. Please wrap your in a .`)}function jw({basename:e=`/`,children:t=null,location:n,navigationType:r=`POP`,navigator:i,static:a=!1,unstable_useTransitions:o}){WS(!ew(),`You cannot render a inside another . You should never have more than one in your app.`);let s=e.replace(/^\/*/,`/`),c=m.useMemo(()=>({basename:s,navigator:i,static:a,unstable_useTransitions:o,future:{}}),[s,i,a,o]);typeof n==`string`&&(n=XS(n));let{pathname:l=`/`,search:u=``,hash:d=``,state:f=null,key:p=`default`}=n,h=m.useMemo(()=>{let e=vC(l,s);return e==null?null:{location:{pathname:e,search:u,hash:d,state:f,key:p},navigationType:r}},[s,l,u,d,f,p,r]);return GS(h!=null,` is not able to match the URL "${l}${u}${d}" because it does not start with the basename, so the won't render anything.`),h==null?null:m.createElement(WC.Provider,{value:c},m.createElement(GC.Provider,{children:t,value:h}))}function Mw({children:e,location:t}){return sw(Nw(e),t)}m.Component;function Nw(e,t=[]){let n=[];return m.Children.forEach(e,(e,r)=>{if(!m.isValidElement(e))return;let i=[...t,r];if(e.type===m.Fragment){n.push.apply(n,Nw(e.props.children,i));return}WS(e.type===Aw,`[${typeof e.type==`string`?e.type:e.type.name}] is not a component. All component children of must be a or `),WS(!e.props.index||!e.props.children,`An index route cannot have child routes.`);let a={id:e.props.id||i.join(`-`),caseSensitive:e.props.caseSensitive,element:e.props.element,Component:e.props.Component,index:e.props.index,path:e.props.path,middleware:e.props.middleware,loader:e.props.loader,action:e.props.action,hydrateFallbackElement:e.props.hydrateFallbackElement,HydrateFallback:e.props.HydrateFallback,errorElement:e.props.errorElement,ErrorBoundary:e.props.ErrorBoundary,hasErrorBoundary:e.props.hasErrorBoundary===!0||e.props.ErrorBoundary!=null||e.props.errorElement!=null,shouldRevalidate:e.props.shouldRevalidate,handle:e.props.handle,lazy:e.props.lazy};e.props.children&&(a.children=Nw(e.props.children,i)),n.push(a)}),n}var Pw=`get`,Fw=`application/x-www-form-urlencoded`;function Iw(e){return typeof HTMLElement<`u`&&e instanceof HTMLElement}function Lw(e){return Iw(e)&&e.tagName.toLowerCase()===`button`}function Rw(e){return Iw(e)&&e.tagName.toLowerCase()===`form`}function zw(e){return Iw(e)&&e.tagName.toLowerCase()===`input`}function Bw(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}function Vw(e,t){return e.button===0&&(!t||t===`_self`)&&!Bw(e)}var Hw=null;function Uw(){if(Hw===null)try{new FormData(document.createElement(`form`),0),Hw=!1}catch{Hw=!0}return Hw}var Ww=new Set([`application/x-www-form-urlencoded`,`multipart/form-data`,`text/plain`]);function Gw(e){return e!=null&&!Ww.has(e)?(GS(!1,`"${e}" is not a valid \`encType\` for \`\`/\`\` and will default to "${Fw}"`),null):e}function Kw(e,t){let n,r,i,a,o;if(Rw(e)){let o=e.getAttribute(`action`);r=o?vC(o,t):null,n=e.getAttribute(`method`)||Pw,i=Gw(e.getAttribute(`enctype`))||Fw,a=new FormData(e)}else if(Lw(e)||zw(e)&&(e.type===`submit`||e.type===`image`)){let o=e.form;if(o==null)throw Error(`Cannot submit a + + {/* */} + +

+ Hit Cmd+Shift+K to hide +

+ + {children} + + + ); }; diff --git a/apps/ui-staff/src/main.tsx b/apps/ui-staff/src/main.tsx index b1cfc1a8c..c8ab49201 100644 --- a/apps/ui-staff/src/main.tsx +++ b/apps/ui-staff/src/main.tsx @@ -1,13 +1,13 @@ import { HelmetProvider } from '@dr.pogodin/react-helmet'; import { App as AntdApp, ConfigProvider } from 'antd'; -import React from 'react'; +import React, { useContext } from 'react'; import { createRoot } from 'react-dom/client'; import { AuthProvider } from 'react-oidc-context'; import { BrowserRouter } from 'react-router-dom'; import './index.less'; import App from './App.tsx'; import { oidcConfig } from './config/oidc-config.tsx'; -import { ThemeProvider } from './contexts/theme-context.tsx'; +import { ThemeContext, ThemeProvider } from './contexts/theme-context.tsx'; const rootElement = document.getElementById('root'); if (!rootElement) { @@ -15,8 +15,18 @@ if (!rootElement) { } const ConfigProviderWrapper = () => { + const { currentTokens } = useContext(ThemeContext); + return ( - + diff --git a/packages/ocom/ui-staff-route-community-management/package.json b/packages/ocom/ui-staff-route-community-management/package.json index cba0cc205..72881e15e 100644 --- a/packages/ocom/ui-staff-route-community-management/package.json +++ b/packages/ocom/ui-staff-route-community-management/package.json @@ -15,6 +15,7 @@ "test:watch": "vitest" }, "dependencies": { + "@ocom/ui-staff-route-shared": "workspace:*", "antd": "catalog:", "react": "^19.1.1", "react-dom": "^19.1.1" diff --git a/packages/ocom/ui-staff-route-community-management/src/section-layout.tsx b/packages/ocom/ui-staff-route-community-management/src/section-layout.tsx index b9dbbba43..ac61362bd 100644 --- a/packages/ocom/ui-staff-route-community-management/src/section-layout.tsx +++ b/packages/ocom/ui-staff-route-community-management/src/section-layout.tsx @@ -1,3 +1,11 @@ -export const SectionLayout: React.FC = () => { - return
Staff Root Placeholder
; +import type { FC } from 'react'; +import { StaffRouteShell } from '@ocom/ui-staff-route-shared'; + +export const SectionLayout: FC = () => { + return ( + + ); }; diff --git a/packages/ocom/ui-staff-route-finance/package.json b/packages/ocom/ui-staff-route-finance/package.json index da2e53796..2ab9c430b 100644 --- a/packages/ocom/ui-staff-route-finance/package.json +++ b/packages/ocom/ui-staff-route-finance/package.json @@ -15,6 +15,7 @@ "test:watch": "vitest" }, "dependencies": { + "@ocom/ui-staff-route-shared": "workspace:*", "antd": "catalog:", "react": "^19.1.1", "react-dom": "^19.1.1" diff --git a/packages/ocom/ui-staff-route-finance/src/section-layout.tsx b/packages/ocom/ui-staff-route-finance/src/section-layout.tsx index b9dbbba43..e66d288d6 100644 --- a/packages/ocom/ui-staff-route-finance/src/section-layout.tsx +++ b/packages/ocom/ui-staff-route-finance/src/section-layout.tsx @@ -1,3 +1,11 @@ -export const SectionLayout: React.FC = () => { - return
Staff Root Placeholder
; +import type { FC } from 'react'; +import { StaffRouteShell } from '@ocom/ui-staff-route-shared'; + +export const SectionLayout: FC = () => { + return ( + + ); }; diff --git a/packages/ocom/ui-staff-route-root/package.json b/packages/ocom/ui-staff-route-root/package.json index c90d70478..2c321a9a9 100644 --- a/packages/ocom/ui-staff-route-root/package.json +++ b/packages/ocom/ui-staff-route-root/package.json @@ -15,6 +15,7 @@ "test:watch": "vitest" }, "dependencies": { + "@ocom/ui-staff-route-shared": "workspace:*", "@ocom/ui-staff-route-community-management": "workspace:*", "@ocom/ui-staff-route-finance": "workspace:*", "@ocom/ui-staff-route-tech-admin": "workspace:*", diff --git a/packages/ocom/ui-staff-route-root/src/section-layout.tsx b/packages/ocom/ui-staff-route-root/src/section-layout.tsx index 1046f95b1..d2d7c2281 100644 --- a/packages/ocom/ui-staff-route-root/src/section-layout.tsx +++ b/packages/ocom/ui-staff-route-root/src/section-layout.tsx @@ -1,19 +1,11 @@ import type { FC } from 'react'; +import { StaffRouteShell } from '@ocom/ui-staff-route-shared'; export const SectionLayout: FC = () => { return ( -
- -
-
Welcome to Staff area. Select a section from the menu.
-
-
+ ); }; diff --git a/packages/ocom/ui-staff-route-shared/src/index.tsx b/packages/ocom/ui-staff-route-shared/src/index.tsx index db42a8d03..458ff69d6 100644 --- a/packages/ocom/ui-staff-route-shared/src/index.tsx +++ b/packages/ocom/ui-staff-route-shared/src/index.tsx @@ -1,4 +1,5 @@ import { createElement, type FC } from 'react'; import { SectionLayout } from './section-layout.tsx'; +export { StaffRouteShell, type StaffRouteShellProps } from './staff-route-shell.tsx'; export const Root: FC = () => createElement(SectionLayout); diff --git a/packages/ocom/ui-staff-route-shared/src/section-layout.tsx b/packages/ocom/ui-staff-route-shared/src/section-layout.tsx index b9dbbba43..9181f815a 100644 --- a/packages/ocom/ui-staff-route-shared/src/section-layout.tsx +++ b/packages/ocom/ui-staff-route-shared/src/section-layout.tsx @@ -1,3 +1,11 @@ -export const SectionLayout: React.FC = () => { - return
Staff Root Placeholder
; +import type { FC } from 'react'; +import { StaffRouteShell } from './staff-route-shell.tsx'; + +export const SectionLayout: FC = () => { + return ( + + ); }; diff --git a/packages/ocom/ui-staff-route-shared/src/staff-route-shell.tsx b/packages/ocom/ui-staff-route-shared/src/staff-route-shell.tsx new file mode 100644 index 000000000..a256b0aed --- /dev/null +++ b/packages/ocom/ui-staff-route-shared/src/staff-route-shell.tsx @@ -0,0 +1,56 @@ +import type { FC } from 'react'; + +export interface StaffRouteShellProps { + title: string; + description: string; +} + +const navLinks = [ + { label: 'Community Management', href: '/staff/community' }, + { label: 'User Management', href: '/staff/users' }, + { label: 'Finance', href: '/staff/finance' }, + { label: 'Tech Admin', href: '/staff/tech' }, +]; + +export const StaffRouteShell: FC = ({ title, description }) => { + return ( +
+
+
+
{title}
+
{description}
+
+
+ +
+
+ {description} +
+
+
+
+
+ ); +}; diff --git a/packages/ocom/ui-staff-route-tech-admin/package.json b/packages/ocom/ui-staff-route-tech-admin/package.json index e3bed5e33..2a6af1e5a 100644 --- a/packages/ocom/ui-staff-route-tech-admin/package.json +++ b/packages/ocom/ui-staff-route-tech-admin/package.json @@ -15,6 +15,7 @@ "test:watch": "vitest" }, "dependencies": { + "@ocom/ui-staff-route-shared": "workspace:*", "antd": "catalog:", "react": "^19.1.1" }, diff --git a/packages/ocom/ui-staff-route-tech-admin/src/section-layout.tsx b/packages/ocom/ui-staff-route-tech-admin/src/section-layout.tsx index b9dbbba43..5b44c01e5 100644 --- a/packages/ocom/ui-staff-route-tech-admin/src/section-layout.tsx +++ b/packages/ocom/ui-staff-route-tech-admin/src/section-layout.tsx @@ -1,3 +1,11 @@ -export const SectionLayout: React.FC = () => { - return
Staff Root Placeholder
; +import type { FC } from 'react'; +import { StaffRouteShell } from '@ocom/ui-staff-route-shared'; + +export const SectionLayout: FC = () => { + return ( + + ); }; diff --git a/packages/ocom/ui-staff-route-user-management/package.json b/packages/ocom/ui-staff-route-user-management/package.json index 79fe087b8..5543b8ed5 100644 --- a/packages/ocom/ui-staff-route-user-management/package.json +++ b/packages/ocom/ui-staff-route-user-management/package.json @@ -15,6 +15,7 @@ "test:watch": "vitest" }, "dependencies": { + "@ocom/ui-staff-route-shared": "workspace:*", "react": "^19.1.1" }, "devDependencies": { diff --git a/packages/ocom/ui-staff-route-user-management/src/section-layout.tsx b/packages/ocom/ui-staff-route-user-management/src/section-layout.tsx index b9dbbba43..9230cd667 100644 --- a/packages/ocom/ui-staff-route-user-management/src/section-layout.tsx +++ b/packages/ocom/ui-staff-route-user-management/src/section-layout.tsx @@ -1,3 +1,11 @@ -export const SectionLayout: React.FC = () => { - return
Staff Root Placeholder
; +import type { FC } from 'react'; +import { StaffRouteShell } from '@ocom/ui-staff-route-shared'; + +export const SectionLayout: FC = () => { + return ( + + ); }; From 9256b16cc26cbe90ff533058a86e7d9eb632a072 Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Thu, 23 Apr 2026 15:22:48 -0400 Subject: [PATCH 08/88] fix: update ApolloConnectionProps interface --- apps/ui-staff/src/apollo-connection.tsx | 64 ------------------- .../ui/organisms/apollo-connection/index.tsx | 2 +- package.json | 4 +- 3 files changed, 3 insertions(+), 67 deletions(-) delete mode 100644 apps/ui-staff/src/apollo-connection.tsx diff --git a/apps/ui-staff/src/apollo-connection.tsx b/apps/ui-staff/src/apollo-connection.tsx deleted file mode 100644 index 49e156c42..000000000 --- a/apps/ui-staff/src/apollo-connection.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { ApolloLink, ApolloProvider, from } from '@apollo/client'; -import { RestLink } from 'apollo-link-rest'; -import { type FC, useCallback, useEffect } from 'react'; -import { useAuth } from 'react-oidc-context'; -import { useLocation } from 'react-router-dom'; -import { ApolloLinkToAddAuthHeader, ApolloLinkToAddCustomHeader, BaseApolloLink, client, TerminatingApolloLinkForGraphqlServer } from './components/ui/organisms/apollo-connection/apollo-client-links.tsx'; - -export type ApolloConnectionProps = { - children: React.ReactNode; -} -export const ApolloConnection: FC = (props: ApolloConnectionProps) => { - const auth = useAuth(); - const location = useLocation(); - - const communityId = location.pathname.match(/\/community\/([a-f\d]{24})/i)?.[1] ?? null; - const memberId = location.pathname.match(/\/(member|admin)\/([a-f\d]{24})/i)?.[2] ?? null; - - const apolloLinkChainForGraphqlDataSource = from([ - BaseApolloLink(), - ApolloLinkToAddAuthHeader(auth), - // Use the community header name for parity with ui-community and the server expectations. - ApolloLinkToAddCustomHeader('x-community-id', communityId, communityId !== 'accounts'), - ApolloLinkToAddCustomHeader('x-member-id', memberId), - TerminatingApolloLinkForGraphqlServer({ - // biome-ignore lint:useLiteralKeys - uri: `${import.meta.env['VITE_FUNCTION_ENDPOINT']}`, - batchMax: 15, - batchInterval: 50, - }), - ]); - - const apolloLinkChainForCountryDataSource = from([ - new RestLink({ - uri: 'https://countries.trevorblades.com/', - }), - ]); - - const updateLink = useCallback(() => { - const linkMap = { - CountryDetails: apolloLinkChainForCountryDataSource, - default: apolloLinkChainForGraphqlDataSource, - }; - - return ApolloLink.from([ - ApolloLink.split( - // various options to split: - // 1. use a custom property in context: (operation) => operation.getContext().dataSource === some DataSourceEnum, - // 2. check for string name of the query if it is named: (operation) => operation.operationName === "CountryDetails", - (operation) => operation.operationName in linkMap, - new ApolloLink((operation, forward) => { - const link = linkMap[operation.operationName as keyof typeof linkMap] || linkMap.default; - return link.request(operation, forward); - }), - apolloLinkChainForGraphqlDataSource, - ), - ]); - }, [apolloLinkChainForGraphqlDataSource, apolloLinkChainForCountryDataSource]); - - useEffect(() => { - client.setLink(updateLink()); - }, [updateLink]); - - return {props.children}; -}; diff --git a/apps/ui-staff/src/components/ui/organisms/apollo-connection/index.tsx b/apps/ui-staff/src/components/ui/organisms/apollo-connection/index.tsx index 9c03f23c6..ed07f70be 100644 --- a/apps/ui-staff/src/components/ui/organisms/apollo-connection/index.tsx +++ b/apps/ui-staff/src/components/ui/organisms/apollo-connection/index.tsx @@ -5,7 +5,7 @@ import { useAuth } from 'react-oidc-context'; import { useLocation } from 'react-router-dom'; import { ApolloLinkToAddAuthHeader, ApolloLinkToAddCustomHeader, BaseApolloLink, client, TerminatingApolloLinkForGraphqlServer } from './apollo-client-links.tsx'; -export interface ApolloConnectionProps { +interface ApolloConnectionProps { children: React.ReactNode; } diff --git a/package.json b/package.json index dbd9903e1..82de10856 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "type": "module", "author": "CellixJs", "license": "MIT", - "packageManager": "pnpm@10.30.1", + "packageManager": "pnpm@10.33.2", "scripts": { "antd": "antd", "audit": "(pnpm audit --audit-level=high --prod) && (pnpm audit --audit-level=critical --dev)", @@ -118,7 +118,7 @@ "playwright-core": "1.59.0", "playwright": "1.59.0", "protobufjs": "7.5.5", - "uuid": "^14.0.0" + "uuid": "^14.0.0" }, "patchedDependencies": { "@azure/functions@4.11.0": "patches/@azure__functions@4.11.0.patch" From cb0f4526ab9568e6007797094982a33c15362bc4 Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Fri, 24 Apr 2026 12:02:21 -0400 Subject: [PATCH 09/88] Update Snyk ignore rules for UUID and adjust package versions for compatibility --- .snyk | 6 + package.json | 2 +- pnpm-lock.yaml | 1113 ++++++++++++++++++++++++------------------------ 3 files changed, 571 insertions(+), 550 deletions(-) diff --git a/.snyk b/.snyk index 29532879c..6098d09c3 100644 --- a/.snyk +++ b/.snyk @@ -52,3 +52,9 @@ ignore: reason: 'Transitive dependency in @mongodb-memory-server; not exploitable in current usage.' expires: '2026-03-26T00:00:00.000Z' created: '2026-03-12T12:35:00.000Z' + + 'SNYK-JS-UUID-16133035': + - '* > uuid@11.1.0': + reason: 'Required for Azurite compatibility.' + expires: '2026-10-24T00:00:00.000Z' + created: '2026-04-24T11:48:00.000Z' diff --git a/package.json b/package.json index 82de10856..b5bb586d3 100644 --- a/package.json +++ b/package.json @@ -118,7 +118,7 @@ "playwright-core": "1.59.0", "playwright": "1.59.0", "protobufjs": "7.5.5", - "uuid": "^14.0.0" + "postcss": "^8.5.10" }, "patchedDependencies": { "@azure/functions@4.11.0": "patches/@azure__functions@4.11.0.patch" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d81b0b29b..167cf85e0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -82,7 +82,7 @@ overrides: playwright-core: 1.59.0 playwright: 1.59.0 protobufjs: 7.5.5 - uuid: ^14.0.0 + postcss: ^8.5.10 patchedDependencies: '@azure/functions@4.11.0': @@ -3158,217 +3158,217 @@ packages: resolution: {integrity: sha512-isfLLwksH3yHkFXfCI2Gcaqg7wGGHZZwunoJzEZk0yKYIokgre6hYVFibKL3SYAoR1kBXova8LB+JoO5vZzi9w==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-cascade-layers@5.0.2': resolution: {integrity: sha512-nWBE08nhO8uWl6kSAeCx4im7QfVko3zLrtgWZY4/bP87zrSPpSyN/3W3TDqz1jJuH+kbKOHXg5rJnK+ZVYcFFg==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-color-function-display-p3-linear@1.0.1': resolution: {integrity: sha512-E5qusdzhlmO1TztYzDIi8XPdPoYOjoTY6HBYBCYSj+Gn4gQRBlvjgPQXzfzuPQqt8EhkC/SzPKObg4Mbn8/xMg==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-color-function@4.0.12': resolution: {integrity: sha512-yx3cljQKRaSBc2hfh8rMZFZzChaFgwmO2JfFgFr1vMcF3C/uyy5I4RFIBOIWGq1D+XbKCG789CGkG6zzkLpagA==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-color-mix-function@3.0.12': resolution: {integrity: sha512-4STERZfCP5Jcs13P1U5pTvI9SkgLgfMUMhdXW8IlJWkzOOOqhZIjcNhWtNJZes2nkBDsIKJ0CJtFtuaZ00moag==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-color-mix-variadic-function-arguments@1.0.2': resolution: {integrity: sha512-rM67Gp9lRAkTo+X31DUqMEq+iK+EFqsidfecmhrteErxJZb6tUoJBVQca1Vn1GpDql1s1rD1pKcuYzMsg7Z1KQ==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-content-alt-text@2.0.8': resolution: {integrity: sha512-9SfEW9QCxEpTlNMnpSqFaHyzsiRpZ5J5+KqCu1u5/eEJAWsMhzT40qf0FIbeeglEvrGRMdDzAxMIz3wqoGSb+Q==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-contrast-color-function@2.0.12': resolution: {integrity: sha512-YbwWckjK3qwKjeYz/CijgcS7WDUCtKTd8ShLztm3/i5dhh4NaqzsbYnhm4bjrpFpnLZ31jVcbK8YL77z3GBPzA==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-exponential-functions@2.0.9': resolution: {integrity: sha512-abg2W/PI3HXwS/CZshSa79kNWNZHdJPMBXeZNyPQFbbj8sKO3jXxOt/wF7juJVjyDTc6JrvaUZYFcSBZBhaxjw==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-font-format-keywords@4.0.0': resolution: {integrity: sha512-usBzw9aCRDvchpok6C+4TXC57btc4bJtmKQWOHQxOVKen1ZfVqBUuCZ/wuqdX5GHsD0NRSr9XTP+5ID1ZZQBXw==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-gamut-mapping@2.0.11': resolution: {integrity: sha512-fCpCUgZNE2piVJKC76zFsgVW1apF6dpYsqGyH8SIeCcM4pTEsRTWTLCaJIMKFEundsCKwY1rwfhtrio04RJ4Dw==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-gradients-interpolation-method@5.0.12': resolution: {integrity: sha512-jugzjwkUY0wtNrZlFeyXzimUL3hN4xMvoPnIXxoZqxDvjZRiSh+itgHcVUWzJ2VwD/VAMEgCLvtaJHX+4Vj3Ow==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-hwb-function@4.0.12': resolution: {integrity: sha512-mL/+88Z53KrE4JdePYFJAQWFrcADEqsLprExCM04GDNgHIztwFzj0Mbhd/yxMBngq0NIlz58VVxjt5abNs1VhA==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-ic-unit@4.0.4': resolution: {integrity: sha512-yQ4VmossuOAql65sCPppVO1yfb7hDscf4GseF0VCA/DTDaBc0Wtf8MTqVPfjGYlT5+2buokG0Gp7y0atYZpwjg==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-initial@2.0.1': resolution: {integrity: sha512-L1wLVMSAZ4wovznquK0xmC7QSctzO4D0Is590bxpGqhqjboLXYA16dWZpfwImkdOgACdQ9PqXsuRroW6qPlEsg==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-is-pseudo-class@5.0.3': resolution: {integrity: sha512-jS/TY4SpG4gszAtIg7Qnf3AS2pjcUM5SzxpApOrlndMeGhIbaTzWBzzP/IApXoNWEW7OhcjkRT48jnAUIFXhAQ==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-light-dark-function@2.0.11': resolution: {integrity: sha512-fNJcKXJdPM3Lyrbmgw2OBbaioU7yuKZtiXClf4sGdQttitijYlZMD5K7HrC/eF83VRWRrYq6OZ0Lx92leV2LFA==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-logical-float-and-clear@3.0.0': resolution: {integrity: sha512-SEmaHMszwakI2rqKRJgE+8rpotFfne1ZS6bZqBoQIicFyV+xT1UF42eORPxJkVJVrH9C0ctUgwMSn3BLOIZldQ==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-logical-overflow@2.0.0': resolution: {integrity: sha512-spzR1MInxPuXKEX2csMamshR4LRaSZ3UXVaRGjeQxl70ySxOhMpP2252RAFsg8QyyBXBzuVOOdx1+bVO5bPIzA==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-logical-overscroll-behavior@2.0.0': resolution: {integrity: sha512-e/webMjoGOSYfqLunyzByZj5KKe5oyVg/YSbie99VEaSDE2kimFm0q1f6t/6Jo+VVCQ/jbe2Xy+uX+C4xzWs4w==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-logical-resize@3.0.0': resolution: {integrity: sha512-DFbHQOFW/+I+MY4Ycd/QN6Dg4Hcbb50elIJCfnwkRTCX05G11SwViI5BbBlg9iHRl4ytB7pmY5ieAFk3ws7yyg==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-logical-viewport-units@3.0.4': resolution: {integrity: sha512-q+eHV1haXA4w9xBwZLKjVKAWn3W2CMqmpNpZUk5kRprvSiBEGMgrNH3/sJZ8UA3JgyHaOt3jwT9uFa4wLX4EqQ==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-media-minmax@2.0.9': resolution: {integrity: sha512-af9Qw3uS3JhYLnCbqtZ9crTvvkR+0Se+bBqSr7ykAnl9yKhk6895z9rf+2F4dClIDJWxgn0iZZ1PSdkhrbs2ig==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-media-queries-aspect-ratio-number-values@3.0.5': resolution: {integrity: sha512-zhAe31xaaXOY2Px8IYfoVTB3wglbJUVigGphFLj6exb7cjZRH9A6adyE22XfFK3P2PzwRk0VDeTJmaxpluyrDg==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-nested-calc@4.0.0': resolution: {integrity: sha512-jMYDdqrQQxE7k9+KjstC3NbsmC063n1FTPLCgCRS2/qHUbHM0mNy9pIn4QIiQGs9I/Bg98vMqw7mJXBxa0N88A==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-normalize-display-values@4.0.0': resolution: {integrity: sha512-HlEoG0IDRoHXzXnkV4in47dzsxdsjdz6+j7MLjaACABX2NfvjFS6XVAnpaDyGesz9gK2SC7MbNwdCHusObKJ9Q==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-oklab-function@4.0.12': resolution: {integrity: sha512-HhlSmnE1NKBhXsTnNGjxvhryKtO7tJd1w42DKOGFD6jSHtYOrsJTQDKPMwvOfrzUAk8t7GcpIfRyM7ssqHpFjg==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-progressive-custom-properties@4.2.1': resolution: {integrity: sha512-uPiiXf7IEKtUQXsxu6uWtOlRMXd2QWWy5fhxHDnPdXKCQckPP3E34ZgDoZ62r2iT+UOgWsSbM4NvHE5m3mAEdw==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-random-function@2.0.1': resolution: {integrity: sha512-q+FQaNiRBhnoSNo+GzqGOIBKoHQ43lYz0ICrV+UudfWnEF6ksS6DsBIJSISKQT2Bvu3g4k6r7t0zYrk5pDlo8w==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-relative-color-syntax@3.0.12': resolution: {integrity: sha512-0RLIeONxu/mtxRtf3o41Lq2ghLimw0w9ByLWnnEVuy89exmEEq8bynveBxNW3nyHqLAFEeNtVEmC1QK9MZ8Huw==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-scope-pseudo-class@4.0.1': resolution: {integrity: sha512-IMi9FwtH6LMNuLea1bjVMQAsUhFxJnyLSgOp/cpv5hrzWmrUYU5fm0EguNDIIOHUqzXode8F/1qkC/tEo/qN8Q==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-sign-functions@1.1.4': resolution: {integrity: sha512-P97h1XqRPcfcJndFdG95Gv/6ZzxUBBISem0IDqPZ7WMvc/wlO+yU0c5D/OCpZ5TJoTt63Ok3knGk64N+o6L2Pg==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-stepped-value-functions@4.0.9': resolution: {integrity: sha512-h9btycWrsex4dNLeQfyU3y3w40LMQooJWFMm/SK9lrKguHDcFl4VMkncKKoXi2z5rM9YGWbUQABI8BT2UydIcA==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-text-decoration-shorthand@4.0.3': resolution: {integrity: sha512-KSkGgZfx0kQjRIYnpsD7X2Om9BUXX/Kii77VBifQW9Ih929hK0KNjVngHDH0bFB9GmfWcR9vJYJJRvw/NQjkrA==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-trigonometric-functions@4.0.9': resolution: {integrity: sha512-Hnh5zJUdpNrJqK9v1/E3BbrQhaDTj5YiX7P61TOvUhoDHnUmsNNxcDAgkQ32RrcWx9GVUvfUNPcUkn8R3vIX6A==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/postcss-unset-value@4.0.0': resolution: {integrity: sha512-cBz3tOCI5Fw6NIFEwU3RiwK6mn3nKegjpJuzCndoGq3BZPkUjnsq7uQmIeMNeMbMk7YD2MfKcgCpZwX5jyXqCA==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@csstools/selector-resolve-nested@3.1.0': resolution: {integrity: sha512-mf1LEW0tJLKfWyvn5KdDrhpxHyuxpbNwTIwOYLIvsTffeyOf85j5oIzfG0yosxDgx/sswlqBnESYUcQH0vgZ0g==} @@ -3386,7 +3386,7 @@ packages: resolution: {integrity: sha512-5VdOr0Z71u+Yp3ozOx8T11N703wIFGVRgOWbOZMKgglPJsWA54MRIoMNVMa7shUToIhx5J8vX4sOZgD2XiihiQ==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 '@ctrl/tinycolor@3.6.1': resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==} @@ -6733,7 +6733,7 @@ packages: engines: {node: ^10 || ^12 || >=14} hasBin: true peerDependencies: - postcss: ^8.1.0 + postcss: ^8.5.10 available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} @@ -7337,19 +7337,19 @@ packages: resolution: {integrity: sha512-jf+twWGDf6LDoXDUode+nc7ZlrqfaNphrBIBrcmeP3D8yw1uPaix1gCC8LUQUGQ6CycuK2opkbFFWFuq/a94ag==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 css-declaration-sorter@7.3.0: resolution: {integrity: sha512-LQF6N/3vkAMYF4xoHLJfG718HRJh34Z8BnNhd6bosOMIVjMlhuZK5++oZa3uYAgrI5+7x2o27gUqTR2U/KjUOQ==} engines: {node: ^14 || ^16 || >=18} peerDependencies: - postcss: ^8.0.9 + postcss: ^8.5.10 css-has-pseudo@7.0.3: resolution: {integrity: sha512-oG+vKuGyqe/xvEMoxAQrhi7uY16deJR3i7wwhBerVrGQKSqUC5GiOVxTpM9F9B9hw0J+eKeOWLH7E9gZ1Dr5rA==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 css-loader@6.11.0: resolution: {integrity: sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==} @@ -7392,7 +7392,7 @@ packages: resolution: {integrity: sha512-VCtXZAWivRglTZditUfB4StnsWr6YVZ2PRtuxQLKTNRdtAf8tpzaVPE9zXIF3VaSc7O70iK/j1+NXxyQCqdPjQ==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 css-select@4.3.0: resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} @@ -7427,25 +7427,25 @@ packages: resolution: {integrity: sha512-Nhao7eD8ph2DoHolEzQs5CfRpiEP0xa1HBdnFZ82kvqdmbwVBUr2r1QuQ4t1pi+D1ZpqpcO4T+wy/7RxzJ/WPQ==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 cssnano-preset-default@6.1.2: resolution: {integrity: sha512-1C0C+eNaeN8OcHQa193aRgYexyJtU8XwbdieEjClw+J9d94E41LwT6ivKH0WT+fYwYWB0Zp3I3IZ7tI/BbUbrg==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 cssnano-utils@4.0.2: resolution: {integrity: sha512-ZR1jHg+wZ8o4c3zqf1SIUSTIvm/9mU343FMR6Obe/unskbvpGhZOo1J6d/r8D1pzkRQYuwbcH3hToOuoA2G7oQ==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 cssnano@6.1.2: resolution: {integrity: sha512-rYk5UeX7VAM/u0lNqewCdasdtPK81CgX8wJFLEIXHbV2oldWRgJAsZrdhRXkV1NJzA2g850KiFm9mMU2HxNxMA==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 csso@5.0.5: resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} @@ -8572,7 +8572,7 @@ packages: resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} engines: {node: ^10 || ^12 || >= 14} peerDependencies: - postcss: ^8.1.0 + postcss: ^8.5.10 ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -10291,163 +10291,163 @@ packages: resolution: {integrity: sha512-Uai+SupNSqzlschRyNx3kbCTWgY/2hcwtHEI/ej2LJWc9JJ77qKgGptd8DHwY1mXtZ7Aoh4z4yxfwMBue9eNgw==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 postcss-calc@9.0.1: resolution: {integrity: sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.2.2 + postcss: ^8.5.10 postcss-clamp@4.1.0: resolution: {integrity: sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==} engines: {node: '>=7.6.0'} peerDependencies: - postcss: ^8.4.6 + postcss: ^8.5.10 postcss-color-functional-notation@7.0.12: resolution: {integrity: sha512-TLCW9fN5kvO/u38/uesdpbx3e8AkTYhMvDZYa9JpmImWuTE99bDQ7GU7hdOADIZsiI9/zuxfAJxny/khknp1Zw==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 postcss-color-hex-alpha@10.0.0: resolution: {integrity: sha512-1kervM2cnlgPs2a8Vt/Qbe5cQ++N7rkYo/2rz2BkqJZIHQwaVuJgQH38REHrAi4uM0b1fqxMkWYmese94iMp3w==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 postcss-color-rebeccapurple@10.0.0: resolution: {integrity: sha512-JFta737jSP+hdAIEhk1Vs0q0YF5P8fFcj+09pweS8ktuGuZ8pPlykHsk6mPxZ8awDl4TrcxUqJo9l1IhVr/OjQ==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 postcss-colormin@6.1.0: resolution: {integrity: sha512-x9yX7DOxeMAR+BgGVnNSAxmAj98NX/YxEMNFP+SDCEeNLb2r3i6Hh1ksMsnW8Ub5SLCpbescQqn9YEbE9554Sw==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-convert-values@6.1.0: resolution: {integrity: sha512-zx8IwP/ts9WvUM6NkVSkiU902QZL1bwPhaVaLynPtCsOTqp+ZKbNi+s6XJg3rfqpKGA/oc7Oxk5t8pOQJcwl/w==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-custom-media@11.0.6: resolution: {integrity: sha512-C4lD4b7mUIw+RZhtY7qUbf4eADmb7Ey8BFA2px9jUbwg7pjTZDl4KY4bvlUV+/vXQvzQRfiGEVJyAbtOsCMInw==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 postcss-custom-properties@14.0.6: resolution: {integrity: sha512-fTYSp3xuk4BUeVhxCSJdIPhDLpJfNakZKoiTDx7yRGCdlZrSJR7mWKVOBS4sBF+5poPQFMj2YdXx1VHItBGihQ==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 postcss-custom-selectors@8.0.5: resolution: {integrity: sha512-9PGmckHQswiB2usSO6XMSswO2yFWVoCAuih1yl9FVcwkscLjRKjwsjM3t+NIWpSU2Jx3eOiK2+t4vVTQaoCHHg==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 postcss-dir-pseudo-class@9.0.1: resolution: {integrity: sha512-tRBEK0MHYvcMUrAuYMEOa0zg9APqirBcgzi6P21OhxtJyJADo/SWBwY1CAwEohQ/6HDaa9jCjLRG7K3PVQYHEA==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 postcss-discard-comments@6.0.2: resolution: {integrity: sha512-65w/uIqhSBBfQmYnG92FO1mWZjJ4GL5b8atm5Yw2UgrwD7HiNiSSNwJor1eCFGzUgYnN/iIknhNRVqjrrpuglw==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-discard-duplicates@6.0.3: resolution: {integrity: sha512-+JA0DCvc5XvFAxwx6f/e68gQu/7Z9ud584VLmcgto28eB8FqSFZwtrLwB5Kcp70eIoWP/HXqz4wpo8rD8gpsTw==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-discard-empty@6.0.3: resolution: {integrity: sha512-znyno9cHKQsK6PtxL5D19Fj9uwSzC2mB74cpT66fhgOadEUPyXFkbgwm5tvc3bt3NAy8ltE5MrghxovZRVnOjQ==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-discard-overridden@6.0.2: resolution: {integrity: sha512-j87xzI4LUggC5zND7KdjsI25APtyMuynXZSujByMaav2roV6OZX+8AaCUcZSWqckZpjAjRyFDdpqybgjFO0HJQ==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-discard-unused@6.0.5: resolution: {integrity: sha512-wHalBlRHkaNnNwfC8z+ppX57VhvS+HWgjW508esjdaEYr3Mx7Gnn2xA4R/CKf5+Z9S5qsqC+Uzh4ueENWwCVUA==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-double-position-gradients@6.0.4: resolution: {integrity: sha512-m6IKmxo7FxSP5nF2l63QbCC3r+bWpFUWmZXZf096WxG0m7Vl1Q1+ruFOhpdDRmKrRS+S3Jtk+TVk/7z0+BVK6g==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 postcss-focus-visible@10.0.1: resolution: {integrity: sha512-U58wyjS/I1GZgjRok33aE8juW9qQgQUNwTSdxQGuShHzwuYdcklnvK/+qOWX1Q9kr7ysbraQ6ht6r+udansalA==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 postcss-focus-within@9.0.1: resolution: {integrity: sha512-fzNUyS1yOYa7mOjpci/bR+u+ESvdar6hk8XNK/TRR0fiGTp2QT5N+ducP0n3rfH/m9I7H/EQU6lsa2BrgxkEjw==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 postcss-font-variant@5.0.0: resolution: {integrity: sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==} peerDependencies: - postcss: ^8.1.0 + postcss: ^8.5.10 postcss-gap-properties@6.0.0: resolution: {integrity: sha512-Om0WPjEwiM9Ru+VhfEDPZJAKWUd0mV1HmNXqp2C29z80aQ2uP9UVhLc7e3aYMIor/S5cVhoPgYQ7RtfeZpYTRw==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 postcss-image-set-function@7.0.0: resolution: {integrity: sha512-QL7W7QNlZuzOwBTeXEmbVckNt1FSmhQtbMRvGGqqU4Nf4xk6KUEQhAoWuMzwbSv5jxiRiSZ5Tv7eiDB9U87znA==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 postcss-import@15.1.0: resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} engines: {node: '>=14.0.0'} peerDependencies: - postcss: ^8.0.0 + postcss: ^8.5.10 postcss-js@4.1.0: resolution: {integrity: sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==} engines: {node: ^12 || ^14 || >= 16} peerDependencies: - postcss: ^8.4.21 + postcss: ^8.5.10 postcss-lab-function@7.0.12: resolution: {integrity: sha512-tUcyRk1ZTPec3OuKFsqtRzW2Go5lehW29XA21lZ65XmzQkz43VY2tyWEC202F7W3mILOjw0voOiuxRGTsN+J9w==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 postcss-load-config@6.0.1: resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} engines: {node: '>= 18'} peerDependencies: jiti: 2.6.1 - postcss: '>=8.0.9' + postcss: ^8.5.10 tsx: ^4.8.1 yaml: 2.8.3 peerDependenciesMeta: @@ -10464,216 +10464,216 @@ packages: resolution: {integrity: sha512-iW5WTTBSC5BfsBJ9daFMPVrLT36MrNiC6fqOZTTaHjBNX6Pfd5p+hSBqe/fEeNd7pc13QiAyGt7VdGMw4eRC4A==} engines: {node: '>= 14.15.0'} peerDependencies: - postcss: ^7.0.0 || ^8.0.1 + postcss: ^8.5.10 webpack: ^5.105.4 postcss-logical@8.1.0: resolution: {integrity: sha512-pL1hXFQ2fEXNKiNiAgtfA005T9FBxky5zkX6s4GZM2D8RkVgRqz3f4g1JUoq925zXv495qk8UNldDwh8uGEDoA==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 postcss-merge-idents@6.0.3: resolution: {integrity: sha512-1oIoAsODUs6IHQZkLQGO15uGEbK3EAl5wi9SS8hs45VgsxQfMnxvt+L+zIr7ifZFIH14cfAeVe2uCTa+SPRa3g==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-merge-longhand@6.0.5: resolution: {integrity: sha512-5LOiordeTfi64QhICp07nzzuTDjNSO8g5Ksdibt44d+uvIIAE1oZdRn8y/W5ZtYgRH/lnLDlvi9F8btZcVzu3w==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-merge-rules@6.1.1: resolution: {integrity: sha512-KOdWF0gju31AQPZiD+2Ar9Qjowz1LTChSjFFbS+e2sFgc4uHOp3ZvVX4sNeTlk0w2O31ecFGgrFzhO0RSWbWwQ==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-minify-font-values@6.1.0: resolution: {integrity: sha512-gklfI/n+9rTh8nYaSJXlCo3nOKqMNkxuGpTn/Qm0gstL3ywTr9/WRKznE+oy6fvfolH6dF+QM4nCo8yPLdvGJg==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-minify-gradients@6.0.3: resolution: {integrity: sha512-4KXAHrYlzF0Rr7uc4VrfwDJ2ajrtNEpNEuLxFgwkhFZ56/7gaE4Nr49nLsQDZyUe+ds+kEhf+YAUolJiYXF8+Q==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-minify-params@6.1.0: resolution: {integrity: sha512-bmSKnDtyyE8ujHQK0RQJDIKhQ20Jq1LYiez54WiaOoBtcSuflfK3Nm596LvbtlFcpipMjgClQGyGr7GAs+H1uA==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-minify-selectors@6.0.4: resolution: {integrity: sha512-L8dZSwNLgK7pjTto9PzWRoMbnLq5vsZSTu8+j1P/2GB8qdtGQfn+K1uSvFgYvgh83cbyxT5m43ZZhUMTJDSClQ==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-modules-extract-imports@3.1.0: resolution: {integrity: sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==} engines: {node: ^10 || ^12 || >= 14} peerDependencies: - postcss: ^8.1.0 + postcss: ^8.5.10 postcss-modules-local-by-default@4.2.0: resolution: {integrity: sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==} engines: {node: ^10 || ^12 || >= 14} peerDependencies: - postcss: ^8.1.0 + postcss: ^8.5.10 postcss-modules-scope@3.2.1: resolution: {integrity: sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==} engines: {node: ^10 || ^12 || >= 14} peerDependencies: - postcss: ^8.1.0 + postcss: ^8.5.10 postcss-modules-values@4.0.0: resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} engines: {node: ^10 || ^12 || >= 14} peerDependencies: - postcss: ^8.1.0 + postcss: ^8.5.10 postcss-nested@6.2.0: resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} engines: {node: '>=12.0'} peerDependencies: - postcss: ^8.2.14 + postcss: ^8.5.10 postcss-nesting@13.0.2: resolution: {integrity: sha512-1YCI290TX+VP0U/K/aFxzHzQWHWURL+CtHMSbex1lCdpXD1SoR2sYuxDu5aNI9lPoXpKTCggFZiDJbwylU0LEQ==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 postcss-normalize-charset@6.0.2: resolution: {integrity: sha512-a8N9czmdnrjPHa3DeFlwqst5eaL5W8jYu3EBbTTkI5FHkfMhFZh1EGbku6jhHhIzTA6tquI2P42NtZ59M/H/kQ==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-normalize-display-values@6.0.2: resolution: {integrity: sha512-8H04Mxsb82ON/aAkPeq8kcBbAtI5Q2a64X/mnRRfPXBq7XeogoQvReqxEfc0B4WPq1KimjezNC8flUtC3Qz6jg==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-normalize-positions@6.0.2: resolution: {integrity: sha512-/JFzI441OAB9O7VnLA+RtSNZvQ0NCFZDOtp6QPFo1iIyawyXg0YI3CYM9HBy1WvwCRHnPep/BvI1+dGPKoXx/Q==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-normalize-repeat-style@6.0.2: resolution: {integrity: sha512-YdCgsfHkJ2jEXwR4RR3Tm/iOxSfdRt7jplS6XRh9Js9PyCR/aka/FCb6TuHT2U8gQubbm/mPmF6L7FY9d79VwQ==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-normalize-string@6.0.2: resolution: {integrity: sha512-vQZIivlxlfqqMp4L9PZsFE4YUkWniziKjQWUtsxUiVsSSPelQydwS8Wwcuw0+83ZjPWNTl02oxlIvXsmmG+CiQ==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-normalize-timing-functions@6.0.2: resolution: {integrity: sha512-a+YrtMox4TBtId/AEwbA03VcJgtyW4dGBizPl7e88cTFULYsprgHWTbfyjSLyHeBcK/Q9JhXkt2ZXiwaVHoMzA==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-normalize-unicode@6.1.0: resolution: {integrity: sha512-QVC5TQHsVj33otj8/JD869Ndr5Xcc/+fwRh4HAsFsAeygQQXm+0PySrKbr/8tkDKzW+EVT3QkqZMfFrGiossDg==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-normalize-url@6.0.2: resolution: {integrity: sha512-kVNcWhCeKAzZ8B4pv/DnrU1wNh458zBNp8dh4y5hhxih5RZQ12QWMuQrDgPRw3LRl8mN9vOVfHl7uhvHYMoXsQ==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-normalize-whitespace@6.0.2: resolution: {integrity: sha512-sXZ2Nj1icbJOKmdjXVT9pnyHQKiSAyuNQHSgRCUgThn2388Y9cGVDR+E9J9iAYbSbLHI+UUwLVl1Wzco/zgv0Q==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-opacity-percentage@3.0.0: resolution: {integrity: sha512-K6HGVzyxUxd/VgZdX04DCtdwWJ4NGLG212US4/LA1TLAbHgmAsTWVR86o+gGIbFtnTkfOpb9sCRBx8K7HO66qQ==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 postcss-ordered-values@6.0.2: resolution: {integrity: sha512-VRZSOB+JU32RsEAQrO94QPkClGPKJEL/Z9PCBImXMhIeK5KAYo6slP/hBYlLgrCjFxyqvn5VC81tycFEDBLG1Q==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-overflow-shorthand@6.0.0: resolution: {integrity: sha512-BdDl/AbVkDjoTofzDQnwDdm/Ym6oS9KgmO7Gr+LHYjNWJ6ExORe4+3pcLQsLA9gIROMkiGVjjwZNoL/mpXHd5Q==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 postcss-page-break@3.0.4: resolution: {integrity: sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==} peerDependencies: - postcss: ^8 + postcss: ^8.5.10 postcss-place@10.0.0: resolution: {integrity: sha512-5EBrMzat2pPAxQNWYavwAfoKfYcTADJ8AXGVPcUZ2UkNloUTWzJQExgrzrDkh3EKzmAx1evfTAzF9I8NGcc+qw==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 postcss-preset-env@10.4.0: resolution: {integrity: sha512-2kqpOthQ6JhxqQq1FSAAZGe9COQv75Aw8WbsOvQVNJ2nSevc9Yx/IKZGuZ7XJ+iOTtVon7LfO7ELRzg8AZ+sdw==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 postcss-pseudo-class-any-link@10.0.1: resolution: {integrity: sha512-3el9rXlBOqTFaMFkWDOkHUTQekFIYnaQY55Rsp8As8QQkpiSgIYEcF/6Ond93oHiDsGb4kad8zjt+NPlOC1H0Q==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 postcss-reduce-idents@6.0.3: resolution: {integrity: sha512-G3yCqZDpsNPoQgbDUy3T0E6hqOQ5xigUtBQyrmq3tn2GxlyiL0yyl7H+T8ulQR6kOcHJ9t7/9H4/R2tv8tJbMA==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-reduce-initial@6.1.0: resolution: {integrity: sha512-RarLgBK/CrL1qZags04oKbVbrrVK2wcxhvta3GCxrZO4zveibqbRPmm2VI8sSgCXwoUHEliRSbOfpR0b/VIoiw==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-reduce-transforms@6.0.2: resolution: {integrity: sha512-sB+Ya++3Xj1WaT9+5LOOdirAxP7dJZms3GRcYheSPi1PiTMigsxHAdkrbItHxwYHr4kt1zL7mmcHstgMYT+aiA==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-replace-overflow-wrap@4.0.0: resolution: {integrity: sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==} peerDependencies: - postcss: ^8.0.3 + postcss: ^8.5.10 postcss-selector-not@8.0.1: resolution: {integrity: sha512-kmVy/5PYVb2UOhy0+LqUYAhKj7DUGDpSWa5LZqlkWJaaAV+dxxsOG3+St0yNLu6vsKD7Dmqx+nWQt0iil89+WA==} engines: {node: '>=18'} peerDependencies: - postcss: ^8.4 + postcss: ^8.5.10 postcss-selector-parser@6.1.2: resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} @@ -10687,19 +10687,19 @@ packages: resolution: {integrity: sha512-AZ5fDMLD8SldlAYlvi8NIqo0+Z8xnXU2ia0jxmuhxAU+Lqt9K+AlmLNJ/zWEnE9x+Zx3qL3+1K20ATgNOr3fAA==} engines: {node: '>=14.0.0'} peerDependencies: - postcss: ^8.4.23 + postcss: ^8.5.10 postcss-svgo@6.0.3: resolution: {integrity: sha512-dlrahRmxP22bX6iKEjOM+c8/1p+81asjKT+V5lrgOH944ryx/OHpclnIbGsKVd3uWOXFLYJwCVf0eEkJGvO96g==} engines: {node: ^14 || ^16 || >= 18} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-unique-selectors@6.0.4: resolution: {integrity: sha512-K38OCaIrO8+PzpArzkLKB42dSARtC2tmG6PvD4b1o1Q2E9Os8jzfWFfSy/rixsHwohtsDdFtAWGjFVFUdwYaMg==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} @@ -10708,14 +10708,10 @@ packages: resolution: {integrity: sha512-5BxW9l1evPB/4ZIc+2GobEBoKC+h8gPGCMi+jxsYvd2x0mjq7wazk6DrP71pStqxE9Foxh5TVnonbWpFZzXaYg==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 - postcss@8.5.6: - resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} - engines: {node: ^10 || ^12 || >=14} - - postcss@8.5.8: - resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} + postcss@8.5.10: + resolution: {integrity: sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==} engines: {node: ^10 || ^12 || >=14} pretty-error@4.0.0: @@ -11762,7 +11758,7 @@ packages: resolution: {integrity: sha512-gSTTEQ670cJNoaeIp9KX6lZmm8LJ3jPB5yJmX8Zq/wQxOsAFXV3qjWzHas3YYk1qesuVIyYWWUpZ0vSE/dTSGg==} engines: {node: ^14 || ^16 || >=18.0} peerDependencies: - postcss: ^8.4.31 + postcss: ^8.5.10 stylis@4.3.6: resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==} @@ -12279,8 +12275,25 @@ packages: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} - uuid@14.0.0: - resolution: {integrity: sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==} + uuid@10.0.0: + resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + hasBin: true + + uuid@11.0.5: + resolution: {integrity: sha512-508e6IcKLrhxKdBbcA2b4KQZlLVp2+J5UwQ6F7Drckkc5N9ZJwFa4TgWtsww9UG8fGHbm6gbV19TdM5pQ4GaIA==} + hasBin: true + + uuid@11.1.0: + resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} + hasBin: true + + uuid@3.4.0: + resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} + deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. + hasBin: true + + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true validate-npm-package-license@3.0.4: @@ -13058,7 +13071,7 @@ snapshots: loglevel: 1.9.2 lru-cache: 11.2.4 negotiator: 1.0.0 - uuid: 14.0.0 + uuid: 11.1.0 whatwg-mimetype: 4.0.0 transitivePeerDependencies: - supports-color @@ -13341,7 +13354,7 @@ snapshots: tough-cookie: 2.5.0 tslib: 1.14.1 tunnel: 0.0.6 - uuid: 14.0.0 + uuid: 3.4.0 xml2js: 0.4.23 transitivePeerDependencies: - debug @@ -13357,7 +13370,7 @@ snapshots: dependencies: '@azure/msal-common': 14.16.1 jsonwebtoken: 9.0.2 - uuid: 14.0.0 + uuid: 8.3.2 '@azure/opentelemetry-instrumentation-azure-sdk@1.0.0-beta.9': dependencies: @@ -14239,251 +14252,251 @@ snapshots: '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - '@csstools/postcss-alpha-function@1.0.1(postcss@8.5.8)': + '@csstools/postcss-alpha-function@1.0.1(postcss@8.5.10)': dependencies: '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.8) - '@csstools/utilities': 2.0.0(postcss@8.5.8) - postcss: 8.5.8 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) + postcss: 8.5.10 - '@csstools/postcss-cascade-layers@5.0.2(postcss@8.5.8)': + '@csstools/postcss-cascade-layers@5.0.2(postcss@8.5.10)': dependencies: '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.1) - postcss: 8.5.8 + postcss: 8.5.10 postcss-selector-parser: 7.1.1 - '@csstools/postcss-color-function-display-p3-linear@1.0.1(postcss@8.5.8)': + '@csstools/postcss-color-function-display-p3-linear@1.0.1(postcss@8.5.10)': dependencies: '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.8) - '@csstools/utilities': 2.0.0(postcss@8.5.8) - postcss: 8.5.8 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) + postcss: 8.5.10 - '@csstools/postcss-color-function@4.0.12(postcss@8.5.8)': + '@csstools/postcss-color-function@4.0.12(postcss@8.5.10)': dependencies: '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.8) - '@csstools/utilities': 2.0.0(postcss@8.5.8) - postcss: 8.5.8 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) + postcss: 8.5.10 - '@csstools/postcss-color-mix-function@3.0.12(postcss@8.5.8)': + '@csstools/postcss-color-mix-function@3.0.12(postcss@8.5.10)': dependencies: '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.8) - '@csstools/utilities': 2.0.0(postcss@8.5.8) - postcss: 8.5.8 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) + postcss: 8.5.10 - '@csstools/postcss-color-mix-variadic-function-arguments@1.0.2(postcss@8.5.8)': + '@csstools/postcss-color-mix-variadic-function-arguments@1.0.2(postcss@8.5.10)': dependencies: '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.8) - '@csstools/utilities': 2.0.0(postcss@8.5.8) - postcss: 8.5.8 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) + postcss: 8.5.10 - '@csstools/postcss-content-alt-text@2.0.8(postcss@8.5.8)': + '@csstools/postcss-content-alt-text@2.0.8(postcss@8.5.10)': dependencies: '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.8) - '@csstools/utilities': 2.0.0(postcss@8.5.8) - postcss: 8.5.8 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) + postcss: 8.5.10 - '@csstools/postcss-contrast-color-function@2.0.12(postcss@8.5.8)': + '@csstools/postcss-contrast-color-function@2.0.12(postcss@8.5.10)': dependencies: '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.8) - '@csstools/utilities': 2.0.0(postcss@8.5.8) - postcss: 8.5.8 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) + postcss: 8.5.10 - '@csstools/postcss-exponential-functions@2.0.9(postcss@8.5.8)': + '@csstools/postcss-exponential-functions@2.0.9(postcss@8.5.10)': dependencies: '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - postcss: 8.5.8 + postcss: 8.5.10 - '@csstools/postcss-font-format-keywords@4.0.0(postcss@8.5.8)': + '@csstools/postcss-font-format-keywords@4.0.0(postcss@8.5.10)': dependencies: - '@csstools/utilities': 2.0.0(postcss@8.5.8) - postcss: 8.5.8 + '@csstools/utilities': 2.0.0(postcss@8.5.10) + postcss: 8.5.10 postcss-value-parser: 4.2.0 - '@csstools/postcss-gamut-mapping@2.0.11(postcss@8.5.8)': + '@csstools/postcss-gamut-mapping@2.0.11(postcss@8.5.10)': dependencies: '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - postcss: 8.5.8 + postcss: 8.5.10 - '@csstools/postcss-gradients-interpolation-method@5.0.12(postcss@8.5.8)': + '@csstools/postcss-gradients-interpolation-method@5.0.12(postcss@8.5.10)': dependencies: '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.8) - '@csstools/utilities': 2.0.0(postcss@8.5.8) - postcss: 8.5.8 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) + postcss: 8.5.10 - '@csstools/postcss-hwb-function@4.0.12(postcss@8.5.8)': + '@csstools/postcss-hwb-function@4.0.12(postcss@8.5.10)': dependencies: '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.8) - '@csstools/utilities': 2.0.0(postcss@8.5.8) - postcss: 8.5.8 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) + postcss: 8.5.10 - '@csstools/postcss-ic-unit@4.0.4(postcss@8.5.8)': + '@csstools/postcss-ic-unit@4.0.4(postcss@8.5.10)': dependencies: - '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.8) - '@csstools/utilities': 2.0.0(postcss@8.5.8) - postcss: 8.5.8 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) + postcss: 8.5.10 postcss-value-parser: 4.2.0 - '@csstools/postcss-initial@2.0.1(postcss@8.5.8)': + '@csstools/postcss-initial@2.0.1(postcss@8.5.10)': dependencies: - postcss: 8.5.8 + postcss: 8.5.10 - '@csstools/postcss-is-pseudo-class@5.0.3(postcss@8.5.8)': + '@csstools/postcss-is-pseudo-class@5.0.3(postcss@8.5.10)': dependencies: '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.1) - postcss: 8.5.8 + postcss: 8.5.10 postcss-selector-parser: 7.1.1 - '@csstools/postcss-light-dark-function@2.0.11(postcss@8.5.8)': + '@csstools/postcss-light-dark-function@2.0.11(postcss@8.5.10)': dependencies: '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.8) - '@csstools/utilities': 2.0.0(postcss@8.5.8) - postcss: 8.5.8 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) + postcss: 8.5.10 - '@csstools/postcss-logical-float-and-clear@3.0.0(postcss@8.5.8)': + '@csstools/postcss-logical-float-and-clear@3.0.0(postcss@8.5.10)': dependencies: - postcss: 8.5.8 + postcss: 8.5.10 - '@csstools/postcss-logical-overflow@2.0.0(postcss@8.5.8)': + '@csstools/postcss-logical-overflow@2.0.0(postcss@8.5.10)': dependencies: - postcss: 8.5.8 + postcss: 8.5.10 - '@csstools/postcss-logical-overscroll-behavior@2.0.0(postcss@8.5.8)': + '@csstools/postcss-logical-overscroll-behavior@2.0.0(postcss@8.5.10)': dependencies: - postcss: 8.5.8 + postcss: 8.5.10 - '@csstools/postcss-logical-resize@3.0.0(postcss@8.5.8)': + '@csstools/postcss-logical-resize@3.0.0(postcss@8.5.10)': dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-value-parser: 4.2.0 - '@csstools/postcss-logical-viewport-units@3.0.4(postcss@8.5.8)': + '@csstools/postcss-logical-viewport-units@3.0.4(postcss@8.5.10)': dependencies: '@csstools/css-tokenizer': 3.0.4 - '@csstools/utilities': 2.0.0(postcss@8.5.8) - postcss: 8.5.8 + '@csstools/utilities': 2.0.0(postcss@8.5.10) + postcss: 8.5.10 - '@csstools/postcss-media-minmax@2.0.9(postcss@8.5.8)': + '@csstools/postcss-media-minmax@2.0.9(postcss@8.5.10)': dependencies: '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 '@csstools/media-query-list-parser': 4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - postcss: 8.5.8 + postcss: 8.5.10 - '@csstools/postcss-media-queries-aspect-ratio-number-values@3.0.5(postcss@8.5.8)': + '@csstools/postcss-media-queries-aspect-ratio-number-values@3.0.5(postcss@8.5.10)': dependencies: '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 '@csstools/media-query-list-parser': 4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - postcss: 8.5.8 + postcss: 8.5.10 - '@csstools/postcss-nested-calc@4.0.0(postcss@8.5.8)': + '@csstools/postcss-nested-calc@4.0.0(postcss@8.5.10)': dependencies: - '@csstools/utilities': 2.0.0(postcss@8.5.8) - postcss: 8.5.8 + '@csstools/utilities': 2.0.0(postcss@8.5.10) + postcss: 8.5.10 postcss-value-parser: 4.2.0 - '@csstools/postcss-normalize-display-values@4.0.0(postcss@8.5.8)': + '@csstools/postcss-normalize-display-values@4.0.0(postcss@8.5.10)': dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-value-parser: 4.2.0 - '@csstools/postcss-oklab-function@4.0.12(postcss@8.5.8)': + '@csstools/postcss-oklab-function@4.0.12(postcss@8.5.10)': dependencies: '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.8) - '@csstools/utilities': 2.0.0(postcss@8.5.8) - postcss: 8.5.8 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) + postcss: 8.5.10 - '@csstools/postcss-progressive-custom-properties@4.2.1(postcss@8.5.8)': + '@csstools/postcss-progressive-custom-properties@4.2.1(postcss@8.5.10)': dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-value-parser: 4.2.0 - '@csstools/postcss-random-function@2.0.1(postcss@8.5.8)': + '@csstools/postcss-random-function@2.0.1(postcss@8.5.10)': dependencies: '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - postcss: 8.5.8 + postcss: 8.5.10 - '@csstools/postcss-relative-color-syntax@3.0.12(postcss@8.5.8)': + '@csstools/postcss-relative-color-syntax@3.0.12(postcss@8.5.10)': dependencies: '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.8) - '@csstools/utilities': 2.0.0(postcss@8.5.8) - postcss: 8.5.8 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) + postcss: 8.5.10 - '@csstools/postcss-scope-pseudo-class@4.0.1(postcss@8.5.8)': + '@csstools/postcss-scope-pseudo-class@4.0.1(postcss@8.5.10)': dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-selector-parser: 7.1.1 - '@csstools/postcss-sign-functions@1.1.4(postcss@8.5.8)': + '@csstools/postcss-sign-functions@1.1.4(postcss@8.5.10)': dependencies: '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - postcss: 8.5.8 + postcss: 8.5.10 - '@csstools/postcss-stepped-value-functions@4.0.9(postcss@8.5.8)': + '@csstools/postcss-stepped-value-functions@4.0.9(postcss@8.5.10)': dependencies: '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - postcss: 8.5.8 + postcss: 8.5.10 - '@csstools/postcss-text-decoration-shorthand@4.0.3(postcss@8.5.8)': + '@csstools/postcss-text-decoration-shorthand@4.0.3(postcss@8.5.10)': dependencies: '@csstools/color-helpers': 5.1.0 - postcss: 8.5.8 + postcss: 8.5.10 postcss-value-parser: 4.2.0 - '@csstools/postcss-trigonometric-functions@4.0.9(postcss@8.5.8)': + '@csstools/postcss-trigonometric-functions@4.0.9(postcss@8.5.10)': dependencies: '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - postcss: 8.5.8 + postcss: 8.5.10 - '@csstools/postcss-unset-value@4.0.0(postcss@8.5.8)': + '@csstools/postcss-unset-value@4.0.0(postcss@8.5.10)': dependencies: - postcss: 8.5.8 + postcss: 8.5.10 '@csstools/selector-resolve-nested@3.1.0(postcss-selector-parser@7.1.1)': dependencies: @@ -14493,9 +14506,9 @@ snapshots: dependencies: postcss-selector-parser: 7.1.1 - '@csstools/utilities@2.0.0(postcss@8.5.8)': + '@csstools/utilities@2.0.0(postcss@8.5.10)': dependencies: - postcss: 8.5.8 + postcss: 8.5.10 '@ctrl/tinycolor@3.6.1': {} @@ -14596,14 +14609,14 @@ snapshots: '@types/uuid': 10.0.0 class-transformer: 0.5.1 reflect-metadata: 0.2.2 - uuid: 14.0.0 + uuid: 10.0.0 '@cucumber/messages@27.2.0': dependencies: '@types/uuid': 10.0.0 class-transformer: 0.5.1 reflect-metadata: 0.2.2 - uuid: 14.0.0 + uuid: 11.0.5 '@cucumber/node@0.4.0': dependencies: @@ -14708,14 +14721,14 @@ snapshots: copy-webpack-plugin: 11.0.0(webpack@5.105.4(esbuild@0.27.4)) css-loader: 6.11.0(webpack@5.105.4(esbuild@0.27.4)) css-minimizer-webpack-plugin: 5.0.1(clean-css@5.3.3)(esbuild@0.27.4)(webpack@5.105.4(esbuild@0.27.4)) - cssnano: 6.1.2(postcss@8.5.8) + cssnano: 6.1.2(postcss@8.5.10) file-loader: 6.2.0(webpack@5.105.4(esbuild@0.27.4)) html-minifier-terser: 7.2.0 mini-css-extract-plugin: 2.9.4(webpack@5.105.4(esbuild@0.27.4)) null-loader: 4.0.1(webpack@5.105.4(esbuild@0.27.4)) - postcss: 8.5.8 - postcss-loader: 7.3.4(postcss@8.5.8)(typescript@6.0.2)(webpack@5.105.4(esbuild@0.27.4)) - postcss-preset-env: 10.4.0(postcss@8.5.8) + postcss: 8.5.10 + postcss-loader: 7.3.4(postcss@8.5.10)(typescript@6.0.2)(webpack@5.105.4(esbuild@0.27.4)) + postcss-preset-env: 10.4.0(postcss@8.5.10) terser-webpack-plugin: 5.3.14(esbuild@0.27.4)(webpack@5.105.4(esbuild@0.27.4)) tslib: 2.8.1 url-loader: 4.1.1(file-loader@6.2.0(webpack@5.105.4(esbuild@0.27.4)))(webpack@5.105.4(esbuild@0.27.4)) @@ -14802,9 +14815,9 @@ snapshots: '@docusaurus/cssnano-preset@3.9.2': dependencies: - cssnano-preset-advanced: 6.1.2(postcss@8.5.8) - postcss: 8.5.8 - postcss-sort-media-queries: 5.2.0(postcss@8.5.8) + cssnano-preset-advanced: 6.1.2(postcss@8.5.10) + postcss: 8.5.10 + postcss-sort-media-queries: 5.2.0(postcss@8.5.10) tslib: 2.8.1 '@docusaurus/logger@3.9.2': @@ -15236,7 +15249,7 @@ snapshots: infima: 0.2.0-alpha.45 lodash: 4.18.1 nprogress: 0.2.0 - postcss: 8.5.8 + postcss: 8.5.10 prism-react-renderer: 2.4.1(react@19.2.0) prismjs: 1.30.0 react: 19.2.0 @@ -18728,14 +18741,14 @@ snapshots: auto-bind@4.0.0: {} - autoprefixer@10.4.22(postcss@8.5.8): + autoprefixer@10.4.22(postcss@8.5.10): dependencies: browserslist: 4.28.1 caniuse-lite: 1.0.30001777 fraction.js: 5.3.4 normalize-range: 0.1.2 picocolors: 1.1.1 - postcss: 8.5.8 + postcss: 8.5.10 postcss-value-parser: 4.2.0 available-typed-arrays@1.0.7: @@ -18776,7 +18789,7 @@ snapshots: to-readable-stream: 2.1.0 tslib: 2.8.1 uri-templates: 0.2.0 - uuid: 14.0.0 + uuid: 3.4.0 winston: 3.18.3 xml2js: 0.6.2 transitivePeerDependencies: @@ -19408,30 +19421,30 @@ snapshots: dependencies: type-fest: 1.4.0 - css-blank-pseudo@7.0.1(postcss@8.5.8): + css-blank-pseudo@7.0.1(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-selector-parser: 7.1.1 - css-declaration-sorter@7.3.0(postcss@8.5.8): + css-declaration-sorter@7.3.0(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 - css-has-pseudo@7.0.3(postcss@8.5.8): + css-has-pseudo@7.0.3(postcss@8.5.10): dependencies: '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.1) - postcss: 8.5.8 + postcss: 8.5.10 postcss-selector-parser: 7.1.1 postcss-value-parser: 4.2.0 css-loader@6.11.0(webpack@5.105.4(esbuild@0.27.4)): dependencies: - icss-utils: 5.1.0(postcss@8.5.8) - postcss: 8.5.8 - postcss-modules-extract-imports: 3.1.0(postcss@8.5.8) - postcss-modules-local-by-default: 4.2.0(postcss@8.5.8) - postcss-modules-scope: 3.2.1(postcss@8.5.8) - postcss-modules-values: 4.0.0(postcss@8.5.8) + icss-utils: 5.1.0(postcss@8.5.10) + postcss: 8.5.10 + postcss-modules-extract-imports: 3.1.0(postcss@8.5.10) + postcss-modules-local-by-default: 4.2.0(postcss@8.5.10) + postcss-modules-scope: 3.2.1(postcss@8.5.10) + postcss-modules-values: 4.0.0(postcss@8.5.10) postcss-value-parser: 4.2.0 semver: 7.7.3 optionalDependencies: @@ -19440,9 +19453,9 @@ snapshots: css-minimizer-webpack-plugin@5.0.1(clean-css@5.3.3)(esbuild@0.27.4)(webpack@5.105.4(esbuild@0.27.4)): dependencies: '@jridgewell/trace-mapping': 0.3.31 - cssnano: 6.1.2(postcss@8.5.8) + cssnano: 6.1.2(postcss@8.5.10) jest-worker: 29.7.0 - postcss: 8.5.8 + postcss: 8.5.10 schema-utils: 4.3.3 serialize-javascript: 7.0.5 webpack: 5.105.4(esbuild@0.27.4) @@ -19450,9 +19463,9 @@ snapshots: clean-css: 5.3.3 esbuild: 0.27.4 - css-prefers-color-scheme@10.0.0(postcss@8.5.8): + css-prefers-color-scheme@10.0.0(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 css-select@4.3.0: dependencies: @@ -19488,60 +19501,60 @@ snapshots: cssesc@3.0.0: {} - cssnano-preset-advanced@6.1.2(postcss@8.5.8): + cssnano-preset-advanced@6.1.2(postcss@8.5.10): dependencies: - autoprefixer: 10.4.22(postcss@8.5.8) + autoprefixer: 10.4.22(postcss@8.5.10) browserslist: 4.28.1 - cssnano-preset-default: 6.1.2(postcss@8.5.8) - postcss: 8.5.8 - postcss-discard-unused: 6.0.5(postcss@8.5.8) - postcss-merge-idents: 6.0.3(postcss@8.5.8) - postcss-reduce-idents: 6.0.3(postcss@8.5.8) - postcss-zindex: 6.0.2(postcss@8.5.8) + cssnano-preset-default: 6.1.2(postcss@8.5.10) + postcss: 8.5.10 + postcss-discard-unused: 6.0.5(postcss@8.5.10) + postcss-merge-idents: 6.0.3(postcss@8.5.10) + postcss-reduce-idents: 6.0.3(postcss@8.5.10) + postcss-zindex: 6.0.2(postcss@8.5.10) - cssnano-preset-default@6.1.2(postcss@8.5.8): + cssnano-preset-default@6.1.2(postcss@8.5.10): dependencies: browserslist: 4.28.1 - css-declaration-sorter: 7.3.0(postcss@8.5.8) - cssnano-utils: 4.0.2(postcss@8.5.8) - postcss: 8.5.8 - postcss-calc: 9.0.1(postcss@8.5.8) - postcss-colormin: 6.1.0(postcss@8.5.8) - postcss-convert-values: 6.1.0(postcss@8.5.8) - postcss-discard-comments: 6.0.2(postcss@8.5.8) - postcss-discard-duplicates: 6.0.3(postcss@8.5.8) - postcss-discard-empty: 6.0.3(postcss@8.5.8) - postcss-discard-overridden: 6.0.2(postcss@8.5.8) - postcss-merge-longhand: 6.0.5(postcss@8.5.8) - postcss-merge-rules: 6.1.1(postcss@8.5.8) - postcss-minify-font-values: 6.1.0(postcss@8.5.8) - postcss-minify-gradients: 6.0.3(postcss@8.5.8) - postcss-minify-params: 6.1.0(postcss@8.5.8) - postcss-minify-selectors: 6.0.4(postcss@8.5.8) - postcss-normalize-charset: 6.0.2(postcss@8.5.8) - postcss-normalize-display-values: 6.0.2(postcss@8.5.8) - postcss-normalize-positions: 6.0.2(postcss@8.5.8) - postcss-normalize-repeat-style: 6.0.2(postcss@8.5.8) - postcss-normalize-string: 6.0.2(postcss@8.5.8) - postcss-normalize-timing-functions: 6.0.2(postcss@8.5.8) - postcss-normalize-unicode: 6.1.0(postcss@8.5.8) - postcss-normalize-url: 6.0.2(postcss@8.5.8) - postcss-normalize-whitespace: 6.0.2(postcss@8.5.8) - postcss-ordered-values: 6.0.2(postcss@8.5.8) - postcss-reduce-initial: 6.1.0(postcss@8.5.8) - postcss-reduce-transforms: 6.0.2(postcss@8.5.8) - postcss-svgo: 6.0.3(postcss@8.5.8) - postcss-unique-selectors: 6.0.4(postcss@8.5.8) - - cssnano-utils@4.0.2(postcss@8.5.8): - dependencies: - postcss: 8.5.8 - - cssnano@6.1.2(postcss@8.5.8): - dependencies: - cssnano-preset-default: 6.1.2(postcss@8.5.8) + css-declaration-sorter: 7.3.0(postcss@8.5.10) + cssnano-utils: 4.0.2(postcss@8.5.10) + postcss: 8.5.10 + postcss-calc: 9.0.1(postcss@8.5.10) + postcss-colormin: 6.1.0(postcss@8.5.10) + postcss-convert-values: 6.1.0(postcss@8.5.10) + postcss-discard-comments: 6.0.2(postcss@8.5.10) + postcss-discard-duplicates: 6.0.3(postcss@8.5.10) + postcss-discard-empty: 6.0.3(postcss@8.5.10) + postcss-discard-overridden: 6.0.2(postcss@8.5.10) + postcss-merge-longhand: 6.0.5(postcss@8.5.10) + postcss-merge-rules: 6.1.1(postcss@8.5.10) + postcss-minify-font-values: 6.1.0(postcss@8.5.10) + postcss-minify-gradients: 6.0.3(postcss@8.5.10) + postcss-minify-params: 6.1.0(postcss@8.5.10) + postcss-minify-selectors: 6.0.4(postcss@8.5.10) + postcss-normalize-charset: 6.0.2(postcss@8.5.10) + postcss-normalize-display-values: 6.0.2(postcss@8.5.10) + postcss-normalize-positions: 6.0.2(postcss@8.5.10) + postcss-normalize-repeat-style: 6.0.2(postcss@8.5.10) + postcss-normalize-string: 6.0.2(postcss@8.5.10) + postcss-normalize-timing-functions: 6.0.2(postcss@8.5.10) + postcss-normalize-unicode: 6.1.0(postcss@8.5.10) + postcss-normalize-url: 6.0.2(postcss@8.5.10) + postcss-normalize-whitespace: 6.0.2(postcss@8.5.10) + postcss-ordered-values: 6.0.2(postcss@8.5.10) + postcss-reduce-initial: 6.1.0(postcss@8.5.10) + postcss-reduce-transforms: 6.0.2(postcss@8.5.10) + postcss-svgo: 6.0.3(postcss@8.5.10) + postcss-unique-selectors: 6.0.4(postcss@8.5.10) + + cssnano-utils@4.0.2(postcss@8.5.10): + dependencies: + postcss: 8.5.10 + + cssnano@6.1.2(postcss@8.5.10): + dependencies: + cssnano-preset-default: 6.1.2(postcss@8.5.10) lilconfig: 3.1.3 - postcss: 8.5.8 + postcss: 8.5.10 csso@5.0.5: dependencies: @@ -20911,9 +20924,9 @@ snapshots: dependencies: safer-buffer: 2.1.2 - icss-utils@5.1.0(postcss@8.5.8): + icss-utils@5.1.0(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 ieee754@1.2.1: {} @@ -22889,429 +22902,429 @@ snapshots: possible-typed-array-names@1.1.0: {} - postcss-attribute-case-insensitive@7.0.1(postcss@8.5.8): + postcss-attribute-case-insensitive@7.0.1(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-selector-parser: 7.1.1 - postcss-calc@9.0.1(postcss@8.5.8): + postcss-calc@9.0.1(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-selector-parser: 6.1.2 postcss-value-parser: 4.2.0 - postcss-clamp@4.1.0(postcss@8.5.8): + postcss-clamp@4.1.0(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-color-functional-notation@7.0.12(postcss@8.5.8): + postcss-color-functional-notation@7.0.12(postcss@8.5.10): dependencies: '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.8) - '@csstools/utilities': 2.0.0(postcss@8.5.8) - postcss: 8.5.8 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) + postcss: 8.5.10 - postcss-color-hex-alpha@10.0.0(postcss@8.5.8): + postcss-color-hex-alpha@10.0.0(postcss@8.5.10): dependencies: - '@csstools/utilities': 2.0.0(postcss@8.5.8) - postcss: 8.5.8 + '@csstools/utilities': 2.0.0(postcss@8.5.10) + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-color-rebeccapurple@10.0.0(postcss@8.5.8): + postcss-color-rebeccapurple@10.0.0(postcss@8.5.10): dependencies: - '@csstools/utilities': 2.0.0(postcss@8.5.8) - postcss: 8.5.8 + '@csstools/utilities': 2.0.0(postcss@8.5.10) + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-colormin@6.1.0(postcss@8.5.8): + postcss-colormin@6.1.0(postcss@8.5.10): dependencies: browserslist: 4.28.1 caniuse-api: 3.0.0 colord: 2.9.3 - postcss: 8.5.8 + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-convert-values@6.1.0(postcss@8.5.8): + postcss-convert-values@6.1.0(postcss@8.5.10): dependencies: browserslist: 4.28.1 - postcss: 8.5.8 + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-custom-media@11.0.6(postcss@8.5.8): + postcss-custom-media@11.0.6(postcss@8.5.10): dependencies: '@csstools/cascade-layer-name-parser': 2.0.5(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 '@csstools/media-query-list-parser': 4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - postcss: 8.5.8 + postcss: 8.5.10 - postcss-custom-properties@14.0.6(postcss@8.5.8): + postcss-custom-properties@14.0.6(postcss@8.5.10): dependencies: '@csstools/cascade-layer-name-parser': 2.0.5(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - '@csstools/utilities': 2.0.0(postcss@8.5.8) - postcss: 8.5.8 + '@csstools/utilities': 2.0.0(postcss@8.5.10) + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-custom-selectors@8.0.5(postcss@8.5.8): + postcss-custom-selectors@8.0.5(postcss@8.5.10): dependencies: '@csstools/cascade-layer-name-parser': 2.0.5(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - postcss: 8.5.8 + postcss: 8.5.10 postcss-selector-parser: 7.1.1 - postcss-dir-pseudo-class@9.0.1(postcss@8.5.8): + postcss-dir-pseudo-class@9.0.1(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-selector-parser: 7.1.1 - postcss-discard-comments@6.0.2(postcss@8.5.8): + postcss-discard-comments@6.0.2(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 - postcss-discard-duplicates@6.0.3(postcss@8.5.8): + postcss-discard-duplicates@6.0.3(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 - postcss-discard-empty@6.0.3(postcss@8.5.8): + postcss-discard-empty@6.0.3(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 - postcss-discard-overridden@6.0.2(postcss@8.5.8): + postcss-discard-overridden@6.0.2(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 - postcss-discard-unused@6.0.5(postcss@8.5.8): + postcss-discard-unused@6.0.5(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-selector-parser: 6.1.2 - postcss-double-position-gradients@6.0.4(postcss@8.5.8): + postcss-double-position-gradients@6.0.4(postcss@8.5.10): dependencies: - '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.8) - '@csstools/utilities': 2.0.0(postcss@8.5.8) - postcss: 8.5.8 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-focus-visible@10.0.1(postcss@8.5.8): + postcss-focus-visible@10.0.1(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-selector-parser: 7.1.1 - postcss-focus-within@9.0.1(postcss@8.5.8): + postcss-focus-within@9.0.1(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-selector-parser: 7.1.1 - postcss-font-variant@5.0.0(postcss@8.5.8): + postcss-font-variant@5.0.0(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 - postcss-gap-properties@6.0.0(postcss@8.5.8): + postcss-gap-properties@6.0.0(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 - postcss-image-set-function@7.0.0(postcss@8.5.8): + postcss-image-set-function@7.0.0(postcss@8.5.10): dependencies: - '@csstools/utilities': 2.0.0(postcss@8.5.8) - postcss: 8.5.8 + '@csstools/utilities': 2.0.0(postcss@8.5.10) + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-import@15.1.0(postcss@8.5.6): + postcss-import@15.1.0(postcss@8.5.10): dependencies: - postcss: 8.5.6 + postcss: 8.5.10 postcss-value-parser: 4.2.0 read-cache: 1.0.0 resolve: 1.22.11 - postcss-js@4.1.0(postcss@8.5.6): + postcss-js@4.1.0(postcss@8.5.10): dependencies: camelcase-css: 2.0.1 - postcss: 8.5.6 + postcss: 8.5.10 - postcss-lab-function@7.0.12(postcss@8.5.8): + postcss-lab-function@7.0.12(postcss@8.5.10): dependencies: '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.8) - '@csstools/utilities': 2.0.0(postcss@8.5.8) - postcss: 8.5.8 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) + postcss: 8.5.10 - postcss-load-config@6.0.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(yaml@2.8.3): + postcss-load-config@6.0.1(jiti@2.6.1)(postcss@8.5.10)(tsx@4.21.0)(yaml@2.8.3): dependencies: lilconfig: 3.1.3 optionalDependencies: jiti: 2.6.1 - postcss: 8.5.6 + postcss: 8.5.10 tsx: 4.21.0 yaml: 2.8.3 - postcss-loader@7.3.4(postcss@8.5.8)(typescript@6.0.2)(webpack@5.105.4(esbuild@0.27.4)): + postcss-loader@7.3.4(postcss@8.5.10)(typescript@6.0.2)(webpack@5.105.4(esbuild@0.27.4)): dependencies: cosmiconfig: 8.3.6(typescript@6.0.2) jiti: 2.6.1 - postcss: 8.5.8 + postcss: 8.5.10 semver: 7.7.3 webpack: 5.105.4(esbuild@0.27.4) transitivePeerDependencies: - typescript - postcss-logical@8.1.0(postcss@8.5.8): + postcss-logical@8.1.0(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-merge-idents@6.0.3(postcss@8.5.8): + postcss-merge-idents@6.0.3(postcss@8.5.10): dependencies: - cssnano-utils: 4.0.2(postcss@8.5.8) - postcss: 8.5.8 + cssnano-utils: 4.0.2(postcss@8.5.10) + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-merge-longhand@6.0.5(postcss@8.5.8): + postcss-merge-longhand@6.0.5(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-value-parser: 4.2.0 - stylehacks: 6.1.1(postcss@8.5.8) + stylehacks: 6.1.1(postcss@8.5.10) - postcss-merge-rules@6.1.1(postcss@8.5.8): + postcss-merge-rules@6.1.1(postcss@8.5.10): dependencies: browserslist: 4.28.1 caniuse-api: 3.0.0 - cssnano-utils: 4.0.2(postcss@8.5.8) - postcss: 8.5.8 + cssnano-utils: 4.0.2(postcss@8.5.10) + postcss: 8.5.10 postcss-selector-parser: 6.1.2 - postcss-minify-font-values@6.1.0(postcss@8.5.8): + postcss-minify-font-values@6.1.0(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-minify-gradients@6.0.3(postcss@8.5.8): + postcss-minify-gradients@6.0.3(postcss@8.5.10): dependencies: colord: 2.9.3 - cssnano-utils: 4.0.2(postcss@8.5.8) - postcss: 8.5.8 + cssnano-utils: 4.0.2(postcss@8.5.10) + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-minify-params@6.1.0(postcss@8.5.8): + postcss-minify-params@6.1.0(postcss@8.5.10): dependencies: browserslist: 4.28.1 - cssnano-utils: 4.0.2(postcss@8.5.8) - postcss: 8.5.8 + cssnano-utils: 4.0.2(postcss@8.5.10) + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-minify-selectors@6.0.4(postcss@8.5.8): + postcss-minify-selectors@6.0.4(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-selector-parser: 6.1.2 - postcss-modules-extract-imports@3.1.0(postcss@8.5.8): + postcss-modules-extract-imports@3.1.0(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 - postcss-modules-local-by-default@4.2.0(postcss@8.5.8): + postcss-modules-local-by-default@4.2.0(postcss@8.5.10): dependencies: - icss-utils: 5.1.0(postcss@8.5.8) - postcss: 8.5.8 + icss-utils: 5.1.0(postcss@8.5.10) + postcss: 8.5.10 postcss-selector-parser: 7.1.1 postcss-value-parser: 4.2.0 - postcss-modules-scope@3.2.1(postcss@8.5.8): + postcss-modules-scope@3.2.1(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-selector-parser: 7.1.1 - postcss-modules-values@4.0.0(postcss@8.5.8): + postcss-modules-values@4.0.0(postcss@8.5.10): dependencies: - icss-utils: 5.1.0(postcss@8.5.8) - postcss: 8.5.8 + icss-utils: 5.1.0(postcss@8.5.10) + postcss: 8.5.10 - postcss-nested@6.2.0(postcss@8.5.6): + postcss-nested@6.2.0(postcss@8.5.10): dependencies: - postcss: 8.5.6 + postcss: 8.5.10 postcss-selector-parser: 6.1.2 - postcss-nesting@13.0.2(postcss@8.5.8): + postcss-nesting@13.0.2(postcss@8.5.10): dependencies: '@csstools/selector-resolve-nested': 3.1.0(postcss-selector-parser@7.1.1) '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.1) - postcss: 8.5.8 + postcss: 8.5.10 postcss-selector-parser: 7.1.1 - postcss-normalize-charset@6.0.2(postcss@8.5.8): + postcss-normalize-charset@6.0.2(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 - postcss-normalize-display-values@6.0.2(postcss@8.5.8): + postcss-normalize-display-values@6.0.2(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-normalize-positions@6.0.2(postcss@8.5.8): + postcss-normalize-positions@6.0.2(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-normalize-repeat-style@6.0.2(postcss@8.5.8): + postcss-normalize-repeat-style@6.0.2(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-normalize-string@6.0.2(postcss@8.5.8): + postcss-normalize-string@6.0.2(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-normalize-timing-functions@6.0.2(postcss@8.5.8): + postcss-normalize-timing-functions@6.0.2(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-normalize-unicode@6.1.0(postcss@8.5.8): + postcss-normalize-unicode@6.1.0(postcss@8.5.10): dependencies: browserslist: 4.28.1 - postcss: 8.5.8 + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-normalize-url@6.0.2(postcss@8.5.8): + postcss-normalize-url@6.0.2(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-normalize-whitespace@6.0.2(postcss@8.5.8): + postcss-normalize-whitespace@6.0.2(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-opacity-percentage@3.0.0(postcss@8.5.8): + postcss-opacity-percentage@3.0.0(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 - postcss-ordered-values@6.0.2(postcss@8.5.8): + postcss-ordered-values@6.0.2(postcss@8.5.10): dependencies: - cssnano-utils: 4.0.2(postcss@8.5.8) - postcss: 8.5.8 + cssnano-utils: 4.0.2(postcss@8.5.10) + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-overflow-shorthand@6.0.0(postcss@8.5.8): + postcss-overflow-shorthand@6.0.0(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-page-break@3.0.4(postcss@8.5.8): + postcss-page-break@3.0.4(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 - postcss-place@10.0.0(postcss@8.5.8): + postcss-place@10.0.0(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-preset-env@10.4.0(postcss@8.5.8): - dependencies: - '@csstools/postcss-alpha-function': 1.0.1(postcss@8.5.8) - '@csstools/postcss-cascade-layers': 5.0.2(postcss@8.5.8) - '@csstools/postcss-color-function': 4.0.12(postcss@8.5.8) - '@csstools/postcss-color-function-display-p3-linear': 1.0.1(postcss@8.5.8) - '@csstools/postcss-color-mix-function': 3.0.12(postcss@8.5.8) - '@csstools/postcss-color-mix-variadic-function-arguments': 1.0.2(postcss@8.5.8) - '@csstools/postcss-content-alt-text': 2.0.8(postcss@8.5.8) - '@csstools/postcss-contrast-color-function': 2.0.12(postcss@8.5.8) - '@csstools/postcss-exponential-functions': 2.0.9(postcss@8.5.8) - '@csstools/postcss-font-format-keywords': 4.0.0(postcss@8.5.8) - '@csstools/postcss-gamut-mapping': 2.0.11(postcss@8.5.8) - '@csstools/postcss-gradients-interpolation-method': 5.0.12(postcss@8.5.8) - '@csstools/postcss-hwb-function': 4.0.12(postcss@8.5.8) - '@csstools/postcss-ic-unit': 4.0.4(postcss@8.5.8) - '@csstools/postcss-initial': 2.0.1(postcss@8.5.8) - '@csstools/postcss-is-pseudo-class': 5.0.3(postcss@8.5.8) - '@csstools/postcss-light-dark-function': 2.0.11(postcss@8.5.8) - '@csstools/postcss-logical-float-and-clear': 3.0.0(postcss@8.5.8) - '@csstools/postcss-logical-overflow': 2.0.0(postcss@8.5.8) - '@csstools/postcss-logical-overscroll-behavior': 2.0.0(postcss@8.5.8) - '@csstools/postcss-logical-resize': 3.0.0(postcss@8.5.8) - '@csstools/postcss-logical-viewport-units': 3.0.4(postcss@8.5.8) - '@csstools/postcss-media-minmax': 2.0.9(postcss@8.5.8) - '@csstools/postcss-media-queries-aspect-ratio-number-values': 3.0.5(postcss@8.5.8) - '@csstools/postcss-nested-calc': 4.0.0(postcss@8.5.8) - '@csstools/postcss-normalize-display-values': 4.0.0(postcss@8.5.8) - '@csstools/postcss-oklab-function': 4.0.12(postcss@8.5.8) - '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.8) - '@csstools/postcss-random-function': 2.0.1(postcss@8.5.8) - '@csstools/postcss-relative-color-syntax': 3.0.12(postcss@8.5.8) - '@csstools/postcss-scope-pseudo-class': 4.0.1(postcss@8.5.8) - '@csstools/postcss-sign-functions': 1.1.4(postcss@8.5.8) - '@csstools/postcss-stepped-value-functions': 4.0.9(postcss@8.5.8) - '@csstools/postcss-text-decoration-shorthand': 4.0.3(postcss@8.5.8) - '@csstools/postcss-trigonometric-functions': 4.0.9(postcss@8.5.8) - '@csstools/postcss-unset-value': 4.0.0(postcss@8.5.8) - autoprefixer: 10.4.22(postcss@8.5.8) + postcss-preset-env@10.4.0(postcss@8.5.10): + dependencies: + '@csstools/postcss-alpha-function': 1.0.1(postcss@8.5.10) + '@csstools/postcss-cascade-layers': 5.0.2(postcss@8.5.10) + '@csstools/postcss-color-function': 4.0.12(postcss@8.5.10) + '@csstools/postcss-color-function-display-p3-linear': 1.0.1(postcss@8.5.10) + '@csstools/postcss-color-mix-function': 3.0.12(postcss@8.5.10) + '@csstools/postcss-color-mix-variadic-function-arguments': 1.0.2(postcss@8.5.10) + '@csstools/postcss-content-alt-text': 2.0.8(postcss@8.5.10) + '@csstools/postcss-contrast-color-function': 2.0.12(postcss@8.5.10) + '@csstools/postcss-exponential-functions': 2.0.9(postcss@8.5.10) + '@csstools/postcss-font-format-keywords': 4.0.0(postcss@8.5.10) + '@csstools/postcss-gamut-mapping': 2.0.11(postcss@8.5.10) + '@csstools/postcss-gradients-interpolation-method': 5.0.12(postcss@8.5.10) + '@csstools/postcss-hwb-function': 4.0.12(postcss@8.5.10) + '@csstools/postcss-ic-unit': 4.0.4(postcss@8.5.10) + '@csstools/postcss-initial': 2.0.1(postcss@8.5.10) + '@csstools/postcss-is-pseudo-class': 5.0.3(postcss@8.5.10) + '@csstools/postcss-light-dark-function': 2.0.11(postcss@8.5.10) + '@csstools/postcss-logical-float-and-clear': 3.0.0(postcss@8.5.10) + '@csstools/postcss-logical-overflow': 2.0.0(postcss@8.5.10) + '@csstools/postcss-logical-overscroll-behavior': 2.0.0(postcss@8.5.10) + '@csstools/postcss-logical-resize': 3.0.0(postcss@8.5.10) + '@csstools/postcss-logical-viewport-units': 3.0.4(postcss@8.5.10) + '@csstools/postcss-media-minmax': 2.0.9(postcss@8.5.10) + '@csstools/postcss-media-queries-aspect-ratio-number-values': 3.0.5(postcss@8.5.10) + '@csstools/postcss-nested-calc': 4.0.0(postcss@8.5.10) + '@csstools/postcss-normalize-display-values': 4.0.0(postcss@8.5.10) + '@csstools/postcss-oklab-function': 4.0.12(postcss@8.5.10) + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/postcss-random-function': 2.0.1(postcss@8.5.10) + '@csstools/postcss-relative-color-syntax': 3.0.12(postcss@8.5.10) + '@csstools/postcss-scope-pseudo-class': 4.0.1(postcss@8.5.10) + '@csstools/postcss-sign-functions': 1.1.4(postcss@8.5.10) + '@csstools/postcss-stepped-value-functions': 4.0.9(postcss@8.5.10) + '@csstools/postcss-text-decoration-shorthand': 4.0.3(postcss@8.5.10) + '@csstools/postcss-trigonometric-functions': 4.0.9(postcss@8.5.10) + '@csstools/postcss-unset-value': 4.0.0(postcss@8.5.10) + autoprefixer: 10.4.22(postcss@8.5.10) browserslist: 4.28.1 - css-blank-pseudo: 7.0.1(postcss@8.5.8) - css-has-pseudo: 7.0.3(postcss@8.5.8) - css-prefers-color-scheme: 10.0.0(postcss@8.5.8) + css-blank-pseudo: 7.0.1(postcss@8.5.10) + css-has-pseudo: 7.0.3(postcss@8.5.10) + css-prefers-color-scheme: 10.0.0(postcss@8.5.10) cssdb: 8.4.3 - postcss: 8.5.8 - postcss-attribute-case-insensitive: 7.0.1(postcss@8.5.8) - postcss-clamp: 4.1.0(postcss@8.5.8) - postcss-color-functional-notation: 7.0.12(postcss@8.5.8) - postcss-color-hex-alpha: 10.0.0(postcss@8.5.8) - postcss-color-rebeccapurple: 10.0.0(postcss@8.5.8) - postcss-custom-media: 11.0.6(postcss@8.5.8) - postcss-custom-properties: 14.0.6(postcss@8.5.8) - postcss-custom-selectors: 8.0.5(postcss@8.5.8) - postcss-dir-pseudo-class: 9.0.1(postcss@8.5.8) - postcss-double-position-gradients: 6.0.4(postcss@8.5.8) - postcss-focus-visible: 10.0.1(postcss@8.5.8) - postcss-focus-within: 9.0.1(postcss@8.5.8) - postcss-font-variant: 5.0.0(postcss@8.5.8) - postcss-gap-properties: 6.0.0(postcss@8.5.8) - postcss-image-set-function: 7.0.0(postcss@8.5.8) - postcss-lab-function: 7.0.12(postcss@8.5.8) - postcss-logical: 8.1.0(postcss@8.5.8) - postcss-nesting: 13.0.2(postcss@8.5.8) - postcss-opacity-percentage: 3.0.0(postcss@8.5.8) - postcss-overflow-shorthand: 6.0.0(postcss@8.5.8) - postcss-page-break: 3.0.4(postcss@8.5.8) - postcss-place: 10.0.0(postcss@8.5.8) - postcss-pseudo-class-any-link: 10.0.1(postcss@8.5.8) - postcss-replace-overflow-wrap: 4.0.0(postcss@8.5.8) - postcss-selector-not: 8.0.1(postcss@8.5.8) - - postcss-pseudo-class-any-link@10.0.1(postcss@8.5.8): - dependencies: - postcss: 8.5.8 + postcss: 8.5.10 + postcss-attribute-case-insensitive: 7.0.1(postcss@8.5.10) + postcss-clamp: 4.1.0(postcss@8.5.10) + postcss-color-functional-notation: 7.0.12(postcss@8.5.10) + postcss-color-hex-alpha: 10.0.0(postcss@8.5.10) + postcss-color-rebeccapurple: 10.0.0(postcss@8.5.10) + postcss-custom-media: 11.0.6(postcss@8.5.10) + postcss-custom-properties: 14.0.6(postcss@8.5.10) + postcss-custom-selectors: 8.0.5(postcss@8.5.10) + postcss-dir-pseudo-class: 9.0.1(postcss@8.5.10) + postcss-double-position-gradients: 6.0.4(postcss@8.5.10) + postcss-focus-visible: 10.0.1(postcss@8.5.10) + postcss-focus-within: 9.0.1(postcss@8.5.10) + postcss-font-variant: 5.0.0(postcss@8.5.10) + postcss-gap-properties: 6.0.0(postcss@8.5.10) + postcss-image-set-function: 7.0.0(postcss@8.5.10) + postcss-lab-function: 7.0.12(postcss@8.5.10) + postcss-logical: 8.1.0(postcss@8.5.10) + postcss-nesting: 13.0.2(postcss@8.5.10) + postcss-opacity-percentage: 3.0.0(postcss@8.5.10) + postcss-overflow-shorthand: 6.0.0(postcss@8.5.10) + postcss-page-break: 3.0.4(postcss@8.5.10) + postcss-place: 10.0.0(postcss@8.5.10) + postcss-pseudo-class-any-link: 10.0.1(postcss@8.5.10) + postcss-replace-overflow-wrap: 4.0.0(postcss@8.5.10) + postcss-selector-not: 8.0.1(postcss@8.5.10) + + postcss-pseudo-class-any-link@10.0.1(postcss@8.5.10): + dependencies: + postcss: 8.5.10 postcss-selector-parser: 7.1.1 - postcss-reduce-idents@6.0.3(postcss@8.5.8): + postcss-reduce-idents@6.0.3(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-reduce-initial@6.1.0(postcss@8.5.8): + postcss-reduce-initial@6.1.0(postcss@8.5.10): dependencies: browserslist: 4.28.1 caniuse-api: 3.0.0 - postcss: 8.5.8 + postcss: 8.5.10 - postcss-reduce-transforms@6.0.2(postcss@8.5.8): + postcss-reduce-transforms@6.0.2(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-value-parser: 4.2.0 - postcss-replace-overflow-wrap@4.0.0(postcss@8.5.8): + postcss-replace-overflow-wrap@4.0.0(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 - postcss-selector-not@8.0.1(postcss@8.5.8): + postcss-selector-not@8.0.1(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-selector-parser: 7.1.1 postcss-selector-parser@6.1.2: @@ -23324,35 +23337,29 @@ snapshots: cssesc: 3.0.0 util-deprecate: 1.0.2 - postcss-sort-media-queries@5.2.0(postcss@8.5.8): + postcss-sort-media-queries@5.2.0(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 sort-css-media-queries: 2.2.0 - postcss-svgo@6.0.3(postcss@8.5.8): + postcss-svgo@6.0.3(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-value-parser: 4.2.0 svgo: 3.3.3 - postcss-unique-selectors@6.0.4(postcss@8.5.8): + postcss-unique-selectors@6.0.4(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 postcss-selector-parser: 6.1.2 postcss-value-parser@4.2.0: {} - postcss-zindex@6.0.2(postcss@8.5.8): + postcss-zindex@6.0.2(postcss@8.5.10): dependencies: - postcss: 8.5.8 + postcss: 8.5.10 - postcss@8.5.6: - dependencies: - nanoid: 3.3.11 - picocolors: 1.1.1 - source-map-js: 1.2.1 - - postcss@8.5.8: + postcss@8.5.10: dependencies: nanoid: 3.3.11 picocolors: 1.1.1 @@ -24021,7 +24028,7 @@ snapshots: dependencies: escalade: 3.2.0 picocolors: 1.1.1 - postcss: 8.5.8 + postcss: 8.5.10 strip-json-comments: 3.1.1 run-applescript@7.1.0: {} @@ -24169,7 +24176,7 @@ snapshots: semver: 7.7.3 sequelize-pool: 7.1.0 toposort-class: 1.0.1 - uuid: 14.0.0 + uuid: 8.3.2 validator: 13.15.23 wkx: 0.5.0 optionalDependencies: @@ -24365,7 +24372,7 @@ snapshots: sockjs@0.3.24: dependencies: faye-websocket: 0.11.4 - uuid: 14.0.0 + uuid: 8.3.2 websocket-driver: 0.7.4 sort-css-media-queries@2.2.0: {} @@ -24607,10 +24614,10 @@ snapshots: dependencies: inline-style-parser: 0.2.7 - stylehacks@6.1.1(postcss@8.5.8): + stylehacks@6.1.1(postcss@8.5.10): dependencies: browserslist: 4.28.1 - postcss: 8.5.8 + postcss: 8.5.10 postcss-selector-parser: 6.1.2 stylis@4.3.6: {} @@ -24687,11 +24694,11 @@ snapshots: normalize-path: 3.0.0 object-hash: 3.0.0 picocolors: 1.1.1 - postcss: 8.5.6 - postcss-import: 15.1.0(postcss@8.5.6) - postcss-js: 4.1.0(postcss@8.5.6) - postcss-load-config: 6.0.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(yaml@2.8.3) - postcss-nested: 6.2.0(postcss@8.5.6) + postcss: 8.5.10 + postcss-import: 15.1.0(postcss@8.5.10) + postcss-js: 4.1.0(postcss@8.5.10) + postcss-load-config: 6.0.1(jiti@2.6.1)(postcss@8.5.10)(tsx@4.21.0)(yaml@2.8.3) + postcss-nested: 6.2.0(postcss@8.5.10) postcss-selector-parser: 6.1.2 resolve: 1.22.11 sucrase: 3.35.1 @@ -25139,7 +25146,15 @@ snapshots: utils-merge@1.0.1: {} - uuid@14.0.0: {} + uuid@10.0.0: {} + + uuid@11.0.5: {} + + uuid@11.1.0: {} + + uuid@3.4.0: {} + + uuid@8.3.2: {} validate-npm-package-license@3.0.4: dependencies: @@ -25175,7 +25190,7 @@ snapshots: dependencies: lightningcss: 1.32.0 picomatch: 4.0.4 - postcss: 8.5.8 + postcss: 8.5.10 rolldown: 1.0.0-rc.12(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1) tinyglobby: 0.2.15 optionalDependencies: @@ -25195,7 +25210,7 @@ snapshots: dependencies: lightningcss: 1.32.0 picomatch: 4.0.4 - postcss: 8.5.8 + postcss: 8.5.10 rolldown: 1.0.0-rc.12(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1) tinyglobby: 0.2.15 optionalDependencies: From e7d8ae1898a097dc92300e48fab79a7e889040a6 Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Fri, 24 Apr 2026 12:21:50 -0400 Subject: [PATCH 10/88] update snyke ignore --- .snyk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.snyk b/.snyk index 6098d09c3..aa06cdae5 100644 --- a/.snyk +++ b/.snyk @@ -54,7 +54,7 @@ ignore: created: '2026-03-12T12:35:00.000Z' 'SNYK-JS-UUID-16133035': - - '* > uuid@11.1.0': + - '* > uuid': reason: 'Required for Azurite compatibility.' expires: '2026-10-24T00:00:00.000Z' created: '2026-04-24T11:48:00.000Z' From 19531b8e36e5792f65d7063ab2b7441652ad63f4 Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Mon, 27 Apr 2026 12:25:14 -0400 Subject: [PATCH 11/88] update layout and styling in ThemeProvider component --- apps/ui-staff/src/contexts/theme-context.tsx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/apps/ui-staff/src/contexts/theme-context.tsx b/apps/ui-staff/src/contexts/theme-context.tsx index 9e266740c..62e172f9f 100644 --- a/apps/ui-staff/src/contexts/theme-context.tsx +++ b/apps/ui-staff/src/contexts/theme-context.tsx @@ -143,7 +143,7 @@ export const ThemeProvider = ({ children }: { children: ReactNode }) => {
-
+
- - {/* */}
-

+

Hit Cmd+Shift+K to hide -

+

{children}
From c8d30dec83c512501517a54c94f6cb25a846ba03 Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Mon, 27 Apr 2026 15:41:42 -0400 Subject: [PATCH 12/88] fix: update dev script to use correct localhost domain --- apps/ui-staff/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ui-staff/package.json b/apps/ui-staff/package.json index 7d9d6c7e4..8d9b0cdff 100644 --- a/apps/ui-staff/package.json +++ b/apps/ui-staff/package.json @@ -9,7 +9,7 @@ "format:check": "biome format .", "prebuild": "pnpm run lint", "build": "tsc --build && vite build", - "dev": "node ../../build-pipeline/scripts/portless-dev.mjs staff.localhost vite", + "dev": "node ../../build-pipeline/scripts/portless-dev.mjs staff.ownercommunity.localhost vite", "start": "vite", "preview": "vite preview", "test": "vitest run --silent --reporter=dot", From 3385ed1155c8145870faf745fdc0e57b9fdaef0c Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Tue, 28 Apr 2026 12:17:02 -0400 Subject: [PATCH 13/88] feat: integrate StaffAuthProvider for user identity management --- apps/ui-staff/src/App.tsx | 27 +++++-- .../ocom/ui-staff-route-shared/src/index.tsx | 2 +- .../src/staff-route-shell.tsx | 78 ++++++++++++++++++- 3 files changed, 95 insertions(+), 12 deletions(-) diff --git a/apps/ui-staff/src/App.tsx b/apps/ui-staff/src/App.tsx index 7a690bd19..338df3406 100644 --- a/apps/ui-staff/src/App.tsx +++ b/apps/ui-staff/src/App.tsx @@ -5,6 +5,8 @@ import { Root as CommunityManagement } from '@ocom/ui-staff-route-community-mana import { Root as UserManagement } from '@ocom/ui-staff-route-user-management'; import { Root as Finance } from '@ocom/ui-staff-route-finance'; import { Root as TechAdmin } from '@ocom/ui-staff-route-tech-admin'; +import { StaffAuthProvider } from '@ocom/ui-staff-route-shared'; +import { useAuth } from 'react-oidc-context'; import './App.css'; import { ApolloConnection } from './components/ui/organisms/apollo-connection/index.tsx'; import { AuthLanding } from './components/ui/molecules/auth-landing/index.tsx'; @@ -12,6 +14,15 @@ import { Unauthorized } from './unauthorized.tsx'; export default function App() { const rootSection = ; + const auth = useAuth(); + + // Build a best-effort identity object to supply to shared placeholders + + // Provide a best-effort raw profile to the shared staff shell. StaffRouteShell will + // attempt to extract display name and roles from this raw profile. + const identity = { + raw: (auth?.user?.profile as Record) ?? undefined, + }; const authSection = ( @@ -21,13 +32,15 @@ export default function App() { const staffSection = ( - - } /> - } /> - } /> - } /> - } /> - + + + } /> + } /> + } /> + } /> + } /> + + ); diff --git a/packages/ocom/ui-staff-route-shared/src/index.tsx b/packages/ocom/ui-staff-route-shared/src/index.tsx index 458ff69d6..456f74eb3 100644 --- a/packages/ocom/ui-staff-route-shared/src/index.tsx +++ b/packages/ocom/ui-staff-route-shared/src/index.tsx @@ -1,5 +1,5 @@ import { createElement, type FC } from 'react'; import { SectionLayout } from './section-layout.tsx'; -export { StaffRouteShell, type StaffRouteShellProps } from './staff-route-shell.tsx'; +export { StaffRouteShell, type StaffRouteShellProps, StaffAuthContext, StaffAuthProvider, type StaffAuth } from './staff-route-shell.tsx'; export const Root: FC = () => createElement(SectionLayout); diff --git a/packages/ocom/ui-staff-route-shared/src/staff-route-shell.tsx b/packages/ocom/ui-staff-route-shared/src/staff-route-shell.tsx index a256b0aed..1f8504c81 100644 --- a/packages/ocom/ui-staff-route-shared/src/staff-route-shell.tsx +++ b/packages/ocom/ui-staff-route-shared/src/staff-route-shell.tsx @@ -1,10 +1,24 @@ -import type { FC } from 'react'; +import { type FC, createContext, useContext, type ReactNode } from 'react'; export interface StaffRouteShellProps { title: string; description: string; } +export type StaffAuth = { + name?: string; + username?: string; + email?: string; + roles?: string[]; + raw?: Record; +}; + +export const StaffAuthContext = createContext(undefined); + +export const StaffAuthProvider: FC<{ value: StaffAuth; children?: ReactNode }> = ({ value, children }) => ( + {children} +); + const navLinks = [ { label: 'Community Management', href: '/staff/community' }, { label: 'User Management', href: '/staff/users' }, @@ -12,13 +26,53 @@ const navLinks = [ { label: 'Tech Admin', href: '/staff/tech' }, ]; +const extractRoles = (raw: Record | undefined): string[] | undefined => { + if (!raw) return undefined; + const r = raw as Record; + const candidates: Array = [ + (r['roles'] as string | string[] | undefined), + (r['role'] as string | string[] | undefined), + (r['groups'] as string | string[] | undefined), + (r['app_roles'] as string | string[] | undefined), + ((r['realm_access'] as Record | undefined)?.['roles'] as string[] | undefined), + ]; + const roles: string[] = []; + for (const c of candidates) { + if (Array.isArray(c)) { + roles.push(...c.filter((x) => typeof x === 'string') as string[]); + } else if (typeof c === 'string') { + roles.push(c); + } + } + return roles.length ? Array.from(new Set(roles)) : undefined; +}; + export const StaffRouteShell: FC = ({ title, description }) => { + const auth = useContext(StaffAuthContext); + const raw = auth?.raw as Record | undefined; + const fallbackName = raw ? ((raw['name'] as string | undefined) ?? (raw['preferred_username'] as string | undefined) ?? (raw['email'] as string | undefined)) : undefined; + const name = auth?.name ?? auth?.username ?? auth?.email ?? fallbackName; + const roles = auth?.roles ?? extractRoles(auth?.raw); + return (
-
-
{title}
-
{description}
+
+
+
{title}
+
{description}
+
+
+
Placeholder
+ { name ? ( +
+
Signed in as
+
{name}
+
+ ) : ( +
Not signed in
+ )} +
From 0a7817fe584c95856b3f777a773c3452b3ffa2ad Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Wed, 29 Apr 2026 10:14:31 -0400 Subject: [PATCH 14/88] update OIDC configuration and add mock data for staff authentication --- .../service-config/token-validation/index.ts | 2 +- apps/ui-staff/.gitignore | 26 ++++++++++++++++ apps/ui-staff/dist/index.html | 2 +- apps/ui-staff/mock-oidc.json | 14 +++++++++ apps/ui-staff/src/config/oidc-config.tsx | 30 +++++++++++++++---- 5 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 apps/ui-staff/.gitignore create mode 100644 apps/ui-staff/mock-oidc.json diff --git a/apps/api/src/service-config/token-validation/index.ts b/apps/api/src/service-config/token-validation/index.ts index 46070d09e..001e9b7a0 100644 --- a/apps/api/src/service-config/token-validation/index.ts +++ b/apps/api/src/service-config/token-validation/index.ts @@ -1,4 +1,4 @@ export const portalTokens = new Map([ ['AccountPortal', 'ACCOUNT_PORTAL'], - // ['StaffPortal', 'STAFF_PORTAL'], + ['StaffPortal', 'STAFF_PORTAL'], ]); diff --git a/apps/ui-staff/.gitignore b/apps/ui-staff/.gitignore new file mode 100644 index 000000000..893233b1a --- /dev/null +++ b/apps/ui-staff/.gitignore @@ -0,0 +1,26 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local +tsconfig.tsbuildinfo + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? +.env diff --git a/apps/ui-staff/dist/index.html b/apps/ui-staff/dist/index.html index 11ea063ba..a2ff4ca2a 100644 --- a/apps/ui-staff/dist/index.html +++ b/apps/ui-staff/dist/index.html @@ -5,7 +5,7 @@ Staff UI - + diff --git a/apps/ui-staff/mock-oidc.json b/apps/ui-staff/mock-oidc.json new file mode 100644 index 000000000..4ebe8093e --- /dev/null +++ b/apps/ui-staff/mock-oidc.json @@ -0,0 +1,14 @@ +{ + "name": "staff", + "envVars": { + "clientId": "VITE_AAD_B2C_STAFF_CLIENTID", + "redirectUri": "VITE_AAD_B2C_STAFF_REDIRECT_URI" + }, + "claims": { + "sub": "10000000-0000-4000-8000-000000000001", + "email": "staff@sharethrift.onmicrosoft.com", + "given_name": "Staff", + "family_name": "User", + "tid": "test-staff-tenant-id" + } +} diff --git a/apps/ui-staff/src/config/oidc-config.tsx b/apps/ui-staff/src/config/oidc-config.tsx index f5ce248ad..726c72774 100644 --- a/apps/ui-staff/src/config/oidc-config.tsx +++ b/apps/ui-staff/src/config/oidc-config.tsx @@ -1,13 +1,31 @@ -export const oidcConfig = { - // minimal placeholder config for local development - authority: import.meta.env.VITE_AAD_B2C_ACCOUNT_AUTHORITY ?? 'https://mock-auth.staff.localhost', - client_id: import.meta.env.VITE_AAD_B2C_ACCOUNT_CLIENTID ?? 'mock-client', - redirect_uri: import.meta.env.VITE_AAD_B2C_REDIRECT_URI ?? 'https://staff.localhost/auth-redirect', +type OIDCConfig = { + authority: string; + client_id: string; + redirect_uri: string; + code_verifier: boolean; + noonce: boolean; + response_type: string; + scope: string; + onSigninCallback: () => void; +}; + +export const oidcConfig: OIDCConfig = { + authority: + // biome-ignore lint:useLiteralKeys + import.meta.env['VITE_AAD_B2C_STAFF_AUTHORITY'] ?? 'https://mock-auth.ownercommunity.localhost:1355/staff', + // biome-ignore lint:useLiteralKeys + client_id: import.meta.env['VITE_AAD_B2C_STAFF_CLIENTID'] ?? 'mock-client', + + redirect_uri: + // biome-ignore lint:useLiteralKeys + import.meta.env['VITE_AAD_B2C_STAFF_REDIRECT_URI'] ?? 'https://staff.ownercommunity.localhost:1355/auth-redirect', code_verifier: true, noonce: true, response_type: 'code', - scope: import.meta.env.VITE_AAD_B2C_ACCOUNT_SCOPES, + // biome-ignore lint:useLiteralKeys + scope: import.meta.env['VITE_AAD_B2C_STAFF_SCOPES'], onSigninCallback: (): void => { + console.log('onSigninCallback'); globalThis.history.replaceState({}, document.title, globalThis.location.pathname); const redirectToPath = globalThis.sessionStorage.getItem('redirectTo'); if (redirectToPath) { From 0095df38c699194a365561814f7fc6273231f207 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Wed, 29 Apr 2026 20:09:17 +0530 Subject: [PATCH 15/88] feat: implement login page and update routing for authentication --- apps/ui-staff/src/App.test.tsx | 33 ++++--- apps/ui-staff/src/App.tsx | 65 ++++++++++--- .../ui/molecules/login-page/index.tsx | 93 +++++++++++++++++++ 3 files changed, 165 insertions(+), 26 deletions(-) create mode 100644 apps/ui-staff/src/components/ui/molecules/login-page/index.tsx diff --git a/apps/ui-staff/src/App.test.tsx b/apps/ui-staff/src/App.test.tsx index 2cc024463..557272063 100644 --- a/apps/ui-staff/src/App.test.tsx +++ b/apps/ui-staff/src/App.test.tsx @@ -1,33 +1,35 @@ -import { describe, it, expect, vi } from 'vitest'; import * as React from 'react'; -import { MemoryRouter } from 'react-router-dom'; import { renderToString } from 'react-dom/server'; +import { MemoryRouter } from 'react-router-dom'; +import { describe, expect, it, vi } from 'vitest'; // Mock RequireAuth from @cellix/ui-core so tests don't depend on oidc context behavior vi.mock('@cellix/ui-core', () => ({ RequireAuth: ({ children }: { children: React.ReactNode }) => React.createElement(React.Fragment, {}, children), })); +// Mock react-oidc-context so login page renders without auth context +vi.mock('react-oidc-context', () => ({ + useAuth: () => ({ isLoading: false, activeNavigator: undefined, isAuthenticated: false, error: undefined, signinRedirect: vi.fn() }), +})); + import App from './App'; describe('App', () => { - it('renders root section without throwing', () => { + it('renders login page at root without throwing', () => { const html = renderToString( - MemoryRouter ? ( - - - - ) : ( + - ), + , ); expect(typeof html).toBe('string'); expect(html.length).toBeGreaterThan(0); + expect(html).toContain('Staff Portal'); }); it('renders auth-redirect route without throwing', () => { const html = renderToString( - + , ); @@ -37,11 +39,20 @@ describe('App', () => { it('renders unauthorized route without throwing and contains Unauthorized text', () => { const html = renderToString( - + , ); expect(typeof html).toBe('string'); expect(html).toContain('Unauthorized'); }); + + it('redirects unknown routes to root', () => { + const html = renderToString( + + + , + ); + expect(typeof html).toBe('string'); + }); }); diff --git a/apps/ui-staff/src/App.tsx b/apps/ui-staff/src/App.tsx index 338df3406..766eb5acf 100644 --- a/apps/ui-staff/src/App.tsx +++ b/apps/ui-staff/src/App.tsx @@ -1,19 +1,18 @@ import { RequireAuth } from '@cellix/ui-core'; -import { Route, Routes } from 'react-router-dom'; -import { Root } from '@ocom/ui-staff-route-root'; import { Root as CommunityManagement } from '@ocom/ui-staff-route-community-management'; -import { Root as UserManagement } from '@ocom/ui-staff-route-user-management'; import { Root as Finance } from '@ocom/ui-staff-route-finance'; -import { Root as TechAdmin } from '@ocom/ui-staff-route-tech-admin'; import { StaffAuthProvider } from '@ocom/ui-staff-route-shared'; +import { Root as TechAdmin } from '@ocom/ui-staff-route-tech-admin'; +import { Root as UserManagement } from '@ocom/ui-staff-route-user-management'; import { useAuth } from 'react-oidc-context'; +import { Navigate, Route, Routes } from 'react-router-dom'; import './App.css'; -import { ApolloConnection } from './components/ui/organisms/apollo-connection/index.tsx'; import { AuthLanding } from './components/ui/molecules/auth-landing/index.tsx'; +import { LoginPage } from './components/ui/molecules/login-page/index.tsx'; +import { ApolloConnection } from './components/ui/organisms/apollo-connection/index.tsx'; import { Unauthorized } from './unauthorized.tsx'; export default function App() { - const rootSection = ; const auth = useAuth(); // Build a best-effort identity object to supply to shared placeholders @@ -34,11 +33,26 @@ export default function App() { - } /> - } /> - } /> - } /> - } /> + } + /> + } + /> + } + /> + } + /> + } + /> @@ -47,10 +61,31 @@ export default function App() { return ( - - - } /> - + } + /> + + } + /> + + + } + /> ); diff --git a/apps/ui-staff/src/components/ui/molecules/login-page/index.tsx b/apps/ui-staff/src/components/ui/molecules/login-page/index.tsx new file mode 100644 index 000000000..4ccb03151 --- /dev/null +++ b/apps/ui-staff/src/components/ui/molecules/login-page/index.tsx @@ -0,0 +1,93 @@ +import { Button, Card, Col, Row, Space, Spin, Typography } from 'antd'; +import type { FC } from 'react'; +import { useAuth } from 'react-oidc-context'; +import { Navigate } from 'react-router-dom'; + +const { Title, Paragraph } = Typography; + +export const LoginPage: FC = () => { + const auth = useAuth(); + + if (auth.isLoading || auth.activeNavigator) { + return ( + + + + Please wait... + + + ); + } + + if (auth.isAuthenticated) { + return ( + + ); + } + + return ( + + + + +
+ + Staff Portal + + + Sign in to access the CellixJS staff dashboard. + +
+ + {auth.error && Sign-in failed: {auth.error.message}} + + +
+
+ +
+ ); +}; From 7124050fbe4ef177af551c5f312cc5638befb910 Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Wed, 29 Apr 2026 12:17:02 -0400 Subject: [PATCH 16/88] fix build issue --- packages/ocom/graphql/src/schema/builder/resolver-builder.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/ocom/graphql/src/schema/builder/resolver-builder.ts b/packages/ocom/graphql/src/schema/builder/resolver-builder.ts index 3c58020e7..36c166850 100644 --- a/packages/ocom/graphql/src/schema/builder/resolver-builder.ts +++ b/packages/ocom/graphql/src/schema/builder/resolver-builder.ts @@ -1,10 +1,11 @@ import { mergeResolvers } from '@graphql-tools/merge'; import type { Resolvers } from './generated.ts'; +import endUserRoleResolvers from '../types/end-user-role.resolvers.ts'; import { ocomGraphqlPermissions, ocomGraphqlResolvers } from './resolver-manifest.generated.ts'; function mergeResolverModules(modules: Resolvers[]): Resolvers { return (modules.length === 0 ? {} : mergeResolvers(modules)) as Resolvers; } -export const resolvers: Resolvers = mergeResolverModules(ocomGraphqlResolvers); +export const resolvers: Resolvers = mergeResolverModules([...ocomGraphqlResolvers, endUserRoleResolvers]); export const permissions: Resolvers = mergeResolverModules(ocomGraphqlPermissions); From cdcdab13b75cbb84e640345114a78d444ecf5de7 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Wed, 29 Apr 2026 21:55:06 +0530 Subject: [PATCH 17/88] chore: update TypeScript version to 6.0.3 in pnpm-lock.yaml --- pnpm-lock.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7e12e54f7..11d6bbc31 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -581,7 +581,7 @@ importers: version: 3.4.18(tsx@4.21.0)(yaml@2.8.3) typescript: specifier: 'catalog:' - version: 6.0.2 + version: 6.0.3 vite: specifier: 8.0.5 version: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) @@ -1873,7 +1873,7 @@ importers: version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) typescript: specifier: 'catalog:' - version: 6.0.2 + version: 6.0.3 vite: specifier: 8.0.5 version: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) @@ -1916,7 +1916,7 @@ importers: version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) typescript: specifier: 'catalog:' - version: 6.0.2 + version: 6.0.3 vite: specifier: 8.0.5 version: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) @@ -1968,7 +1968,7 @@ importers: version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) typescript: specifier: 'catalog:' - version: 6.0.2 + version: 6.0.3 vite: specifier: 8.0.5 version: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) @@ -1999,7 +1999,7 @@ importers: version: 26.1.0 typescript: specifier: 'catalog:' - version: 6.0.2 + version: 6.0.3 vite: specifier: 8.0.5 version: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) @@ -2039,7 +2039,7 @@ importers: version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) typescript: specifier: 'catalog:' - version: 6.0.2 + version: 6.0.3 vite: specifier: 8.0.5 version: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) @@ -2076,7 +2076,7 @@ importers: version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) typescript: specifier: 'catalog:' - version: 6.0.2 + version: 6.0.3 vite: specifier: 8.0.5 version: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) From be5783e6763bdfead4da4ee5889e8dc1c7c3d332 Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Wed, 29 Apr 2026 12:29:29 -0400 Subject: [PATCH 18/88] refine login page and add logout functionality --- apps/ui-staff/src/App.tsx | 4 + .../ui/molecules/login-page/index.tsx | 89 ++++--------------- .../src/staff-route-shell.tsx | 21 +++++ 3 files changed, 41 insertions(+), 73 deletions(-) diff --git a/apps/ui-staff/src/App.tsx b/apps/ui-staff/src/App.tsx index 766eb5acf..192baf174 100644 --- a/apps/ui-staff/src/App.tsx +++ b/apps/ui-staff/src/App.tsx @@ -21,6 +21,10 @@ export default function App() { // attempt to extract display name and roles from this raw profile. const identity = { raw: (auth?.user?.profile as Record) ?? undefined, + onLogout: () => + auth.signoutRedirect({ + post_logout_redirect_uri: globalThis.location.origin, + }), }; const authSection = ( diff --git a/apps/ui-staff/src/components/ui/molecules/login-page/index.tsx b/apps/ui-staff/src/components/ui/molecules/login-page/index.tsx index 4ccb03151..b89f6a3bb 100644 --- a/apps/ui-staff/src/components/ui/molecules/login-page/index.tsx +++ b/apps/ui-staff/src/components/ui/molecules/login-page/index.tsx @@ -1,31 +1,13 @@ -import { Button, Card, Col, Row, Space, Spin, Typography } from 'antd'; -import type { FC } from 'react'; +import { Button, Typography } from 'antd'; +import type React from 'react'; import { useAuth } from 'react-oidc-context'; import { Navigate } from 'react-router-dom'; -const { Title, Paragraph } = Typography; +const { Title } = Typography; -export const LoginPage: FC = () => { +export const LoginPage: React.FC = () => { const auth = useAuth(); - if (auth.isLoading || auth.activeNavigator) { - return ( - - - - Please wait... - - - ); - } - if (auth.isAuthenticated) { return ( { } return ( - - - +
+ Staff Portal + - - - - + Login + +
+
); }; diff --git a/packages/ocom/ui-staff-route-shared/src/staff-route-shell.tsx b/packages/ocom/ui-staff-route-shared/src/staff-route-shell.tsx index 1f8504c81..30d342d5a 100644 --- a/packages/ocom/ui-staff-route-shared/src/staff-route-shell.tsx +++ b/packages/ocom/ui-staff-route-shared/src/staff-route-shell.tsx @@ -11,6 +11,7 @@ export type StaffAuth = { email?: string; roles?: string[]; raw?: Record; + onLogout?: () => Promise | void; }; export const StaffAuthContext = createContext(undefined); @@ -68,6 +69,26 @@ export const StaffRouteShell: FC = ({ title, description }
Signed in as
{name}
+ {auth?.onLogout ? ( + + ) : null}
) : (
Not signed in
From 49f66f81f7843bf65533f46158670d6e9aac5407 Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Wed, 29 Apr 2026 14:30:18 -0400 Subject: [PATCH 19/88] remove dist files --- apps/ui-staff/dist/assets/index-7FJd3hWI.css | 1 - apps/ui-staff/dist/assets/index-D51pPdcv.js | 264 ------------------- apps/ui-staff/dist/index.html | 14 - 3 files changed, 279 deletions(-) delete mode 100644 apps/ui-staff/dist/assets/index-7FJd3hWI.css delete mode 100644 apps/ui-staff/dist/assets/index-D51pPdcv.js delete mode 100644 apps/ui-staff/dist/index.html diff --git a/apps/ui-staff/dist/assets/index-7FJd3hWI.css b/apps/ui-staff/dist/assets/index-7FJd3hWI.css deleted file mode 100644 index acd50b78f..000000000 --- a/apps/ui-staff/dist/assets/index-7FJd3hWI.css +++ /dev/null @@ -1 +0,0 @@ -html,body,#root{height:100%;margin:0;padding:0}.App{text-align:center} diff --git a/apps/ui-staff/dist/assets/index-D51pPdcv.js b/apps/ui-staff/dist/assets/index-D51pPdcv.js deleted file mode 100644 index e264c4f55..000000000 --- a/apps/ui-staff/dist/assets/index-D51pPdcv.js +++ /dev/null @@ -1,264 +0,0 @@ -var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,t)=>()=>(e&&(t=e(e=0)),t),s=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),c=(e,n)=>{let r={};for(var i in e)t(r,i,{get:e[i],enumerable:!0});return n||t(r,Symbol.toStringTag,{value:`Module`}),r},l=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;li[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},u=(n,r,a)=>(a=n==null?{}:e(i(n)),l(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n)),d=e=>a.call(e,`module.exports`)?e[`module.exports`]:l(t({},`__esModule`,{value:!0}),e);(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var f=s((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.consumer`),s=Symbol.for(`react.context`),c=Symbol.for(`react.forward_ref`),l=Symbol.for(`react.suspense`),u=Symbol.for(`react.memo`),d=Symbol.for(`react.lazy`),f=Symbol.for(`react.activity`),p=Symbol.iterator;function m(e){return typeof e!=`object`||!e?null:(e=p&&e[p]||e[`@@iterator`],typeof e==`function`?e:null)}var h={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},g=Object.assign,_={};function v(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}v.prototype.isReactComponent={},v.prototype.setState=function(e,t){if(typeof e!=`object`&&typeof e!=`function`&&e!=null)throw Error(`takes an object of state variables to update or a function which returns an object of state variables.`);this.updater.enqueueSetState(this,e,t,`setState`)},v.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,`forceUpdate`)};function y(){}y.prototype=v.prototype;function b(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}var x=b.prototype=new y;x.constructor=b,g(x,v.prototype),x.isPureReactComponent=!0;var S=Array.isArray;function C(){}var w={H:null,A:null,T:null,S:null},T=Object.prototype.hasOwnProperty;function E(e,n,r){var i=r.ref;return{$$typeof:t,type:e,key:n,ref:i===void 0?null:i,props:r}}function D(e,t){return E(e.type,t,e.props)}function O(e){return typeof e==`object`&&!!e&&e.$$typeof===t}function k(e){var t={"=":`=0`,":":`=2`};return`$`+e.replace(/[=:]/g,function(e){return t[e]})}var A=/\/+/g;function j(e,t){return typeof e==`object`&&e&&e.key!=null?k(``+e.key):t.toString(36)}function M(e){switch(e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason;default:switch(typeof e.status==`string`?e.then(C,C):(e.status=`pending`,e.then(function(t){e.status===`pending`&&(e.status=`fulfilled`,e.value=t)},function(t){e.status===`pending`&&(e.status=`rejected`,e.reason=t)})),e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason}}throw e}function N(e,r,i,a,o){var s=typeof e;(s===`undefined`||s===`boolean`)&&(e=null);var c=!1;if(e===null)c=!0;else switch(s){case`bigint`:case`string`:case`number`:c=!0;break;case`object`:switch(e.$$typeof){case t:case n:c=!0;break;case d:return c=e._init,N(c(e._payload),r,i,a,o)}}if(c)return o=o(e),c=a===``?`.`+j(e,0):a,S(o)?(i=``,c!=null&&(i=c.replace(A,`$&/`)+`/`),N(o,r,i,``,function(e){return e})):o!=null&&(O(o)&&(o=D(o,i+(o.key==null||e&&e.key===o.key?``:(``+o.key).replace(A,`$&/`)+`/`)+c)),r.push(o)),1;c=0;var l=a===``?`.`:a+`:`;if(S(e))for(var u=0;u{t.exports=f()})),m=u(p()),h=function(e){return e.CHARSET=`charset`,e.CSS_TEXT=`cssText`,e.HREF=`href`,e.HTTPEQUIV=`http-equiv`,e.INNER_HTML=`innerHTML`,e.ITEM_PROP=`itemprop`,e.NAME=`name`,e.PROPERTY=`property`,e.REL=`rel`,e.SRC=`src`,e}({}),g=function(e){return e.BASE=`base`,e.BODY=`body`,e.HEAD=`head`,e.HTML=`html`,e.LINK=`link`,e.META=`meta`,e.NOSCRIPT=`noscript`,e.SCRIPT=`script`,e.STYLE=`style`,e.TITLE=`title`,e.FRAGMENT=`Symbol(react.fragment)`,e}({}),_={link:{rel:[`amphtml`,`canonical`,`alternate`]},meta:{charset:``,name:[`generator`,`robots`,`description`],property:[`og:type`,`og:title`,`og:url`,`og:image`,`og:image:alt`,`og:description`,`twitter:url`,`twitter:title`,`twitter:description`,`twitter:image`,`twitter:image:alt`,`twitter:card`,`twitter:site`]},script:{type:[`application/ld+json`]}},v=Object.values(g),y={accesskey:`accessKey`,charset:`charSet`,class:`className`,contenteditable:`contentEditable`,contextmenu:`contextMenu`,"http-equiv":`httpEquiv`,itemprop:`itemProp`,tabindex:`tabIndex`},b=(()=>{let e={};for(let[t,n]of Object.entries(y))e[n]=t;return e})(),x=`data-rh`,S=!!(typeof window<`u`&&window.document.createElement);function C(e,t){for(let n=e.length-1;n>=0;--n){let r=e[n][1][t];if(r!==void 0)return r}}function w(e){let t=C(e,g.TITLE),n=C(e,`titleTemplate`);if(Array.isArray(t)&&(t=t.join(``)),n&&t)return n.replace(/%s/g,()=>t);let r=C(e,`defaultTitle`);return(t||r)??void 0}function T(e,t){let n={};for(let r of t){let t=r[1][e];t&&Object.assign(n,t)}return n}function E(e){for(let t=e.length-1;t>=0;--t){let n=e[t][1].base;if(n?.href)return n}}function D(e,t){let n;for(let r of Object.keys(e)){let i=r;t.includes(i)&&!(n===h.REL&&e[n].toLowerCase()===`canonical`)&&!(i===h.REL&&e[i].toLowerCase()===`stylesheet`)&&(n=i),t.includes(i)&&(i===h.INNER_HTML||i===h.CSS_TEXT||i===h.ITEM_PROP)&&(n=i)}return n??null}function O(e,t,n){let r={};return n.map(([,e])=>e).filter(t=>Array.isArray(t[e])?!0:(t[e]!==void 0&&console.warn(`Helmet: ${e} should be of type "Array". Instead found type "${typeof t[e]}"`),!1)).map(t=>t[e]).reverse().reduce((e,n)=>{let i={};n.filter(e=>{let n=D(e,t);if(!n||!e[n])return!1;let a=e[n].toLowerCase();return r[n]||(r[n]={}),i[n]||(i[n]={}),r[n][a]?!1:(i[n][a]=!0,!0)}).reverse().forEach(t=>e.push(t));let a=Object.keys(i);for(let e of a)r[e]={...r[e],...i[e]};return e},[]).reverse()}function k(e,t){for(let[,n]of e)if(n[t])return!0;return!1}function A(e){return Array.isArray(e)?e.join(``):e}function j(e,t){for(let n of Object.keys(e))if(t[n]?.includes(e[n]))return!0;return!1}function M(e,t){let n={default:[],priority:[]};if(e)for(let r of e)j(r,t)?n.priority.push(r):n.default.push(r);return n}function N(e){let t={};for(let[n,r]of Object.entries(e))t[n]=Array.isArray(r)?r.slice():r;return t}function P(e,t){let n=e;for(let[e,r]of Object.entries(t))if(Array.isArray(r)){let t=n[e];n[e]=t?t.concat(r):r}else n[e]=r}function F(e,t,n){let r=e[t];r?r.push(n):e[t]=[n]}function I(e){let t=O(g.LINK,[h.REL,h.HREF],e),n=O(`meta`,[h.NAME,`charSet`,`httpEquiv`,h.PROPERTY,`itemProp`],e),r=O(`script`,[h.SRC,h.INNER_HTML],e),i=k(e,`prioritizeSeoTags`),a;if(i){let e=M(t,_.link);t=e.default;let i=M(n,_.meta);n=i.default;let o=M(r,_.script);r=o.default,a={links:e.priority,meta:i.priority,script:o.priority}}return{base:E(e),bodyAttributes:T(`bodyAttributes`,e),defer:C(e,`defer`),encodeSpecialCharacters:C(e,`encodeSpecialCharacters`)??!0,htmlAttributes:T(`htmlAttributes`,e),links:t,meta:n,noscript:O(`noscript`,[h.INNER_HTML],e),onChangeClientState:C(e,`onChangeClientState`),priority:a,script:r,style:O(`style`,[h.CSS_TEXT],e),title:w(e),titleAttributes:T(`titleAttributes`,e)}}function L(e){return b[e]??e}var ee=s((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.fragment`);function r(e,n,r){var i=null;if(r!==void 0&&(i=``+r),n.key!==void 0&&(i=``+n.key),`key`in n)for(var a in r={},n)a!==`key`&&(r[a]=n[a]);else r=n;return n=r.ref,{$$typeof:t,type:e,key:i,ref:n===void 0?null:n,props:r}}e.Fragment=n,e.jsx=r,e.jsxs=r})),R=s(((e,t)=>{t.exports=ee()}))(),z=[g.NOSCRIPT,g.SCRIPT,g.STYLE],B=(e,t=!0)=>t?e.replace(/&/g,`&`).replace(//g,`>`).replace(/"/g,`"`).replace(/'/g,`'`):e;function V(e){let t=``;for(let[n,r]of Object.entries(e)){let e=L(n),i=r===void 0?e:`${e}="${r}"`;i&&t&&(t+=` `),t+=i}return t}var te=(e,t,n)=>{let r=V(t);r&&=` ${r}`;let i=A(e);return`${B(i,n)}`};function ne(e,t,n){let r=``;for(let i of t){let t=``,a=Object.entries(i);for(let[e,r]of a)if(!(e===h.INNER_HTML||e===h.CSS_TEXT)){let i=b[e]??e,a;a=r===void 0?i:`${i}="${B(typeof r==`string`?r:String(r),n)}"`,t?t+=` ${a}`:t=a}let o=i.innerHTML??i.cssText??``,s=!z.includes(e);r+=`<${e} ${x}="true" ${t}${s?`/>`:`>${o}`}`}return r}function re(e,t={}){let n={};t.addHelmetDataAttr&&(n[x]=!0),t.addKey!==void 0&&(n.key=t.addKey);for(let[t,r]of Object.entries(e)){let e=y[t]??t;switch(e){case`cssText`:case`innerHTML`:n.dangerouslySetInnerHTML={__html:r};break;default:n[e]=r}}return n}function ie(e,t){return[(0,R.jsx)(`title`,{...re(t,{addHelmetDataAttr:!0}),children:e},e)]}function ae(e,t,n){return(0,m.createElement)(e,re(t,{addHelmetDataAttr:!0,addKey:n}))}function oe(e,t){let n=[];for(let r=0;r(e.state??=I(e.helmets),e.state);return{base:{toComponent(){let e=t().base;return e?oe(`base`,[e]):[]},toString(){let e=t();return e.base?ne(`base`,[e.base],e.encodeSpecialCharacters):``}},bodyAttributes:{toComponent(){let e=t().bodyAttributes;return re(e??{})},toString(){let e=t().bodyAttributes;return V(e??{})}},htmlAttributes:{toComponent(){let e=t().htmlAttributes;return re(e??{})},toString(){let e=t().htmlAttributes;return V(e??{})}},link:{toComponent(){return oe(`link`,t().links??[])},toString(){let e=t();return ne(`link`,e.links??[],e.encodeSpecialCharacters)}},meta:{toComponent(){return oe(`meta`,t().meta??[])},toString(){let e=t();return ne(`meta`,e.meta??[],e.encodeSpecialCharacters)}},noscript:{toComponent(){return oe(`noscript`,t().noscript??[])},toString(){let e=t();return ne(`noscript`,e.noscript??[],e.encodeSpecialCharacters)}},priority:{toComponent(){let e=t();return[...oe(`meta`,e.priority?.meta??[]),...oe(`link`,e.priority?.links??[]),...oe(`script`,e.priority?.script??[])]},toString(){let e=t(),n=ne(`meta`,e.priority?.meta??[],e.encodeSpecialCharacters),r=ne(`link`,e.priority?.links??[],e.encodeSpecialCharacters),i=ne(`script`,e.priority?.script??[],e.encodeSpecialCharacters),a=n;return r&&(a&&(a+=` `),a+=r),i&&(a&&(a+=` `),a+=i),a}},script:{toComponent(){return oe(`script`,t().script??[])},toString(){let e=t();return ne(`script`,e.script??[],e.encodeSpecialCharacters)}},style:{toComponent(){return oe(`style`,t().style??[])},toString(){let e=t();return ne(`style`,e.style??[],e.encodeSpecialCharacters)}},title:{toComponent(){let e=t();return ie(e.title??``,e.titleAttributes??{})},toString(){let e=t();return te(e.title??``,e.titleAttributes??{},e.encodeSpecialCharacters)}}}}function se(e,t){let n=document.head||document.querySelector(g.HEAD),r=n.querySelectorAll(`${e}[${x}]`),i=[],a=[...r],o=[];for(let n of t){let t=document.createElement(e);for(let[e,r]of Object.entries(n))if(Object.prototype.hasOwnProperty.call(n,e)){let i=b[e]??e;i===h.INNER_HTML?t.innerHTML=r:i===h.CSS_TEXT?t.styleSheet?t.styleSheet.cssText=n.cssText:t.appendChild(document.createTextNode(n.cssText)):t.setAttribute(i,r??``)}t.setAttribute(x,`true`);let r={};for(let{name:e,value:n}of t.attributes)r[e]=n;i.push(r);for(let e=0;;++e){if(t.isEqualNode(a[e])){a.splice(e,1);break}if(e>=a.length){o.push(t);break}}}return a.forEach(e=>e.parentNode?.removeChild(e)),o.forEach(e=>n.appendChild(e)),{allTags:i,newTags:o,oldTags:a}}function ce(e,t){let[n]=document.getElementsByTagName(e);if(!n)return;let r=n.getAttribute(x),i=r?r.split(`,`):[],a=[...i],o=[];for(let e of Object.keys(t))o.push(b[e]??e);for(let[e,r]of Object.entries(t)){let t=b[e]??e;n.getAttribute(t)!==r&&n.setAttribute(t,r??``),i.includes(t)||i.push(t);let o=a.indexOf(t);o!==-1&&a.splice(o,1)}for(let e=a.length-1;e>=0;--e)n.removeAttribute(a[e]);i.length===a.length?n.removeAttribute(x):n.getAttribute(`data-rh`)!==o.join(`,`)&&n.setAttribute(x,o.join(`,`))}function le(e,t){e!==void 0&&document.title!==e&&(document.title=A(e)),ce(g.TITLE,t)}function U(e,t){let{base:n,bodyAttributes:r,defer:i,htmlAttributes:a,links:o,meta:s,noscript:c,onChangeClientState:l,script:u,style:d,title:f,titleAttributes:p}=e;ce(g.BODY,r??{}),ce(g.HTML,a??{}),le(f,p);let m={baseTag:se(g.BASE,n?[n]:[]),linkTags:se(g.LINK,o??[]),metaTags:se(g.META,s??[]),noscriptTags:se(g.NOSCRIPT,c??[]),scriptTags:se(g.SCRIPT,u??[]),styleTags:se(g.STYLE,d??[])},h={baseTag:[],bodyAttributes:{},defer:i??!1,htmlAttributes:{},linkTags:[],metaTags:[],noscriptTags:[],onChangeClientState:l??(()=>void 0),scriptTags:[],styleTags:[],title:f??``,titleAttributes:{}},_={},v={};Object.keys(m).forEach(e=>{let{allTags:t,newTags:n,oldTags:r}=m[e];h[e]=t,n.length&&(_[e]=n),r.length&&(v[e]=m[e].oldTags)}),(t||Object.keys(_).length||Object.keys(v).length)&&l?.(h,_,v)}var ue=(0,m.createContext)(void 0),de=({children:e,context:t})=>{let{current:n}=(0,m.useRef)({firstRender:!0,helmets:[],state:void 0}),r=(0,m.useRef)(null);return r.current??={clientApply(){S&&!n.state&&(n.state=I(n.helmets),n.state.defer?n.nextAnimFrameId??=requestAnimationFrame(()=>{n.state??=I(n.helmets),U(n.state,n.firstRender),n.firstRender=!1,delete n.nextAnimFrameId}):(n.nextAnimFrameId!==void 0&&(cancelAnimationFrame(n.nextAnimFrameId),delete n.nextAnimFrameId),U(n.state,n.firstRender),n.firstRender=!1))},update(e,t){let r=n.helmets.findIndex(t=>t[0]===e);r>=0?(delete n.state,t?n.helmets[r][1]=t:n.helmets.splice(r,1)):t&&(delete n.state,n.helmets.push([e,t]))}},t&&(!t.helmet||t.helmet!==n.serverState)&&(n.serverState??=H(n),t.helmet=n.serverState),(0,R.jsx)(ue,{value:r.current,children:e})};function fe(e,t){if(typeof e!=`string`)throw Error(`You may be attempting to nest components within each other, which is not allowed. Refer to our API for more information.`);if(!v.includes(e))throw Error(`Only elements types ${v.join(`, `)} are allowed. Helmet does not support rendering <${e}> elements. Refer to our API for more information.`);if(!(!t||typeof t==`string`||Array.isArray(t)))throw Error(`Helmet expects a string as a child of <${e}>. Did you forget to wrap your children in braces? ( <${e}>{\`\`} ) Refer to our API for more information.`)}function pe(e){let t=y[e];return t&&console.warn(`"${e}" is not a valid JSX prop, replace it by "${t}"`),t??e}function me(e){let t=N(e);for(let t of Object.values(e))if(Array.isArray(t)){for(let e of t)if(e)for(let t of Object.keys(e)){let n=pe(t);n!==t&&(e[n]=e[t],delete e[t])}}else if(t&&typeof t==`object`){let e=t;for(let t of Object.keys(e)){let n=pe(t);n!==t&&(e[n]=e[t],delete e[t])}}return m.Children.forEach(e.children,e=>{if(e==null)return;if(typeof e!=`object`||!(`props`in e))throw Error(`"${typeof e}" is not a valid descendant`);let n,r={};if(e.props)for(let[t,i]of Object.entries(e.props))t===`children`?n=i:r[pe(t)]=i;let{type:i}=e;typeof i==`symbol`&&(i=i.toString()),fe(i,n);function a(e){typeof e!=`string`&&console.error(`child of ${i} element should be a string`)}switch(i){case g.BASE:t.base=r;break;case g.BODY:t.bodyAttributes=r;break;case g.FRAGMENT:P(t,me({children:n}));break;case g.HTML:t.htmlAttributes=r;break;case g.LINK:case g.META:if(n)throw Error(`<${i} /> elements are self-closing and can not contain children. Refer to our API for more information.`);F(t,i,r);break;case g.NOSCRIPT:case g.SCRIPT:n!==void 0&&(a(n),r.innerHTML=n),F(t,i,r);break;case g.STYLE:a(n),r.cssText=n,F(t,i,r);break;case g.TITLE:t.titleAttributes=r,typeof n==`string`?t.title=n:Array.isArray(n)&&(t.title=n.join(``));break;case g.HEAD:default:}}),delete t.children,t}var he=e=>{let t=(0,m.use)(ue);if(!t)throw Error(` component must be within a children tree`);let n=(0,m.useId)();return t.update(n,me(e)),(0,m.useEffect)(()=>{t.update(n,me(e)),t.clientApply()}),(0,m.useEffect)(()=>()=>{t.update(n,void 0),t.clientApply()},[t,n]),null},ge=(0,m.createContext)({description:``,title:``}),_e=({children:e,description:t,extraMetaTags:n,image:r,siteName:i,socialDescription:a,socialTitle:o,title:s,url:c})=>{let l=o||s,u=a||t,d=(0,m.useMemo)(()=>({description:t,image:r,siteName:i,socialDescription:a,socialTitle:o,title:s,url:c}),[t,r,i,a,o,s,c]),f=[];if(n?.length)for(let e=0;e{let t=m.useRef(e);return t.current=e,m.useCallback((...e)=>t.current?.(...e),[])};function ve(){return!!(typeof window<`u`&&window.document&&window.document.createElement)}var ye=ve()?m.useLayoutEffect:m.useEffect,G=(e,t)=>{let n=m.useRef(!0);ye(()=>e(n.current),t),ye(()=>(n.current=!1,()=>{n.current=!0}),[])},be=e=>{let t=m.useRef(!1),[n,r]=m.useState(e);m.useEffect(()=>(t.current=!1,()=>{t.current=!0}),[]);function i(e,n){n&&t.current||r(e)}return[n,i]};function xe(e,t){let[n,r]=(0,m.useState)(e),i=t===void 0?n:t;return G(e=>{e||r(t)},[t]),[i,r]}var Se=s((e=>{var t=Symbol.for(`react.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.provider`),s=Symbol.for(`react.context`),c=Symbol.for(`react.server_context`),l=Symbol.for(`react.forward_ref`),u=Symbol.for(`react.suspense`),d=Symbol.for(`react.suspense_list`),f=Symbol.for(`react.memo`),p=Symbol.for(`react.lazy`);function m(e){if(typeof e==`object`&&e){var m=e.$$typeof;switch(m){case t:switch(e=e.type,e){case r:case a:case i:case u:case d:return e;default:switch(e&&=e.$$typeof,e){case c:case s:case l:case p:case f:case o:return e;default:return m}}case n:return m}}}e.ForwardRef=l,e.isMemo=function(e){return m(e)===f}})),Ce=s(((e,t)=>{t.exports=Se()}));function we(e,t,n){let r=m.useRef({});return(!(`value`in r.current)||n(r.current.condition,t))&&(r.current.value=e(),r.current.condition=t),r.current.value}var Te=Symbol.for(`react.element`),Ee=Symbol.for(`react.transitional.element`),De=Symbol.for(`react.fragment`);function Oe(e){return e&&typeof e==`object`&&(e.$$typeof===Te||e.$$typeof===Ee)&&e.type===De}var ke=Ce(),Ae=Number(m.version.split(`.`)[0]),je=(e,t)=>{typeof e==`function`?e(t):typeof e==`object`&&e&&`current`in e&&(e.current=t)},Me=(...e)=>{let t=e.filter(Boolean);return t.length<=1?t[0]:t=>{e.forEach(e=>{je(e,t)})}},Ne=(...e)=>we(()=>Me(...e),e,(e,t)=>e.length!==t.length||e.every((e,n)=>e!==t[n])),Pe=e=>{if(!e)return!1;if(Fe(e)&&Ae>=19)return!0;let t=(0,ke.isMemo)(e)?e.type.type:e.type;return!(typeof t==`function`&&!t.prototype?.render&&t.$$typeof!==ke.ForwardRef||typeof e==`function`&&!e.prototype?.render&&e.$$typeof!==ke.ForwardRef)};function Fe(e){return(0,m.isValidElement)(e)&&!Oe(e)}var Ie=e=>Fe(e)&&Pe(e),Le=e=>{if(e&&Fe(e)){let t=e;return t.props.propertyIsEnumerable(`ref`)?t.props.ref:t.ref}return null};function Re(e,t){let n=e;for(let e=0;e`u`?Object.keys:Reflect.ownKeys;function We(e,t={}){let{prepareArray:n}=t,r=n||(()=>[]),i=He(e[0]);return e.forEach(e=>{function t(n,a){let o=new Set(a),s=Re(e,n),c=Array.isArray(s);if(c||Ve(s)){if(!o.has(s)){o.add(s);let e=Re(i,n);c?i=Be(i,n,r(e,s)):(!e||typeof e!=`object`)&&(i=Be(i,n,He(s))),Ue(s).forEach(e=>{Object.getOwnPropertyDescriptor(s,e).enumerable&&t([...n,e],o)})}}else i=Be(i,n,s)}t([])}),i}function Ge(...e){return We(e)}var Ke={},qe=[],Je=e=>{qe.push(e)};function Ye(e,t){}function Xe(e,t){}function Ze(){Ke={}}function Qe(e,t,n){!t&&!Ke[n]&&(e(!1,n),Ke[n]=!0)}function $e(e,t){Qe(Ye,e,t)}function et(e,t){Qe(Xe,e,t)}$e.preMessage=Je,$e.resetWarned=Ze,$e.noteOnce=et;function tt(e,t){let n=Object.assign({},e);return Array.isArray(t)&&t.forEach(e=>{delete n[e]}),n}function nt(e,t={}){let n=[];return m.Children.forEach(e,e=>{e==null&&!t.keepEmpty||(Array.isArray(e)?n=n.concat(nt(e)):Oe(e)&&e.props?n=n.concat(nt(e.props.children,t)):n.push(e))}),n}function rt(){}var{resetWarned:it}=$e,at=m.createContext({}),ot=()=>{let e=()=>{};return e.deprecated=rt,e};function st(e){return e instanceof HTMLElement||e instanceof SVGElement}function ct(e){return e&&typeof e==`object`&&st(e.nativeElement)?e.nativeElement:st(e)?e:null}var lt=m.createContext(null);function ut({children:e,onBatchResize:t}){let n=m.useRef(0),r=m.useRef([]),i=m.useContext(lt),a=m.useCallback((e,a,o)=>{n.current+=1;let s=n.current;r.current.push({size:e,element:a,data:o}),Promise.resolve().then(()=>{s===n.current&&(t?.(r.current),r.current=[])}),i?.(e,a,o)},[t,i]);return m.createElement(lt.Provider,{value:a},e)}var dt=new Map;function ft(e){e.forEach(e=>{let{target:t}=e;dt.get(t)?.forEach(e=>e(t))})}var pt;function mt(){return pt||=new ResizeObserver(ft),pt}function ht(e,t){dt.has(e)||(dt.set(e,new Set),mt().observe(e)),dt.get(e).add(t)}function gt(e,t){dt.has(e)&&(dt.get(e).delete(t),dt.get(e).size||(mt().unobserve(e),dt.delete(e)))}function _t(e,t,n,r){let i=m.useRef({width:-1,height:-1,offsetWidth:-1,offsetHeight:-1}),a=W(e=>{let{width:t,height:a}=e.getBoundingClientRect(),{offsetWidth:o,offsetHeight:s}=e,c=Math.floor(t),l=Math.floor(a);if(i.current.width!==c||i.current.height!==l||i.current.offsetWidth!==o||i.current.offsetHeight!==s){let u={width:c,height:l,offsetWidth:o,offsetHeight:s};i.current=u;let d=o===Math.round(t)?t:o,f=s===Math.round(a)?a:s,p={...u,offsetWidth:d,offsetHeight:f};r?.(p,e),Promise.resolve().then(()=>{n?.(p,e)})}}),o=typeof t==`function`,s=m.useRef(0);m.useEffect(()=>{let n=o?t():t;return n&&e?ht(n,a):e&&o&&(s.current+=1),()=>{n&>(n,a)}},[e,o?s.current:t])}function vt(e,t){let{children:n,disabled:r,onResize:i,data:a}=e,o=m.useRef(null),s=m.useContext(lt),c=typeof n==`function`,l=c?n(o):n,u=!c&&m.isValidElement(l)&&Pe(l),d=Ne(u?Le(l):null,o),f=()=>ct(o.current);return m.useImperativeHandle(t,()=>f()),_t(!r,f,i,(e,t)=>{s?.(e,t,a)}),u?m.cloneElement(l,{ref:d}):l}var yt=m.forwardRef(vt);function bt(){return bt=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let i=n?.key||`${xt}-${r}`;return m.createElement(yt,bt({},e,{key:i,ref:r===0?t:void 0}),n)})}var Ct=m.forwardRef(St);Ct.Collection=ut;function wt(e){var t,n,r=``;if(typeof e==`string`||typeof e==`number`)r+=e;else if(typeof e==`object`)if(Array.isArray(e)){var i=e.length;for(t=0;te.length)&&(t=e.length);for(var n=0,r=Array(t);n+setTimeout(e,16),Mt=e=>clearTimeout(e);typeof window<`u`&&`requestAnimationFrame`in window&&(jt=e=>window.requestAnimationFrame(e),Mt=e=>window.cancelAnimationFrame(e));var Nt=0,Pt=new Map;function Ft(e){Pt.delete(e)}var It=(e,t=1)=>{Nt+=1;let n=Nt;function r(t){if(t===0)Ft(n),e();else{let e=jt(()=>{r(t-1)});Pt.set(n,e)}}return r(t),n};It.cancel=e=>{let t=Pt.get(e);return Ft(e),Mt(t)};var Lt=`anticon`,Rt=[`outlined`,`borderless`,`filled`,`underlined`],zt=m.createContext({getPrefixCls:(e,t)=>t||(e?`ant-${e}`:`ant`),iconPrefixCls:Lt}),{Consumer:Bt}=zt,Vt={};function Ht(e){let t=m.useContext(zt),{getPrefixCls:n,direction:r,getPopupContainer:i,renderEmpty:a}=t;return{classNames:Vt,styles:Vt,...t[e],getPrefixCls:n,direction:r,getPopupContainer:i,renderEmpty:a}}function Ut(e){for(var t=0,n,r=0,i=e.length;i>=4;++r,i-=4)n=e.charCodeAt(r)&255|(e.charCodeAt(++r)&255)<<8|(e.charCodeAt(++r)&255)<<16|(e.charCodeAt(++r)&255)<<24,n=(n&65535)*1540483477+((n>>>16)*59797<<16),n^=n>>>24,t=(n&65535)*1540483477+((n>>>16)*59797<<16)^(t&65535)*1540483477+((t>>>16)*59797<<16);switch(i){case 3:t^=(e.charCodeAt(r+2)&255)<<16;case 2:t^=(e.charCodeAt(r+1)&255)<<8;case 1:t^=e.charCodeAt(r)&255,t=(t&65535)*1540483477+((t>>>16)*59797<<16)}return t^=t>>>13,t=(t&65535)*1540483477+((t>>>16)*59797<<16),((t^t>>>15)>>>0).toString(36)}function Wt(e,t){if(!e)return!1;if(e.contains)return e.contains(t);let n=t;for(;n;){if(n===e)return!0;n=n.parentNode}return!1}var Gt=`data-rc-order`,Kt=`data-rc-priority`,qt=`rc-util-key`,Jt=new Map;function Yt({mark:e}={}){return e?e.startsWith(`data-`)?e:`data-${e}`:qt}function Xt(e){return e.attachTo?e.attachTo:document.querySelector(`head`)||document.body}function Zt(e){return e===`queue`?`prependQueue`:e?`prepend`:`append`}function Qt(e){return Array.from((Jt.get(e)||e).children).filter(e=>e.tagName===`STYLE`)}function $t(e,t={}){if(!ve())return null;let{csp:n,prepend:r,priority:i=0}=t,a=Zt(r),o=a===`prependQueue`,s=document.createElement(`style`);s.setAttribute(Gt,a),o&&i&&s.setAttribute(Kt,`${i}`),n?.nonce&&(s.nonce=n?.nonce),s.innerHTML=e;let c=Xt(t),{firstChild:l}=c;if(r){if(o){let e=(t.styles||Qt(c)).filter(e=>[`prepend`,`prependQueue`].includes(e.getAttribute(Gt))?i>=Number(e.getAttribute(Kt)||0):!1);if(e.length)return c.insertBefore(s,e[e.length-1].nextSibling),s}c.insertBefore(s,l)}else c.appendChild(s);return s}function en(e,t={}){let{styles:n}=t;return n||=Qt(Xt(t)),n.find(n=>n.getAttribute(Yt(t))===e)}function tn(e,t={}){let n=en(e,t);n&&Xt(t).removeChild(n)}function nn(e,t){let n=Jt.get(e);if(!n||!Wt(document,n)){let n=$t(``,t),{parentNode:r}=n;Jt.set(e,r),e.removeChild(n)}}function rn(e,t,n={}){let r=Xt(n),i=Qt(r),a={...n,styles:i};nn(r,a);let o=en(t,a);if(o)return a.csp?.nonce&&o.nonce!==a.csp?.nonce&&(o.nonce=a.csp?.nonce),o.innerHTML!==e&&(o.innerHTML=e),o;let s=$t(e,a);return s.setAttribute(Yt(a),t),s}function an(e,t,n=!1){let r=new Set;function i(e,t,a=1){let o=r.has(e);if($e(!o,`Warning: There may be circular references`),o)return!1;if(e===t)return!0;if(n&&a>1)return!1;r.add(e);let s=a+1;if(Array.isArray(e)){if(!Array.isArray(t)||e.length!==t.length)return!1;for(let n=0;ni(e[n],t[n],s)):!1}return!1}return i(e,t)}var on=`%`;function sn(e){return e.join(on)}var cn=0,ln=class{instanceId;constructor(e){this.instanceId=e}cache=new Map;updateTimes=new Map;extracted=new Set;get(e){return this.opGet(sn(e))}opGet(e){return this.cache.get(e)||null}update(e,t){return this.opUpdate(sn(e),t)}opUpdate(e,t){let n=t(this.cache.get(e));n===null?(this.cache.delete(e),this.updateTimes.delete(e)):(this.cache.set(e,n),this.updateTimes.set(e,cn),cn+=1)}},un=`data-token-hash`,dn=`data-css-hash`,fn=`__cssinjs_instance__`;function pn(){let e=Math.random().toString(12).slice(2);if(typeof document<`u`&&document.head&&document.body){let t=document.body.querySelectorAll(`style[data-css-hash]`)||[],{firstChild:n}=document.head;Array.from(t).forEach(t=>{t[fn]||=e,t.__cssinjs_instance__===e&&document.head.insertBefore(t,n)});let r={};Array.from(document.querySelectorAll(`style[${dn}]`)).forEach(t=>{let n=t.getAttribute(dn);r[n]?t.__cssinjs_instance__===e&&t.parentNode?.removeChild(t):r[n]=!0})}return new ln(e)}var mn=m.createContext({hashPriority:`low`,cache:pn(),defaultCache:!0,autoPrefix:!1});function hn(e,t){if(e.length!==t.length)return!1;for(let n=0;n{n=n?n?.map?.get(e):void 0}),n?.value&&t&&(n.value[1]=this.cacheCallTimes++),n?.value}get(e){return this.internalGet(e,!0)?.[0]}has(e){return!!this.internalGet(e)}set(t,n){if(!this.has(t)){if(this.size()+1>e.MAX_CACHE_SIZE+e.MAX_CACHE_OFFSET){let[e]=this.keys.reduce((e,t)=>{let[,n]=e;return this.internalGet(t)[1]{if(i===t.length-1)r.set(e,{value:[n,this.cacheCallTimes++]});else{let t=r.get(e);t?t.map||=new Map:r.set(e,{map:new Map}),r=r.get(e).map}})}deleteByPath(e,t){let n=e.get(t[0]);if(t.length===1)return n.map?e.set(t[0],{map:n.map}):e.delete(t[0]),n.value?.[0];let r=this.deleteByPath(n.map,t.slice(1));return(!n.map||n.map.size===0)&&!n.value&&e.delete(t[0]),r}delete(e){if(this.has(e))return this.keys=this.keys.filter(t=>!hn(t,e)),this.deleteByPath(this.cache,e)}},_n=0,vn=class{derivatives;id;constructor(e){this.derivatives=Array.isArray(e)?e:[e],this.id=_n,e.length===0&&e.length,_n+=1}getDerivativeToken(e){return this.derivatives.reduce((t,n)=>n(e,t),void 0)}},yn=new gn;function bn(e){let t=Array.isArray(e)?e:[e];return yn.has(t)||yn.set(t,new vn(t)),yn.get(t)}var xn=new WeakMap,Sn={};function Cn(e,t){let n=xn;for(let e=0;e{let r=e[n];t+=n,r instanceof vn?t+=r.id:r&&typeof r==`object`?t+=Tn(r):t+=r}),t=Ut(t),wn.set(e,t)),t}function En(e,t){return Ut(`${t}_${Tn(e)}`)}`random-${Date.now()}-${Math.random()}`.replace(/\./g,``);var Dn=ve();function q(e){return typeof e==`number`?`${e}px`:e}function On(e){let{hashCls:t,hashPriority:n=`low`}=e||{};if(!t)return``;let r=`.${t}`;return n===`low`?`:where(${r})`:r}var kn=e=>e!=null;function An(e,t){let n=typeof t==`function`?t():t;return n?{...e,csp:{...e.csp,nonce:n}}:e}var jn=(e,t=``)=>`--${t?`${t}-`:``}${e}`.replace(/([a-z0-9])([A-Z])/g,`$1-$2`).replace(/([A-Z]+)([A-Z][a-z0-9]+)/g,`$1-$2`).replace(/([a-z])([A-Z0-9])/g,`$1-$2`).toLowerCase(),Mn=(e,t,n)=>{let{hashCls:r,hashPriority:i=`low`,scope:a}=n||{};if(!Object.keys(e).length)return``;let o=`${On({hashCls:r,hashPriority:i})}.${t}`,s=[a].flat().filter(Boolean);return`${s.length?s.map(e=>`${o}.${e}`).join(`, `):o}{${Object.entries(e).map(([e,t])=>`${e}:${t};`).join(``)}}`},Nn=(e,t,n)=>{let{hashCls:r,hashPriority:i=`low`,prefix:a,unitless:o,ignore:s,preserve:c}=n||{},l={},u={};return Object.entries(e).forEach(([e,t])=>{if(c?.[e])u[e]=t;else if((typeof t==`string`||typeof t==`number`)&&!s?.[e]){let n=jn(e,a);l[n]=typeof t==`number`&&!o?.[e]?`${t}px`:String(t),u[e]=`var(${n})`}}),[u,Mn(l,t,{scope:n?.scope,hashCls:r,hashPriority:i})]},Pn=new Map;function Fn(e,t,n,r,i){let{cache:a}=m.useContext(mn),o=sn([e,...t]),s=e=>{a.opUpdate(o,t=>{let[r=0,i]=t||[void 0,void 0],a=[r,i||n()];return e?e(a):a})};m.useMemo(()=>{s()},[o]);let c=a.opGet(o)[1];return(0,m.useInsertionEffect)(()=>(s(([e,t])=>[e+1,t]),Pn.has(o)||(i?.(c),Pn.set(o,!0),Promise.resolve().then(()=>{Pn.delete(o)})),()=>{a.opUpdate(o,e=>{let[t=0,n]=e||[];return t-1==0?(r?.(n,!1),Pn.delete(o),null):[t-1,n]})}),[o]),c}var In={},Ln=`css`,Rn=new Map;function zn(e){Rn.set(e,(Rn.get(e)||0)+1)}function Bn(e,t){typeof document<`u`&&document.querySelectorAll(`style[${un}="${e}"]`).forEach(e=>{e.__cssinjs_instance__===t&&e.parentNode?.removeChild(e)})}var Vn=-1;function Hn(e,t){Rn.set(e,(Rn.get(e)||0)-1);let n=new Set;Rn.forEach((e,t)=>{e<=0&&n.add(t)}),Rn.size-n.size>Vn&&n.forEach(e=>{Bn(e,t),Rn.delete(e)})}var Un=(e,t,n,r)=>{let i={...n.getDerivativeToken(e),...t};return r&&(i=r(i)),i},Wn=`token`;function Gn(e,t,n){let{cache:{instanceId:r},container:i,hashPriority:a}=(0,m.useContext)(mn),{salt:o=``,override:s=In,formatToken:c,getComputedToken:l,cssVar:u,nonce:d}=n,f=Cn(()=>Object.assign({},...t),t),p=Tn(f),h=Tn(s),g=Tn(u);return Fn(Wn,[o,e.id,p,h,g],()=>{let t=l?l(f,s,e):Un(f,s,e,c),n={...t},r=`${o}_${u.prefix}`,i=Ut(r),d=`${Ln}-${i}`;n._tokenKey=En(n,r);let[p,m]=Nn(t,u.key,{prefix:u.prefix,ignore:u.ignore,unitless:u.unitless,preserve:u.preserve,hashPriority:a,hashCls:u.hashed?d:void 0});return p._hashId=i,zn(u.key),[p,d,n,m,u.key]},([,,,,e])=>{Hn(e,r)},([,,,e,t])=>{if(!e)return;let n={mark:dn,prepend:`queue`,attachTo:i,priority:-999};n=An(n,d);let a=rn(e,Ut(`css-var-${t}`),n);a[fn]=r,a.setAttribute(un,t)})}var Kn={animationIterationCount:1,borderImageOutset:1,borderImageSlice:1,borderImageWidth:1,boxFlex:1,boxFlexGroup:1,boxOrdinalGroup:1,columnCount:1,columns:1,flex:1,flexGrow:1,flexPositive:1,flexShrink:1,flexNegative:1,flexOrder:1,gridRow:1,gridRowEnd:1,gridRowSpan:1,gridRowStart:1,gridColumn:1,gridColumnEnd:1,gridColumnSpan:1,gridColumnStart:1,msGridRow:1,msGridRowSpan:1,msGridColumn:1,msGridColumnSpan:1,fontWeight:1,lineHeight:1,opacity:1,order:1,orphans:1,tabSize:1,widows:1,zIndex:1,zoom:1,WebkitLineClamp:1,fillOpacity:1,floodOpacity:1,stopOpacity:1,strokeDasharray:1,strokeDashoffset:1,strokeMiterlimit:1,strokeOpacity:1,strokeWidth:1},qn=`-ms-`,Jn=`-moz-`,Yn=`-webkit-`,Xn=`comm`,Zn=`rule`,Qn=`decl`,$n=`@import`,er=`@namespace`,tr=`@keyframes`,nr=`@layer`,rr=Math.abs,ir=String.fromCharCode,ar=Object.assign;function or(e,t){return dr(e,0)^45?(((t<<2^dr(e,0))<<2^dr(e,1))<<2^dr(e,2))<<2^dr(e,3):0}function sr(e){return e.trim()}function cr(e,t){return(e=t.exec(e))?e[0]:e}function lr(e,t,n){return e.replace(t,n)}function ur(e,t,n){return e.indexOf(t,n)}function dr(e,t){return e.charCodeAt(t)|0}function fr(e,t,n){return e.slice(t,n)}function pr(e){return e.length}function mr(e){return e.length}function hr(e,t){return t.push(e),e}function gr(e,t){return e.map(t).join(``)}function _r(e,t){return e.filter(function(e){return!cr(e,t)})}var vr=1,yr=1,br=0,xr=0,Sr=0,Cr=``;function wr(e,t,n,r,i,a,o,s){return{value:e,root:t,parent:n,type:r,props:i,children:a,line:vr,column:yr,length:o,return:``,siblings:s}}function Tr(e,t){return ar(wr(``,null,null,``,null,null,0,e.siblings),e,{length:-e.length},t)}function Er(e){for(;e.root;)e=Tr(e.root,{children:[e]});hr(e,e.siblings)}function Dr(){return Sr}function Or(){return Sr=xr>0?dr(Cr,--xr):0,yr--,Sr===10&&(yr=1,vr--),Sr}function kr(){return Sr=xr2||Nr(Sr)>3?``:` `}function Rr(e,t){for(;--t&&kr()&&!(Sr<48||Sr>102||Sr>57&&Sr<65||Sr>70&&Sr<97););return Mr(e,jr()+(t<6&&Ar()==32&&kr()==32))}function zr(e){for(;kr();)switch(Sr){case e:return xr;case 34:case 39:e!==34&&e!==39&&zr(Sr);break;case 40:e===41&&zr(e);break;case 92:kr();break}return xr}function Br(e,t){for(;kr()&&e+Sr!==57&&!(e+Sr===84&&Ar()===47););return`/*`+Mr(t,xr-1)+`*`+ir(e===47?e:kr())}function Vr(e){for(;!Nr(Ar());)kr();return Mr(e,xr)}function Hr(e){return Fr(Ur(``,null,null,null,[``],e=Pr(e),0,[0],e))}function Ur(e,t,n,r,i,a,o,s,c){for(var l=0,u=0,d=o,f=0,p=0,m=0,h=1,g=1,_=1,v=0,y=``,b=i,x=a,S=r,C=y;g;)switch(m=v,v=kr()){case 40:if(m!=108&&dr(C,d-1)==58){ur(C+=lr(Ir(v),`&`,`&\f`),`&\f`,rr(l?s[l-1]:0))!=-1&&(_=-1);break}case 34:case 39:case 91:C+=Ir(v);break;case 9:case 10:case 13:case 32:C+=Lr(m);break;case 92:C+=Rr(jr()-1,7);continue;case 47:switch(Ar()){case 42:case 47:hr(Gr(Br(kr(),jr()),t,n,c),c),(Nr(m||1)==5||Nr(Ar()||1)==5)&&pr(C)&&fr(C,-1,void 0)!==` `&&(C+=` `);break;default:C+=`/`}break;case 123*h:s[l++]=pr(C)*_;case 125*h:case 59:case 0:switch(v){case 0:case 125:g=0;case 59+u:_==-1&&(C=lr(C,/\f/g,``)),p>0&&(pr(C)-d||h===0&&m===47)&&hr(p>32?Kr(C+`;`,r,n,d-1,c):Kr(lr(C,` `,``)+`;`,r,n,d-2,c),c);break;case 59:C+=`;`;default:if(hr(S=Wr(C,t,n,l,u,i,s,y,b=[],x=[],d,a),a),v===123)if(u===0)Ur(C,t,S,S,b,a,d,s,x);else{switch(f){case 99:if(dr(C,3)===110)break;case 108:if(dr(C,2)===97)break;default:u=0;case 100:case 109:case 115:}u?Ur(e,S,S,r&&hr(Wr(e,S,S,0,0,i,s,y,i,b=[],d,x),x),i,x,d,s,r?b:x):Ur(C,S,S,S,[``],x,0,s,x)}}l=u=p=0,h=_=1,y=C=``,d=o;break;case 58:d=1+pr(C),p=m;default:if(h<1){if(v==123)--h;else if(v==125&&h++==0&&Or()==125)continue}switch(C+=ir(v),v*h){case 38:_=u>0?1:(C+=`\f`,-1);break;case 44:s[l++]=(pr(C)-1)*_,_=1;break;case 64:Ar()===45&&(C+=Ir(kr())),f=Ar(),u=d=pr(y=C+=Vr(jr())),v++;break;case 45:m===45&&pr(C)==2&&(h=0)}}return a}function Wr(e,t,n,r,i,a,o,s,c,l,u,d){for(var f=i-1,p=i===0?a:[``],m=mr(p),h=0,g=0,_=0;h0?p[v]+` `+y:lr(y,/&\f/g,p[v])))&&(c[_++]=b);return wr(e,t,n,i===0?Zn:s,c,l,u,d)}function Gr(e,t,n,r){return wr(e,t,n,Xn,ir(Dr()),fr(e,2,-2),0,r)}function Kr(e,t,n,r,i){return wr(e,t,n,Qn,fr(e,0,r),fr(e,r+1,-1),r,i)}function qr(e,t,n){switch(or(e,t)){case 5103:return Yn+`print-`+e+e;case 5737:case 4201:case 3177:case 3433:case 1641:case 4457:case 2921:case 5572:case 6356:case 5844:case 3191:case 6645:case 3005:case 4215:case 6389:case 5109:case 5365:case 5621:case 3829:case 6391:case 5879:case 5623:case 6135:case 4599:return Yn+e+e;case 4855:return Yn+e.replace(`add`,`source-over`).replace(`substract`,`source-out`).replace(`intersect`,`source-in`).replace(`exclude`,`xor`)+e;case 4789:return Jn+e+e;case 5349:case 4246:case 4810:case 6968:case 2756:return Yn+e+Jn+e+qn+e+e;case 5936:switch(dr(e,t+11)){case 114:return Yn+e+qn+lr(e,/[svh]\w+-[tblr]{2}/,`tb`)+e;case 108:return Yn+e+qn+lr(e,/[svh]\w+-[tblr]{2}/,`tb-rl`)+e;case 45:return Yn+e+qn+lr(e,/[svh]\w+-[tblr]{2}/,`lr`)+e}case 6828:case 4268:case 2903:return Yn+e+qn+e+e;case 6165:return Yn+e+qn+`flex-`+e+e;case 5187:return Yn+e+lr(e,/(\w+).+(:[^]+)/,Yn+`box-$1$2`+qn+`flex-$1$2`)+e;case 5443:return Yn+e+qn+`flex-item-`+lr(e,/flex-|-self/g,``)+(cr(e,/flex-|baseline/)?``:qn+`grid-row-`+lr(e,/flex-|-self/g,``))+e;case 4675:return Yn+e+qn+`flex-line-pack`+lr(e,/align-content|flex-|-self/g,``)+e;case 5548:return Yn+e+qn+lr(e,`shrink`,`negative`)+e;case 5292:return Yn+e+qn+lr(e,`basis`,`preferred-size`)+e;case 6060:return Yn+`box-`+lr(e,`-grow`,``)+Yn+e+qn+lr(e,`grow`,`positive`)+e;case 4554:return Yn+lr(e,/([^-])(transform)/g,`$1`+Yn+`$2`)+e;case 6187:return lr(lr(lr(e,/(zoom-|grab)/,Yn+`$1`),/(image-set)/,Yn+`$1`),e,``)+e;case 5495:case 3959:return lr(e,/(image-set\([^]*)/,Yn+"$1$`$1");case 4968:return lr(lr(e,/(.+:)(flex-)?(.*)/,Yn+`box-pack:$3`+qn+`flex-pack:$3`),/space-between/,`justify`)+Yn+e+e;case 4200:if(!cr(e,/flex-|baseline/))return qn+`grid-column-align`+fr(e,t)+e;break;case 2592:case 3360:return qn+lr(e,`template-`,``)+e;case 4384:case 3616:return n&&n.some(function(e,n){return t=n,cr(e.props,/grid-\w+-end/)})?~ur(e+(n=n[t].value),`span`,0)?e:qn+lr(e,`-start`,``)+e+qn+`grid-row-span:`+(~ur(n,`span`,0)?cr(n,/\d+/):cr(n,/\d+/)-+cr(e,/\d+/))+`;`:qn+lr(e,`-start`,``)+e;case 4896:case 4128:return n&&n.some(function(e){return cr(e.props,/grid-\w+-start/)})?e:qn+lr(lr(e,`-end`,`-span`),`span `,``)+e;case 4095:case 3583:case 4068:case 2532:return lr(e,/(.+)-inline(.+)/,Yn+`$1$2`)+e;case 8116:case 7059:case 5753:case 5535:case 5445:case 5701:case 4933:case 4677:case 5533:case 5789:case 5021:case 4765:if(pr(e)-1-t>6)switch(dr(e,t+1)){case 109:if(dr(e,t+4)!==45)break;case 102:return lr(e,/(.+:)(.+)-([^]+)/,`$1`+Yn+`$2-$3$1`+Jn+(dr(e,t+3)==108?`$3`:`$2-$3`))+e;case 115:return~ur(e,`stretch`,0)?qr(lr(e,`stretch`,`fill-available`),t,n)+e:e}break;case 5152:case 5920:return lr(e,/(.+?):(\d+)(\s*\/\s*(span)?\s*(\d+))?(.*)/,function(t,n,r,i,a,o,s){return qn+n+`:`+r+s+(i?qn+n+`-span:`+(a?o:o-+r)+s:``)+e});case 4949:if(dr(e,t+6)===121)return lr(e,`:`,`:`+Yn)+e;break;case 6444:switch(dr(e,dr(e,14)===45?18:11)){case 120:return lr(e,/(.+:)([^;\s!]+)(;|(\s+)?!.+)?/,`$1`+Yn+(dr(e,14)===45?`inline-`:``)+`box$3$1`+Yn+`$2$3$1`+qn+`$2box$3`)+e;case 100:return lr(e,`:`,`:`+qn)+e}break;case 5719:case 2647:case 2135:case 3927:case 2391:return lr(e,`scroll-`,`scroll-snap-`)+e}return e}function Jr(e,t){for(var n=``,r=0;r-1&&!e.return)switch(e.type){case Qn:e.return=qr(e.value,e.length,n);return;case tr:return Jr([Tr(e,{value:lr(e.value,`@`,`@`+Yn)})],r);case Zn:if(e.length)return gr(n=e.props,function(t){switch(cr(t,r=/(::plac\w+|:read-\w+)/)){case`:read-only`:case`:read-write`:Er(Tr(e,{props:[lr(t,/:(read-\w+)/,`:`+Jn+`$1`)]})),Er(Tr(e,{props:[t]})),ar(e,{props:_r(n,r)});break;case`::placeholder`:Er(Tr(e,{props:[lr(t,/:(plac\w+)/,`:`+Yn+`input-$1`)]})),Er(Tr(e,{props:[lr(t,/:(plac\w+)/,`:`+Jn+`$1`)]})),Er(Tr(e,{props:[lr(t,/:(plac\w+)/,qn+`input-$1`)]})),Er(Tr(e,{props:[t]})),ar(e,{props:_r(n,r)});break}return``})}}var Qr=`data-ant-cssinjs-cache-path`,$r=`_FILE_STYLE__`,ei,ti=!0;function ni(){if(!ei&&(ei={},ve())){let e=document.createElement(`div`);e.className=Qr,e.style.position=`fixed`,e.style.visibility=`hidden`,e.style.top=`-9999px`,document.body.appendChild(e);let t=getComputedStyle(e).content||``;t=t.replace(/^"/,``).replace(/"$/,``),t.split(`;`).forEach(e=>{let[t,n]=e.split(`:`);ei[t]=n});let n=document.querySelector(`style[${Qr}]`);n&&(ti=!1,n.parentNode?.removeChild(n)),document.body.removeChild(e)}}function ri(e){return ni(),!!ei[e]}function ii(e){let t=ei[e],n=null;if(t&&ve())if(ti)n=$r;else{let t=document.querySelector(`style[${dn}="${ei[e]}"]`);t?n=t.innerHTML:delete ei[e]}return[n,t]}var ai=`_skip_check_`,oi=`_multi_value_`;function si(e,t){return(t?Jr(Hr(e),Xr([Zr,Yr])):Jr(Hr(e),Yr)).replace(/\{%%%\:[^;];}/g,`;`)}function ci(e){return typeof e==`object`&&e&&(ai in e||oi in e)}function li(e,t,n=`high`){if(!t)return e;let r=On({hashCls:t,hashPriority:n});return e.split(`,`).map(e=>{let t=e.trim().split(/\s+/),n=t[0]||``,i=n.match(/^\w+/)?.[0]||``;return n=`${i}${r}${n.slice(i.length)}`,[n,...t.slice(1)].join(` `)}).join(`,`)}var ui=(e,t={},{root:n,injectHash:r,parentSelectors:i}={root:!0,parentSelectors:[]})=>{let{hashId:a,layer:o,path:s,hashPriority:c,transformers:l=[],linters:u=[]}=t,d=``,f={};function p(e){let n=e.getName(a);if(!f[n]){let[r]=ui(e.style,t,{root:!1,parentSelectors:i});f[n]=`@keyframes ${e.getName(a)}${r}`}}function m(e,t=[]){return e.forEach(e=>{Array.isArray(e)?m(e,t):e&&t.push(e)}),t}return m(Array.isArray(e)?e:[e]).forEach(e=>{let o=typeof e==`string`&&!n?{}:e;if(typeof o==`string`)d+=`${o}\n`;else if(o._keyframe)p(o);else{let e=l.reduce((e,t)=>t?.visit?.(e)||e,o);Object.keys(e).forEach(o=>{let s=e[o];if(typeof s==`object`&&s&&(o!==`animationName`||!s._keyframe)&&!ci(s)){let e=!1,l=o.trim(),u=!1;(n||r)&&a?l.startsWith(`@`)?e=!0:l=li(l===`&`?``:o,a,c):n&&!a&&(l===`&`||l===``)&&(l=``,u=!0);let[p,m]=ui(s,t,{root:u,injectHash:e,parentSelectors:[...i,l]});f={...f,...m},d+=`${l}${p}`}else{function e(e,t){let n=e.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`),r=t;!Kn[e]&&typeof r==`number`&&r!==0&&(r=`${r}px`),e===`animationName`&&t?._keyframe&&(p(t),r=t.getName(a)),d+=`${n}:${r};`}let t=s?.value??s;typeof s==`object`&&s?.[oi]&&Array.isArray(t)?t.forEach(t=>{e(o,t)}):kn(t)&&e(o,t)}})}}),n?o&&(d&&=`@layer ${o.name} {${d}}`,o.dependencies&&(f[`@layer ${o.name}`]=o.dependencies.map(e=>`@layer ${e}, ${o.name};`).join(` -`))):d=`{${d}}`,[d,f]};function di(e,t){return Ut(`${e.join(`%`)}${t}`)}var fi=`style`;function pi(e,t){let{path:n,hashId:r,layer:i,nonce:a,clientOnly:o,order:s=0}=e,{mock:c,hashPriority:l,container:u,transformers:d,linters:f,cache:p,layer:h,autoPrefix:g}=m.useContext(mn),_=[r||``];h&&_.push(`layer`),_.push(...n);let v=Dn;Fn(fi,_,()=>{let e=_.join(`|`);if(ri(e)){let[t,n]=ii(e);if(t)return[t,n,{},o,s]}let[a,c]=ui(t(),{hashId:r,hashPriority:l,layer:h?i:void 0,path:n.join(`-`),transformers:d,linters:f}),u=si(a,g||!1);return[u,di(_,u),c,o,s]},(e,t)=>{let[,n]=e;t&&Dn&&tn(n,{mark:dn,attachTo:u})},e=>{let[t,n,r,,i]=e;if(v&&t!==`_FILE_STYLE__`){let e={mark:dn,prepend:h?!1:`queue`,attachTo:u,priority:i};e=An(e,a);let o=[],s=[];Object.keys(r).forEach(e=>{e.startsWith(`@layer`)?o.push(e):s.push(e)}),o.forEach(t=>{rn(si(r[t],g||!1),`_layer-${t}`,{...e,prepend:!0})});let c=rn(t,n,e);c[fn]=p.instanceId,s.forEach(t=>{rn(si(r[t],g||!1),`_effect-${t}`,e)})}})}var mi=`cssVar`,hi=(e,t)=>{let{key:n,prefix:r,unitless:i,ignore:a,token:o,hashId:s,scope:c,nonce:l}=e,{cache:{instanceId:u},container:d,hashPriority:f}=(0,m.useContext)(mn),{_tokenKey:p}=o,h=Array.isArray(c)?c.join(`@@`):c,g=[...e.path,n,h,p];return Fn(mi,g,()=>{let[e,o]=Nn(t(),n,{prefix:r,unitless:i,ignore:a,scope:c,hashPriority:f,hashCls:s});return[e,o,di(g,o),n]},([,,e])=>{Dn&&tn(e,{mark:dn,attachTo:d})},([,e,t])=>{if(!e)return;let r={mark:dn,prepend:`queue`,attachTo:d,priority:-999};r=An(r,l);let i=rn(e,t,r);i[fn]=u,i.setAttribute(un,n)})},gi=class{name;style;constructor(e,t){this.name=e,this.style=t}getName(e=``){return e?`${e}-${this.name}`:this.name}_keyframe=!0};function _i(e){return e.notSplit=!0,e}_i([`borderTop`,`borderBottom`]),_i([`borderTop`]),_i([`borderBottom`]),_i([`borderLeft`,`borderRight`]),_i([`borderLeft`]),_i([`borderRight`]);function vi(e){"@babel/helpers - typeof";return vi=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},vi(e)}function yi(e){if(Array.isArray(e))return e}function bi(e,t){var n=e==null?null:typeof Symbol<`u`&&e[Symbol.iterator]||e[`@@iterator`];if(n!=null){var r,i,a,o,s=[],c=!0,l=!1;try{if(a=(n=n.call(e)).next,t===0){if(Object(n)!==n)return;c=!1}else for(;!(c=(r=a.call(n)).done)&&(s.push(r.value),s.length!==t);c=!0);}catch(e){l=!0,i=e}finally{try{if(!c&&n.return!=null&&(o=n.return(),Object(o)!==o))return}finally{if(l)throw i}}return s}}function xi(){throw TypeError(`Invalid attempt to destructure non-iterable instance. -In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function Si(e,t){return yi(e)||bi(e,t)||Ot(e,t)||xi()}function Ci(e,t){if(vi(e)!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(vi(r)!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}function wi(e){var t=Ci(e,`string`);return vi(t)==`symbol`?t:t+``}function Ti(e,t,n){return(t=wi(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function Ei(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function Di(e){for(var t=1;t1e4){var t=Date.now();this.lastAccessBeat.forEach(function(n,r){t-n>ta&&(e.map.delete(r),e.lastAccessBeat.delete(r))}),this.accessBeat=0}}}]),e}());function ra(e,t){return m.useMemo(function(){var n=na.get(t);if(n)return n;var r=e();return na.set(t,r),r},t)}var ia=function(){return{}};function aa(e){var t=e.useCSP,n=t===void 0?ia:t,r=e.useToken,i=e.usePrefix,a=e.getResetStyles,o=e.getCommonStyle,s=e.getCompUnitless;function c(e,t,n,r){var i=Array.isArray(e)?e[0]:e;function a(e){return`${String(i)}${e.slice(0,1).toUpperCase()}${e.slice(1)}`}var o=r?.unitless||{},c=Di(Di({},typeof s==`function`?s(e):{}),{},Ti({},a(`zIndexPopup`),!0));Object.keys(o).forEach(function(e){c[a(e)]=o[e]});var d=Di(Di({},r),{},{unitless:c,prefixToken:a}),f=u(e,t,n,d),p=l(i,n,d);return function(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:e,n=f(e,t),i=r?.extraCssVarPrefixCls,a=typeof i==`function`?i({prefixCls:e,rootCls:t}):i;return[n,p(a!=null&&a.length?[t].concat(At(a)):t)]}}function l(e,t,i){var a=i.unitless,o=i.prefixToken,s=i.ignore;return function(c){var l=r(),u=l.cssVar,d=l.realToken,f=n();return hi({path:[e],prefix:u.prefix,key:u.key,unitless:a,ignore:s,token:d,scope:c,nonce:function(){return f.nonce}},function(){var n=$i(e,d,t),r=Ki(e,d,n,{deprecatedTokens:i?.deprecatedTokens});return n&&Object.keys(n).forEach(function(e){r[o(e)]=r[e],delete r[e]}),r}),u?.key}}function u(t,s,c){var l=arguments.length>3&&arguments[3]!==void 0?arguments[3]:{},u=Array.isArray(t)?t:[t,t],d=Si(u,1)[0],f=u.join(`-`),p=e.layer||{name:`antd`};return function(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:e,u=r(),h=u.theme,g=u.realToken,_=u.hashId,v=u.token,y=u.cssVar,b=u.zeroRuntime;if((0,m.useMemo)(function(){return b},[]))return _;var x=i(),S=x.rootPrefixCls,C=x.iconPrefixCls,w=n(),T=`css`,E=ra(function(){var e=new Set;return Object.keys(l.unitless||{}).forEach(function(t){e.add(jn(t,y.prefix)),e.add(jn(t,Gi(d,y.prefix)))}),Wi(T,e)},[T,d,y?.prefix]),D=ea(T),O=D.max,k=D.min,A={theme:h,token:v,hashId:_,nonce:function(){return w.nonce},clientOnly:l.clientOnly,layer:p,order:l.order||-999};return typeof a==`function`&&pi(Di(Di({},A),{},{clientOnly:!1,path:[`Shared`,S]}),function(){return a(v,{prefix:{rootPrefixCls:S,iconPrefixCls:C},csp:w})}),pi(Di(Di({},A),{},{path:[f,e,C]}),function(){if(l.injectStyle===!1)return[];var n=Qi(v),r=n.token,i=n.flush,a=$i(d,g,c),u=`.${e}`,f=Ki(d,g,a,{deprecatedTokens:l.deprecatedTokens});a&&vi(a)===`object`&&Object.keys(a).forEach(function(e){a[e]=`var(${jn(e,Gi(d,y.prefix))})`});var p=Yi(r,{componentCls:u,prefixCls:e,iconCls:`.${C}`,antCls:`.${S}`,calc:E,max:O,min:k},a),m=s(p,{hashId:_,prefixCls:e,rootPrefixCls:S,iconPrefixCls:C});i(d,f);var h=typeof o==`function`?o(p,e,t,l.resetFont):null;return[l.resetStyle===!1?null:h,m]}),_}}function d(e,t,n){var r=u(e,t,n,Di({resetStyle:!1,order:-998},arguments.length>3&&arguments[3]!==void 0?arguments[3]:{}));return function(e){var t=e.prefixCls,n=e.rootCls;return r(t,n===void 0?t:n),null}}return{genStyleHooks:c,genSubStyleComponent:d,genComponentStyleHook:u}}var oa=[`blue`,`purple`,`cyan`,`green`,`magenta`,`pink`,`red`,`orange`,`yellow`,`volcano`,`geekblue`,`lime`,`gold`];function sa(e){return(e+8)/e}function ca(e){let t=Array.from({length:10}).map((t,n)=>{let r=n-1,i=e*Math.E**(r/5);return Math.floor((n>1?Math.floor(i):Math.ceil(i))/2)*2});return t[1]=e,t.map(e=>({size:e,lineHeight:sa(e)}))}var la=`6.3.5`,ua={blue:`#1677FF`,purple:`#722ED1`,cyan:`#13C2C2`,green:`#52C41A`,magenta:`#EB2F96`,pink:`#EB2F96`,red:`#F5222D`,orange:`#FA8C16`,yellow:`#FADB14`,volcano:`#FA541C`,geekblue:`#2F54EB`,gold:`#FAAD14`,lime:`#A0D911`},da={...ua,colorPrimary:`#1677ff`,colorSuccess:`#52c41a`,colorWarning:`#faad14`,colorError:`#ff4d4f`,colorInfo:`#1677ff`,colorLink:``,colorTextBase:``,colorBgBase:``,fontFamily:`-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, -'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', -'Noto Color Emoji'`,fontFamilyCode:`'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace`,fontSize:14,lineWidth:1,lineType:`solid`,motionUnit:.1,motionBase:0,motionEaseOutCirc:`cubic-bezier(0.08, 0.82, 0.17, 1)`,motionEaseInOutCirc:`cubic-bezier(0.78, 0.14, 0.15, 0.86)`,motionEaseOut:`cubic-bezier(0.215, 0.61, 0.355, 1)`,motionEaseInOut:`cubic-bezier(0.645, 0.045, 0.355, 1)`,motionEaseOutBack:`cubic-bezier(0.12, 0.4, 0.29, 1.46)`,motionEaseInBack:`cubic-bezier(0.71, -0.46, 0.88, 0.6)`,motionEaseInQuint:`cubic-bezier(0.755, 0.05, 0.855, 0.06)`,motionEaseOutQuint:`cubic-bezier(0.23, 1, 0.32, 1)`,borderRadius:6,sizeUnit:4,sizeStep:4,sizePopupArrow:16,controlHeight:32,zIndexBase:0,zIndexPopupBase:1e3,opacityImage:1,wireframe:!1,motion:!0},fa={aliceblue:`9ehhb`,antiquewhite:`9sgk7`,aqua:`1ekf`,aquamarine:`4zsno`,azure:`9eiv3`,beige:`9lhp8`,bisque:`9zg04`,black:`0`,blanchedalmond:`9zhe5`,blue:`73`,blueviolet:`5e31e`,brown:`6g016`,burlywood:`8ouiv`,cadetblue:`3qba8`,chartreuse:`4zshs`,chocolate:`87k0u`,coral:`9yvyo`,cornflowerblue:`3xael`,cornsilk:`9zjz0`,crimson:`8l4xo`,cyan:`1ekf`,darkblue:`3v`,darkcyan:`rkb`,darkgoldenrod:`776yz`,darkgray:`6mbhl`,darkgreen:`jr4`,darkgrey:`6mbhl`,darkkhaki:`7ehkb`,darkmagenta:`5f91n`,darkolivegreen:`3bzfz`,darkorange:`9yygw`,darkorchid:`5z6x8`,darkred:`5f8xs`,darksalmon:`9441m`,darkseagreen:`5lwgf`,darkslateblue:`2th1n`,darkslategray:`1ugcv`,darkslategrey:`1ugcv`,darkturquoise:`14up`,darkviolet:`5rw7n`,deeppink:`9yavn`,deepskyblue:`11xb`,dimgray:`442g9`,dimgrey:`442g9`,dodgerblue:`16xof`,firebrick:`6y7tu`,floralwhite:`9zkds`,forestgreen:`1cisi`,fuchsia:`9y70f`,gainsboro:`8m8kc`,ghostwhite:`9pq0v`,goldenrod:`8j4f4`,gold:`9zda8`,gray:`50i2o`,green:`pa8`,greenyellow:`6senj`,grey:`50i2o`,honeydew:`9eiuo`,hotpink:`9yrp0`,indianred:`80gnw`,indigo:`2xcoy`,ivory:`9zldc`,khaki:`9edu4`,lavenderblush:`9ziet`,lavender:`90c8q`,lawngreen:`4vk74`,lemonchiffon:`9zkct`,lightblue:`6s73a`,lightcoral:`9dtog`,lightcyan:`8s1rz`,lightgoldenrodyellow:`9sjiq`,lightgray:`89jo3`,lightgreen:`5nkwg`,lightgrey:`89jo3`,lightpink:`9z6wx`,lightsalmon:`9z2ii`,lightseagreen:`19xgq`,lightskyblue:`5arju`,lightslategray:`4nwk9`,lightslategrey:`4nwk9`,lightsteelblue:`6wau6`,lightyellow:`9zlcw`,lime:`1edc`,limegreen:`1zcxe`,linen:`9shk6`,magenta:`9y70f`,maroon:`4zsow`,mediumaquamarine:`40eju`,mediumblue:`5p`,mediumorchid:`79qkz`,mediumpurple:`5r3rv`,mediumseagreen:`2d9ip`,mediumslateblue:`4tcku`,mediumspringgreen:`1di2`,mediumturquoise:`2uabw`,mediumvioletred:`7rn9h`,midnightblue:`z980`,mintcream:`9ljp6`,mistyrose:`9zg0x`,moccasin:`9zfzp`,navajowhite:`9zest`,navy:`3k`,oldlace:`9wq92`,olive:`50hz4`,olivedrab:`472ub`,orange:`9z3eo`,orangered:`9ykg0`,orchid:`8iu3a`,palegoldenrod:`9bl4a`,palegreen:`5yw0o`,paleturquoise:`6v4ku`,palevioletred:`8k8lv`,papayawhip:`9zi6t`,peachpuff:`9ze0p`,peru:`80oqn`,pink:`9z8wb`,plum:`8nba5`,powderblue:`6wgdi`,purple:`4zssg`,rebeccapurple:`3zk49`,red:`9y6tc`,rosybrown:`7cv4f`,royalblue:`2jvtt`,saddlebrown:`5fmkz`,salmon:`9rvci`,sandybrown:`9jn1c`,seagreen:`1tdnb`,seashell:`9zje6`,sienna:`6973h`,silver:`7ir40`,skyblue:`5arjf`,slateblue:`45e4t`,slategray:`4e100`,slategrey:`4e100`,snow:`9zke2`,springgreen:`1egv`,steelblue:`2r1kk`,tan:`87yx8`,teal:`pds`,thistle:`8ggk8`,tomato:`9yqfb`,turquoise:`2j4r4`,violet:`9b10u`,wheat:`9ld4j`,white:`9zldr`,whitesmoke:`9lhpx`,yellow:`9zl6o`,yellowgreen:`61fzm`},pa=Math.round;function ma(e,t){let n=e.replace(/^[^(]*\((.*)/,`$1`).replace(/\).*/,``).match(/\d*\.?\d+%?/g)||[],r=n.map(e=>parseFloat(e));for(let e=0;e<3;e+=1)r[e]=t(r[e]||0,n[e]||``,e);return n[3]?r[3]=n[3].includes(`%`)?r[3]/100:r[3]:r[3]=1,r}var ha=(e,t,n)=>n===0?e:e/100;function ga(e,t){let n=t||255;return e>n?n:e<0?0:e}var _a=class e{isValid=!0;r=0;g=0;b=0;a=1;_h;_hsl_s;_hsv_s;_l;_v;_max;_min;_brightness;constructor(t){function n(e){return e[0]in t&&e[1]in t&&e[2]in t}if(t)if(typeof t==`string`){let e=t.trim();function n(t){return e.startsWith(t)}if(/^#?[A-F\d]{3,8}$/i.test(e))this.fromHexString(e);else if(n(`rgb`))this.fromRgbString(e);else if(n(`hsl`))this.fromHslString(e);else if(n(`hsv`)||n(`hsb`))this.fromHsvString(e);else{let t=fa[e.toLowerCase()];t&&this.fromHexString(parseInt(t,36).toString(16).padStart(6,`0`))}}else if(t instanceof e)this.r=t.r,this.g=t.g,this.b=t.b,this.a=t.a,this._h=t._h,this._hsl_s=t._hsl_s,this._hsv_s=t._hsv_s,this._l=t._l,this._v=t._v;else if(n(`rgb`))this.r=ga(t.r),this.g=ga(t.g),this.b=ga(t.b),this.a=typeof t.a==`number`?ga(t.a,1):1;else if(n(`hsl`))this.fromHsl(t);else if(n(`hsv`))this.fromHsv(t);else throw Error(`@ant-design/fast-color: unsupported input `+JSON.stringify(t))}setR(e){return this._sc(`r`,e)}setG(e){return this._sc(`g`,e)}setB(e){return this._sc(`b`,e)}setA(e){return this._sc(`a`,e,1)}setHue(e){let t=this.toHsv();return t.h=e,this._c(t)}getLuminance(){function e(e){let t=e/255;return t<=.03928?t/12.92:((t+.055)/1.055)**2.4}let t=e(this.r),n=e(this.g),r=e(this.b);return .2126*t+.7152*n+.0722*r}getHue(){if(this._h===void 0){let e=this.getMax()-this.getMin();e===0?this._h=0:this._h=pa(60*(this.r===this.getMax()?(this.g-this.b)/e+(this.g1&&(r=1),this._c({h:t,s:n,l:r,a:this.a})}mix(e,t=50){let n=this._c(e),r=t/100,i=e=>(n[e]-this[e])*r+this[e],a={r:pa(i(`r`)),g:pa(i(`g`)),b:pa(i(`b`)),a:pa(i(`a`)*100)/100};return this._c(a)}tint(e=10){return this.mix({r:255,g:255,b:255,a:1},e)}shade(e=10){return this.mix({r:0,g:0,b:0,a:1},e)}onBackground(e){let t=this._c(e),n=this.a+t.a*(1-this.a),r=e=>pa((this[e]*this.a+t[e]*t.a*(1-this.a))/n);return this._c({r:r(`r`),g:r(`g`),b:r(`b`),a:n})}isDark(){return this.getBrightness()<128}isLight(){return this.getBrightness()>=128}equals(e){return this.r===e.r&&this.g===e.g&&this.b===e.b&&this.a===e.a}clone(){return this._c(this)}toHexString(){let e=`#`,t=(this.r||0).toString(16);e+=t.length===2?t:`0`+t;let n=(this.g||0).toString(16);e+=n.length===2?n:`0`+n;let r=(this.b||0).toString(16);if(e+=r.length===2?r:`0`+r,typeof this.a==`number`&&this.a>=0&&this.a<1){let t=pa(this.a*255).toString(16);e+=t.length===2?t:`0`+t}return e}toHsl(){return{h:this.getHue(),s:this.getHSLSaturation(),l:this.getLightness(),a:this.a}}toHslString(){let e=this.getHue(),t=pa(this.getHSLSaturation()*100),n=pa(this.getLightness()*100);return this.a===1?`hsl(${e},${t}%,${n}%)`:`hsla(${e},${t}%,${n}%,${this.a})`}toHsv(){return{h:this.getHue(),s:this.getHSVSaturation(),v:this.getValue(),a:this.a}}toRgb(){return{r:this.r,g:this.g,b:this.b,a:this.a}}toRgbString(){return this.a===1?`rgb(${this.r},${this.g},${this.b})`:`rgba(${this.r},${this.g},${this.b},${this.a})`}toString(){return this.toRgbString()}_sc(e,t,n){let r=this.clone();return r[e]=ga(t,n),r}_c(e){return new this.constructor(e)}getMax(){return this._max===void 0&&(this._max=Math.max(this.r,this.g,this.b)),this._max}getMin(){return this._min===void 0&&(this._min=Math.min(this.r,this.g,this.b)),this._min}fromHexString(e){let t=e.replace(`#`,``);function n(e,n){return parseInt(t[e]+t[n||e],16)}t.length<6?(this.r=n(0),this.g=n(1),this.b=n(2),this.a=t[3]?n(3)/255:1):(this.r=n(0,1),this.g=n(2,3),this.b=n(4,5),this.a=t[6]?n(6,7)/255:1)}fromHsl({h:e,s:t,l:n,a:r}){let i=(e%360+360)%360;if(this._h=i,this._hsl_s=t,this._l=n,this.a=typeof r==`number`?r:1,t<=0){let e=pa(n*255);this.r=e,this.g=e,this.b=e;return}let a=0,o=0,s=0,c=i/60,l=(1-Math.abs(2*n-1))*t,u=l*(1-Math.abs(c%2-1));c>=0&&c<1?(a=l,o=u):c>=1&&c<2?(a=u,o=l):c>=2&&c<3?(o=l,s=u):c>=3&&c<4?(o=u,s=l):c>=4&&c<5?(a=u,s=l):c>=5&&c<6&&(a=l,s=u);let d=n-l/2;this.r=pa((a+d)*255),this.g=pa((o+d)*255),this.b=pa((s+d)*255)}fromHsv({h:e,s:t,v:n,a:r}){let i=(e%360+360)%360;this._h=i,this._hsv_s=t,this._v=n,this.a=typeof r==`number`?r:1;let a=pa(n*255);if(this.r=a,this.g=a,this.b=a,t<=0)return;let o=i/60,s=Math.floor(o),c=o-s,l=pa(n*(1-t)*255),u=pa(n*(1-t*c)*255),d=pa(n*(1-t*(1-c))*255);switch(s){case 0:this.g=d,this.b=l;break;case 1:this.r=u,this.b=l;break;case 2:this.r=l,this.b=d;break;case 3:this.r=l,this.g=u;break;case 4:this.r=d,this.g=l;break;default:this.g=l,this.b=u;break}}fromHsvString(e){let t=ma(e,ha);this.fromHsv({h:t[0],s:t[1],v:t[2],a:t[3]})}fromHslString(e){let t=ma(e,ha);this.fromHsl({h:t[0],s:t[1],l:t[2],a:t[3]})}fromRgbString(e){let t=ma(e,(e,t)=>t.includes(`%`)?pa(e/100*255):e);this.r=t[0],this.g=t[1],this.b=t[2],this.a=t[3]}},va=2,ya=.16,ba=.05,xa=.05,Sa=.15,Ca=5,wa=4,Ta=[{index:7,amount:15},{index:6,amount:25},{index:5,amount:30},{index:5,amount:45},{index:5,amount:65},{index:5,amount:85},{index:4,amount:90},{index:3,amount:95},{index:2,amount:97},{index:1,amount:98}];function Ea(e,t,n){let r;return r=Math.round(e.h)>=60&&Math.round(e.h)<=240?n?Math.round(e.h)-va*t:Math.round(e.h)+va*t:n?Math.round(e.h)+va*t:Math.round(e.h)-va*t,r<0?r+=360:r>=360&&(r-=360),r}function Da(e,t,n){if(e.h===0&&e.s===0)return e.s;let r;return r=n?e.s-ya*t:t===wa?e.s+ya:e.s+ba*t,r>1&&(r=1),n&&t===Ca&&r>.1&&(r=.1),r<.06&&(r=.06),Math.round(r*100)/100}function Oa(e,t,n){let r;return r=n?e.v+xa*t:e.v-Sa*t,r=Math.max(0,Math.min(1,r)),Math.round(r*100)/100}function ka(e,t={}){let n=[],r=new _a(e),i=r.toHsv();for(let e=Ca;e>0;--e){let t=new _a({h:Ea(i,e,!0),s:Da(i,e,!0),v:Oa(i,e,!0)});n.push(t)}n.push(r);for(let e=1;e<=wa;e+=1){let t=new _a({h:Ea(i,e),s:Da(i,e),v:Oa(i,e)});n.push(t)}return t.theme===`dark`?Ta.map(({index:e,amount:r})=>new _a(t.backgroundColor||`#141414`).mix(n[e],r).toHexString()):n.map(e=>e.toHexString())}var Aa={red:`#F5222D`,volcano:`#FA541C`,orange:`#FA8C16`,gold:`#FAAD14`,yellow:`#FADB14`,lime:`#A0D911`,green:`#52C41A`,cyan:`#13C2C2`,blue:`#1677FF`,geekblue:`#2F54EB`,purple:`#722ED1`,magenta:`#EB2F96`,grey:`#666666`},ja=[`#fff1f0`,`#ffccc7`,`#ffa39e`,`#ff7875`,`#ff4d4f`,`#f5222d`,`#cf1322`,`#a8071a`,`#820014`,`#5c0011`];ja.primary=ja[5];var Ma=[`#fff2e8`,`#ffd8bf`,`#ffbb96`,`#ff9c6e`,`#ff7a45`,`#fa541c`,`#d4380d`,`#ad2102`,`#871400`,`#610b00`];Ma.primary=Ma[5];var Na=[`#fff7e6`,`#ffe7ba`,`#ffd591`,`#ffc069`,`#ffa940`,`#fa8c16`,`#d46b08`,`#ad4e00`,`#873800`,`#612500`];Na.primary=Na[5];var Pa=[`#fffbe6`,`#fff1b8`,`#ffe58f`,`#ffd666`,`#ffc53d`,`#faad14`,`#d48806`,`#ad6800`,`#874d00`,`#613400`];Pa.primary=Pa[5];var Fa=[`#feffe6`,`#ffffb8`,`#fffb8f`,`#fff566`,`#ffec3d`,`#fadb14`,`#d4b106`,`#ad8b00`,`#876800`,`#614700`];Fa.primary=Fa[5];var Ia=[`#fcffe6`,`#f4ffb8`,`#eaff8f`,`#d3f261`,`#bae637`,`#a0d911`,`#7cb305`,`#5b8c00`,`#3f6600`,`#254000`];Ia.primary=Ia[5];var La=[`#f6ffed`,`#d9f7be`,`#b7eb8f`,`#95de64`,`#73d13d`,`#52c41a`,`#389e0d`,`#237804`,`#135200`,`#092b00`];La.primary=La[5];var Ra=[`#e6fffb`,`#b5f5ec`,`#87e8de`,`#5cdbd3`,`#36cfc9`,`#13c2c2`,`#08979c`,`#006d75`,`#00474f`,`#002329`];Ra.primary=Ra[5];var za=[`#e6f4ff`,`#bae0ff`,`#91caff`,`#69b1ff`,`#4096ff`,`#1677ff`,`#0958d9`,`#003eb3`,`#002c8c`,`#001d66`];za.primary=za[5];var Ba=[`#f0f5ff`,`#d6e4ff`,`#adc6ff`,`#85a5ff`,`#597ef7`,`#2f54eb`,`#1d39c4`,`#10239e`,`#061178`,`#030852`];Ba.primary=Ba[5];var Va=[`#f9f0ff`,`#efdbff`,`#d3adf7`,`#b37feb`,`#9254de`,`#722ed1`,`#531dab`,`#391085`,`#22075e`,`#120338`];Va.primary=Va[5];var Ha=[`#fff0f6`,`#ffd6e7`,`#ffadd2`,`#ff85c0`,`#f759ab`,`#eb2f96`,`#c41d7f`,`#9e1068`,`#780650`,`#520339`];Ha.primary=Ha[5];var Ua=[`#a6a6a6`,`#999999`,`#8c8c8c`,`#808080`,`#737373`,`#666666`,`#404040`,`#1a1a1a`,`#000000`,`#000000`];Ua.primary=Ua[5];var Wa={red:ja,volcano:Ma,orange:Na,gold:Pa,yellow:Fa,lime:Ia,green:La,cyan:Ra,blue:za,geekblue:Ba,purple:Va,magenta:Ha,grey:Ua},Ga=[`#2a1215`,`#431418`,`#58181c`,`#791a1f`,`#a61d24`,`#d32029`,`#e84749`,`#f37370`,`#f89f9a`,`#fac8c3`];Ga.primary=Ga[5];var Ka=[`#2b1611`,`#441d12`,`#592716`,`#7c3118`,`#aa3e19`,`#d84a1b`,`#e87040`,`#f3956a`,`#f8b692`,`#fad4bc`];Ka.primary=Ka[5];var qa=[`#2b1d11`,`#442a11`,`#593815`,`#7c4a15`,`#aa6215`,`#d87a16`,`#e89a3c`,`#f3b765`,`#f8cf8d`,`#fae3b7`];qa.primary=qa[5];var Ja=[`#2b2111`,`#443111`,`#594214`,`#7c5914`,`#aa7714`,`#d89614`,`#e8b339`,`#f3cc62`,`#f8df8b`,`#faedb5`];Ja.primary=Ja[5];var Ya=[`#2b2611`,`#443b11`,`#595014`,`#7c6e14`,`#aa9514`,`#d8bd14`,`#e8d639`,`#f3ea62`,`#f8f48b`,`#fafab5`];Ya.primary=Ya[5];var Xa=[`#1f2611`,`#2e3c10`,`#3e4f13`,`#536d13`,`#6f9412`,`#8bbb11`,`#a9d134`,`#c9e75d`,`#e4f88b`,`#f0fab5`];Xa.primary=Xa[5];var Za=[`#162312`,`#1d3712`,`#274916`,`#306317`,`#3c8618`,`#49aa19`,`#6abe39`,`#8fd460`,`#b2e58b`,`#d5f2bb`];Za.primary=Za[5];var Qa=[`#112123`,`#113536`,`#144848`,`#146262`,`#138585`,`#13a8a8`,`#33bcb7`,`#58d1c9`,`#84e2d8`,`#b2f1e8`];Qa.primary=Qa[5];var $a=[`#111a2c`,`#112545`,`#15325b`,`#15417e`,`#1554ad`,`#1668dc`,`#3c89e8`,`#65a9f3`,`#8dc5f8`,`#b7dcfa`];$a.primary=$a[5];var eo=[`#131629`,`#161d40`,`#1c2755`,`#203175`,`#263ea0`,`#2b4acb`,`#5273e0`,`#7f9ef3`,`#a8c1f8`,`#d2e0fa`];eo.primary=eo[5];var to=[`#1a1325`,`#24163a`,`#301c4d`,`#3e2069`,`#51258f`,`#642ab5`,`#854eca`,`#ab7ae0`,`#cda8f0`,`#ebd7fa`];to.primary=to[5];var no=[`#291321`,`#40162f`,`#551c3b`,`#75204f`,`#a02669`,`#cb2b83`,`#e0529c`,`#f37fb7`,`#f8a8cc`,`#fad2e3`];no.primary=no[5];var ro=[`#151515`,`#1f1f1f`,`#2d2d2d`,`#393939`,`#494949`,`#5a5a5a`,`#6a6a6a`,`#7b7b7b`,`#888888`,`#969696`];ro.primary=ro[5];function io(e,{generateColorPalettes:t,generateNeutralColorPalettes:n}){let{colorSuccess:r,colorWarning:i,colorError:a,colorInfo:o,colorPrimary:s,colorBgBase:c,colorTextBase:l}=e,u=t(s),d=t(r),f=t(i),p=t(a),m=t(o),h=n(c,l),g=t(e.colorLink||e.colorInfo),_=new _a(p[1]).mix(new _a(p[3]),50).toHexString(),v={};return oa.forEach(n=>{let r=e[n];if(r){let e=t(r);v[`${n}Hover`]=e[5],v[`${n}Active`]=e[7]}}),{...h,colorPrimaryBg:u[1],colorPrimaryBgHover:u[2],colorPrimaryBorder:u[3],colorPrimaryBorderHover:u[4],colorPrimaryHover:u[5],colorPrimary:u[6],colorPrimaryActive:u[7],colorPrimaryTextHover:u[8],colorPrimaryText:u[9],colorPrimaryTextActive:u[10],colorSuccessBg:d[1],colorSuccessBgHover:d[2],colorSuccessBorder:d[3],colorSuccessBorderHover:d[4],colorSuccessHover:d[4],colorSuccess:d[6],colorSuccessActive:d[7],colorSuccessTextHover:d[8],colorSuccessText:d[9],colorSuccessTextActive:d[10],colorErrorBg:p[1],colorErrorBgHover:p[2],colorErrorBgFilledHover:_,colorErrorBgActive:p[3],colorErrorBorder:p[3],colorErrorBorderHover:p[4],colorErrorHover:p[5],colorError:p[6],colorErrorActive:p[7],colorErrorTextHover:p[8],colorErrorText:p[9],colorErrorTextActive:p[10],colorWarningBg:f[1],colorWarningBgHover:f[2],colorWarningBorder:f[3],colorWarningBorderHover:f[4],colorWarningHover:f[4],colorWarning:f[6],colorWarningActive:f[7],colorWarningTextHover:f[8],colorWarningText:f[9],colorWarningTextActive:f[10],colorInfoBg:m[1],colorInfoBgHover:m[2],colorInfoBorder:m[3],colorInfoBorderHover:m[4],colorInfoHover:m[4],colorInfo:m[6],colorInfoActive:m[7],colorInfoTextHover:m[8],colorInfoText:m[9],colorInfoTextActive:m[10],colorLinkHover:g[4],colorLink:g[6],colorLinkActive:g[7],...v,colorBgMask:new _a(`#000`).setA(.45).toRgbString(),colorWhite:`#fff`}}var ao=e=>{let t=e,n=e,r=e,i=e;return e<6&&e>=5?t=e+1:e<16&&e>=6?t=e+2:e>=16&&(t=16),e<7&&e>=5?n=4:e<8&&e>=7?n=5:e<14&&e>=8?n=6:e<16&&e>=14?n=7:e>=16&&(n=8),e<6&&e>=2?r=1:e>=6&&(r=2),e>4&&e<8?i=4:e>=8&&(i=6),{borderRadius:e,borderRadiusXS:r,borderRadiusSM:n,borderRadiusLG:t,borderRadiusOuter:i}};function oo(e){let{motionUnit:t,motionBase:n,borderRadius:r,lineWidth:i}=e;return{motionDurationFast:`${(n+t).toFixed(1)}s`,motionDurationMid:`${(n+t*2).toFixed(1)}s`,motionDurationSlow:`${(n+t*3).toFixed(1)}s`,lineWidthBold:i+1,...ao(r)}}var so=e=>{let{controlHeight:t}=e;return{controlHeightSM:t*.75,controlHeightXS:t*.5,controlHeightLG:t*1.25}},co=e=>{let t=ca(e),n=t.map(e=>e.size),r=t.map(e=>e.lineHeight),i=n[1],a=n[0],o=n[2],s=r[1],c=r[0],l=r[2];return{fontSizeSM:a,fontSize:i,fontSizeLG:o,fontSizeXL:n[3],fontSizeHeading1:n[6],fontSizeHeading2:n[5],fontSizeHeading3:n[4],fontSizeHeading4:n[3],fontSizeHeading5:n[2],lineHeight:s,lineHeightLG:l,lineHeightSM:c,fontHeight:Math.round(s*i),fontHeightLG:Math.round(l*o),fontHeightSM:Math.round(c*a),lineHeightHeading1:r[6],lineHeightHeading2:r[5],lineHeightHeading3:r[4],lineHeightHeading4:r[3],lineHeightHeading5:r[2]}};function lo(e){let{sizeUnit:t,sizeStep:n}=e;return{sizeXXL:t*(n+8),sizeXL:t*(n+4),sizeLG:t*(n+2),sizeMD:t*(n+1),sizeMS:t*n,size:t*n,sizeSM:t*(n-1),sizeXS:t*(n-2),sizeXXS:t*(n-3)}}var uo=(e,t)=>new _a(e).setA(t).toRgbString(),fo=(e,t)=>new _a(e).darken(t).toHexString(),po=e=>{let t=ka(e);return{1:t[0],2:t[1],3:t[2],4:t[3],5:t[4],6:t[5],7:t[6],8:t[4],9:t[5],10:t[6]}},mo=(e,t)=>{let n=e||`#fff`,r=t||`#000`;return{colorBgBase:n,colorTextBase:r,colorText:uo(r,.88),colorTextSecondary:uo(r,.65),colorTextTertiary:uo(r,.45),colorTextQuaternary:uo(r,.25),colorFill:uo(r,.15),colorFillSecondary:uo(r,.06),colorFillTertiary:uo(r,.04),colorFillQuaternary:uo(r,.02),colorBgSolid:uo(r,1),colorBgSolidHover:uo(r,.75),colorBgSolidActive:uo(r,.95),colorBgLayout:fo(n,4),colorBgContainer:fo(n,0),colorBgElevated:fo(n,0),colorBgSpotlight:uo(r,.85),colorBgBlur:`transparent`,colorBorder:fo(n,15),colorBorderDisabled:fo(n,15),colorBorderSecondary:fo(n,6)}};function ho(e){Aa.pink=Aa.magenta,Wa.pink=Wa.magenta;let t=Object.keys(ua).map(t=>{let n=e[t]===Aa[t]?Wa[t]:ka(e[t]);return Array.from({length:10},()=>1).reduce((e,r,i)=>(e[`${t}-${i+1}`]=n[i],e[`${t}${i+1}`]=n[i],e),{})}).reduce((e,t)=>(e={...e,...t},e),{});return{...e,...t,...io(e,{generateColorPalettes:po,generateNeutralColorPalettes:mo}),...co(e.fontSize),...lo(e),...so(e),...oo(e)}}var go=bn(ho),_o={token:da,override:{override:da},hashed:!0},vo=m.createContext(_o);function yo(e){return e>=0&&e<=255}function bo(e,t){let{r:n,g:r,b:i,a}=new _a(e).toRgb();if(a<1)return e;let{r:o,g:s,b:c}=new _a(t).toRgb();for(let e=.01;e<=1;e+=.01){let t=Math.round((n-o*(1-e))/e),a=Math.round((r-s*(1-e))/e),l=Math.round((i-c*(1-e))/e);if(yo(t)&&yo(a)&&yo(l))return new _a({r:t,g:a,b:l,a:Math.round(e*100)/100}).toRgbString()}return new _a({r:n,g:r,b:i,a:1}).toRgbString()}function xo(e){let{override:t,...n}=e,r={...t};Object.keys(da).forEach(e=>{delete r[e]});let i={...n,...r},a=1200,o=1600,s=1920;return i.motion===!1&&(i.motionDurationFast=`0s`,i.motionDurationMid=`0s`,i.motionDurationSlow=`0s`),{...i,colorFillContent:i.colorFillSecondary,colorFillContentHover:i.colorFill,colorFillAlter:i.colorFillQuaternary,colorBgContainerDisabled:i.colorFillTertiary,colorBorderBg:i.colorBgContainer,colorSplit:bo(i.colorBorderSecondary,i.colorBgContainer),colorTextPlaceholder:i.colorTextQuaternary,colorTextDisabled:i.colorTextQuaternary,colorTextHeading:i.colorText,colorTextLabel:i.colorTextSecondary,colorTextDescription:i.colorTextTertiary,colorTextLightSolid:i.colorWhite,colorHighlight:i.colorError,colorBgTextHover:i.colorFillSecondary,colorBgTextActive:i.colorFill,colorIcon:i.colorTextTertiary,colorIconHover:i.colorText,colorErrorOutline:bo(i.colorErrorBg,i.colorBgContainer),colorWarningOutline:bo(i.colorWarningBg,i.colorBgContainer),fontSizeIcon:i.fontSizeSM,lineWidthFocus:i.lineWidth*3,lineWidth:i.lineWidth,controlOutlineWidth:i.lineWidth*2,controlInteractiveSize:i.controlHeight/2,controlItemBgHover:i.colorFillTertiary,controlItemBgActive:i.colorPrimaryBg,controlItemBgActiveHover:i.colorPrimaryBgHover,controlItemBgActiveDisabled:i.colorFill,controlTmpOutline:i.colorFillQuaternary,controlOutline:bo(i.colorPrimaryBg,i.colorBgContainer),lineType:i.lineType,borderRadius:i.borderRadius,borderRadiusXS:i.borderRadiusXS,borderRadiusSM:i.borderRadiusSM,borderRadiusLG:i.borderRadiusLG,fontWeightStrong:600,opacityLoading:.65,linkDecoration:`none`,linkHoverDecoration:`none`,linkFocusDecoration:`none`,controlPaddingHorizontal:12,controlPaddingHorizontalSM:8,paddingXXS:i.sizeXXS,paddingXS:i.sizeXS,paddingSM:i.sizeSM,padding:i.size,paddingMD:i.sizeMD,paddingLG:i.sizeLG,paddingXL:i.sizeXL,paddingContentHorizontalLG:i.sizeLG,paddingContentVerticalLG:i.sizeMS,paddingContentHorizontal:i.sizeMS,paddingContentVertical:i.sizeSM,paddingContentHorizontalSM:i.size,paddingContentVerticalSM:i.sizeXS,marginXXS:i.sizeXXS,marginXS:i.sizeXS,marginSM:i.sizeSM,margin:i.size,marginMD:i.sizeMD,marginLG:i.sizeLG,marginXL:i.sizeXL,marginXXL:i.sizeXXL,boxShadow:` - 0 6px 16px 0 rgba(0, 0, 0, 0.08), - 0 3px 6px -4px rgba(0, 0, 0, 0.12), - 0 9px 28px 8px rgba(0, 0, 0, 0.05) - `,boxShadowSecondary:` - 0 6px 16px 0 rgba(0, 0, 0, 0.08), - 0 3px 6px -4px rgba(0, 0, 0, 0.12), - 0 9px 28px 8px rgba(0, 0, 0, 0.05) - `,boxShadowTertiary:` - 0 1px 2px 0 rgba(0, 0, 0, 0.03), - 0 1px 6px -1px rgba(0, 0, 0, 0.02), - 0 2px 4px 0 rgba(0, 0, 0, 0.02) - `,screenXS:480,screenXSMin:480,screenXSMax:575,screenSM:576,screenSMMin:576,screenSMMax:767,screenMD:768,screenMDMin:768,screenMDMax:991,screenLG:992,screenLGMin:992,screenLGMax:a-1,screenXL:a,screenXLMin:a,screenXLMax:o-1,screenXXL:o,screenXXLMin:o,screenXXLMax:s-1,screenXXXL:s,screenXXXLMin:s,boxShadowPopoverArrow:`2px 2px 5px rgba(0, 0, 0, 0.05)`,boxShadowCard:` - 0 1px 2px -2px ${new _a(`rgba(0, 0, 0, 0.16)`).toRgbString()}, - 0 3px 6px 0 ${new _a(`rgba(0, 0, 0, 0.12)`).toRgbString()}, - 0 5px 12px 4px ${new _a(`rgba(0, 0, 0, 0.09)`).toRgbString()} - `,boxShadowDrawerRight:` - -6px 0 16px 0 rgba(0, 0, 0, 0.08), - -3px 0 6px -4px rgba(0, 0, 0, 0.12), - -9px 0 28px 8px rgba(0, 0, 0, 0.05) - `,boxShadowDrawerLeft:` - 6px 0 16px 0 rgba(0, 0, 0, 0.08), - 3px 0 6px -4px rgba(0, 0, 0, 0.12), - 9px 0 28px 8px rgba(0, 0, 0, 0.05) - `,boxShadowDrawerUp:` - 0 6px 16px 0 rgba(0, 0, 0, 0.08), - 0 3px 6px -4px rgba(0, 0, 0, 0.12), - 0 9px 28px 8px rgba(0, 0, 0, 0.05) - `,boxShadowDrawerDown:` - 0 -6px 16px 0 rgba(0, 0, 0, 0.08), - 0 -3px 6px -4px rgba(0, 0, 0, 0.12), - 0 -9px 28px 8px rgba(0, 0, 0, 0.05) - `,boxShadowTabsOverflowLeft:`inset 10px 0 8px -8px rgba(0, 0, 0, 0.08)`,boxShadowTabsOverflowRight:`inset -10px 0 8px -8px rgba(0, 0, 0, 0.08)`,boxShadowTabsOverflowTop:`inset 0 10px 8px -8px rgba(0, 0, 0, 0.08)`,boxShadowTabsOverflowBottom:`inset 0 -10px 8px -8px rgba(0, 0, 0, 0.08)`,...r}}var So={lineHeight:!0,lineHeightSM:!0,lineHeightLG:!0,lineHeightHeading1:!0,lineHeightHeading2:!0,lineHeightHeading3:!0,lineHeightHeading4:!0,lineHeightHeading5:!0,opacityLoading:!0,fontWeightStrong:!0,zIndexPopupBase:!0,zIndexBase:!0,opacityImage:!0},Co={motionBase:!0,motionUnit:!0},wo={screenXS:!0,screenXSMin:!0,screenXSMax:!0,screenSM:!0,screenSMMin:!0,screenSMMax:!0,screenMD:!0,screenMDMin:!0,screenMDMax:!0,screenLG:!0,screenLGMin:!0,screenLGMax:!0,screenXL:!0,screenXLMin:!0,screenXLMax:!0,screenXXL:!0,screenXXLMin:!0,screenXXLMax:!0,screenXXXL:!0,screenXXXLMin:!0},To=(e,t,n)=>{let r=n.getDerivativeToken(e),{override:i,...a}=t,o={...r,override:i};return o=xo(o),a&&Object.entries(a).forEach(([e,t])=>{let{theme:n,...r}=t,i=r;n&&(i=To({...o,...r},{override:r},n)),o[e]=i}),o};function Eo(){let{token:e,hashed:t,theme:n,override:r,cssVar:i,zeroRuntime:a}=m.useContext(vo),{csp:o}=m.useContext(zt),s={prefix:i?.prefix??`ant`,key:i?.key??`css-var-root`},c=`${la}-${t||``}`,l=n||go,[u,d,f]=Gn(l,[da,e],{salt:c,override:r,getComputedToken:To,cssVar:{...s,unitless:So,ignore:Co,preserve:wo},nonce:o?.nonce});return[l,f,t?d:``,u,s,!!a]}var Do=(e,t=!1)=>({boxSizing:`border-box`,margin:0,padding:0,color:e.colorText,fontSize:e.fontSize,lineHeight:e.lineHeight,listStyle:`none`,fontFamily:t?`inherit`:e.fontFamily}),Oo=()=>({display:`inline-flex`,alignItems:`center`,color:`inherit`,fontStyle:`normal`,lineHeight:0,textAlign:`center`,textTransform:`none`,verticalAlign:`-0.125em`,textRendering:`optimizeLegibility`,"-webkit-font-smoothing":`antialiased`,"-moz-osx-font-smoothing":`grayscale`,"> *":{lineHeight:1},svg:{display:`inline-block`}}),ko=()=>({"&::before":{display:`table`,content:`""`},"&::after":{display:`table`,clear:`both`,content:`""`}}),Ao=(e,t)=>({outline:`${q(e.lineWidthFocus)} solid ${e.colorPrimaryBorder}`,outlineOffset:t??1,transition:[`outline-offset`,`outline`].map(e=>`${e} 0s`).join(`, `)}),jo=(e,t)=>({"&:focus-visible":Ao(e,t)}),Mo=e=>({a:{color:e.colorLink,textDecoration:e.linkDecoration,backgroundColor:`transparent`,outline:`none`,cursor:`pointer`,transition:`color ${e.motionDurationSlow}`,"-webkit-text-decoration-skip":`objects`,"&:hover":{color:e.colorLinkHover},"&:active":{color:e.colorLinkActive},"&:active, &:hover":{textDecoration:e.linkHoverDecoration,outline:0},"&:focus":{textDecoration:e.linkFocusDecoration,outline:0},...jo(e),"&[disabled]":{color:e.colorTextDisabled,cursor:`not-allowed`}}}),No=(e,t,n,r)=>{let i=`[class^="${t}"], [class*=" ${t}"]`,a=n?`.${n}`:i,o={boxSizing:`border-box`,"&::before, &::after":{boxSizing:`border-box`}},s={};return r!==!1&&(s={fontFamily:e.fontFamily,fontSize:e.fontSize}),{[a]:{...s,...o,[i]:o}}},Po=e=>({[`.${e}`]:{...Oo(),[`.${e} .${e}-icon`]:{display:`block`}}}),Fo=e=>({color:e.colorLink,textDecoration:e.linkDecoration,outline:`none`,cursor:`pointer`,transition:`all ${e.motionDurationSlow}`,border:0,padding:0,background:`none`,userSelect:`none`,...jo(e),"&:hover":{color:e.colorLinkHover,textDecoration:e.linkHoverDecoration},"&:focus":{color:e.colorLinkHover,textDecoration:e.linkFocusDecoration},"&:active":{color:e.colorLinkActive,textDecoration:e.linkHoverDecoration}}),{genStyleHooks:Io,genComponentStyleHook:Lo,genSubStyleComponent:Ro}=aa({usePrefix:()=>{let{getPrefixCls:e,iconPrefixCls:t}=(0,m.useContext)(zt);return{rootPrefixCls:e(),iconPrefixCls:t}},useToken:()=>{let[e,t,n,r,i,a]=Eo();return{theme:e,realToken:t,hashId:n,token:r,cssVar:i,zeroRuntime:a}},useCSP:()=>{let{csp:e}=(0,m.useContext)(zt);return e??{}},getResetStyles:(e,t)=>{let n=Mo(e);return[n,{"&":n},Po(t?.prefix.iconPrefixCls??`anticon`)]},getCommonStyle:No,getCompUnitless:()=>So}),zo=(e,t)=>{let n=`--${e.replace(/\./g,``)}-${t}-`;return[e=>`${n}${e}`,(e,t)=>t?`var(${n}${e}, ${t})`:`var(${n}${e})`]};function Bo(e,t){return oa.reduce((n,r)=>{let i=e[`${r}1`],a=e[`${r}3`],o=e[`${r}6`],s=e[`${r}7`];return{...n,...t(r,{lightColor:i,lightBorderColor:a,darkColor:o,textColor:s})}},{})}var Vo=(e,t)=>{let[n,r]=Eo();return pi({theme:n,token:r,hashId:``,path:[`ant-design-icons`,e],nonce:()=>t?.nonce,layer:{name:`antd`}},()=>Po(e))},Ho={icon:{tag:`svg`,attrs:{viewBox:`64 64 896 896`,focusable:`false`},children:[{tag:`path`,attrs:{d:`M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm193.5 301.7l-210.6 292a31.8 31.8 0 01-51.7 0L318.5 484.9c-3.8-5.3 0-12.7 6.5-12.7h46.9c10.2 0 19.9 4.9 25.9 13.3l71.2 98.8 157.2-218c6-8.3 15.6-13.3 25.9-13.3H699c6.5 0 10.3 7.4 6.5 12.7z`}}]},name:`check-circle`,theme:`filled`},Uo=(0,m.createContext)({});function Wo(e){return e?.getRootNode?.()}function Go(e){return Wo(e)instanceof ShadowRoot}function Ko(e){return Go(e)?Wo(e):null}function qo(e){return e.replace(/-(.)/g,(e,t)=>t.toUpperCase())}function Jo(e,t){$e(e,`[@ant-design/icons] ${t}`)}function Yo(e){return typeof e==`object`&&typeof e.name==`string`&&typeof e.theme==`string`&&(typeof e.icon==`object`||typeof e.icon==`function`)}function Xo(e={}){return Object.keys(e).reduce((t,n)=>{let r=e[n];switch(n){case`class`:t.className=r,delete t.class;break;default:delete t[n],t[qo(n)]=r}return t},{})}function Zo(e,t,n){return n?m.createElement(e.tag,{key:t,...Xo(e.attrs),...n},(e.children||[]).map((n,r)=>Zo(n,`${t}-${e.tag}-${r}`))):m.createElement(e.tag,{key:t,...Xo(e.attrs)},(e.children||[]).map((n,r)=>Zo(n,`${t}-${e.tag}-${r}`)))}function Qo(e){return ka(e)[0]}function $o(e){return e?Array.isArray(e)?e:[e]:[]}var es=` -.anticon { - display: inline-flex; - align-items: center; - color: inherit; - font-style: normal; - line-height: 0; - text-align: center; - text-transform: none; - vertical-align: -0.125em; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -.anticon > * { - line-height: 1; -} - -.anticon svg { - display: inline-block; - vertical-align: inherit; -} - -.anticon::before { - display: none; -} - -.anticon .anticon-icon { - display: block; -} - -.anticon[tabindex] { - cursor: pointer; -} - -.anticon-spin { - -webkit-animation: loadingCircle 1s infinite linear; - animation: loadingCircle 1s infinite linear; -} - -@-webkit-keyframes loadingCircle { - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } -} - -@keyframes loadingCircle { - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } -} -`,ts=e=>{let{csp:t,prefixCls:n,layer:r}=(0,m.useContext)(Uo),i=es;n&&(i=i.replace(/anticon/g,n)),r&&(i=`@layer ${r} {\n${i}\n}`),(0,m.useEffect)(()=>{let n=e.current,a=Ko(n);rn(i,`@ant-design-icons`,{prepend:!r,csp:t,attachTo:a})},[])},ns={primaryColor:`#333`,secondaryColor:`#E6E6E6`,calculated:!1};function rs({primaryColor:e,secondaryColor:t}){ns.primaryColor=e,ns.secondaryColor=t||Qo(e),ns.calculated=!!t}function is(){return{...ns}}var as=e=>{let{icon:t,className:n,onClick:r,style:i,primaryColor:a,secondaryColor:o,...s}=e,c=m.useRef(null),l=ns;if(a&&(l={primaryColor:a,secondaryColor:o||Qo(a)}),ts(c),Jo(Yo(t),`icon should be icon definiton, but got ${t}`),!Yo(t))return null;let u=t;return u&&typeof u.icon==`function`&&(u={...u,icon:u.icon(l.primaryColor,l.secondaryColor)}),Zo(u.icon,`svg-${u.name}`,{className:n,onClick:r,style:i,"data-icon":u.name,width:`1em`,height:`1em`,fill:`currentColor`,"aria-hidden":`true`,...s,ref:c})};as.displayName=`IconReact`,as.getTwoToneColors=is,as.setTwoToneColors=rs;function os(e){let[t,n]=$o(e);return as.setTwoToneColors({primaryColor:t,secondaryColor:n})}function ss(){let e=as.getTwoToneColors();return e.calculated?[e.primaryColor,e.secondaryColor]:e.primaryColor}function cs(){return cs=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{className:n,icon:r,spin:i,rotate:a,tabIndex:o,onClick:s,twoToneColor:c,...l}=e,{prefixCls:u=`anticon`,rootClassName:d}=m.useContext(Uo),f=K(d,u,{[`${u}-${r.name}`]:!!r.name,[`${u}-spin`]:!!i||r.name===`loading`},n),p=o;p===void 0&&s&&(p=-1);let h=a?{msTransform:`rotate(${a}deg)`,transform:`rotate(${a}deg)`}:void 0,[g,_]=$o(c);return m.createElement(`span`,cs({role:`img`,"aria-label":r.name},l,{ref:t,tabIndex:p,onClick:s,className:f}),m.createElement(as,{icon:r,primaryColor:g,secondaryColor:_,style:h}))});ls.getTwoToneColor=ss,ls.setTwoToneColor=os;function us(){return us=Object.assign?Object.assign.bind():function(e){for(var t=1;tm.createElement(ls,us({},e,{ref:t,icon:Ho}))),fs={icon:{tag:`svg`,attrs:{"fill-rule":`evenodd`,viewBox:`64 64 896 896`,focusable:`false`},children:[{tag:`path`,attrs:{d:`M512 64c247.4 0 448 200.6 448 448S759.4 960 512 960 64 759.4 64 512 264.6 64 512 64zm127.98 274.82h-.04l-.08.06L512 466.75 384.14 338.88c-.04-.05-.06-.06-.08-.06a.12.12 0 00-.07 0c-.03 0-.05.01-.09.05l-45.02 45.02a.2.2 0 00-.05.09.12.12 0 000 .07v.02a.27.27 0 00.06.06L466.75 512 338.88 639.86c-.05.04-.06.06-.06.08a.12.12 0 000 .07c0 .03.01.05.05.09l45.02 45.02a.2.2 0 00.09.05.12.12 0 00.07 0c.02 0 .04-.01.08-.05L512 557.25l127.86 127.87c.04.04.06.05.08.05a.12.12 0 00.07 0c.03 0 .05-.01.09-.05l45.02-45.02a.2.2 0 00.05-.09.12.12 0 000-.07v-.02a.27.27 0 00-.05-.06L557.25 512l127.87-127.86c.04-.04.05-.06.05-.08a.12.12 0 000-.07c0-.03-.01-.05-.05-.09l-45.02-45.02a.2.2 0 00-.09-.05.12.12 0 00-.07 0z`}}]},name:`close-circle`,theme:`filled`};function ps(){return ps=Object.assign?Object.assign.bind():function(e){for(var t=1;tm.createElement(ls,ps({},e,{ref:t,icon:fs}))),hs={icon:{tag:`svg`,attrs:{"fill-rule":`evenodd`,viewBox:`64 64 896 896`,focusable:`false`},children:[{tag:`path`,attrs:{d:`M799.86 166.31c.02 0 .04.02.08.06l57.69 57.7c.04.03.05.05.06.08a.12.12 0 010 .06c0 .03-.02.05-.06.09L569.93 512l287.7 287.7c.04.04.05.06.06.09a.12.12 0 010 .07c0 .02-.02.04-.06.08l-57.7 57.69c-.03.04-.05.05-.07.06a.12.12 0 01-.07 0c-.03 0-.05-.02-.09-.06L512 569.93l-287.7 287.7c-.04.04-.06.05-.09.06a.12.12 0 01-.07 0c-.02 0-.04-.02-.08-.06l-57.69-57.7c-.04-.03-.05-.05-.06-.07a.12.12 0 010-.07c0-.03.02-.05.06-.09L454.07 512l-287.7-287.7c-.04-.04-.05-.06-.06-.09a.12.12 0 010-.07c0-.02.02-.04.06-.08l57.7-57.69c.03-.04.05-.05.07-.06a.12.12 0 01.07 0c.03 0 .05.02.09.06L512 454.07l287.7-287.7c.04-.04.06-.05.09-.06a.12.12 0 01.07 0z`}}]},name:`close`,theme:`outlined`};function gs(){return gs=Object.assign?Object.assign.bind():function(e){for(var t=1;tm.createElement(ls,gs({},e,{ref:t,icon:hs}))),vs={icon:{tag:`svg`,attrs:{viewBox:`64 64 896 896`,focusable:`false`},children:[{tag:`path`,attrs:{d:`M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z`}}]},name:`exclamation-circle`,theme:`filled`};function ys(){return ys=Object.assign?Object.assign.bind():function(e){for(var t=1;tm.createElement(ls,ys({},e,{ref:t,icon:vs}))),xs={icon:{tag:`svg`,attrs:{viewBox:`64 64 896 896`,focusable:`false`},children:[{tag:`path`,attrs:{d:`M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm32 664c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V456c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272zm-32-344a48.01 48.01 0 010-96 48.01 48.01 0 010 96z`}}]},name:`info-circle`,theme:`filled`};function Ss(){return Ss=Object.assign?Object.assign.bind():function(e){for(var t=1;tm.createElement(ls,Ss({},e,{ref:t,icon:xs}))),ws=m.createContext({}),Ts=e=>{let{children:t,...n}=e,r=m.useMemo(()=>({motion:n.motion}),[n.motion]);return m.createElement(ws.Provider,{value:r},t)};function Es(e){let[,t]=m.useReducer(e=>e+1,0),n=m.useRef(e);return[W(()=>n.current),W(e=>{n.current=typeof e==`function`?e(n.current):e,t()})]}var Ds=`none`,Os=`appear`,ks=`enter`,As=`leave`,js=`none`,Ms=`prepare`,Ns=`start`,Ps=`active`,Fs=`prepared`;function Is(e,t){let n={};return n[e.toLowerCase()]=t.toLowerCase(),n[`Webkit${e}`]=`webkit${t}`,n[`Moz${e}`]=`moz${t}`,n[`ms${e}`]=`MS${t}`,n[`O${e}`]=`o${t.toLowerCase()}`,n}function Ls(e,t){let n={animationend:Is(`Animation`,`AnimationEnd`),transitionend:Is(`Transition`,`TransitionEnd`)};return e&&(`AnimationEvent`in t||delete n.animationend.animation,`TransitionEvent`in t||delete n.transitionend.transition),n}var Rs=Ls(ve(),typeof window<`u`?window:{}),zs={};ve()&&({style:zs}=document.createElement(`div`));var Bs={};function Vs(e){if(Bs[e])return Bs[e];let t=Rs[e];if(t){let n=Object.keys(t),r=n.length;for(let i=0;ie[1].toUpperCase())]:`${e}-${t}`:null}var Js=(e=>{let t=(0,m.useRef)();function n(t){t&&(t.removeEventListener(Ks,e),t.removeEventListener(Gs,e))}function r(r){t.current&&t.current!==r&&n(t.current),r&&r!==t.current&&(r.addEventListener(Ks,e),r.addEventListener(Gs,e),t.current=r)}return m.useEffect(()=>()=>{n(t.current),t.current=null},[]),[r,n]}),Ys=ve()?m.useLayoutEffect:m.useEffect,Xs=(()=>{let e=m.useRef(null);function t(){It.cancel(e.current)}function n(r,i=2){t();let a=It(()=>{i<=1?r({isCanceled:()=>a!==e.current}):n(r,i-1)});e.current=a}return m.useEffect(()=>()=>{t()},[]),[n,t]}),Zs=[Ms,Ns,Ps,`end`],Qs=[Ms,Fs];function $s(e){return e===`active`||e===`end`}var ec=((e,t,n)=>{let[r,i]=be(js),[a,o]=Xs();function s(){i(Ms,!0)}let c=t?Qs:Zs;return Ys(()=>{if(r!==`none`&&r!==`end`){let e=c[c.indexOf(r)+1],t=n(r);t===!1?i(e,!0):e&&a(n=>{function r(){n.isCanceled()||i(e,!0)}t===!0?r():Promise.resolve(t).then(r)})}},[e,r]),m.useEffect(()=>()=>{o()},[]),[s,r]});function tc(e,t,n,{motionEnter:r=!0,motionAppear:i=!0,motionLeave:a=!0,motionDeadline:o,motionLeaveImmediately:s,onAppearPrepare:c,onEnterPrepare:l,onLeavePrepare:u,onAppearStart:d,onEnterStart:f,onLeaveStart:p,onAppearActive:h,onEnterActive:g,onLeaveActive:_,onAppearEnd:v,onEnterEnd:y,onLeaveEnd:b,onVisibleChanged:x}){let[S,C]=m.useState(),[w,T]=Es(Ds),[E,D]=m.useState([null,null]),O=w(),k=(0,m.useRef)(!1),A=(0,m.useRef)(null);function j(){return n()}let M=(0,m.useRef)(!1);function N(){T(Ds),D([null,null])}let P=W(e=>{let t=w();if(t===`none`)return;let n=j();if(e&&!e.deadline&&e.target!==n)return;let r=M.current,i;t===`appear`&&r?i=v?.(n,e):t===`enter`&&r?i=y?.(n,e):t===`leave`&&r&&(i=b?.(n,e)),r&&i!==!1&&N()}),[F]=Js(P),I=e=>{switch(e){case Os:return{[Ms]:c,[Ns]:d,[Ps]:h};case ks:return{[Ms]:l,[Ns]:f,[Ps]:g};case As:return{[Ms]:u,[Ns]:p,[Ps]:_};default:return{}}},L=m.useMemo(()=>I(O),[O]),[ee,R]=ec(O,!e,e=>{if(e===`prepare`){let e=L[Ms];return e?e(j()):!1}return e in L&&D([L[e]?.(j(),null)||null,e]),e===`active`&&O!==`none`&&(F(j()),o>0&&(clearTimeout(A.current),A.current=setTimeout(()=>{P({deadline:!0})},o))),e===`prepared`&&N(),!0});M.current=$s(R);let z=(0,m.useRef)(null);Ys(()=>{if(k.current&&z.current===t)return;C(t);let n=k.current;k.current=!0;let o;!n&&t&&i&&(o=Os),n&&t&&r&&(o=ks),(n&&!t&&a||!n&&s&&!t&&a)&&(o=As);let c=I(o);o&&(e||c.prepare)?(T(o),ee()):T(Ds),z.current=t},[t]),(0,m.useEffect)(()=>{(O===`appear`&&!i||O===`enter`&&!r||O===`leave`&&!a)&&T(Ds)},[i,r,a]),(0,m.useEffect)(()=>()=>{k.current=!1,clearTimeout(A.current)},[]);let B=m.useRef(!1);(0,m.useEffect)(()=>{S&&(B.current=!0),S!==void 0&&O===`none`&&((B.current||S)&&x?.(S),B.current=!0)},[S,O]);let V=E[0];L.prepare&&R===`start`&&(V={transition:`none`,...V});let te=E[1];return[w,R,V,S??t,!k.current&&O===`none`&&e&&i?`NONE`:R===`start`||R===`active`?te===R:!0]}function nc(e){return e?.length<2}function rc(e){let t=e;typeof e==`object`&&({transitionSupport:t}=e);function n(e,n){return!!(e.motionName&&t&&n!==!1)}let r=m.forwardRef((e,t)=>{let{visible:r=!0,removeOnLeave:i=!0,forceRender:a,children:o,motionName:s,leavedClassName:c,eventProps:l}=e,{motion:u}=m.useContext(ws),d=n(e,u),f=(0,m.useRef)();function p(){return ct(f.current)}let[h,g,_,v,y]=tc(d,r,p,e),b=h(),x=m.useRef(v);v&&(x.current=!0);let S=m.useMemo(()=>{let e={};return Object.defineProperties(e,{nativeElement:{enumerable:!0,get:p},inMotion:{enumerable:!0,get:()=>()=>h()!==Ds},enableMotion:{enumerable:!0,get:()=>()=>d}}),e},[]);m.useImperativeHandle(t,()=>S,[]);let C=m.useRef(0);y&&(C.current+=1);let w=m.useMemo(()=>{if(y===`NONE`)return null;let e,t={...l,visible:r};if(!o)e=null;else if(b===`none`)e=v?o({...t},f):!i&&x.current&&c?o({...t,className:c},f):a||!i&&!c?o({...t,style:{display:`none`}},f):null;else{let n;g===`prepare`?n=`prepare`:$s(g)?n=`active`:g===`start`&&(n=`start`);let r=qs(s,`${b}-${n}`);e=o({...t,className:K(qs(s,b),{[r]:r&&n,[s]:typeof s==`string`}),style:_},f)}return e},[C.current]);if(nc(o)&&Ie(w)){let e=Le(w);if(e!==f)return m.cloneElement(w,{ref:Me(e,f)})}return w});return r.displayName=`CSSMotion`,r}var ic=rc(Ws),ac=`keep`,oc=`remove`,sc=`removed`;function cc(e){let t;return t=e&&typeof e==`object`&&`key`in e?e:{key:e},{...t,key:String(t.key)}}function lc(e=[]){return e.map(cc)}function uc(e=[],t=[]){let n=[],r=0,i=t.length,a=lc(e),o=lc(t);a.forEach(e=>{let t=!1;for(let a=r;a({...e,status:`add`}))),r=a),n.push({...i,status:ac}),r+=1,t=!0;break}}t||n.push({...e,status:oc})}),r({...e,status:`add`}))));let s={};return n.forEach(({key:e})=>{s[e]=(s[e]||0)+1}),Object.keys(s).filter(e=>s[e]>1).forEach(e=>{n=n.filter(({key:t,status:n})=>t!==e||n!==`remove`),n.forEach(t=>{t.key===e&&(t.status=ac)})}),n}function dc(){return dc=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let n=t.find(({key:t})=>e.key===t);return!(n&&n.status===`removed`&&e.status===`remove`)})}}removeKey=e=>{this.setState(t=>({keyEntities:t.keyEntities.map(t=>t.key===e?{...t,status:sc}:t)}),()=>{let{keyEntities:e}=this.state;e.filter(({status:e})=>e!==`removed`).length===0&&this.props.onAllRemoved&&this.props.onAllRemoved()})};render(){let{keyEntities:e}=this.state,{component:n,children:r,onVisibleChanged:i,onAllRemoved:a,...o}=this.props,s=n||m.Fragment,c={};return fc.forEach(e=>{c[e]=o[e],delete o[e]}),delete o.keys,m.createElement(s,o,e.map(({status:e,...n},a)=>{let o=e===`add`||e===`keep`;return m.createElement(t,dc({},c,{key:n.key,visible:o,eventProps:n,onVisibleChanged:e=>{i?.(e,{key:n.key}),e||this.removeKey(n.key)}}),nc(r)?e=>r({...e,index:a}):(e,t)=>r({...e,index:a},t))}))}}return n}var mc=pc(Ws),hc=ic,gc=`accept acceptCharset accessKey action allowFullScreen allowTransparency - alt async autoComplete autoFocus autoPlay capture cellPadding cellSpacing challenge - charSet checked classID className colSpan cols content contentEditable contextMenu - controls coords crossOrigin data dateTime default defer dir disabled download draggable - encType form formAction formEncType formMethod formNoValidate formTarget frameBorder - headers height hidden high href hrefLang htmlFor httpEquiv icon id inputMode integrity - is keyParams keyType kind label lang list loop low manifest marginHeight marginWidth max maxLength media - mediaGroup method min minLength multiple muted name noValidate nonce open - optimum pattern placeholder poster preload radioGroup readOnly rel required - reversed role rowSpan rows sandbox scope scoped scrolling seamless selected - shape size sizes span spellCheck src srcDoc srcLang srcSet start step style - summary tabIndex target title type useMap value width wmode wrap onCopy onCut onPaste onCompositionEnd onCompositionStart onCompositionUpdate onKeyDown - onKeyPress onKeyUp onFocus onBlur onChange onInput onSubmit onClick onContextMenu onDoubleClick - onDrag onDragEnd onDragEnter onDragExit onDragLeave onDragOver onDragStart onDrop onMouseDown - onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUp onSelect onTouchCancel - onTouchEnd onTouchMove onTouchStart onScroll onWheel onAbort onCanPlay onCanPlayThrough - onDurationChange onEmptied onEncrypted onEnded onError onLoadedData onLoadedMetadata - onLoadStart onPause onPlay onPlaying onProgress onRateChange onSeeked onSeeking onStalled onSuspend onTimeUpdate onVolumeChange onWaiting onLoad onError`.split(/[\s\n]+/),_c=`aria-`,vc=`data-`;function yc(e,t){return e.indexOf(t)===0}function bc(e,t=!1){let n;n=t===!1?{aria:!0,data:!0,attr:!0}:t===!0?{aria:!0}:{...t};let r={};return Object.keys(e).forEach(t=>{(n.aria&&(t===`role`||yc(t,_c))||n.data&&yc(t,vc)||n.attr&&gc.includes(t))&&(r[t]=e[t])}),r}var xc={items_per_page:`/ page`,jump_to:`Go to`,jump_to_confirm:`confirm`,page:`Page`,prev_page:`Previous Page`,next_page:`Next Page`,prev_5:`Previous 5 Pages`,next_5:`Next 5 Pages`,prev_3:`Previous 3 Pages`,next_3:`Next 3 Pages`,page_size:`Page Size`},Sc={yearFormat:`YYYY`,dayFormat:`D`,cellMeridiemFormat:`A`,monthBeforeYear:!0};function Cc(e){"@babel/helpers - typeof";return Cc=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},Cc(e)}function wc(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function Tc(e){for(var t=1;tIc.reduce((e,t)=>({...e,...t}),Pc.Modal);function Rc(e){if(e){let t={...e};return Ic.push(t),Fc=Lc(),()=>{Ic=Ic.filter(e=>e!==t),Fc=Lc()}}Fc={...Pc.Modal}}function zc(){return Fc}var Bc=(0,m.createContext)(void 0),Vc=(e,t)=>{let n=m.useContext(Bc);return[m.useMemo(()=>{let r=t||Pc[e],i=n?.[e]??{};return{...typeof r==`function`?r():r,...i||{}}},[e,t,n]),m.useMemo(()=>{let e=n?.locale;return n?.exist&&!e?Pc.locale:e},[n])]},Hc=`internalMark`,Uc=e=>{let{locale:t={},children:n,_ANT_MARK__:r}=e;m.useEffect(()=>Rc(t?.Modal),[t]);let i=m.useMemo(()=>({...t,exist:!0}),[t]);return m.createElement(Bc.Provider,{value:i},n)};function Wc(...e){let t={};return e.forEach(e=>{e&&Object.keys(e).forEach(n=>{e[n]!==void 0&&(t[n]=e[n])})}),t}var Gc=e=>e!=null,Kc=e=>{if(!e)return;let{closable:t,closeIcon:n}=e;return{closable:t,closeIcon:n}},qc={},Jc=(e,t)=>{if(!e&&(e===!1||t===!1||t===null))return!1;if(e===void 0&&t===void 0)return null;let n={closeIcon:typeof t!=`boolean`&&t!==null?t:void 0};return e&&typeof e==`object`&&(n={...n,...e}),n},Yc=(e,t,n)=>e===!1?!1:e?Wc(n,t,e):t===!1?!1:t?Wc(n,t):n.closable?n:!1,Xc=(e,t,n)=>{let{closeIconRender:r}=t,{closeIcon:i,...a}=e,o=i,s=bc(a,!0);return Gc(o)&&(r&&(o=r(o)),o=m.isValidElement(o)?m.cloneElement(o,{"aria-label":n,...o.props,...s}):m.createElement(`span`,{"aria-label":n,...s},o)),[o,s]},Zc=(e,t,n=qc,r=`Close`)=>{let i=Jc(e?.closable,e?.closeIcon),a=Jc(t?.closable,t?.closeIcon),o={closeIcon:m.createElement(_s,null),...n},s=Yc(i,a,o),c=typeof s==`boolean`?!1:!!s?.disabled;if(s===!1)return[!1,null,c,{}];let[l,u]=Xc(s,o,r);return[!0,l,c,u]},Qc=(e,t,n=qc)=>{let[r]=Vc(`global`,Pc.global);return m.useMemo(()=>Zc(e,t,{closeIcon:m.createElement(_s,null),...n},r.close),[e,t,n,r.close])},$c=()=>m.useReducer(e=>e+1,0),el=(e,t)=>{let n={};return e&&typeof e==`object`&&(n=e),typeof e==`boolean`&&(n={enabled:e}),n.closable===void 0&&t!==void 0&&(n.closable=t),n},tl=(e,t,n,r)=>(0,m.useMemo)(()=>{let i=el(e,r),a=el(t),o={blur:!1,...a,...i,closable:i.closable??r??a.closable??!0},s=o.blur?`${n}-mask-blur`:void 0;return[o.enabled!==!1,{mask:s},!!o.closable]},[e,t,n,r]),nl=(e,...t)=>{let n=e||{};return t.filter(Boolean).reduce((e,t)=>(Object.keys(t||{}).forEach(r=>{let i=n[r],a=t[r];if(i&&typeof i==`object`)if(a&&typeof a==`object`)e[r]=nl(i,e[r],a);else{let{_default:t}=i;t&&(e[r]=e[r]||{},e[r][t]=K(e[r][t],a))}else e[r]=K(e[r],a)}),e),{})},rl=(e,...t)=>m.useMemo(()=>nl.apply(void 0,[e].concat(t)),[e].concat(t)),il=(...e)=>e.filter(Boolean).reduce((e,t={})=>(Object.keys(t).forEach(n=>{e[n]={...e[n],...t[n]}}),e),{}),al=(...e)=>m.useMemo(()=>il.apply(void 0,e),[].concat(e)),ol=(e,t)=>{let n={...e};return Object.keys(t).forEach(e=>{if(e!==`_default`){let r=t[e],i=n[e]||{};n[e]=r?ol(i,r):i}}),n},sl=(e,t)=>typeof e==`function`?e(t):e,cl=(e,t,n,r)=>{let i=e.map(e=>e?sl(e,n):void 0),a=t.map(e=>e?sl(e,n):void 0),o=rl.apply(void 0,[r].concat(At(i))),s=al.apply(void 0,At(a));return m.useMemo(()=>r?[ol(o,r),ol(s,r)]:[o,s],[o,s,r])},ll=e=>e===`horizontal`||e===`vertical`,ul=(e,t,n)=>(0,m.useMemo)(()=>{let r=ll(e),i;return i=r?e:typeof t==`boolean`?t?`vertical`:`horizontal`:ll(n)?n:`horizontal`,[i,i===`vertical`]},[n,e,t]),dl=()=>{let[e,t]=m.useState([]);return[e,m.useCallback(e=>(t(t=>[].concat(At(t),[e])),()=>{t(t=>t.filter(t=>t!==e))}),[])]},fl=m.createContext(void 0),pl=100,ml=pl*10;ml+pl;var hl={Modal:pl,Drawer:pl,Popover:pl,Popconfirm:pl,Tooltip:pl,Tour:pl,FloatButton:pl},gl={SelectLike:50,Dropdown:50,DatePicker:50,Menu:50,ImagePreview:1},_l=e=>e in hl,vl=(e,t)=>{let[,n]=Eo(),r=m.useContext(fl),i=_l(e),a;if(t!==void 0)a=[t,t];else{let o=r??0;i?o+=(r?0:n.zIndexPopupBase)+hl[e]:o+=gl[e],a=[r===void 0?t:o,o]}return a},yl=e=>`${e}-css-var`,bl=(0,m.createContext)(void 0),xl=s((e=>{var t=p();function n(e){var t=`https://react.dev/errors/`+e;if(1{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=xl()})),Cl=m.createContext(null),wl=!1;function Tl(e){return typeof e==`boolean`&&(wl=e),wl}var El=[];function Dl(e,t){let[n]=m.useState(()=>ve()?document.createElement(`div`):null),r=m.useRef(!1),i=m.useContext(Cl),[a,o]=m.useState(El),s=i||(r.current?void 0:e=>{o(t=>[e,...t])});function c(){n.parentElement||document.body.appendChild(n),r.current=!0}function l(){n.parentElement?.removeChild(n),r.current=!1}return G(()=>(e?i?i(c):c():l(),l),[e]),G(()=>{a.length&&(a.forEach(e=>e()),o(El))},[a]),[n,s]}function Ol(e){let t=`rc-scrollbar-measure-${Math.random().toString(36).substring(7)}`,n=document.createElement(`div`);n.id=t;let r=n.style;r.position=`absolute`,r.left=`0`,r.top=`0`,r.width=`100px`,r.height=`100px`,r.overflow=`scroll`;let i,a;if(e){let n=getComputedStyle(e);r.scrollbarColor=n.scrollbarColor,r.scrollbarWidth=n.scrollbarWidth;let o=getComputedStyle(e,`::-webkit-scrollbar`),s=parseInt(o.width,10),c=parseInt(o.height,10);try{rn(` -#${t}::-webkit-scrollbar { -${s?`width: ${o.width};`:``} -${c?`height: ${o.height};`:``} -}`,t)}catch(e){console.error(e),i=s,a=c}}document.body.appendChild(n);let o=e&&i&&!Number.isNaN(i)?i:n.offsetWidth-n.clientWidth,s=e&&a&&!Number.isNaN(a)?a:n.offsetHeight-n.clientHeight;return document.body.removeChild(n),tn(t),{width:o,height:s}}function kl(e){return typeof document>`u`||!e||!(e instanceof Element)?{width:0,height:0}:Ol(e)}function Al(){return document.body.scrollHeight>(window.innerHeight||document.documentElement.clientHeight)&&window.innerWidth>document.body.offsetWidth}var jl=`rc-util-locker-${Date.now()}`,Ml=0;function Nl(e){let t=!!e,[n]=m.useState(()=>(Ml+=1,`${jl}_${Ml}`));G(()=>{if(t){let e=kl(document.body).width;rn(` -html body { - overflow-y: hidden; - ${Al()?`width: calc(100% - ${e}px);`:``} -}`,n)}else tn(n);return()=>{tn(n)}},[t,n])}function Pl(){return{...m}.useId}var Fl=0,Il=Pl(),Ll=Il?function(e){let t=Il();return e||t}:function(e){let[t,n]=m.useState(`ssr-id`);return m.useEffect(()=>{let e=Fl;Fl+=1,n(`rc_unique_${e}`)},[]),e||t},Rl=[],zl=200,Bl=0,Vl=e=>{if(e.key===`Escape`&&!e.isComposing){if(Date.now()-Bl=0;--n)Rl[n].onEsc({top:n===t-1,event:e})}},Hl=()=>{Bl=Date.now()};function Ul(){window.addEventListener(`keydown`,Vl),window.addEventListener(`compositionend`,Hl)}function Wl(){Rl.length===0&&(window.removeEventListener(`keydown`,Vl),window.removeEventListener(`compositionend`,Hl))}function Gl(e,t){let n=Ll(),r=W(t),i=()=>{Rl.find(e=>e.id===n)||Rl.push({id:n,onEsc:r})},a=()=>{Rl=Rl.filter(e=>e.id!==n)};(0,m.useMemo)(()=>{e?i():e||a()},[e]),(0,m.useEffect)(()=>{if(e)return i(),Ul(),()=>{a(),Wl()}},[e])}var Kl=u(Sl()),ql=e=>e===!1?!1:!ve()||!e?null:typeof e==`string`?document.querySelector(e):typeof e==`function`?e():e,Jl=m.forwardRef((e,t)=>{let{open:n,autoLock:r,getContainer:i,debug:a,autoDestroy:o=!0,children:s,onEsc:c}=e,[l,u]=m.useState(n),d=l||n;m.useEffect(()=>{(o||n)&&u(n)},[n,o]);let[f,p]=m.useState(()=>ql(i));m.useEffect(()=>{let e=ql(i);p(()=>e??null)});let[h,g]=Dl(d&&!f,a),_=f??h;Nl(r&&n&&ve()&&(_===h||_===document.body)),Gl(n,c);let v=null;s&&Pe(s)&&t&&(v=Le(s));let y=Ne(v,t);if(!d||!ve()||f===void 0)return null;let b=_===!1||Tl(),x=s;return t&&(x=m.cloneElement(s,{ref:y})),m.createElement(Cl.Provider,{value:g},b?x:(0,Kl.createPortal)(x,_))});function Yl(e){let{prefixCls:t,align:n,arrow:r,arrowPos:i}=e,{className:a,content:o,style:s}=r||{},{x:c=0,y:l=0}=i,u=m.useRef(null);if(!n||!n.points)return null;let d={position:`absolute`};if(n.autoArrow!==!1){let e=n.points[0],t=n.points[1],r=e[0],i=e[1],a=t[0],o=t[1];r===a||![`t`,`b`].includes(r)?d.top=l:r===`t`?d.top=0:d.bottom=0,i===o||![`l`,`r`].includes(i)?d.left=c:i===`l`?d.left=0:d.right=0}return m.createElement(`div`,{ref:u,className:K(`${t}-arrow`,a),style:{...d,...s}},o)}function Xl(){return Xl=Object.assign?Object.assign.bind():function(e){for(var t=1;tm.createElement(`div`,{style:{zIndex:r},className:K(`${t}-mask`,o&&`${t}-mobile-mask`,e)})):null}var Ql=m.memo(({children:e})=>e,(e,t)=>t.cache);function $l(e,t,n,r,i,a,o,s){let c=`auto`,l=e?{}:{left:`-1000vw`,top:`-1000vh`,right:c,bottom:c};if(!e&&(t||!n)){let{points:e}=r,t=r.dynamicInset||r._experimental?.dynamicInset,n=t&&e[0][1]===`r`,u=t&&e[0][0]===`b`;n?(l.right=i,l.left=c):(l.left=o,l.right=c),u?(l.bottom=a,l.top=c):(l.top=s,l.bottom=c)}return l}function eu(){return eu=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{onEsc:n,popup:r,className:i,prefixCls:a,style:o,target:s,onVisibleChanged:c,open:l,keepDom:u,fresh:d,onClick:f,mask:p,arrow:h,arrowPos:g,align:_,motion:v,maskMotion:y,mobile:b,forceRender:x,getPopupContainer:S,autoDestroy:C,portal:w,children:T,zIndex:E,onMouseEnter:D,onMouseLeave:O,onPointerEnter:k,onPointerDownCapture:A,ready:j,offsetX:M,offsetY:N,offsetR:P,offsetB:F,onAlign:I,onPrepare:L,onResize:ee,stretch:R,targetWidth:z,targetHeight:B}=e,V=typeof r==`function`?r():r,te=l||u,ne=!!b,[re,ie,ae]=m.useMemo(()=>b?[b.mask,b.maskMotion,b.motion]:[p,y,v],[b,p,y,v]),oe=S?.length>0,[H,se]=m.useState(!S||!oe);G(()=>{!H&&oe&&s&&se(!0)},[H,oe,s]);let ce=W((e,t)=>{ee?.(e,t),I()}),le=$l(ne,j,l,_,P,F,M,N);if(!H)return null;let U={};return R&&(R.includes(`height`)&&B?U.height=B:R.includes(`minHeight`)&&B&&(U.minHeight=B),R.includes(`width`)&&z?U.width=z:R.includes(`minWidth`)&&z&&(U.minWidth=z)),l||(U.pointerEvents=`none`),m.createElement(w,{open:x||te,getContainer:S&&(()=>S(s)),autoDestroy:C,onEsc:n},m.createElement(Zl,{prefixCls:a,open:l,zIndex:E,mask:re,motion:ie,mobile:ne}),m.createElement(Ct,{onResize:ce,disabled:!l},e=>m.createElement(hc,eu({motionAppear:!0,motionEnter:!0,motionLeave:!0,removeOnLeave:!1,forceRender:x,leavedClassName:`${a}-hidden`},ae,{onAppearPrepare:L,onEnterPrepare:L,visible:l,onVisibleChanged:e=>{v?.onVisibleChanged?.(e),c(e)}}),({className:n,style:r},s)=>{let c=K(a,n,i,{[`${a}-mobile`]:ne});return m.createElement(`div`,{ref:Me(e,t,s),className:c,style:{"--arrow-x":`${g.x||0}px`,"--arrow-y":`${g.y||0}px`,...le,...U,...r,boxSizing:`border-box`,zIndex:E,...o},onMouseEnter:D,onMouseLeave:O,onPointerEnter:k,onClick:f,onPointerDownCapture:A},h&&m.createElement(Yl,{prefixCls:a,arrow:h,arrowPos:g,align:_}),m.createElement(Ql,{cache:!l&&!d},V))})),T)}),nu=m.createContext(null),ru=m.createContext(null);function iu(e){return e?Array.isArray(e)?e:[e]:[]}function au(e,t,n){return m.useMemo(()=>{let r=iu(t??e),i=iu(n??e),a=new Set(r),o=new Set(i);return a.has(`hover`)&&!a.has(`click`)&&a.add(`touch`),o.has(`hover`)&&!o.has(`click`)&&o.add(`touch`),[a,o]},[e,t,n])}var ou=(e=>{if(!e)return!1;if(e instanceof Element){if(e.offsetParent)return!0;if(e.getBBox){let{width:t,height:n}=e.getBBox();if(t||n)return!0}if(e.getBoundingClientRect){let{width:t,height:n}=e.getBoundingClientRect();if(t||n)return!0}}return!1});function su(e=[],t=[],n){let r=(e,t)=>e[t]||``;return n?r(e,0)===r(t,0):r(e,0)===r(t,0)&&r(e,1)===r(t,1)}function cu(e,t,n,r){let{points:i}=n,a=Object.keys(e);for(let n=0;nr.includes(e))&&t.push(n),n=n.parentElement}return t}function du(e,t=1){return Number.isNaN(e)?t:e}function fu(e){return du(parseFloat(e),0)}function pu(e,t){let n={...e};return(t||[]).forEach(e=>{if(e instanceof HTMLBodyElement||e instanceof HTMLHtmlElement)return;let{overflow:t,overflowClipMargin:r,borderTopWidth:i,borderBottomWidth:a,borderLeftWidth:o,borderRightWidth:s}=lu(e).getComputedStyle(e),c=e.getBoundingClientRect(),{offsetHeight:l,clientHeight:u,offsetWidth:d,clientWidth:f}=e,p=fu(i),m=fu(a),h=fu(o),g=fu(s),_=du(Math.round(c.width/d*1e3)/1e3),v=du(Math.round(c.height/l*1e3)/1e3),y=(d-f-h-g)*_,b=(l-u-p-m)*v,x=p*v,S=m*v,C=h*_,w=g*_,T=0,E=0;if(t===`clip`){let e=fu(r);T=e*_,E=e*v}let D=c.x+C-T,O=c.y+x-E,k=D+c.width+2*T-C-w-y,A=O+c.height+2*E-x-S-b;n.left=Math.max(n.left,D),n.top=Math.max(n.top,O),n.right=Math.min(n.right,k),n.bottom=Math.min(n.bottom,A)}),n}function mu(e,t=0){let n=`${t}`,r=n.match(/^(.*)\%$/);return r?e*(parseFloat(r[1])/100):parseFloat(n)}function hu(e,t){let[n,r]=t||[];return[mu(e.width,n),mu(e.height,r)]}function gu(e=``){return[e[0],e[1]]}function _u(e,t){let n=t[0],r=t[1],i,a;return a=n===`t`?e.y:n===`b`?e.y+e.height:e.y+e.height/2,i=r===`l`?e.x:r===`r`?e.x+e.width:e.x+e.width/2,{x:i,y:a}}function vu(e,t){let n={t:`b`,b:`t`,l:`r`,r:`l`},r=[...e];return r[t]=n[e[t]]||`c`,r}function yu(e){return e.join(``)}function bu(e,t,n,r,i,a,o,s){let[c,l]=m.useState({ready:!1,offsetX:0,offsetY:0,offsetR:0,offsetB:0,arrowX:0,arrowY:0,scaleX:1,scaleY:1,align:i[r]||{}}),u=m.useRef(0),d=m.useMemo(()=>!t||s?[]:uu(t),[t]),f=m.useRef({});e||(f.current={});let p=W(()=>{if(t&&n&&e&&!s){let e=t,s=e.ownerDocument,c=lu(e),{position:u}=c.getComputedStyle(e),p=e.style.left,m=e.style.top,h=e.style.right,g=e.style.bottom,_=e.style.overflow,v={...i[r],...a},y=s.createElement(`div`);e.parentElement?.appendChild(y),y.style.left=`${e.offsetLeft}px`,y.style.top=`${e.offsetTop}px`,y.style.position=u,y.style.height=`${e.offsetHeight}px`,y.style.width=`${e.offsetWidth}px`,e.style.left=`0`,e.style.top=`0`,e.style.right=`auto`,e.style.bottom=`auto`,e.style.overflow=`hidden`;let b;if(Array.isArray(n))b={x:n[0],y:n[1],width:0,height:0};else{let e=n.getBoundingClientRect();e.x=e.x??e.left,e.y=e.y??e.top,b={x:e.x,y:e.y,width:e.width,height:e.height}}let x=e.getBoundingClientRect(),{height:S,width:C}=c.getComputedStyle(e);x.x=x.x??x.left,x.y=x.y??x.top;let{clientWidth:w,clientHeight:T,scrollWidth:E,scrollHeight:D,scrollTop:O,scrollLeft:k}=s.documentElement,A=x.height,j=x.width,M=b.height,N=b.width,P={left:0,top:0,right:w,bottom:T},F={left:-k,top:-O,right:E-k,bottom:D-O},{htmlRegion:I}=v,L=`visible`,ee=`visibleFirst`;I!==`scroll`&&I!==ee&&(I=L);let R=I===ee,z=pu(F,d),B=pu(P,d),V=I===L?B:z,te=R?B:V;e.style.left=`auto`,e.style.top=`auto`,e.style.right=`0`,e.style.bottom=`0`;let ne=e.getBoundingClientRect();e.style.left=p,e.style.top=m,e.style.right=h,e.style.bottom=g,e.style.overflow=_,e.parentElement?.removeChild(y);let re=du(Math.round(j/parseFloat(C)*1e3)/1e3),ie=du(Math.round(A/parseFloat(S)*1e3)/1e3);if(re===0||ie===0||st(n)&&!ou(n))return;let{offset:ae,targetOffset:oe}=v,[H,se]=hu(x,ae),[ce,le]=hu(b,oe);b.x-=ce,b.y-=le;let[U,ue]=v.points||[],de=gu(ue),fe=gu(U),pe=_u(b,de),me=_u(x,fe),he={...v},ge=[fe,de],_e=pe.x-me.x+H,W=pe.y-me.y+se;function ve(e,t,n=V){let r=x.x+e,i=x.y+t,a=r+j,o=i+A,s=Math.max(r,n.left),c=Math.max(i,n.top),l=Math.min(a,n.right),u=Math.min(o,n.bottom);return Math.max(0,(l-s)*(u-c))}let ye=ve(_e,W),G=ve(_e,W,B),be=_u(b,[`t`,`l`]),xe=_u(x,[`t`,`l`]),Se=_u(b,[`b`,`r`]),Ce=_u(x,[`b`,`r`]),{adjustX:we,adjustY:Te,shiftX:Ee,shiftY:De}=v.overflow||{},Oe=e=>typeof e==`boolean`?e:e>=0,ke,Ae,je,Me;function Ne(){ke=x.y+W,Ae=ke+A,je=x.x+_e,Me=je+j}Ne();let Pe=Oe(Te),Fe=fe[0]===de[0];if(Pe&&fe[0]===`t`&&(Ae>te.bottom||f.current.bt)){let e=W;Fe?e-=A-M:e=be.y-Ce.y-se;let t=ve(_e,e),n=ve(_e,e,B);t>ye||t===ye&&(!R||n>=G)?(f.current.bt=!0,W=e,se=-se,ge=[vu(ge[0],0),vu(ge[1],0)]):f.current.bt=!1}if(Pe&&fe[0]===`b`&&(keye||t===ye&&(!R||n>=G)?(f.current.tb=!0,W=e,se=-se,ge=[vu(ge[0],0),vu(ge[1],0)]):f.current.tb=!1}let Ie=Oe(we),Le=fe[1]===de[1];if(Ie&&fe[1]===`l`&&(Me>te.right||f.current.rl)){let e=_e;Le?e-=j-N:e=be.x-Ce.x-H;let t=ve(e,W),n=ve(e,W,B);t>ye||t===ye&&(!R||n>=G)?(f.current.rl=!0,_e=e,H=-H,ge=[vu(ge[0],1),vu(ge[1],1)]):f.current.rl=!1}if(Ie&&fe[1]===`r`&&(jeye||t===ye&&(!R||n>=G)?(f.current.lr=!0,_e=e,H=-H,ge=[vu(ge[0],1),vu(ge[1],1)]):f.current.lr=!1}he.points=[yu(ge[0]),yu(ge[1])],Ne();let Re=Ee===!0?0:Ee;typeof Re==`number`&&(jeB.right&&(_e-=Me-B.right-H,b.x>B.right-Re&&(_e+=b.x-B.right+Re)));let ze=De===!0?0:De;typeof ze==`number`&&(keB.bottom&&(W-=Ae-B.bottom-se,b.y>B.bottom-ze&&(W+=b.y-B.bottom+ze)));let Be=x.x+_e,Ve=Be+j,He=x.y+W,Ue=He+A,We=b.x,Ge=We+N,Ke=b.y,qe=Ke+M,Je=(Math.max(Be,We)+Math.min(Ve,Ge))/2-Be,Ye=(Math.max(He,Ke)+Math.min(Ue,qe))/2-He;o?.(t,he);let Xe=ne.right-x.x-(_e+x.width),Ze=ne.bottom-x.y-(W+x.height);re===1&&(_e=Math.floor(_e),Xe=Math.floor(Xe)),ie===1&&(W=Math.floor(W),Ze=Math.floor(Ze)),l({ready:!0,offsetX:_e/re,offsetY:W/ie,offsetR:Xe/re,offsetB:Ze/ie,arrowX:Je/re,arrowY:Ye/ie,scaleX:re,scaleY:ie,align:he})}}),h=()=>{u.current+=1;let e=u.current;Promise.resolve().then(()=>{u.current===e&&p()})},g=()=>{l(e=>({...e,ready:!1}))};return G(g,[r]),G(()=>{e||g()},[e]),[c.ready,c.offsetX,c.offsetY,c.offsetR,c.offsetB,c.arrowX,c.arrowY,c.scaleX,c.scaleY,c.align,h]}function xu(){let e=m.useRef(null),t=()=>{e.current&&=(clearTimeout(e.current),null)};return m.useEffect(()=>()=>{t()},[]),(n,r)=>{t(),r===0?n():e.current=setTimeout(()=>{n()},r*1e3)}}function Su(e,t,n,r,i){G(()=>{if(e&&t&&n){let e=t,a=n,o=uu(e),s=uu(a),c=lu(a),l=new Set([c,...o,...s]);function u(){r(),i()}return l.forEach(e=>{e.addEventListener(`scroll`,u,{passive:!0})}),c.addEventListener(`resize`,u,{passive:!0}),r(),()=>{l.forEach(e=>{e.removeEventListener(`scroll`,u),c.removeEventListener(`resize`,u)})}}},[e,t,n])}function Cu(e,t,n,r,i,a,o,s){let c=m.useRef(e);c.current=e;let l=m.useRef(!1);m.useEffect(()=>{if(t&&r&&(!i||a)){let e=()=>{l.current=!1},t=e=>{c.current&&!o(e.composedPath?.()?.[0]||e.target)&&!l.current&&s(!1)},i=lu(r);i.addEventListener(`pointerdown`,e,!0),i.addEventListener(`mousedown`,t,!0),i.addEventListener(`contextmenu`,t,!0);let a=Ko(n);return a&&(a.addEventListener(`mousedown`,t,!0),a.addEventListener(`contextmenu`,t,!0)),()=>{i.removeEventListener(`pointerdown`,e,!0),i.removeEventListener(`mousedown`,t,!0),i.removeEventListener(`contextmenu`,t,!0),a&&(a.removeEventListener(`mousedown`,t,!0),a.removeEventListener(`contextmenu`,t,!0))}}},[t,n,r,i,a]);function u(){l.current=!0}return u}function wu(){let[e,t]=m.useState(null),[n,r]=m.useState(!1),[i,a]=m.useState(!1),o=m.useRef(null);return[W(e=>{e===!1?(o.current=null,r(!1)):i&&n?o.current=e:(r(!0),t(e),o.current=null,n||a(!0))}),n,e,W(e=>{e?(a(!1),o.current&&=(t(o.current),null)):(a(!1),o.current=null)})]}function Tu(){return Tu=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{prefixCls:t,isMobile:n,ready:r,open:i,align:a,offsetR:o,offsetB:s,offsetX:c,offsetY:l,arrowPos:u,popupSize:d,motion:f,uniqueContainerClassName:p,uniqueContainerStyle:h}=e,g=`${t}-unique-container`,[_,v]=m.useState(!1),y=$l(n,r,i,a,o,s,c,l),b=m.useRef(y);r&&(b.current=y);let x={};return d&&(x.width=d.width,x.height=d.height),m.createElement(hc,Tu({motionAppear:!0,motionEnter:!0,motionLeave:!0,removeOnLeave:!1,leavedClassName:`${g}-hidden`},f,{visible:i,onVisibleChanged:e=>{v(e)}}),({className:e,style:t})=>{let n=K(g,e,p,{[`${g}-visible`]:_});return m.createElement(`div`,{className:n,style:{"--arrow-x":`${u?.x||0}px`,"--arrow-y":`${u?.y||0}px`,...b.current,...x,...t,...h}})})},Du=({children:e,postTriggerProps:t})=>{let[n,r,i,a]=wu(),o=m.useMemo(()=>!i||!t?i:t(i),[i,t]),[s,c]=m.useState(null),[l,u]=m.useState(null),d=m.useRef(null),f=W(e=>{d.current=e,st(e)&&s!==e&&c(e)}),p=m.useRef(null),h=xu(),g=W((e,t)=>{p.current=t,h(()=>{n(e)},e.delay)}),_=e=>{h(()=>{p.current?.()||n(!1)},e)},v=W(e=>{a(e)}),[y,b,x,S,C,w,T,,,E,D]=bu(r,s,o?.target,o?.popupPlacement,o?.builtinPlacements||{},o?.popupAlign,void 0,!1),O=m.useMemo(()=>o?K(cu(o.builtinPlacements||{},o.prefixCls||``,E,!1),o.getPopupClassNameFromAlign?.(E)):``,[E,o?.getPopupClassNameFromAlign,o?.builtinPlacements,o?.prefixCls]),k=m.useMemo(()=>({show:g,hide:_}),[]);m.useEffect(()=>{D()},[o?.target]);let A=W(()=>(D(),Promise.resolve())),j=m.useRef({}),M=m.useContext(nu),N=m.useMemo(()=>({registerSubPopup:(e,t)=>{j.current[e]=t,M?.registerSubPopup(e,t)}}),[M]),P=o?.prefixCls;return m.createElement(ru.Provider,{value:k},e,o&&m.createElement(nu.Provider,{value:N},m.createElement(tu,{ref:f,portal:Jl,onEsc:o.onEsc,prefixCls:P,popup:o.popup,className:K(o.popupClassName,O,`${P}-unique-controlled`),style:o.popupStyle,target:o.target,open:r,keepDom:!0,fresh:!0,autoDestroy:!1,onVisibleChanged:v,ready:y,offsetX:b,offsetY:x,offsetR:S,offsetB:C,onAlign:D,onPrepare:A,onResize:e=>u({width:e.offsetWidth,height:e.offsetHeight}),arrowPos:{x:w,y:T},align:E,zIndex:o.zIndex,mask:o.mask,arrow:o.arrow,motion:o.popupMotion,maskMotion:o.maskMotion,getPopupContainer:o.getPopupContainer},m.createElement(Eu,{prefixCls:P,isMobile:!1,ready:y,open:r,align:E,offsetR:S,offsetB:C,offsetX:b,offsetY:x,arrowPos:{x:w,y:T},popupSize:l,motion:o.popupMotion,uniqueContainerClassName:K(o.uniqueContainerClassName,O),uniqueContainerStyle:o.uniqueContainerStyle}))))};function Ou(e=Jl){return m.forwardRef((t,n)=>{let{prefixCls:r=`rc-trigger-popup`,children:i,action:a=`hover`,showAction:o,hideAction:s,popupVisible:c,defaultPopupVisible:l,onOpenChange:u,afterOpenChange:d,onPopupVisibleChange:f,afterPopupVisibleChange:p,mouseEnterDelay:h,mouseLeaveDelay:g=.1,focusDelay:_,blurDelay:v,mask:y,maskClosable:b=!0,getPopupContainer:x,forceRender:S,autoDestroy:C,popup:w,popupClassName:T,uniqueContainerClassName:E,uniqueContainerStyle:D,popupStyle:O,popupPlacement:k,builtinPlacements:A={},popupAlign:j,zIndex:M,stretch:N,getPopupClassNameFromAlign:P,fresh:F,unique:I,alignPoint:L,onPopupClick:ee,onPopupAlign:R,arrow:z,popupMotion:B,maskMotion:V,mobile:te,...ne}=t,re=C||!1,ie=c===void 0,ae=!!te,oe=m.useRef({}),H=m.useContext(nu),se=m.useMemo(()=>({registerSubPopup:(e,t)=>{oe.current[e]=t,H?.registerSubPopup(e,t)}}),[H]),ce=m.useContext(ru),le=Ll(),[U,ue]=m.useState(null),de=m.useRef(null),fe=W(e=>{de.current=e,st(e)&&U!==e&&ue(e),H?.registerSubPopup(le,e)}),[pe,me]=m.useState(null),he=m.useRef(null),ge=W(e=>{let t=ct(e);st(t)&&pe!==t&&(me(t),he.current=t)}),_e={},ve=W(e=>{let t=pe;return t?.contains(e)||Ko(t)?.host===e||e===t||U?.contains(e)||Ko(U)?.host===e||e===U||Object.values(oe.current).some(t=>t?.contains(e)||e===t)}),ye=z?{...z===!0?{}:z}:null,[be,Se]=xe(l||!1,c),Ce=be||!1,we=m.useMemo(()=>{let e=typeof i==`function`?i({open:Ce}):i;return m.Children.only(e)},[i,Ce]),Te=we?.props||{},Ee=W(()=>Ce),De=W((e=0)=>({popup:w,target:pe,delay:e,prefixCls:r,popupClassName:T,uniqueContainerClassName:E,uniqueContainerStyle:D,popupStyle:O,popupPlacement:k,builtinPlacements:A,popupAlign:j,zIndex:M,mask:y,maskClosable:b,popupMotion:B,maskMotion:V,arrow:ye,getPopupContainer:x,getPopupClassNameFromAlign:P,id:le,onEsc:Me}));G(()=>{ce&&I&&pe&&!ie&&!H&&(Ce?ce.show(De(h),Ee):ce.hide(g))},[Ce,pe]);let Oe=m.useRef(Ce);Oe.current=Ce;let ke=W(e=>{(0,Kl.flushSync)(()=>{Ce!==e&&(Se(e),u?.(e),f?.(e))})}),Ae=xu(),je=(e,t=0)=>{if(c!==void 0){Ae(()=>{ke(e)},t);return}if(ce&&I&&ie&&!H){e?ce.show(De(t),Ee):ce.hide(t);return}Ae(()=>{ke(e)},t)};function Me({top:e}){e&&je(!1)}let[Pe,Fe]=m.useState(!1);G(e=>{(!e||Ce)&&Fe(!0)},[Ce]);let[Ie,Re]=m.useState(null),[ze,Be]=m.useState(null),Ve=e=>{Be([e.clientX,e.clientY])},[He,Ue,We,Ge,Ke,qe,Je,Ye,Xe,Ze,Qe]=bu(Ce,U,L&&ze!==null?ze:pe,k,A,j,R,ae),[$e,et]=au(a,o,s),tt=$e.has(`click`),nt=et.has(`click`)||et.has(`contextMenu`),rt=W(()=>{Pe||Qe()});Su(Ce,pe,U,rt,()=>{Oe.current&&L&&nt&&je(!1)}),G(()=>{rt()},[ze,k]),G(()=>{Ce&&!A?.[k]&&rt()},[JSON.stringify(j)]);let it=m.useMemo(()=>K(cu(A,r,Ze,L),P?.(Ze)),[Ze,P,A,r,L]);m.useImperativeHandle(n,()=>({nativeElement:he.current,popupElement:de.current,forceAlign:rt}));let[at,ot]=m.useState(0),[lt,ut]=m.useState(0),dt=()=>{if(N&&pe){let e=pe.getBoundingClientRect();ot(e.width),ut(e.height)}},ft=()=>{dt(),rt()},pt=e=>{Fe(!1),Qe(),d?.(e),p?.(e)},mt=()=>new Promise(e=>{dt(),Re(()=>e)});G(()=>{Ie&&(Qe(),Ie(),Re(null))},[Ie]);function ht(e,t,n,r,i){_e[e]=(a,...o)=>{(!i||!i())&&(r?.(a),je(t,n)),Te[e]?.(a,...o)}}let gt=$e.has(`touch`),vt=et.has(`touch`),yt=m.useRef(!1);(gt||vt)&&(_e.onTouchStart=(...e)=>{yt.current=!0,Oe.current&&vt?je(!1):!Oe.current&>&&je(!0),Te.onTouchStart?.(...e)}),(tt||nt)&&(_e.onClick=(e,...t)=>{Oe.current&&nt?je(!1):!Oe.current&&tt&&(Ve(e),je(!0)),Te.onClick?.(e,...t),yt.current=!1});let bt=Cu(Ce,nt||vt,pe,U,y,b,ve,je),xt=$e.has(`hover`),St=et.has(`hover`),Ct,wt,Tt=()=>yt.current;if(xt){let e=e=>{Ve(e)};ht(`onMouseEnter`,!0,h,e,Tt),ht(`onPointerEnter`,!0,h,e,Tt),Ct=e=>{(Ce||Pe)&&U?.contains(e.target)&&je(!0,h)},L&&(_e.onMouseMove=e=>{Te.onMouseMove?.(e)})}St&&(ht(`onMouseLeave`,!1,g,void 0,Tt),ht(`onPointerLeave`,!1,g,void 0,Tt),wt=()=>{je(!1,g)}),$e.has(`focus`)&&ht(`onFocus`,!0,_),et.has(`focus`)&&ht(`onBlur`,!1,v),$e.has(`contextMenu`)&&(_e.onContextMenu=(e,...t)=>{Oe.current&&et.has(`contextMenu`)?je(!1):(Ve(e),je(!0)),e.preventDefault(),Te.onContextMenu?.(e,...t)});let Et=m.useRef(!1);Et.current||=S||Ce||Pe;let Dt={...Te,..._e},Ot={};[`onContextMenu`,`onClick`,`onMouseDown`,`onTouchStart`,`onMouseEnter`,`onMouseLeave`,`onFocus`,`onBlur`].forEach(e=>{ne[e]&&(Ot[e]=(...t)=>{Dt[e]?.(...t),ne[e](...t)})});let kt={x:qe,y:Je};_t(Ce,pe,ft);let At=Ne(ge,Le(we)),jt=m.cloneElement(we,{...Dt,...Ot,ref:At});return m.createElement(m.Fragment,null,jt,Et.current&&(!ce||!I)&&m.createElement(nu.Provider,{value:se},m.createElement(tu,{portal:e,ref:fe,prefixCls:r,popup:w,className:K(T,!ae&&it),style:O,target:pe,onMouseEnter:Ct,onMouseLeave:wt,onPointerEnter:Ct,zIndex:M,open:Ce,keepDom:Pe,fresh:F,onClick:ee,onPointerDownCapture:bt,mask:y,motion:B,maskMotion:V,onVisibleChanged:pt,onPrepare:mt,forceRender:S,autoDestroy:re,getPopupContainer:x,onEsc:Me,align:Ze,arrow:ye,arrowPos:kt,ready:He,offsetX:Ue,offsetY:We,offsetR:Ge,offsetB:Ke,onAlign:rt,stretch:N,targetWidth:at/Ye,targetHeight:lt/Xe,mobile:te})))})}var ku=Ou(Jl);function Au(e){return e&&m.isValidElement(e)&&e.type===m.Fragment}var ju=(e,t,n)=>m.isValidElement(e)?m.cloneElement(e,typeof n==`function`?n(e.props||{}):n):t;function Mu(e,t){return ju(e,e,t)}var Nu=({children:e})=>{let{getPrefixCls:t}=m.useContext(zt),n=t();return m.isValidElement(e)?m.createElement(hc,{visible:!0,motionName:`${n}-fade`,motionAppear:!0,motionEnter:!0,motionLeave:!1,removeOnLeave:!1},({style:t,className:n})=>Mu(e,e=>({className:K(e.className,n),style:{...e.style,...t}}))):e},Pu=[null,null];function Fu(e){if(Pu[0]!==e){let t={};Object.keys(e).forEach(n=>{t[n]={...e[n],dynamicInset:!1}}),Pu[0]=e,Pu[1]=t}return Pu[1]}var Iu=({children:e})=>m.createElement(Du,{postTriggerProps:e=>{let{id:t,builtinPlacements:n,popup:r}=e,i=typeof r==`function`?r():r,a=Fu(n);return{...e,getPopupContainer:null,arrow:!1,popup:m.createElement(Nu,{key:t},i),builtinPlacements:a}}},e),Lu=m.createContext(!1),Ru=({children:e,disabled:t})=>{let n=m.useContext(Lu);return m.createElement(Lu.Provider,{value:t??n},e)},zu=m.createContext(void 0),Bu=({children:e,size:t})=>{let n=m.useContext(zu);return m.createElement(zu.Provider,{value:t||n},e)};function Vu(){return{componentDisabled:(0,m.useContext)(Lu),componentSize:(0,m.useContext)(zu)}}function Hu(e,t,n){ot(`ConfigProvider`);let r=e||{},i=r.inherit===!1||!t?{..._o,hashed:t?.hashed??_o.hashed,cssVar:t?.cssVar}:t,a=(0,m.useId)();return we(()=>{if(!e)return t;let o={...i.components};Object.keys(e.components||{}).forEach(t=>{o[t]={...o[t],...e.components[t]}});let s=`css-var-${a.replace(/:/g,``)}`,c={prefix:n?.prefixCls,...i.cssVar,...r.cssVar,key:r.cssVar?.key||s};return{...i,...r,token:{...i.token,...r.token},components:o,cssVar:c}},[r,i],(e,t)=>e.some((e,n)=>{let r=t[n];return!an(e,r,!0)}))}var Uu=m.createContext(!0);function Wu(e){let t=m.useContext(Uu),{children:n}=e,[,r]=Eo(),{motion:i}=r,a=m.useRef(!1);return a.current||=t!==i,a.current?m.createElement(Uu.Provider,{value:i},m.createElement(Ts,{motion:i},n)):n}var Gu=()=>null,Ku=({iconPrefixCls:e,csp:t})=>(Vo(e,t),null),qu=[`getTargetContainer`,`getPopupContainer`,`renderEmpty`,`input`,`pagination`,`form`,`select`,`button`],Ju=e=>{let{prefixCls:t,iconPrefixCls:n,theme:r,holderRender:i}=e;`holderRender`in e},Yu=e=>{let{children:t,csp:n,autoInsertSpaceInButton:r,alert:i,affix:a,anchor:o,app:s,form:c,locale:l,componentSize:u,direction:d,space:f,splitter:p,virtual:h,dropdownMatchSelectWidth:g,popupMatchSelectWidth:_,popupOverflow:v,legacyLocale:y,parentContext:b,iconPrefixCls:x,theme:S,componentDisabled:C,segmented:w,statistic:T,spin:E,calendar:D,carousel:O,cascader:k,collapse:A,typography:j,checkbox:M,descriptions:N,divider:P,drawer:F,skeleton:I,steps:L,image:ee,layout:R,list:z,mentions:B,modal:V,progress:te,result:ne,slider:re,breadcrumb:ie,masonry:ae,menu:oe,pagination:H,input:se,textArea:ce,otp:le,empty:U,badge:ue,radio:de,rate:fe,ribbon:pe,switch:me,transfer:he,avatar:ge,message:_e,tag:W,table:ve,card:ye,cardMeta:G,tabs:be,timeline:xe,timePicker:Se,upload:Ce,notification:Te,tree:Ee,colorPicker:De,datePicker:Oe,rangePicker:ke,flex:Ae,wave:je,dropdown:Me,warning:Ne,tour:Pe,tooltip:Fe,popover:Ie,popconfirm:Le,qrcode:Re,floatButton:ze,floatButtonGroup:Be,variant:Ve,inputNumber:He,treeSelect:Ue,watermark:We}=e,Ke=m.useCallback((t,n)=>{let{prefixCls:r}=e;if(n)return n;let i=r||b.getPrefixCls(``);return t?`${i}-${t}`:i},[b.getPrefixCls,e.prefixCls]),qe=x||b.iconPrefixCls||`anticon`,Je=n||b.csp,Ye=Hu(S,b.theme,{prefixCls:Ke(``)}),Xe={csp:Je,autoInsertSpaceInButton:r,alert:i,affix:a,anchor:o,app:s,locale:l||y,direction:d,space:f,splitter:p,virtual:h,popupMatchSelectWidth:_??g,popupOverflow:v,getPrefixCls:Ke,iconPrefixCls:qe,theme:Ye,segmented:w,statistic:T,spin:E,calendar:D,carousel:O,cascader:k,collapse:A,typography:j,checkbox:M,descriptions:N,divider:P,drawer:F,skeleton:I,steps:L,image:ee,input:se,textArea:ce,otp:le,layout:R,list:z,mentions:B,modal:V,progress:te,result:ne,slider:re,breadcrumb:ie,masonry:ae,menu:oe,pagination:H,empty:U,badge:ue,radio:de,rate:fe,ribbon:pe,switch:me,transfer:he,avatar:ge,message:_e,tag:W,table:ve,card:ye,cardMeta:G,tabs:be,timeline:xe,timePicker:Se,upload:Ce,notification:Te,tree:Ee,colorPicker:De,datePicker:Oe,rangePicker:ke,flex:Ae,wave:je,dropdown:Me,warning:Ne,tour:Pe,tooltip:Fe,popover:Ie,popconfirm:Le,qrcode:Re,floatButton:ze,floatButtonGroup:Be,variant:Ve,inputNumber:He,treeSelect:Ue,watermark:We},Ze={...b};Object.keys(Xe).forEach(e=>{Xe[e]!==void 0&&(Ze[e]=Xe[e])}),qu.forEach(t=>{let n=e[t];n&&(Ze[t]=n)}),r!==void 0&&(Ze.button={autoInsertSpace:r,...Ze.button});let Qe=we(()=>Ze,Ze,(e,t)=>{let n=Object.keys(e),r=Object.keys(t);return n.length!==r.length||n.some(n=>e[n]!==t[n])}),{layer:$e}=m.useContext(mn),et=m.useMemo(()=>({prefixCls:qe,csp:Je,layer:$e?`antd`:void 0}),[qe,Je,$e]),tt=m.createElement(m.Fragment,null,m.createElement(Ku,{iconPrefixCls:qe,csp:Je}),m.createElement(Gu,{dropdownMatchSelectWidth:g}),t),nt=m.useMemo(()=>Ge(Pc.Form?.defaultValidateMessages||{},Qe.locale?.Form?.defaultValidateMessages||{},Qe.form?.validateMessages||{},c?.validateMessages||{}),[Qe,c?.validateMessages]);Object.keys(nt).length>0&&(tt=m.createElement(bl.Provider,{value:nt},tt)),l&&(tt=m.createElement(Uc,{locale:l,_ANT_MARK__:Hc},tt)),(qe||Je)&&(tt=m.createElement(Uo.Provider,{value:et},tt)),u&&(tt=m.createElement(Bu,{size:u},tt)),tt=m.createElement(Wu,null,tt),Fe?.unique&&(tt=m.createElement(Iu,null,tt));let rt=m.useMemo(()=>{let{algorithm:e,token:t,components:n,cssVar:r,...i}=Ye||{},a=e&&(!Array.isArray(e)||e.length>0)?bn(e):go,o={};Object.entries(n||{}).forEach(([e,t])=>{let n={...t};`algorithm`in n&&(n.algorithm===!0?n.theme=a:(Array.isArray(n.algorithm)||typeof n.algorithm==`function`)&&(n.theme=bn(n.algorithm)),delete n.algorithm),o[e]=n});let s={...da,...t};return{...i,theme:a,token:s,components:o,override:{override:s,...o},cssVar:r}},[Ye]);return S&&(tt=m.createElement(vo.Provider,{value:rt},tt)),Qe.warning&&(tt=m.createElement(at.Provider,{value:Qe.warning},tt)),C!==void 0&&(tt=m.createElement(Ru,{disabled:C},tt)),m.createElement(zt.Provider,{value:Qe},tt)},Xu=e=>{let t=m.useContext(zt),n=m.useContext(Bc);return m.createElement(Yu,{parentContext:t,legacyLocale:n,...e})};Xu.ConfigContext=zt,Xu.SizeContext=zu,Xu.config=Ju,Xu.useConfig=Vu,Object.defineProperty(Xu,`SizeContext`,{get:()=>zu});var J={MAC_ENTER:3,BACKSPACE:8,TAB:9,NUM_CENTER:12,ENTER:13,SHIFT:16,CTRL:17,ALT:18,PAUSE:19,CAPS_LOCK:20,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,PRINT_SCREEN:44,INSERT:45,DELETE:46,ZERO:48,ONE:49,TWO:50,THREE:51,FOUR:52,FIVE:53,SIX:54,SEVEN:55,EIGHT:56,NINE:57,QUESTION_MARK:63,A:65,B:66,C:67,D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90,META:91,WIN_KEY_RIGHT:92,CONTEXT_MENU:93,NUM_ZERO:96,NUM_ONE:97,NUM_TWO:98,NUM_THREE:99,NUM_FOUR:100,NUM_FIVE:101,NUM_SIX:102,NUM_SEVEN:103,NUM_EIGHT:104,NUM_NINE:105,NUM_MULTIPLY:106,NUM_PLUS:107,NUM_MINUS:109,NUM_PERIOD:110,NUM_DIVISION:111,F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120,F10:121,F11:122,F12:123,NUMLOCK:144,SEMICOLON:186,DASH:189,EQUALS:187,COMMA:188,PERIOD:190,SLASH:191,APOSTROPHE:192,SINGLE_QUOTE:222,OPEN_SQUARE_BRACKET:219,BACKSLASH:220,CLOSE_SQUARE_BRACKET:221,WIN_KEY:224,MAC_FF_META:224,WIN_IME:229,isTextModifyingKeyEvent:function(e){let{keyCode:t}=e;if(e.altKey&&!e.ctrlKey||e.metaKey||t>=J.F1&&t<=J.F12)return!1;switch(t){case J.ALT:case J.CAPS_LOCK:case J.CONTEXT_MENU:case J.CTRL:case J.DOWN:case J.END:case J.ESC:case J.HOME:case J.INSERT:case J.LEFT:case J.MAC_FF_META:case J.META:case J.NUMLOCK:case J.NUM_CENTER:case J.PAGE_DOWN:case J.PAGE_UP:case J.PAUSE:case J.PRINT_SCREEN:case J.RIGHT:case J.SHIFT:case J.UP:case J.WIN_KEY:case J.WIN_KEY_RIGHT:return!1;default:return!0}},isCharacterKey:function(e){if(e>=J.ZERO&&e<=J.NINE||e>=J.NUM_ZERO&&e<=J.NUM_MULTIPLY||e>=J.A&&e<=J.Z||window.navigator.userAgent.indexOf(`WebKit`)!==-1&&e===0)return!0;switch(e){case J.SPACE:case J.QUESTION_MARK:case J.NUM_PLUS:case J.NUM_MINUS:case J.NUM_PERIOD:case J.NUM_DIVISION:case J.SEMICOLON:case J.DASH:case J.EQUALS:case J.COMMA:case J.PERIOD:case J.SLASH:case J.APOSTROPHE:case J.SINGLE_QUOTE:case J.OPEN_SQUARE_BRACKET:case J.BACKSLASH:case J.CLOSE_SQUARE_BRACKET:return!0;default:return!1}},isEditableTarget:function(e){let t=e.target;if(!(t instanceof HTMLElement))return!1;let n=t.tagName;return!!(n===`INPUT`||n===`TEXTAREA`||n===`SELECT`||t.isContentEditable)}};function Zu(){return Zu=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{prefixCls:n,style:r,className:i,duration:a=4.5,showProgress:o,pauseOnHover:s=!0,eventKey:c,content:l,closable:u,props:d,onClick:f,onNoticeClose:p,times:h,hovering:g}=e,[_,v]=m.useState(!1),[y,b]=m.useState(0),[x,S]=m.useState(0),C=g||_,w=typeof a==`number`?a:0,T=w>0&&o,E=()=>{p(c)},D=e=>{(e.key===`Enter`||e.code===`Enter`||e.keyCode===J.ENTER)&&E()};m.useEffect(()=>{if(!C&&w>0){let e=Date.now()-x,t=setTimeout(()=>{E()},w*1e3-x);return()=>{s&&clearTimeout(t),S(Date.now()-e)}}},[w,C,h]),m.useEffect(()=>{if(!C&&T&&(s||x===0)){let e=performance.now(),t,n=()=>{cancelAnimationFrame(t),t=requestAnimationFrame(t=>{let r=t+x-e,i=Math.min(r/(w*1e3),1);b(i*100),i<1&&n()})};return n(),()=>{s&&cancelAnimationFrame(t)}}},[w,x,C,T,h]);let O=m.useMemo(()=>typeof u==`object`&&u?u:{},[u]),k=bc(O,!0),A=100-(!y||y<0?0:y>100?100:y),j=`${n}-notice`;return m.createElement(`div`,Zu({},d,{ref:t,className:K(j,i,{[`${j}-closable`]:u}),style:r,onMouseEnter:e=>{v(!0),d?.onMouseEnter?.(e)},onMouseLeave:e=>{v(!1),d?.onMouseLeave?.(e)},onClick:f}),m.createElement(`div`,{className:`${j}-content`},l),u&&m.createElement(`button`,Zu({className:`${j}-close`,onKeyDown:D,"aria-label":`Close`},k,{onClick:e=>{e.preventDefault(),e.stopPropagation(),E()}}),O.closeIcon??`x`),T&&m.createElement(`progress`,{className:`${j}-progress`,max:`100`,value:A},A+`%`))}),$u=m.createContext({}),ed=({children:e,classNames:t})=>m.createElement($u.Provider,{value:{classNames:t}},e),td=8,nd=3,rd=16,id=e=>{let t={offset:td,threshold:nd,gap:rd};return e&&typeof e==`object`&&(t.offset=e.offset??td,t.threshold=e.threshold??nd,t.gap=e.gap??rd),[!!e,t]};function ad(){return ad=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{configList:t,placement:n,prefixCls:r,className:i,style:a,motion:o,onAllNoticeRemoved:s,onNoticeClose:c,stack:l}=e,{classNames:u}=(0,m.useContext)($u),d=(0,m.useRef)({}),[f,p]=(0,m.useState)(null),[h,g]=(0,m.useState)([]),_=t.map(e=>({config:e,key:String(e.key)})),[v,{offset:y,threshold:b,gap:x}]=id(l),S=v&&(h.length>0||_.length<=b),C=typeof o==`function`?o(n):o;return(0,m.useEffect)(()=>{v&&h.length>1&&g(e=>e.filter(e=>_.some(({key:t})=>e===t)))},[h,_,v]),(0,m.useEffect)(()=>{v&&d.current[_[_.length-1]?.key]&&p(d.current[_[_.length-1]?.key])},[_,v]),m.createElement(mc,ad({key:n,className:K(r,`${r}-${n}`,u?.list,i,{[`${r}-stack`]:!!v,[`${r}-stack-expanded`]:S}),style:a,keys:_,motionAppear:!0},C,{onAllRemoved:()=>{s(n)}}),({config:e,className:t,style:i,index:a},o)=>{let{key:s,times:l}=e,p=String(s),{className:b,style:C,classNames:w,styles:T,...E}=e,D=_.findIndex(e=>e.key===p),O={};if(v){let e=_.length-1-(D>-1?D:a-1),t=n===`top`||n===`bottom`?`-50%`:`0`;if(e>0){O.height=S?d.current[p]?.offsetHeight:f?.offsetHeight;let r=0;for(let t=0;tg(e=>e.includes(p)?e:[...e,p]),onMouseLeave:()=>g(e=>e.filter(e=>e!==p))},m.createElement(Qu,ad({},E,{ref:e=>{D>-1?d.current[p]=e:delete d.current[p]},prefixCls:r,classNames:w,styles:T,className:K(b,u?.notice),style:C,times:l,key:s,eventKey:s,onNoticeClose:c,hovering:v&&h.length>0})))})},sd=m.forwardRef((e,t)=>{let{prefixCls:n=`rc-notification`,container:r,motion:i,maxCount:a,className:o,style:s,onAllRemoved:c,stack:l,renderNotifications:u}=e,[d,f]=m.useState([]),p=e=>{let t=d.find(t=>t.key===e),n=t?.closable,{onClose:r}=n&&typeof n==`object`?n:{};r?.(),t?.onClose?.(),f(t=>t.filter(t=>t.key!==e))};m.useImperativeHandle(t,()=>({open:e=>{f(t=>{let n=[...t],r=n.findIndex(t=>t.key===e.key),i={...e};return r>=0?(i.times=(t[r]?.times||0)+1,n[r]=i):(i.times=0,n.push(i)),a>0&&n.length>a&&(n=n.slice(-a)),n})},close:e=>{p(e)},destroy:()=>{f([])}}));let[h,g]=m.useState({});m.useEffect(()=>{let e={};d.forEach(t=>{let{placement:n=`topRight`}=t;n&&(e[n]=e[n]||[],e[n].push(t))}),Object.keys(h).forEach(t=>{e[t]=e[t]||[]}),g(e)},[d]);let _=e=>{g(t=>{let n={...t};return(n[e]||[]).length||delete n[e],n})},v=m.useRef(!1);if(m.useEffect(()=>{Object.keys(h).length>0?v.current=!0:v.current&&=(c?.(),!1)},[h]),!r)return null;let y=Object.keys(h);return(0,Kl.createPortal)(m.createElement(m.Fragment,null,y.map(e=>{let t=h[e],r=m.createElement(od,{key:e,configList:t,placement:e,prefixCls:n,className:o?.(e),style:s?.(e),motion:i,onNoticeClose:p,onAllNoticeRemoved:_,stack:l});return u?u(r,{prefixCls:n,key:e}):r})),r)}),cd=()=>document.body,ld=0;function ud(...e){let t={};return e.forEach(e=>{e&&Object.keys(e).forEach(n=>{let r=e[n];r!==void 0&&(t[n]=r)})}),t}function dd(e={}){let{getContainer:t=cd,motion:n,prefixCls:r,maxCount:i,className:a,style:o,onAllRemoved:s,stack:c,renderNotifications:l,...u}=e,[d,f]=m.useState(),p=m.useRef(),h=m.createElement(sd,{container:d,ref:p,prefixCls:r,motion:n,maxCount:i,className:a,style:o,onAllRemoved:s,stack:c,renderNotifications:l}),[g,_]=m.useState([]),v=W(e=>{let t=ud(u,e);(t.key===null||t.key===void 0)&&(t.key=`rc-notification-${ld}`,ld+=1),_(e=>[...e,{type:`open`,config:t}])}),y=m.useMemo(()=>({open:v,close:e=>{_(t=>[...t,{type:`close`,key:e}])},destroy:()=>{_(e=>[...e,{type:`destroy`}])}}),[]);return m.useEffect(()=>{f(t())}),m.useEffect(()=>{if(p.current&&g.length){g.forEach(e=>{switch(e.type){case`open`:p.current.open(e.config);break;case`close`:p.current.close(e.key);break;case`destroy`:p.current.destroy();break}});let e,t;_(n=>((e!==n||!t)&&(e=n,t=n.filter(e=>!g.includes(e))),t))}},[g]),[y,h]}var fd={icon:{tag:`svg`,attrs:{viewBox:`0 0 1024 1024`,focusable:`false`},children:[{tag:`path`,attrs:{d:`M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 00-94.3-139.9 437.71 437.71 0 00-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z`}}]},name:`loading`,theme:`outlined`};function pd(){return pd=Object.assign?Object.assign.bind():function(e){for(var t=1;tm.createElement(ls,pd({},e,{ref:t,icon:fd}))),hd=e=>{let{componentCls:t,iconCls:n,boxShadow:r,colorText:i,colorSuccess:a,colorError:o,colorWarning:s,colorInfo:c,fontSizeLG:l,motionEaseInOutCirc:u,motionDurationSlow:d,marginXS:f,paddingXS:p,borderRadiusLG:m,zIndexPopup:h,contentPadding:g,contentBg:_}=e,v=`${t}-notice`,y=new gi(`MessageMoveIn`,{"0%":{padding:0,transform:`translateY(-100%)`,opacity:0},"100%":{padding:p,transform:`translateY(0)`,opacity:1}}),b=new gi(`MessageMoveOut`,{"0%":{maxHeight:e.height,padding:p,opacity:1},"100%":{maxHeight:0,padding:0,opacity:0}}),x={padding:p,textAlign:`center`,[`${t}-custom-content`]:{display:`flex`,alignItems:`center`},[`${t}-custom-content > ${n}`]:{marginInlineEnd:f,fontSize:l},[`${v}-content`]:{display:`inline-block`,padding:g,background:_,borderRadius:m,boxShadow:r,pointerEvents:`all`},[`${t}-success > ${n}`]:{color:a},[`${t}-error > ${n}`]:{color:o},[`${t}-warning > ${n}`]:{color:s},[`${t}-info > ${n}, - ${t}-loading > ${n}`]:{color:c}};return[{[t]:{...Do(e),color:i,position:`fixed`,top:f,width:`100%`,pointerEvents:`none`,zIndex:h,[`${t}-move-up`]:{animationFillMode:`forwards`},[` - ${t}-move-up-appear, - ${t}-move-up-enter - `]:{animationName:y,animationDuration:d,animationPlayState:`paused`,animationTimingFunction:u},[` - ${t}-move-up-appear${t}-move-up-appear-active, - ${t}-move-up-enter${t}-move-up-enter-active - `]:{animationPlayState:`running`},[`${t}-move-up-leave`]:{animationName:b,animationDuration:d,animationPlayState:`paused`,animationTimingFunction:u},[`${t}-move-up-leave${t}-move-up-leave-active`]:{animationPlayState:`running`},"&-rtl":{direction:`rtl`,span:{direction:`rtl`}}}},{[t]:{[`${v}-wrapper`]:{...x}}},{[`${t}-notice-pure-panel`]:{...x,padding:0,textAlign:`start`}}]},gd=Io(`Message`,e=>hd(Yi(e,{height:150})),e=>({zIndexPopup:e.zIndexPopupBase+ml+10,contentBg:e.colorBgElevated,contentPadding:`${(e.controlHeightLG-e.fontSize*e.lineHeight)/2}px ${e.paddingSM}px`})),_d={info:m.createElement(Cs,null),success:m.createElement(ds,null),error:m.createElement(ms,null),warning:m.createElement(bs,null),loading:m.createElement(md,null)},vd=e=>{let{prefixCls:t,type:n,icon:r,children:i,classNames:a,styles:o}=e,s=Mu(r||n&&_d[n],e=>{let t={...e?.style,...o?.icon};return{className:K(e.className,a?.icon),style:t}});return m.createElement(`div`,{className:K(`${t}-custom-content`,`${t}-${n}`)},s,m.createElement(`span`,{className:a?.content,style:o?.content},i))};function yd(e,t){return{motionName:t??`${e}-move-up`}}function bd(e){let t,n=new Promise(n=>{t=e(()=>{n(!0)})}),r=()=>{t?.()};return r.then=(e,t)=>n.then(e,t),r.promise=n,r}var xd=8,Sd=3,Cd=({children:e,prefixCls:t})=>{let n=yl(t),[r,i]=gd(t,n);return m.createElement(ed,{classNames:{list:K(r,i,n)}},e)},wd=(e,{prefixCls:t,key:n})=>m.createElement(Cd,{prefixCls:t,key:n},e),Td=m.forwardRef((e,t)=>{let{top:n,prefixCls:r,getContainer:i,maxCount:a,duration:o=Sd,rtl:s,transitionName:c,onAllRemoved:l,pauseOnHover:u=!0}=e,{getPrefixCls:d,direction:f,getPopupContainer:p}=Ht(`message`),{message:h}=m.useContext(zt),g=r||d(`message`),_=()=>({left:`50%`,transform:`translateX(-50%)`,top:n??xd}),v=()=>K({[`${g}-rtl`]:s??f===`rtl`}),y=()=>yd(g,c),[b,x]=cl([e?.classNames,h?.classNames],[e?.styles,h?.styles],{props:e}),[S,C]=dd({prefixCls:g,style:_,className:v,motion:y,closable:!1,duration:o,getContainer:()=>i?.()||p?.()||document.body,maxCount:a,onAllRemoved:l,renderNotifications:wd,pauseOnHover:u});return m.useImperativeHandle(t,()=>({...S,prefixCls:g,message:h,classNames:b,styles:x})),C}),Ed=0;function Dd(e){let t=m.useRef(null);return ot(`Message`),[m.useMemo(()=>{let n=e=>{t.current?.close(e)},r=r=>{if(!t.current){let e=()=>{};return e.then=()=>{},e}let{open:i,prefixCls:a,message:o,classNames:s,styles:c}=t.current,l=o?.className||{},u=o?.style||{},d=o?.classNames||{},f=o?.styles||{},p=`${a}-notice`,{content:h,icon:g,type:_,key:v,className:y,style:b,onClose:x,classNames:S={},styles:C={},...w}=r,T=v;Gc(T)||(Ed+=1,T=`antd-message-${Ed}`);let E={...e,...r},D=sl(d,{props:E}),O=sl(S,{props:E}),k=sl(f,{props:E}),A=sl(C,{props:E}),j=nl(void 0,D,O,s),M=il(k,A,c);return bd(e=>(i({...w,key:T,content:m.createElement(vd,{prefixCls:a,type:_,icon:g,classNames:j,styles:M},h),placement:`top`,className:K({[`${p}-${_}`]:_},y,l,j.root),style:{...M.root,...u,...b},onClose:()=>{x?.(),e()}}),()=>{n(T)}))},i={open:r,destroy:e=>{e===void 0?t.current?.destroy():n(e)}};return[`info`,`success`,`warning`,`error`,`loading`].forEach(e=>{i[e]=(t,n,i)=>{let a;a=t&&typeof t==`object`&&`content`in t?t:{content:t};let o,s;return typeof n==`function`?s=n:(o=n,s=i),r({onClose:s,duration:o,...a,type:e})}}),i},[]),m.createElement(Td,{key:`message-holder`,...e,ref:t})]}function Od(e){return Dd(e)}var kd=s((e=>{function t(e,t){var n=e.length;e.push(t);a:for(;0>>1,a=e[r];if(0>>1;ri(c,n))li(u,c)?(e[r]=u,e[l]=n,r=l):(e[r]=c,e[s]=n,r=s);else if(li(u,n))e[r]=u,e[l]=n,r=l;else break a}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return n===0?e.id-t.id:n}if(e.unstable_now=void 0,typeof performance==`object`&&typeof performance.now==`function`){var a=performance;e.unstable_now=function(){return a.now()}}else{var o=Date,s=o.now();e.unstable_now=function(){return o.now()-s}}var c=[],l=[],u=1,d=null,f=3,p=!1,m=!1,h=!1,g=!1,_=typeof setTimeout==`function`?setTimeout:null,v=typeof clearTimeout==`function`?clearTimeout:null,y=typeof setImmediate<`u`?setImmediate:null;function b(e){for(var i=n(l);i!==null;){if(i.callback===null)r(l);else if(i.startTime<=e)r(l),i.sortIndex=i.expirationTime,t(c,i);else break;i=n(l)}}function x(e){if(h=!1,b(e),!m)if(n(c)!==null)m=!0,S||(S=!0,O());else{var t=n(l);t!==null&&j(x,t.startTime-e)}}var S=!1,C=-1,w=5,T=-1;function E(){return g?!0:!(e.unstable_now()-Tt&&E());){var o=d.callback;if(typeof o==`function`){d.callback=null,f=d.priorityLevel;var s=o(d.expirationTime<=t);if(t=e.unstable_now(),typeof s==`function`){d.callback=s,b(t),i=!0;break b}d===n(c)&&r(c),b(t)}else r(c);d=n(c)}if(d!==null)i=!0;else{var u=n(l);u!==null&&j(x,u.startTime-t),i=!1}}break a}finally{d=null,f=a,p=!1}i=void 0}}finally{i?O():S=!1}}}var O;if(typeof y==`function`)O=function(){y(D)};else if(typeof MessageChannel<`u`){var k=new MessageChannel,A=k.port2;k.port1.onmessage=D,O=function(){A.postMessage(null)}}else O=function(){_(D,0)};function j(t,n){C=_(function(){t(e.unstable_now())},n)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(e){e.callback=null},e.unstable_forceFrameRate=function(e){0>e||125o?(r.sortIndex=a,t(l,r),n(c)===null&&r===n(l)&&(h?(v(C),C=-1):h=!0,j(x,a-o))):(r.sortIndex=s,t(c,r),m||p||(m=!0,S||(S=!0,O()))),r},e.unstable_shouldYield=E,e.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}})),Ad=s(((e,t)=>{t.exports=kd()})),jd=s((e=>{var t=Ad(),n=p(),r=Sl();function i(e){var t=`https://react.dev/errors/`+e;if(1ee||(e.current=L[ee],L[ee]=null,ee--)}function B(e,t){ee++,L[ee]=e.current,e.current=t}var V=R(null),te=R(null),ne=R(null),re=R(null);function ie(e,t){switch(B(ne,t),B(te,e),B(V,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Kd(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Kd(t),e=qd(t,e);else switch(e){case`svg`:e=1;break;case`math`:e=2;break;default:e=0}}z(V),B(V,e)}function ae(){z(V),z(te),z(ne)}function oe(e){e.memoizedState!==null&&B(re,e);var t=V.current,n=qd(t,e.type);t!==n&&(B(te,e),B(V,n))}function H(e){te.current===e&&(z(V),z(te)),re.current===e&&(z(re),rp._currentValue=I)}var se,ce;function le(e){if(se===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);se=t&&t[1]||``,ce=-1)`:-1i||c[r]!==l[i]){var u=` -`+c[r].replace(` at new `,` at `);return e.displayName&&u.includes(``)&&(u=u.replace(``,e.displayName)),u}while(1<=r&&0<=i);break}}}finally{U=!1,Error.prepareStackTrace=n}return(n=e?e.displayName||e.name:``)?le(n):``}function de(e,t){switch(e.tag){case 26:case 27:case 5:return le(e.type);case 16:return le(`Lazy`);case 13:return e.child!==t&&t!==null?le(`Suspense Fallback`):le(`Suspense`);case 19:return le(`SuspenseList`);case 0:case 15:return ue(e.type,!1);case 11:return ue(e.type.render,!1);case 1:return ue(e.type,!0);case 31:return le(`Activity`);default:return``}}function fe(e){try{var t=``,n=null;do t+=de(e,n),n=e,e=e.return;while(e);return t}catch(e){return` -Error generating stack: `+e.message+` -`+e.stack}}var pe=Object.prototype.hasOwnProperty,me=t.unstable_scheduleCallback,he=t.unstable_cancelCallback,ge=t.unstable_shouldYield,_e=t.unstable_requestPaint,W=t.unstable_now,ve=t.unstable_getCurrentPriorityLevel,ye=t.unstable_ImmediatePriority,G=t.unstable_UserBlockingPriority,be=t.unstable_NormalPriority,xe=t.unstable_LowPriority,Se=t.unstable_IdlePriority,Ce=t.log,we=t.unstable_setDisableYieldValue,Te=null,Ee=null;function De(e){if(typeof Ce==`function`&&we(e),Ee&&typeof Ee.setStrictMode==`function`)try{Ee.setStrictMode(Te,e)}catch{}}var Oe=Math.clz32?Math.clz32:je,ke=Math.log,Ae=Math.LN2;function je(e){return e>>>=0,e===0?32:31-(ke(e)/Ae|0)|0}var Me=256,Ne=262144,Pe=4194304;function Fe(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function Ie(e,t,n){var r=e.pendingLanes;if(r===0)return 0;var i=0,a=e.suspendedLanes,o=e.pingedLanes;e=e.warmLanes;var s=r&134217727;return s===0?(s=r&~a,s===0?o===0?n||(n=r&~e,n!==0&&(i=Fe(n))):i=Fe(o):i=Fe(s)):(r=s&~a,r===0?(o&=s,o===0?n||(n=s&~e,n!==0&&(i=Fe(n))):i=Fe(o)):i=Fe(r)),i===0?0:t!==0&&t!==i&&(t&a)===0&&(a=i&-i,n=t&-t,a>=n||a===32&&n&4194048)?t:i}function Le(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function Re(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function ze(){var e=Pe;return Pe<<=1,!(Pe&62914560)&&(Pe=4194304),e}function Be(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function Ve(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function He(e,t,n,r,i,a){var o=e.pendingLanes;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=n,e.entangledLanes&=n,e.errorRecoveryDisabledLanes&=n,e.shellSuspendCounter=0;var s=e.entanglements,c=e.expirationTimes,l=e.hiddenUpdates;for(n=o&~n;0`u`||window.document===void 0||window.document.createElement===void 0),$t=!1;if(Qt)try{var en={};Object.defineProperty(en,`passive`,{get:function(){$t=!0}}),window.addEventListener(`test`,en,en),window.removeEventListener(`test`,en,en)}catch{$t=!1}var tn=null,nn=null,rn=null;function an(){if(rn)return rn;var e,t=nn,n=t.length,r,i=`value`in tn?tn.value:tn.textContent,a=i.length;for(e=0;e=In),zn=` `,Bn=!1;function Vn(e,t){switch(e){case`keyup`:return Pn.indexOf(t.keyCode)!==-1;case`keydown`:return t.keyCode!==229;case`keypress`:case`mousedown`:case`focusout`:return!0;default:return!1}}function Hn(e){return e=e.detail,typeof e==`object`&&`data`in e?e.data:null}var Un=!1;function Wn(e,t){switch(e){case`compositionend`:return Hn(t);case`keypress`:return t.which===32?(Bn=!0,zn):null;case`textInput`:return e=t.data,e===zn&&Bn?null:e;default:return null}}function Gn(e,t){if(Un)return e===`compositionend`||!Fn&&Vn(e,t)?(e=an(),rn=nn=tn=null,Un=!1,e):null;switch(e){case`paste`:return null;case`keypress`:if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}a:{for(;n;){if(n.nextSibling){n=n.nextSibling;break a}n=n.parentNode}n=void 0}n=pr(n)}}function hr(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?hr(e,t.parentNode):`contains`in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function gr(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=Et(e.document);t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href==`string`}catch{n=!1}if(n)e=t.contentWindow;else break;t=Et(e.document)}return t}function _r(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t===`input`&&(e.type===`text`||e.type===`search`||e.type===`tel`||e.type===`url`||e.type===`password`)||t===`textarea`||e.contentEditable===`true`)}var vr=Qt&&`documentMode`in document&&11>=document.documentMode,yr=null,br=null,xr=null,Sr=!1;function Cr(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;Sr||yr==null||yr!==Et(r)||(r=yr,`selectionStart`in r&&_r(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),xr&&fr(xr,r)||(xr=r,r=kd(br,`onSelect`),0>=o,i-=o,hi=1<<32-Oe(t)+i|n<h?(g=d,d=null):g=d.sibling;var _=p(i,d,s[h],c);if(_===null){d===null&&(d=g);break}e&&d&&_.alternate===null&&t(i,d),a=o(_,a,h),u===null?l=_:u.sibling=_,u=_,d=g}if(h===s.length)return n(i,d),wi&&_i(i,h),l;if(d===null){for(;hg?(_=h,h=null):_=h.sibling;var y=p(a,h,v.value,l);if(y===null){h===null&&(h=_);break}e&&h&&y.alternate===null&&t(a,h),s=o(y,s,g),d===null?u=y:d.sibling=y,d=y,h=_}if(v.done)return n(a,h),wi&&_i(a,g),u;if(h===null){for(;!v.done;g++,v=c.next())v=f(a,v.value,l),v!==null&&(s=o(v,s,g),d===null?u=v:d.sibling=v,d=v);return wi&&_i(a,g),u}for(h=r(h);!v.done;g++,v=c.next())v=m(h,a,g,v.value,l),v!==null&&(e&&v.alternate!==null&&h.delete(v.key===null?g:v.key),s=o(v,s,g),d===null?u=v:d.sibling=v,d=v);return e&&h.forEach(function(e){return t(a,e)}),wi&&_i(a,g),u}function b(e,r,o,c){if(typeof o==`object`&&o&&o.type===_&&o.key===null&&(o=o.props.children),typeof o==`object`&&o){switch(o.$$typeof){case h:a:{for(var l=o.key;r!==null;){if(r.key===l){if(l=o.type,l===_){if(r.tag===7){n(e,r.sibling),c=a(r,o.props.children),c.return=e,e=c;break a}}else if(r.elementType===l||typeof l==`object`&&l&&l.$$typeof===E&&va(l)===r.type){n(e,r.sibling),c=a(r,o.props),Ta(c,o),c.return=e,e=c;break a}n(e,r);break}else t(e,r);r=r.sibling}o.type===_?(c=ni(o.props.children,e.mode,c,o.key),c.return=e,e=c):(c=ti(o.type,o.key,o.props,null,e.mode,c),Ta(c,o),c.return=e,e=c)}return s(e);case g:a:{for(l=o.key;r!==null;){if(r.key===l)if(r.tag===4&&r.stateNode.containerInfo===o.containerInfo&&r.stateNode.implementation===o.implementation){n(e,r.sibling),c=a(r,o.children||[]),c.return=e,e=c;break a}else{n(e,r);break}else t(e,r);r=r.sibling}c=ai(o,e.mode,c),c.return=e,e=c}return s(e);case E:return o=va(o),b(e,r,o,c)}if(N(o))return v(e,r,o,c);if(A(o)){if(l=A(o),typeof l!=`function`)throw Error(i(150));return o=l.call(o),y(e,r,o,c)}if(typeof o.then==`function`)return b(e,r,wa(o),c);if(o.$$typeof===x)return b(e,r,Ki(e,o),c);Ea(e,o)}return typeof o==`string`&&o!==``||typeof o==`number`||typeof o==`bigint`?(o=``+o,r!==null&&r.tag===6?(n(e,r.sibling),c=a(r,o),c.return=e,e=c):(n(e,r),c=ri(o,e.mode,c),c.return=e,e=c),s(e)):n(e,r)}return function(e,t,n,r){try{Ca=0;var i=b(e,t,n,r);return Sa=null,i}catch(t){if(t===fa||t===ma)throw t;var a=Zr(29,t,null,e.mode);return a.lanes=r,a.return=e,a}}}var Oa=Da(!0),ka=Da(!1),Aa=!1;function ja(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Ma(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function Na(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function Pa(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,Il&2){var i=r.pending;return i===null?t.next=t:(t.next=i.next,i.next=t),r.pending=t,t=Jr(e),qr(e,null,n),t}return Wr(e,r,t,n),Jr(e)}function Fa(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,n&4194048)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,We(e,n)}}function Ia(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var i=null,a=null;if(n=n.firstBaseUpdate,n!==null){do{var o={lane:n.lane,tag:n.tag,payload:n.payload,callback:null,next:null};a===null?i=a=o:a=a.next=o,n=n.next}while(n!==null);a===null?i=a=t:a=a.next=t}else i=a=t;n={baseState:r.baseState,firstBaseUpdate:i,lastBaseUpdate:a,shared:r.shared,callbacks:r.callbacks},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}var La=!1;function Ra(){if(La){var e=ra;if(e!==null)throw e}}function za(e,t,n,r){La=!1;var i=e.updateQueue;Aa=!1;var a=i.firstBaseUpdate,o=i.lastBaseUpdate,s=i.shared.pending;if(s!==null){i.shared.pending=null;var c=s,l=c.next;c.next=null,o===null?a=l:o.next=l,o=c;var u=e.alternate;u!==null&&(u=u.updateQueue,s=u.lastBaseUpdate,s!==o&&(s===null?u.firstBaseUpdate=l:s.next=l,u.lastBaseUpdate=c))}if(a!==null){var d=i.baseState;o=0,u=l=c=null,s=a;do{var p=s.lane&-536870913,m=p!==s.lane;if(m?(zl&p)===p:(r&p)===p){p!==0&&p===na&&(La=!0),u!==null&&(u=u.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});a:{var h=e,g=s;p=t;var _=n;switch(g.tag){case 1:if(h=g.payload,typeof h==`function`){d=h.call(_,d,p);break a}d=h;break a;case 3:h.flags=h.flags&-65537|128;case 0:if(h=g.payload,p=typeof h==`function`?h.call(_,d,p):h,p==null)break a;d=f({},d,p);break a;case 2:Aa=!0}}p=s.callback,p!==null&&(e.flags|=64,m&&(e.flags|=8192),m=i.callbacks,m===null?i.callbacks=[p]:m.push(p))}else m={lane:p,tag:s.tag,payload:s.payload,callback:s.callback,next:null},u===null?(l=u=m,c=d):u=u.next=m,o|=p;if(s=s.next,s===null){if(s=i.shared.pending,s===null)break;m=s,s=m.next,m.next=null,i.lastBaseUpdate=m,i.shared.pending=null}}while(1);u===null&&(c=d),i.baseState=c,i.firstBaseUpdate=l,i.lastBaseUpdate=u,a===null&&(i.shared.lanes=0),ql|=o,e.lanes=o,e.memoizedState=d}}function Ba(e,t){if(typeof e!=`function`)throw Error(i(191,e));e.call(t)}function Va(e,t){var n=e.callbacks;if(n!==null)for(e.callbacks=null,e=0;ea?a:8;var o=P.T,s={};P.T=s,Os(e,!1,t,n);try{var c=i(),l=P.S;l!==null&&l(s,c),typeof c==`object`&&c&&typeof c.then==`function`?Ds(e,t,oa(c,r),hu(e)):Ds(e,t,r,hu(e))}catch(n){Ds(e,t,{then:function(){},status:`rejected`,reason:n},hu())}finally{F.p=a,o!==null&&s.types!==null&&(o.types=s.types),P.T=o}}function _s(){}function vs(e,t,n,r){if(e.tag!==5)throw Error(i(476));var a=ys(e).queue;gs(e,a,t,I,n===null?_s:function(){return bs(e),n(r)})}function ys(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:I,baseState:I,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ko,lastRenderedState:I},next:null};var n={};return t.next={memoizedState:n,baseState:n,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ko,lastRenderedState:n},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function bs(e){var t=ys(e);t.next===null&&(t=e.alternate.memoizedState),Ds(e,t.next.queue,{},hu())}function xs(){return Gi(rp)}function Ss(){return wo().memoizedState}function Cs(){return wo().memoizedState}function ws(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var n=hu();e=Na(n);var r=Pa(t,e,n);r!==null&&(_u(r,t,n),Fa(r,t,n)),t={cache:Qi()},e.payload=t;return}t=t.return}}function Ts(e,t,n){var r=hu();n={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null},ks(e)?As(t,n):(n=Gr(e,t,n,r),n!==null&&(_u(n,e,r),js(n,t,r)))}function Es(e,t,n){Ds(e,t,n,hu())}function Ds(e,t,n,r){var i={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null};if(ks(e))As(t,i);else{var a=e.alternate;if(e.lanes===0&&(a===null||a.lanes===0)&&(a=t.lastRenderedReducer,a!==null))try{var o=t.lastRenderedState,s=a(o,n);if(i.hasEagerState=!0,i.eagerState=s,dr(s,o))return Wr(e,t,i,0),Ll===null&&Ur(),!1}catch{}if(n=Gr(e,t,i,r),n!==null)return _u(n,e,r),js(n,t,r),!0}return!1}function Os(e,t,n,r){if(r={lane:2,revertLane:pd(),gesture:null,action:r,hasEagerState:!1,eagerState:null,next:null},ks(e)){if(t)throw Error(i(479))}else t=Gr(e,n,r,2),t!==null&&_u(t,e,2)}function ks(e){var t=e.alternate;return e===ro||t!==null&&t===ro}function As(e,t){so=oo=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function js(e,t,n){if(n&4194048){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,We(e,n)}}var Ms={readContext:Gi,use:Do,useCallback:mo,useContext:mo,useEffect:mo,useImperativeHandle:mo,useLayoutEffect:mo,useInsertionEffect:mo,useMemo:mo,useReducer:mo,useRef:mo,useState:mo,useDebugValue:mo,useDeferredValue:mo,useTransition:mo,useSyncExternalStore:mo,useId:mo,useHostTransitionStatus:mo,useFormState:mo,useActionState:mo,useOptimistic:mo,useMemoCache:mo,useCacheRefresh:mo};Ms.useEffectEvent=mo;var Ns={readContext:Gi,use:Do,useCallback:function(e,t){return Co().memoizedState=[e,t===void 0?null:t],e},useContext:Gi,useEffect:rs,useImperativeHandle:function(e,t,n){n=n==null?null:n.concat([e]),ts(4194308,4,ls.bind(null,t,e),n)},useLayoutEffect:function(e,t){return ts(4194308,4,e,t)},useInsertionEffect:function(e,t){ts(4,2,e,t)},useMemo:function(e,t){var n=Co();t=t===void 0?null:t;var r=e();if(co){De(!0);try{e()}finally{De(!1)}}return n.memoizedState=[r,t],r},useReducer:function(e,t,n){var r=Co();if(n!==void 0){var i=n(t);if(co){De(!0);try{n(t)}finally{De(!1)}}}else i=t;return r.memoizedState=r.baseState=i,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:i},r.queue=e,e=e.dispatch=Ts.bind(null,ro,e),[r.memoizedState,e]},useRef:function(e){var t=Co();return e={current:e},t.memoizedState=e},useState:function(e){e=zo(e);var t=e.queue,n=Es.bind(null,ro,t);return t.dispatch=n,[e.memoizedState,n]},useDebugValue:ds,useDeferredValue:function(e,t){return ms(Co(),e,t)},useTransition:function(){var e=zo(!1);return e=gs.bind(null,ro,e.queue,!0,!1),Co().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,n){var r=ro,a=Co();if(wi){if(n===void 0)throw Error(i(407));n=n()}else{if(n=t(),Ll===null)throw Error(i(349));zl&127||Po(r,t,n)}a.memoizedState=n;var o={value:n,getSnapshot:t};return a.queue=o,rs(Io.bind(null,r,o,e),[e]),r.flags|=2048,$o(9,{destroy:void 0},Fo.bind(null,r,o,n,t),null),n},useId:function(){var e=Co(),t=Ll.identifierPrefix;if(wi){var n=gi,r=hi;n=(r&~(1<<32-Oe(r)-1)).toString(32)+n,t=`_`+t+`R_`+n,n=lo++,0<\/script>`,o=o.removeChild(o.firstChild);break;case`select`:o=typeof r.is==`string`?s.createElement(`select`,{is:r.is}):s.createElement(`select`),r.multiple?o.multiple=!0:r.size&&(o.size=r.size);break;default:o=typeof r.is==`string`?s.createElement(a,{is:r.is}):s.createElement(a)}}o[Ze]=t,o[Qe]=r;a:for(s=t.child;s!==null;){if(s.tag===5||s.tag===6)o.appendChild(s.stateNode);else if(s.tag!==4&&s.tag!==27&&s.child!==null){s.child.return=s,s=s.child;continue}if(s===t)break a;for(;s.sibling===null;){if(s.return===null||s.return===t)break a;s=s.return}s.sibling.return=s.return,s=s.sibling}t.stateNode=o;a:switch(zd(o,a,r),a){case`button`:case`input`:case`select`:case`textarea`:r=!!r.autoFocus;break a;case`img`:r=!0;break a;default:r=!1}r&&Dc(t)}}return Mc(t),Oc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,n),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==r&&Dc(t);else{if(typeof r!=`string`&&t.stateNode===null)throw Error(i(166));if(e=ne.current,ji(t)){if(e=t.stateNode,n=t.memoizedProps,r=null,a=Si,a!==null)switch(a.tag){case 27:case 5:r=a.memoizedProps}e[Ze]=t,e=!!(e.nodeValue===n||r!==null&&!0===r.suppressHydrationWarning||Id(e.nodeValue,n)),e||Oi(t,!0)}else e=Gd(e).createTextNode(r),e[Ze]=t,t.stateNode=e}return Mc(t),null;case 31:if(n=t.memoizedState,e===null||e.memoizedState!==null){if(r=ji(t),n!==null){if(e===null){if(!r)throw Error(i(318));if(e=t.memoizedState,e=e===null?null:e.dehydrated,!e)throw Error(i(557));e[Ze]=t}else Mi(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;Mc(t),e=!1}else n=Ni(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),e=!0;if(!e)return t.flags&256?($a(t),t):($a(t),null);if(t.flags&128)throw Error(i(558))}return Mc(t),null;case 13:if(r=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(a=ji(t),r!==null&&r.dehydrated!==null){if(e===null){if(!a)throw Error(i(318));if(a=t.memoizedState,a=a===null?null:a.dehydrated,!a)throw Error(i(317));a[Ze]=t}else Mi(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;Mc(t),a=!1}else a=Ni(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=a),a=!0;if(!a)return t.flags&256?($a(t),t):($a(t),null)}return $a(t),t.flags&128?(t.lanes=n,t):(n=r!==null,e=e!==null&&e.memoizedState!==null,n&&(r=t.child,a=null,r.alternate!==null&&r.alternate.memoizedState!==null&&r.alternate.memoizedState.cachePool!==null&&(a=r.alternate.memoizedState.cachePool.pool),o=null,r.memoizedState!==null&&r.memoizedState.cachePool!==null&&(o=r.memoizedState.cachePool.pool),o!==a&&(r.flags|=2048)),n!==e&&n&&(t.child.flags|=8192),Ac(t,t.updateQueue),Mc(t),null);case 4:return ae(),e===null&&Td(t.stateNode.containerInfo),Mc(t),null;case 10:return zi(t.type),Mc(t),null;case 19:if(z(eo),r=t.memoizedState,r===null)return Mc(t),null;if(a=(t.flags&128)!=0,o=r.rendering,o===null)if(a)jc(r,!1);else{if(Kl!==0||e!==null&&e.flags&128)for(e=t.child;e!==null;){if(o=to(e),o!==null){for(t.flags|=128,jc(r,!1),e=o.updateQueue,t.updateQueue=e,Ac(t,e),t.subtreeFlags=0,e=n,n=t.child;n!==null;)ei(n,e),n=n.sibling;return B(eo,eo.current&1|2),wi&&_i(t,r.treeForkCount),t.child}e=e.sibling}r.tail!==null&&W()>ru&&(t.flags|=128,a=!0,jc(r,!1),t.lanes=4194304)}else{if(!a)if(e=to(o),e!==null){if(t.flags|=128,a=!0,e=e.updateQueue,t.updateQueue=e,Ac(t,e),jc(r,!0),r.tail===null&&r.tailMode===`hidden`&&!o.alternate&&!wi)return Mc(t),null}else 2*W()-r.renderingStartTime>ru&&n!==536870912&&(t.flags|=128,a=!0,jc(r,!1),t.lanes=4194304);r.isBackwards?(o.sibling=t.child,t.child=o):(e=r.last,e===null?t.child=o:e.sibling=o,r.last=o)}return r.tail===null?(Mc(t),null):(e=r.tail,r.rendering=e,r.tail=e.sibling,r.renderingStartTime=W(),e.sibling=null,n=eo.current,B(eo,a?n&1|2:n&1),wi&&_i(t,r.treeForkCount),e);case 22:case 23:return $a(t),Ka(),r=t.memoizedState!==null,e===null?r&&(t.flags|=8192):e.memoizedState!==null!==r&&(t.flags|=8192),r?n&536870912&&!(t.flags&128)&&(Mc(t),t.subtreeFlags&6&&(t.flags|=8192)):Mc(t),n=t.updateQueue,n!==null&&Ac(t,n.retryQueue),n=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(n=e.memoizedState.cachePool.pool),r=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(r=t.memoizedState.cachePool.pool),r!==n&&(t.flags|=2048),e!==null&&z(ca),null;case 24:return n=null,e!==null&&(n=e.memoizedState.cache),t.memoizedState.cache!==n&&(t.flags|=2048),zi(Zi),Mc(t),null;case 25:return null;case 30:return null}throw Error(i(156,t.tag))}function Pc(e,t){switch(bi(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return zi(Zi),ae(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return H(t),null;case 31:if(t.memoizedState!==null){if($a(t),t.alternate===null)throw Error(i(340));Mi()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if($a(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(i(340));Mi()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return z(eo),null;case 4:return ae(),null;case 10:return zi(t.type),null;case 22:case 23:return $a(t),Ka(),e!==null&&z(ca),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return zi(Zi),null;case 25:return null;default:return null}}function Fc(e,t){switch(bi(t),t.tag){case 3:zi(Zi),ae();break;case 26:case 27:case 5:H(t);break;case 4:ae();break;case 31:t.memoizedState!==null&&$a(t);break;case 13:$a(t);break;case 19:z(eo);break;case 10:zi(t.type);break;case 22:case 23:$a(t),Ka(),e!==null&&z(ca);break;case 24:zi(Zi)}}function Ic(e,t){try{var n=t.updateQueue,r=n===null?null:n.lastEffect;if(r!==null){var i=r.next;n=i;do{if((n.tag&e)===e){r=void 0;var a=n.create,o=n.inst;r=a(),o.destroy=r}n=n.next}while(n!==i)}}catch(e){qu(t,t.return,e)}}function Lc(e,t,n){try{var r=t.updateQueue,i=r===null?null:r.lastEffect;if(i!==null){var a=i.next;r=a;do{if((r.tag&e)===e){var o=r.inst,s=o.destroy;if(s!==void 0){o.destroy=void 0,i=t;var c=n,l=s;try{l()}catch(e){qu(i,c,e)}}}r=r.next}while(r!==a)}}catch(e){qu(t,t.return,e)}}function Rc(e){var t=e.updateQueue;if(t!==null){var n=e.stateNode;try{Va(t,n)}catch(t){qu(e,e.return,t)}}}function zc(e,t,n){n.props=Bs(e.type,e.memoizedProps),n.state=e.memoizedState;try{n.componentWillUnmount()}catch(n){qu(e,t,n)}}function Bc(e,t){try{var n=e.ref;if(n!==null){switch(e.tag){case 26:case 27:case 5:var r=e.stateNode;break;case 30:r=e.stateNode;break;default:r=e.stateNode}typeof n==`function`?e.refCleanup=n(r):n.current=r}}catch(n){qu(e,t,n)}}function Vc(e,t){var n=e.ref,r=e.refCleanup;if(n!==null)if(typeof r==`function`)try{r()}catch(n){qu(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof n==`function`)try{n(null)}catch(n){qu(e,t,n)}else n.current=null}function Hc(e){var t=e.type,n=e.memoizedProps,r=e.stateNode;try{a:switch(t){case`button`:case`input`:case`select`:case`textarea`:n.autoFocus&&r.focus();break a;case`img`:n.src?r.src=n.src:n.srcSet&&(r.srcset=n.srcSet)}}catch(t){qu(e,e.return,t)}}function Uc(e,t,n){try{var r=e.stateNode;Bd(r,e.type,n,t),r[Qe]=t}catch(t){qu(e,e.return,t)}}function Wc(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&nf(e.type)||e.tag===4}function Gc(e){a:for(;;){for(;e.sibling===null;){if(e.return===null||Wc(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&nf(e.type)||e.flags&2||e.child===null||e.tag===4)continue a;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function Kc(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?(n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n).insertBefore(e,t):(t=n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n,t.appendChild(e),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=Ut));else if(r!==4&&(r===27&&nf(e.type)&&(n=e.stateNode,t=null),e=e.child,e!==null))for(Kc(e,t,n),e=e.sibling;e!==null;)Kc(e,t,n),e=e.sibling}function qc(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(r!==4&&(r===27&&nf(e.type)&&(n=e.stateNode),e=e.child,e!==null))for(qc(e,t,n),e=e.sibling;e!==null;)qc(e,t,n),e=e.sibling}function Jc(e){var t=e.stateNode,n=e.memoizedProps;try{for(var r=e.type,i=t.attributes;i.length;)t.removeAttributeNode(i[0]);zd(t,r,n),t[Ze]=e,t[Qe]=n}catch(t){qu(e,e.return,t)}}var Yc=!1,Xc=!1,Zc=!1,Qc=typeof WeakSet==`function`?WeakSet:Set,$c=null;function el(e,t){if(e=e.containerInfo,Ud=fp,e=gr(e),_r(e)){if(`selectionStart`in e)var n={start:e.selectionStart,end:e.selectionEnd};else a:{n=(n=e.ownerDocument)&&n.defaultView||window;var r=n.getSelection&&n.getSelection();if(r&&r.rangeCount!==0){n=r.anchorNode;var a=r.anchorOffset,o=r.focusNode;r=r.focusOffset;try{n.nodeType,o.nodeType}catch{n=null;break a}var s=0,c=-1,l=-1,u=0,d=0,f=e,p=null;b:for(;;){for(var m;f!==n||a!==0&&f.nodeType!==3||(c=s+a),f!==o||r!==0&&f.nodeType!==3||(l=s+r),f.nodeType===3&&(s+=f.nodeValue.length),(m=f.firstChild)!==null;)p=f,f=m;for(;;){if(f===e)break b;if(p===n&&++u===a&&(c=s),p===o&&++d===r&&(l=s),(m=f.nextSibling)!==null)break;f=p,p=f.parentNode}f=m}n=c===-1||l===-1?null:{start:c,end:l}}else n=null}n||={start:0,end:0}}else n=null;for(Wd={focusedElem:e,selectionRange:n},fp=!1,$c=t;$c!==null;)if(t=$c,e=t.child,t.subtreeFlags&1028&&e!==null)e.return=t,$c=e;else for(;$c!==null;){switch(t=$c,o=t.alternate,e=t.flags,t.tag){case 0:if(e&4&&(e=t.updateQueue,e=e===null?null:e.events,e!==null))for(n=0;n title`))),zd(o,r,n),o[Ze]=e,ut(o),r=o;break a;case`link`:var s=Kf(`link`,`href`,a).get(r+(n.href||``));if(s){for(var c=0;cg&&(o=g,g=h,h=o);var _=mr(s,h),v=mr(s,g);if(_&&v&&(p.rangeCount!==1||p.anchorNode!==_.node||p.anchorOffset!==_.offset||p.focusNode!==v.node||p.focusOffset!==v.offset)){var y=d.createRange();y.setStart(_.node,_.offset),p.removeAllRanges(),h>g?(p.addRange(y),p.extend(v.node,v.offset)):(y.setEnd(v.node,v.offset),p.addRange(y))}}}}for(d=[],p=s;p=p.parentNode;)p.nodeType===1&&d.push({element:p,left:p.scrollLeft,top:p.scrollTop});for(typeof s.focus==`function`&&s.focus(),s=0;sn?32:n,P.T=null,n=du,du=null;var o=su,s=lu;if(ou=0,cu=su=null,lu=0,Il&6)throw Error(i(331));var c=Il;if(Il|=4,jl(o.current),Cl(o,o.current,s,n),Il=c,od(0,!1),Ee&&typeof Ee.onPostCommitFiberRoot==`function`)try{Ee.onPostCommitFiberRoot(Te,o)}catch{}return!0}finally{F.p=a,P.T=r,Uu(e,t)}}function Ku(e,t,n){t=si(n,t),t=Ks(e.stateNode,t,2),e=Pa(e,t,2),e!==null&&(Ve(e,2),ad(e))}function qu(e,t,n){if(e.tag===3)Ku(e,e,n);else for(;t!==null;){if(t.tag===3){Ku(t,e,n);break}else if(t.tag===1){var r=t.stateNode;if(typeof t.type.getDerivedStateFromError==`function`||typeof r.componentDidCatch==`function`&&(au===null||!au.has(r))){e=si(n,e),n=qs(2),r=Pa(t,n,2),r!==null&&(Js(n,r,t,e),Ve(r,2),ad(r));break}}t=t.return}}function Ju(e,t,n){var r=e.pingCache;if(r===null){r=e.pingCache=new Fl;var i=new Set;r.set(t,i)}else i=r.get(t),i===void 0&&(i=new Set,r.set(t,i));i.has(n)||(Wl=!0,i.add(n),e=Yu.bind(null,e,t,n),t.then(e,e))}function Yu(e,t,n){var r=e.pingCache;r!==null&&r.delete(t),e.pingedLanes|=e.suspendedLanes&n,e.warmLanes&=~n,Ll===e&&(zl&n)===n&&(Kl===4||Kl===3&&(zl&62914560)===zl&&300>W()-tu?!(Il&2)&&wu(e,0):Yl|=n,Zl===zl&&(Zl=0)),ad(e)}function Xu(e,t){t===0&&(t=ze()),e=Kr(e,t),e!==null&&(Ve(e,t),ad(e))}function J(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),Xu(e,n)}function Zu(e,t){var n=0;switch(e.tag){case 31:case 13:var r=e.stateNode,a=e.memoizedState;a!==null&&(n=a.retryLane);break;case 19:r=e.stateNode;break;case 22:r=e.stateNode._retryCache;break;default:throw Error(i(314))}r!==null&&r.delete(t),Xu(e,n)}function Qu(e,t){return me(e,t)}var $u=null,ed=null,td=!1,nd=!1,rd=!1,id=0;function ad(e){e!==ed&&e.next===null&&(ed===null?$u=ed=e:ed=ed.next=e),nd=!0,td||(td=!0,fd())}function od(e,t){if(!rd&&nd){rd=!0;do for(var n=!1,r=$u;r!==null;){if(!t)if(e!==0){var i=r.pendingLanes;if(i===0)var a=0;else{var o=r.suspendedLanes,s=r.pingedLanes;a=(1<<31-Oe(42|e)+1)-1,a&=i&~(o&~s),a=a&201326741?a&201326741|1:a?a|2:0}a!==0&&(n=!0,dd(r,a))}else a=zl,a=Ie(r,r===Ll?a:0,r.cancelPendingCommit!==null||r.timeoutHandle!==-1),!(a&3)||Le(r,a)||(n=!0,dd(r,a));r=r.next}while(n);rd=!1}}function sd(){cd()}function cd(){nd=td=!1;var e=0;id!==0&&Xd()&&(e=id);for(var t=W(),n=null,r=$u;r!==null;){var i=r.next,a=ld(r,t);a===0?(r.next=null,n===null?$u=i:n.next=i,i===null&&(ed=n)):(n=r,(e!==0||a&3)&&(nd=!0)),r=i}ou!==0&&ou!==5||od(e,!1),id!==0&&(id=0)}function ld(e,t){for(var n=e.suspendedLanes,r=e.pingedLanes,i=e.expirationTimes,a=e.pendingLanes&-62914561;0s)break;var u=c.transferSize,d=c.initiatorType;u&&Vd(d)&&(c=c.responseEnd,o+=u*(c`u`?null:document;function Ef(e,t,n){var r=Tf;if(r&&typeof t==`string`&&t){var i=Ot(t);i=`link[rel="`+e+`"][href="`+i+`"]`,typeof n==`string`&&(i+=`[crossorigin="`+n+`"]`),bf.has(i)||(bf.add(i),e={rel:e,crossOrigin:n,href:t},r.querySelector(i)===null&&(t=r.createElement(`link`),zd(t,`link`,e),ut(t),r.head.appendChild(t)))}}function Df(e){Sf.D(e),Ef(`dns-prefetch`,e,null)}function Of(e,t){Sf.C(e,t),Ef(`preconnect`,e,t)}function kf(e,t,n){Sf.L(e,t,n);var r=Tf;if(r&&e&&t){var i=`link[rel="preload"][as="`+Ot(t)+`"]`;t===`image`&&n&&n.imageSrcSet?(i+=`[imagesrcset="`+Ot(n.imageSrcSet)+`"]`,typeof n.imageSizes==`string`&&(i+=`[imagesizes="`+Ot(n.imageSizes)+`"]`)):i+=`[href="`+Ot(e)+`"]`;var a=i;switch(t){case`style`:a=Ff(e);break;case`script`:a=zf(e)}yf.has(a)||(e=f({rel:`preload`,href:t===`image`&&n&&n.imageSrcSet?void 0:e,as:t},n),yf.set(a,e),r.querySelector(i)!==null||t===`style`&&r.querySelector(If(a))||t===`script`&&r.querySelector(Bf(a))||(t=r.createElement(`link`),zd(t,`link`,e),ut(t),r.head.appendChild(t)))}}function Af(e,t){Sf.m(e,t);var n=Tf;if(n&&e){var r=t&&typeof t.as==`string`?t.as:`script`,i=`link[rel="modulepreload"][as="`+Ot(r)+`"][href="`+Ot(e)+`"]`,a=i;switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:a=zf(e)}if(!yf.has(a)&&(e=f({rel:`modulepreload`,href:e},t),yf.set(a,e),n.querySelector(i)===null)){switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:if(n.querySelector(Bf(a)))return}r=n.createElement(`link`),zd(r,`link`,e),ut(r),n.head.appendChild(r)}}}function jf(e,t,n){Sf.S(e,t,n);var r=Tf;if(r&&e){var i=lt(r).hoistableStyles,a=Ff(e);t||=`default`;var o=i.get(a);if(!o){var s={loading:0,preload:null};if(o=r.querySelector(If(a)))s.loading=5;else{e=f({rel:`stylesheet`,href:e,"data-precedence":t},n),(n=yf.get(a))&&Uf(e,n);var c=o=r.createElement(`link`);ut(c),zd(c,`link`,e),c._p=new Promise(function(e,t){c.onload=e,c.onerror=t}),c.addEventListener(`load`,function(){s.loading|=1}),c.addEventListener(`error`,function(){s.loading|=2}),s.loading|=4,Hf(o,t,r)}o={type:`stylesheet`,instance:o,count:1,state:s},i.set(a,o)}}}function Mf(e,t){Sf.X(e,t);var n=Tf;if(n&&e){var r=lt(n).hoistableScripts,i=zf(e),a=r.get(i);a||(a=n.querySelector(Bf(i)),a||(e=f({src:e,async:!0},t),(t=yf.get(i))&&Wf(e,t),a=n.createElement(`script`),ut(a),zd(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function Nf(e,t){Sf.M(e,t);var n=Tf;if(n&&e){var r=lt(n).hoistableScripts,i=zf(e),a=r.get(i);a||(a=n.querySelector(Bf(i)),a||(e=f({src:e,async:!0,type:`module`},t),(t=yf.get(i))&&Wf(e,t),a=n.createElement(`script`),ut(a),zd(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function Pf(e,t,n,r){var a=(a=ne.current)?xf(a):null;if(!a)throw Error(i(446));switch(e){case`meta`:case`title`:return null;case`style`:return typeof n.precedence==`string`&&typeof n.href==`string`?(t=Ff(n.href),n=lt(a).hoistableStyles,r=n.get(t),r||(r={type:`style`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};case`link`:if(n.rel===`stylesheet`&&typeof n.href==`string`&&typeof n.precedence==`string`){e=Ff(n.href);var o=lt(a).hoistableStyles,s=o.get(e);if(s||(a=a.ownerDocument||a,s={type:`stylesheet`,instance:null,count:0,state:{loading:0,preload:null}},o.set(e,s),(o=a.querySelector(If(e)))&&!o._p&&(s.instance=o,s.state.loading=5),yf.has(e)||(n={rel:`preload`,as:`style`,href:n.href,crossOrigin:n.crossOrigin,integrity:n.integrity,media:n.media,hrefLang:n.hrefLang,referrerPolicy:n.referrerPolicy},yf.set(e,n),o||Rf(a,e,n,s.state))),t&&r===null)throw Error(i(528,``));return s}if(t&&r!==null)throw Error(i(529,``));return null;case`script`:return t=n.async,n=n.src,typeof n==`string`&&t&&typeof t!=`function`&&typeof t!=`symbol`?(t=zf(n),n=lt(a).hoistableScripts,r=n.get(t),r||(r={type:`script`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};default:throw Error(i(444,e))}}function Ff(e){return`href="`+Ot(e)+`"`}function If(e){return`link[rel="stylesheet"][`+e+`]`}function Lf(e){return f({},e,{"data-precedence":e.precedence,precedence:null})}function Rf(e,t,n,r){e.querySelector(`link[rel="preload"][as="style"][`+t+`]`)?r.loading=1:(t=e.createElement(`link`),r.preload=t,t.addEventListener(`load`,function(){return r.loading|=1}),t.addEventListener(`error`,function(){return r.loading|=2}),zd(t,`link`,n),ut(t),e.head.appendChild(t))}function zf(e){return`[src="`+Ot(e)+`"]`}function Bf(e){return`script[async]`+e}function Vf(e,t,n){if(t.count++,t.instance===null)switch(t.type){case`style`:var r=e.querySelector(`style[data-href~="`+Ot(n.href)+`"]`);if(r)return t.instance=r,ut(r),r;var a=f({},n,{"data-href":n.href,"data-precedence":n.precedence,href:null,precedence:null});return r=(e.ownerDocument||e).createElement(`style`),ut(r),zd(r,`style`,a),Hf(r,n.precedence,e),t.instance=r;case`stylesheet`:a=Ff(n.href);var o=e.querySelector(If(a));if(o)return t.state.loading|=4,t.instance=o,ut(o),o;r=Lf(n),(a=yf.get(a))&&Uf(r,a),o=(e.ownerDocument||e).createElement(`link`),ut(o);var s=o;return s._p=new Promise(function(e,t){s.onload=e,s.onerror=t}),zd(o,`link`,r),t.state.loading|=4,Hf(o,n.precedence,e),t.instance=o;case`script`:return o=zf(n.src),(a=e.querySelector(Bf(o)))?(t.instance=a,ut(a),a):(r=n,(a=yf.get(o))&&(r=f({},n),Wf(r,a)),e=e.ownerDocument||e,a=e.createElement(`script`),ut(a),zd(a,`link`,r),e.head.appendChild(a),t.instance=a);case`void`:return null;default:throw Error(i(443,t.type))}else t.type===`stylesheet`&&!(t.state.loading&4)&&(r=t.instance,t.state.loading|=4,Hf(r,n.precedence,e));return t.instance}function Hf(e,t,n){for(var r=n.querySelectorAll(`link[rel="stylesheet"][data-precedence],style[data-precedence]`),i=r.length?r[r.length-1]:null,a=i,o=0;o title`):null)}function Jf(e,t,n){if(n===1||t.itemProp!=null)return!1;switch(e){case`meta`:case`title`:return!0;case`style`:if(typeof t.precedence!=`string`||typeof t.href!=`string`||t.href===``)break;return!0;case`link`:if(typeof t.rel!=`string`||typeof t.href!=`string`||t.href===``||t.onLoad||t.onError)break;switch(t.rel){case`stylesheet`:return e=t.disabled,typeof t.precedence==`string`&&e==null;default:return!0}case`script`:if(t.async&&typeof t.async!=`function`&&typeof t.async!=`symbol`&&!t.onLoad&&!t.onError&&t.src&&typeof t.src==`string`)return!0}return!1}function Yf(e){return!(e.type===`stylesheet`&&!(e.state.loading&3))}function Xf(e,t,n,r){if(n.type===`stylesheet`&&(typeof r.media!=`string`||!1!==matchMedia(r.media).matches)&&!(n.state.loading&4)){if(n.instance===null){var i=Ff(r.href),a=t.querySelector(If(i));if(a){t=a._p,typeof t==`object`&&t&&typeof t.then==`function`&&(e.count++,e=$f.bind(e),t.then(e,e)),n.state.loading|=4,n.instance=a,ut(a);return}a=t.ownerDocument||t,r=Lf(r),(i=yf.get(i))&&Uf(r,i),a=a.createElement(`link`),ut(a);var o=a;o._p=new Promise(function(e,t){o.onload=e,o.onerror=t}),zd(a,`link`,r),n.instance=a}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(n,t),(t=n.state.preload)&&!(n.state.loading&3)&&(e.count++,n=$f.bind(e),t.addEventListener(`load`,n),t.addEventListener(`error`,n))}}var Zf=0;function Qf(e,t){return e.stylesheets&&e.count===0&&tp(e,e.stylesheets),0Zf?50:800)+t);return e.unsuspend=n,function(){e.unsuspend=null,clearTimeout(r),clearTimeout(i)}}:null}function $f(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)tp(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var ep=null;function tp(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,ep=new Map,t.forEach(np,e),ep=null,$f.call(e))}function np(e,t){if(!(t.state.loading&4)){var n=ep.get(e);if(n)var r=n.get(null);else{n=new Map,ep.set(e,n);for(var i=e.querySelectorAll(`link[data-precedence],style[data-precedence]`),a=0;a{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=jd()}))(),Nd=`__rc_react_root__`;function Pd(e,t){let n=t[Nd]||(0,Md.createRoot)(t);n.render(e),t[Nd]=n}async function Fd(e){return Promise.resolve().then(()=>{e[Nd]?.unmount(),delete e[Nd]})}var Id=(e,t,n)=>n===void 0?`${e}-${t}`:n,Ld=Lo(`Wave`,e=>{let{componentCls:t,colorPrimary:n,motionDurationSlow:r,motionEaseInOut:i,motionEaseOutCirc:a,antCls:o}=e,[,s]=zo(o,`wave`);return{[t]:{position:`absolute`,background:`transparent`,pointerEvents:`none`,boxSizing:`border-box`,color:s(`color`,n),boxShadow:`0 0 0 0 currentcolor`,opacity:.2,"&.wave-motion-appear":{transition:[`box-shadow 0.4s`,`opacity 2s`].map(e=>`${e} ${a}`).join(`,`),"&-active":{boxShadow:`0 0 0 6px currentcolor`,opacity:0},"&.wave-quick":{transition:[`box-shadow`,`opacity`].map(e=>`${e} ${r} ${i}`).join(`,`)}}}}}),Rd=`ant-wave-target`;function zd(e){return e&&typeof e==`string`&&e!==`#fff`&&e!==`#ffffff`&&e!==`rgb(255, 255, 255)`&&e!==`rgba(255, 255, 255, 1)`&&!/rgba\((?:\d*, ){3}0\)/.test(e)&&e!==`transparent`&&e!==`canvastext`}function Bd(e,t=null){let n=getComputedStyle(e),{borderTopColor:r,borderColor:i,backgroundColor:a}=n;return t&&zd(n[t])?n[t]:[r,i,a].find(zd)??null}function Vd(e){return Number.isNaN(e)?0:e}var Hd=e=>{let{className:t,target:n,component:r,colorSource:i}=e,a=m.useRef(null),{getPrefixCls:o}=m.useContext(zt),[s]=zo(o(),`wave`),[c,l]=m.useState(null),[u,d]=m.useState([]),[f,p]=m.useState(0),[h,g]=m.useState(0),[_,v]=m.useState(0),[y,b]=m.useState(0),[x,S]=m.useState(!1),C={left:f,top:h,width:_,height:y,borderRadius:u.map(e=>`${e}px`).join(` `)};c&&(C[s(`color`)]=c);function w(){let e=getComputedStyle(n);l(Bd(n,i));let t=e.position===`static`,{borderLeftWidth:r,borderTopWidth:a}=e;p(t?n.offsetLeft:Vd(-Number.parseFloat(r))),g(t?n.offsetTop:Vd(-Number.parseFloat(a))),v(n.offsetWidth),b(n.offsetHeight);let{borderTopLeftRadius:o,borderTopRightRadius:s,borderBottomLeftRadius:c,borderBottomRightRadius:u}=e;d([o,s,u,c].map(e=>Vd(Number.parseFloat(e))))}if(m.useEffect(()=>{if(n){let e=It(()=>{w(),S(!0)}),t;return typeof ResizeObserver<`u`&&(t=new ResizeObserver(w),t.observe(n)),()=>{It.cancel(e),t?.disconnect()}}},[n]),!x)return null;let T=(r===`Checkbox`||r===`Radio`)&&n?.classList.contains(Rd);return m.createElement(hc,{visible:!0,motionAppear:!0,motionName:`wave-motion`,motionDeadline:5e3,onAppearEnd:(e,t)=>{if(t.deadline||t.propertyName===`opacity`){let e=a.current?.parentElement;Fd(e).then(()=>{e?.remove()})}return!1}},({className:e},n)=>m.createElement(`div`,{ref:Me(a,n),className:K(t,e,{"wave-quick":T}),style:C}))},Ud=(e,t)=>{let{component:n}=t;if(n===`Checkbox`&&!e.querySelector(`input`)?.checked)return;let r=document.createElement(`div`);r.style.position=`absolute`,r.style.left=`0px`,r.style.top=`0px`,e?.insertBefore(r,e?.firstChild),Pd(m.createElement(Hd,{...t,target:e}),r)},Wd=(e,t,n,r)=>{let{wave:i}=m.useContext(zt),[,a,o]=Eo(),s=W(s=>{let c=e.current;if(i?.disabled||!c)return;let l=c.querySelector(`.${Rd}`)||c,{showEffect:u}=i||{};(u||Ud)(l,{className:t,token:a,component:n,event:s,hashId:o,colorSource:r})}),c=m.useRef(null);return m.useEffect(()=>()=>{It.cancel(c.current)},[]),e=>{It.cancel(c.current),c.current=It(()=>{s(e)})}},Gd=e=>{let{children:t,disabled:n,component:r,colorSource:i}=e,{getPrefixCls:a}=(0,m.useContext)(zt),o=(0,m.useRef)(null),s=a(`wave`),c=Wd(o,K(s,Ld(s)),r,i);return m.useEffect(()=>{let e=o.current;if(!e||e.nodeType!==window.Node.ELEMENT_NODE||n)return;let t=t=>{!ou(t.target)||!e.getAttribute||e.getAttribute(`disabled`)||e.disabled||e.className.includes(`disabled`)&&!e.className.includes(`disabled:`)||e.getAttribute(`aria-disabled`)===`true`||e.className.includes(`-leave`)||c(t)};return e.addEventListener(`click`,t,!0),()=>{e.removeEventListener(`click`,t,!0)}},[n]),m.isValidElement(t)?Mu(t,{ref:Pe(t)?Me(Le(t),o):o}):t??null},Kd=e=>{let t=m.useContext(zu);return m.useMemo(()=>e?typeof e==`string`?e??t:typeof e==`function`?e(t):t:t,[e,t])},qd=Io([`Space`,`Compact`],e=>{let{componentCls:t}=e;return{[t]:{display:`inline-flex`,"&-block":{display:`flex`,width:`100%`},"&-vertical":{flexDirection:`column`},"&-rtl":{direction:`rtl`}}}},()=>({}),{resetStyle:!1}),Jd=m.createContext(null),Yd=(e,t)=>{let n=m.useContext(Jd),r=m.useMemo(()=>{if(!n)return``;let{compactDirection:r,isFirstItem:i,isLastItem:a}=n,o=r===`vertical`?`-vertical-`:`-`;return K(`${e}-compact${o}item`,{[`${e}-compact${o}first-item`]:i,[`${e}-compact${o}last-item`]:a,[`${e}-compact${o}item-rtl`]:t===`rtl`})},[e,t,n]);return{compactSize:n?.compactSize,compactDirection:n?.compactDirection,compactItemClassnames:r}},Xd=e=>{let{children:t}=e;return m.createElement(Jd.Provider,{value:null},t)},Zd=e=>{let{children:t,...n}=e;return m.createElement(Jd.Provider,{value:m.useMemo(()=>n,[n])},t)},Qd=e=>{let{getPrefixCls:t,direction:n}=m.useContext(zt),{size:r,direction:i,orientation:a,block:o,prefixCls:s,className:c,rootClassName:l,children:u,vertical:d,...f}=e,[p,h]=ul(a,d,i),g=Kd(e=>r??e),_=t(`space-compact`,s),[v]=qd(_),y=K(_,v,{[`${_}-rtl`]:n===`rtl`,[`${_}-block`]:o,[`${_}-vertical`]:h},c,l),b=m.useContext(Jd),x=nt(u),S=m.useMemo(()=>x.map((e,t)=>{let n=e?.key||`${_}-item-${t}`;return m.createElement(Zd,{key:n,compactSize:g,compactDirection:p,isFirstItem:t===0&&(!b||b?.isFirstItem),isLastItem:t===x.length-1&&(!b||b?.isLastItem)},e)}),[x,b,p,g,_]);return x.length===0?null:m.createElement(`div`,{className:y,...f},S)},$d=m.createContext(void 0),ef=e=>{let{getPrefixCls:t,direction:n}=m.useContext(zt),{prefixCls:r,size:i,className:a,...o}=e,s=t(`btn-group`,r),[,,c]=Eo(),l=m.useMemo(()=>{switch(i){case`large`:return`lg`;case`small`:return`sm`;default:return``}},[i]),u=K(s,{[`${s}-${l}`]:l,[`${s}-rtl`]:n===`rtl`},a,c);return m.createElement($d.Provider,{value:i},m.createElement(`div`,{...o,className:u}))},tf=/^[\u4E00-\u9FA5]{2}$/,nf=tf.test.bind(tf);function rf(e){return e===`danger`?{danger:!0}:{type:e}}function af(e){return typeof e==`string`}function of(e){return e===`text`||e===`link`}function sf(e,t,n,r){if(!Gc(e)||e===``)return;let i=t?` `:``;return typeof e!=`string`&&typeof e!=`number`&&af(e.type)&&nf(e.props.children)?Mu(e,e=>{let t=K(e.className,r)||void 0,a={...n,...e.style};return{...e,children:e.children.split(``).join(i),className:t,style:a}}):af(e)?m.createElement(`span`,{className:r,style:n},nf(e)?e.split(``).join(i):e):Au(e)?m.createElement(`span`,{className:r,style:n},e):Mu(e,e=>({...e,className:K(e.className,r)||void 0,style:{...e.style,...n}}))}function cf(e,t,n,r){let i=!1,a=[];return m.Children.forEach(e,e=>{let t=typeof e,n=t===`string`||t===`number`;if(i&&n){let t=a.length-1;a[t]=`${a[t]}${e}`}else a.push(e);i=n}),m.Children.map(a,e=>sf(e,t,n,r))}[`default`,`primary`,`danger`].concat(At(oa));var lf=(0,m.forwardRef)((e,t)=>{let{className:n,style:r,children:i,prefixCls:a}=e,o=K(`${a}-icon`,n);return m.createElement(`span`,{ref:t,className:o,style:r},i)}),uf=(0,m.forwardRef)((e,t)=>{let{prefixCls:n,className:r,style:i,iconClassName:a}=e,o=K(`${n}-loading-icon`,r);return m.createElement(lf,{prefixCls:n,className:o,style:i,ref:t},m.createElement(md,{className:a}))}),df=()=>({width:0,opacity:0,transform:`scale(0)`}),ff=e=>({width:e.scrollWidth,opacity:1,transform:`scale(1)`}),pf=e=>{let{prefixCls:t,loading:n,existIcon:r,className:i,style:a,mount:o}=e,s=!!n;return r?m.createElement(uf,{prefixCls:t,className:i,style:a}):m.createElement(hc,{visible:s,motionName:`${t}-loading-icon-motion`,motionAppear:!o,motionEnter:!o,motionLeave:!o,removeOnLeave:!0,onAppearStart:df,onAppearActive:ff,onEnterStart:df,onEnterActive:ff,onLeaveStart:ff,onLeaveActive:df},({className:e,style:n},r)=>{let o={...a,...n};return m.createElement(uf,{prefixCls:t,className:K(i,e),style:o,ref:r})})},mf=e=>({animationDuration:e,animationFillMode:`both`}),hf=(e,t,n,r,i=!1)=>{let a=i?`&`:``;return{[` - ${a}${e}-enter, - ${a}${e}-appear - `]:{...mf(r),animationPlayState:`paused`},[`${a}${e}-leave`]:{...mf(r),animationPlayState:`paused`},[` - ${a}${e}-enter${e}-enter-active, - ${a}${e}-appear${e}-appear-active - `]:{animationName:t,animationPlayState:`running`},[`${a}${e}-leave${e}-leave-active`]:{animationName:n,animationPlayState:`running`,pointerEvents:`none`}}},gf=new gi(`antFadeIn`,{"0%":{opacity:0},"100%":{opacity:1}}),_f=new gi(`antFadeOut`,{"0%":{opacity:1},"100%":{opacity:0}}),vf=(e,t=!1)=>{let{antCls:n}=e,r=`${n}-fade`,i=t?`&`:``;return[hf(r,gf,_f,e.motionDurationMid,t),{[` - ${i}${r}-enter, - ${i}${r}-appear - `]:{opacity:0,animationTimingFunction:`linear`},[`${i}${r}-leave`]:{animationTimingFunction:`linear`}}]},yf=()=>({"@media (prefers-reduced-motion: reduce)":{transition:`none`,animation:`none`}}),bf=new gi(`antZoomIn`,{"0%":{transform:`scale(0.2)`,opacity:0},"100%":{transform:`scale(1)`,opacity:1}}),xf=new gi(`antZoomOut`,{"0%":{transform:`scale(1)`},"100%":{transform:`scale(0.2)`,opacity:0}}),Sf=new gi(`antZoomBigIn`,{"0%":{transform:`scale(0.8)`,opacity:0},"100%":{transform:`scale(1)`,opacity:1}}),Cf=new gi(`antZoomBigOut`,{"0%":{transform:`scale(1)`},"100%":{transform:`scale(0.8)`,opacity:0}}),wf=new gi(`antZoomUpIn`,{"0%":{transform:`scale(0.8)`,transformOrigin:`50% 0%`,opacity:0},"100%":{transform:`scale(1)`,transformOrigin:`50% 0%`}}),Tf=new gi(`antZoomUpOut`,{"0%":{transform:`scale(1)`,transformOrigin:`50% 0%`},"100%":{transform:`scale(0.8)`,transformOrigin:`50% 0%`,opacity:0}}),Ef=new gi(`antZoomLeftIn`,{"0%":{transform:`scale(0.8)`,transformOrigin:`0% 50%`,opacity:0},"100%":{transform:`scale(1)`,transformOrigin:`0% 50%`}}),Df=new gi(`antZoomLeftOut`,{"0%":{transform:`scale(1)`,transformOrigin:`0% 50%`},"100%":{transform:`scale(0.8)`,transformOrigin:`0% 50%`,opacity:0}}),Of=new gi(`antZoomRightIn`,{"0%":{transform:`scale(0.8)`,transformOrigin:`100% 50%`,opacity:0},"100%":{transform:`scale(1)`,transformOrigin:`100% 50%`}}),kf=new gi(`antZoomRightOut`,{"0%":{transform:`scale(1)`,transformOrigin:`100% 50%`},"100%":{transform:`scale(0.8)`,transformOrigin:`100% 50%`,opacity:0}}),Af=new gi(`antZoomDownIn`,{"0%":{transform:`scale(0.8)`,transformOrigin:`50% 100%`,opacity:0},"100%":{transform:`scale(1)`,transformOrigin:`50% 100%`}}),jf=new gi(`antZoomDownOut`,{"0%":{transform:`scale(1)`,transformOrigin:`50% 100%`},"100%":{transform:`scale(0.8)`,transformOrigin:`50% 100%`,opacity:0}}),Mf={zoom:{inKeyframes:bf,outKeyframes:xf},"zoom-big":{inKeyframes:Sf,outKeyframes:Cf},"zoom-big-fast":{inKeyframes:Sf,outKeyframes:Cf},"zoom-left":{inKeyframes:Ef,outKeyframes:Df},"zoom-right":{inKeyframes:Of,outKeyframes:kf},"zoom-up":{inKeyframes:wf,outKeyframes:Tf},"zoom-down":{inKeyframes:Af,outKeyframes:jf}},Nf=(e,t)=>{let{antCls:n}=e,r=`${n}-${t}`,{inKeyframes:i,outKeyframes:a}=Mf[t];return[hf(r,i,a,t===`zoom-big-fast`?e.motionDurationFast:e.motionDurationMid),{[` - ${r}-enter, - ${r}-appear - `]:{transform:`scale(0)`,opacity:0,animationTimingFunction:e.motionEaseOutCirc,"&-prepare":{transform:`none`}},[`${r}-leave`]:{animationTimingFunction:e.motionEaseInOutCirc}}]},Pf=(e,t)=>({[`> span, > ${e}`]:{"&:not(:last-child)":{[`&, & > ${e}`]:{"&:not(:disabled)":{borderInlineEndColor:t}}},"&:not(:first-child)":{[`&, & > ${e}`]:{"&:not(:disabled)":{borderInlineStartColor:t}}}}}),Ff=e=>{let{componentCls:t,fontSize:n,lineWidth:r,groupBorderColor:i,colorErrorHover:a}=e;return{[`${t}-group`]:[{position:`relative`,display:`inline-flex`,[`> span, > ${t}`]:{"&:not(:last-child)":{[`&, & > ${t}`]:{borderStartEndRadius:0,borderEndEndRadius:0}},"&:not(:first-child)":{marginInlineStart:e.calc(r).mul(-1).equal(),[`&, & > ${t}`]:{borderStartStartRadius:0,borderEndStartRadius:0}}},[t]:{position:`relative`,zIndex:1,"&:hover, &:focus, &:active":{zIndex:2},"&[disabled]":{zIndex:0}},[`${t}-icon-only`]:{fontSize:n}},Pf(`${t}-primary`,i),Pf(`${t}-danger`,a)]}},If=e=>Math.round(Number(e||0)),Lf=e=>{if(e instanceof _a)return e;if(e&&typeof e==`object`&&`h`in e&&`b`in e){let{b:t,...n}=e;return{...n,v:t}}return typeof e==`string`&&/hsb/.test(e)?e.replace(/hsb/,`hsv`):e},Rf=class extends _a{constructor(e){super(Lf(e))}toHsbString(){let e=this.toHsb(),t=If(e.s*100),n=If(e.b*100),r=If(e.h),i=e.a,a=`hsb(${r}, ${t}%, ${n}%)`,o=`hsba(${r}, ${t}%, ${n}%, ${i.toFixed(i===0?0:2)})`;return i===1?a:o}toHsb(){let{v:e,...t}=this.toHsv();return{...t,b:e,a:this.a}}};(e=>e instanceof Rf?e:new Rf(e))(`#1677ff`);var zf=(e,t)=>e?.replace(/[^0-9a-f]/gi,``).slice(0,t?8:6)||``,Bf=(e,t)=>e?zf(e,t):``,Vf=function(){function e(t){if(Oi(this,e),this.cleared=!1,t instanceof e){this.metaColor=t.metaColor.clone(),this.colors=t.colors?.map(t=>({color:new e(t.color),percent:t.percent})),this.cleared=t.cleared;return}let n=Array.isArray(t);n&&t.length?(this.colors=t.map(({color:t,percent:n})=>({color:new e(t),percent:n})),this.metaColor=new Rf(this.colors[0].color.metaColor)):this.metaColor=new Rf(n?``:t),(!t||n&&!this.colors)&&(this.metaColor=this.metaColor.setA(0),this.cleared=!0)}return Ai(e,[{key:`toHsb`,value:function(){return this.metaColor.toHsb()}},{key:`toHsbString`,value:function(){return this.metaColor.toHsbString()}},{key:`toHex`,value:function(){return Bf(this.toHexString(),this.metaColor.a<1)}},{key:`toHexString`,value:function(){return this.metaColor.toHexString()}},{key:`toRgb`,value:function(){return this.metaColor.toRgb()}},{key:`toRgbString`,value:function(){return this.metaColor.toRgbString()}},{key:`isGradient`,value:function(){return!!this.colors&&!this.cleared}},{key:`getColors`,value:function(){return this.colors||[{color:this,percent:0}]}},{key:`toCssString`,value:function(){let{colors:e}=this;return e?`linear-gradient(90deg, ${e.map(e=>`${e.color.toRgbString()} ${e.percent}%`).join(`, `)})`:this.metaColor.toRgbString()}},{key:`equals`,value:function(e){return!e||this.isGradient()!==e.isGradient()?!1:this.isGradient()?this.colors.length===e.colors.length&&this.colors.every((t,n)=>{let r=e.colors[n];return t.percent===r.percent&&t.color.equals(r.color)}):this.toHexString()===e.toHexString()}}])}(),Hf=e=>e instanceof Vf?e:new Vf(e),Uf=(e,t)=>{let{r:n,g:r,b:i,a}=e.toRgb(),o=new Rf(e.toRgbString()).onBackground(t).toHsv();return a<=.5?o.v>.5:n*.299+r*.587+i*.114>192},Wf=e=>{let{paddingInline:t,onlyIconSize:n,borderColorDisabled:r}=e;return Yi(e,{buttonPaddingHorizontal:t,buttonPaddingVertical:0,buttonIconOnlyFontSize:n,colorBorderDisabled:r})},Gf=e=>{let t=e.contentFontSize??e.fontSize,n=e.contentFontSizeSM??e.fontSize,r=e.contentFontSizeLG??e.fontSizeLG,i=e.contentLineHeight??sa(t),a=e.contentLineHeightSM??sa(n),o=e.contentLineHeightLG??sa(r),s=Uf(new Vf(e.colorBgSolid),`#fff`)?`#000`:`#fff`,c=oa.reduce((t,n)=>({...t,[`${n}ShadowColor`]:`0 ${q(e.controlOutlineWidth)} 0 ${bo(e[`${n}1`],e.colorBgContainer)}`}),{}),l=e.colorBgContainerDisabled,u=e.colorBgContainerDisabled;return{...c,fontWeight:400,iconGap:e.marginXS,defaultShadow:`0 ${e.controlOutlineWidth}px 0 ${e.controlTmpOutline}`,primaryShadow:`0 ${e.controlOutlineWidth}px 0 ${e.controlOutline}`,dangerShadow:`0 ${e.controlOutlineWidth}px 0 ${e.colorErrorOutline}`,primaryColor:e.colorTextLightSolid,dangerColor:e.colorTextLightSolid,borderColorDisabled:e.colorBorderDisabled,defaultGhostColor:e.colorBgContainer,ghostBg:`transparent`,defaultGhostBorderColor:e.colorBgContainer,paddingInline:e.paddingContentHorizontal-e.lineWidth,paddingInlineLG:e.paddingContentHorizontal-e.lineWidth,paddingInlineSM:8-e.lineWidth,onlyIconSize:`inherit`,onlyIconSizeSM:`inherit`,onlyIconSizeLG:`inherit`,groupBorderColor:e.colorPrimaryHover,linkHoverBg:`transparent`,textTextColor:e.colorText,textTextHoverColor:e.colorText,textTextActiveColor:e.colorText,textHoverBg:e.colorFillTertiary,defaultColor:e.colorText,defaultBg:e.colorBgContainer,defaultBorderColor:e.colorBorder,defaultBorderColorDisabled:e.colorBorder,defaultHoverBg:e.colorBgContainer,defaultHoverColor:e.colorPrimaryHover,defaultHoverBorderColor:e.colorPrimaryHover,defaultActiveBg:e.colorBgContainer,defaultActiveColor:e.colorPrimaryActive,defaultActiveBorderColor:e.colorPrimaryActive,solidTextColor:s,contentFontSize:t,contentFontSizeSM:n,contentFontSizeLG:r,contentLineHeight:i,contentLineHeightSM:a,contentLineHeightLG:o,paddingBlock:Math.max((e.controlHeight-t*i)/2-e.lineWidth,0),paddingBlockSM:Math.max((e.controlHeightSM-n*a)/2-e.lineWidth,0),paddingBlockLG:Math.max((e.controlHeightLG-r*o)/2-e.lineWidth,0),defaultBgDisabled:l,dashedBgDisabled:u}},Kf=e=>{let{componentCls:t,antCls:n,lineWidth:r}=e,[i,a]=zo(n,`btn`);return{[t]:[{[i(`border-width`)]:r,[i(`border-color`)]:`#000`,[i(`border-color-hover`)]:a(`border-color`),[i(`border-color-active`)]:a(`border-color`),[i(`border-color-disabled`)]:a(`border-color`),[i(`border-style`)]:`solid`,[i(`text-color`)]:`#000`,[i(`text-color-hover`)]:a(`text-color`),[i(`text-color-active`)]:a(`text-color`),[i(`text-color-disabled`)]:a(`text-color`),[i(`bg-color`)]:`#ddd`,[i(`bg-color-hover`)]:a(`bg-color`),[i(`bg-color-active`)]:a(`bg-color`),[i(`bg-color-disabled`)]:e.colorBgContainerDisabled,[i(`bg-color-container`)]:e.colorBgContainer,[i(`shadow`)]:`none`},{border:[a(`border-width`),a(`border-style`),a(`border-color`)].join(` `),color:a(`text-color`),backgroundColor:a(`bg-color`),[`&:not(:disabled):not(${t}-disabled)`]:{"&:hover":{border:[a(`border-width`),a(`border-style`),a(`border-color-hover`)].join(` `),color:a(`text-color-hover`),backgroundColor:a(`bg-color-hover`)},"&:active":{border:[a(`border-width`),a(`border-style`),a(`border-color-active`)].join(` `),color:a(`text-color-active`),backgroundColor:a(`bg-color-active`)}}},{[`&${t}-variant-solid`]:{[i(`solid-bg-color`)]:a(`color-base`),[i(`solid-bg-color-hover`)]:a(`color-hover`),[i(`solid-bg-color-active`)]:a(`color-active`),[i(`border-color`)]:`transparent`,[i(`text-color`)]:e.colorTextLightSolid,[i(`bg-color`)]:a(`solid-bg-color`),[i(`bg-color-hover`)]:a(`solid-bg-color-hover`),[i(`bg-color-active`)]:a(`solid-bg-color-active`),boxShadow:a(`shadow`)},[`&${t}-variant-outlined, &${t}-variant-dashed`]:{[i(`border-color`)]:a(`color-base`),[i(`border-color-hover`)]:a(`color-hover`),[i(`border-color-active`)]:a(`color-active`),[i(`bg-color`)]:a(`bg-color-container`),[i(`text-color`)]:a(`color-base`),[i(`text-color-hover`)]:a(`color-hover`),[i(`text-color-active`)]:a(`color-active`),boxShadow:a(`shadow`)},[`&${t}-variant-dashed`]:{[i(`border-style`)]:`dashed`,[i(`bg-color-disabled`)]:e.dashedBgDisabled},[`&${t}-variant-filled`]:{[i(`border-color`)]:`transparent`,[i(`text-color`)]:a(`color-base`),[i(`bg-color`)]:a(`color-light`),[i(`bg-color-hover`)]:a(`color-light-hover`),[i(`bg-color-active`)]:a(`color-light-active`)},[`&${t}-variant-text, &${t}-variant-link`]:{[i(`border-color`)]:`transparent`,[i(`text-color`)]:a(`color-base`),[i(`text-color-hover`)]:a(`color-hover`),[i(`text-color-active`)]:a(`color-active`),[i(`bg-color`)]:`transparent`,[i(`bg-color-hover`)]:`transparent`,[i(`bg-color-active`)]:`transparent`,[`&:disabled, &${e.componentCls}-disabled`]:{background:`transparent`,borderColor:`transparent`}},[`&${t}-variant-text`]:{[i(`bg-color-hover`)]:a(`color-light`),[i(`bg-color-active`)]:a(`color-light-active`)}},{[`&${t}-variant-link`]:{[i(`color-base`)]:e.colorLink,[i(`color-hover`)]:e.colorLinkHover,[i(`color-active`)]:e.colorLinkActive,[i(`bg-color-hover`)]:e.linkHoverBg},[`&${t}-color-primary`]:{[i(`color-base`)]:e.colorPrimary,[i(`color-hover`)]:e.colorPrimaryHover,[i(`color-active`)]:e.colorPrimaryActive,[i(`color-light`)]:e.colorPrimaryBg,[i(`color-light-hover`)]:e.colorPrimaryBgHover,[i(`color-light-active`)]:e.colorPrimaryBorder,[i(`shadow`)]:e.primaryShadow,[`&${t}-variant-solid`]:{[i(`text-color`)]:e.primaryColor,[i(`text-color-hover`)]:a(`text-color`),[i(`text-color-active`)]:a(`text-color`)}},[`&${t}-color-dangerous`]:{[i(`color-base`)]:e.colorError,[i(`color-hover`)]:e.colorErrorHover,[i(`color-active`)]:e.colorErrorActive,[i(`color-light`)]:e.colorErrorBg,[i(`color-light-hover`)]:e.colorErrorBgFilledHover,[i(`color-light-active`)]:e.colorErrorBgActive,[i(`shadow`)]:e.dangerShadow,[`&${t}-variant-solid`]:{[i(`text-color`)]:e.dangerColor,[i(`text-color-hover`)]:a(`text-color`),[i(`text-color-active`)]:a(`text-color`)}},[`&${t}-color-default`]:{[i(`solid-bg-color`)]:e.colorBgSolid,[i(`solid-bg-color-hover`)]:e.colorBgSolidHover,[i(`solid-bg-color-active`)]:e.colorBgSolidActive,[i(`color-base`)]:e.defaultBorderColor,[i(`color-hover`)]:e.defaultHoverBorderColor,[i(`color-active`)]:e.defaultActiveBorderColor,[i(`color-light`)]:e.colorFillTertiary,[i(`color-light-hover`)]:e.colorFillSecondary,[i(`color-light-active`)]:e.colorFill,[i(`text-color`)]:e.defaultColor,[i(`text-color-hover`)]:e.defaultHoverColor,[i(`text-color-active`)]:e.defaultActiveColor,[i(`shadow`)]:e.defaultShadow,[`&${t}-variant-outlined`]:{[i(`bg-color-disabled`)]:e.defaultBgDisabled},[`&${t}-variant-solid`]:{[i(`text-color`)]:e.solidTextColor,[i(`text-color-hover`)]:a(`text-color`),[i(`text-color-active`)]:a(`text-color`)},[`&${t}-variant-filled, &${t}-variant-text`]:{[i(`text-color-hover`)]:a(`text-color`),[i(`text-color-active`)]:a(`text-color`)},[`&${t}-variant-outlined, &${t}-variant-dashed`]:{[i(`text-color`)]:e.defaultColor,[i(`text-color-hover`)]:e.defaultHoverColor,[i(`text-color-active`)]:e.defaultActiveColor,[i(`bg-color-container`)]:e.defaultBg,[i(`bg-color-hover`)]:e.defaultHoverBg,[i(`bg-color-active`)]:e.defaultActiveBg},[`&${t}-variant-text`]:{[i(`text-color`)]:e.textTextColor,[i(`text-color-hover`)]:e.textTextHoverColor,[i(`text-color-active`)]:e.textTextActiveColor,[i(`bg-color-hover`)]:e.textHoverBg},[`&${t}-background-ghost`]:{[`&${t}-variant-outlined, &${t}-variant-dashed`]:{[i(`text-color`)]:e.defaultGhostColor,[i(`border-color`)]:e.defaultGhostBorderColor}}}},oa.map(n=>{let r=e[`${n}6`],a=e[`${n}1`],o=e[`${n}Hover`],s=e[`${n}2`],c=e[`${n}3`],l=e[`${n}Active`],u=e[`${n}ShadowColor`];return{[`&${t}-color-${n}`]:{[i(`color-base`)]:r,[i(`color-hover`)]:o,[i(`color-active`)]:l,[i(`color-light`)]:a,[i(`color-light-hover`)]:s,[i(`color-light-active`)]:c,[i(`shadow`)]:u}}}),{[`&:disabled, &${e.componentCls}-disabled`]:{cursor:`not-allowed`,borderColor:e.colorBorderDisabled,background:a(`bg-color-disabled`),color:e.colorTextDisabled,boxShadow:`none`}},{[`&${t}-background-ghost`]:{[i(`bg-color`)]:e.ghostBg,[i(`bg-color-hover`)]:e.ghostBg,[i(`bg-color-active`)]:e.ghostBg,[i(`shadow`)]:`none`,[`&${t}-variant-outlined, &${t}-variant-dashed`]:{[i(`bg-color-hover`)]:e.ghostBg,[i(`bg-color-active`)]:e.ghostBg}}}]}},qf=e=>{let{componentCls:t,iconCls:n,fontWeight:r,opacityLoading:i,motionDurationSlow:a,motionEaseInOut:o,iconGap:s,calc:c}=e;return{[t]:{outline:`none`,position:`relative`,display:`inline-flex`,gap:s,alignItems:`center`,justifyContent:`center`,fontWeight:r,whiteSpace:`nowrap`,textAlign:`center`,backgroundImage:`none`,cursor:`pointer`,transition:`all ${e.motionDurationMid} ${e.motionEaseInOut}`,userSelect:`none`,touchAction:`manipulation`,...yf(),"&:disabled > *":{pointerEvents:`none`},[`${t}-icon > svg`]:Oo(),"> a":{color:`currentColor`},"&:not(:disabled)":jo(e),[`&${t}-two-chinese-chars::first-letter`]:{letterSpacing:`0.34em`},[`&${t}-two-chinese-chars > *:not(${n})`]:{marginInlineEnd:`-0.34em`,letterSpacing:`0.34em`},[`&${t}-icon-only`]:{paddingInline:0,[`&${t}-compact-item`]:{flex:`none`}},[`&${t}-loading`]:{opacity:i,cursor:`default`},[`${t}-loading-icon`]:{transition:[`width`,`opacity`,`margin`].map(e=>`${e} ${a} ${o}`).join(`,`)},[`&:not(${t}-icon-end)`]:{[`${t}-loading-icon-motion`]:{"&-appear-start, &-enter-start":{marginInlineEnd:c(s).mul(-1).equal()},"&-appear-active, &-enter-active":{marginInlineEnd:0},"&-leave-start":{marginInlineEnd:0},"&-leave-active":{marginInlineEnd:c(s).mul(-1).equal()}}},"&-icon-end":{flexDirection:`row-reverse`,[`${t}-loading-icon-motion`]:{"&-appear-start, &-enter-start":{marginInlineStart:c(s).mul(-1).equal()},"&-appear-active, &-enter-active":{marginInlineStart:0},"&-leave-start":{marginInlineStart:0},"&-leave-active":{marginInlineStart:c(s).mul(-1).equal()}}}}}},Jf=e=>({minWidth:e.controlHeight,paddingInline:0,borderRadius:`50%`}),Yf=(e,t=``)=>{let{componentCls:n,controlHeight:r,fontSize:i,borderRadius:a,buttonPaddingHorizontal:o,iconCls:s,buttonPaddingVertical:c,buttonIconOnlyFontSize:l}=e;return[{[t]:{fontSize:i,height:r,padding:`${q(c)} ${q(o)}`,borderRadius:a,[`&${n}-icon-only`]:{width:r,[s]:{fontSize:l}}}},{[`${n}${n}-circle${t}`]:Jf(e)},{[`${n}${n}-round${t}`]:{borderRadius:e.controlHeight,[`&:not(${n}-icon-only)`]:{paddingInline:e.buttonPaddingHorizontal}}}]},Xf=e=>Yf(Yi(e,{fontSize:e.contentFontSize}),e.componentCls),Zf=e=>Yf(Yi(e,{controlHeight:e.controlHeightSM,fontSize:e.contentFontSizeSM,padding:e.paddingXS,buttonPaddingHorizontal:e.paddingInlineSM,buttonPaddingVertical:0,borderRadius:e.borderRadiusSM,buttonIconOnlyFontSize:e.onlyIconSizeSM}),`${e.componentCls}-sm`),Qf=e=>Yf(Yi(e,{controlHeight:e.controlHeightLG,fontSize:e.contentFontSizeLG,buttonPaddingHorizontal:e.paddingInlineLG,buttonPaddingVertical:0,borderRadius:e.borderRadiusLG,buttonIconOnlyFontSize:e.onlyIconSizeLG}),`${e.componentCls}-lg`),$f=e=>{let{componentCls:t}=e;return{[t]:{[`&${t}-block`]:{width:`100%`}}}},ep=Io(`Button`,e=>{let t=Wf(e);return[qf(t),Xf(t),Zf(t),Qf(t),$f(t),Kf(t),Ff(t)]},Gf,{unitless:{fontWeight:!0,contentLineHeight:!0,contentLineHeightSM:!0,contentLineHeightLG:!0}});function tp(e,t,n,r){let{focusElCls:i,focus:a,borderElCls:o}=n,s=o?`> *`:``,c=[`hover`,a?`focus`:null,`active`].filter(Boolean).map(e=>`&:${e} ${s}`).join(`,`);return{[`&-item:not(${t}-last-item)`]:{marginInlineEnd:e.calc(e.lineWidth).mul(-1).equal()},[`&-item:not(${r}-status-success)`]:{zIndex:2},"&-item":{[c]:{zIndex:3},...i?{[`&${i}`]:{zIndex:3}}:{},[`&[disabled] ${s}`]:{zIndex:0}}}}function np(e,t,n){let{borderElCls:r}=n,i=r?`> ${r}`:``;return{[`&-item:not(${t}-first-item):not(${t}-last-item) ${i}`]:{borderRadius:0},[`&-item:not(${t}-last-item)${t}-first-item`]:{[`& ${i}, &${e}-sm ${i}, &${e}-lg ${i}`]:{borderStartEndRadius:0,borderEndEndRadius:0}},[`&-item:not(${t}-first-item)${t}-last-item`]:{[`& ${i}, &${e}-sm ${i}, &${e}-lg ${i}`]:{borderStartStartRadius:0,borderEndStartRadius:0}}}}function rp(e,t={focus:!0}){let{componentCls:n}=e,{componentCls:r}=t,i=r||n,a=`${i}-compact`;return{[a]:{...tp(e,a,t,i),...np(i,a,t)}}}function ip(e,t,n){return{[`&-item:not(${t}-last-item)`]:{marginBottom:e.calc(e.lineWidth).mul(-1).equal()},[`&-item:not(${n}-status-success)`]:{zIndex:2},"&-item":{"&:hover,&:focus,&:active":{zIndex:3},"&[disabled]":{zIndex:0}}}}function ap(e,t){return{[`&-item:not(${t}-first-item):not(${t}-last-item)`]:{borderRadius:0},[`&-item${t}-first-item:not(${t}-last-item)`]:{[`&, &${e}-sm, &${e}-lg`]:{borderEndEndRadius:0,borderEndStartRadius:0}},[`&-item${t}-last-item:not(${t}-first-item)`]:{[`&, &${e}-sm, &${e}-lg`]:{borderStartStartRadius:0,borderStartEndRadius:0}}}}function op(e){let t=`${e.componentCls}-compact-vertical`;return{[t]:{...ip(e,t,e.componentCls),...ap(e.componentCls,t)}}}var sp=e=>{let{antCls:t,componentCls:n,lineWidth:r,calc:i,colorBgContainer:a}=e,o=`${n}-variant-solid:not([disabled])`,s=i(r).mul(-1).equal(),[c,l]=zo(t,`btn`),u=e=>({[`${n}-compact${e?`-vertical`:``}-item`]:{[c(`compact-connect-border-color`)]:l(`bg-color-hover`),[`&${o}`]:{transition:`none`,[`& + ${o}:before`]:[{position:`absolute`,backgroundColor:l(`compact-connect-border-color`),content:`""`},e?{top:s,insetInline:s,height:r}:{insetBlock:s,insetInlineStart:s,width:r}],"&:hover:before":{display:`none`}}}});return[u(),u(!0),{[`${o}${n}-color-default`]:{[c(`compact-connect-border-color`)]:`color-mix(in srgb, ${l(`bg-color-hover`)} 75%, ${a})`}}]},cp=Ro([`Button`,`compact`],e=>{let t=Wf(e);return[rp(t),op(t),sp(t)]},Gf);function lp(e){if(typeof e==`object`&&e){let t=e?.delay;return t=!Number.isNaN(t)&&typeof t==`number`?t:0,{loading:t<=0,delay:t}}return{loading:!!e,delay:0}}var up={default:[`default`,`outlined`],primary:[`primary`,`solid`],dashed:[`default`,`dashed`],link:[`link`,`link`],text:[`default`,`text`]},dp=m.forwardRef((e,t)=>{let{_skipSemantic:n,loading:r=!1,prefixCls:i,color:a,variant:o,type:s,danger:c=!1,shape:l,size:u,disabled:d,className:f,rootClassName:p,children:h,icon:g,iconPosition:_,iconPlacement:v,ghost:y=!1,block:b=!1,htmlType:x=`button`,classNames:S,styles:C,style:w,autoInsertSpace:T,autoFocus:E,...D}=e,O=nt(h),k=s||`default`,{getPrefixCls:A,direction:j,autoInsertSpace:M,className:N,style:P,classNames:F,styles:I,loadingIcon:L,shape:ee,color:R,variant:z}=Ht(`button`),B=l||ee||`default`,[V,te]=(0,m.useMemo)(()=>{if(a&&o)return[a,o];if(s||c){let e=up[k]||[];return c?[`danger`,e[1]]:e}return R&&z?[R,z]:[`default`,`outlined`]},[a,o,s,c,R,z,k]),[ne,re]=(0,m.useMemo)(()=>y&&te===`solid`?[V,`outlined`]:[V,te],[V,te,y]),ie=ne===`danger`,ae=ie?`dangerous`:ne,oe=T??M??!0,H=A(`btn`,i),[se,ce]=ep(H),le=(0,m.useContext)(Lu),U=d??le,ue=(0,m.useContext)($d),de=(0,m.useMemo)(()=>lp(r),[r]),[fe,pe]=(0,m.useState)(de.loading),[me,he]=(0,m.useState)(!1),ge=(0,m.useRef)(null),_e=Ne(t,ge),W=O.length===1&&!g&&!of(re),ve=(0,m.useRef)(!0);m.useEffect(()=>(ve.current=!1,()=>{ve.current=!0}),[]),G(()=>{let e=null;de.delay>0?e=setTimeout(()=>{e=null,pe(!0)},de.delay):pe(de.loading);function t(){e&&=(clearTimeout(e),null)}return t},[de.delay,de.loading]),(0,m.useEffect)(()=>{if(!ge.current||!oe)return;let e=ge.current.textContent||``;W&&nf(e)?me||he(!0):me&&he(!1)}),(0,m.useEffect)(()=>{E&&ge.current&&ge.current.focus()},[]);let ye=m.useCallback(t=>{if(fe||U){t.preventDefault();return}e.onClick?.((`href`in e,t))},[e.onClick,fe,U]),{compactSize:be,compactItemClassnames:xe}=Yd(H,j),Se=Kd(e=>u??be??ue??e),Ce=fe?`loading`:g,we=v??_??`start`,Te=tt(D,[`navigate`]),Ee={...e,type:k,color:ne,variant:re,danger:ie,shape:B,size:Se,disabled:U,loading:fe,iconPlacement:we},[De,Oe]=cl([n?void 0:F,S],[n?void 0:I,C],{props:Ee}),ke=K(H,se,ce,{[`${H}-${B}`]:B!==`default`&&B!==`square`&&B,[`${H}-${k}`]:k,[`${H}-dangerous`]:c,[`${H}-color-${ae}`]:ae,[`${H}-variant-${re}`]:re,[`${H}-lg`]:Se===`large`,[`${H}-sm`]:Se===`small`,[`${H}-icon-only`]:!h&&h!==0&&!!Ce,[`${H}-background-ghost`]:y&&!of(re),[`${H}-loading`]:fe,[`${H}-two-chinese-chars`]:me&&oe&&!fe,[`${H}-block`]:b,[`${H}-rtl`]:j===`rtl`,[`${H}-icon-end`]:we===`end`},xe,f,p,N,De.root),Ae={...Oe.root,...P,...w},je={className:De.icon,style:Oe.icon},Me=e=>m.createElement(lf,{prefixCls:H,...je},e),Pe=m.createElement(pf,{existIcon:!!g,prefixCls:H,loading:fe,mount:ve.current,...je}),Fe=r&&typeof r==`object`&&r.icon||L,Ie;Ie=g&&!fe?Me(g):r&&Fe?Me(Fe):Pe;let Le=Gc(h)?cf(h,W&&oe,Oe.content,De.content):null;if(Te.href!==void 0)return m.createElement(`a`,{...Te,className:K(ke,{[`${H}-disabled`]:U}),href:U?void 0:Te.href,style:Ae,onClick:ye,ref:_e,tabIndex:U?-1:0,"aria-disabled":U},Ie,Le);let Re=m.createElement(`button`,{...D,type:x,className:ke,style:Ae,onClick:ye,disabled:U,ref:_e},Ie,Le,xe&&m.createElement(cp,{prefixCls:H}));return of(re)||(Re=m.createElement(Gd,{component:`Button`,disabled:fe},Re)),Re});dp.Group=ef,dp.__ANT_BUTTON=!0;var fp=e=>typeof e?.then==`function`,pp=e=>{let{type:t,children:n,prefixCls:r,buttonProps:i,close:a,autoFocus:o,emitEvent:s,isSilent:c,quitOnNullishReturnValue:l,actionFn:u}=e,d=m.useRef(!1),f=m.useRef(null),[p,h]=be(!1),g=(...e)=>{a?.(...e)};m.useEffect(()=>{let e=null;return o&&(e=setTimeout(()=>{f.current?.focus({preventScroll:!0})})),()=>{e&&clearTimeout(e)}},[o]);let _=e=>{fp(e)&&(h(!0),e.then((...e)=>{h(!1,!0),g.apply(void 0,e),d.current=!1},e=>{if(h(!1,!0),d.current=!1,!c?.())return Promise.reject(e)}))},v=e=>{if(d.current)return;if(d.current=!0,!u){g();return}let t;if(s){if(t=u(e),l&&!fp(t)){d.current=!1,g(e);return}}else if(u.length)t=u(a),d.current=!1;else if(t=u(),!fp(t)){g();return}_(t)};return m.createElement(dp,{...rf(t),onClick:v,loading:p,prefixCls:r,...i,ref:f},n)},mp=m.createContext({}),{Provider:hp}=mp,gp=()=>{let{autoFocusButton:e,cancelButtonProps:t,cancelTextLocale:n,isSilent:r,mergedOkCancel:i,rootPrefixCls:a,close:o,onCancel:s,onConfirm:c,onClose:l}=(0,m.useContext)(mp);return i?m.createElement(pp,{isSilent:r,actionFn:s,close:(...e)=>{o?.(...e),c?.(!1),l?.()},autoFocus:e===`cancel`,buttonProps:t,prefixCls:`${a}-btn`},n):null},_p=()=>{let{autoFocusButton:e,close:t,isSilent:n,okButtonProps:r,rootPrefixCls:i,okTextLocale:a,okType:o,onConfirm:s,onOk:c,onClose:l}=(0,m.useContext)(mp);return m.createElement(pp,{isSilent:n,type:o||`primary`,actionFn:c,close:(...e)=>{t?.(...e),s?.(!0),l?.()},autoFocus:e===`ok`,buttonProps:r,prefixCls:`${i}-btn`},a)},vp=m.createContext({});function yp(e,t,n){let r=t;return!r&&n&&(r=`${e}-${n}`),r}function bp(e,t){let n=e[`page${t?`Y`:`X`}Offset`],r=`scroll${t?`Top`:`Left`}`;if(typeof n!=`number`){let t=e.document;n=t.documentElement[r],typeof n!=`number`&&(n=t.body[r])}return n}function xp(e){let t=e.getBoundingClientRect(),n={left:t.left,top:t.top},r=e.ownerDocument,i=r.defaultView||r.parentWindow;return n.left+=bp(i),n.top+=bp(i,!0),n}function Sp(e,t=!1){if(ou(e)){let n=e.nodeName.toLowerCase(),r=[`input`,`select`,`textarea`,`button`].includes(n)||e.isContentEditable||n===`a`&&!!e.getAttribute(`href`),i=e.getAttribute(`tabindex`),a=Number(i),o=null;return i&&!Number.isNaN(a)?o=a:r&&o===null&&(o=0),r&&e.disabled&&(o=null),o!==null&&(o>=0||t&&o<0)}return!1}function Cp(e,t=!1){let n=[...e.querySelectorAll(`*`)].filter(e=>Sp(e,t));return Sp(e,t)&&n.unshift(e),n}function wp(e,t){if(!e)return;e.focus(t);let{cursor:n}=t||{};if(n&&(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement)){let t=e.value.length;switch(n){case`start`:e.setSelectionRange(0,0);break;case`end`:e.setSelectionRange(t,t);break;default:e.setSelectionRange(0,t)}}}var Tp=null,Ep=[],Dp=new Map,Op=new Map;function kp(){return Ep[Ep.length-1]}function Ap(e){let t=kp();if(e&&t){let n;for(let[e,r]of Dp.entries())if(r===t){n=e;break}let r=Op.get(n);return!!r&&(r===e||r.contains(e))}return!1}function jp(e){let{activeElement:t}=document;return e===t||e.contains(t)}function Mp(){let e=kp(),{activeElement:t}=document;if(!Ap(t))if(e&&!jp(e)){let t=Cp(e);(t.includes(Tp)?Tp:t[0])?.focus({preventScroll:!0})}else Tp=t}function Np(e){if(e.key===`Tab`){let{activeElement:t}=document,n=Cp(kp()),r=n[n.length-1];e.shiftKey&&t===n[0]?Tp=r:!e.shiftKey&&t===r&&(Tp=n[0])}}function Pp(e,t){return e&&(Dp.set(t,e),Ep=Ep.filter(t=>t!==e),Ep.push(e),window.addEventListener(`focusin`,Mp),window.addEventListener(`keydown`,Np,!0),Mp()),()=>{Tp=null,Ep=Ep.filter(t=>t!==e),Dp.delete(t),Op.delete(t),Ep.length===0&&(window.removeEventListener(`focusin`,Mp),window.removeEventListener(`keydown`,Np,!0))}}function Fp(e,t){let n=Ll();return(0,m.useEffect)(()=>{if(e){let e=t();if(e)return Pp(e,n)}},[e,n]),[e=>{e&&Op.set(n,e)}]}var Ip=m.memo(({children:e})=>e,(e,{shouldUpdate:t})=>!t);function Lp(){return Lp=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{prefixCls:n,className:r,style:i,title:a,ariaId:o,footer:s,closable:c,closeIcon:l,onClose:u,children:d,bodyStyle:f,bodyProps:p,modalRender:h,onMouseDown:g,onMouseUp:_,holderRef:v,visible:y,forceRender:b,width:x,height:S,classNames:C,styles:w,isFixedPos:T,focusTrap:E}=e,{panel:D}=m.useContext(vp),O=(0,m.useRef)(null),k=Ne(v,D,O),[A]=Fp(y&&T&&E!==!1,()=>O.current);m.useImperativeHandle(t,()=>({focus:()=>{O.current?.focus({preventScroll:!0})}}));let j={};x!==void 0&&(j.width=x),S!==void 0&&(j.height=S);let M=s?m.createElement(`div`,{className:K(`${n}-footer`,C?.footer),style:{...w?.footer}},s):null,N=a?m.createElement(`div`,{className:K(`${n}-header`,C?.header),style:{...w?.header}},m.createElement(`div`,{className:K(`${n}-title`,C?.title),id:o,style:{...w?.title}},a)):null,P=(0,m.useMemo)(()=>typeof c==`object`&&c?c:c?{closeIcon:l??m.createElement(`span`,{className:`${n}-close-x`})}:{},[c,l,n]),F=bc(P,!0),I=typeof c==`object`&&c.disabled,L=c?m.createElement(`button`,Lp({type:`button`,onClick:u,"aria-label":`Close`},F,{className:`${n}-close`,disabled:I}),P.closeIcon):null,ee=m.createElement(`div`,{className:K(`${n}-container`,C?.container),style:w?.container},L,N,m.createElement(`div`,Lp({className:K(`${n}-body`,C?.body),style:{...f,...w?.body}},p),d),M);return m.createElement(`div`,{key:`dialog-element`,role:`dialog`,"aria-labelledby":a?o:null,"aria-modal":`true`,ref:k,style:{...i,...j},className:K(n,r),onMouseDown:g,onMouseUp:_,tabIndex:-1,onFocus:e=>{A(e.target)}},m.createElement(Ip,{shouldUpdate:y||b},h?h(ee):ee))});function zp(){return zp=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{prefixCls:n,title:r,style:i,className:a,visible:o,forceRender:s,destroyOnHidden:c,motionName:l,ariaId:u,onVisibleChanged:d,mousePosition:f}=e,p=(0,m.useRef)(null),h=(0,m.useRef)(null);m.useImperativeHandle(t,()=>({...h.current,inMotion:p.current.inMotion,enableMotion:p.current.enableMotion}));let[g,_]=m.useState(),v={};g&&(v.transformOrigin=g);function y(){if(!p.current?.nativeElement)return;let e=xp(p.current.nativeElement);_(f&&(f.x||f.y)?`${f.x-e.left}px ${f.y-e.top}px`:``)}return m.createElement(hc,{visible:o,onVisibleChanged:d,onAppearPrepare:y,onEnterPrepare:y,forceRender:s,motionName:l,removeOnLeave:c,ref:p},({className:t,style:o},s)=>m.createElement(Rp,zp({},e,{ref:h,title:r,ariaId:u,prefixCls:n,holderRef:s,style:{...o,...i,...v},className:K(a,t)})))});function Vp(){return Vp=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{prefixCls:t,style:n,visible:r,maskProps:i,motionName:a,className:o}=e;return m.createElement(hc,{key:`mask`,visible:r,motionName:a,leavedClassName:`${t}-mask-hidden`},({className:e,style:r},a)=>m.createElement(`div`,Vp({ref:a,style:{...r,...n},className:K(`${t}-mask`,e,o)},i)))};function Up(){return Up=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{prefixCls:t=`rc-dialog`,zIndex:n,visible:r=!1,focusTriggerAfterClose:i=!0,wrapStyle:a,wrapClassName:o,wrapProps:s,onClose:c,afterOpenChange:l,afterClose:u,transitionName:d,animation:f,closable:p=!0,mask:h=!0,maskTransitionName:g,maskAnimation:_,maskClosable:v=!0,maskStyle:y,maskProps:b,rootClassName:x,rootStyle:S,classNames:C,styles:w}=e,T=(0,m.useRef)(null),E=(0,m.useRef)(null),D=(0,m.useRef)(null),[O,k]=m.useState(r),[A,j]=m.useState(!1),M=Ll();function N(){Wt(E.current,document.activeElement)||(T.current=document.activeElement)}function P(){Wt(E.current,document.activeElement)||D.current?.focus()}function F(){if(k(!1),h&&T.current&&i){try{T.current.focus({preventScroll:!0})}catch{}T.current=null}O&&u?.()}function I(e){e?P():F(),l?.(e)}function L(e){c?.(e)}let ee=(0,m.useRef)(!1),R=null;v&&(R=e=>{E.current===e.target&&ee.current&&L(e)});function z(e){ee.current=e.target===E.current}(0,m.useEffect)(()=>{r?(ee.current=!1,k(!0),N(),E.current&&j(getComputedStyle(E.current).position===`fixed`)):O&&D.current.enableMotion()&&!D.current.inMotion()&&F()},[r]);let B={zIndex:n,...a,...w?.wrapper,display:O?null:`none`};return m.createElement(`div`,Up({className:K(`${t}-root`,x),style:S},bc(e,{data:!0})),m.createElement(Hp,{prefixCls:t,visible:h&&r,motionName:yp(t,g,_),style:{zIndex:n,...y,...w?.mask},maskProps:b,className:C?.mask}),m.createElement(`div`,Up({className:K(`${t}-wrap`,o,C?.wrapper),ref:E,onClick:R,onMouseDown:z,style:B},s),m.createElement(Bp,Up({},e,{isFixedPos:A,ref:D,closable:p,ariaId:M,prefixCls:t,visible:r&&O,onClose:L,onVisibleChanged:I,motionName:yp(t,d,f)}))))};function Gp(){return Gp=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{visible:t,getContainer:n,forceRender:r,destroyOnHidden:i=!1,afterClose:a,closable:o,panelRef:s,keyboard:c=!0,onClose:l}=e,[u,d]=m.useState(t),f=m.useMemo(()=>({panel:s}),[s]);return m.useEffect(()=>{t&&d(!0)},[t]),!r&&i&&!u?null:m.createElement(vp.Provider,{value:f},m.createElement(Jl,{open:t||r||u,onEsc:({top:e,event:t})=>{if(e&&c){t.stopPropagation(),l?.(t);return}},autoDestroy:!1,getContainer:n,autoLock:t||u},m.createElement(Wp,Gp({},e,{destroyOnHidden:i,afterClose:()=>{let{afterClose:e}=(o&&typeof o==`object`?o:{})||{};e?.(),a?.(),d(!1)}}))))},qp=`RC_FORM_INTERNAL_HOOKS`,Jp=()=>{$e(!1,`Can not find FormContext. Please make sure you wrap Field under Form.`)},Yp=m.createContext({getFieldValue:Jp,getFieldsValue:Jp,getFieldError:Jp,getFieldWarning:Jp,getFieldsError:Jp,isFieldsTouched:Jp,isFieldTouched:Jp,isFieldValidating:Jp,isFieldsValidating:Jp,resetFields:Jp,setFields:Jp,setFieldValue:Jp,setFieldsValue:Jp,validateFields:Jp,submit:Jp,getInternalHooks:()=>(Jp(),{dispatch:Jp,initEntityValue:Jp,registerField:Jp,useSubscribe:Jp,setInitialValues:Jp,destroyForm:Jp,setCallbacks:Jp,registerWatch:Jp,getFields:Jp,setValidateMessages:Jp,setPreserve:Jp,getInitialValue:Jp})}),Xp=m.createContext(null);function Zp(e){return e==null?[]:Array.isArray(e)?e:[e]}function Qp(e){return e&&!!e._init}function $p(){return{default:`Validation error on field %s`,required:`%s is required`,enum:`%s must be one of %s`,whitespace:`%s cannot be empty`,date:{format:`%s date %s is invalid for format %s`,parse:`%s date could not be parsed, %s is invalid `,invalid:`%s date %s is invalid`},types:{string:`%s is not a %s`,method:`%s is not a %s (function)`,array:`%s is not an %s`,object:`%s is not an %s`,number:`%s is not a %s`,date:`%s is not a %s`,boolean:`%s is not a %s`,integer:`%s is not an %s`,float:`%s is not a %s`,regexp:`%s is not a valid %s`,email:`%s is not a valid %s`,tel:`%s is not a valid %s`,url:`%s is not a valid %s`,hex:`%s is not a valid %s`},string:{len:`%s must be exactly %s characters`,min:`%s must be at least %s characters`,max:`%s cannot be longer than %s characters`,range:`%s must be between %s and %s characters`},number:{len:`%s must equal %s`,min:`%s cannot be less than %s`,max:`%s cannot be greater than %s`,range:`%s must be between %s and %s`},array:{len:`%s must be exactly %s in length`,min:`%s cannot be less than %s in length`,max:`%s cannot be greater than %s in length`,range:`%s must be between %s and %s in length`},pattern:{mismatch:`%s value %s does not match pattern %s`},clone:function(){var e=JSON.parse(JSON.stringify(this));return e.clone=this.clone,e}}}var em=$p();function tm(e){try{return Function.toString.call(e).indexOf(`[native code]`)!==-1}catch{return typeof e==`function`}}function nm(e,t,n){if(Fi())return Reflect.construct.apply(null,arguments);var r=[null];r.push.apply(r,t);var i=new(e.bind.apply(e,r));return n&&Mi(i,n.prototype),i}function rm(e){var t=typeof Map==`function`?new Map:void 0;return rm=function(e){if(e===null||!tm(e))return e;if(typeof e!=`function`)throw TypeError(`Super expression must either be null or a function`);if(t!==void 0){if(t.has(e))return t.get(e);t.set(e,n)}function n(){return nm(e,arguments,Pi(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),Mi(n,e)},rm(e)}var im=/%[sdj%]/g,am=function(){};function om(e){if(!e||!e.length)return null;var t={};return e.forEach(function(e){var n=e.field;t[n]=t[n]||[],t[n].push(e)}),t}function sm(e){var t=[...arguments].slice(1),n=0,r=t.length;return typeof e==`function`?e.apply(null,t):typeof e==`string`?e.replace(im,function(e){if(e===`%%`)return`%`;if(n>=r)return e;switch(e){case`%s`:return String(t[n++]);case`%d`:return Number(t[n++]);case`%j`:try{return JSON.stringify(t[n++])}catch{return`[Circular]`}break;default:return e}}):e}function cm(e){return e===`string`||e===`url`||e===`hex`||e===`email`||e===`date`||e===`pattern`||e===`tel`}function lm(e,t){return!!(e==null||t===`array`&&Array.isArray(e)&&!e.length||cm(t)&&typeof e==`string`&&!e)}function um(e,t,n){var r=[],i=0,a=e.length;function o(e){r.push.apply(r,At(e||[])),i++,i===a&&n(r)}e.forEach(function(e){t(e,o)})}function dm(e,t,n){var r=0,i=e.length;function a(o){if(o&&o.length){n(o);return}var s=r;r+=1,se.max?r.push(sm(i.messages[u].max,e.fullField,e.max)):o&&s&&(le.max)&&r.push(sm(i.messages[u].range,e.fullField,e.min,e.max))},Cm=function(e,t,n,r,i,a){e.required&&(!n.hasOwnProperty(e.field)||lm(t,a||e.type))&&r.push(sm(i.messages.required,e.fullField))},wm,Tm=(function(){if(wm)return wm;var e=`[a-fA-F\\d:]`,t=function(t){return t&&t.includeBoundaries?`(?:(?<=\\s|^)(?=${e})|(?<=${e})(?=\\s|\$))`:``},n=`(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}`,r=`[a-fA-F\\d]{1,4}`,i=`(?:${[`(?:${r}:){7}(?:${r}|:)`,`(?:${r}:){6}(?:${n}|:${r}|:)`,`(?:${r}:){5}(?::${n}|(?::${r}){1,2}|:)`,`(?:${r}:){4}(?:(?::${r}){0,1}:${n}|(?::${r}){1,3}|:)`,`(?:${r}:){3}(?:(?::${r}){0,2}:${n}|(?::${r}){1,4}|:)`,`(?:${r}:){2}(?:(?::${r}){0,3}:${n}|(?::${r}){1,5}|:)`,`(?:${r}:){1}(?:(?::${r}){0,4}:${n}|(?::${r}){1,6}|:)`,`(?::(?:(?::${r}){0,5}:${n}|(?::${r}){1,7}|:))`].join(`|`)})(?:%[0-9a-zA-Z]{1,})?`,a=RegExp(`(?:^${n}\$)|(?:^${i}\$)`),o=RegExp(`^${n}\$`),s=RegExp(`^${i}\$`),c=function(e){return e&&e.exact?a:RegExp(`(?:${t(e)}${n}${t(e)})|(?:${t(e)}${i}${t(e)})`,`g`)};c.v4=function(e){return e&&e.exact?o:RegExp(`${t(e)}${n}${t(e)}`,`g`)},c.v6=function(e){return e&&e.exact?s:RegExp(`${t(e)}${i}${t(e)}`,`g`)};var l=`(?:(?:(?:[a-z]+:)?//)|www\\.)(?:\\S+(?::\\S*)?@)?(?:localhost|${c.v4().source}|${c.v6().source}|(?:(?:[a-z\\u00a1-\\uffff0-9][-_]*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:[/?#][^\\s"]*)?`;return wm=RegExp(`(?:^${l}\$)`,`i`),wm}),Em={email:/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+\.)+[a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]{2,}))$/,tel:/^(\+[0-9]{1,3}[-\s\u2011]?)?(\([0-9]{1,4}\)[-\s\u2011]?)?([0-9]+[-\s\u2011]?)*[0-9]+$/,hex:/^#?([a-f0-9]{6}|[a-f0-9]{3})$/i},Dm={integer:function(e){return Dm.number(e)&&parseInt(e,10)===e},float:function(e){return Dm.number(e)&&!Dm.integer(e)},array:function(e){return Array.isArray(e)},regexp:function(e){if(e instanceof RegExp)return!0;try{return!!new RegExp(e)}catch{return!1}},date:function(e){return typeof e.getTime==`function`&&typeof e.getMonth==`function`&&typeof e.getYear==`function`&&!isNaN(e.getTime())},number:function(e){return isNaN(e)?!1:typeof e==`number`},object:function(e){return vi(e)===`object`&&!Dm.array(e)},method:function(e){return typeof e==`function`},email:function(e){return typeof e==`string`&&e.length<=320&&!!e.match(Em.email)},tel:function(e){return typeof e==`string`&&e.length<=32&&!!e.match(Em.tel)},url:function(e){return typeof e==`string`&&e.length<=2048&&!!e.match(Tm())},hex:function(e){return typeof e==`string`&&!!e.match(Em.hex)}},Om={required:Cm,whitespace:function(e,t,n,r,i){(/^\s+$/.test(t)||t===``)&&r.push(sm(i.messages.whitespace,e.fullField))},type:function(e,t,n,r,i){if(e.required&&t===void 0){Cm(e,t,n,r,i);return}var a=[`integer`,`float`,`array`,`regexp`,`object`,`method`,`email`,`tel`,`number`,`date`,`url`,`hex`],o=e.type;a.indexOf(o)>-1?Dm[o](t)||r.push(sm(i.messages.types[o],e.fullField,e.type)):o&&vi(t)!==e.type&&r.push(sm(i.messages.types[o],e.fullField,e.type))},range:Sm,enum:bm,pattern:xm},km=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(lm(t)&&!e.required)return n();Om.required(e,t,r,a,i)}n(a)},Am=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(t==null&&!e.required)return n();Om.required(e,t,r,a,i,`array`),t!=null&&(Om.type(e,t,r,a,i),Om.range(e,t,r,a,i))}n(a)},jm=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(lm(t)&&!e.required)return n();Om.required(e,t,r,a,i),t!==void 0&&Om.type(e,t,r,a,i)}n(a)},Mm=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(lm(t,`date`)&&!e.required)return n();if(Om.required(e,t,r,a,i),!lm(t,`date`)){var o=t instanceof Date?t:new Date(t);Om.type(e,o,r,a,i),o&&Om.range(e,o.getTime(),r,a,i)}}n(a)},Nm=`enum`,Pm=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(lm(t)&&!e.required)return n();Om.required(e,t,r,a,i),t!==void 0&&Om[Nm](e,t,r,a,i)}n(a)},Fm=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(lm(t)&&!e.required)return n();Om.required(e,t,r,a,i),t!==void 0&&(Om.type(e,t,r,a,i),Om.range(e,t,r,a,i))}n(a)},Im=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(lm(t)&&!e.required)return n();Om.required(e,t,r,a,i),t!==void 0&&(Om.type(e,t,r,a,i),Om.range(e,t,r,a,i))}n(a)},Lm=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(lm(t)&&!e.required)return n();Om.required(e,t,r,a,i),t!==void 0&&Om.type(e,t,r,a,i)}n(a)},Rm=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(t===``&&(t=void 0),lm(t)&&!e.required)return n();Om.required(e,t,r,a,i),t!==void 0&&(Om.type(e,t,r,a,i),Om.range(e,t,r,a,i))}n(a)},zm=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(lm(t)&&!e.required)return n();Om.required(e,t,r,a,i),t!==void 0&&Om.type(e,t,r,a,i)}n(a)},Bm=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(lm(t,`string`)&&!e.required)return n();Om.required(e,t,r,a,i),lm(t,`string`)||Om.pattern(e,t,r,a,i)}n(a)},Vm=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(lm(t)&&!e.required)return n();Om.required(e,t,r,a,i),lm(t)||Om.type(e,t,r,a,i)}n(a)},Hm=function(e,t,n,r,i){var a=[],o=Array.isArray(t)?`array`:vi(t);Om.required(e,t,r,a,i,o),n(a)},Um=function(e,t,n,r,i){var a=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(lm(t,`string`)&&!e.required)return n();Om.required(e,t,r,a,i,`string`),lm(t,`string`)||(Om.type(e,t,r,a,i),Om.range(e,t,r,a,i),Om.pattern(e,t,r,a,i),e.whitespace===!0&&Om.whitespace(e,t,r,a,i))}n(a)},Wm=function(e,t,n,r,i){var a=e.type,o=[];if(e.required||!e.required&&r.hasOwnProperty(e.field)){if(lm(t,a)&&!e.required)return n();Om.required(e,t,r,o,i,a),lm(t,a)||Om.type(e,t,r,o,i)}n(o)},Gm={string:Um,method:Lm,number:Rm,boolean:jm,regexp:Vm,integer:Im,float:Fm,array:Am,object:zm,enum:Pm,pattern:Bm,date:Mm,url:Wm,hex:Wm,email:Wm,tel:Wm,required:Hm,any:km},Km=function(){function e(t){Oi(this,e),Ti(this,`rules`,null),Ti(this,`_messages`,em),this.define(t)}return Ai(e,[{key:`define`,value:function(e){var t=this;if(!e)throw Error(`Cannot configure a schema with no rules`);if(vi(e)!==`object`||Array.isArray(e))throw Error(`Rules must be an object`);this.rules={},Object.keys(e).forEach(function(n){var r=e[n];t.rules[n]=Array.isArray(r)?r:[r]})}},{key:`messages`,value:function(e){return e&&(this._messages=vm($p(),e)),this._messages}},{key:`validate`,value:function(t){var n=this,r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},i=arguments.length>2&&arguments[2]!==void 0?arguments[2]:function(){},a=t,o=r,s=i;if(typeof o==`function`&&(s=o,o={}),!this.rules||Object.keys(this.rules).length===0)return s&&s(null,a),Promise.resolve(a);function c(e){var t=[],n={};function r(e){if(Array.isArray(e)){var n;t=(n=t).concat.apply(n,At(e))}else t.push(e)}for(var i=0;i0&&arguments[0]!==void 0?arguments[0]:[],l=Array.isArray(c)?c:[c];!o.suppressWarning&&l.length&&e.warning(`async-validator:`,l),l.length&&r.message!==void 0&&r.message!==null&&(l=[].concat(r.message));var u=l.map(_m(r,a));if(o.first&&u.length)return d[r.field]=1,n(u);if(!i)n(u);else{if(r.required&&!t.value)return r.message===void 0?o.error&&(u=[o.error(r,sm(o.messages.required,r.field))]):u=[].concat(r.message).map(_m(r,a)),n(u);var f={};r.defaultField&&Object.keys(t.value).map(function(e){f[e]=r.defaultField}),f=Di(Di({},f),t.rule.fields);var p={};Object.keys(f).forEach(function(e){var t=f[e];p[e]=(Array.isArray(t)?t:[t]).map(s.bind(null,e))});var m=new e(p);m.messages(o.messages),t.rule.options&&(t.rule.options.messages=o.messages,t.rule.options.error=o.error),m.validate(t.value,t.rule.options||o,function(e){var t=[];u&&u.length&&t.push.apply(t,At(u)),e&&e.length&&t.push.apply(t,At(e)),n(t.length?t:null)})}}var l;if(r.asyncValidator)l=r.asyncValidator(r,t.value,c,t.source,o);else if(r.validator){try{l=r.validator(r,t.value,c,t.source,o)}catch(e){var u,f;(u=(f=console).error)==null||u.call(f,e),o.suppressValidatorError||setTimeout(function(){throw e},0),c(e.message)}l===!0?c():l===!1?c(typeof r.message==`function`?r.message(r.fullField||r.field):r.message||`${r.fullField||r.field} fails`):l instanceof Array?c(l):l instanceof Error&&c(l.message)}l&&l.then&&l.then(function(){return c()},function(e){return c(e)})},function(e){c(e)},a)}},{key:`getType`,value:function(e){if(e.type===void 0&&e.pattern instanceof RegExp&&(e.type=`pattern`),typeof e.validator!=`function`&&e.type&&!Gm.hasOwnProperty(e.type))throw Error(sm(`Unknown rule type %s`,e.type));return e.type||`string`}},{key:`getValidationMethod`,value:function(e){if(typeof e.validator==`function`)return e.validator;var t=Object.keys(e),n=t.indexOf(`message`);return n!==-1&&t.splice(n,1),t.length===1&&t[0]===`required`?Gm.required:Gm[this.getType(e)]||void 0}}]),e}();Ti(Km,`register`,function(e,t){if(typeof t!=`function`)throw Error(`Cannot register a validator by type, validator is not a function`);Gm[e]=t}),Ti(Km,`warning`,am),Ti(Km,`messages`,em),Ti(Km,`validators`,Gm);var qm="'${name}' is not a valid ${type}",Jm={default:"Validation error on field '${name}'",required:"'${name}' is required",enum:"'${name}' must be one of [${enum}]",whitespace:"'${name}' cannot be empty",date:{format:"'${name}' is invalid for format date",parse:"'${name}' could not be parsed as date",invalid:"'${name}' is invalid date"},types:{string:qm,method:qm,array:qm,object:qm,number:qm,date:qm,boolean:qm,integer:qm,float:qm,regexp:qm,email:qm,tel:qm,url:qm,hex:qm},string:{len:"'${name}' must be exactly ${len} characters",min:"'${name}' must be at least ${min} characters",max:"'${name}' cannot be longer than ${max} characters",range:"'${name}' must be between ${min} and ${max} characters"},number:{len:"'${name}' must equal ${len}",min:"'${name}' cannot be less than ${min}",max:"'${name}' cannot be greater than ${max}",range:"'${name}' must be between ${min} and ${max}"},array:{len:"'${name}' must be exactly ${len} in length",min:"'${name}' cannot be less than ${min} in length",max:"'${name}' cannot be greater than ${max} in length",range:"'${name}' must be between ${min} and ${max} in length"},pattern:{mismatch:"'${name}' does not match pattern ${pattern}"}},Ym=Km;function Xm(e,t){return e.replace(/\\?\$\{\w+\}/g,e=>e.startsWith(`\\`)?e.slice(1):t[e.slice(2,-1)])}var Zm=`CODE_LOGIC_ERROR`;async function Qm(e,t,n,r,i){let a={...n};if(delete a.ruleIndex,Ym.warning=()=>void 0,a.validator){let e=a.validator;a.validator=(...t)=>{try{return e(...t)}catch(e){return console.error(e),Promise.reject(Zm)}}}let o=null;a&&a.type===`array`&&a.defaultField&&(o=a.defaultField,delete a.defaultField);let s=new Ym({[e]:[a]}),c=Ge(Jm,r.validateMessages);s.messages(c);let l=[];try{await Promise.resolve(s.validate({[e]:t},{...r}))}catch(e){e.errors&&(l=e.errors.map(({message:e},t)=>{let n=e===Zm?c.default:e;return m.isValidElement(n)?m.cloneElement(n,{key:`error_${t}`}):n}))}if(!l.length&&o&&Array.isArray(t)&&t.length>0)return(await Promise.all(t.map((t,n)=>Qm(`${e}.${n}`,t,o,r,i)))).reduce((e,t)=>[...e,...t],[]);let u={...n,name:e,enum:(n.enum||[]).join(`, `),...i};return l.map(e=>typeof e==`string`?Xm(e,u):e)}function $m(e,t,n,r,i,a){let o=e.join(`.`),s=n.map((e,t)=>{let n=e.validator,r={...e,ruleIndex:t};return n&&(r.validator=(e,t,r)=>{let i=!1,a=n(e,t,(...e)=>{Promise.resolve().then(()=>{$e(!i,"Your validator function has already return a promise. `callback` will be ignored."),i||r(...e)})});i=a&&typeof a.then==`function`&&typeof a.catch==`function`,$e(i,"`callback` is deprecated. Please return a promise instead."),i&&a.then(()=>{r()}).catch(e=>{r(e||` `)})}),r}).sort(({warningOnly:e,ruleIndex:t},{warningOnly:n,ruleIndex:r})=>!!e==!!n?t-r:e?1:-1),c;if(i===!0)c=new Promise(async(e,n)=>{for(let e=0;eQm(o,t,e,r,a).then(t=>({errors:t,rule:e})));c=(i?th(e):eh(e)).then(e=>Promise.reject(e))}return c.catch(e=>e),c}async function eh(e){return Promise.all(e).then(e=>[].concat(...e))}async function th(e){let t=0;return new Promise(n=>{e.forEach(r=>{r.then(r=>{r.errors.length&&n([r]),t+=1,t===e.length&&n([])})})})}function nh(e){return Zp(e)}function rh(e,t){let n={};return t.forEach(t=>{let r=Re(e,t);n=Be(n,t,r)}),n}function ih(e,t,n=!1){return e&&e.some(e=>ah(t,e,n))}function ah(e,t,n=!1){return!e||!t||!n&&e.length!==t.length?!1:t.every((t,n)=>e[n]===t)}function oh(e,t){if(e===t)return!0;if(!e&&t||e&&!t||!e||!t||typeof e!=`object`||typeof t!=`object`)return!1;let n=Object.keys(e),r=Object.keys(t);return[...new Set([...n,...r])].every(n=>{let r=e[n],i=t[n];return typeof r==`function`&&typeof i==`function`?!0:r===i})}function sh(e,...t){let n=t[0];return n&&n.target&&typeof n.target==`object`&&e in n.target?n.target[e]:n}function ch(e,t,n){let{length:r}=e;if(t<0||t>=r||n<0||n>=r)return e;let i=e[t],a=t-n;return a>0?[...e.slice(0,n),i,...e.slice(n,t),...e.slice(t+1,r)]:a<0?[...e.slice(0,t),...e.slice(t+1,n+1),i,...e.slice(n+1,r)]:e}var lh=e=>{let t=new MessageChannel;t.port1.onmessage=e,t.port2.postMessage(null)},uh=class{namePathList=[];taskId=0;watcherList=new Set;form;constructor(e){this.form=e}register(e){return this.watcherList.add(e),()=>{this.watcherList.delete(e)}}notify(e){e.forEach(e=>{this.namePathList.every(t=>!ah(t,e))&&this.namePathList.push(e)}),this.doBatch()}doBatch(){this.taskId+=1;let e=this.taskId;lh(()=>{if(e===this.taskId&&this.watcherList.size){let e=this.form.getForm(),t=e.getFieldsValue(),n=e.getFieldsValue(!0);this.watcherList.forEach(e=>{e(t,n,this.namePathList)}),this.namePathList=[]}})}};async function dh(){return new Promise(e=>{lh(()=>{It(()=>{e()})})})}function fh(){return fh=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{preserve:e,isListField:t,name:n}=this.props;this.cancelRegisterFunc&&this.cancelRegisterFunc(t,e,nh(n)),this.cancelRegisterFunc=null};getNamePath=()=>{let{name:e,fieldContext:t}=this.props,{prefixName:n=[]}=t;return e===void 0?[]:[...n,...e]};getRules=()=>{let{rules:e=[],fieldContext:t}=this.props;return e.map(e=>typeof e==`function`?e(t):e)};reRender(){this.mounted&&this.forceUpdate()}refresh=()=>{this.mounted&&this.setState(({resetCount:e})=>({resetCount:e+1}))};metaCache=null;triggerMetaEvent=e=>{let{onMetaChange:t}=this.props;if(t){let n={...this.getMeta(),destroy:e};an(this.metaCache,n)||t(n),this.metaCache=n}else this.metaCache=null};onStoreChange=(e,t,n)=>{let{shouldUpdate:r,dependencies:i=[],onReset:a}=this.props,{store:o}=n,s=this.getNamePath(),c=this.getValue(e),l=this.getValue(o),u=t&&ih(t,s);switch(n.type===`valueUpdate`&&n.source===`external`&&!an(c,l)&&(this.touched=!0,this.dirty=!0,this.validatePromise=null,this.errors=ph,this.warnings=mh,this.triggerMetaEvent()),n.type){case`reset`:if(!t||u){this.touched=!1,this.dirty=!1,this.validatePromise=void 0,this.errors=ph,this.warnings=mh,this.triggerMetaEvent(),a?.(),this.refresh();return}break;case`remove`:if(r&&hh(r,e,o,c,l,n)){this.reRender();return}break;case`setField`:{let{data:i}=n;if(u){`touched`in i&&(this.touched=i.touched),`validating`in i&&!(`originRCField`in i)&&(this.validatePromise=i.validating?Promise.resolve([]):null),`errors`in i&&(this.errors=i.errors||ph),`warnings`in i&&(this.warnings=i.warnings||mh),this.dirty=!0,this.triggerMetaEvent(),this.reRender();return}else if(`value`in i&&ih(t,s,!0)){this.reRender();return}if(r&&!s.length&&hh(r,e,o,c,l,n)){this.reRender();return}break}case`dependenciesUpdate`:if(i.map(nh).some(e=>ih(n.relatedFields,e))){this.reRender();return}break;default:if(u||(!i.length||s.length||r)&&hh(r,e,o,c,l,n)){this.reRender();return}break}r===!0&&this.reRender()};validateRules=e=>{let t=this.getNamePath(),n=this.getValue(),{triggerName:r,validateOnly:i=!1,delayFrame:a}=e||{},o=Promise.resolve().then(async()=>{if(!this.mounted)return[];let{validateFirst:i=!1,messageVariables:s,validateDebounce:c}=this.props;a&&await dh();let l=this.getRules();if(r&&(l=l.filter(e=>e).filter(e=>{let{validateTrigger:t}=e;return t?Zp(t).includes(r):!0})),c&&r&&(await new Promise(e=>{setTimeout(e,c)}),this.validatePromise!==o))return[];let u=$m(t,n,l,e,i,s);return u.catch(e=>e).then((e=ph)=>{if(this.validatePromise===o){this.validatePromise=null;let t=[],n=[];e.forEach?.(({rule:{warningOnly:e},errors:r=ph})=>{e?n.push(...r):t.push(...r)}),this.errors=t,this.warnings=n,this.triggerMetaEvent(),this.reRender()}}),u});return i?o:(this.validatePromise=o,this.dirty=!0,this.errors=ph,this.warnings=mh,this.triggerMetaEvent(),this.reRender(),o)};isFieldValidating=()=>!!this.validatePromise;isFieldTouched=()=>this.touched;isFieldDirty=()=>{if(this.dirty||this.props.initialValue!==void 0)return!0;let{fieldContext:e}=this.props,{getInitialValue:t}=e.getInternalHooks(qp);return t(this.getNamePath())!==void 0};getErrors=()=>this.errors;getWarnings=()=>this.warnings;isListField=()=>this.props.isListField;isList=()=>this.props.isList;isPreserve=()=>this.props.preserve;getMeta=()=>(this.prevValidating=this.isFieldValidating(),{touched:this.isFieldTouched(),validating:this.prevValidating,errors:this.errors,warnings:this.warnings,name:this.getNamePath(),validated:this.validatePromise===null});getOnlyChild=e=>{if(typeof e==`function`){let t=this.getMeta();return{...this.getOnlyChild(e(this.getControlled(),t,this.props.fieldContext)),isFunction:!0}}let t=nt(e);return t.length!==1||!m.isValidElement(t[0])?{child:t,isFunction:!1}:{child:t[0],isFunction:!1}};getValue=e=>{let{getFieldsValue:t}=this.props.fieldContext,n=this.getNamePath();return Re(e||t(!0),n)};getControlled=(e={})=>{let{name:t,trigger:n=`onChange`,validateTrigger:r,getValueFromEvent:i,normalize:a,valuePropName:o=`value`,getValueProps:s,fieldContext:c}=this.props,l=r===void 0?c.validateTrigger:r,u=this.getNamePath(),{getInternalHooks:d,getFieldsValue:f}=c,{dispatch:p}=d(qp),m=this.getValue(),h=s||(e=>({[o]:e})),g=e[n],_=t===void 0?{}:h(m),v={...e,..._};return v[n]=(...e)=>{this.touched=!0,this.dirty=!0,this.triggerMetaEvent();let t;t=i?i(...e):sh(o,...e),a&&(t=a(t,m,f(!0))),t!==m&&p({type:`updateValue`,namePath:u,value:t}),g&&g(...e)},Zp(l||[]).forEach(e=>{let t=v[e];v[e]=(...n)=>{t&&t(...n);let{rules:r}=this.props;r&&r.length&&p({type:`validateField`,namePath:u,triggerName:e})}}),v};render(){let{resetCount:e}=this.state,{children:t}=this.props,{child:n,isFunction:r}=this.getOnlyChild(t),i;return r?i=n:m.isValidElement(n)?i=m.cloneElement(n,this.getControlled(n.props)):($e(!n,"`children` of Field is not validate ReactElement."),i=n),m.createElement(m.Fragment,{key:e},i)}};function _h({name:e,...t}){let n=m.useContext(Yp),r=m.useContext(Xp),i=e===void 0?void 0:nh(e),a=t.isListField??!!r,o=`keep`;return a||(o=`_${(i||[]).join(`_`)}`),m.createElement(gh,fh({key:o,name:i,isListField:a},t,{fieldContext:n}))}function vh({name:e,initialValue:t,children:n,rules:r,validateTrigger:i,isListField:a}){let o=m.useContext(Yp),s=m.useContext(Xp),c=m.useRef({keys:[],id:0}).current,l=m.useMemo(()=>[...nh(o.prefixName)||[],...nh(e)],[o.prefixName,e]),u=m.useMemo(()=>({...o,prefixName:l}),[o,l]),d=m.useMemo(()=>({getKey:e=>{let t=l.length,n=e[t];return[c.keys[n],e.slice(t+1)]}}),[c,l]);return typeof n==`function`?m.createElement(Xp.Provider,{value:d},m.createElement(Yp.Provider,{value:u},m.createElement(_h,{name:[],shouldUpdate:(e,t,{source:n})=>n===`internal`?!1:e!==t,rules:r,validateTrigger:i,initialValue:t,isList:!0,isListField:a??!!s},({value:e=[],onChange:t},r)=>{let{getFieldValue:i}=o,a=()=>i(l||[])||[],s={add:(e,n)=>{let r=a();n>=0&&n<=r.length?(c.keys=[...c.keys.slice(0,n),c.id,...c.keys.slice(n)],t([...r.slice(0,n),e,...r.slice(n)])):(c.keys=[...c.keys,c.id],t([...r,e])),c.id+=1},remove:e=>{let n=a(),r=new Set(Array.isArray(e)?e:[e]);r.size<=0||(c.keys=c.keys.filter((e,t)=>!r.has(t)),t(n.filter((e,t)=>!r.has(t))))},move(e,n){if(e===n)return;let r=a();e<0||e>=r.length||n<0||n>=r.length||(c.keys=ch(c.keys,e,n),t(ch(r,e,n)))}},u=e||[];return Array.isArray(u)||(u=[]),n(u.map((e,t)=>{let n=c.keys[t];return n===void 0&&(c.keys[t]=c.id,n=c.keys[t],c.id+=1),{name:t,key:n,isListField:!0}}),s,r)}))):($e(!1,`Form.List only accepts function as children.`),null)}function yh(e){let t=!1,n=e.length,r=[];return e.length?new Promise((i,a)=>{e.forEach((e,o)=>{e.catch(e=>(t=!0,e)).then(e=>{--n,r[o]=e,!(n>0)&&(t&&a(r),i(r))})})}):Promise.resolve([])}var bh=`__@field_split__`;function xh(e){return e.map(e=>`${typeof e}:${e}`).join(bh)}var Sh=class{kvs=new Map;set(e,t){this.kvs.set(xh(e),t)}get(e){return this.kvs.get(xh(e))}getAsPrefix(e){let t=xh(e),n=t+bh,r=[],i=this.kvs.get(t);return i!==void 0&&r.push(i),this.kvs.forEach((e,t)=>{t.startsWith(n)&&r.push(e)}),r}update(e,t){let n=t(this.get(e));n?this.set(e,n):this.delete(e)}delete(e){this.kvs.delete(xh(e))}map(e){return[...this.kvs.entries()].map(([t,n])=>e({key:t.split(bh).map(e=>{let[,t,n]=e.match(/^([^:]*):(.*)$/);return t===`number`?Number(n):n}),value:n}))}toJSON(){let e={};return this.map(({key:t,value:n})=>(e[t.join(`.`)]=n,null)),e}},Ch=class{formHooked=!1;forceRootUpdate;subscribable=!0;store={};fieldEntities=[];initialValues={};callbacks={};validateMessages=null;preserve=null;lastValidatePromise=null;watcherCenter=new uh(this);constructor(e){this.forceRootUpdate=e}getForm=()=>({getFieldValue:this.getFieldValue,getFieldsValue:this.getFieldsValue,getFieldError:this.getFieldError,getFieldWarning:this.getFieldWarning,getFieldsError:this.getFieldsError,isFieldsTouched:this.isFieldsTouched,isFieldTouched:this.isFieldTouched,isFieldValidating:this.isFieldValidating,isFieldsValidating:this.isFieldsValidating,resetFields:this.resetFields,setFields:this.setFields,setFieldValue:this.setFieldValue,setFieldsValue:this.setFieldsValue,validateFields:this.validateFields,submit:this.submit,_init:!0,getInternalHooks:this.getInternalHooks});getInternalHooks=e=>e===`RC_FORM_INTERNAL_HOOKS`?(this.formHooked=!0,{dispatch:this.dispatch,initEntityValue:this.initEntityValue,registerField:this.registerField,useSubscribe:this.useSubscribe,setInitialValues:this.setInitialValues,destroyForm:this.destroyForm,setCallbacks:this.setCallbacks,setValidateMessages:this.setValidateMessages,getFields:this.getFields,setPreserve:this.setPreserve,getInitialValue:this.getInitialValue,registerWatch:this.registerWatch}):($e(!1,"`getInternalHooks` is internal usage. Should not call directly."),null);useSubscribe=e=>{this.subscribable=e};prevWithoutPreserves=null;setInitialValues=(e,t)=>{if(this.initialValues=e||{},t){let t=Ge(e,this.store);this.prevWithoutPreserves?.map(({key:n})=>{t=Be(t,n,Re(e,n))}),this.prevWithoutPreserves=null,this.updateStore(t)}};destroyForm=e=>{if(e)this.updateStore({});else{let e=new Sh;this.getFieldEntities(!0).forEach(t=>{this.isMergedPreserve(t.isPreserve())||e.set(t.getNamePath(),!0)}),this.prevWithoutPreserves=e}};getInitialValue=e=>{let t=Re(this.initialValues,e);return e.length?Ge(t):t};setCallbacks=e=>{this.callbacks=e};setValidateMessages=e=>{this.validateMessages=e};setPreserve=e=>{this.preserve=e};registerWatch=e=>this.watcherCenter.register(e);notifyWatch=(e=[])=>{this.watcherCenter.notify(e)};timeoutId=null;warningUnhooked=()=>{};updateStore=e=>{this.store=e};getFieldEntities=(e=!1)=>e?this.fieldEntities.filter(e=>e.getNamePath().length):this.fieldEntities;getFieldsMap=(e=!1)=>{let t=new Sh;return this.getFieldEntities(e).forEach(e=>{let n=e.getNamePath();t.set(n,e)}),t};getFieldEntitiesForNamePathList=(e,t=!1)=>{if(!e)return this.getFieldEntities(!0);let n=this.getFieldsMap(!0);return t?e.flatMap(e=>{let t=nh(e),r=n.getAsPrefix(t);return r.length?r:[{INVALIDATE_NAME_PATH:t}]}):e.map(e=>{let t=nh(e);return n.get(t)||{INVALIDATE_NAME_PATH:nh(e)}})};getFieldsValue=(e,t)=>{this.warningUnhooked();let n,r;if(e===!0||Array.isArray(e)?(n=e,r=t):e&&typeof e==`object`&&(r=e.filter),n===!0&&!r)return this.store;let i=this.getFieldEntitiesForNamePathList(Array.isArray(n)?n:null,!0),a=[],o=[];i.forEach(e=>{let t=e.INVALIDATE_NAME_PATH||e.getNamePath();if(e.isList?.()){o.push(t);return}if(!r)a.push(t);else{let n=`getMeta`in e?e.getMeta():null;r(n)&&a.push(t)}});let s=rh(this.store,a.map(nh));return o.forEach(e=>{Re(s,e)||(s=Be(s,e,[]))}),s};getFieldValue=e=>{this.warningUnhooked();let t=nh(e);return Re(this.store,t)};getFieldsError=e=>(this.warningUnhooked(),this.getFieldEntitiesForNamePathList(e).map((t,n)=>t&&!t.INVALIDATE_NAME_PATH?{name:t.getNamePath(),errors:t.getErrors(),warnings:t.getWarnings()}:{name:nh(e[n]),errors:[],warnings:[]}));getFieldError=e=>{this.warningUnhooked();let t=nh(e);return this.getFieldsError([t])[0].errors};getFieldWarning=e=>{this.warningUnhooked();let t=nh(e);return this.getFieldsError([t])[0].warnings};isFieldsTouched=(...e)=>{this.warningUnhooked();let[t,n]=e,r,i=!1;e.length===0?r=null:e.length===1?Array.isArray(t)?(r=t.map(nh),i=!1):(r=null,i=t):(r=t.map(nh),i=n);let a=this.getFieldEntities(!0),o=e=>e.isFieldTouched();if(!r)return i?a.every(e=>o(e)||e.isList()):a.some(o);let s=new Sh;r.forEach(e=>{s.set(e,[])}),a.forEach(e=>{let t=e.getNamePath();r.forEach(n=>{n.every((e,n)=>t[n]===e)&&s.update(n,t=>[...t,e])})});let c=e=>e.some(o),l=s.map(({value:e})=>e);return i?l.every(c):l.some(c)};isFieldTouched=e=>(this.warningUnhooked(),this.isFieldsTouched([e]));isFieldsValidating=e=>{this.warningUnhooked();let t=this.getFieldEntities();if(!e)return t.some(e=>e.isFieldValidating());let n=e.map(nh);return t.some(e=>ih(n,e.getNamePath())&&e.isFieldValidating())};isFieldValidating=e=>(this.warningUnhooked(),this.isFieldsValidating([e]));resetWithFieldInitialValue=(e={})=>{let t=new Sh,n=this.getFieldEntities(!0);n.forEach(e=>{let{initialValue:n}=e.props,r=e.getNamePath();if(n!==void 0){let i=t.get(r)||new Set;i.add({entity:e,value:n}),t.set(r,i)}});let r=n=>{n.forEach(n=>{let{initialValue:r}=n.props;if(r!==void 0){let r=n.getNamePath();if(this.getInitialValue(r)!==void 0)$e(!1,`Form already set 'initialValues' with path '${r.join(`.`)}'. Field can not overwrite it.`);else{let i=t.get(r);if(i&&i.size>1)$e(!1,`Multiple Field with path '${r.join(`.`)}' set 'initialValue'. Can not decide which one to pick.`);else if(i){let t=this.getFieldValue(r);!n.isListField()&&(!e.skipExist||t===void 0)&&this.updateStore(Be(this.store,r,[...i][0].value))}}}})},i;e.entities?i=e.entities:e.namePathList?(i=[],e.namePathList.forEach(e=>{let n=t.get(e);n&&i.push(...[...n].map(e=>e.entity))})):i=n,r(i)};resetFields=e=>{this.warningUnhooked();let t=this.store;if(!e){this.updateStore(Ge(this.initialValues)),this.resetWithFieldInitialValue(),this.notifyObservers(t,null,{type:`reset`}),this.notifyWatch();return}let n=e.map(nh);n.forEach(e=>{let t=this.getInitialValue(e);this.updateStore(Be(this.store,e,t))}),this.resetWithFieldInitialValue({namePathList:n}),this.notifyObservers(t,n,{type:`reset`}),this.notifyWatch(n)};setFields=e=>{this.warningUnhooked();let t=this.store,n=[];e.forEach(e=>{let{name:r,...i}=e,a=nh(r);n.push(a),`value`in i&&this.updateStore(Be(this.store,a,i.value)),this.notifyObservers(t,[a],{type:`setField`,data:e})}),this.notifyWatch(n)};getFields=()=>this.getFieldEntities(!0).map(e=>{let t=e.getNamePath(),n={...e.getMeta(),name:t,value:this.getFieldValue(t)};return Object.defineProperty(n,`originRCField`,{value:!0}),n});initEntityValue=e=>{let{initialValue:t}=e.props;if(t!==void 0){let n=e.getNamePath();Re(this.store,n)===void 0&&this.updateStore(Be(this.store,n,t))}};isMergedPreserve=e=>(e===void 0?this.preserve:e)??!0;registerField=e=>{this.fieldEntities.push(e);let t=e.getNamePath();if(this.notifyWatch([t]),e.props.initialValue!==void 0){let t=this.store;this.resetWithFieldInitialValue({entities:[e],skipExist:!0}),this.notifyObservers(t,[e.getNamePath()],{type:`valueUpdate`,source:`internal`})}return(n,r,i=[])=>{if(this.fieldEntities=this.fieldEntities.filter(t=>t!==e),!this.isMergedPreserve(r)&&(!n||i.length>1)){let e=n?void 0:this.getInitialValue(t);if(t.length&&this.getFieldValue(t)!==e&&this.fieldEntities.every(e=>!ah(e.getNamePath(),t))){let n=this.store;this.updateStore(Be(n,t,e,!0)),this.notifyObservers(n,[t],{type:`remove`}),this.triggerDependenciesUpdate(n,t)}}this.notifyWatch([t])}};dispatch=e=>{switch(e.type){case`updateValue`:{let{namePath:t,value:n}=e;this.updateValue(t,n);break}case`validateField`:{let{namePath:t,triggerName:n}=e;this.validateFields([t],{triggerName:n});break}default:}};notifyObservers=(e,t,n)=>{if(this.subscribable){let r={...n,store:this.getFieldsValue(!0)};this.getFieldEntities().forEach(({onStoreChange:n})=>{n(e,t,r)})}else this.forceRootUpdate()};triggerDependenciesUpdate=(e,t)=>{let n=this.getDependencyChildrenFields(t);return n.length&&this.validateFields(n,{delayFrame:!0}),this.notifyObservers(e,n,{type:`dependenciesUpdate`,relatedFields:[t,...n]}),n};updateValue=(e,t)=>{let n=nh(e),r=this.store;this.updateStore(Be(this.store,n,t)),this.notifyObservers(r,[n],{type:`valueUpdate`,source:`internal`}),this.notifyWatch([n]);let i=this.triggerDependenciesUpdate(r,n),{onValuesChange:a}=this.callbacks;if(a){let e=rh(this.store,[n]);a(e,Be(this.getFieldsValue(),n,Re(e,n)))}this.triggerOnFieldsChange([n,...i])};setFieldsValue=e=>{this.warningUnhooked();let t=this.store;if(e){let t=Ge(this.store,e);this.updateStore(t)}this.notifyObservers(t,null,{type:`valueUpdate`,source:`external`}),this.notifyWatch()};setFieldValue=(e,t)=>{this.setFields([{name:e,value:t,errors:[],warnings:[],touched:!0}])};getDependencyChildrenFields=e=>{let t=new Set,n=[],r=new Sh;this.getFieldEntities().forEach(e=>{let{dependencies:t}=e.props;(t||[]).forEach(t=>{let n=nh(t);r.update(n,(t=new Set)=>(t.add(e),t))})});let i=e=>{(r.get(e)||new Set).forEach(e=>{if(!t.has(e)){t.add(e);let r=e.getNamePath();e.isFieldDirty()&&r.length&&(n.push(r),i(r))}})};return i(e),n};triggerOnFieldsChange=(e,t)=>{let{onFieldsChange:n}=this.callbacks;if(n){let r=this.getFields();if(t){let e=new Sh;t.forEach(({name:t,errors:n})=>{e.set(t,n)}),r.forEach(t=>{t.errors=e.get(t.name)||t.errors})}let i=r.filter(({name:t})=>ih(e,t));i.length&&n(i,r)}};validateFields=(e,t)=>{this.warningUnhooked();let n,r;Array.isArray(e)||typeof e==`string`||typeof t==`string`?(n=e,r=t):r=e;let i=!!n,a=i?n.map(nh):[],o=[...a],s=[],c=String(Date.now()),l=new Set,{recursive:u,dirty:d}=r||{};this.getFieldEntities(!0).forEach(e=>{let t=e.getNamePath();if(i||((!e.isList()||!a.some(e=>ah(e,t,!0)))&&o.push(t),a.push(t)),!(!e.props.rules||!e.props.rules.length)&&!(d&&!e.isFieldDirty())&&(l.add(t.join(c)),!i||ih(a,t,u))){let n=e.validateRules({validateMessages:{...Jm,...this.validateMessages},...r});s.push(n.then(()=>({name:t,errors:[],warnings:[]})).catch(e=>{let n=[],r=[];return e.forEach?.(({rule:{warningOnly:e},errors:t})=>{e?r.push(...t):n.push(...t)}),n.length?Promise.reject({name:t,errors:n,warnings:r}):{name:t,errors:n,warnings:r}}))}});let f=yh(s);this.lastValidatePromise=f,f.catch(e=>e).then(e=>{let t=e.map(({name:e})=>e);this.notifyObservers(this.store,t,{type:`validateFinish`}),this.triggerOnFieldsChange(t,e)});let p=f.then(()=>this.lastValidatePromise===f?Promise.resolve(this.getFieldsValue(o)):Promise.reject([])).catch(e=>{let t=e.filter(e=>e&&e.errors.length),n=t[0]?.errors?.[0];return Promise.reject({message:n,values:this.getFieldsValue(a),errorFields:t,outOfDate:this.lastValidatePromise!==f})});p.catch(e=>e);let m=a.filter(e=>l.has(e.join(c)));return this.triggerOnFieldsChange(m),p};submit=()=>{this.warningUnhooked(),this.validateFields().then(e=>{let{onFinish:t}=this.callbacks;if(t)try{t(e)}catch(e){console.error(e)}}).catch(e=>{let{onFinishFailed:t}=this.callbacks;t&&t(e)})}};function wh(e){let t=m.useRef(null),[,n]=m.useState({});return t.current||(e?t.current=e:t.current=new Ch(()=>{n({})}).getForm()),[t.current]}var Th=m.createContext({triggerFormChange:()=>{},triggerFormFinish:()=>{},registerForm:()=>{},unregisterForm:()=>{}}),Eh=({validateMessages:e,onFormChange:t,onFormFinish:n,children:r})=>{let i=m.useContext(Th),a=m.useRef({});return m.createElement(Th.Provider,{value:{...i,validateMessages:{...i.validateMessages,...e},triggerFormChange:(e,n)=>{t&&t(e,{changedFields:n,forms:a.current}),i.triggerFormChange(e,n)},triggerFormFinish:(e,t)=>{n&&n(e,{values:t,forms:a.current}),i.triggerFormFinish(e,t)},registerForm:(e,t)=>{e&&(a.current={...a.current,[e]:t}),i.registerForm(e,t)},unregisterForm:e=>{let t={...a.current};delete t[e],a.current=t,i.unregisterForm(e)}}},r)};function Dh(){return Dh=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let _=m.useRef(null),v=m.useContext(Th),[y]=wh(r),{useSubscribe:b,setInitialValues:x,setCallbacks:S,setValidateMessages:C,setPreserve:w,destroyForm:T}=y.getInternalHooks(qp);m.useImperativeHandle(g,()=>({...y,nativeElement:_.current})),m.useEffect(()=>(v.registerForm(e,y),()=>{v.unregisterForm(e)}),[v,y,e]),C({...v.validateMessages,...s}),S({onValuesChange:l,onFieldsChange:(t,...n)=>{v.triggerFormChange(e,t),u&&u(t,...n)},onFinish:t=>{v.triggerFormFinish(e,t),d&&d(t)},onFinishFailed:f}),w(i);let E=m.useRef(null);x(t,!E.current),E.current||=!0,m.useEffect(()=>()=>T(p),[]);let D,O=typeof a==`function`;D=O?a(y.getFieldsValue(!0),y):a,b(!O);let k=m.useRef(null);m.useEffect(()=>{oh(k.current||[],n||[])||y.setFields(n||[]),k.current=n},[n,y]);let A=m.useMemo(()=>({...y,validateTrigger:c}),[y,c]),j=m.createElement(Xp.Provider,{value:null},m.createElement(Yp.Provider,{value:A},D));return o===!1?j:m.createElement(o,Dh({},h,{ref:_,onSubmit:e=>{e.preventDefault(),e.stopPropagation(),y.submit()},onReset:e=>{e.preventDefault(),y.resetFields(),h.onReset?.(e)}}),j)};function kh(e){try{return JSON.stringify(e)}catch{return Math.random()}}function Ah(...e){let[t,n={}]=e,r=Qp(n)?{form:n}:n,i=r.form,[a,o]=(0,m.useState)(()=>typeof t==`function`?t({}):void 0),s=(0,m.useMemo)(()=>kh(a),[a]),c=(0,m.useRef)(s);c.current=s;let l=(0,m.useContext)(Yp),u=i||l,d=u&&u._init,{getFieldsValue:f,getInternalHooks:p}=u,{registerWatch:h}=p(qp),g=W((e,n)=>{let i=r.preserve?n??f(!0):e??f(),s=typeof t==`function`?t(i):Re(i,nh(t));kh(a)!==kh(s)&&o(s)});return(0,m.useEffect)(()=>{d&&g()},[d,typeof t==`function`?t:JSON.stringify(t)]),(0,m.useEffect)(()=>{if(d)return h((e,t)=>{g(e,t)})},[d]),a}var jh=m.forwardRef(Oh);jh.FormProvider=Eh,jh.Field=_h,jh.List=vh,jh.useForm=wh,jh.useWatch=Ah;var Mh=m.createContext({}),Nh=({children:e,status:t,override:n})=>{let r=m.useContext(Mh),i=m.useMemo(()=>{let e={...r};return n&&delete e.isFormItemInput,t&&(delete e.status,delete e.hasFeedback,delete e.feedbackIcon),e},[t,n,r]);return m.createElement(Mh.Provider,{value:i},e)},Ph=m.createContext(void 0),Fh=e=>{let{space:t,form:n,children:r}=e;if(!Gc(r))return null;let i=r;return n&&(i=m.createElement(Nh,{override:!0,status:!0},i)),t&&(i=m.createElement(Xd,null,i)),i},Ih=e=>{if(ve()&&window.document.documentElement){let t=Array.isArray(e)?e:[e],{documentElement:n}=window.document;return t.some(e=>e in n.style)}return!1},Lh=(e,t)=>{if(!Ih(e))return!1;let n=document.createElement(`div`),r=n.style[e];return n.style[e]=t,n.style[e]!==r};function Rh(e,t){return!Array.isArray(e)&&t!==void 0?Lh(e,t):Ih(e)}var zh=()=>ve()&&window.document.documentElement;function Bh(e,t,n){return(0,m.useMemo)(()=>({trap:t??!0,focusTriggerAfterClose:n??!0,...e}),[e,t,n])}var Vh=e=>{let{prefixCls:t,className:n,style:r,size:i,shape:a}=e,o=K({[`${t}-lg`]:i===`large`,[`${t}-sm`]:i===`small`}),s=K({[`${t}-circle`]:a===`circle`,[`${t}-square`]:a===`square`,[`${t}-round`]:a===`round`}),c=m.useMemo(()=>typeof i==`number`?{width:i,height:i,lineHeight:`${i}px`}:{},[i]);return m.createElement(`span`,{className:K(t,o,s,n),style:{...c,...r}})},Hh=new gi(`ant-skeleton-loading`,{"0%":{backgroundPosition:`100% 50%`},"100%":{backgroundPosition:`0 50%`}}),Uh=e=>({height:e,lineHeight:q(e)}),Wh=e=>({width:e,...Uh(e)}),Gh=e=>({background:e.skeletonLoadingBackground,backgroundSize:`400% 100%`,animationName:Hh,animationDuration:e.skeletonLoadingMotionDuration,animationTimingFunction:`ease`,animationIterationCount:`infinite`}),Kh=(e,t)=>({width:t(e).mul(5).equal(),minWidth:t(e).mul(5).equal(),...Uh(e)}),qh=e=>{let{skeletonAvatarCls:t,gradientFromColor:n,controlHeight:r,controlHeightLG:i,controlHeightSM:a}=e;return{[t]:{display:`inline-block`,verticalAlign:`top`,background:n,...Wh(r)},[`${t}${t}-circle`]:{borderRadius:`50%`},[`${t}${t}-lg`]:{...Wh(i)},[`${t}${t}-sm`]:{...Wh(a)}}},Jh=e=>{let{controlHeight:t,borderRadiusSM:n,skeletonInputCls:r,controlHeightLG:i,controlHeightSM:a,gradientFromColor:o,calc:s}=e;return{[r]:{display:`inline-block`,verticalAlign:`top`,background:o,borderRadius:n,...Kh(t,s)},[`${r}-lg`]:{...Kh(i,s)},[`${r}-sm`]:{...Kh(a,s)}}},Yh=e=>{let{gradientFromColor:t,borderRadiusSM:n,imageSizeBase:r,calc:i}=e;return{display:`inline-flex`,alignItems:`center`,justifyContent:`center`,verticalAlign:`middle`,background:t,borderRadius:n,...Wh(i(r).mul(2).equal())}},Xh=e=>({[e.skeletonNodeCls]:{...Yh(e)}}),Zh=e=>{let{skeletonImageCls:t,imageSizeBase:n,calc:r}=e;return{[t]:{...Yh(e),[`${t}-path`]:{fill:`#bfbfbf`},[`${t}-svg`]:{...Wh(n),maxWidth:r(n).mul(4).equal(),maxHeight:r(n).mul(4).equal()},[`${t}-svg${t}-svg-circle`]:{borderRadius:`50%`}},[`${t}${t}-circle`]:{borderRadius:`50%`}}},Qh=(e,t,n)=>{let{skeletonButtonCls:r}=e;return{[`${n}${r}-circle`]:{width:t,minWidth:t,borderRadius:`50%`},[`${n}${r}-round`]:{borderRadius:t}}},$h=(e,t)=>({width:t(e).mul(2).equal(),minWidth:t(e).mul(2).equal(),...Uh(e)}),eg=e=>{let{borderRadiusSM:t,skeletonButtonCls:n,controlHeight:r,controlHeightLG:i,controlHeightSM:a,gradientFromColor:o,calc:s}=e;return{[n]:{display:`inline-block`,verticalAlign:`top`,background:o,borderRadius:t,width:s(r).mul(2).equal(),minWidth:s(r).mul(2).equal(),...$h(r,s)},...Qh(e,r,n),[`${n}-lg`]:{...$h(i,s)},...Qh(e,i,`${n}-lg`),[`${n}-sm`]:{...$h(a,s)},...Qh(e,a,`${n}-sm`)}},tg=e=>{let{componentCls:t,skeletonAvatarCls:n,skeletonTitleCls:r,skeletonParagraphCls:i,skeletonButtonCls:a,skeletonInputCls:o,skeletonNodeCls:s,skeletonImageCls:c,controlHeight:l,controlHeightLG:u,controlHeightSM:d,gradientFromColor:f,padding:p,marginSM:m,borderRadius:h,titleHeight:g,blockRadius:_,paragraphLiHeight:v,controlHeightXS:y,paragraphMarginTop:b}=e;return{[t]:{display:`table`,width:`100%`,[`${t}-header`]:{display:`table-cell`,paddingInlineEnd:p,verticalAlign:`top`,[n]:{display:`inline-block`,verticalAlign:`top`,background:f,...Wh(l)},[`${n}-circle`]:{borderRadius:`50%`},[`${n}-lg`]:{...Wh(u)},[`${n}-sm`]:{...Wh(d)}},[`${t}-section`]:{display:`table-cell`,width:`100%`,verticalAlign:`top`,[r]:{width:`100%`,height:g,background:f,borderRadius:_,[`+ ${i}`]:{marginBlockStart:d}},[i]:{padding:0,"> li":{width:`100%`,height:v,listStyle:`none`,background:f,borderRadius:_,"+ li":{marginBlockStart:y}}},[`${i}> li:last-child:not(:first-child):not(:nth-child(2))`]:{width:`61%`}},[`&-round ${t}-section`]:{[`${r}, ${i} > li`]:{borderRadius:h}}},[`${t}-with-avatar ${t}-section`]:{[r]:{marginBlockStart:m,[`+ ${i}`]:{marginBlockStart:b}}},[`${t}${t}-element`]:{display:`inline-block`,width:`auto`,...eg(e),...qh(e),...Jh(e),...Xh(e),...Zh(e)},[`${t}${t}-block`]:{width:`100%`,[a]:{width:`100%`},[o]:{width:`100%`}},[`${t}${t}-active`]:{[` - ${r}, - ${i} > li, - ${n}, - ${a}, - ${o}, - ${s}, - ${c} - `]:{...Gh(e)}}}},ng=Io(`Skeleton`,e=>{let{componentCls:t,calc:n}=e;return tg(Yi(e,{skeletonAvatarCls:`${t}-avatar`,skeletonTitleCls:`${t}-title`,skeletonParagraphCls:`${t}-paragraph`,skeletonButtonCls:`${t}-button`,skeletonInputCls:`${t}-input`,skeletonNodeCls:`${t}-node`,skeletonImageCls:`${t}-image`,imageSizeBase:n(e.controlHeight).mul(1.5).equal(),borderRadius:100,skeletonLoadingBackground:`linear-gradient(90deg, ${e.gradientFromColor} 25%, ${e.gradientToColor} 37%, ${e.gradientFromColor} 63%)`,skeletonLoadingMotionDuration:`1.4s`}))},e=>{let{colorFillContent:t,colorFill:n}=e,r=t,i=n;return{color:r,colorGradientEnd:i,gradientFromColor:r,gradientToColor:i,titleHeight:e.controlHeight/2,blockRadius:e.borderRadiusSM,paragraphMarginTop:e.marginLG+e.marginXXS,paragraphLiHeight:e.controlHeight/2}},{deprecatedTokens:[[`color`,`gradientFromColor`],[`colorGradientEnd`,`gradientToColor`]]}),rg=e=>{let{prefixCls:t,className:n,classNames:r,rootClassName:i,active:a,style:o,styles:s,shape:c=`circle`,size:l,...u}=e,{getPrefixCls:d}=m.useContext(zt),f=d(`skeleton`,t),[p,h]=ng(f),g=Kd(e=>l??e),_=K(f,`${f}-element`,{[`${f}-active`]:a},r?.root,n,i,p,h);return m.createElement(`div`,{className:_,style:s?.root},m.createElement(Vh,{prefixCls:`${f}-avatar`,className:r?.content,style:{...s?.content,...o},shape:c,size:g,...u}))},ig=e=>{let{prefixCls:t,className:n,rootClassName:r,classNames:i,active:a,style:o,styles:s,block:c=!1,size:l,...u}=e,{getPrefixCls:d}=m.useContext(zt),f=d(`skeleton`,t),[p,h]=ng(f),g=Kd(e=>l??e),_=K(f,`${f}-element`,{[`${f}-active`]:a,[`${f}-block`]:c},i?.root,n,r,p,h);return m.createElement(`div`,{className:_,style:s?.root},m.createElement(Vh,{prefixCls:`${f}-button`,className:i?.content,style:{...s?.content,...o},size:g,...u}))},ag=e=>{let{prefixCls:t,className:n,classNames:r,rootClassName:i,internalClassName:a,style:o,styles:s,active:c,children:l}=e,{getPrefixCls:u}=m.useContext(zt),d=u(`skeleton`,t),[f,p]=ng(d),h=K(d,`${d}-element`,{[`${d}-active`]:c},f,r?.root,n,i,p);return m.createElement(`div`,{className:h,style:s?.root},m.createElement(`div`,{className:K(r?.content,a||`${d}-node`),style:{...s?.content,...o}},l))},og=e=>{let{getPrefixCls:t}=m.useContext(zt),n=t(`skeleton`,e.prefixCls);return m.createElement(ag,{...e,internalClassName:`${n}-image`},m.createElement(`svg`,{viewBox:`0 0 1098 1024`,xmlns:`http://www.w3.org/2000/svg`,className:`${n}-image-svg`},m.createElement(`title`,null,`Image placeholder`),m.createElement(`path`,{d:`M365.7 329.1q0 45.8-32 77.7t-77.7 32-77.7-32-32-77.7 32-77.6 77.7-32 77.7 32 32 77.6M951 548.6v256H146.3V694.9L329 512l91.5 91.4L713 311zm54.8-402.3H91.4q-7.4 0-12.8 5.4T73 164.6v694.8q0 7.5 5.5 12.9t12.8 5.4h914.3q7.5 0 12.9-5.4t5.4-12.9V164.6q0-7.5-5.4-12.9t-12.9-5.4m91.4 18.3v694.8q0 37.8-26.8 64.6t-64.6 26.9H91.4q-37.7 0-64.6-26.9T0 859.4V164.6q0-37.8 26.8-64.6T91.4 73h914.3q37.8 0 64.6 26.9t26.8 64.6`,className:`${n}-image-path`})))},sg=e=>{let{prefixCls:t,className:n,classNames:r,rootClassName:i,active:a,block:o,style:s,styles:c,size:l,...u}=e,{getPrefixCls:d}=m.useContext(zt),f=d(`skeleton`,t),[p,h]=ng(f),g=Kd(e=>l??e),_=K(f,`${f}-element`,{[`${f}-active`]:a,[`${f}-block`]:o},r?.root,n,i,p,h);return m.createElement(`div`,{className:_,style:c?.root},m.createElement(Vh,{prefixCls:`${f}-input`,className:r?.content,style:{...c?.content,...s},size:g,...u}))},cg=(e,t)=>{let{width:n,rows:r=2}=t;if(Array.isArray(n))return n[e];if(r-1===e)return n},lg=e=>{let{prefixCls:t,className:n,style:r,rows:i=0}=e,a=Array.from({length:i}).map((t,n)=>m.createElement(`li`,{key:n,style:{width:cg(n,e)}}));return m.createElement(`ul`,{className:K(t,n),style:r},a)},ug=({prefixCls:e,className:t,width:n,style:r})=>m.createElement(`h3`,{className:K(e,t),style:{width:n,...r}});function dg(e){return e&&typeof e==`object`?e:{}}function fg(e,t){return e&&!t?{size:`large`,shape:`square`}:{size:`large`,shape:`circle`}}function pg(e,t){return!e&&t?{width:`38%`}:e&&t?{width:`50%`}:{}}function mg(e,t){let n={};return(!e||!t)&&(n.width=`61%`),!e&&t?n.rows=3:n.rows=2,n}var hg=e=>{let{prefixCls:t,loading:n,className:r,rootClassName:i,classNames:a,style:o,styles:s,children:c,avatar:l=!1,title:u=!0,paragraph:d=!0,active:f,round:p}=e,{getPrefixCls:h,direction:g,className:_,style:v,classNames:y,styles:b}=Ht(`skeleton`),x=h(`skeleton`,t),[S,C]=ng(x),w={...e,avatar:l,title:u,paragraph:d},[T,E]=cl([y,a],[b,s],{props:w});if(n||!(`loading`in e)){let e=!!l,t=!!u,n=!!d,a;if(e){let e={className:T.avatar,prefixCls:`${x}-avatar`,...fg(t,n),...dg(l),style:E.avatar};a=m.createElement(`div`,{className:K(T.header,`${x}-header`),style:E.header},m.createElement(Vh,{...e}))}let s;if(t||n){let r;if(t){let t={className:T.title,prefixCls:`${x}-title`,...pg(e,n),...dg(u),style:E.title};r=m.createElement(ug,{...t})}let i;if(n){let n={className:T.paragraph,prefixCls:`${x}-paragraph`,...mg(e,t),...dg(d),style:E.paragraph};i=m.createElement(lg,{...n})}s=m.createElement(`div`,{className:K(T.section,`${x}-section`),style:E.section},r,i)}let c=K(x,{[`${x}-with-avatar`]:e,[`${x}-active`]:f,[`${x}-rtl`]:g===`rtl`,[`${x}-round`]:p},T.root,_,r,i,S,C);return m.createElement(`div`,{className:c,style:{...E.root,...v,...o}},a,s)}return c??null};hg.Button=ig,hg.Avatar=rg,hg.Input=sg,hg.Image=og,hg.Node=ag;var gg=hg;function _g(){}var vg=m.createContext({add:_g,remove:_g});function yg(e){let t=m.useContext(vg),n=m.useRef(null);return W(r=>{if(r){let i=e?r.querySelector(e):r;i&&(t.add(i),n.current=i)}else t.remove(n.current)})}var bg=()=>{let{cancelButtonProps:e,cancelTextLocale:t,onCancel:n}=(0,m.useContext)(mp);return m.createElement(dp,{onClick:n,...e},t)},xg=()=>{let{confirmLoading:e,okButtonProps:t,okType:n,okTextLocale:r,onOk:i}=(0,m.useContext)(mp);return m.createElement(dp,{...rf(n),loading:e,onClick:i,...t},r)};function Sg(e,t){return m.createElement(`span`,{className:`${e}-close-x`},t||m.createElement(_s,{className:`${e}-close-icon`}))}var Cg=e=>{let{okText:t,okType:n=`primary`,cancelText:r,confirmLoading:i,onOk:a,onCancel:o,okButtonProps:s,cancelButtonProps:c,footer:l}=e,[u]=Vc(`Modal`,zc()),d=t||u?.okText,f=r||u?.cancelText,p=m.useMemo(()=>({confirmLoading:i,okButtonProps:s,cancelButtonProps:c,okTextLocale:d,cancelTextLocale:f,okType:n,onOk:a,onCancel:o}),[i,s,c,d,f,n,a,o]),h;return typeof l==`function`||l===void 0?(h=m.createElement(m.Fragment,null,m.createElement(bg,null),m.createElement(xg,null)),typeof l==`function`&&(h=l(h,{OkBtn:xg,CancelBtn:bg})),h=m.createElement(hp,{value:p},h)):h=l,m.createElement(Ru,{disabled:!1},h)},wg=e=>{let{componentCls:t}=e;return{[t]:{display:`flex`,flexFlow:`row wrap`,minWidth:0,"&::before, &::after":{display:`flex`},"&-no-wrap":{flexWrap:`nowrap`},"&-start":{justifyContent:`flex-start`},"&-center":{justifyContent:`center`},"&-end":{justifyContent:`flex-end`},"&-space-between":{justifyContent:`space-between`},"&-space-around":{justifyContent:`space-around`},"&-space-evenly":{justifyContent:`space-evenly`},"&-top":{alignItems:`flex-start`},"&-middle":{alignItems:`center`},"&-bottom":{alignItems:`flex-end`}}}},Tg=e=>{let{componentCls:t}=e;return{[t]:{position:`relative`,maxWidth:`100%`,minHeight:1}}},Eg=(e,t)=>{let{componentCls:n,gridColumns:r,antCls:i}=e,[a,o]=zo(i,`grid`),[,s]=zo(i,`col`),c={};for(let e=r;e>=0;e--)e===0?(c[`${n}${t}-${e}`]={display:`none`},c[`${n}-push-${e}`]={insetInlineStart:`auto`},c[`${n}-pull-${e}`]={insetInlineEnd:`auto`},c[`${n}${t}-push-${e}`]={insetInlineStart:`auto`},c[`${n}${t}-pull-${e}`]={insetInlineEnd:`auto`},c[`${n}${t}-offset-${e}`]={marginInlineStart:0},c[`${n}${t}-order-${e}`]={order:0}):(c[`${n}${t}-${e}`]=[{[a(`display`)]:`block`,display:`block`},{display:o(`display`),flex:`0 0 ${e/r*100}%`,maxWidth:`${e/r*100}%`}],c[`${n}${t}-push-${e}`]={insetInlineStart:`${e/r*100}%`},c[`${n}${t}-pull-${e}`]={insetInlineEnd:`${e/r*100}%`},c[`${n}${t}-offset-${e}`]={marginInlineStart:`${e/r*100}%`},c[`${n}${t}-order-${e}`]={order:e});return c[`${n}${t}-flex`]={flex:s(`${t.replace(/-/,``)}-flex`)},c},Dg=(e,t)=>Eg(e,t),Og=(e,t,n)=>({[`@media (min-width: ${q(t)})`]:{...Dg(e,n)}}),kg=()=>({}),Ag=()=>({}),jg=Io(`Grid`,wg,kg),Mg=e=>({xs:e.screenXSMin,sm:e.screenSMMin,md:e.screenMDMin,lg:e.screenLGMin,xl:e.screenXLMin,xxl:e.screenXXLMin,xxxl:e.screenXXXLMin});Io(`Grid`,e=>{let t=Yi(e,{gridColumns:24}),n=Mg(t);return delete n.xs,[Tg(t),Dg(t,``),Dg(t,`-xs`),Object.keys(n).map(e=>Og(t,n[e],`-${e}`)).reduce((e,t)=>({...e,...t}),{})]},Ag);function Ng(e){return{position:e,inset:0}}var Pg=e=>{let{componentCls:t,antCls:n}=e;return[{[`${t}-root`]:{[`${t}${n}-zoom-enter, ${t}${n}-zoom-appear`]:{transform:`none`,opacity:0,animationDuration:e.motionDurationSlow,userSelect:`none`},[`${t}${n}-zoom-leave ${t}-container`]:{pointerEvents:`none`},[`${t}-mask`]:{...Ng(`fixed`),zIndex:e.zIndexPopupBase,height:`100%`,backgroundColor:e.colorBgMask,pointerEvents:`none`,[`&${t}-mask-blur`]:{backdropFilter:`blur(4px)`},[`${t}-hidden`]:{display:`none`}},[`${t}-wrap`]:{...Ng(`fixed`),zIndex:e.zIndexPopupBase,overflow:`auto`,outline:0,WebkitOverflowScrolling:`touch`}}},{[`${t}-root`]:vf(e)}]},Fg=e=>{let{componentCls:t,motionDurationMid:n}=e;return[{[`${t}-root`]:{[`${t}-wrap-rtl`]:{direction:`rtl`},[`${t}-centered`]:{textAlign:`center`,"&::before":{display:`inline-block`,width:0,height:`100%`,verticalAlign:`middle`,content:`""`},[t]:{top:0,display:`inline-block`,paddingBottom:0,textAlign:`start`,verticalAlign:`middle`}},[`@media (max-width: ${e.screenSMMax}px)`]:{[t]:{maxWidth:`calc(100vw - 16px)`,margin:`${q(e.marginXS)} auto`},[`${t}-centered`]:{[t]:{flex:1}}}}},{[t]:{...Do(e),pointerEvents:`none`,position:`relative`,top:100,width:`auto`,maxWidth:`calc(100vw - ${q(e.calc(e.margin).mul(2).equal())})`,margin:`0 auto`,"&:focus-visible":{borderRadius:e.borderRadiusLG,...Ao(e)},[`${t}-title`]:{margin:0,color:e.titleColor,fontWeight:e.fontWeightStrong,fontSize:e.titleFontSize,lineHeight:e.titleLineHeight,wordWrap:`break-word`},[`${t}-container`]:{position:`relative`,backgroundColor:e.contentBg,backgroundClip:`padding-box`,border:0,borderRadius:e.borderRadiusLG,boxShadow:e.boxShadow,pointerEvents:`auto`,padding:e.contentPadding},[`${t}-close`]:{position:`absolute`,top:e.calc(e.modalHeaderHeight).sub(e.modalCloseBtnSize).div(2).equal(),insetInlineEnd:e.calc(e.modalHeaderHeight).sub(e.modalCloseBtnSize).div(2).equal(),zIndex:e.calc(e.zIndexPopupBase).add(10).equal(),padding:0,color:e.modalCloseIconColor,fontWeight:e.fontWeightStrong,lineHeight:1,textDecoration:`none`,background:`transparent`,borderRadius:e.borderRadiusSM,width:e.modalCloseBtnSize,height:e.modalCloseBtnSize,border:0,outline:0,cursor:`pointer`,transition:[`color`,`background-color`].map(e=>`${e} ${n}`).join(`, `),"&-x":{display:`flex`,fontSize:e.fontSizeLG,fontStyle:`normal`,lineHeight:q(e.modalCloseBtnSize),justifyContent:`center`,textTransform:`none`,textRendering:`auto`},"&:disabled":{pointerEvents:`none`},"&:hover":{color:e.modalCloseIconHoverColor,backgroundColor:e.colorBgTextHover,textDecoration:`none`},"&:active":{backgroundColor:e.colorBgTextActive},...jo(e)},[`${t}-header`]:{color:e.colorText,background:e.headerBg,borderRadius:`${q(e.borderRadiusLG)} ${q(e.borderRadiusLG)} 0 0`,marginBottom:e.headerMarginBottom,padding:e.headerPadding,borderBottom:e.headerBorderBottom},[`${t}-body`]:{fontSize:e.fontSize,lineHeight:e.lineHeight,wordWrap:`break-word`,padding:e.bodyPadding,[`${t}-body-skeleton`]:{width:`100%`,height:`100%`,display:`flex`,justifyContent:`center`,alignItems:`center`,margin:`${q(e.margin)} auto`}},[`${t}-footer`]:{textAlign:`end`,background:e.footerBg,marginTop:e.footerMarginTop,padding:e.footerPadding,borderTop:e.footerBorderTop,borderRadius:e.footerBorderRadius,[`> ${e.antCls}-btn + ${e.antCls}-btn`]:{marginInlineStart:e.marginXS}},[`${t}-open`]:{overflow:`hidden`}}},{[`${t}-pure-panel`]:{top:`auto`,padding:0,display:`flex`,flexDirection:`column`,[`${t}-container, - ${t}-body, - ${t}-confirm-body-wrapper`]:{display:`flex`,flexDirection:`column`,flex:`auto`},[`${t}-confirm-body`]:{marginBottom:`auto`}}}]},Ig=e=>{let{componentCls:t}=e;return{[`${t}-root`]:{[`${t}-wrap-rtl`]:{direction:`rtl`,[`${t}-confirm-body`]:{direction:`rtl`}}}}},Lg=e=>{let{componentCls:t}=e,n=Mg(e),r={...n};delete r.xs;let i=`--${t.replace(`.`,``)}-`,a=Object.keys(r).map(e=>({[`@media (min-width: ${q(r[e])})`]:{width:`var(${i}${e}-width)`}}));return{[`${t}-root`]:{[t]:[].concat(At(Object.keys(n).map((e,t)=>{let r=Object.keys(n)[t-1];return r?{[`${i}${e}-width`]:`var(${i}${r}-width)`}:null})),[{width:`var(${i}xs-width)`}],At(a))}}},Rg=e=>{let t=e.padding,n=e.fontSizeHeading5,r=e.lineHeightHeading5;return Yi(e,{modalHeaderHeight:e.calc(e.calc(r).mul(n).equal()).add(e.calc(t).mul(2).equal()).equal(),modalFooterBorderColorSplit:e.colorSplit,modalFooterBorderStyle:e.lineType,modalFooterBorderWidth:e.lineWidth,modalCloseIconColor:e.colorIcon,modalCloseIconHoverColor:e.colorIconHover,modalCloseBtnSize:e.controlHeight,modalConfirmIconSize:e.fontHeight,modalTitleHeight:e.calc(e.titleFontSize).mul(e.titleLineHeight).equal()})},zg=e=>({footerBg:`transparent`,headerBg:`transparent`,titleLineHeight:e.lineHeightHeading5,titleFontSize:e.fontSizeHeading5,contentBg:e.colorBgElevated,titleColor:e.colorTextHeading,contentPadding:e.wireframe?0:`${q(e.paddingMD)} ${q(e.paddingContentHorizontalLG)}`,headerPadding:e.wireframe?`${q(e.padding)} ${q(e.paddingLG)}`:0,headerBorderBottom:e.wireframe?`${q(e.lineWidth)} ${e.lineType} ${e.colorSplit}`:`none`,headerMarginBottom:e.wireframe?0:e.marginXS,bodyPadding:e.wireframe?e.paddingLG:0,footerPadding:e.wireframe?`${q(e.paddingXS)} ${q(e.padding)}`:0,footerBorderTop:e.wireframe?`${q(e.lineWidth)} ${e.lineType} ${e.colorSplit}`:`none`,footerBorderRadius:e.wireframe?`0 0 ${q(e.borderRadiusLG)} ${q(e.borderRadiusLG)}`:0,footerMarginTop:e.wireframe?0:e.marginSM,confirmBodyPadding:e.wireframe?`${q(e.padding*2)} ${q(e.padding*2)} ${q(e.paddingLG)}`:0,confirmIconMarginInlineEnd:e.wireframe?e.margin:e.marginSM,confirmBtnsMarginTop:e.wireframe?e.marginLG:e.marginSM,mask:!0}),Bg=Io(`Modal`,e=>{let t=Rg(e);return[Fg(t),Ig(t),Pg(t),Nf(t,`zoom`),Lg(t)]},zg,{unitless:{titleLineHeight:!0}}),Vg;zh()&&document.documentElement.addEventListener(`click`,e=>{Vg={x:e.pageX,y:e.pageY},setTimeout(()=>{Vg=null},100)},!0);var Hg=e=>{let{prefixCls:t,className:n,rootClassName:r,open:i,wrapClassName:a,centered:o,getContainer:s,style:c,width:l=520,footer:u,classNames:d,styles:f,children:p,loading:h,confirmLoading:g,zIndex:_,mousePosition:v,onOk:y,onCancel:b,okButtonProps:x,cancelButtonProps:S,destroyOnHidden:C,destroyOnClose:w,panelRef:T=null,closable:E,mask:D,modalRender:O,maskClosable:k,focusTriggerAfterClose:A,focusable:j,...M}=e,{getPopupContainer:N,getPrefixCls:P,direction:F,className:I,style:L,classNames:ee,styles:R,centered:z,cancelButtonProps:B,okButtonProps:V,mask:te}=Ht(`modal`),{modal:ne}=m.useContext(zt),[re,ie]=m.useMemo(()=>typeof E==`boolean`?[void 0,void 0]:[E?.afterClose,E?.onClose],[E]),ae=P(`modal`,t),oe=P(),[H,se,ce]=tl(D,te,ae,k),le=Bh(j,H,A),U=e=>{g||(b?.(e),ie?.())},ue=e=>{y?.(e),ie?.()},de=yl(ae),[fe,pe]=Bg(ae,de),me=K(a,{[`${ae}-centered`]:o??z,[`${ae}-wrap-rtl`]:F===`rtl`}),he=u!==null&&!h?m.createElement(Cg,{...e,okButtonProps:{...V,...x},onOk:ue,cancelButtonProps:{...B,...S},onCancel:U}):null,[ge,_e,W,ve]=Qc(Kc(e),Kc(ne),{closable:!0,closeIcon:m.createElement(_s,{className:`${ae}-close-icon`}),closeIconRender:e=>Sg(ae,e)}),ye=ge?{disabled:W,closeIcon:_e,afterClose:re,...ve}:!1,G=O?e=>m.createElement(`div`,{className:`${ae}-render`},O(e)):void 0,be=Me(T,yg(`.${ae}-${O?`render`:`container`}`)),[xe,Se]=vl(`Modal`,_),Ce={...e,width:l,panelRef:T,focusTriggerAfterClose:le.focusTriggerAfterClose,focusable:le,mask:H,maskClosable:ce,zIndex:xe},[we,Te]=cl([ee,d,se],[R,f],{props:Ce}),[Ee,De]=m.useMemo(()=>l&&typeof l==`object`?[void 0,l]:[l,void 0],[l]),Oe=m.useMemo(()=>{let e={};return De&&Object.keys(De).forEach(t=>{let n=De[t];n!==void 0&&(e[`--${ae}-${t}-width`]=typeof n==`number`?`${n}px`:n)}),e},[ae,De]);return m.createElement(Fh,{form:!0,space:!0},m.createElement(fl.Provider,{value:Se},m.createElement(Kp,{width:Ee,...M,zIndex:xe,getContainer:s===void 0?N:s,prefixCls:ae,rootClassName:K(fe,r,pe,de,we.root),rootStyle:Te.root,footer:he,visible:i,mousePosition:v??Vg,onClose:U,closable:ye,closeIcon:_e,transitionName:Id(oe,`zoom`,e.transitionName),maskTransitionName:Id(oe,`fade`,e.maskTransitionName),mask:H,maskClosable:ce,className:K(fe,n,I),style:{...L,...c,...Oe},classNames:{...we,wrapper:K(we.wrapper,me)},styles:Te,panelRef:be,destroyOnHidden:C??w,modalRender:G,focusTriggerAfterClose:le.focusTriggerAfterClose,focusTrap:le.trap},h?m.createElement(gg,{active:!0,title:!1,paragraph:{rows:4},className:`${ae}-body-skeleton`}):p)))},Ug=e=>{let{componentCls:t,titleFontSize:n,titleLineHeight:r,modalConfirmIconSize:i,fontSize:a,lineHeight:o,modalTitleHeight:s,fontHeight:c,confirmBodyPadding:l}=e,u=`${t}-confirm`;return{[u]:{"&-rtl":{direction:`rtl`},[`${e.antCls}-modal-header`]:{display:`none`},[`${u}-body-wrapper`]:{...ko()},[`&${t} ${t}-body`]:{padding:l},[`${u}-body`]:{display:`flex`,flexWrap:`nowrap`,alignItems:`start`,[`> ${e.iconCls}`]:{flex:`none`,fontSize:i,marginInlineEnd:e.confirmIconMarginInlineEnd,marginTop:e.calc(e.calc(c).sub(i).equal()).div(2).equal()},[`&-has-title > ${e.iconCls}`]:{marginTop:e.calc(e.calc(s).sub(i).equal()).div(2).equal()}},[`${u}-paragraph`]:{display:`flex`,flexDirection:`column`,flex:`auto`,rowGap:e.marginXS,maxWidth:`calc(100% - ${q(e.marginSM)})`},[`${u}-body-no-icon ${u}-paragraph`]:{maxWidth:`100%`},[`${e.iconCls} + ${u}-paragraph`]:{maxWidth:`calc(100% - ${q(e.calc(e.modalConfirmIconSize).add(e.marginSM).equal())})`},[`${u}-title`]:{color:e.colorTextHeading,fontWeight:e.fontWeightStrong,fontSize:n,lineHeight:r},[`${u}-container`]:{color:e.colorText,fontSize:a,lineHeight:o},[`${u}-btns`]:{textAlign:`end`,marginTop:e.confirmBtnsMarginTop,[`${e.antCls}-btn + ${e.antCls}-btn`]:{marginBottom:0,marginInlineStart:e.marginXS}}},[`${u}-error ${u}-body > ${e.iconCls}`]:{color:e.colorError},[`${u}-warning ${u}-body > ${e.iconCls}, - ${u}-confirm ${u}-body > ${e.iconCls}`]:{color:e.colorWarning},[`${u}-info ${u}-body > ${e.iconCls}`]:{color:e.colorInfo},[`${u}-success ${u}-body > ${e.iconCls}`]:{color:e.colorSuccess}}},Wg=Ro([`Modal`,`confirm`],e=>Ug(Rg(e)),zg,{order:-1e3}),Gg=e=>{let{prefixCls:t,icon:n,okText:r,cancelText:i,confirmPrefixCls:a,type:o,okCancel:s,footer:c,locale:l,autoFocusButton:u,focusable:d,...f}=e,p=n;if(!n&&n!==null)switch(o){case`info`:p=m.createElement(Cs,null);break;case`success`:p=m.createElement(ds,null);break;case`error`:p=m.createElement(ms,null);break;default:p=m.createElement(bs,null)}let h=s??o===`confirm`,g=m.useMemo(()=>{let e=d?.autoFocusButton||u;return e||e===null?e:`ok`},[u,d?.autoFocusButton]),[_]=Vc(`Modal`),v=l||_,y=r||(h?v?.okText:v?.justOkText),b=i||v?.cancelText,{closable:x}=f,{onClose:S}=x&&typeof x==`object`?x:{},C=m.useMemo(()=>({autoFocusButton:g,cancelTextLocale:b,okTextLocale:y,mergedOkCancel:h,onClose:S,...f}),[g,b,y,h,S,f]),w=m.createElement(m.Fragment,null,m.createElement(gp,null),m.createElement(_p,null)),T=Gc(e.title)&&e.title!==``,E=Gc(p),D=`${a}-body`;return m.createElement(`div`,{className:`${a}-body-wrapper`},m.createElement(`div`,{className:K(D,{[`${D}-has-title`]:T,[`${D}-no-icon`]:!E})},p,m.createElement(`div`,{className:`${a}-paragraph`},T&&m.createElement(`span`,{className:`${a}-title`},e.title),m.createElement(`div`,{className:`${a}-content`},e.content))),c===void 0||typeof c==`function`?m.createElement(hp,{value:C},m.createElement(`div`,{className:`${a}-btns`},typeof c==`function`?c(w,{OkBtn:_p,CancelBtn:gp}):w)):c,m.createElement(Wg,{prefixCls:t}))},Kg=e=>{let{close:t,zIndex:n,maskStyle:r,direction:i,prefixCls:a,wrapClassName:o,rootPrefixCls:s,bodyStyle:c,closable:l=!1,onConfirm:u,styles:d,title:f,mask:p,maskClosable:h,okButtonProps:g,cancelButtonProps:_}=e,{cancelButtonProps:v,okButtonProps:y}=Ht(`modal`),b=`${a}-confirm`,x=e.width||416,S=e.style||{},C=K(b,`${b}-${e.type}`,{[`${b}-rtl`]:i===`rtl`},e.className),w=m.useMemo(()=>{let e=el(p,h);return e.closable??=!1,e},[p,h]),[,T]=Eo(),E=m.useMemo(()=>n===void 0?T.zIndexPopupBase+ml:n,[n,T]);return m.createElement(Hg,{...e,className:C,wrapClassName:K({[`${b}-centered`]:!!e.centered},o),onCancel:()=>{t?.({triggerCancel:!0}),u?.(!1)},title:f,footer:null,transitionName:Id(s||``,`zoom`,e.transitionName),maskTransitionName:Id(s||``,`fade`,e.maskTransitionName),mask:w,style:S,styles:{body:c,mask:r,...d},width:x,zIndex:E,closable:l},m.createElement(Gg,{...e,confirmPrefixCls:b,okButtonProps:{...y,...g},cancelButtonProps:{...v,..._}}))},qg=e=>{let{rootPrefixCls:t,iconPrefixCls:n,direction:r,theme:i}=e;return m.createElement(Xu,{prefixCls:t,iconPrefixCls:n,direction:r,theme:i},m.createElement(Kg,{...e}))},Jg=[];function Yg(e){return{...e,type:`warning`}}function Xg(e){return{...e,type:`info`}}function Zg(e){return{...e,type:`success`}}function Qg(e){return{...e,type:`error`}}function $g(e){return{...e,type:`confirm`}}var e_=m.forwardRef((e,t)=>{let{afterClose:n,config:r,...i}=e,[a,o]=m.useState(!0),[s,c]=m.useState(r),{direction:l,getPrefixCls:u}=m.useContext(zt),d=u(`modal`),f=u(),p=()=>{n(),s.afterClose?.()},h=(...e)=>{o(!1),e.some(e=>e?.triggerCancel)&&s.onCancel?.(()=>{},...e.slice(1))};m.useImperativeHandle(t,()=>({destroy:h,update:e=>{c(t=>{let n=typeof e==`function`?e(t):e;return{...t,...n}})}}));let g=s.okCancel??s.type===`confirm`,[_]=Vc(`Modal`,Pc.Modal);return m.createElement(qg,{prefixCls:d,rootPrefixCls:f,...s,close:h,open:a,afterClose:p,okText:s.okText||(g?_?.okText:_?.justOkText),direction:s.direction||l,cancelText:s.cancelText||_?.cancelText,...i})}),t_=0,n_=m.memo(m.forwardRef((e,t)=>{let[n,r]=dl();return m.useImperativeHandle(t,()=>({patchElement:r}),[r]),m.createElement(m.Fragment,null,n)}));function r_(){let e=m.useRef(null),[t,n]=m.useState([]);m.useEffect(()=>{t.length&&(At(t).forEach(e=>{e()}),n([]))},[t]);let r=m.useCallback(t=>function(r){t_+=1;let i=m.createRef(),a,o=new Promise(e=>{a=e}),s=!1,c,l=m.createElement(e_,{key:`modal-${t_}`,config:t(r),ref:i,afterClose:()=>{c?.()},isSilent:()=>s,onConfirm:e=>{a(e)}});return c=e.current?.patchElement(l),c&&Jg.push(c),{destroy:()=>{function e(){i.current?.destroy()}i.current?e():n(t=>[].concat(At(t),[e]))},update:e=>{function t(){i.current?.update(e)}i.current?t():n(e=>[].concat(At(e),[t]))},then:e=>(s=!0,o.then(e))}},[]);return[m.useMemo(()=>({info:r(Xg),success:r(Zg),error:r(Qg),warning:r(Yg),confirm:r($g)}),[r]),m.createElement(n_,{key:`modal-holder`,ref:e})]}var i_=e=>{let{componentCls:t,notificationMarginEdge:n,animationMaxHeight:r}=e,i=`${t}-notice`,a=new gi(`antNotificationFadeIn`,{"0%":{transform:`translate3d(100%, 0, 0)`,opacity:0},"100%":{transform:`translate3d(0, 0, 0)`,opacity:1}}),o=new gi(`antNotificationTopFadeIn`,{"0%":{top:-r,opacity:0},"100%":{top:0,opacity:1}}),s=new gi(`antNotificationBottomFadeIn`,{"0%":{bottom:e.calc(r).mul(-1).equal(),opacity:0},"100%":{bottom:0,opacity:1}}),c=new gi(`antNotificationLeftFadeIn`,{"0%":{transform:`translate3d(-100%, 0, 0)`,opacity:0},"100%":{transform:`translate3d(0, 0, 0)`,opacity:1}});return{[t]:{[`&${t}-top, &${t}-bottom`]:{marginInline:0,[i]:{marginInline:`auto auto`}},[`&${t}-top`]:{[`${t}-fade-enter${t}-fade-enter-active, ${t}-fade-appear${t}-fade-appear-active`]:{animationName:o}},[`&${t}-bottom`]:{[`${t}-fade-enter${t}-fade-enter-active, ${t}-fade-appear${t}-fade-appear-active`]:{animationName:s}},[`&${t}-topRight, &${t}-bottomRight`]:{[`${t}-fade-enter${t}-fade-enter-active, ${t}-fade-appear${t}-fade-appear-active`]:{animationName:a}},[`&${t}-topLeft, &${t}-bottomLeft`]:{marginRight:{value:0,_skip_check_:!0},marginLeft:{value:n,_skip_check_:!0},[i]:{marginInlineEnd:`auto`,marginInlineStart:0},[`${t}-fade-enter${t}-fade-enter-active, ${t}-fade-appear${t}-fade-appear-active`]:{animationName:c}}}}},a_=[`top`,`topLeft`,`topRight`,`bottom`,`bottomLeft`,`bottomRight`],o_={topLeft:`left`,topRight:`right`,bottomLeft:`left`,bottomRight:`right`,top:`left`,bottom:`left`},s_=(e,t)=>{let{componentCls:n}=e;return{[`${n}-${t}`]:{[`&${n}-stack > ${n}-notice-wrapper`]:{[t.startsWith(`top`)?`top`:`bottom`]:0,[o_[t]]:{value:0,_skip_check_:!0}}}}},c_=e=>{let t={};for(let n=1;n ${e.componentCls}-notice`]:{opacity:0,transition:`opacity ${e.motionDurationMid}`}};return{[`&:not(:nth-last-child(-n+${e.notificationStackLayer}))`]:{opacity:0,overflow:`hidden`,color:`transparent`,pointerEvents:`none`},...t}},l_=e=>{let t={};for(let n=1;n{let{componentCls:t}=e;return{[`${t}-stack`]:{[`& > ${t}-notice-wrapper`]:{transition:`transform ${e.motionDurationSlow}, backdrop-filter 0s`,willChange:`transform, opacity`,position:`absolute`,...c_(e)}},[`${t}-stack:not(${t}-stack-expanded)`]:{[`& > ${t}-notice-wrapper`]:{...l_(e)}},[`${t}-stack${t}-stack-expanded`]:{[`& > ${t}-notice-wrapper`]:{"&:not(:nth-last-child(-n + 1))":{opacity:1,overflow:`unset`,color:`inherit`,pointerEvents:`auto`,[`& > ${e.componentCls}-notice`]:{opacity:1}},"&:after":{content:`""`,position:`absolute`,height:e.margin,width:`100%`,insetInline:0,bottom:e.calc(e.margin).mul(-1).equal(),background:`transparent`,pointerEvents:`auto`}}},...a_.map(t=>s_(e,t)).reduce((e,t)=>({...e,...t}),{})}},d_=e=>{let{iconCls:t,componentCls:n,boxShadow:r,fontSizeLG:i,notificationMarginBottom:a,borderRadiusLG:o,colorSuccess:s,colorInfo:c,colorWarning:l,colorError:u,colorTextHeading:d,notificationBg:f,notificationPadding:p,notificationMarginEdge:m,progressBg:h,notificationProgressHeight:g,fontSize:_,lineHeight:v,width:y,notificationIconSize:b,colorText:x,colorSuccessBg:S,colorErrorBg:C,colorInfoBg:w,colorWarningBg:T,motionDurationMid:E}=e,D=`${n}-notice`;return{position:`relative`,marginBottom:a,marginInlineStart:`auto`,background:f,borderRadius:o,boxShadow:r,[D]:{padding:p,width:y,maxWidth:`calc(100vw - ${q(e.calc(m).mul(2).equal())})`,lineHeight:v,wordWrap:`break-word`,borderRadius:o,overflow:`hidden`,"&-success":S?{background:S}:{},"&-error":C?{background:C}:{},"&-info":w?{background:w}:{},"&-warning":T?{background:T}:{}},[`${D}-title`]:{marginBottom:e.marginXS,color:d,fontSize:i,lineHeight:e.lineHeightLG},[`${D}-description`]:{fontSize:_,color:x,marginTop:e.marginXS},[`${D}-closable ${D}-title`]:{paddingInlineEnd:e.paddingLG},[`${D}-with-icon ${D}-title`]:{marginBottom:e.marginXS,marginInlineStart:e.calc(e.marginSM).add(b).equal(),fontSize:i},[`${D}-with-icon ${D}-description`]:{marginInlineStart:e.calc(e.marginSM).add(b).equal(),fontSize:_},[`${D}-icon`]:{position:`absolute`,fontSize:b,lineHeight:1,[`&-success${t}`]:{color:s},[`&-info${t}`]:{color:c},[`&-warning${t}`]:{color:l},[`&-error${t}`]:{color:u}},[`${D}-close`]:{position:`absolute`,top:e.notificationPaddingVertical,insetInlineEnd:e.notificationPaddingHorizontal,color:e.colorIcon,outline:`none`,width:e.notificationCloseButtonSize,height:e.notificationCloseButtonSize,borderRadius:e.borderRadiusSM,transition:[`color`,`background-color`].map(e=>`${e} ${E}`).join(`, `),display:`flex`,alignItems:`center`,justifyContent:`center`,background:`none`,border:`none`,"&:hover":{color:e.colorIconHover,backgroundColor:e.colorBgTextHover},"&:active":{backgroundColor:e.colorBgTextActive},...jo(e)},[`${D}-progress`]:{position:`absolute`,display:`block`,appearance:`none`,inlineSize:`calc(100% - ${q(o)} * 2)`,left:{_skip_check_:!0,value:o},right:{_skip_check_:!0,value:o},bottom:0,blockSize:g,border:0,"&, &::-webkit-progress-bar":{borderRadius:o,backgroundColor:`rgba(0, 0, 0, 0.04)`},"&::-moz-progress-bar":{background:h},"&::-webkit-progress-value":{borderRadius:o,background:h}},[`${D}-actions`]:{float:`right`,marginTop:e.marginSM}}},f_=e=>{let{componentCls:t,notificationMarginBottom:n,notificationMarginEdge:r,motionDurationMid:i,motionEaseInOut:a}=e,o=`${t}-notice`,s=new gi(`antNotificationFadeOut`,{"0%":{maxHeight:e.animationMaxHeight,marginBottom:n},"100%":{maxHeight:0,marginBottom:0,paddingTop:0,paddingBottom:0,opacity:0}});return[{[t]:{...Do(e),position:`fixed`,zIndex:e.zIndexPopup,marginRight:{value:r,_skip_check_:!0},[`${t}-hook-holder`]:{position:`relative`},[`${t}-fade-appear-prepare`]:{opacity:`0 !important`},[`${t}-fade-enter, ${t}-fade-appear`]:{animationDuration:e.motionDurationMid,animationTimingFunction:a,animationFillMode:`both`,opacity:0,animationPlayState:`paused`},[`${t}-fade-leave`]:{animationTimingFunction:a,animationFillMode:`both`,animationDuration:i,animationPlayState:`paused`},[`${t}-fade-enter${t}-fade-enter-active, ${t}-fade-appear${t}-fade-appear-active`]:{animationPlayState:`running`},[`${t}-fade-leave${t}-fade-leave-active`]:{animationName:s,animationPlayState:`running`},"&-rtl":{direction:`rtl`,[`${o}-actions`]:{float:`left`}}}},{[t]:{[`${o}-wrapper`]:d_(e)}}]},p_=e=>({zIndexPopup:e.zIndexPopupBase+ml+50,width:384,progressBg:`linear-gradient(90deg, ${e.colorPrimaryBorderHover}, ${e.colorPrimary})`,colorSuccessBg:void 0,colorErrorBg:void 0,colorInfoBg:void 0,colorWarningBg:void 0}),m_=e=>{let t=e.paddingMD,n=e.paddingLG;return Yi(e,{notificationBg:e.colorBgElevated,notificationPaddingVertical:t,notificationPaddingHorizontal:n,notificationIconSize:e.calc(e.fontSizeLG).mul(e.lineHeightLG).equal(),notificationCloseButtonSize:e.calc(e.controlHeightLG).mul(.55).equal(),notificationMarginBottom:e.margin,notificationPadding:`${q(e.paddingMD)} ${q(e.paddingContentHorizontalLG)}`,notificationMarginEdge:e.marginLG,animationMaxHeight:150,notificationStackLayer:3,notificationProgressHeight:2})},h_=Io(`Notification`,e=>{let t=m_(e);return[f_(t),i_(t),u_(t)]},p_);function g_(e,t){return t===null||t===!1?null:t||m.createElement(_s,{className:`${e}-close-icon`})}var __={success:ds,info:Cs,error:ms,warning:bs},v_=e=>{let{prefixCls:t,icon:n,type:r,title:i,description:a,actions:o,role:s=`alert`,styles:c,classNames:l}=e,u=null;return n?u=m.createElement(`span`,{className:K(`${t}-icon`,l.icon),style:c.icon},n):r&&(u=m.createElement(__[r]||null,{className:K(`${t}-icon`,l.icon,`${t}-icon-${r}`),style:c.icon})),m.createElement(`div`,{className:K({[`${t}-with-icon`]:u}),role:s},u,m.createElement(`div`,{className:K(`${t}-title`,l.title),style:c.title},i),a&&m.createElement(`div`,{className:K(`${t}-description`,l.description),style:c.description},a),o&&m.createElement(`div`,{className:K(`${t}-actions`,l.actions),style:c.actions},o))};function y_(e,t,n){let r;switch(e){case`top`:r={left:`50%`,transform:`translateX(-50%)`,right:`auto`,top:t,bottom:`auto`};break;case`topLeft`:r={left:0,top:t,bottom:`auto`};break;case`topRight`:r={right:0,top:t,bottom:`auto`};break;case`bottom`:r={left:`50%`,transform:`translateX(-50%)`,right:`auto`,top:`auto`,bottom:n};break;case`bottomLeft`:r={left:0,top:`auto`,bottom:n};break;default:r={right:0,top:`auto`,bottom:n};break}return r}function b_(e){return{motionName:`${e}-fade`}}function x_(e,t,n){return e===void 0?t?.closeIcon===void 0?n?.closeIcon:t.closeIcon:e}var S_=24,C_=4.5,w_=`topRight`,T_=({children:e,prefixCls:t})=>{let n=yl(t),[r,i]=h_(t,n);return m.createElement(ed,{classNames:{list:K(r,i,n)}},e)},E_=(e,{prefixCls:t,key:n})=>m.createElement(T_,{prefixCls:t,key:n},e),D_=m.forwardRef((e,t)=>{let{top:n,bottom:r,prefixCls:i,getContainer:a,maxCount:o,rtl:s,onAllRemoved:c,stack:l,duration:u=C_,pauseOnHover:d=!0,showProgress:f}=e,{getPrefixCls:p,getPopupContainer:h,direction:g}=Ht(`notification`),{notification:_}=(0,m.useContext)(zt),[,v]=Eo(),y=i||p(`notification`),b=(0,m.useMemo)(()=>typeof u==`number`&&u>0?u:!1,[u]),[x,S]=dd({prefixCls:y,style:e=>y_(e,n??S_,r??S_),className:()=>K({[`${y}-rtl`]:s??g===`rtl`}),motion:()=>b_(y),closable:{closeIcon:g_(y)},duration:b,getContainer:()=>a?.()||h?.()||document.body,maxCount:o,pauseOnHover:d,showProgress:f,onAllRemoved:c,renderNotifications:E_,stack:l===!1?!1:{threshold:typeof l==`object`?l?.threshold:void 0,offset:8,gap:v.margin}}),[C,w]=cl([_?.classNames,e?.classNames],[_?.styles,e?.styles],{props:e});return m.useImperativeHandle(t,()=>({...x,prefixCls:y,notification:_,classNames:C,styles:w})),S});function O_(e){let t=m.useRef(null);ot(`Notification`);let{notification:n}=m.useContext(zt);return[m.useMemo(()=>{let r=r=>{if(!t.current)return;let{open:i,prefixCls:a,notification:o,classNames:s,styles:c}=t.current,l=o?.className||{},u=o?.style||{},d=`${a}-notice`,{title:f,message:p,description:h,icon:g,type:_,btn:v,actions:y,className:b,style:x,role:S=`alert`,closeIcon:C,closable:w,classNames:T={},styles:E={},...D}=r,O=f??p,k=y??v,A=g_(d,x_(C,e,o)),[j,M,,N]=Zc(Kc({...e||{},...r}),Kc(n),{closable:!0,closeIcon:A}),P=j?{onClose:w&&typeof w==`object`?w.onClose:void 0,closeIcon:M,...N}:!1,F=sl(T,{props:r}),I=sl(E,{props:r}),L=nl(void 0,s,F),ee=il(c,I);return i({placement:e?.placement??w_,...D,content:m.createElement(v_,{prefixCls:d,icon:g,type:_,title:O,description:h,actions:k,role:S,classNames:L,styles:ee}),className:K({[`${d}-${_}`]:_},b,l,L.root),style:{...u,...ee.root,...x},closable:P})},i={open:r,destroy:e=>{e===void 0?t.current?.destroy():t.current?.close(e)}};return[`success`,`info`,`warning`,`error`].forEach(e=>{i[e]=t=>r({...t,type:e})}),i},[e,n]),m.createElement(D_,{key:`notification-holder`,...e,ref:t})]}function k_(e){return O_(e)}var A_=m.createContext({}),j_=m.createContext({message:{},notification:{},modal:{}}),M_=Io(`App`,e=>{let{componentCls:t,colorText:n,fontSize:r,lineHeight:i,fontFamily:a}=e;return{[t]:{color:n,fontSize:r,lineHeight:i,fontFamily:a,[`&${t}-rtl`]:{direction:`rtl`}}}},()=>({})),N_=e=>{let{prefixCls:t,children:n,className:r,rootClassName:i,message:a,notification:o,style:s,component:c=`div`}=e,{direction:l,getPrefixCls:u,className:d,style:f}=Ht(`app`),p=u(`app`,t),[h,g]=M_(p),_=K(h,p,r,i,g,{[`${p}-rtl`]:l===`rtl`}),v=(0,m.useContext)(A_),y=m.useMemo(()=>({message:{...v.message,...a},notification:{...v.notification,...o}}),[a,o,v.message,v.notification]),[b,x]=Od(y.message),[S,C]=k_(y.notification),[w,T]=r_(),E=m.useMemo(()=>({message:b,notification:S,modal:w}),[b,S,w]);ot(`App`)(!(g&&c===!1),`usage`,"When using cssVar, ensure `component` is assigned a valid React component string.");let D=c===!1?m.Fragment:c,O={className:K(d,_),style:{...f,...s}};return m.createElement(j_.Provider,{value:E},m.createElement(A_.Provider,{value:y},m.createElement(D,{...c===!1?void 0:O},T,x,C,n)))},P_=()=>m.useContext(j_),F_=N_;F_.useApp=P_;var I_=(e,t,n)=>K({[`${e}-status-success`]:t===`success`,[`${e}-status-warning`]:t===`warning`,[`${e}-status-error`]:t===`error`,[`${e}-status-validating`]:t===`validating`,[`${e}-has-feedback`]:n}),L_=(e,t)=>t||e,R_=(e,t,n)=>{let{variant:r,[e]:i}=m.useContext(zt),a=m.useContext(Ph),o=i?.variant,s;s=t===void 0?n===!1?`borderless`:a??o??r??`outlined`:t;let c=Rt.includes(s);return[s,c]},z_={icon:{tag:`svg`,attrs:{viewBox:`64 64 896 896`,focusable:`false`},children:[{tag:`path`,attrs:{d:`M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 00-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z`}}]},name:`check`,theme:`outlined`};function B_(){return B_=Object.assign?Object.assign.bind():function(e){for(var t=1;tm.createElement(ls,B_({},e,{ref:t,icon:z_}))),H_=[`xxxl`,`xxl`,`xl`,`lg`,`md`,`sm`,`xs`];[].concat(H_).reverse();var U_=e=>({xs:`(max-width: ${e.screenXSMax}px)`,sm:`(min-width: ${e.screenSM}px)`,md:`(min-width: ${e.screenMD}px)`,lg:`(min-width: ${e.screenLG}px)`,xl:`(min-width: ${e.screenXL}px)`,xxl:`(min-width: ${e.screenXXL}px)`,xxxl:`(min-width: ${e.screenXXXL}px)`}),W_=e=>{let t=e,n=[].concat(H_).reverse();return n.forEach((e,r)=>{let i=e.toUpperCase(),a=`screen${i}Min`,o=`screen${i}`;if(!(t[a]<=t[o]))throw Error(`${a}<=${o} fails : !(${t[a]}<=${t[o]})`);if(r{let[,e]=Eo(),t=U_(W_(e));return m.useMemo(()=>{let e=new Map,n=-1,r={};return{responsiveMap:t,matchHandlers:{},dispatch(t){return r=t,e.forEach(e=>{e(r)}),e.size>=1},subscribe(t){return e.size||this.register(),n+=1,e.set(n,t),t(r),n},unsubscribe(t){e.delete(t),e.size||this.unregister()},register(){Object.entries(t).forEach(([e,t])=>{let n=({matches:t})=>{this.dispatch({...r,[e]:t})},i=window.matchMedia(t);typeof i?.addEventListener==`function`&&i.addEventListener(`change`,n),this.matchHandlers[t]={mql:i,listener:n},n(i)})},unregister(){Object.values(t).forEach(e=>{let t=this.matchHandlers[e];typeof t?.mql?.removeEventListener==`function`&&t.mql.removeEventListener(`change`,t?.listener)}),e.clear()}}},[t])};function K_(e=!0,t={}){let n=(0,m.useRef)(t),[,r]=$c(),i=G_();return G(()=>{let t=i.subscribe(t=>{n.current=t,e&&r()});return()=>i.unsubscribe(t)},[]),n.current}var q_=e=>{let{children:t,prefixCls:n,id:r,classNames:i,styles:a,className:o,style:s}=e;return m.createElement(`div`,{id:r,className:K(`${n}-container`,i?.container,o),style:{...a?.container,...s},role:`tooltip`},typeof t==`function`?t():t)},J_={shiftX:64,adjustY:1},Y_={adjustX:1,shiftY:!0},X_=[0,0],Z_={left:{points:[`cr`,`cl`],overflow:Y_,offset:[-4,0],targetOffset:X_},right:{points:[`cl`,`cr`],overflow:Y_,offset:[4,0],targetOffset:X_},top:{points:[`bc`,`tc`],overflow:J_,offset:[0,-4],targetOffset:X_},bottom:{points:[`tc`,`bc`],overflow:J_,offset:[0,4],targetOffset:X_},topLeft:{points:[`bl`,`tl`],overflow:J_,offset:[0,-4],targetOffset:X_},leftTop:{points:[`tr`,`tl`],overflow:Y_,offset:[-4,0],targetOffset:X_},topRight:{points:[`br`,`tr`],overflow:J_,offset:[0,-4],targetOffset:X_},rightTop:{points:[`tl`,`tr`],overflow:Y_,offset:[4,0],targetOffset:X_},bottomRight:{points:[`tr`,`br`],overflow:J_,offset:[0,4],targetOffset:X_},rightBottom:{points:[`bl`,`br`],overflow:Y_,offset:[4,0],targetOffset:X_},bottomLeft:{points:[`tl`,`bl`],overflow:J_,offset:[0,4],targetOffset:X_},leftBottom:{points:[`br`,`bl`],overflow:Y_,offset:[-4,0],targetOffset:X_}};function Q_(){return Q_=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{trigger:n=[`hover`],mouseEnterDelay:r=0,mouseLeaveDelay:i=.1,prefixCls:a=`rc-tooltip`,children:o,onVisibleChange:s,afterVisibleChange:c,motion:l,placement:u=`right`,align:d={},destroyOnHidden:f=!1,defaultVisible:p,getTooltipContainer:h,arrowContent:g,overlay:_,id:v,showArrow:y=!0,classNames:b,styles:x,...S}=e,C=Ll(v),w=(0,m.useRef)(null);(0,m.useImperativeHandle)(t,()=>w.current);let T={...S};`visible`in e&&(T.popupVisible=e.visible);let E=m.useMemo(()=>{if(!y)return!1;let e=y===!0?{}:y;return{...e,className:K(e.className,b?.arrow),style:{...e.style,...x?.arrow},content:e.content??g}},[y,b?.arrow,x?.arrow,g]);return m.createElement(ku,Q_({popupClassName:b?.root,prefixCls:a,popup:m.createElement(q_,{key:`content`,prefixCls:a,id:C,classNames:b,styles:x},_),action:n,builtinPlacements:Z_,popupPlacement:u,ref:w,popupAlign:d,getPopupContainer:h,onOpenChange:s,afterOpenChange:c,popupMotion:l,defaultPopupVisible:p,autoDestroy:f,mouseLeaveDelay:i,popupStyle:x?.root,mouseEnterDelay:r,arrow:E,uniqueContainerClassName:b?.uniqueContainer,uniqueContainerStyle:x?.uniqueContainer},T),({open:e})=>{let t=m.Children.only(o),n={"aria-describedby":_&&e?C:void 0};return m.cloneElement(t,n)})});function ev(e){let{sizePopupArrow:t,borderRadiusXS:n,borderRadiusOuter:r}=e,i=t/2,a=i,o=r*1/Math.sqrt(2),s=i-r*(1-1/Math.sqrt(2)),c=i-1/Math.sqrt(2)*n,l=r*(Math.sqrt(2)-1)+1/Math.sqrt(2)*n,u=2*i-c,d=l,f=2*i-o,p=s,m=2*i-0,h=a,g=i*Math.sqrt(2)+r*(Math.sqrt(2)-2),_=r*(Math.sqrt(2)-1),v=`polygon(${_}px 100%, 50% ${_}px, ${2*i-_}px 100%, ${_}px 100%)`;return{arrowShadowWidth:g,arrowPath:`path('M 0 ${a} A ${r} ${r} 0 0 0 ${o} ${s} L ${c} ${l} A ${n} ${n} 0 0 1 ${u} ${d} L ${f} ${p} A ${r} ${r} 0 0 0 ${m} ${h} Z')`,arrowPolygon:v}}var tv=(e,t,n)=>{let{sizePopupArrow:r,arrowPolygon:i,arrowPath:a,arrowShadowWidth:o,borderRadiusXS:s,calc:c}=e;return{pointerEvents:`none`,width:r,height:r,overflow:`hidden`,"&::before":{position:`absolute`,bottom:0,insetInlineStart:0,width:r,height:c(r).div(2).equal(),background:t,clipPath:{_multi_value_:!0,value:[i,a]},content:`""`},"&::after":{content:`""`,position:`absolute`,width:o,height:o,bottom:0,insetInline:0,margin:`auto`,borderRadius:{_skip_check_:!0,value:`0 0 ${q(s)} 0`},transform:`translateY(50%) rotate(-135deg)`,boxShadow:n,zIndex:0,background:`transparent`}}};function nv(e){let{contentRadius:t,limitVerticalRadius:n}=e,r=t>12?t+2:12;return{arrowOffsetHorizontal:r,arrowOffsetVertical:n?8:r}}function rv(e,t){return e?t:{}}var iv=(e,t,n)=>{let{componentCls:r,boxShadowPopoverArrow:i,arrowOffsetVertical:a,arrowOffsetHorizontal:o,antCls:s}=e,[c]=zo(s,`tooltip`),{arrowDistance:l=0,arrowPlacement:u={left:!0,right:!0,top:!0,bottom:!0}}=n||{};return{[r]:{[`${r}-arrow`]:[{position:`absolute`,zIndex:1,display:`block`,...tv(e,t,i),"&:before":{background:t}}],...rv(!!u.top,{[[`&-placement-top > ${r}-arrow`,`&-placement-topLeft > ${r}-arrow`,`&-placement-topRight > ${r}-arrow`].join(`,`)]:{bottom:l,transform:`translateY(100%) rotate(180deg)`},[`&-placement-top > ${r}-arrow`]:{left:{_skip_check_:!0,value:`50%`},transform:`translateX(-50%) translateY(100%) rotate(180deg)`},"&-placement-topLeft":{[c(`arrow-offset-x`)]:o,[`> ${r}-arrow`]:{left:{_skip_check_:!0,value:o}}},"&-placement-topRight":{[c(`arrow-offset-x`)]:`calc(100% - ${q(o)})`,[`> ${r}-arrow`]:{right:{_skip_check_:!0,value:o}}}}),...rv(!!u.bottom,{[[`&-placement-bottom > ${r}-arrow`,`&-placement-bottomLeft > ${r}-arrow`,`&-placement-bottomRight > ${r}-arrow`].join(`,`)]:{top:l,transform:`translateY(-100%)`},[`&-placement-bottom > ${r}-arrow`]:{left:{_skip_check_:!0,value:`50%`},transform:`translateX(-50%) translateY(-100%)`},"&-placement-bottomLeft":{[c(`arrow-offset-x`)]:o,[`> ${r}-arrow`]:{left:{_skip_check_:!0,value:o}}},"&-placement-bottomRight":{[c(`arrow-offset-x`)]:`calc(100% - ${q(o)})`,[`> ${r}-arrow`]:{right:{_skip_check_:!0,value:o}}}}),...rv(!!u.left,{[[`&-placement-left > ${r}-arrow`,`&-placement-leftTop > ${r}-arrow`,`&-placement-leftBottom > ${r}-arrow`].join(`,`)]:{right:{_skip_check_:!0,value:l},transform:`translateX(100%) rotate(90deg)`},[`&-placement-left > ${r}-arrow`]:{top:{_skip_check_:!0,value:`50%`},transform:`translateY(-50%) translateX(100%) rotate(90deg)`},[`&-placement-leftTop > ${r}-arrow`]:{top:a},[`&-placement-leftBottom > ${r}-arrow`]:{bottom:a}}),...rv(!!u.right,{[[`&-placement-right > ${r}-arrow`,`&-placement-rightTop > ${r}-arrow`,`&-placement-rightBottom > ${r}-arrow`].join(`,`)]:{left:{_skip_check_:!0,value:l},transform:`translateX(-100%) rotate(-90deg)`},[`&-placement-right > ${r}-arrow`]:{top:{_skip_check_:!0,value:`50%`},transform:`translateY(-50%) translateX(-100%) rotate(-90deg)`},[`&-placement-rightTop > ${r}-arrow`]:{top:a},[`&-placement-rightBottom > ${r}-arrow`]:{bottom:a}})}}};function av(e,t,n,r){if(r===!1)return{adjustX:!1,adjustY:!1};let i=r&&typeof r==`object`?r:{},a={};switch(e){case`top`:case`bottom`:a.shiftX=t.arrowOffsetHorizontal*2+n,a.shiftY=!0,a.adjustY=!0;break;case`left`:case`right`:a.shiftY=t.arrowOffsetVertical*2+n,a.shiftX=!0,a.adjustX=!0;break}let o={...a,...i};return o.shiftX||(o.adjustX=!0),o.shiftY||(o.adjustY=!0),o}var ov={left:{points:[`cr`,`cl`]},right:{points:[`cl`,`cr`]},top:{points:[`bc`,`tc`]},bottom:{points:[`tc`,`bc`]},topLeft:{points:[`bl`,`tl`]},leftTop:{points:[`tr`,`tl`]},topRight:{points:[`br`,`tr`]},rightTop:{points:[`tl`,`tr`]},bottomRight:{points:[`tr`,`br`]},rightBottom:{points:[`bl`,`br`]},bottomLeft:{points:[`tl`,`bl`]},leftBottom:{points:[`br`,`bl`]}},sv={topLeft:{points:[`bl`,`tc`]},leftTop:{points:[`tr`,`cl`]},topRight:{points:[`br`,`tc`]},rightTop:{points:[`tl`,`cr`]},bottomRight:{points:[`tr`,`bc`]},rightBottom:{points:[`bl`,`cr`]},bottomLeft:{points:[`tl`,`bc`]},leftBottom:{points:[`br`,`cl`]}},cv=new Set([`topLeft`,`topRight`,`bottomLeft`,`bottomRight`,`leftTop`,`leftBottom`,`rightTop`,`rightBottom`]);function lv(e){let{arrowWidth:t,autoAdjustOverflow:n,arrowPointAtCenter:r,offset:i,borderRadius:a,visibleFirst:o}=e,s=t/2,c={},l=nv({contentRadius:a,limitVerticalRadius:!0});return Object.keys(ov).forEach(e=>{let a={...r&&sv[e]||ov[e],offset:[0,0],dynamicInset:!0};switch(c[e]=a,cv.has(e)&&(a.autoArrow=!1),e){case`top`:case`topLeft`:case`topRight`:a.offset[1]=-s-i;break;case`bottom`:case`bottomLeft`:case`bottomRight`:a.offset[1]=s+i;break;case`left`:case`leftTop`:case`leftBottom`:a.offset[0]=-s-i;break;case`right`:case`rightTop`:case`rightBottom`:a.offset[0]=s+i;break}if(r)switch(e){case`topLeft`:case`bottomLeft`:a.offset[0]=-l.arrowOffsetHorizontal-s;break;case`topRight`:case`bottomRight`:a.offset[0]=l.arrowOffsetHorizontal+s;break;case`leftTop`:case`rightTop`:a.offset[1]=-l.arrowOffsetHorizontal*2+s;break;case`leftBottom`:case`rightBottom`:a.offset[1]=l.arrowOffsetHorizontal*2-s;break}a.overflow=av(e,l,t,n),o&&(a.htmlRegion=`visibleFirst`)}),c}var uv=m.createContext(!1),dv=(e,t)=>{let n=e=>typeof e==`boolean`?{show:e}:e||{};return m.useMemo(()=>{let r=n(e),i=n(t);return{...i,...r,show:r.show??i.show??!0}},[e,t])},fv=`50%`,pv=e=>{let{calc:t,componentCls:n,tooltipMaxWidth:r,tooltipColor:i,tooltipBg:a,tooltipBorderRadius:o,zIndexPopup:s,controlHeight:c,boxShadowSecondary:l,paddingSM:u,paddingXS:d,arrowOffsetHorizontal:f,sizePopupArrow:p,antCls:m}=e,[h,g]=zo(m,`tooltip`),_=t(o).add(p).add(f).equal(),v={minWidth:t(o).mul(2).add(p).equal(),minHeight:c,padding:`${q(e.calc(u).div(2).equal())} ${q(d)}`,color:g(`overlay-color`,i),textAlign:`start`,textDecoration:`none`,wordWrap:`break-word`,backgroundColor:a,borderRadius:o,boxShadow:l,boxSizing:`border-box`},y={[h(`valid-offset-x`)]:g(`arrow-offset-x`,`var(--arrow-x)`),transformOrigin:[g(`valid-offset-x`,fv),`var(--arrow-y, ${fv})`].join(` `)};return[{[n]:{...Do(e),position:`absolute`,zIndex:s,display:`block`,width:`max-content`,maxWidth:r,visibility:`visible`,...y,"&-hidden":{display:`none`},[h(`arrow-background-color`)]:a,[`${n}-container`]:[v,vf(e,!0)],[`&:has(~ ${n}-unique-container)`]:{[`${n}-container`]:{border:`none`,background:`transparent`,boxShadow:`none`}},[[`&-placement-topLeft`,`&-placement-topRight`,`&-placement-bottomLeft`,`&-placement-bottomRight`].join(`,`)]:{minWidth:_},[[`&-placement-left`,`&-placement-leftTop`,`&-placement-leftBottom`,`&-placement-right`,`&-placement-rightTop`,`&-placement-rightBottom`].join(`,`)]:{[`${n}-inner`]:{borderRadius:e.min(o,8)}},[`${n}-content`]:{position:`relative`},...Bo(e,(e,{darkColor:t})=>({[`&${n}-${e}`]:{[`${n}-container`]:{backgroundColor:t},[`${n}-arrow`]:{[h(`arrow-background-color`)]:t}}})),"&-rtl":{direction:`rtl`}}},iv(e,g(`arrow-background-color`)),{[`${n}-pure`]:{position:`relative`,maxWidth:`none`,margin:e.sizePopupArrow}},{[`${n}-unique-container`]:{...v,...y,position:`absolute`,zIndex:t(s).sub(1).equal(),"&-hidden":{display:`none`},"&-visible":{transition:`all ${e.motionDurationSlow}`}}}]},mv=e=>({zIndexPopup:e.zIndexPopupBase+70,maxWidth:250,...nv({contentRadius:e.borderRadius,limitVerticalRadius:!0}),...ev(Yi(e,{borderRadiusOuter:Math.min(e.borderRadiusOuter,4)}))}),hv=(e,t,n=!0)=>Io(`Tooltip`,e=>{let{borderRadius:t,colorTextLightSolid:n,colorBgSpotlight:r,maxWidth:i}=e;return[pv(Yi(e,{tooltipMaxWidth:i,tooltipColor:n,tooltipBorderRadius:t,tooltipBg:r})),Nf(e,`zoom-big-fast`)]},mv,{resetStyle:!1,injectStyle:n})(e,t),gv=oa.map(e=>`${e}-inverse`);function _v(e,t=!0){return t?[].concat(At(gv),At(oa)).includes(e):oa.includes(e)}var vv=(e,t,n)=>{let r=_v(n),[i]=zo(e,`tooltip`),a=K({[`${t}-${n}`]:n&&r}),o={},s={},c=Hf(n).toRgb(),l=(.299*c.r+.587*c.g+.114*c.b)/255<.5?`#FFF`:`#000`;return n&&!r&&(o.background=n,o[i(`overlay-color`)]=l,s[i(`arrow-background-color`)]=n),{className:a,overlayStyle:o,arrowStyle:s}},yv=e=>{let{prefixCls:t,className:n,placement:r=`top`,title:i,color:a,overlayInnerStyle:o,classNames:s,styles:c}=e,{getPrefixCls:l}=m.useContext(zt),u=l(`tooltip`,t),d=l(),f=yl(u),[p,h]=hv(u,f),g=vv(d,u,a),_=g.arrowStyle,v=m.useMemo(()=>({container:{...o,...g.overlayStyle}}),[o,g.overlayStyle]),y={...e,placement:r},[b,x]=cl([s],[v,c],{props:y}),S=K(f,p,h,u,`${u}-pure`,`${u}-placement-${r}`,n,g.className);return m.createElement(`div`,{className:S,style:_},m.createElement(`div`,{className:`${u}-arrow`}),m.createElement(q_,{...e,className:p,prefixCls:u,classNames:b,styles:x},i))},bv=m.forwardRef((e,t)=>{let{prefixCls:n,openClassName:r,getTooltipContainer:i,color:a,children:o,afterOpenChange:s,arrow:c,destroyTooltipOnHide:l,destroyOnHidden:u,title:d,overlay:f,trigger:p,builtinPlacements:h,autoAdjustOverflow:g=!0,motion:_,getPopupContainer:v,placement:y=`top`,mouseEnterDelay:b=.1,mouseLeaveDelay:x=.1,rootClassName:S,styles:C,classNames:w,onOpenChange:T,overlayInnerStyle:E,overlayStyle:D,overlayClassName:O,...k}=e,[,A]=Eo(),{getPopupContainer:j,getPrefixCls:M,direction:N,className:P,style:F,classNames:I,styles:L,arrow:ee,trigger:R}=Ht(`tooltip`),z=dv(c,ee),B=z.show,V=p||R||`hover`,te=v||j,ne=u??!!l,re=m.useContext(uv);ot(`Tooltip`);let ie=m.useRef(null),ae=()=>{ie.current?.forceAlign()};m.useImperativeHandle(t,()=>({forceAlign:ae,nativeElement:ie.current?.nativeElement,popupElement:ie.current?.popupElement}));let[oe,H]=xe(e.defaultOpen??!1,e.open),se=!d&&!f&&d!==0,ce=e=>{H(se?!1:e),!se&&T&&T(e)},le=m.useMemo(()=>h||lv({arrowPointAtCenter:z?.pointAtCenter??!1,autoAdjustOverflow:g,arrowWidth:B?A.sizePopupArrow:0,borderRadius:A.borderRadius,offset:A.marginXXS,visibleFirst:!0}),[z,h,A,B,g]),U=m.useMemo(()=>d===0?d:f||d||``,[f,d]),ue=m.createElement(Fh,{space:!0,form:!0},typeof U==`function`?U():U),de={...e,trigger:V,builtinPlacements:le,getPopupContainer:te,destroyOnHidden:ne},[fe,pe]=cl([I,w],[L,C],{props:de}),me=M(`tooltip`,n),he=M(),ge=e[`data-popover-inject`],_e=oe;(!(`open`in e)&&se||re)&&(_e=!1);let W=m.isValidElement(o)&&!Au(o)?o:m.createElement(`span`,null,o),ve=W.props,ye=!ve.className||typeof ve.className==`string`?K(ve.className,r||`${me}-open`):ve.className,G=yl(me),[be,Se]=hv(me,G,!ge),Ce=vv(he,me,a),we=Ce.arrowStyle,Te=K(G,be,Se),Ee=K(O,{[`${me}-rtl`]:N===`rtl`},Ce.className,S,Te,P,fe.root),[De,Oe]=vl(`Tooltip`,k.zIndex),ke={...pe.container,...E,...Ce.overlayStyle},Ae=m.createElement($_,{unique:!0,...k,zIndex:De,showArrow:B,placement:y,mouseEnterDelay:b,mouseLeaveDelay:x,prefixCls:me,classNames:{root:Ee,container:fe.container,arrow:fe.arrow,uniqueContainer:K(Te,fe.container)},styles:{root:{...we,...pe.root,...F,...D},container:ke,uniqueContainer:ke,arrow:pe.arrow},ref:ie,overlay:ue,visible:_e,onVisibleChange:ce,afterVisibleChange:s,arrowContent:m.createElement(`span`,{className:`${me}-arrow-content`}),motion:{motionName:Id(he,`zoom-big-fast`,typeof _?.motionName==`string`?_?.motionName:void 0),motionDeadline:1e3},trigger:V,builtinPlacements:le,getTooltipContainer:te,destroyOnHidden:ne},_e?Mu(W,{className:ye}):W);return m.createElement(fl.Provider,{value:Oe},Ae)});bv._InternalPanelDoNotUseOrYouWillBeFired=yv,bv.UniqueProvider=Iu;var xv=dp;function Sv(e){return Yi(e,{inputAffixPadding:e.paddingXXS})}var Cv=e=>{let{controlHeight:t,fontSize:n,lineHeight:r,lineWidth:i,controlHeightSM:a,controlHeightLG:o,fontSizeLG:s,lineHeightLG:c,paddingSM:l,controlPaddingHorizontalSM:u,controlPaddingHorizontal:d,colorFillAlter:f,colorPrimaryHover:p,colorPrimary:m,controlOutlineWidth:h,controlOutline:g,colorErrorOutline:_,colorWarningOutline:v,colorBgContainer:y,inputFontSize:b,inputFontSizeLG:x,inputFontSizeSM:S}=e,C=b||n,w=S||C,T=x||s,E=Math.round((t-C*r)/2*10)/10-i,D=Math.round((a-w*r)/2*10)/10-i,O=Math.ceil((o-T*c)/2*10)/10-i;return{paddingBlock:Math.max(E,0),paddingBlockSM:Math.max(D,0),paddingBlockLG:Math.max(O,0),paddingInline:l-i,paddingInlineSM:u-i,paddingInlineLG:d-i,addonBg:f,activeBorderColor:m,hoverBorderColor:p,activeShadow:`0 0 0 ${h}px ${g}`,errorActiveShadow:`0 0 0 ${h}px ${_}`,warningActiveShadow:`0 0 0 ${h}px ${v}`,hoverBg:y,activeBg:y,inputFontSize:C,inputFontSizeLG:T,inputFontSizeSM:w}},wv=e=>({borderColor:e.hoverBorderColor,backgroundColor:e.hoverBg}),Tv=e=>({color:e.colorTextDisabled,backgroundColor:e.colorBgContainerDisabled,borderColor:e.colorBorder,boxShadow:`none`,cursor:`not-allowed`,opacity:1,"input[disabled], textarea[disabled]":{cursor:`not-allowed`},"&:hover:not([disabled])":{...wv(Yi(e,{hoverBorderColor:e.colorBorder,hoverBg:e.colorBgContainerDisabled}))}}),Ev=(e,t)=>({background:e.colorBgContainer,borderWidth:e.lineWidth,borderStyle:e.lineType,borderColor:t.borderColor,"&:hover":{borderColor:t.hoverBorderColor,backgroundColor:e.hoverBg},"&:focus, &:focus-within":{borderColor:t.activeBorderColor,boxShadow:t.activeShadow,outline:0,backgroundColor:e.activeBg}}),Dv=(e,t)=>({[`&${e.componentCls}-status-${t.status}:not(${e.componentCls}-disabled)`]:{...Ev(e,t),[`${e.componentCls}-prefix, ${e.componentCls}-suffix`]:{color:t.affixColor}},[`&${e.componentCls}-status-${t.status}${e.componentCls}-disabled`]:{borderColor:t.borderColor}}),Ov=(e,t)=>({"&-outlined":{...Ev(e,{borderColor:e.colorBorder,hoverBorderColor:e.hoverBorderColor,activeBorderColor:e.activeBorderColor,activeShadow:e.activeShadow}),[`&${e.componentCls}-disabled, &[disabled]`]:{...Tv(e)},...Dv(e,{status:`error`,borderColor:e.colorError,hoverBorderColor:e.colorErrorBorderHover,activeBorderColor:e.colorError,activeShadow:e.errorActiveShadow,affixColor:e.colorError}),...Dv(e,{status:`warning`,borderColor:e.colorWarning,hoverBorderColor:e.colorWarningBorderHover,activeBorderColor:e.colorWarning,activeShadow:e.warningActiveShadow,affixColor:e.colorWarning}),...t}}),kv=(e,t)=>({[`&${e.componentCls}-group-wrapper-status-${t.status}`]:{[`${e.componentCls}-group-addon`]:{borderColor:t.addonBorderColor,color:t.addonColor}}}),Av=e=>({"&-outlined":{[`${e.componentCls}-group`]:{"&-addon":{background:e.addonBg,border:`${q(e.lineWidth)} ${e.lineType} ${e.colorBorder}`},"&-addon:first-child":{borderInlineEnd:0},"&-addon:last-child":{borderInlineStart:0}},...kv(e,{status:`error`,addonBorderColor:e.colorError,addonColor:e.colorErrorText}),...kv(e,{status:`warning`,addonBorderColor:e.colorWarning,addonColor:e.colorWarningText}),[`&${e.componentCls}-group-wrapper-disabled`]:{[`${e.componentCls}-group-addon`]:{...Tv(e)}}}}),jv=(e,t)=>{let{componentCls:n}=e;return{"&-borderless":{background:`transparent`,border:`none`,paddingBlock:e.calc(e.paddingBlock).add(e.lineWidth).equal(),[`&${n}-sm, &${n}-affix-wrapper-sm`]:{paddingBlock:e.calc(e.paddingBlockSM).add(e.lineWidth).equal()},[`&${n}-lg, &${n}-affix-wrapper-lg`]:{paddingBlock:e.calc(e.paddingBlockLG).add(e.lineWidth).equal()},"&:focus, &:focus-within":{outline:`none`},[`&${n}-disabled, &[disabled]`]:{color:e.colorTextDisabled,cursor:`not-allowed`},[`&${n}-status-error`]:{"&, & input, & textarea":{color:e.colorError}},[`&${n}-status-warning`]:{"&, & input, & textarea":{color:e.colorWarning}},...t}}},Mv=(e,t)=>({background:t.bg,borderWidth:e.lineWidth,borderStyle:e.lineType,borderColor:`transparent`,"input&, & input, textarea&, & textarea":{color:t?.inputColor??`unset`},"&:hover":{background:t.hoverBg},"&:focus, &:focus-within":{outline:0,borderColor:t.activeBorderColor,backgroundColor:e.activeBg}}),Nv=(e,t)=>({[`&${e.componentCls}-status-${t.status}:not(${e.componentCls}-disabled)`]:{...Mv(e,t),[`${e.componentCls}-prefix, ${e.componentCls}-suffix`]:{color:t.affixColor}}}),Pv=(e,t)=>({"&-filled":{...Mv(e,{bg:e.colorFillTertiary,hoverBg:e.colorFillSecondary,activeBorderColor:e.activeBorderColor,inputColor:e.colorText}),[`&${e.componentCls}-disabled, &[disabled]`]:{...Tv(e)},...Nv(e,{status:`error`,bg:e.colorErrorBg,hoverBg:e.colorErrorBgHover,activeBorderColor:e.colorError,inputColor:e.colorErrorText,affixColor:e.colorError}),...Nv(e,{status:`warning`,bg:e.colorWarningBg,hoverBg:e.colorWarningBgHover,activeBorderColor:e.colorWarning,inputColor:e.colorWarningText,affixColor:e.colorWarning}),...t}}),Fv=(e,t)=>({[`&${e.componentCls}-group-wrapper-status-${t.status}`]:{[`${e.componentCls}-group-addon`]:{background:t.addonBg,color:t.addonColor}}}),Iv=e=>({"&-filled":{[`${e.componentCls}-group-addon`]:{background:e.colorFillTertiary,"&:last-child":{position:`static`}},...Fv(e,{status:`error`,addonBg:e.colorErrorBg,addonColor:e.colorErrorText}),...Fv(e,{status:`warning`,addonBg:e.colorWarningBg,addonColor:e.colorWarningText}),[`&${e.componentCls}-group-wrapper-disabled`]:{[`${e.componentCls}-group`]:{"&-addon":{background:e.colorFillTertiary,color:e.colorTextDisabled},"&-addon:first-child":{borderInlineStart:`${q(e.lineWidth)} ${e.lineType} ${e.colorBorder}`,borderTop:`${q(e.lineWidth)} ${e.lineType} ${e.colorBorder}`,borderBottom:`${q(e.lineWidth)} ${e.lineType} ${e.colorBorder}`},"&-addon:last-child":{borderInlineEnd:`${q(e.lineWidth)} ${e.lineType} ${e.colorBorder}`,borderTop:`${q(e.lineWidth)} ${e.lineType} ${e.colorBorder}`,borderBottom:`${q(e.lineWidth)} ${e.lineType} ${e.colorBorder}`}}}}}),Lv=(e,t)=>({background:e.colorBgContainer,borderWidth:`${q(e.lineWidth)} 0`,borderStyle:`${e.lineType} none`,borderColor:`transparent transparent ${t.borderColor} transparent`,borderRadius:0,"&:hover":{borderColor:`transparent transparent ${t.hoverBorderColor} transparent`,backgroundColor:e.hoverBg},"&:focus, &:focus-within":{borderColor:`transparent transparent ${t.activeBorderColor} transparent`,outline:0,backgroundColor:e.activeBg}}),Rv=(e,t)=>({[`&${e.componentCls}-status-${t.status}:not(${e.componentCls}-disabled)`]:{...Lv(e,t),[`${e.componentCls}-prefix, ${e.componentCls}-suffix`]:{color:t.affixColor}},[`&${e.componentCls}-status-${t.status}${e.componentCls}-disabled`]:{borderColor:`transparent transparent ${t.borderColor} transparent`}}),zv=(e,t)=>({"&-underlined":{...Lv(e,{borderColor:e.colorBorder,hoverBorderColor:e.hoverBorderColor,activeBorderColor:e.activeBorderColor,activeShadow:e.activeShadow}),[`&${e.componentCls}-disabled, &[disabled]`]:{color:e.colorTextDisabled,boxShadow:`none`,cursor:`not-allowed`,"&:hover":{borderColor:`transparent transparent ${e.colorBorder} transparent`}},"input[disabled], textarea[disabled]":{cursor:`not-allowed`},...Rv(e,{status:`error`,borderColor:e.colorError,hoverBorderColor:e.colorErrorBorderHover,activeBorderColor:e.colorError,activeShadow:e.errorActiveShadow,affixColor:e.colorError}),...Rv(e,{status:`warning`,borderColor:e.colorWarning,hoverBorderColor:e.colorWarningBorderHover,activeBorderColor:e.colorWarning,activeShadow:e.warningActiveShadow,affixColor:e.colorWarning}),...t}}),Bv=e=>({"&::-moz-placeholder":{opacity:1},"&::placeholder":{color:e,userSelect:`none`},"&:placeholder-shown":{textOverflow:`ellipsis`}}),Vv=e=>{let{paddingBlockLG:t,lineHeightLG:n,borderRadiusLG:r,paddingInlineLG:i}=e;return{padding:`${q(t)} ${q(i)}`,fontSize:e.inputFontSizeLG,lineHeight:n,borderRadius:r}},Hv=e=>({padding:`${q(e.paddingBlockSM)} ${q(e.paddingInlineSM)}`,fontSize:e.inputFontSizeSM,borderRadius:e.borderRadiusSM}),Uv=(e,t={})=>({position:`relative`,display:`inline-block`,width:`100%`,minWidth:0,padding:`${q(e.paddingBlock)} ${q(e.paddingInline)}`,color:e.colorText,fontSize:e.inputFontSize,lineHeight:e.lineHeight,borderRadius:e.borderRadius,transition:`all ${e.motionDurationMid}`,...Bv(e.colorTextPlaceholder),"&-lg":{...Vv(e),...t.largeStyle},"&-sm":{...Hv(e),...t.smallStyle},"&-rtl, &-textarea-rtl":{direction:`rtl`}}),Wv=e=>{let{componentCls:t,antCls:n}=e;return{position:`relative`,display:`table`,width:`100%`,borderCollapse:`separate`,borderSpacing:0,"&[class*='col-']":{paddingInlineEnd:e.paddingXS,"&:last-child":{paddingInlineEnd:0}},[`&-lg ${t}, &-lg > ${t}-group-addon`]:{...Vv(e)},[`&-sm ${t}, &-sm > ${t}-group-addon`]:{...Hv(e)},[`&-lg ${n}-select-single`]:{height:e.controlHeightLG},[`&-sm ${n}-select-single`]:{height:e.controlHeightSM},[`> ${t}`]:{display:`table-cell`,"&:not(:first-child):not(:last-child)":{borderRadius:0}},[`${t}-group`]:{"&-addon, &-wrap":{display:`table-cell`,width:1,whiteSpace:`nowrap`,verticalAlign:`middle`,"&:not(:first-child):not(:last-child)":{borderRadius:0}},"&-wrap > *":{display:`block !important`},"&-addon":{position:`relative`,padding:`0 ${q(e.paddingInline)}`,color:e.colorText,fontWeight:`normal`,fontSize:e.inputFontSize,textAlign:`center`,borderRadius:e.borderRadius,transition:`all ${e.motionDurationSlow}`,lineHeight:1,[`${n}-select`]:{margin:`${q(e.calc(e.paddingBlock).add(1).mul(-1).equal())} ${q(e.calc(e.paddingInline).mul(-1).equal())}`,[`&${n}-select-single:not(${n}-select-customize-input):not(${n}-pagination-size-changer)`]:{backgroundColor:`inherit`,border:`${q(e.lineWidth)} ${e.lineType} transparent`,boxShadow:`none`}},[`${n}-cascader-picker`]:{margin:`-9px ${q(e.calc(e.paddingInline).mul(-1).equal())}`,backgroundColor:`transparent`,[`${n}-cascader-input`]:{textAlign:`start`,border:0,boxShadow:`none`}}}},[t]:{width:`100%`,marginBottom:0,textAlign:`inherit`,"&:focus":{zIndex:1,borderInlineEndWidth:1},"&:hover":{zIndex:1,borderInlineEndWidth:1}},[`> ${t}:first-child, ${t}-group-addon:first-child`]:{borderStartEndRadius:0,borderEndEndRadius:0,[`${n}-select`]:{borderStartEndRadius:0,borderEndEndRadius:0}},[`> ${t}-affix-wrapper`]:{[`&:not(:first-child) ${t}`]:{borderStartStartRadius:0,borderEndStartRadius:0},[`&:not(:last-child) ${t}`]:{borderStartEndRadius:0,borderEndEndRadius:0}},[`> ${t}:last-child, ${t}-group-addon:last-child`]:{borderStartStartRadius:0,borderEndStartRadius:0,[`${n}-select`]:{borderStartStartRadius:0,borderEndStartRadius:0}},[`${t}-affix-wrapper`]:{"&:not(:last-child)":{borderStartEndRadius:0,borderEndEndRadius:0},"&:not(:first-child)":{borderStartStartRadius:0,borderEndStartRadius:0}},[`&${t}-group-compact`]:{display:`block`,...ko(),[`${t}-group-addon, ${t}-group-wrap, > ${t}`]:{"&:not(:first-child):not(:last-child)":{borderInlineEndWidth:e.lineWidth,"&:hover, &:focus":{zIndex:1}}},"& > *":{display:`inline-flex`,float:`none`,verticalAlign:`top`,borderRadius:0},[` - & > ${t}-affix-wrapper, - & > ${t}-number-affix-wrapper, - & > ${n}-picker-range - `]:{display:`inline-flex`},"& > *:not(:last-child)":{marginInlineEnd:e.calc(e.lineWidth).mul(-1).equal(),borderInlineEndWidth:e.lineWidth},[t]:{float:`none`},[`& > ${n}-select, - & > ${n}-select-auto-complete ${t}, - & > ${n}-cascader-picker ${t}, - & > ${t}-group-wrapper ${t}`]:{borderInlineEndWidth:e.lineWidth,borderRadius:0,"&:hover, &:focus":{zIndex:1}},[`& > ${n}-select-focused`]:{zIndex:1},[`& > ${n}-select > ${n}-select-arrow`]:{zIndex:1},[`& > *:first-child, - & > ${n}-select:first-child, - & > ${n}-select-auto-complete:first-child ${t}, - & > ${n}-cascader-picker:first-child ${t}`]:{borderStartStartRadius:e.borderRadius,borderEndStartRadius:e.borderRadius},[`& > *:last-child, - & > ${n}-select:last-child, - & > ${n}-cascader-picker:last-child ${t}, - & > ${n}-cascader-picker-focused:last-child ${t}`]:{borderInlineEndWidth:e.lineWidth,borderStartEndRadius:e.borderRadius,borderEndEndRadius:e.borderRadius},[`& > ${n}-select-auto-complete ${t}`]:{verticalAlign:`top`},[`${t}-group-wrapper + ${t}-group-wrapper`]:{marginInlineStart:e.calc(e.lineWidth).mul(-1).equal(),[`${t}-affix-wrapper`]:{}}}}},Gv=e=>{let{componentCls:t,controlHeightSM:n,lineWidth:r,calc:i}=e,a=i(n).sub(i(r).mul(2)).sub(16).div(2).equal();return{[t]:{...Do(e),...Uv(e),...Ov(e),...Pv(e),...jv(e),...zv(e),'&[type="color"]':{height:e.controlHeight,[`&${t}-lg`]:{height:e.controlHeightLG},[`&${t}-sm`]:{height:n,paddingTop:a,paddingBottom:a}},'&[type="search"]::-webkit-search-cancel-button, &[type="search"]::-webkit-search-decoration':{appearance:`none`}}}},Kv=e=>{let{componentCls:t}=e;return{[`${t}-clear-icon`]:{margin:0,padding:0,lineHeight:0,color:e.colorTextQuaternary,fontSize:e.fontSizeIcon,verticalAlign:-1,cursor:`pointer`,transition:`color ${e.motionDurationSlow}`,border:`none`,outline:`none`,backgroundColor:`transparent`,"&:hover":{color:e.colorIcon},"&:active":{color:e.colorText},"&-hidden":{visibility:`hidden`},"&-has-suffix":{margin:`0 ${q(e.inputAffixPadding)}`}}}},qv=e=>{let{componentCls:t,inputAffixPadding:n,colorTextDescription:r,motionDurationSlow:i,colorIcon:a,colorIconHover:o,iconCls:s}=e,c=`${t}-affix-wrapper`,l=`${t}-affix-wrapper-disabled`;return{[c]:{...Uv(e),display:`inline-flex`,"&-focused, &:focus":{zIndex:1},[`> input${t}`]:{padding:0},[`> input${t}, > textarea${t}`]:{fontSize:`inherit`,border:`none`,borderRadius:0,outline:`none`,background:`transparent`,color:`inherit`,"&::-ms-reveal":{display:`none`},"&:focus":{boxShadow:`none !important`}},"&::before":{display:`inline-block`,width:0,visibility:`hidden`,content:`"\\a0"`},[t]:{"&-prefix, &-suffix":{display:`flex`,flex:`none`,alignItems:`center`,"> *:not(:last-child)":{marginInlineEnd:e.paddingXS}},"&-show-count-suffix":{color:r,direction:`ltr`},"&-show-count-has-suffix":{marginInlineEnd:e.paddingXXS},"&-prefix":{marginInlineEnd:n},"&-suffix":{marginInlineStart:n}},...Kv(e),[`${s}${t}-password-icon`]:{color:a,cursor:`pointer`,transition:`all ${i}`,"&:hover":{color:o}}},[`${t}-underlined`]:{borderRadius:0},[l]:{[`${s}${t}-password-icon`]:{color:a,cursor:`not-allowed`,"&:hover":{color:a}}}}},Jv=e=>{let{componentCls:t,borderRadiusLG:n,borderRadiusSM:r}=e;return{[`${t}-group`]:{...Do(e),...Wv(e),"&-rtl":{direction:`rtl`},"&-wrapper":{display:`inline-block`,width:`100%`,textAlign:`start`,verticalAlign:`top`,"&-rtl":{direction:`rtl`},"&-lg":{[`${t}-group-addon`]:{borderRadius:n,fontSize:e.inputFontSizeLG}},"&-sm":{[`${t}-group-addon`]:{borderRadius:r}},...Av(e),...Iv(e),[`&:not(${t}-compact-first-item):not(${t}-compact-last-item)${t}-compact-item`]:{[`${t}, ${t}-group-addon`]:{borderRadius:0}},[`&:not(${t}-compact-last-item)${t}-compact-first-item`]:{[`${t}, ${t}-group-addon`]:{borderStartEndRadius:0,borderEndEndRadius:0}},[`&:not(${t}-compact-first-item)${t}-compact-last-item`]:{[`${t}, ${t}-group-addon`]:{borderStartStartRadius:0,borderEndStartRadius:0}},[`&:not(${t}-compact-last-item)${t}-compact-item`]:{[`${t}-affix-wrapper`]:{borderStartEndRadius:0,borderEndEndRadius:0}},[`&:not(${t}-compact-first-item)${t}-compact-item`]:{[`${t}-affix-wrapper`]:{borderStartStartRadius:0,borderEndStartRadius:0}}}}}},Yv=e=>{let{componentCls:t}=e;return{[`${t}-out-of-range`]:{[`&, & input, & textarea, ${t}-show-count-suffix, ${t}-data-count`]:{color:e.colorError}}}},Xv=Io([`Input`,`Shared`],e=>{let t=Yi(e,Sv(e));return[Gv(t),qv(t)]},Cv,{resetFont:!1});Io([`Input`,`Component`],e=>{let t=Yi(e,Sv(e));return[Jv(t),Yv(t),rp(t,{focus:!0,focusElCls:`${t.componentCls}-affix-wrapper-focused`})]},Cv,{resetFont:!1});function Zv(e,t,n){var r=n||{},i=r.noTrailing,a=i===void 0?!1:i,o=r.noLeading,s=o===void 0?!1:o,c=r.debounceMode,l=c===void 0?void 0:c,u,d=!1,f=0;function p(){u&&clearTimeout(u)}function m(e){var t=(e||{}).upcomingOnly,n=t===void 0?!1:t;p(),d=!n}function h(){var n=[...arguments],r=this,i=Date.now()-f;if(d)return;function o(){f=Date.now(),t.apply(r,n)}function c(){u=void 0}!s&&l&&!u&&o(),p(),l===void 0&&i>e?s?(f=Date.now(),a||(u=setTimeout(l?c:o,e))):o():a!==!0&&(u=setTimeout(l?c:o,l===void 0?e-i:e))}return h.cancel=m,h}function Qv(e,t,n){var r=(n||{}).atBegin;return Zv(e,t,{debounceMode:(r===void 0?!1:r)!==!1})}var $v=(0,m.createContext)({});function ey(e,t){let n=[void 0,void 0],r=Array.isArray(e)?e:[e,void 0],i=t||{xs:!0,sm:!0,md:!0,lg:!0,xl:!0,xxl:!0,xxxl:!0};return r.forEach((e,t)=>{if(typeof e==`object`&&e)for(let r=0;r{if(typeof e==`string`&&r(e),typeof e==`object`)for(let n=0;n{i()},[JSON.stringify(e),t]),n}var ny=m.forwardRef((e,t)=>{let{prefixCls:n,justify:r,align:i,className:a,style:o,children:s,gutter:c=0,wrap:l,...u}=e,{getPrefixCls:d,direction:f}=m.useContext(zt),p=K_(!0,null),h=ty(i,p),g=ty(r,p),_=d(`row`,n),[v,y]=jg(_),b=ey(c,p),x=K(_,{[`${_}-no-wrap`]:l===!1,[`${_}-${g}`]:g,[`${_}-${h}`]:h,[`${_}-rtl`]:f===`rtl`},a,v,y),S={};b?.[0]&&(S.marginInline=typeof b[0]==`number`?`${b[0]/-2}px`:`calc(${b[0]} / -2)`);let[C,w]=b;S.rowGap=w;let T=m.useMemo(()=>({gutter:[C,w],wrap:l}),[C,w,l]);return m.createElement($v.Provider,{value:T},m.createElement(`div`,{...u,className:x,style:{...S,...o},ref:t},s))}),ry=e=>{let{componentCls:t,borderRadius:n,paddingSM:r,colorBorder:i,paddingXS:a,fontSizeLG:o,fontSizeSM:s,borderRadiusLG:c,borderRadiusSM:l,colorBgContainerDisabled:u,lineWidth:d,antCls:f}=e,[p,m]=zo(f,`space`);return{[t]:[{display:`inline-flex`,alignItems:`center`,gap:0,paddingInline:r,margin:0,borderWidth:d,borderStyle:`solid`,borderRadius:n,"&:hover":{zIndex:0},[`&${t}-disabled`]:{color:e.colorTextDisabled},"&-large":{fontSize:o,borderRadius:c},"&-small":{paddingInline:a,borderRadius:l,fontSize:s},"&-compact-last-item":{borderEndStartRadius:0,borderStartStartRadius:0},"&-compact-first-item":{borderEndEndRadius:0,borderStartEndRadius:0},"&-compact-item:not(:first-child):not(:last-child)":{borderRadius:0},"&-compact-item:not(:last-child)":{borderInlineEndWidth:0},"&-compact-item:not(:first-child)":{borderInlineStartWidth:0}},{[p(`addon-border-color`)]:i,[p(`addon-background`)]:u,[p(`addon-border-color-outlined`)]:i,[p(`addon-background-filled`)]:u,borderColor:m(`addon-border-color`),background:m(`addon-background`),"&-variant-outlined":{[p(`addon-border-color`)]:m(`addon-border-color-outlined`)},"&-variant-filled":{[p(`addon-border-color`)]:`transparent`,[p(`addon-background`)]:m(`addon-background-filled`),[`&${t}-disabled`]:{[p(`addon-border-color`)]:i,[p(`addon-background`)]:u}},"&-variant-borderless":{border:`none`,background:`transparent`},"&-variant-underlined":{border:`none`,background:`transparent`}},{"&-status-error":{[p(`addon-border-color-outlined`)]:e.colorError,[p(`addon-background-filled`)]:e.colorErrorBg,color:e.colorError},"&-status-warning":{[p(`addon-border-color-outlined`)]:e.colorWarning,[p(`addon-background-filled`)]:e.colorWarningBg,color:e.colorWarning}}]}},iy=Io([`Space`,`Addon`],e=>[ry(e),rp(e,{focus:!1})]),ay=m.forwardRef((e,t)=>{let{className:n,children:r,style:i,prefixCls:a,variant:o=`outlined`,disabled:s,status:c,...l}=e,{getPrefixCls:u,direction:d}=m.useContext(zt),f=u(`space-addon`,a),[p,h]=iy(f),{compactItemClassnames:g,compactSize:_}=Yd(f,d),v=I_(f,c),y=K(f,p,g,h,`${f}-variant-${o}`,v,{[`${f}-${_}`]:_,[`${f}-disabled`]:s},n);return m.createElement(`div`,{ref:t,className:y,style:i,...l},r)});function oy(e){return!!(e.addonBefore||e.addonAfter)}function sy(e){return!!(e.prefix||e.suffix||e.allowClear)}function cy(e,t,n){let r=t.cloneNode(!0),i=Object.create(e,{target:{value:r},currentTarget:{value:r}});return r.value=n,typeof t.selectionStart==`number`&&typeof t.selectionEnd==`number`&&(r.selectionStart=t.selectionStart,r.selectionEnd=t.selectionEnd),r.setSelectionRange=(...e)=>{t.setSelectionRange(...e)},i}function ly(e,t,n,r){if(!n)return;let i=t;if(t.type===`click`){i=cy(t,e,``),n(i);return}if(e.type!==`file`&&r!==void 0){i=cy(t,e,r),n(i);return}n(i)}function uy(){return uy=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{inputElement:n,children:r,prefixCls:i,prefix:a,suffix:o,addonBefore:s,addonAfter:c,className:l,style:u,disabled:d,readOnly:f,focused:p,triggerFocus:h,allowClear:g,value:_,handleReset:v,hidden:y,classes:b,classNames:x,dataAttrs:S,styles:C,components:w,onClear:T}=e,E=r??n,D=w?.affixWrapper||`span`,O=w?.groupWrapper||`span`,k=w?.wrapper||`span`,A=w?.groupAddon||`span`,j=(0,m.useRef)(null),M=e=>{j.current?.contains(e.target)&&h?.()},N=sy(e),P=(0,m.cloneElement)(E,{value:_,className:K(E.props?.className,!N&&x?.variant)||null}),F=(0,m.useRef)(null);if(m.useImperativeHandle(t,()=>({nativeElement:F.current||j.current})),N){let e=null;if(g){let t=!d&&!f&&_,n=`${i}-clear-icon`,r=typeof g==`object`&&g?.clearIcon?g.clearIcon:`✖`;e=m.createElement(`button`,{type:`button`,tabIndex:-1,onClick:e=>{v?.(e),T?.()},onMouseDown:e=>e.preventDefault(),className:K(n,{[`${n}-hidden`]:!t,[`${n}-has-suffix`]:!!o})},r)}let t=`${i}-affix-wrapper`,n=K(t,{[`${i}-disabled`]:d,[`${t}-disabled`]:d,[`${t}-focused`]:p,[`${t}-readonly`]:f,[`${t}-input-with-clear-btn`]:o&&g&&_},b?.affixWrapper,x?.affixWrapper,x?.variant),r=(o||g)&&m.createElement(`span`,{className:K(`${i}-suffix`,x?.suffix),style:C?.suffix},e,o);P=m.createElement(D,uy({className:n,style:C?.affixWrapper,onClick:M},S?.affixWrapper,{ref:j}),a&&m.createElement(`span`,{className:K(`${i}-prefix`,x?.prefix),style:C?.prefix},a),P,r)}if(oy(e)){let e=`${i}-group`,t=`${e}-addon`,n=`${e}-wrapper`,r=K(`${i}-wrapper`,e,b?.wrapper,x?.wrapper),a=K(n,{[`${n}-disabled`]:d},b?.group,x?.groupWrapper);P=m.createElement(O,{className:a,ref:F},m.createElement(k,{className:r},s&&m.createElement(A,{className:t},s),P,c&&m.createElement(A,{className:t},c)))}return m.cloneElement(P,{className:K(P.props?.className,l)||null,style:{...P.props?.style,...u},hidden:y})});function fy(e,t){return m.useMemo(()=>{let n={};t&&(n.show=typeof t==`object`&&t.formatter?t.formatter:!!t),n={...n,...e};let{show:r,...i}=n;return{...i,show:!!r,showFormatter:typeof r==`function`?r:void 0,strategy:i.strategy||(e=>e.length)}},[e,t])}var py=e=>{let t;return typeof e==`object`&&e?.clearIcon?t=e:e&&(t={clearIcon:m.createElement(ms,null)}),t};function my(e){return[`small`,`middle`,`medium`,`large`].includes(e)}function hy(e){return e?typeof e==`number`&&!Number.isNaN(e):!1}var gy=m.createContext({latestIndex:0}),_y=gy.Provider,vy=e=>{let{className:t,prefix:n,index:r,children:i,separator:a,style:o,classNames:s,styles:c}=e,{latestIndex:l}=m.useContext(gy);return Gc(i)?m.createElement(m.Fragment,null,m.createElement(`div`,{className:t,style:o},i),r{let{componentCls:t,antCls:n}=e;return{[t]:{display:`inline-flex`,"&-rtl":{direction:`rtl`},"&-vertical":{flexDirection:`column`},"&-align":{flexDirection:`column`,"&-center":{alignItems:`center`},"&-start":{alignItems:`flex-start`},"&-end":{alignItems:`flex-end`},"&-baseline":{alignItems:`baseline`}},[`${t}-item:empty`]:{display:`none`},[`${t}-item > ${n}-badge-not-a-wrapper:only-child`]:{display:`block`}}}},by=e=>{let{componentCls:t}=e;return{[t]:{"&-gap-row-small":{rowGap:e.spaceGapSmallSize},"&-gap-row-medium, &-gap-row-middle":{rowGap:e.spaceGapMiddleSize},"&-gap-row-large":{rowGap:e.spaceGapLargeSize},"&-gap-col-small":{columnGap:e.spaceGapSmallSize},"&-gap-col-medium, &-gap-col-middle":{columnGap:e.spaceGapMiddleSize},"&-gap-col-large":{columnGap:e.spaceGapLargeSize}}}},xy=Io(`Space`,e=>{let t=Yi(e,{spaceGapSmallSize:e.paddingXS,spaceGapMiddleSize:e.padding,spaceGapLargeSize:e.paddingLG});return[yy(t),by(t)]},()=>({}),{resetStyle:!1}),Sy=m.forwardRef((e,t)=>{let{getPrefixCls:n,direction:r,size:i,className:a,style:o,classNames:s,styles:c}=Ht(`space`),{size:l=i??`small`,align:u,className:d,rootClassName:f,children:p,direction:h,orientation:g,prefixCls:_,split:v,separator:y,style:b,vertical:x,wrap:S=!1,classNames:C,styles:w,...T}=e,[E,D]=Array.isArray(l)?l:[l,l],O=my(D),k=my(E),A=hy(D),j=hy(E),M=nt(p,{keepEmpty:!0}),[N,P]=ul(g,x,h),F=u===void 0&&!P?`center`:u,I=y??v,L=n(`space`,_),[ee,R]=xy(L),z={...e,size:l,orientation:N,align:F},[B,V]=cl([s,C],[c,w],{props:z}),te=K(L,a,ee,`${L}-${N}`,{[`${L}-rtl`]:r===`rtl`,[`${L}-align-${F}`]:F,[`${L}-gap-row-${D}`]:O,[`${L}-gap-col-${E}`]:k},d,f,R,B.root),ne=K(`${L}-item`,B.item),re=M.map((e,t)=>{let n=e?.key||`${ne}-${t}`;return m.createElement(vy,{prefix:L,classNames:B,styles:V,className:ne,key:n,index:t,separator:I,style:V.item},e)}),ie=m.useMemo(()=>({latestIndex:M.reduce((e,t,n)=>Gc(t)?n:e,0)}),[M]);if(M.length===0)return null;let ae={};return S&&(ae.flexWrap=`wrap`),!k&&j&&(ae.columnGap=E),!O&&A&&(ae.rowGap=D),m.createElement(`div`,{ref:t,className:te,style:{...ae,...V.root,...o,...b},...T},m.createElement(_y,{value:ie},re))});Sy.Compact=Qd,Sy.Addon=ay;var Cy=` - min-height:0 !important; - max-height:none !important; - height:0 !important; - visibility:hidden !important; - overflow:hidden !important; - position:absolute !important; - z-index:-1000 !important; - top:0 !important; - right:0 !important; - pointer-events: none !important; -`,wy=[`letter-spacing`,`line-height`,`padding-top`,`padding-bottom`,`font-family`,`font-weight`,`font-size`,`font-variant`,`text-rendering`,`text-transform`,`width`,`text-indent`,`padding-left`,`padding-right`,`border-width`,`box-sizing`,`word-break`,`white-space`],Ty={},Ey;function Dy(e,t=!1){let n=e.getAttribute(`id`)||e.getAttribute(`data-reactid`)||e.getAttribute(`name`);if(t&&Ty[n])return Ty[n];let r=window.getComputedStyle(e),i=r.getPropertyValue(`box-sizing`)||r.getPropertyValue(`-moz-box-sizing`)||r.getPropertyValue(`-webkit-box-sizing`),a=parseFloat(r.getPropertyValue(`padding-bottom`))+parseFloat(r.getPropertyValue(`padding-top`)),o=parseFloat(r.getPropertyValue(`border-bottom-width`))+parseFloat(r.getPropertyValue(`border-top-width`)),s={sizingStyle:wy.map(e=>`${e}:${r.getPropertyValue(e)}`).join(`;`),paddingSize:a,borderSize:o,boxSizing:i};return t&&n&&(Ty[n]=s),s}function Oy(e,t=!1,n=null,r=null){Ey||(Ey=document.createElement(`textarea`),Ey.setAttribute(`tab-index`,`-1`),Ey.setAttribute(`aria-hidden`,`true`),Ey.setAttribute(`name`,`hiddenTextarea`),document.body.appendChild(Ey)),e.getAttribute(`wrap`)?Ey.setAttribute(`wrap`,e.getAttribute(`wrap`)):Ey.removeAttribute(`wrap`);let{paddingSize:i,borderSize:a,boxSizing:o,sizingStyle:s}=Dy(e,t);Ey.setAttribute(`style`,`${s};${Cy}`),Ey.value=e.value||e.placeholder||``;let c,l,u,d=Ey.scrollHeight;if(o===`border-box`?d+=a:o===`content-box`&&(d-=i),n!==null||r!==null){Ey.value=` `;let e=Ey.scrollHeight-i;n!==null&&(c=e*n,o===`border-box`&&(c=c+i+a),d=Math.max(c,d)),r!==null&&(l=e*r,o===`border-box`&&(l=l+i+a),u=d>l?``:`hidden`,d=Math.min(l,d))}let f={height:d,overflowY:u,resize:`none`};return c&&(f.minHeight=c),l&&(f.maxHeight=l),f}function ky(){return ky=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{prefixCls:n,defaultValue:r,value:i,autoSize:a,onResize:o,className:s,style:c,disabled:l,onChange:u,onInternalAutoSize:d,...f}=e,[p,h]=xe(r,i),g=p??``,_=e=>{h(e.target.value),u?.(e)},v=m.useRef();m.useImperativeHandle(t,()=>({textArea:v.current}));let[y,b]=m.useMemo(()=>a&&typeof a==`object`?[a.minRows,a.maxRows]:[],[a]),x=!!a,[S,C]=m.useState(My),[w,T]=m.useState(),E=()=>{C(Ay)};G(()=>{x&&E()},[i,y,b,x]),G(()=>{if(S===Ay)C(jy);else if(S===jy){let e=Oy(v.current,!1,y,b);C(My),T(e)}},[S]);let D=m.useRef(),O=()=>{It.cancel(D.current)},k=e=>{S===My&&(o?.(e),a&&(O(),D.current=It(()=>{E()})))};m.useEffect(()=>O,[]);let A=x?w:null,j={...c,...A};return(S===Ay||S===jy)&&(j.overflowY=`hidden`,j.overflowX=`hidden`),m.createElement(Ct,{onResize:k,disabled:!(a||o)},m.createElement(`textarea`,ky({},f,{ref:v,style:j,className:K(n,s,{[`${n}-disabled`]:l}),disabled:l,value:g,onChange:_})))});function Py(){return Py=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let[O,k]=xe(e,t),A=O==null?``:String(O),[j,M]=m.useState(!1),N=m.useRef(!1),[P,F]=m.useState(null),I=(0,m.useRef)(null),L=(0,m.useRef)(null),ee=()=>L.current?.textArea,R=()=>{ee().focus()};(0,m.useImperativeHandle)(D,()=>({resizableTextArea:L.current,focus:R,blur:()=>{ee().blur()},nativeElement:I.current?.nativeElement||ee()})),(0,m.useEffect)(()=>{M(e=>!g&&e)},[g]);let[z,B]=m.useState(null);m.useEffect(()=>{z&&ee().setSelectionRange(...z)},[z]);let V=fy(f,d),te=V.max??o,ne=Number(te)>0,re=V.strategy(A),ie=!!te&&re>te,ae=(e,t)=>{let n=t;!N.current&&V.exceedFormatter&&V.max&&V.strategy(t)>V.max&&(n=V.exceedFormatter(t,{max:V.max}),t!==n&&B([ee().selectionStart||0,ee().selectionEnd||0])),k(n),ly(e.currentTarget,e,i,n)},oe=e=>{N.current=!0,s?.(e)},H=e=>{N.current=!1,ae(e,e.currentTarget.value),c?.(e)},se=e=>{ae(e,e.target.value)},ce=e=>{e.key===`Enter`&&S&&!e.nativeEvent.isComposing&&S(e),T?.(e)},le=e=>{M(!0),n?.(e)},U=e=>{M(!1),r?.(e)},ue=e=>{k(``),R(),ly(ee(),e,i)},de=l,fe;V.show&&(fe=V.showFormatter?V.showFormatter({value:A,count:re,maxLength:te}):`${re}${ne?` / ${te}`:``}`,de=m.createElement(m.Fragment,null,de,m.createElement(`span`,{className:K(`${u}-data-count`,v?.count),style:y?.count},fe)));let pe=e=>{b?.(e),ee()?.style.height&&F(!0)},me=!w&&!d&&!a;return m.createElement(dy,{ref:I,value:A,allowClear:a,handleReset:ue,suffix:de,prefixCls:u,classNames:{...v,affixWrapper:K(v?.affixWrapper,{[`${u}-show-count`]:d,[`${u}-textarea-allow-clear`]:a})},disabled:g,focused:j,className:K(p,ie&&`${u}-out-of-range`),style:{...h,...P&&!me?{height:`auto`}:{}},dataAttrs:{affixWrapper:{"data-count":typeof fe==`string`?fe:void 0}},hidden:_,readOnly:C,onClear:x},m.createElement(Ny,Py({},E,{autoSize:w,maxLength:o,onKeyDown:ce,onChange:se,onFocus:le,onBlur:U,onCompositionStart:oe,onCompositionEnd:H,className:K(v?.textarea),style:{resize:h?.resize,...y?.textarea},disabled:g,prefixCls:u,onResize:pe,ref:L,readOnly:C})))}),Iy=e=>{let{componentCls:t,paddingLG:n}=e,r=`${t}-textarea`;return{[`textarea${t}`]:{maxWidth:`100%`,height:`auto`,minHeight:e.controlHeight,lineHeight:e.lineHeight,verticalAlign:`bottom`,transition:`all ${e.motionDurationSlow}`,resize:`vertical`,[`&${t}-mouse-active`]:{transition:`all ${e.motionDurationSlow}, height 0s, width 0s`}},[`${t}-textarea-affix-wrapper-resize-dirty`]:{width:`auto`},[r]:{position:`relative`,"&-show-count":{[`${t}-data-count`]:{position:`absolute`,bottom:e.calc(e.fontSize).mul(e.lineHeight).mul(-1).equal(),insetInlineEnd:0,color:e.colorTextDescription,whiteSpace:`nowrap`,pointerEvents:`none`}},[` - &-allow-clear > ${t}, - &-affix-wrapper${r}-has-feedback ${t} - `]:{paddingInlineEnd:n},[`&-affix-wrapper${t}-affix-wrapper`]:{padding:0,[`> textarea${t}`]:{fontSize:`inherit`,border:`none`,outline:`none`,background:`transparent`,minHeight:e.calc(e.controlHeight).sub(e.calc(e.lineWidth).mul(2)).equal(),"&:focus":{boxShadow:`none !important`}},[`${t}-suffix`]:{margin:0,"> *:not(:last-child)":{marginInline:0},[`${t}-clear-icon`]:{position:`absolute`,insetInlineEnd:e.paddingInline,insetBlockStart:e.paddingXS},[`${r}-suffix`]:{position:`absolute`,top:0,insetInlineEnd:e.paddingInline,bottom:0,zIndex:1,display:`inline-flex`,alignItems:`center`,margin:`auto`,pointerEvents:`none`}}},[`&-affix-wrapper${t}-affix-wrapper-rtl`]:{[`${t}-suffix`]:{[`${t}-data-count`]:{direction:`ltr`,insetInlineStart:0}}},[`&-affix-wrapper${t}-affix-wrapper-sm`]:{[`${t}-suffix`]:{[`${t}-clear-icon`]:{insetInlineEnd:e.paddingInlineSM}}}}}},Ly=Io([`Input`,`TextArea`],e=>Iy(Yi(e,Sv(e))),Cv,{resetFont:!1}),Ry=(0,m.forwardRef)((e,t)=>{let{prefixCls:n,bordered:r=!0,size:i,disabled:a,status:o,allowClear:s,classNames:c,rootClassName:l,className:u,style:d,styles:f,variant:p,showCount:h,onMouseDown:g,onResize:_,...v}=e,{getPrefixCls:y,direction:b,allowClear:x,autoComplete:S,className:C,style:w,classNames:T,styles:E}=Ht(`textArea`),D=m.useContext(Lu),O=a??D,{status:k,hasFeedback:A,feedbackIcon:j}=m.useContext(Mh),M=L_(k,o),[N,P]=cl([T,c],[E,f],{props:e}),F=m.useRef(null);m.useImperativeHandle(t,()=>({resizableTextArea:F.current?.resizableTextArea,focus:e=>{wp(F.current?.resizableTextArea?.textArea,e)},blur:()=>F.current?.blur(),nativeElement:F.current?.nativeElement||null}));let I=y(`input`,n),L=yl(I),[ee,R]=Xv(I,l);Ly(I,L);let{compactSize:z,compactItemClassnames:B}=Yd(I,b),V=Kd(e=>i??z??e),[te,ne]=R_(`textArea`,p,r),re=py(s??x),[ie,ae]=m.useState(!1),[oe,H]=m.useState(!1),se=e=>{ae(!0),g?.(e);let t=()=>{ae(!1),document.removeEventListener(`mouseup`,t)};document.addEventListener(`mouseup`,t)},ce=e=>{if(_?.(e),ie&&typeof getComputedStyle==`function`){let e=F.current?.nativeElement?.querySelector(`textarea`);e&&getComputedStyle(e).resize===`both`&&H(!0)}};return m.createElement(Fy,{autoComplete:S,...v,style:{...P.root,...w,...d},styles:P,disabled:O,allowClear:re,className:K(R,L,u,l,B,C,N.root,{[`${I}-textarea-affix-wrapper-resize-dirty`]:oe}),classNames:{...N,textarea:K({[`${I}-sm`]:V===`small`,[`${I}-lg`]:V===`large`},ee,N.textarea,ie&&`${I}-mouse-active`),variant:K({[`${I}-${te}`]:ne},I_(I,M)),affixWrapper:K(`${I}-textarea-affix-wrapper`,{[`${I}-affix-wrapper-rtl`]:b===`rtl`,[`${I}-affix-wrapper-sm`]:V===`small`,[`${I}-affix-wrapper-lg`]:V===`large`,[`${I}-textarea-show-count`]:h||e.count?.show},ee)},prefixCls:I,suffix:A&&m.createElement(`span`,{className:`${I}-textarea-suffix`},j),showCount:h,ref:F,onResize:ce,onMouseDown:se})}),zy=100,By=zy/5,Vy=zy/2-By/2,Hy=Vy*2*Math.PI,Uy=50,Wy=e=>{let{dotClassName:t,style:n,hasCircleCls:r}=e;return m.createElement(`circle`,{className:K(`${t}-circle`,{[`${t}-circle-bg`]:r}),r:Vy,cx:Uy,cy:Uy,strokeWidth:By,style:n})},Gy=({percent:e,prefixCls:t})=>{let n=`${t}-dot`,r=`${n}-holder`,i=`${r}-hidden`,[a,o]=m.useState(!1);G(()=>{e!==0&&o(!0)},[e!==0]);let s=Math.max(Math.min(e,100),0);if(!a)return null;let c={strokeDashoffset:`${Hy/4}`,strokeDasharray:`${Hy*s/100} ${Hy*(100-s)/100}`};return m.createElement(`span`,{className:K(r,`${n}-progress`,s<=0&&i)},m.createElement(`svg`,{viewBox:`0 0 ${zy} ${zy}`,role:`progressbar`,"aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":s},m.createElement(Wy,{dotClassName:n,hasCircleCls:!0}),m.createElement(Wy,{dotClassName:n,style:c})))};function Ky(e){let{prefixCls:t,percent:n=0,className:r,style:i}=e,a=`${t}-dot`,o=`${a}-holder`,s=`${o}-hidden`;return m.createElement(m.Fragment,null,m.createElement(`span`,{className:K(o,r,n>0&&s),style:i},m.createElement(`span`,{className:K(a,`${t}-dot-spin`)},[1,2,3,4].map(e=>m.createElement(`i`,{className:`${t}-dot-item`,key:e})))),m.createElement(Gy,{prefixCls:t,percent:n}))}function qy(e){let{prefixCls:t,indicator:n,percent:r,className:i,style:a}=e,o=`${t}-dot`;return n&&m.isValidElement(n)?Mu(n,e=>({className:K(e.className,o,i),style:{...e.style,...a},percent:r})):m.createElement(Ky,{prefixCls:t,percent:r,className:i,style:a})}var Jy=new gi(`antSpinMove`,{to:{opacity:1}}),Yy=new gi(`antRotate`,{to:{transform:`rotate(405deg)`}}),Xy=e=>{let{componentCls:t}=e,n=`${t}-section`;return{[t]:{...Do(e),position:`relative`,"&-rtl":{direction:`rtl`},[`&${n}, ${n}`]:{display:`flex`,alignItems:`center`,flexDirection:`column`,gap:e.paddingSM,color:e.colorPrimary},[`&${n}`]:{display:`inline-flex`},[n]:{position:`absolute`,top:`50%`,left:{_skip_check_:!0,value:`50%`},transform:`translate(-50%, -50%)`,zIndex:1},[`${t}-description`]:{fontSize:e.fontSize,lineHeight:1},[`${t}-container`]:{position:`relative`,transition:`opacity ${e.motionDurationSlow}`,"&::after":{position:`absolute`,top:0,insetInlineEnd:0,bottom:0,insetInlineStart:0,zIndex:10,width:`100%`,height:`100%`,background:e.colorBgContainer,opacity:0,transition:`all ${e.motionDurationSlow}`,content:`""`,pointerEvents:`none`}},"&-spinning":{[`${t}-description`]:{textShadow:`0 0px 5px ${e.colorBgContainer}`},[`${t}-container`]:{clear:`both`,opacity:.5,userSelect:`none`,pointerEvents:`none`,"&::after":{opacity:.4,pointerEvents:`auto`}}},"&-fullscreen":{position:`fixed`,inset:0,backgroundColor:e.colorBgMask,zIndex:e.zIndexPopupBase,opacity:0,pointerEvents:`none`,transition:`all ${e.motionDurationMid}`,[`&${t}-spinning`]:{opacity:1,pointerEvents:`auto`},[n]:{color:e.colorWhite,[`${t}-description`]:{color:e.colorTextLightSolid}}}}}},Zy=e=>{let{componentCls:t,antCls:n,motionDurationSlow:r}=e,[i,a]=zo(n,`spin`);return{[t]:{[i(`dot-holder-size`)]:e.dotSize,[i(`dot-item-size`)]:`calc((${a(`dot-holder-size`)} - ${e.marginXXS} / 2) / 2)`,[`${t}-dot`]:{"&-holder":{width:`1em`,height:`1em`,fontSize:a(`dot-holder-size`),display:`inline-block`,transition:[`transform`,`opacity`].map(e=>`${e} ${r} ease`).join(`, `),transformOrigin:`50% 50%`,lineHeight:1,"&-hidden":{transform:`scale(0.3)`,opacity:0}},position:`relative`,display:`inline-block`,fontSize:a(`dot-holder-size`),width:`1em`,height:`1em`,"&-spin":{transform:`rotate(45deg)`,animationName:Yy,animationDuration:`1.2s`,animationIterationCount:`infinite`,animationTimingFunction:`linear`},"&-item":{position:`absolute`,display:`block`,width:a(`dot-item-size`),height:a(`dot-item-size`),background:`currentColor`,borderRadius:`100%`,transform:`scale(0.75)`,transformOrigin:`50% 50%`,opacity:.3,animationName:Jy,animationDuration:`1s`,animationIterationCount:`infinite`,animationTimingFunction:`linear`,animationDirection:`alternate`,"&:nth-child(1)":{top:0,insetInlineStart:0,animationDelay:`0s`},"&:nth-child(2)":{top:0,insetInlineEnd:0,animationDelay:`0.4s`},"&:nth-child(3)":{insetInlineEnd:0,bottom:0,animationDelay:`0.8s`},"&:nth-child(4)":{bottom:0,insetInlineStart:0,animationDelay:`1.2s`}},"&-progress":{position:`absolute`,left:`50%`,top:0,transform:`translateX(-50%)`},"&-circle":{strokeLinecap:`round`,transition:[`stroke-dashoffset`,`stroke-dasharray`,`stroke`,`stroke-width`,`opacity`].map(e=>`${e} ${r} ease`).join(`,`),fillOpacity:0,stroke:`currentcolor`},"&-circle-bg":{stroke:e.colorFillSecondary}}}}},Qy=e=>{let{componentCls:t}=e,[n]=zo(e.antCls,`spin`);return{[t]:{"&-sm":{[n(`dot-holder-size`)]:e.dotSizeSM},"&-lg":{[n(`dot-holder-size`)]:e.dotSizeLG}}}},$y=Io(`Spin`,e=>{let t=Yi(e,{spinDotDefault:e.colorTextDescription});return[Xy(t),Zy(t),Qy(t)]},e=>{let{controlHeightLG:t,controlHeight:n}=e;return{contentHeight:400,dotSize:t/2,dotSizeSM:t*.35,dotSizeLG:n}}),eb=200,tb=[[30,.05],[70,.03],[96,.01]];function nb(e,t){let[n,r]=m.useState(0),i=m.useRef(null),a=t===`auto`;return m.useEffect(()=>(a&&e&&(r(0),i.current=setInterval(()=>{r(e=>{let t=100-e;for(let n=0;n{i.current&&=(clearInterval(i.current),null)}),[a,e]),a?n:t}var rb;function ib(e,t){return!!e&&!!t&&!Number.isNaN(Number(t))}var ab=e=>{let{prefixCls:t,spinning:n=!0,delay:r=0,className:i,rootClassName:a,size:o,tip:s,description:c,wrapperClassName:l,style:u,children:d,fullscreen:f=!1,indicator:p,percent:h,classNames:g,styles:_,...v}=e,{getPrefixCls:y,direction:b,indicator:x,className:S,style:C,classNames:w,styles:T}=Ht(`spin`),E=y(`spin`,t),[D,O]=$y(E),[k,A]=m.useState(()=>n&&!ib(n,r)),j=nb(k,h);m.useEffect(()=>{if(n){let e=Qv(r,()=>{A(!0)});return e(),()=>{e?.cancel?.()}}A(!1)},[r,n]);let M=Kd(e=>o??e),N=c??s,P={...e,size:M,spinning:k,tip:N,description:N,fullscreen:f,children:d,percent:j},[F,I]=cl([w,g],[T,_],{props:P}),L=p??x??rb,ee=d!==void 0,R=ee||f,z=m.createElement(m.Fragment,null,m.createElement(qy,{className:K(F.indicator),style:I.indicator,prefixCls:E,indicator:L,percent:j}),N&&m.createElement(`div`,{className:K(`${E}-description`,F.tip,F.description),style:{...I.tip,...I.description}},N));return m.createElement(`div`,{className:K(E,{[`${E}-sm`]:M===`small`,[`${E}-lg`]:M===`large`,[`${E}-spinning`]:k,[`${E}-rtl`]:b===`rtl`,[`${E}-fullscreen`]:f},a,F.root,f&&F.mask,R?l:[`${E}-section`,F.section],S,i,D,O),style:{...I.root,...R?{}:I.section,...f?I.mask:{},...C,...u},"aria-live":`polite`,"aria-busy":k,...v},k&&(R?m.createElement(`div`,{className:K(`${E}-section`,F.section),style:I.section},z):z),ee&&m.createElement(`div`,{className:K(`${E}-container`,F.container),style:I.container},d))};ab.setDefaultIndicator=e=>{rb=e};var ob=(e,t={})=>!Gc(e)&&t?.skipEmpty?[]:Array.isArray(e)?e:[e],sb=ny,cb=e=>{let t=e?.algorithm?bn(e.algorithm):go;return Un({...da,...e?.token},{override:e?.token},t,xo)};function lb(e){let{sizeUnit:t,sizeStep:n}=e,r=n-2;return{sizeXXL:t*(r+10),sizeXL:t*(r+6),sizeLG:t*(r+2),sizeMD:t*(r+2),sizeMS:t*(r+1),size:t*r,sizeSM:t*r,sizeXS:t*(r-1),sizeXXS:t*(r-1)}}var ub=(e,t)=>{let n=t??ho(e),r=n.fontSizeSM,i=n.controlHeight-4;return{...n,...lb(t??e),...co(r),controlHeight:i,...so({...n,controlHeight:i})}},db=(e,t)=>new _a(e).setA(t).toRgbString(),fb=(e,t)=>new _a(e).lighten(t).toHexString(),pb=e=>{let t=ka(e,{theme:`dark`});return{1:t[0],2:t[1],3:t[2],4:t[3],5:t[6],6:t[5],7:t[4],8:t[6],9:t[5],10:t[4]}},mb=(e,t)=>{let n=e||`#000`,r=t||`#fff`;return{colorBgBase:n,colorTextBase:r,colorText:db(r,.85),colorTextSecondary:db(r,.65),colorTextTertiary:db(r,.45),colorTextQuaternary:db(r,.25),colorFill:db(r,.18),colorFillSecondary:db(r,.12),colorFillTertiary:db(r,.08),colorFillQuaternary:db(r,.04),colorBgSolid:db(r,.95),colorBgSolidHover:db(r,1),colorBgSolidActive:db(r,.9),colorBgElevated:fb(n,12),colorBgContainer:fb(n,8),colorBgLayout:fb(n,0),colorBgSpotlight:fb(n,26),colorBgBlur:db(r,.04),colorBorder:fb(n,26),colorBorderDisabled:fb(n,26),colorBorderSecondary:fb(n,19)}},hb=(e,t)=>{let n=Object.keys(ua).map(t=>{let n=ka(e[t],{theme:`dark`});return Array.from({length:10},()=>1).reduce((e,r,i)=>(e[`${t}-${i+1}`]=n[i],e[`${t}${i+1}`]=n[i],e),{})}).reduce((e,t)=>(e={...e,...t},e),{}),r=t??ho(e),i=io(e,{generateColorPalettes:pb,generateNeutralColorPalettes:mb}),a=oa.reduce((t,n)=>{let r=e[n];if(r){let e=pb(r);t[`${n}Hover`]=e[7],t[`${n}Active`]=e[5]}return t},{});return{...r,...n,...i,...a,colorPrimaryBg:i.colorPrimaryBorder,colorPrimaryBgHover:i.colorPrimaryBorderHover}};function gb(){let[e,t,n,r]=Eo();return{theme:e,token:t,hashId:n,cssVar:r}}var _b={defaultSeed:_o.token,useToken:gb,defaultAlgorithm:ho,darkAlgorithm:hb,compactAlgorithm:ub,getDesignToken:cb,defaultConfig:_o,_internalContext:vo},vb={icon:{tag:`svg`,attrs:{viewBox:`64 64 896 896`,focusable:`false`},children:[{tag:`path`,attrs:{d:`M257.7 752c2 0 4-.2 6-.5L431.9 722c2-.4 3.9-1.3 5.3-2.8l423.9-423.9a9.96 9.96 0 000-14.1L694.9 114.9c-1.9-1.9-4.4-2.9-7.1-2.9s-5.2 1-7.1 2.9L256.8 538.8c-1.5 1.5-2.4 3.3-2.8 5.3l-29.5 168.2a33.5 33.5 0 009.4 29.8c6.6 6.4 14.9 9.9 23.8 9.9zm67.4-174.4L687.8 215l73.3 73.3-362.7 362.6-88.9 15.7 15.6-89zM880 836H144c-17.7 0-32 14.3-32 32v36c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-36c0-17.7-14.3-32-32-32z`}}]},name:`edit`,theme:`outlined`};function yb(){return yb=Object.assign?Object.assign.bind():function(e){for(var t=1;tm.createElement(ls,yb({},e,{ref:t,icon:vb}))),xb={icon:{tag:`svg`,attrs:{viewBox:`64 64 896 896`,focusable:`false`},children:[{tag:`path`,attrs:{d:`M864 170h-60c-4.4 0-8 3.6-8 8v518H310v-73c0-6.7-7.8-10.5-13-6.3l-141.9 112a8 8 0 000 12.6l141.9 112c5.3 4.2 13 .4 13-6.3v-75h498c35.3 0 64-28.7 64-64V178c0-4.4-3.6-8-8-8z`}}]},name:`enter`,theme:`outlined`};function Sb(){return Sb=Object.assign?Object.assign.bind():function(e){for(var t=1;tm.createElement(ls,Sb({},e,{ref:t,icon:xb}))),wb=(e,t,n,r)=>{let{titleMarginBottom:i,fontWeightStrong:a}=r;return{marginBottom:i,color:n,fontWeight:a,fontSize:e,lineHeight:t}},Tb=e=>{let t=[1,2,3,4,5],n={};return t.forEach(t=>{n[` - h${t}&, - div&-h${t}, - div&-h${t} > textarea, - h${t} - `]=wb(e[`fontSizeHeading${t}`],e[`lineHeightHeading${t}`],e.colorTextHeading,e)}),n},Eb=e=>{let{componentCls:t}=e;return{[`&${`${t}-link`}`]:{...Fo(e),userSelect:`text`,[`&[disabled], &${t}-disabled`]:{color:e.colorTextDisabled,cursor:`not-allowed`,"&:active, &:hover":{color:e.colorTextDisabled},"&:active":{pointerEvents:`none`}}}}},Db=e=>({code:{margin:`0 0.2em`,paddingInline:`0.4em`,paddingBlock:`0.2em 0.1em`,fontSize:`85%`,fontFamily:e.fontFamilyCode,background:`rgba(150, 150, 150, 0.1)`,border:`1px solid rgba(100, 100, 100, 0.2)`,borderRadius:3},kbd:{margin:`0 0.2em`,paddingInline:`0.4em`,paddingBlock:`0.15em 0.1em`,fontSize:`90%`,fontFamily:e.fontFamilyCode,background:`rgba(150, 150, 150, 0.06)`,border:`1px solid rgba(100, 100, 100, 0.2)`,borderBottomWidth:2,borderRadius:3},mark:{padding:0,backgroundColor:Pa[2]},"u, ins":{textDecoration:`underline`,textDecorationSkipInk:`auto`},"s, del":{textDecoration:`line-through`},strong:{fontWeight:e.fontWeightStrong},"ul, ol":{marginInline:0,marginBlock:`0 1em`,padding:0,li:{marginInline:`20px 0`,marginBlock:0,paddingInline:`4px 0`,paddingBlock:0}},ul:{listStyleType:`circle`,ul:{listStyleType:`disc`}},ol:{listStyleType:`decimal`},"pre, blockquote":{margin:`1em 0`},pre:{padding:`0.4em 0.6em`,whiteSpace:`pre-wrap`,wordWrap:`break-word`,background:`rgba(150, 150, 150, 0.1)`,border:`1px solid rgba(100, 100, 100, 0.2)`,borderRadius:3,fontFamily:e.fontFamilyCode,code:{display:`inline`,margin:0,padding:0,fontSize:`inherit`,fontFamily:`inherit`,background:`transparent`,border:0}},blockquote:{paddingInline:`0.6em 0`,paddingBlock:0,borderInlineStart:`4px solid rgba(100, 100, 100, 0.2)`,opacity:.85}}),Ob=e=>{let{componentCls:t,paddingSM:n}=e,r=n;return{"&-edit-content":{position:`relative`,"div&":{insetInlineStart:e.calc(e.paddingSM).mul(-1).equal(),insetBlockStart:e.calc(r).div(-2).add(1).equal(),marginBottom:e.calc(r).div(2).sub(2).equal()},[`${t}-edit-content-confirm`]:{position:`absolute`,insetInlineEnd:e.calc(e.marginXS).add(2).equal(),insetBlockEnd:e.marginXS,color:e.colorIcon,fontWeight:`normal`,fontSize:e.fontSize,fontStyle:`normal`,pointerEvents:`none`},textarea:{margin:`0!important`,MozTransition:`none`,height:`1em`}}}},kb=e=>({[`${e.componentCls}-copy-success`]:{"\n &,\n &:hover,\n &:focus":{color:e.colorSuccess}},[`${e.componentCls}-copy-icon-only`]:{marginInlineStart:0}}),Ab=()=>({"\n a&-ellipsis,\n span&-ellipsis\n ":{display:`inline-block`,maxWidth:`100%`},"&-ellipsis-single-line":{whiteSpace:`nowrap`,overflow:`hidden`,textOverflow:`ellipsis`,"a&, span&":{verticalAlign:`bottom`},"> code":{paddingBlock:0,maxWidth:`calc(100% - 1.2em)`,display:`inline-block`,overflow:`hidden`,textOverflow:`ellipsis`,verticalAlign:`bottom`,boxSizing:`content-box`}},"&-ellipsis-multiple-line":{display:`-webkit-box`,overflow:`hidden`,WebkitLineClamp:3,WebkitBoxOrient:`vertical`}}),jb=Io(`Typography`,e=>{let{componentCls:t,titleMarginTop:n}=e;return{[t]:{color:e.colorText,wordBreak:`break-word`,lineHeight:e.lineHeight,[`&${t}-secondary, &${t}-link${t}-secondary`]:{color:e.colorTextDescription},[`&${t}-success, &${t}-link${t}-success`]:{color:e.colorSuccessText},[`&${t}-warning, &${t}-link${t}-warning`]:{color:e.colorWarningText},[`&${t}-danger, &${t}-link${t}-danger`]:{color:e.colorErrorText,[`&${t}-link:active, &${t}-link:focus`]:{color:e.colorErrorTextActive},[`&${t}-link:hover`]:{color:e.colorErrorTextHover}},[`&${t}-disabled`]:{color:e.colorTextDisabled,cursor:`not-allowed`,userSelect:`none`},"\n div&,\n p\n ":{marginBottom:`1em`},...Tb(e),[` - & + h1${t}, - & + h2${t}, - & + h3${t}, - & + h4${t}, - & + h5${t} - `]:{marginTop:n},"\n div,\n ul,\n li,\n p,\n h1,\n h2,\n h3,\n h4,\n h5":{"\n + h1,\n + h2,\n + h3,\n + h4,\n + h5\n ":{marginTop:n}},...Db(e),...Eb(e),[`${t}-actions`]:{display:`inline`},[` - ${t}-expand, - ${t}-collapse, - ${t}-edit, - ${t}-copy - `]:{...Fo(e),marginInlineStart:e.marginXXS},...Ob(e),...kb(e),...Ab(),"&-rtl":{direction:`rtl`}}}},()=>({titleMarginTop:`1.2em`,titleMarginBottom:`0.5em`})),Mb=e=>{let{prefixCls:t,"aria-label":n,className:r,style:i,direction:a,maxLength:o,autoSize:s=!0,value:c,onSave:l,onCancel:u,onEnd:d,component:f,enterIcon:p=m.createElement(Cb,null)}=e,h=m.useRef(null),g=m.useRef(!1),_=m.useRef(null),[v,y]=m.useState(c);m.useEffect(()=>{y(c)},[c]),m.useEffect(()=>{if(h.current?.resizableTextArea){let{textArea:e}=h.current.resizableTextArea;e.focus();let{length:t}=e.value;e.setSelectionRange(t,t)}},[]);let b=({target:e})=>{y(e.value.replace(/[\n\r]/g,``))},x=()=>{g.current=!0},S=()=>{g.current=!1},C=({keyCode:e})=>{g.current||(_.current=e)},w=()=>{l(v.trim())},T=({keyCode:e,ctrlKey:t,altKey:n,metaKey:r,shiftKey:i})=>{_.current!==e||g.current||t||n||r||i||(e===J.ENTER?(w(),d?.()):e===J.ESC&&u())},E=()=>{w()},[D,O]=jb(t),k=K(t,`${t}-edit-content`,{[`${t}-rtl`]:a===`rtl`,[`${t}-${f}`]:!!f},r,D,O);return m.createElement(`div`,{className:k,style:i},m.createElement(Ry,{ref:h,maxLength:o,value:v,onChange:b,onKeyDown:C,onKeyUp:T,onCompositionStart:x,onCompositionEnd:S,onBlur:E,"aria-label":n,rows:1,autoSize:s}),p===null?null:Mu(p,{className:`${t}-edit-content-confirm`}))},Nb=(e,t)=>{let n=!1,r=r=>{r.stopPropagation(),r.preventDefault(),r.clipboardData?.clearData(),r.clipboardData?.setData(`text/plain`,e),t&&r.clipboardData?.setData(`text/html`,e),n=!0};try{return document.addEventListener(`copy`,r,{capture:!0}),document.execCommand(`copy`),n}catch{return!1}finally{document.removeEventListener(`copy`,r,{capture:!0})}},Pb=async(e,t)=>{try{return t?await navigator.clipboard.write([new ClipboardItem({"text/html":new Blob([e],{type:`text/html`}),"text/plain":new Blob([e],{type:`text/plain`})})]):await navigator.clipboard.writeText(e),!0}catch{return!1}};async function Fb(e,t){if(typeof e!=`string`)return!1;let n=t?.format===`text/html`;return!!(await Pb(e,n)||Nb(e,n))}var Ib=({copyConfig:e,children:t})=>{let[n,r]=m.useState(!1),[i,a]=m.useState(!1),o=m.useRef(null),s=()=>{o.current&&clearTimeout(o.current)},c={};return e.format&&(c.format=e.format),m.useEffect(()=>s,[]),{copied:n,copyLoading:i,onClick:W(async n=>{n?.preventDefault(),n?.stopPropagation(),a(!0);try{await Fb((typeof e.text==`function`?await e.text():e.text)||ob(t,{skipEmpty:!0}).join(``)||``,c),a(!1),r(!0),s(),o.current=setTimeout(()=>{r(!1)},3e3),e.onCopy?.(n)}catch(e){throw a(!1),e}})}};function Lb(e,t){return m.useMemo(()=>{let n=!!e;return[n,{...t,...n&&typeof e==`object`?e:null}]},[e])}var Rb=e=>{let t=(0,m.useRef)(void 0);return(0,m.useEffect)(()=>{t.current=e}),t.current},zb=(e,t,n)=>(0,m.useMemo)(()=>e===!0?{title:t??n}:(0,m.isValidElement)(e)?{title:e}:typeof e==`object`?{title:t??n,...e}:{title:e},[e,t,n]),Bb=m.forwardRef((e,t)=>{let{prefixCls:n,component:r=`article`,className:i,rootClassName:a,children:o,direction:s,style:c,...l}=e,{getPrefixCls:u,direction:d,className:f,style:p}=Ht(`typography`),h=s??d,g=u(`typography`,n),[_,v]=jb(g),y=K(g,f,{[`${g}-rtl`]:h===`rtl`},i,a,_,v),b={...p,...c};return m.createElement(r,{className:y,style:b,ref:t,...l},o)}),Vb={icon:{tag:`svg`,attrs:{viewBox:`64 64 896 896`,focusable:`false`},children:[{tag:`path`,attrs:{d:`M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z`}}]},name:`copy`,theme:`outlined`};function Hb(){return Hb=Object.assign?Object.assign.bind():function(e){for(var t=1;tm.createElement(ls,Hb({},e,{ref:t,icon:Vb}))),Wb=e=>e===!1?[!1,!1]:ob(e);function Gb(e,t,n){return e===!0||e===void 0?t:e||n&&t}function Kb(e){let t=document.createElement(`em`);e.appendChild(t);let n=e.getBoundingClientRect(),r=t.getBoundingClientRect();return e.removeChild(t),n.left>r.left||r.right>n.right||n.top>r.top||r.bottom>n.bottom}var qb=e=>[`string`,`number`].includes(typeof e),Jb=e=>{let{prefixCls:t,copied:n,locale:r,iconOnly:i,tooltips:a,icon:o,tabIndex:s,onCopy:c,loading:l}=e,u=Wb(a),d=Wb(o),{copied:f,copy:p}=r??{},h=n?f:p,g=Gb(u[n?1:0],h),_=typeof g==`string`?g:h;return m.createElement(bv,{title:g},m.createElement(`button`,{type:`button`,className:K(`${t}-copy`,{[`${t}-copy-success`]:n,[`${t}-copy-icon-only`]:i}),onClick:c,"aria-label":_,tabIndex:s},n?Gb(d[1],m.createElement(V_,null),!0):Gb(d[0],l?m.createElement(md,null):m.createElement(Ub,null),!0)))},Yb=m.forwardRef(({style:e,children:t},n)=>{let r=m.useRef(null);return m.useImperativeHandle(n,()=>({isExceed:()=>{let e=r.current;return e.scrollHeight>e.clientHeight},getHeight:()=>r.current.clientHeight})),m.createElement(`span`,{"aria-hidden":!0,ref:r,style:{position:`fixed`,display:`block`,left:0,top:0,pointerEvents:`none`,backgroundColor:`rgba(255, 0, 0, 0.65)`,...e}},t)}),Xb=e=>e.reduce((e,t)=>e+(qb(t)?String(t).length:1),0);function Zb(e,t){let n=0,r=[];for(let i=0;it){let e=t-n;return r.push(String(a).slice(0,e)),r}r.push(a),n=s}return e}var Qb=0,$b=1,ex=2,tx=3,nx=4,rx={display:`-webkit-box`,overflow:`hidden`,WebkitBoxOrient:`vertical`};function ix(e){let{enableMeasure:t,width:n,text:r,children:i,rows:a,expanded:o,miscDeps:s,onEllipsis:c}=e,l=m.useMemo(()=>nt(r),[r]),u=m.useMemo(()=>Xb(l),[r]),d=m.useMemo(()=>i(l,!1),[r]),[f,p]=m.useState(null),h=m.useRef(null),g=m.useRef(null),_=m.useRef(null),v=m.useRef(null),y=m.useRef(null),[b,x]=m.useState(!1),[S,C]=m.useState(Qb),[w,T]=m.useState(0),[E,D]=m.useState(null);G(()=>{C(t&&n&&u?$b:Qb)},[n,r,a,t,l]),G(()=>{if(S===$b)C(ex),D(g.current&&getComputedStyle(g.current).whiteSpace);else if(S===ex){let e=!!_.current?.isExceed();C(e?tx:nx),p(e?[0,u]:null),x(e);let t=_.current?.getHeight()||0,n=a===1?0:v.current?.getHeight()||0,r=y.current?.getHeight()||0;T(Math.max(t,n+r)+1),c(e)}},[S]);let O=f?Math.ceil((f[0]+f[1])/2):0;G(()=>{let[e,t]=f||[0,0];if(e!==t){let n=(h.current?.getHeight()||0)>w,r=O;t-e===1&&(r=n?e:t),p(n?[e,r]:[r,t])}},[f,O]);let k=m.useMemo(()=>{if(!t)return i(l,!1);if(S!==tx||!f||f[0]!==f[1]){let e=i(l,!1);return[nx,Qb].includes(S)?e:m.createElement(`span`,{style:{...rx,WebkitLineClamp:a}},e)}return i(o?l:Zb(l,f[0]),b)},[o,S,f,l].concat(At(s))),A={width:n,margin:0,padding:0,whiteSpace:E===`nowrap`?`normal`:`inherit`};return m.createElement(m.Fragment,null,k,S===ex&&m.createElement(m.Fragment,null,m.createElement(Yb,{style:{...A,...rx,WebkitLineClamp:a},ref:_},d),m.createElement(Yb,{style:{...A,...rx,WebkitLineClamp:a-1},ref:v},d),m.createElement(Yb,{style:{...A,...rx,WebkitLineClamp:1},ref:y},i([],!0))),S===tx&&f&&f[0]!==f[1]&&m.createElement(Yb,{style:{...A,top:400},ref:h},i(Zb(l,O),!0)),S===$b&&m.createElement(`span`,{style:{whiteSpace:`inherit`},ref:g}))}var ax=({enableEllipsis:e,isEllipsis:t,open:n,children:r,tooltipProps:i})=>{if(!i?.title||!e)return r;let a=n&&t;return m.createElement(bv,{open:a,...i},r)};function ox({mark:e,code:t,underline:n,delete:r,strong:i,keyboard:a,italic:o},s){let c=s;function l(e,t){t&&(c=m.createElement(e,{},c))}return l(`strong`,i),l(`u`,n),l(`del`,r),l(`code`,t),l(`mark`,e),l(`kbd`,a),l(`i`,o),c}var sx=`...`,cx=[`delete`,`mark`,`code`,`underline`,`strong`,`keyboard`,`italic`],lx=m.forwardRef((e,t)=>{let{prefixCls:n,className:r,style:i,type:a,disabled:o,children:s,ellipsis:c,editable:l,copyable:u,component:d,title:f,onMouseEnter:p,onMouseLeave:h,...g}=e,{getPrefixCls:_,direction:v}=m.useContext(zt),[y]=Vc(`Text`),b=m.useRef(null),x=m.useRef(null),S=_(`typography`,n),C=tt(g,cx),[w,T]=Lb(l),[E,D]=xe(!1,T.editing),{triggerType:O=[`icon`]}=T,k=e=>{e&&T.onStart?.(),D(e)},A=Rb(E);G(()=>{!E&&A&&x.current?.focus()},[E]);let j=e=>{e?.preventDefault(),k(!0)},M=e=>{T.onChange?.(e),k(!1)},N=()=>{T.onCancel?.(),k(!1)},[P,F]=Lb(u),{copied:I,copyLoading:L,onClick:ee}=Ib({copyConfig:F,children:s}),[R,z]=m.useState(!1),[B,V]=m.useState(!1),[te,ne]=m.useState(!1),[re,ie]=m.useState(!1),[ae,oe]=m.useState(!0),[H,se]=Lb(c,{expandable:!1,symbol:e=>e?y?.collapse:y?.expand}),[ce,le]=xe(se.defaultExpanded||!1,se.expanded),U=H&&(!ce||se.expandable===`collapsible`),{rows:ue=1}=se,de=m.useMemo(()=>U&&(se.suffix!==void 0||se.onEllipsis||se.expandable||w||P),[U,se,w,P]);G(()=>{H&&!de&&(z(Rh(`webkitLineClamp`)),V(Rh(`textOverflow`)))},[de,H]);let[fe,pe]=m.useState(U),me=m.useMemo(()=>de?!1:ue===1?B:R,[de,B,R]);G(()=>{pe(me&&U)},[me,U]);let he=U&&(fe?re:te),ge=U&&ue===1&&fe,_e=U&&ue>1&&fe,W=(e,t)=>{le(t.expanded),se.onExpand?.(e,t)},[ve,ye]=m.useState(0),[be,Se]=m.useState(!1),[Ce,we]=m.useState(!1),Te=({offsetWidth:e})=>{ye(e)},Ee=e=>{ne(e),te!==e&&se.onEllipsis?.(e)};m.useEffect(()=>{let e=b.current;if(H&&fe&&e){let t=Kb(e);re!==t&&ie(t)}},[H,fe,s,_e,ae,ve]),m.useEffect(()=>{let e=b.current;if(typeof IntersectionObserver>`u`||!e||!fe||!U)return;let t=new IntersectionObserver(()=>{oe(!!e.offsetParent)});return t.observe(e),()=>{t.disconnect()}},[fe,U]);let De=zb(se.tooltip,T.text,s),Oe=m.useMemo(()=>{if(!(!H||fe))return[T.text,s,f,De.title].find(qb)},[H,fe,f,De.title,he]);if(E)return m.createElement(Mb,{value:T.text??(typeof s==`string`?s:``),onSave:M,onCancel:N,onEnd:T.onEnd,prefixCls:S,className:r,style:i,direction:v,component:d,maxLength:T.maxLength,autoSize:T.autoSize,enterIcon:T.enterIcon});let ke=()=>{let{expandable:e,symbol:t}=se;return e?m.createElement(`button`,{type:`button`,key:`expand`,className:`${S}-${ce?`collapse`:`expand`}`,onClick:e=>W(e,{expanded:!ce}),"aria-label":ce?y.collapse:y?.expand},typeof t==`function`?t(ce):t):null},Ae=()=>{if(!w)return;let{icon:e,tooltip:t,tabIndex:n}=T,r=nt(t)[0]||y?.edit,i=typeof r==`string`?r:``;return O.includes(`icon`)?m.createElement(bv,{key:`edit`,title:t===!1?``:r},m.createElement(`button`,{type:`button`,ref:x,className:`${S}-edit`,onClick:j,"aria-label":i,tabIndex:n},e||m.createElement(bb,{role:`button`}))):null},je=()=>P?m.createElement(Jb,{key:`copy`,...F,prefixCls:S,copied:I,locale:y,onCopy:ee,loading:L,iconOnly:!Gc(s)}):null,Ne=e=>{let t=e&&ke(),n=Ae(),r=je();return!t&&!n&&!r?null:m.createElement(`span`,{key:`operations`,className:`${S}-actions`,onMouseEnter:()=>Se(!0),onMouseLeave:()=>Se(!1)},t,n,r)},Pe=e=>[e&&!ce&&m.createElement(`span`,{"aria-hidden":!0,key:`ellipsis`},sx),se.suffix,Ne(e)];return m.createElement(Ct,{onResize:Te,disabled:!U},c=>m.createElement(ax,{tooltipProps:De,enableEllipsis:U,isEllipsis:he,open:Ce&&!be},m.createElement(Bb,{onMouseEnter:e=>{we(!0),p?.(e)},onMouseLeave:e=>{we(!1),h?.(e)},className:K({[`${S}-${a}`]:a,[`${S}-disabled`]:o,[`${S}-ellipsis`]:H,[`${S}-ellipsis-single-line`]:ge,[`${S}-ellipsis-multiple-line`]:_e,[`${S}-link`]:d===`a`},r),prefixCls:n,style:{...i,WebkitLineClamp:_e?ue:void 0},component:d,ref:Me(c,b,t),direction:v,onClick:O.includes(`text`)?j:void 0,"aria-label":Oe?.toString(),title:f,...C},m.createElement(ix,{enableMeasure:U&&!fe,text:s,rows:ue,width:ve,onEllipsis:Ee,expanded:ce,miscDeps:[I,ce,L,w,P,y].concat(At(cx.map(t=>e[t])))},(t,n)=>ox(e,m.createElement(m.Fragment,null,t.length>0&&n&&!ce&&Oe?m.createElement(`span`,{key:`show-content`,"aria-hidden":!0},t):t,Pe(n)))))))}),ux=m.forwardRef((e,t)=>{let{ellipsis:n,rel:r,children:i,navigate:a,...o}=e,s={...o,rel:r===void 0&&o.target===`_blank`?`noopener noreferrer`:r};return m.createElement(lx,{...s,ref:t,ellipsis:!!n,component:`a`},i)}),dx=m.forwardRef((e,t)=>{let{children:n,...r}=e;return m.createElement(lx,{ref:t,...r,component:`div`},n)}),fx=m.forwardRef((e,t)=>{let{ellipsis:n,children:r,...i}=e,a=m.useMemo(()=>n&&typeof n==`object`?tt(n,[`expandable`,`rows`]):n,[n]);return m.createElement(lx,{ref:t,...i,ellipsis:a,component:`span`},r)}),px=[1,2,3,4,5],mx=m.forwardRef((e,t)=>{let{level:n=1,children:r,...i}=e,a=px.includes(n)?`h${n}`:`h1`;return m.createElement(lx,{ref:t,...i,component:a},r)}),hx=Bb;hx.Text=fx,hx.Link=ux,hx.Title=mx,hx.Paragraph=dx;var gx=class extends Error{};gx.prototype.name=`InvalidTokenError`;function _x(e){return decodeURIComponent(atob(e).replace(/(.)/g,(e,t)=>{let n=t.charCodeAt(0).toString(16).toUpperCase();return n.length<2&&(n=`0`+n),`%`+n}))}function vx(e){let t=e.replace(/-/g,`+`).replace(/_/g,`/`);switch(t.length%4){case 0:break;case 2:t+=`==`;break;case 3:t+=`=`;break;default:throw Error(`base64 string is not of the correct length`)}try{return _x(t)}catch{return atob(t)}}function yx(e,t){if(typeof e!=`string`)throw new gx(`Invalid token specified: must be a string`);t||={};let n=t.header===!0?0:1,r=e.split(`.`)[n];if(typeof r!=`string`)throw new gx(`Invalid token specified: missing part #${n+1}`);let i;try{i=vx(r)}catch(e){throw new gx(`Invalid token specified: invalid base64 for part #${n+1} (${e.message})`)}try{return JSON.parse(i)}catch(e){throw new gx(`Invalid token specified: invalid json for part #${n+1} (${e.message})`)}}var bx={debug:()=>void 0,info:()=>void 0,warn:()=>void 0,error:()=>void 0},xx,Sx,Cx=(e=>(e[e.NONE=0]=`NONE`,e[e.ERROR=1]=`ERROR`,e[e.WARN=2]=`WARN`,e[e.INFO=3]=`INFO`,e[e.DEBUG=4]=`DEBUG`,e))(Cx||{});(e=>{function t(){xx=3,Sx=bx}e.reset=t;function n(e){if(!(0<=e&&e<=4))throw Error(`Invalid log level`);xx=e}e.setLevel=n;function r(e){Sx=e}e.setLogger=r})(Cx||={});var wx=class e{constructor(e){this._name=e}debug(...t){xx>=4&&Sx.debug(e._format(this._name,this._method),...t)}info(...t){xx>=3&&Sx.info(e._format(this._name,this._method),...t)}warn(...t){xx>=2&&Sx.warn(e._format(this._name,this._method),...t)}error(...t){xx>=1&&Sx.error(e._format(this._name,this._method),...t)}throw(e){throw this.error(e),e}create(e){let t=Object.create(this);return t._method=e,t.debug(`begin`),t}static createStatic(t,n){let r=new e(`${t}.${n}`);return r.debug(`begin`),r}static _format(e,t){let n=`[${e}]`;return t?`${n} ${t}:`:n}static debug(t,...n){xx>=4&&Sx.debug(e._format(t),...n)}static info(t,...n){xx>=3&&Sx.info(e._format(t),...n)}static warn(t,...n){xx>=2&&Sx.warn(e._format(t),...n)}static error(t,...n){xx>=1&&Sx.error(e._format(t),...n)}};Cx.reset();var Tx=class{static decode(e){try{return yx(e)}catch(e){throw wx.error(`JwtUtils.decode`,e),e}}static async generateSignedJwt(e,t,n){let r=`${kx.encodeBase64Url(new TextEncoder().encode(JSON.stringify(e)))}.${kx.encodeBase64Url(new TextEncoder().encode(JSON.stringify(t)))}`,i=await window.crypto.subtle.sign({name:`ECDSA`,hash:{name:`SHA-256`}},n,new TextEncoder().encode(r));return`${r}.${kx.encodeBase64Url(new Uint8Array(i))}`}static async generateSignedJwtWithHmac(e,t,n){let r=`${kx.encodeBase64Url(new TextEncoder().encode(JSON.stringify(e)))}.${kx.encodeBase64Url(new TextEncoder().encode(JSON.stringify(t)))}`,i=await window.crypto.subtle.sign(`HMAC`,n,new TextEncoder().encode(r));return`${r}.${kx.encodeBase64Url(new Uint8Array(i))}`}},Ex=`10000000-1000-4000-8000-100000000000`,Dx=e=>btoa([...new Uint8Array(e)].map(e=>String.fromCharCode(e)).join(``)),Ox=class e{static _randomWord(){let e=new Uint32Array(1);return crypto.getRandomValues(e),e[0]}static generateUUIDv4(){return Ex.replace(/[018]/g,t=>(t^e._randomWord()&15>>t/4).toString(16)).replace(/-/g,``)}static generateCodeVerifier(){return e.generateUUIDv4()+e.generateUUIDv4()+e.generateUUIDv4()}static async generateCodeChallenge(e){if(!crypto.subtle)throw Error(`Crypto.subtle is available only in secure contexts (HTTPS).`);try{let t=new TextEncoder().encode(e);return Dx(await crypto.subtle.digest(`SHA-256`,t)).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}catch(e){throw wx.error(`CryptoUtils.generateCodeChallenge`,e),e}}static generateBasicAuth(e,t){return Dx(new TextEncoder().encode([e,t].join(`:`)))}static async hash(e,t){let n=new TextEncoder().encode(t),r=await crypto.subtle.digest(e,n);return new Uint8Array(r)}static async customCalculateJwkThumbprint(t){let n;switch(t.kty){case`RSA`:n={e:t.e,kty:t.kty,n:t.n};break;case`EC`:n={crv:t.crv,kty:t.kty,x:t.x,y:t.y};break;case`OKP`:n={crv:t.crv,kty:t.kty,x:t.x};break;case`oct`:n={crv:t.k,kty:t.kty};break;default:throw Error(`Unknown jwk type`)}let r=await e.hash(`SHA-256`,JSON.stringify(n));return e.encodeBase64Url(r)}static async generateDPoPProof({url:t,accessToken:n,httpMethod:r,keyPair:i,nonce:a}){let o,s,c={jti:window.crypto.randomUUID(),htm:r??`GET`,htu:t,iat:Math.floor(Date.now()/1e3)};n&&(o=await e.hash(`SHA-256`,n),s=e.encodeBase64Url(o),c.ath=s),a&&(c.nonce=a);try{let e=await crypto.subtle.exportKey(`jwk`,i.publicKey),t={alg:`ES256`,typ:`dpop+jwt`,jwk:{crv:e.crv,kty:e.kty,x:e.x,y:e.y}};return await Tx.generateSignedJwt(t,c,i.privateKey)}catch(e){throw e instanceof TypeError?Error(`Error exporting dpop public key: ${e.message}`):e}}static async generateDPoPJkt(t){try{let n=await crypto.subtle.exportKey(`jwk`,t.publicKey);return await e.customCalculateJwkThumbprint(n)}catch(e){throw e instanceof TypeError?Error(`Could not retrieve dpop keys from storage: ${e.message}`):e}}static async generateDPoPKeys(){return await window.crypto.subtle.generateKey({name:`ECDSA`,namedCurve:`P-256`},!1,[`sign`,`verify`])}static async generateClientAssertionJwt(t,n,r,i=`HS256`){let a=Math.floor(Date.now()/1e3),o={alg:i,typ:`JWT`},s={iss:t,sub:t,aud:r,jti:e.generateUUIDv4(),exp:a+300,iat:a},c={HS256:`SHA-256`,HS384:`SHA-384`,HS512:`SHA-512`}[i];if(!c)throw Error(`Unsupported algorithm: ${i}. Supported algorithms are: HS256, HS384, HS512`);let l=new TextEncoder,u=await crypto.subtle.importKey(`raw`,l.encode(n),{name:`HMAC`,hash:c},!1,[`sign`]);return await Tx.generateSignedJwtWithHmac(o,s,u)}};Ox.encodeBase64Url=e=>Dx(e).replace(/=/g,``).replace(/\+/g,`-`).replace(/\//g,`_`);var kx=Ox,Ax=class{constructor(e){this._name=e,this._callbacks=[],this._logger=new wx(`Event('${this._name}')`)}addHandler(e){return this._callbacks.push(e),()=>this.removeHandler(e)}removeHandler(e){let t=this._callbacks.lastIndexOf(e);t>=0&&this._callbacks.splice(t,1)}async raise(...e){this._logger.debug(`raise:`,...e);for(let t of this._callbacks)await t(...e)}},jx=class{static center({...e}){return e.width??=[800,720,600,480].find(e=>e<=window.outerWidth/1.618)??360,e.left??=Math.max(0,Math.round(window.screenX+(window.outerWidth-e.width)/2)),e.height!=null&&(e.top??=Math.max(0,Math.round(window.screenY+(window.outerHeight-e.height)/2))),e}static serialize(e){return Object.entries(e).filter(([,e])=>e!=null).map(([e,t])=>`${e}=${typeof t==`boolean`?t?`yes`:`no`:t}`).join(`,`)}},Mx=class e extends Ax{constructor(){super(...arguments),this._logger=new wx(`Timer('${this._name}')`),this._timerHandle=null,this._expiration=0,this._callback=()=>{let t=this._expiration-e.getEpochTime();this._logger.debug(`timer completes in`,t),this._expiration<=e.getEpochTime()&&(this.cancel(),super.raise())}}static getEpochTime(){return Math.floor(Date.now()/1e3)}init(t){let n=this._logger.create(`init`);t=Math.max(Math.floor(t),1);let r=e.getEpochTime()+t;if(this.expiration===r&&this._timerHandle){n.debug(`skipping since already initialized for expiration at`,this.expiration);return}this.cancel(),n.debug(`using duration`,t),this._expiration=r;let i=Math.min(t,5);this._timerHandle=setInterval(this._callback,i*1e3)}get expiration(){return this._expiration}cancel(){this._logger.create(`cancel`),this._timerHandle&&=(clearInterval(this._timerHandle),null)}},Nx=class{static readParams(e,t=`query`){if(!e)throw TypeError(`Invalid URL`);let n=new URL(e,`http://127.0.0.1`)[t===`fragment`?`hash`:`search`];return new URLSearchParams(n.slice(1))}},Px=`;`,Fx=class extends Error{constructor(e,t){if(super(e.error_description||e.error||``),this.form=t,this.name=`ErrorResponse`,!e.error)throw wx.error(`ErrorResponse`,`No error passed`),Error(`No error passed`);this.error=e.error,this.error_description=e.error_description??null,this.error_uri=e.error_uri??null,this.state=e.userState,this.session_state=e.session_state??null,this.url_state=e.url_state}},Ix=class extends Error{constructor(e){super(e),this.name=`ErrorTimeout`}},Lx=class{constructor(e){this._logger=new wx(`AccessTokenEvents`),this._expiringTimer=new Mx(`Access token expiring`),this._expiredTimer=new Mx(`Access token expired`),this._expiringNotificationTimeInSeconds=e.expiringNotificationTimeInSeconds}async load(e){let t=this._logger.create(`load`);if(e.access_token&&e.expires_in!==void 0){let n=e.expires_in;if(t.debug(`access token present, remaining duration:`,n),n>0){let e=n-this._expiringNotificationTimeInSeconds;e<=0&&(e=1),t.debug(`registering expiring timer, raising in`,e,`seconds`),this._expiringTimer.init(e)}else t.debug(`canceling existing expiring timer because we're past expiration.`),this._expiringTimer.cancel();let r=n+1;t.debug(`registering expired timer, raising in`,r,`seconds`),this._expiredTimer.init(r)}else this._expiringTimer.cancel(),this._expiredTimer.cancel()}async unload(){this._logger.debug(`unload: canceling existing access token timers`),this._expiringTimer.cancel(),this._expiredTimer.cancel()}addAccessTokenExpiring(e){return this._expiringTimer.addHandler(e)}removeAccessTokenExpiring(e){this._expiringTimer.removeHandler(e)}addAccessTokenExpired(e){return this._expiredTimer.addHandler(e)}removeAccessTokenExpired(e){this._expiredTimer.removeHandler(e)}},Rx=class{constructor(e,t,n,r,i){this._callback=e,this._client_id=t,this._intervalInSeconds=r,this._stopOnError=i,this._logger=new wx(`CheckSessionIFrame`),this._timer=null,this._session_state=null,this._message=e=>{e.origin===this._frame_origin&&e.source===this._frame.contentWindow&&(e.data===`error`?(this._logger.error(`error message from check session op iframe`),this._stopOnError&&this.stop()):e.data===`changed`?(this._logger.debug(`changed message from check session op iframe`),this.stop(),this._callback()):this._logger.debug(e.data+` message from check session op iframe`))};let a=new URL(n);this._frame_origin=a.origin,this._frame=window.document.createElement(`iframe`),this._frame.style.visibility=`hidden`,this._frame.style.position=`fixed`,this._frame.style.left=`-1000px`,this._frame.style.top=`0`,this._frame.width=`0`,this._frame.height=`0`,this._frame.src=a.href}load(){return new Promise(e=>{this._frame.onload=()=>{e()},window.document.body.appendChild(this._frame),window.addEventListener(`message`,this._message,!1)})}start(e){if(this._session_state===e)return;this._logger.create(`start`),this.stop(),this._session_state=e;let t=()=>{!this._frame.contentWindow||!this._session_state||this._frame.contentWindow.postMessage(this._client_id+` `+this._session_state,this._frame_origin)};t(),this._timer=setInterval(t,this._intervalInSeconds*1e3)}stop(){this._logger.create(`stop`),this._session_state=null,this._timer&&=(clearInterval(this._timer),null)}},zx=class{constructor(){this._logger=new wx(`InMemoryWebStorage`),this._data={}}clear(){this._logger.create(`clear`),this._data={}}getItem(e){return this._logger.create(`getItem('${e}')`),this._data[e]}setItem(e,t){this._logger.create(`setItem('${e}')`),this._data[e]=t}removeItem(e){this._logger.create(`removeItem('${e}')`),delete this._data[e]}get length(){return Object.getOwnPropertyNames(this._data).length}key(e){return Object.getOwnPropertyNames(this._data)[e]}},Bx=class extends Error{constructor(e,t){super(t),this.name=`ErrorDPoPNonce`,this.nonce=e}},Vx=class{constructor(e=[],t=null,n={}){this._jwtHandler=t,this._extraHeaders=n,this._logger=new wx(`JsonService`),this._contentTypes=[],this._contentTypes.push(...e,`application/json`),t&&this._contentTypes.push(`application/jwt`)}async fetchWithTimeout(e,t={}){let{timeoutInSeconds:n,...r}=t;if(!n)return await fetch(e,r);let i=new AbortController,a=setTimeout(()=>i.abort(),n*1e3);try{return await fetch(e,{...t,signal:i.signal})}catch(e){throw e instanceof DOMException&&e.name===`AbortError`?new Ix(`Network timed out`):e}finally{clearTimeout(a)}}async getJson(e,{token:t,credentials:n,timeoutInSeconds:r}={}){let i=this._logger.create(`getJson`),a={Accept:this._contentTypes.join(`, `)};t&&(i.debug(`token passed, setting Authorization header`),a.Authorization=`Bearer `+t),this._appendExtraHeaders(a);let o;try{i.debug(`url:`,e),o=await this.fetchWithTimeout(e,{method:`GET`,headers:a,timeoutInSeconds:r,credentials:n})}catch(e){throw i.error(`Network Error`),e}i.debug(`HTTP response received, status`,o.status);let s=o.headers.get(`Content-Type`);if(s&&!this._contentTypes.find(e=>s.startsWith(e))&&i.throw(Error(`Invalid response Content-Type: ${s??`undefined`}, from URL: ${e}`)),o.ok&&this._jwtHandler&&s?.startsWith(`application/jwt`))return await this._jwtHandler(await o.text());let c;try{c=await o.json()}catch(e){throw i.error(`Error parsing JSON response`,e),o.ok?e:Error(`${o.statusText} (${o.status})`)}if(!o.ok)throw i.error(`Error from server:`,c),c.error?new Fx(c):Error(`${o.statusText} (${o.status}): ${JSON.stringify(c)}`);return c}async postForm(e,{body:t,basicAuth:n,timeoutInSeconds:r,initCredentials:i,extraHeaders:a}){let o=this._logger.create(`postForm`),s={Accept:this._contentTypes.join(`, `),"Content-Type":`application/x-www-form-urlencoded`,...a};n!==void 0&&(s.Authorization=`Basic `+n),this._appendExtraHeaders(s);let c;try{o.debug(`url:`,e),c=await this.fetchWithTimeout(e,{method:`POST`,headers:s,body:t,timeoutInSeconds:r,credentials:i})}catch(e){throw o.error(`Network error`),e}o.debug(`HTTP response received, status`,c.status);let l=c.headers.get(`Content-Type`);if(l&&!this._contentTypes.find(e=>l.startsWith(e)))throw Error(`Invalid response Content-Type: ${l??`undefined`}, from URL: ${e}`);let u=await c.text(),d={};if(u)try{d=JSON.parse(u)}catch(e){throw o.error(`Error parsing JSON response`,e),c.ok?e:Error(`${c.statusText} (${c.status})`)}if(!c.ok)throw o.error(`Error from server:`,d),c.headers.has(`dpop-nonce`)?new Bx(c.headers.get(`dpop-nonce`),`${JSON.stringify(d)}`):d.error?new Fx(d,t):Error(`${c.statusText} (${c.status}): ${JSON.stringify(d)}`);return d}_appendExtraHeaders(e){let t=this._logger.create(`appendExtraHeaders`),n=Object.keys(this._extraHeaders),r=[`accept`,`content-type`],i=[`authorization`];n.length!==0&&n.forEach(n=>{if(r.includes(n.toLocaleLowerCase())){t.warn(`Protected header could not be set`,n,r);return}if(i.includes(n.toLocaleLowerCase())&&Object.keys(e).includes(n)){t.warn(`Header could not be overridden`,n,i);return}let a=typeof this._extraHeaders[n]==`function`?this._extraHeaders[n]():this._extraHeaders[n];a&&a!==``&&(e[n]=a)})}},Hx=class{constructor(e){this._settings=e,this._logger=new wx(`MetadataService`),this._signingKeys=null,this._metadata=null,this._metadataUrl=this._settings.metadataUrl,this._jsonService=new Vx([`application/jwk-set+json`],null,this._settings.extraHeaders),this._settings.signingKeys&&(this._logger.debug(`using signingKeys from settings`),this._signingKeys=this._settings.signingKeys),this._settings.metadata&&(this._logger.debug(`using metadata from settings`),this._metadata=this._settings.metadata),this._settings.fetchRequestCredentials&&(this._logger.debug(`using fetchRequestCredentials from settings`),this._fetchRequestCredentials=this._settings.fetchRequestCredentials)}resetSigningKeys(){this._signingKeys=null}async getMetadata(){let e=this._logger.create(`getMetadata`);if(this._metadata)return e.debug(`using cached values`),this._metadata;if(!this._metadataUrl)throw e.throw(Error(`No authority or metadataUrl configured on settings`)),null;e.debug(`getting metadata from`,this._metadataUrl);let t=await this._jsonService.getJson(this._metadataUrl,{credentials:this._fetchRequestCredentials,timeoutInSeconds:this._settings.requestTimeoutInSeconds});return e.debug(`merging remote JSON with seed metadata`),this._metadata=Object.assign({},t,this._settings.metadataSeed),this._metadata}getIssuer(){return this._getMetadataProperty(`issuer`)}getAuthorizationEndpoint(){return this._getMetadataProperty(`authorization_endpoint`)}getUserInfoEndpoint(){return this._getMetadataProperty(`userinfo_endpoint`)}getTokenEndpoint(e=!0){return this._getMetadataProperty(`token_endpoint`,e)}getCheckSessionIframe(){return this._getMetadataProperty(`check_session_iframe`,!0)}getEndSessionEndpoint(){return this._getMetadataProperty(`end_session_endpoint`,!0)}getRevocationEndpoint(e=!0){return this._getMetadataProperty(`revocation_endpoint`,e)}getKeysEndpoint(e=!0){return this._getMetadataProperty(`jwks_uri`,e)}async _getMetadataProperty(e,t=!1){let n=this._logger.create(`_getMetadataProperty('${e}')`),r=await this.getMetadata();if(n.debug(`resolved`),r[e]===void 0){if(t===!0){n.warn(`Metadata does not contain optional property`);return}n.throw(Error(`Metadata does not contain property `+e))}return r[e]}async getSigningKeys(){let e=this._logger.create(`getSigningKeys`);if(this._signingKeys)return e.debug(`returning signingKeys from cache`),this._signingKeys;let t=await this.getKeysEndpoint(!1);e.debug(`got jwks_uri`,t);let n=await this._jsonService.getJson(t,{timeoutInSeconds:this._settings.requestTimeoutInSeconds});if(e.debug(`got key set`,n),!Array.isArray(n.keys))throw e.throw(Error(`Missing keys on keyset`)),null;return this._signingKeys=n.keys,this._signingKeys}},Ux=class{constructor({prefix:e=`oidc.`,store:t=localStorage}={}){this._logger=new wx(`WebStorageStateStore`),this._store=t,this._prefix=e}async set(e,t){this._logger.create(`set('${e}')`),e=this._prefix+e,await this._store.setItem(e,t)}async get(e){return this._logger.create(`get('${e}')`),e=this._prefix+e,await this._store.getItem(e)}async remove(e){this._logger.create(`remove('${e}')`),e=this._prefix+e;let t=await this._store.getItem(e);return await this._store.removeItem(e),t}async getAllKeys(){this._logger.create(`getAllKeys`);let e=await this._store.length,t=[];for(let n=0;n{let t=this._logger.create(`_getClaimsFromJwt`);try{let n=Tx.decode(e);return t.debug(`JWT decoding successful`),n}catch(e){throw t.error(`Error parsing JWT response`),e}},this._jsonService=new Vx(void 0,this._getClaimsFromJwt,this._settings.extraHeaders)}async getClaims(e){let t=this._logger.create(`getClaims`);e||this._logger.throw(Error(`No token passed`));let n=await this._metadataService.getUserInfoEndpoint();t.debug(`got userinfo url`,n);let r=await this._jsonService.getJson(n,{token:e,credentials:this._settings.fetchRequestCredentials,timeoutInSeconds:this._settings.requestTimeoutInSeconds});return t.debug(`got claims`,r),r}},Xx=class{constructor(e,t){this._settings=e,this._metadataService=t,this._logger=new wx(`TokenClient`),this._jsonService=new Vx(this._settings.revokeTokenAdditionalContentTypes,null,this._settings.extraHeaders)}async exchangeCode({grant_type:e=`authorization_code`,redirect_uri:t=this._settings.redirect_uri,client_id:n=this._settings.client_id,client_secret:r=this._settings.client_secret,extraHeaders:i,...a}){let o=this._logger.create(`exchangeCode`);n||o.throw(Error(`A client_id is required`)),t||o.throw(Error(`A redirect_uri is required`)),a.code||o.throw(Error(`A code is required`));let s=new URLSearchParams({grant_type:e,redirect_uri:t});for(let[e,t]of Object.entries(a))t!=null&&s.set(e,t);if((this._settings.client_authentication===`client_secret_basic`||this._settings.client_authentication===`client_secret_jwt`)&&r==null)throw o.throw(Error(`A client_secret is required`)),null;let c,l=await this._metadataService.getTokenEndpoint(!1);switch(this._settings.client_authentication){case`client_secret_basic`:c=kx.generateBasicAuth(n,r);break;case`client_secret_post`:s.append(`client_id`,n),r&&s.append(`client_secret`,r);break;case`client_secret_jwt`:{let e=await kx.generateClientAssertionJwt(n,r,l,this._settings.token_endpoint_auth_signing_alg);s.append(`client_id`,n),s.append(`client_assertion_type`,`urn:ietf:params:oauth:client-assertion-type:jwt-bearer`),s.append(`client_assertion`,e);break}}o.debug(`got token endpoint`);let u=await this._jsonService.postForm(l,{body:s,basicAuth:c,timeoutInSeconds:this._settings.requestTimeoutInSeconds,initCredentials:this._settings.fetchRequestCredentials,extraHeaders:i});return o.debug(`got response`),u}async exchangeCredentials({grant_type:e=`password`,client_id:t=this._settings.client_id,client_secret:n=this._settings.client_secret,scope:r=this._settings.scope,...i}){let a=this._logger.create(`exchangeCredentials`);t||a.throw(Error(`A client_id is required`));let o=new URLSearchParams({grant_type:e});this._settings.omitScopeWhenRequesting||o.set(`scope`,r);for(let[e,t]of Object.entries(i))t!=null&&o.set(e,t);if((this._settings.client_authentication===`client_secret_basic`||this._settings.client_authentication===`client_secret_jwt`)&&n==null)throw a.throw(Error(`A client_secret is required`)),null;let s,c=await this._metadataService.getTokenEndpoint(!1);switch(this._settings.client_authentication){case`client_secret_basic`:s=kx.generateBasicAuth(t,n);break;case`client_secret_post`:o.append(`client_id`,t),n&&o.append(`client_secret`,n);break;case`client_secret_jwt`:{let e=await kx.generateClientAssertionJwt(t,n,c,this._settings.token_endpoint_auth_signing_alg);o.append(`client_id`,t),o.append(`client_assertion_type`,`urn:ietf:params:oauth:client-assertion-type:jwt-bearer`),o.append(`client_assertion`,e);break}}a.debug(`got token endpoint`);let l=await this._jsonService.postForm(c,{body:o,basicAuth:s,timeoutInSeconds:this._settings.requestTimeoutInSeconds,initCredentials:this._settings.fetchRequestCredentials});return a.debug(`got response`),l}async exchangeRefreshToken({grant_type:e=`refresh_token`,client_id:t=this._settings.client_id,client_secret:n=this._settings.client_secret,timeoutInSeconds:r,extraHeaders:i,...a}){let o=this._logger.create(`exchangeRefreshToken`);t||o.throw(Error(`A client_id is required`)),a.refresh_token||o.throw(Error(`A refresh_token is required`));let s=new URLSearchParams({grant_type:e});for(let[e,t]of Object.entries(a))Array.isArray(t)?t.forEach(t=>s.append(e,t)):t!=null&&s.set(e,t);if((this._settings.client_authentication===`client_secret_basic`||this._settings.client_authentication===`client_secret_jwt`)&&n==null)throw o.throw(Error(`A client_secret is required`)),null;let c,l=await this._metadataService.getTokenEndpoint(!1);switch(this._settings.client_authentication){case`client_secret_basic`:c=kx.generateBasicAuth(t,n);break;case`client_secret_post`:s.append(`client_id`,t),n&&s.append(`client_secret`,n);break;case`client_secret_jwt`:{let e=await kx.generateClientAssertionJwt(t,n,l,this._settings.token_endpoint_auth_signing_alg);s.append(`client_id`,t),s.append(`client_assertion_type`,`urn:ietf:params:oauth:client-assertion-type:jwt-bearer`),s.append(`client_assertion`,e);break}}o.debug(`got token endpoint`);let u=await this._jsonService.postForm(l,{body:s,basicAuth:c,timeoutInSeconds:r,initCredentials:this._settings.fetchRequestCredentials,extraHeaders:i});return o.debug(`got response`),u}async revoke(e){let t=this._logger.create(`revoke`);e.token||t.throw(Error(`A token is required`));let n=await this._metadataService.getRevocationEndpoint(!1);t.debug(`got revocation endpoint, revoking ${e.token_type_hint??`default token type`}`);let r=new URLSearchParams;for(let[t,n]of Object.entries(e))n!=null&&r.set(t,n);r.set(`client_id`,this._settings.client_id),this._settings.client_secret&&r.set(`client_secret`,this._settings.client_secret),await this._jsonService.postForm(n,{body:r,timeoutInSeconds:this._settings.requestTimeoutInSeconds}),t.debug(`got response`)}},Zx=class{constructor(e,t,n){this._settings=e,this._metadataService=t,this._claimsService=n,this._logger=new wx(`ResponseValidator`),this._userInfoService=new Yx(this._settings,this._metadataService),this._tokenClient=new Xx(this._settings,this._metadataService)}async validateSigninResponse(e,t,n){let r=this._logger.create(`validateSigninResponse`);this._processSigninState(e,t),r.debug(`state processed`),await this._processCode(e,t,n),r.debug(`code processed`),e.isOpenId&&this._validateIdTokenAttributes(e),r.debug(`tokens validated`),await this._processClaims(e,t?.skipUserInfo,e.isOpenId),r.debug(`claims processed`)}async validateCredentialsResponse(e,t){let n=this._logger.create(`validateCredentialsResponse`),r=e.isOpenId&&!!e.id_token;r&&this._validateIdTokenAttributes(e),n.debug(`tokens validated`),await this._processClaims(e,t,r),n.debug(`claims processed`)}async validateRefreshResponse(e,t){let n=this._logger.create(`validateRefreshResponse`);e.userState=t.data,e.session_state??=t.session_state,e.scope??=t.scope,e.isOpenId&&e.id_token&&(this._validateIdTokenAttributes(e,t.id_token),n.debug(`ID Token validated`)),e.id_token||(e.id_token=t.id_token,e.profile=t.profile);let r=e.isOpenId&&!!e.id_token;await this._processClaims(e,!1,r),n.debug(`claims processed`)}validateSignoutResponse(e,t){let n=this._logger.create(`validateSignoutResponse`);if(t.id!==e.state&&n.throw(Error(`State does not match`)),n.debug(`state validated`),e.userState=t.data,e.error)throw n.warn(`Response was error`,e.error),new Fx(e)}_processSigninState(e,t){let n=this._logger.create(`_processSigninState`);if(t.id!==e.state&&n.throw(Error(`State does not match`)),t.client_id||n.throw(Error(`No client_id on state`)),t.authority||n.throw(Error(`No authority on state`)),this._settings.authority!==t.authority&&n.throw(Error(`authority mismatch on settings vs. signin state`)),this._settings.client_id&&this._settings.client_id!==t.client_id&&n.throw(Error(`client_id mismatch on settings vs. signin state`)),n.debug(`state validated`),e.userState=t.data,e.url_state=t.url_state,e.scope??=t.scope,e.error)throw n.warn(`Response was error`,e.error),new Fx(e);t.code_verifier&&!e.code&&n.throw(Error(`Expected code in response`))}async _processClaims(e,t=!1,n=!0){let r=this._logger.create(`_processClaims`);if(e.profile=this._claimsService.filterProtocolClaims(e.profile),t||!this._settings.loadUserInfo||!e.access_token){r.debug(`not loading user info`);return}r.debug(`loading user info`);let i=await this._userInfoService.getClaims(e.access_token);r.debug(`user info claims received from user info endpoint`),n&&i.sub!==e.profile.sub&&r.throw(Error(`subject from UserInfo response does not match subject in ID Token`)),e.profile=this._claimsService.mergeClaims(e.profile,this._claimsService.filterProtocolClaims(i)),r.debug(`user info claims received, updated profile:`,e.profile)}async _processCode(e,t,n){let r=this._logger.create(`_processCode`);if(e.code){r.debug(`Validating code`);let i=await this._tokenClient.exchangeCode({client_id:t.client_id,client_secret:t.client_secret,code:e.code,redirect_uri:t.redirect_uri,code_verifier:t.code_verifier,extraHeaders:n,...t.extraTokenParams});Object.assign(e,i)}else r.debug(`No code to process`)}_validateIdTokenAttributes(e,t){let n=this._logger.create(`_validateIdTokenAttributes`);n.debug(`decoding ID Token JWT`);let r=Tx.decode(e.id_token??``);if(r.sub||n.throw(Error(`ID Token is missing a subject claim`)),t){let e=Tx.decode(t);r.sub!==e.sub&&n.throw(Error(`sub in id_token does not match current sub`)),r.auth_time&&r.auth_time!==e.auth_time&&n.throw(Error(`auth_time in id_token does not match original auth_time`)),r.azp&&r.azp!==e.azp&&n.throw(Error(`azp in id_token does not match original azp`)),!r.azp&&e.azp&&n.throw(Error(`azp not in id_token, but present in original id_token`))}e.profile=r}},Qx=class e{constructor(e){this.id=e.id||kx.generateUUIDv4(),this.data=e.data,e.created&&e.created>0?this.created=e.created:this.created=Mx.getEpochTime(),this.request_type=e.request_type,this.url_state=e.url_state}toStorageString(){return new wx(`State`).create(`toStorageString`),JSON.stringify({id:this.id,data:this.data,created:this.created,request_type:this.request_type,url_state:this.url_state})}static fromStorageString(t){return wx.createStatic(`State`,`fromStorageString`),Promise.resolve(new e(JSON.parse(t)))}static async clearStaleState(t,n){let r=wx.createStatic(`State`,`clearStaleState`),i=Mx.getEpochTime()-n,a=await t.getAllKeys();r.debug(`got keys`,a);for(let n=0;nS.searchParams.append(`resource`,e));for(let[e,t]of Object.entries({response_mode:c,...b,...h}))t!=null&&S.searchParams.append(e,t.toString());return new e({url:S.href,state:x})}};eS._logger=new wx(`SigninRequest`);var tS=eS,nS=`openid`,rS=class{constructor(e){if(this.access_token=``,this.token_type=``,this.profile={},this.state=e.get(`state`),this.session_state=e.get(`session_state`),this.state){let e=decodeURIComponent(this.state).split(Px);this.state=e[0],e.length>1&&(this.url_state=e.slice(1).join(Px))}this.error=e.get(`error`),this.error_description=e.get(`error_description`),this.error_uri=e.get(`error_uri`),this.code=e.get(`code`)}get expires_in(){if(this.expires_at!==void 0)return this.expires_at-Mx.getEpochTime()}set expires_in(e){typeof e==`string`&&(e=Number(e)),e!==void 0&&e>=0&&(this.expires_at=Math.floor(e)+Mx.getEpochTime())}get isOpenId(){return this.scope?.split(` `).includes(nS)||!!this.id_token}},iS=class{constructor({url:e,state_data:t,id_token_hint:n,post_logout_redirect_uri:r,extraQueryParams:i,request_type:a,client_id:o,url_state:s}){if(this._logger=new wx(`SignoutRequest`),!e)throw this._logger.error(`ctor: No url passed`),Error(`url`);let c=new URL(e);if(n&&c.searchParams.append(`id_token_hint`,n),o&&c.searchParams.append(`client_id`,o),r&&(c.searchParams.append(`post_logout_redirect_uri`,r),t||s)){this.state=new Qx({data:t,request_type:a,url_state:s});let e=this.state.id;s&&(e=`${e}${Px}${s}`),c.searchParams.append(`state`,e)}for(let[e,t]of Object.entries({...i}))t!=null&&c.searchParams.append(e,t.toString());this.url=c.href}},aS=class{constructor(e){if(this.state=e.get(`state`),this.state){let e=decodeURIComponent(this.state).split(Px);this.state=e[0],e.length>1&&(this.url_state=e.slice(1).join(Px))}this.error=e.get(`error`),this.error_description=e.get(`error_description`),this.error_uri=e.get(`error_uri`)}},oS=[`nbf`,`jti`,`auth_time`,`nonce`,`acr`,`amr`,`azp`,`at_hash`],sS=[`sub`,`iss`,`aud`,`exp`,`iat`],cS=class{constructor(e){this._settings=e,this._logger=new wx(`ClaimsService`)}filterProtocolClaims(e){let t={...e};if(this._settings.filterProtocolClaims){let e;e=Array.isArray(this._settings.filterProtocolClaims)?this._settings.filterProtocolClaims:oS;for(let n of e)sS.includes(n)||delete t[n]}return t}mergeClaims(e,t){let n={...e};for(let[e,r]of Object.entries(t))if(n[e]!==r)if(Array.isArray(n[e])||Array.isArray(r))if(this._settings.mergeClaimsStrategy.array==`replace`)n[e]=r;else{let t=Array.isArray(n[e])?n[e]:[n[e]];for(let e of Array.isArray(r)?r:[r])t.includes(e)||t.push(e);n[e]=t}else typeof n[e]==`object`&&typeof r==`object`?n[e]=this.mergeClaims(n[e],r):n[e]=r;return n}},lS=class{constructor(e,t){this.keys=e,this.nonce=t}},uS=class{constructor(e,t){this._logger=new wx(`OidcClient`),this.settings=e instanceof Jx?e:new Jx(e),this.metadataService=t??new Hx(this.settings),this._claimsService=new cS(this.settings),this._validator=new Zx(this.settings,this.metadataService,this._claimsService),this._tokenClient=new Xx(this.settings,this.metadataService)}async createSigninRequest({state:e,request:t,request_uri:n,request_type:r,id_token_hint:i,login_hint:a,skipUserInfo:o,nonce:s,url_state:c,response_type:l=this.settings.response_type,scope:u=this.settings.scope,redirect_uri:d=this.settings.redirect_uri,prompt:f=this.settings.prompt,display:p=this.settings.display,max_age:m=this.settings.max_age,ui_locales:h=this.settings.ui_locales,acr_values:g=this.settings.acr_values,resource:_=this.settings.resource,response_mode:v=this.settings.response_mode,extraQueryParams:y=this.settings.extraQueryParams,extraTokenParams:b=this.settings.extraTokenParams,dpopJkt:x,omitScopeWhenRequesting:S=this.settings.omitScopeWhenRequesting}){let C=this._logger.create(`createSigninRequest`);if(l!==`code`)throw Error(`Only the Authorization Code flow (with PKCE) is supported`);let w=await this.metadataService.getAuthorizationEndpoint();C.debug(`Received authorization endpoint`,w);let T=await tS.create({url:w,authority:this.settings.authority,client_id:this.settings.client_id,redirect_uri:d,response_type:l,scope:u,state_data:e,url_state:c,prompt:f,display:p,max_age:m,ui_locales:h,id_token_hint:i,login_hint:a,acr_values:g,dpopJkt:x,resource:_,request:t,request_uri:n,extraQueryParams:y,extraTokenParams:b,request_type:r,response_mode:v,client_secret:this.settings.client_secret,skipUserInfo:o,nonce:s,disablePKCE:this.settings.disablePKCE,omitScopeWhenRequesting:S});await this.clearStaleState();let E=T.state;return await this.settings.stateStore.set(E.id,E.toStorageString()),T}async readSigninResponseState(e,t=!1){let n=this._logger.create(`readSigninResponseState`),r=new rS(Nx.readParams(e,this.settings.response_mode));if(!r.state)throw n.throw(Error(`No state in response`)),null;let i=await this.settings.stateStore[t?`remove`:`get`](r.state);if(!i)throw n.throw(Error(`No matching state found in storage`)),null;return{state:await $x.fromStorageString(i),response:r}}async processSigninResponse(e,t,n=!0){let r=this._logger.create(`processSigninResponse`),{state:i,response:a}=await this.readSigninResponseState(e,n);if(r.debug(`received state from storage; validating response`),this.settings.dpop&&this.settings.dpop.store){let e=await this.getDpopProof(this.settings.dpop.store);t={...t,DPoP:e}}try{await this._validator.validateSigninResponse(a,i,t)}catch(e){if(e instanceof Bx&&this.settings.dpop){let n=await this.getDpopProof(this.settings.dpop.store,e.nonce);t.DPoP=n,await this._validator.validateSigninResponse(a,i,t)}else throw e}return a}async getDpopProof(e,t){let n,r;return(await e.getAllKeys()).includes(this.settings.client_id)?(r=await e.get(this.settings.client_id),r.nonce!==t&&t&&(r.nonce=t,await e.set(this.settings.client_id,r))):(n=await kx.generateDPoPKeys(),r=new lS(n,t),await e.set(this.settings.client_id,r)),await kx.generateDPoPProof({url:await this.metadataService.getTokenEndpoint(!1),httpMethod:`POST`,keyPair:r.keys,nonce:r.nonce})}async processResourceOwnerPasswordCredentials({username:e,password:t,skipUserInfo:n=!1,extraTokenParams:r={}}){let i=await this._tokenClient.exchangeCredentials({username:e,password:t,...r}),a=new rS(new URLSearchParams);return Object.assign(a,i),await this._validator.validateCredentialsResponse(a,n),a}async useRefreshToken({state:e,redirect_uri:t,resource:n,timeoutInSeconds:r,extraHeaders:i,extraTokenParams:a}){let o=this._logger.create(`useRefreshToken`),s;if(this.settings.refreshTokenAllowedScope===void 0)s=e.scope;else{let t=this.settings.refreshTokenAllowedScope.split(` `);s=(e.scope?.split(` `)||[]).filter(e=>t.includes(e)).join(` `)}if(this.settings.dpop&&this.settings.dpop.store){let e=await this.getDpopProof(this.settings.dpop.store);i={...i,DPoP:e}}let c;try{c=await this._tokenClient.exchangeRefreshToken({refresh_token:e.refresh_token,scope:s,redirect_uri:t,resource:n,timeoutInSeconds:r,extraHeaders:i,...a})}catch(o){if(o instanceof Bx&&this.settings.dpop)i.DPoP=await this.getDpopProof(this.settings.dpop.store,o.nonce),c=await this._tokenClient.exchangeRefreshToken({refresh_token:e.refresh_token,scope:s,redirect_uri:t,resource:n,timeoutInSeconds:r,extraHeaders:i,...a});else throw o}let l=new rS(new URLSearchParams);return Object.assign(l,c),o.debug(`validating response`,l),await this._validator.validateRefreshResponse(l,{...e,scope:s}),l}async createSignoutRequest({state:e,id_token_hint:t,client_id:n,request_type:r,url_state:i,post_logout_redirect_uri:a=this.settings.post_logout_redirect_uri,extraQueryParams:o=this.settings.extraQueryParams}={}){let s=this._logger.create(`createSignoutRequest`),c=await this.metadataService.getEndSessionEndpoint();if(!c)throw s.throw(Error(`No end session endpoint`)),null;s.debug(`Received end session endpoint`,c),!n&&a&&!t&&(n=this.settings.client_id);let l=new iS({url:c,id_token_hint:t,client_id:n,post_logout_redirect_uri:a,state_data:e,extraQueryParams:o,request_type:r,url_state:i});await this.clearStaleState();let u=l.state;return u&&(s.debug(`Signout request has state to persist`),await this.settings.stateStore.set(u.id,u.toStorageString())),l}async readSignoutResponseState(e,t=!1){let n=this._logger.create(`readSignoutResponseState`),r=new aS(Nx.readParams(e,this.settings.response_mode));if(!r.state){if(n.debug(`No state in response`),r.error)throw n.warn(`Response was error:`,r.error),new Fx(r);return{state:void 0,response:r}}let i=await this.settings.stateStore[t?`remove`:`get`](r.state);if(!i)throw n.throw(Error(`No matching state found in storage`)),null;return{state:await Qx.fromStorageString(i),response:r}}async processSignoutResponse(e){let t=this._logger.create(`processSignoutResponse`),{state:n,response:r}=await this.readSignoutResponseState(e,!0);return n?(t.debug(`Received state from storage; validating response`),this._validator.validateSignoutResponse(r,n)):t.debug(`No state from storage; skipping response validation`),r}clearStaleState(){return this._logger.create(`clearStaleState`),Qx.clearStaleState(this.settings.stateStore,this.settings.staleStateAgeInSeconds)}async revokeToken(e,t){return this._logger.create(`revokeToken`),await this._tokenClient.revoke({token:e,token_type_hint:t})}},dS=class{constructor(e){this._userManager=e,this._logger=new wx(`SessionMonitor`),this._start=async e=>{let t=e.session_state;if(!t)return;let n=this._logger.create(`_start`);if(e.profile?(this._sub=e.profile.sub,n.debug(`session_state`,t,`, sub`,this._sub)):(this._sub=void 0,n.debug(`session_state`,t,`, anonymous user`)),this._checkSessionIFrame){this._checkSessionIFrame.start(t);return}try{let e=await this._userManager.metadataService.getCheckSessionIframe();if(e){n.debug(`initializing check session iframe`);let r=this._userManager.settings.client_id,i=this._userManager.settings.checkSessionIntervalInSeconds,a=this._userManager.settings.stopCheckSessionOnError,o=new Rx(this._callback,r,e,i,a);await o.load(),this._checkSessionIFrame=o,o.start(t)}else n.warn(`no check session iframe found in the metadata`)}catch(e){n.error(`Error from getCheckSessionIframe:`,e instanceof Error?e.message:e)}},this._stop=()=>{let e=this._logger.create(`_stop`);if(this._sub=void 0,this._checkSessionIFrame&&this._checkSessionIFrame.stop(),this._userManager.settings.monitorAnonymousSession){let t=setInterval(async()=>{clearInterval(t);try{let e=await this._userManager.querySessionStatus();if(e){let t={session_state:e.session_state,profile:e.sub?{sub:e.sub}:null};this._start(t)}}catch(t){e.error(`error from querySessionStatus`,t instanceof Error?t.message:t)}},1e3)}},this._callback=async()=>{let e=this._logger.create(`_callback`);try{let t=await this._userManager.querySessionStatus(),n=!0;t&&this._checkSessionIFrame?t.sub===this._sub?(n=!1,this._checkSessionIFrame.start(t.session_state),e.debug(`same sub still logged in at OP, session state has changed, restarting check session iframe; session_state`,t.session_state),await this._userManager.events._raiseUserSessionChanged()):e.debug(`different subject signed into OP`,t.sub):e.debug(`subject no longer signed into OP`),n?this._sub?await this._userManager.events._raiseUserSignedOut():await this._userManager.events._raiseUserSignedIn():e.debug(`no change in session detected, no event to raise`)}catch(t){this._sub&&(e.debug(`Error calling queryCurrentSigninSession; raising signed out event`,t),await this._userManager.events._raiseUserSignedOut())}},e||this._logger.throw(Error(`No user manager passed`)),this._userManager.events.addUserLoaded(this._start),this._userManager.events.addUserUnloaded(this._stop),this._init().catch(e=>{this._logger.error(e)})}async _init(){this._logger.create(`_init`);let e=await this._userManager.getUser();if(e)this._start(e);else if(this._userManager.settings.monitorAnonymousSession){let e=await this._userManager.querySessionStatus();if(e){let t={session_state:e.session_state,profile:e.sub?{sub:e.sub}:null};this._start(t)}}}},fS=class e{constructor(e){this.id_token=e.id_token,this.session_state=e.session_state??null,this.access_token=e.access_token,this.refresh_token=e.refresh_token,this.token_type=e.token_type,this.scope=e.scope,this.profile=e.profile,this.expires_at=e.expires_at,this.state=e.userState,this.url_state=e.url_state}get expires_in(){if(this.expires_at!==void 0)return this.expires_at-Mx.getEpochTime()}set expires_in(e){e!==void 0&&(this.expires_at=Math.floor(e)+Mx.getEpochTime())}get expired(){let e=this.expires_in;if(e!==void 0)return e<=0}get scopes(){return this.scope?.split(` `)??[]}toStorageString(){return new wx(`User`).create(`toStorageString`),JSON.stringify({id_token:this.id_token,session_state:this.session_state,access_token:this.access_token,refresh_token:this.refresh_token,token_type:this.token_type,scope:this.scope,profile:this.profile,expires_at:this.expires_at})}static fromStorageString(t){return wx.createStatic(`User`,`fromStorageString`),new e(JSON.parse(t))}},pS=`oidc-client`,mS=class{constructor(){this._abort=new Ax(`Window navigation aborted`),this._disposeHandlers=new Set,this._window=null}async navigate(e){let t=this._logger.create(`navigate`);if(!this._window)throw Error(`Attempted to navigate on a disposed window`);t.debug(`setting URL in window`),this._window.location.replace(e.url);let{url:n,keepOpen:r}=await new Promise((n,r)=>{let i=i=>{let a=i.data,o=e.scriptOrigin??window.location.origin;if(!(i.origin!==o||a?.source!==pS)){try{let n=Nx.readParams(a.url,e.response_mode).get(`state`);if(n||t.warn(`no state found in response url`),i.source!==this._window&&n!==e.state)return}catch{this._dispose(),r(Error(`Invalid response from window`))}n(a)}};window.addEventListener(`message`,i,!1),this._disposeHandlers.add(()=>window.removeEventListener(`message`,i,!1));let a=new BroadcastChannel(`oidc-client-popup-${e.state}`);a.addEventListener(`message`,i,!1),this._disposeHandlers.add(()=>a.close()),this._disposeHandlers.add(this._abort.addHandler(e=>{this._dispose(),r(e)}))});return t.debug(`got response from window`),this._dispose(),r||this.close(),{url:n}}_dispose(){this._logger.create(`_dispose`);for(let e of this._disposeHandlers)e();this._disposeHandlers.clear()}static _notifyParent(e,t,n=!1,r=window.location.origin){let i={source:pS,url:t,keepOpen:n},a=new wx(`_notifyParent`);if(e)a.debug(`With parent. Using parent.postMessage.`),e.postMessage(i,r);else{a.debug(`No parent. Using BroadcastChannel.`);let e=new URL(t).searchParams.get(`state`);if(!e)throw Error(`No parent and no state in URL. Can't complete notification.`);let n=new BroadcastChannel(`oidc-client-popup-${e}`);n.postMessage(i),n.close()}}},hS={location:!1,toolbar:!1,height:640,closePopupWindowAfterInSeconds:-1},gS=`_blank`,_S=60,vS=2,yS=10,bS=class extends Jx{constructor(e){let{popup_redirect_uri:t=e.redirect_uri,popup_post_logout_redirect_uri:n=e.post_logout_redirect_uri,popupWindowFeatures:r=hS,popupWindowTarget:i=gS,redirectMethod:a=`assign`,redirectTarget:o=`self`,iframeNotifyParentOrigin:s=e.iframeNotifyParentOrigin,iframeScriptOrigin:c=e.iframeScriptOrigin,requestTimeoutInSeconds:l,silent_redirect_uri:u=e.redirect_uri,silentRequestTimeoutInSeconds:d,automaticSilentRenew:f=!0,validateSubOnSilentRenew:p=!0,includeIdTokenInSilentRenew:m=!1,monitorSession:h=!1,monitorAnonymousSession:g=!1,checkSessionIntervalInSeconds:_=vS,query_status_response_type:v=`code`,stopCheckSessionOnError:y=!0,revokeTokenTypes:b=[`access_token`,`refresh_token`],revokeTokensOnSignout:x=!1,includeIdTokenInSilentSignout:S=!1,accessTokenExpiringNotificationTimeInSeconds:C=_S,userStore:w}=e;super(e),this.popup_redirect_uri=t,this.popup_post_logout_redirect_uri=n,this.popupWindowFeatures=r,this.popupWindowTarget=i,this.redirectMethod=a,this.redirectTarget=o,this.iframeNotifyParentOrigin=s,this.iframeScriptOrigin=c,this.silent_redirect_uri=u,this.silentRequestTimeoutInSeconds=d||l||yS,this.automaticSilentRenew=f,this.validateSubOnSilentRenew=p,this.includeIdTokenInSilentRenew=m,this.monitorSession=h,this.monitorAnonymousSession=g,this.checkSessionIntervalInSeconds=_,this.stopCheckSessionOnError=y,this.query_status_response_type=v,this.revokeTokenTypes=b,this.revokeTokensOnSignout=x,this.includeIdTokenInSilentSignout=S,this.accessTokenExpiringNotificationTimeInSeconds=C,w?this.userStore=w:this.userStore=new Ux({store:typeof window<`u`?window.sessionStorage:new zx})}},xS=class e extends mS{constructor({silentRequestTimeoutInSeconds:t=yS}){super(),this._logger=new wx(`IFrameWindow`),this._timeoutInSeconds=t,this._frame=e.createHiddenIframe(),this._window=this._frame.contentWindow}static createHiddenIframe(){let e=window.document.createElement(`iframe`);return e.style.visibility=`hidden`,e.style.position=`fixed`,e.style.left=`-1000px`,e.style.top=`0`,e.width=`0`,e.height=`0`,window.document.body.appendChild(e),e}async navigate(e){this._logger.debug(`navigate: Using timeout of:`,this._timeoutInSeconds);let t=setTimeout(()=>void this._abort.raise(new Ix(`IFrame timed out without a response`)),this._timeoutInSeconds*1e3);return this._disposeHandlers.add(()=>clearTimeout(t)),await super.navigate(e)}close(){var e;this._frame&&=(this._frame.parentNode&&(this._frame.addEventListener(`load`,e=>{var t;let n=e.target;(t=n.parentNode)==null||t.removeChild(n),this._abort.raise(Error(`IFrame removed from DOM`))},!0),(e=this._frame.contentWindow)==null||e.location.replace(`about:blank`)),null),this._window=null}static notifyParent(e,t){return super._notifyParent(window.parent,e,!1,t)}},SS=class{constructor(e){this._settings=e,this._logger=new wx(`IFrameNavigator`)}async prepare({silentRequestTimeoutInSeconds:e=this._settings.silentRequestTimeoutInSeconds}){return new xS({silentRequestTimeoutInSeconds:e})}async callback(e){this._logger.create(`callback`),xS.notifyParent(e,this._settings.iframeNotifyParentOrigin)}},CS=500,wS=1e3,TS=class extends mS{constructor({popupWindowTarget:e=gS,popupWindowFeatures:t={},popupSignal:n,popupAbortOnClose:r}){super(),this._logger=new wx(`PopupWindow`);let i=jx.center({...hS,...t});this._window=window.open(void 0,e,jx.serialize(i)),this.abortOnClose=!!r,n&&n.addEventListener(`abort`,()=>{this._abort.raise(Error(n.reason??`Popup aborted`))}),t.closePopupWindowAfterInSeconds&&t.closePopupWindowAfterInSeconds>0&&setTimeout(()=>{if(!this._window||typeof this._window.closed!=`boolean`||this._window.closed){this._abort.raise(Error(`Popup blocked by user`));return}this.close()},t.closePopupWindowAfterInSeconds*wS)}async navigate(e){var t;(t=this._window)==null||t.focus();let n=setInterval(()=>{(!this._window||this._window.closed)&&(this._logger.debug(`Popup closed by user or isolated by redirect`),r(),this._disposeHandlers.delete(r),this.abortOnClose&&this._abort.raise(Error(`Popup closed by user`)))},CS),r=()=>clearInterval(n);return this._disposeHandlers.add(r),await super.navigate(e)}close(){this._window&&(this._window.closed||(this._window.close(),this._abort.raise(Error(`Popup closed`)))),this._window=null}static notifyOpener(e,t){super._notifyParent(window.opener,e,t),!t&&!window.opener&&window.close()}},ES=class{constructor(e){this._settings=e,this._logger=new wx(`PopupNavigator`)}async prepare({popupWindowFeatures:e=this._settings.popupWindowFeatures,popupWindowTarget:t=this._settings.popupWindowTarget,popupSignal:n,popupAbortOnClose:r}){return new TS({popupWindowFeatures:e,popupWindowTarget:t,popupSignal:n,popupAbortOnClose:r})}async callback(e,{keepOpen:t=!1}){this._logger.create(`callback`),TS.notifyOpener(e,t)}},DS=class{constructor(e){this._settings=e,this._logger=new wx(`RedirectNavigator`)}async prepare({redirectMethod:e=this._settings.redirectMethod,redirectTarget:t=this._settings.redirectTarget}){this._logger.create(`prepare`);let n=window.self;t===`top`&&(n=window.top??window.self);let r=n.location[e].bind(n.location),i;return{navigate:async e=>(this._logger.create(`navigate`),await new Promise((t,n)=>{i=n,window.addEventListener(`pageshow`,()=>t(window.location.href)),r(e.url)})),close:()=>{this._logger.create(`close`),i?.(Error(`Redirect aborted`)),n.stop()}}}async callback(){}},OS=class extends Lx{constructor(e){super({expiringNotificationTimeInSeconds:e.accessTokenExpiringNotificationTimeInSeconds}),this._logger=new wx(`UserManagerEvents`),this._userLoaded=new Ax(`User loaded`),this._userUnloaded=new Ax(`User unloaded`),this._silentRenewError=new Ax(`Silent renew error`),this._userSignedIn=new Ax(`User signed in`),this._userSignedOut=new Ax(`User signed out`),this._userSessionChanged=new Ax(`User session changed`)}async load(e,t=!0){await super.load(e),t&&await this._userLoaded.raise(e)}async unload(){await super.unload(),await this._userUnloaded.raise()}addUserLoaded(e){return this._userLoaded.addHandler(e)}removeUserLoaded(e){return this._userLoaded.removeHandler(e)}addUserUnloaded(e){return this._userUnloaded.addHandler(e)}removeUserUnloaded(e){return this._userUnloaded.removeHandler(e)}addSilentRenewError(e){return this._silentRenewError.addHandler(e)}removeSilentRenewError(e){return this._silentRenewError.removeHandler(e)}async _raiseSilentRenewError(e){await this._silentRenewError.raise(e)}addUserSignedIn(e){return this._userSignedIn.addHandler(e)}removeUserSignedIn(e){this._userSignedIn.removeHandler(e)}async _raiseUserSignedIn(){await this._userSignedIn.raise()}addUserSignedOut(e){return this._userSignedOut.addHandler(e)}removeUserSignedOut(e){this._userSignedOut.removeHandler(e)}async _raiseUserSignedOut(){await this._userSignedOut.raise()}addUserSessionChanged(e){return this._userSessionChanged.addHandler(e)}removeUserSessionChanged(e){this._userSessionChanged.removeHandler(e)}async _raiseUserSessionChanged(){await this._userSessionChanged.raise()}},kS=class{constructor(e){this._userManager=e,this._logger=new wx(`SilentRenewService`),this._isStarted=!1,this._retryTimer=new Mx(`Retry Silent Renew`),this._tokenExpiring=async()=>{let e=this._logger.create(`_tokenExpiring`);try{await this._userManager.signinSilent(),e.debug(`silent token renewal successful`)}catch(t){if(t instanceof Ix){e.warn(`ErrorTimeout from signinSilent:`,t,`retry in 5s`),this._retryTimer.init(5);return}e.error(`Error from signinSilent:`,t),await this._userManager.events._raiseSilentRenewError(t)}}}async start(){let e=this._logger.create(`start`);if(!this._isStarted){this._isStarted=!0,this._userManager.events.addAccessTokenExpiring(this._tokenExpiring),this._retryTimer.addHandler(this._tokenExpiring);try{await this._userManager.getUser()}catch(t){e.error(`getUser error`,t)}}}stop(){this._isStarted&&=(this._retryTimer.cancel(),this._retryTimer.removeHandler(this._tokenExpiring),this._userManager.events.removeAccessTokenExpiring(this._tokenExpiring),!1)}},AS=class{constructor(e){this.refresh_token=e.refresh_token,this.id_token=e.id_token,this.session_state=e.session_state,this.scope=e.scope,this.profile=e.profile,this.data=e.state}},jS=class{constructor(e,t,n,r){this._logger=new wx(`UserManager`),this.settings=new bS(e),this._client=new uS(e),this._redirectNavigator=t??new DS(this.settings),this._popupNavigator=n??new ES(this.settings),this._iframeNavigator=r??new SS(this.settings),this._events=new OS(this.settings),this._silentRenewService=new kS(this),this.settings.automaticSilentRenew&&this.startSilentRenew(),this._sessionMonitor=null,this.settings.monitorSession&&(this._sessionMonitor=new dS(this))}get events(){return this._events}get metadataService(){return this._client.metadataService}async getUser(e=!1){let t=this._logger.create(`getUser`),n=await this._loadUser();return n?(t.info(`user loaded`),await this._events.load(n,e),n):(t.info(`user not found in storage`),null)}async removeUser(){let e=this._logger.create(`removeUser`);await this.storeUser(null),e.info(`user removed from storage`),await this._events.unload()}async signinRedirect(e={}){this._logger.create(`signinRedirect`);let{redirectMethod:t,...n}=e,r;this.settings.dpop?.bind_authorization_code&&(r=await this.generateDPoPJkt(this.settings.dpop));let i=await this._redirectNavigator.prepare({redirectMethod:t});await this._signinStart({request_type:`si:r`,dpopJkt:r,...n},i)}async signinRedirectCallback(e=window.location.href){let t=this._logger.create(`signinRedirectCallback`),n=await this._signinEnd(e);return n.profile&&n.profile.sub?t.info(`success, signed in subject`,n.profile.sub):t.info(`no subject`),n}async signinResourceOwnerCredentials({username:e,password:t,skipUserInfo:n=!1}){let r=this._logger.create(`signinResourceOwnerCredential`),i=await this._client.processResourceOwnerPasswordCredentials({username:e,password:t,skipUserInfo:n,extraTokenParams:this.settings.extraTokenParams});r.debug(`got signin response`);let a=await this._buildUser(i);return a.profile&&a.profile.sub?r.info(`success, signed in subject`,a.profile.sub):r.info(`no subject`),a}async signinPopup(e={}){let t=this._logger.create(`signinPopup`),n;this.settings.dpop?.bind_authorization_code&&(n=await this.generateDPoPJkt(this.settings.dpop));let{popupWindowFeatures:r,popupWindowTarget:i,popupSignal:a,popupAbortOnClose:o,...s}=e,c=this.settings.popup_redirect_uri;c||t.throw(Error(`No popup_redirect_uri configured`));let l=await this._popupNavigator.prepare({popupWindowFeatures:r,popupWindowTarget:i,popupSignal:a,popupAbortOnClose:o}),u=await this._signin({request_type:`si:p`,redirect_uri:c,display:`popup`,dpopJkt:n,...s},l);return u&&(u.profile&&u.profile.sub?t.info(`success, signed in subject`,u.profile.sub):t.info(`no subject`)),u}async signinPopupCallback(e=window.location.href,t=!1){let n=this._logger.create(`signinPopupCallback`);await this._popupNavigator.callback(e,{keepOpen:t}),n.info(`success`)}async signinSilent(e={}){let t=this._logger.create(`signinSilent`),{silentRequestTimeoutInSeconds:n,...r}=e,i=await this._loadUser();if(!e.forceIframeAuth&&i?.refresh_token){t.debug(`using refresh token`);let e=new AS(i);return await this._useRefreshToken({state:e,redirect_uri:r.redirect_uri,resource:r.resource,extraTokenParams:r.extraTokenParams,timeoutInSeconds:n})}let a;this.settings.dpop?.bind_authorization_code&&(a=await this.generateDPoPJkt(this.settings.dpop));let o=this.settings.silent_redirect_uri;o||t.throw(Error(`No silent_redirect_uri configured`));let s;i&&this.settings.validateSubOnSilentRenew&&(t.debug(`subject prior to silent renew:`,i.profile.sub),s=i.profile.sub);let c=await this._iframeNavigator.prepare({silentRequestTimeoutInSeconds:n});return i=await this._signin({request_type:`si:s`,redirect_uri:o,prompt:`none`,id_token_hint:this.settings.includeIdTokenInSilentRenew?i?.id_token:void 0,dpopJkt:a,...r},c,s),i&&(i.profile?.sub?t.info(`success, signed in subject`,i.profile.sub):t.info(`no subject`)),i}async _useRefreshToken(e){let t=await this._client.useRefreshToken({timeoutInSeconds:this.settings.silentRequestTimeoutInSeconds,...e}),n=new fS({...e.state,...t});return await this.storeUser(n),await this._events.load(n),n}async signinSilentCallback(e=window.location.href){let t=this._logger.create(`signinSilentCallback`);await this._iframeNavigator.callback(e),t.info(`success`)}async signinCallback(e=window.location.href){let{state:t}=await this._client.readSigninResponseState(e);switch(t.request_type){case`si:r`:return await this.signinRedirectCallback(e);case`si:p`:await this.signinPopupCallback(e);break;case`si:s`:await this.signinSilentCallback(e);break;default:throw Error(`invalid response_type in state`)}}async signoutCallback(e=window.location.href,t=!1){let{state:n}=await this._client.readSignoutResponseState(e);if(n)switch(n.request_type){case`so:r`:return await this.signoutRedirectCallback(e);case`so:p`:await this.signoutPopupCallback(e,t);break;case`so:s`:await this.signoutSilentCallback(e);break;default:throw Error(`invalid response_type in state`)}}async querySessionStatus(e={}){let t=this._logger.create(`querySessionStatus`),{silentRequestTimeoutInSeconds:n,...r}=e,i=this.settings.silent_redirect_uri;i||t.throw(Error(`No silent_redirect_uri configured`));let a=await this._loadUser(),o=await this._iframeNavigator.prepare({silentRequestTimeoutInSeconds:n}),s=await this._signinStart({request_type:`si:s`,redirect_uri:i,prompt:`none`,id_token_hint:this.settings.includeIdTokenInSilentRenew?a?.id_token:void 0,response_type:this.settings.query_status_response_type,scope:`openid`,skipUserInfo:!0,...r},o);try{let e=await this._client.processSigninResponse(s.url,{});return t.debug(`got signin response`),e.session_state&&e.profile.sub?(t.info(`success for subject`,e.profile.sub),{session_state:e.session_state,sub:e.profile.sub}):(t.info(`success, user not authenticated`),null)}catch(e){if(this.settings.monitorAnonymousSession&&e instanceof Fx)switch(e.error){case`login_required`:case`consent_required`:case`interaction_required`:case`account_selection_required`:return t.info(`success for anonymous user`),{session_state:e.session_state}}throw e}}async _signin(e,t,n){let r=await this._signinStart(e,t);return await this._signinEnd(r.url,n)}async _signinStart(e,t){let n=this._logger.create(`_signinStart`);try{let r=await this._client.createSigninRequest(e);return n.debug(`got signin request`),await t.navigate({url:r.url,state:r.state.id,response_mode:r.state.response_mode,scriptOrigin:this.settings.iframeScriptOrigin})}catch(e){throw n.debug(`error after preparing navigator, closing navigator window`),t.close(),e}}async _signinEnd(e,t){let n=this._logger.create(`_signinEnd`),r=await this._client.processSigninResponse(e,{});return n.debug(`got signin response`),await this._buildUser(r,t)}async _buildUser(e,t){let n=this._logger.create(`_buildUser`),r=new fS(e);if(t){if(t!==r.profile.sub)throw n.debug(`current user does not match user returned from signin. sub from signin:`,r.profile.sub),new Fx({...e,error:`login_required`});n.debug(`current user matches user returned from signin`)}return await this.storeUser(r),n.debug(`user stored`),await this._events.load(r),r}async signoutRedirect(e={}){let t=this._logger.create(`signoutRedirect`),{redirectMethod:n,...r}=e,i=await this._redirectNavigator.prepare({redirectMethod:n});await this._signoutStart({request_type:`so:r`,post_logout_redirect_uri:this.settings.post_logout_redirect_uri,...r},i),t.info(`success`)}async signoutRedirectCallback(e=window.location.href){let t=this._logger.create(`signoutRedirectCallback`),n=await this._signoutEnd(e);return t.info(`success`),n}async signoutPopup(e={}){let t=this._logger.create(`signoutPopup`),{popupWindowFeatures:n,popupWindowTarget:r,popupSignal:i,...a}=e,o=this.settings.popup_post_logout_redirect_uri,s=await this._popupNavigator.prepare({popupWindowFeatures:n,popupWindowTarget:r,popupSignal:i});await this._signout({request_type:`so:p`,post_logout_redirect_uri:o,state:o==null?void 0:{},...a},s),t.info(`success`)}async signoutPopupCallback(e=window.location.href,t=!1){let n=this._logger.create(`signoutPopupCallback`);await this._popupNavigator.callback(e,{keepOpen:t}),n.info(`success`)}async _signout(e,t){let n=await this._signoutStart(e,t);return await this._signoutEnd(n.url)}async _signoutStart(e={},t){let n=this._logger.create(`_signoutStart`);try{let r=await this._loadUser();n.debug(`loaded current user from storage`),this.settings.revokeTokensOnSignout&&await this._revokeInternal(r);let i=e.id_token_hint||r&&r.id_token;i&&(n.debug(`setting id_token_hint in signout request`),e.id_token_hint=i),await this.removeUser(),n.debug(`user removed, creating signout request`);let a=await this._client.createSignoutRequest(e);return n.debug(`got signout request`),await t.navigate({url:a.url,state:a.state?.id,scriptOrigin:this.settings.iframeScriptOrigin})}catch(e){throw n.debug(`error after preparing navigator, closing navigator window`),t.close(),e}}async _signoutEnd(e){let t=this._logger.create(`_signoutEnd`),n=await this._client.processSignoutResponse(e);return t.debug(`got signout response`),n}async signoutSilent(e={}){let t=this._logger.create(`signoutSilent`),{silentRequestTimeoutInSeconds:n,...r}=e,i=this.settings.includeIdTokenInSilentSignout?(await this._loadUser())?.id_token:void 0,a=this.settings.popup_post_logout_redirect_uri,o=await this._iframeNavigator.prepare({silentRequestTimeoutInSeconds:n});await this._signout({request_type:`so:s`,post_logout_redirect_uri:a,id_token_hint:i,...r},o),t.info(`success`)}async signoutSilentCallback(e=window.location.href){let t=this._logger.create(`signoutSilentCallback`);await this._iframeNavigator.callback(e),t.info(`success`)}async revokeTokens(e){let t=await this._loadUser();await this._revokeInternal(t,e)}async _revokeInternal(e,t=this.settings.revokeTokenTypes){let n=this._logger.create(`_revokeInternal`);if(!e)return;let r=t.filter(t=>typeof e[t]==`string`);if(!r.length){n.debug(`no need to revoke due to no token(s)`);return}for(let t of r)await this._client.revokeToken(e[t],t),n.info(`${t} revoked successfully`),t!==`access_token`&&(e[t]=null);await this.storeUser(e),n.debug(`user stored`),await this._events.load(e)}startSilentRenew(){this._logger.create(`startSilentRenew`),this._silentRenewService.start()}stopSilentRenew(){this._silentRenewService.stop()}get _userStoreKey(){return`user:${this.settings.authority}:${this.settings.client_id}`}async _loadUser(){let e=this._logger.create(`_loadUser`),t=await this.settings.userStore.get(this._userStoreKey);return t?(e.debug(`user storageString loaded`),fS.fromStorageString(t)):(e.debug(`no user storageString`),null)}async storeUser(e){let t=this._logger.create(`storeUser`);if(e){t.debug(`storing user`);let n=e.toStorageString();await this.settings.userStore.set(this._userStoreKey,n)}else this._logger.debug(`removing user`),await this.settings.userStore.remove(this._userStoreKey),this.settings.dpop&&await this.settings.dpop.store.remove(this.settings.client_id)}async clearStaleState(){await this._client.clearStaleState()}async dpopProof(e,t,n,r){let i=await(this.settings.dpop?.store)?.get(this.settings.client_id);if(i)return await kx.generateDPoPProof({url:e,accessToken:t?.access_token,httpMethod:n,keyPair:i.keys,nonce:r})}async generateDPoPJkt(e){let t=await e.store.get(this.settings.client_id);return t||(t=new lS(await kx.generateDPoPKeys()),await e.store.set(this.settings.client_id,t)),await kx.generateDPoPJkt(t.keys)}},MS=m.createContext(void 0);MS.displayName=`AuthContext`;var NS={isLoading:!0,isAuthenticated:!1},PS=(e,t)=>{switch(t.type){case`INITIALISED`:case`USER_LOADED`:return{...e,user:t.user,isLoading:!1,isAuthenticated:t.user?!t.user.expired:!1,error:void 0};case`USER_SIGNED_OUT`:case`USER_UNLOADED`:return{...e,user:void 0,isAuthenticated:!1};case`NAVIGATOR_INIT`:return{...e,isLoading:!0,activeNavigator:t.method};case`NAVIGATOR_CLOSE`:return{...e,isLoading:!1,activeNavigator:void 0};case`ERROR`:{let n=t.error;return n.toString=()=>`${n.name}: ${n.message}`,{...e,isLoading:!1,error:n}}default:{let n=TypeError(`unknown type ${t.type}`),r={name:n.name,message:n.message,innerError:n,stack:n.stack,source:`unknown`};return r.toString=()=>`${r.name}: ${r.message}`,{...e,isLoading:!1,error:r}}}},FS=(e=window.location)=>{let t=new URLSearchParams(e.search);return!!((t.get(`code`)||t.get(`error`))&&t.get(`state`)||(t=new URLSearchParams(e.hash.replace(`#`,`?`)),(t.get(`code`)||t.get(`error`))&&t.get(`state`)))},IS=BS(`signinCallback`,`Sign-in failed`),LS=BS(`signoutCallback`,`Sign-out failed`),RS=BS(`renewSilent`,`Renew silent failed`);function zS(e,t){return{name:VS(e,`name`,()=>`Error`),message:VS(e,`message`,()=>t),stack:VS(e,`stack`,()=>Error().stack),innerError:e}}function BS(e,t){return n=>({...zS(n,t),source:e})}function VS(e,t,n){if(e&&typeof e==`object`){let n=e[t];if(typeof n==`string`)return n}return n()}var HS=[`clearStaleState`,`querySessionStatus`,`revokeTokens`,`startSilentRenew`,`stopSilentRenew`],US=[`signinPopup`,`signinSilent`,`signinRedirect`,`signinResourceOwnerCredentials`,`signoutPopup`,`signoutRedirect`,`signoutSilent`],WS=e=>()=>{throw Error(`UserManager#${e} was called from an unsupported context. If this is a server-rendered page, defer this call with useEffect() or pass a custom UserManager implementation.`)},GS=typeof window>`u`?null:jS,KS=e=>{let{children:t,onSigninCallback:n,skipSigninCallback:r,matchSignoutCallback:i,onSignoutCallback:a,onRemoveUser:o,userManager:s=null,...c}=e,[l]=m.useState(()=>s??(GS?new GS(c):{settings:c})),[u,d]=m.useReducer(PS,NS),f=m.useMemo(()=>Object.assign({settings:l.settings,events:l.events},Object.fromEntries(HS.map(e=>[e,l[e]?.bind(l)??WS(e)])),Object.fromEntries(US.map(e=>[e,l[e]?async t=>{d({type:`NAVIGATOR_INIT`,method:e});try{return await l[e](t)}catch(n){return d({type:`ERROR`,error:{...zS(n,`Unknown error while executing ${e}(...).`),source:e,args:t}}),null}finally{d({type:`NAVIGATOR_CLOSE`})}}:WS(e)]))),[l]),p=m.useRef(!1);m.useEffect(()=>{!l||p.current||(p.current=!0,(async()=>{try{let e=null;FS()&&!r&&(e=await l.signinCallback(),n&&await n(e)),e||=await l.getUser(),d({type:`INITIALISED`,user:e})}catch(e){d({type:`ERROR`,error:IS(e)})}try{if(i&&i(l.settings)){let e=await l.signoutCallback();a&&await a(e)}}catch(e){d({type:`ERROR`,error:LS(e)})}})())},[l,r,n,a,i]),m.useEffect(()=>{if(!l)return;let e=e=>{d({type:`USER_LOADED`,user:e})};l.events.addUserLoaded(e);let t=()=>{d({type:`USER_UNLOADED`})};l.events.addUserUnloaded(t);let n=()=>{d({type:`USER_SIGNED_OUT`})};l.events.addUserSignedOut(n);let r=e=>{d({type:`ERROR`,error:RS(e)})};return l.events.addSilentRenewError(r),()=>{l.events.removeUserLoaded(e),l.events.removeUserUnloaded(t),l.events.removeUserSignedOut(n),l.events.removeSilentRenewError(r)}},[l]);let h=m.useCallback(async()=>{await l.removeUser(),o&&await o()},[l,o]),g=m.useMemo(()=>({...u,...f,removeUser:h}),[u,f,h]);return m.createElement(MS.Provider,{value:g},t)},qS=()=>{let e=m.useContext(MS);return e||console.warn(`AuthProvider context is undefined, please verify you are calling useAuth() as child of a component.`),e},JS=`modulepreload`,YS=function(e){return`/`+e},XS={},ZS=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}r=o(t.map(t=>{if(t=YS(t,n),t in XS)return;XS[t]=!0;let r=t.endsWith(`.css`),i=r?`[rel="stylesheet"]`:``;if(n)for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}else if(document.querySelector(`link[href="${t}"]${i}`))return;let o=document.createElement(`link`);if(o.rel=r?`stylesheet`:JS,r||(o.as=`script`),o.crossOrigin=``,o.href=t,a&&o.setAttribute(`nonce`,a),document.head.appendChild(o),r)return new Promise((e,n)=>{o.addEventListener(`load`,e),o.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},QS=`popstate`;function $S(e={}){function t(e,t){let{pathname:n,search:r,hash:i}=e.location;return iC(``,{pathname:n,search:r,hash:i},t.state&&t.state.usr||null,t.state&&t.state.key||`default`)}function n(e,t){return typeof t==`string`?t:aC(t)}return sC(t,n,null,e)}function eC(e,t){if(e===!1||e==null)throw Error(t)}function tC(e,t){if(!e){typeof console<`u`&&console.warn(t);try{throw Error(t)}catch{}}}function nC(){return Math.random().toString(36).substring(2,10)}function rC(e,t){return{usr:e.state,key:e.key,idx:t}}function iC(e,t,n=null,r){return{pathname:typeof e==`string`?e:e.pathname,search:``,hash:``,...typeof t==`string`?oC(t):t,state:n,key:t&&t.key||r||nC()}}function aC({pathname:e=`/`,search:t=``,hash:n=``}){return t&&t!==`?`&&(e+=t.charAt(0)===`?`?t:`?`+t),n&&n!==`#`&&(e+=n.charAt(0)===`#`?n:`#`+n),e}function oC(e){let t={};if(e){let n=e.indexOf(`#`);n>=0&&(t.hash=e.substring(n),e=e.substring(0,n));let r=e.indexOf(`?`);r>=0&&(t.search=e.substring(r),e=e.substring(0,r)),e&&(t.pathname=e)}return t}function sC(e,t,n,r={}){let{window:i=document.defaultView,v5Compat:a=!1}=r,o=i.history,s=`POP`,c=null,l=u();l??(l=0,o.replaceState({...o.state,idx:l},``));function u(){return(o.state||{idx:null}).idx}function d(){s=`POP`;let e=u(),t=e==null?null:e-l;l=e,c&&c({action:s,location:h.location,delta:t})}function f(e,t){s=`PUSH`;let r=iC(h.location,e,t);n&&n(r,e),l=u()+1;let d=rC(r,l),f=h.createHref(r);try{o.pushState(d,``,f)}catch(e){if(e instanceof DOMException&&e.name===`DataCloneError`)throw e;i.location.assign(f)}a&&c&&c({action:s,location:h.location,delta:1})}function p(e,t){s=`REPLACE`;let r=iC(h.location,e,t);n&&n(r,e),l=u();let i=rC(r,l),d=h.createHref(r);o.replaceState(i,``,d),a&&c&&c({action:s,location:h.location,delta:0})}function m(e){return cC(e)}let h={get action(){return s},get location(){return e(i,o)},listen(e){if(c)throw Error(`A history only accepts one active listener`);return i.addEventListener(QS,d),c=e,()=>{i.removeEventListener(QS,d),c=null}},createHref(e){return t(i,e)},createURL:m,encodeLocation(e){let t=m(e);return{pathname:t.pathname,search:t.search,hash:t.hash}},push:f,replace:p,go(e){return o.go(e)}};return h}function cC(e,t=!1){let n=`http://localhost`;typeof window<`u`&&(n=window.location.origin===`null`?window.location.href:window.location.origin),eC(n,`No window.location.(origin|href) available to create URL`);let r=typeof e==`string`?e:aC(e);return r=r.replace(/ $/,`%20`),!t&&r.startsWith(`//`)&&(r=n+r),new URL(r,n)}function lC(e,t,n=`/`){return uC(e,t,n,!1)}function uC(e,t,n,r){let i=OC((typeof t==`string`?oC(t):t).pathname||`/`,n);if(i==null)return null;let a=fC(e);mC(a);let o=null;for(let e=0;o==null&&e{let c={relativePath:s===void 0?e.path||``:s,caseSensitive:e.caseSensitive===!0,childrenIndex:a,route:e};if(c.relativePath.startsWith(`/`)){if(!c.relativePath.startsWith(r)&&o)return;eC(c.relativePath.startsWith(r),`Absolute route path "${c.relativePath}" nested under path "${r}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),c.relativePath=c.relativePath.slice(r.length)}let l=LC([r,c.relativePath]),u=n.concat(c);e.children&&e.children.length>0&&(eC(e.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${l}".`),fC(e.children,t,u,l,o)),!(e.path==null&&!e.index)&&t.push({path:l,score:SC(l,e.index),routesMeta:u})};return e.forEach((e,t)=>{if(e.path===``||!e.path?.includes(`?`))a(e,t);else for(let n of pC(e.path))a(e,t,!0,n)}),t}function pC(e){let t=e.split(`/`);if(t.length===0)return[];let[n,...r]=t,i=n.endsWith(`?`),a=n.replace(/\?$/,``);if(r.length===0)return i?[a,``]:[a];let o=pC(r.join(`/`)),s=[];return s.push(...o.map(e=>e===``?a:[a,e].join(`/`))),i&&s.push(...o),s.map(t=>e.startsWith(`/`)&&t===``?`/`:t)}function mC(e){e.sort((e,t)=>e.score===t.score?CC(e.routesMeta.map(e=>e.childrenIndex),t.routesMeta.map(e=>e.childrenIndex)):t.score-e.score)}var hC=/^:[\w-]+$/,gC=3,_C=2,vC=1,yC=10,bC=-2,xC=e=>e===`*`;function SC(e,t){let n=e.split(`/`),r=n.length;return n.some(xC)&&(r+=bC),t&&(r+=_C),n.filter(e=>!xC(e)).reduce((e,t)=>e+(hC.test(t)?gC:t===``?vC:yC),r)}function CC(e,t){return e.length===t.length&&e.slice(0,-1).every((e,n)=>e===t[n])?e[e.length-1]-t[t.length-1]:0}function wC(e,t,n=!1){let{routesMeta:r}=e,i={},a=`/`,o=[];for(let e=0;e{if(t===`*`){let e=s[r]||``;o=a.slice(0,a.length-e.length).replace(/(.)\/+$/,`$1`)}let i=s[r];return n&&!i?e[t]=void 0:e[t]=(i||``).replace(/%2F/g,`/`),e},{}),pathname:a,pathnameBase:o,pattern:e}}function EC(e,t=!1,n=!0){tC(e===`*`||!e.endsWith(`*`)||e.endsWith(`/*`),`Route path "${e}" will be treated as if it were "${e.replace(/\*$/,`/*`)}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${e.replace(/\*$/,`/*`)}".`);let r=[],i=`^`+e.replace(/\/*\*?$/,``).replace(/^\/*/,`/`).replace(/[\\.*+^${}|()[\]]/g,`\\$&`).replace(/\/:([\w-]+)(\?)?/g,(e,t,n)=>(r.push({paramName:t,isOptional:n!=null}),n?`/?([^\\/]+)?`:`/([^\\/]+)`)).replace(/\/([\w-]+)\?(\/|$)/g,`(/$1)?$2`);return e.endsWith(`*`)?(r.push({paramName:`*`}),i+=e===`*`||e===`/*`?`(.*)$`:`(?:\\/(.+)|\\/*)$`):n?i+=`\\/*$`:e!==``&&e!==`/`&&(i+=`(?:(?=\\/|$))`),[new RegExp(i,t?void 0:`i`),r]}function DC(e){try{return e.split(`/`).map(e=>decodeURIComponent(e).replace(/\//g,`%2F`)).join(`/`)}catch(t){return tC(!1,`The URL path "${e}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${t}).`),e}}function OC(e,t){if(t===`/`)return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let n=t.endsWith(`/`)?t.length-1:t.length,r=e.charAt(n);return r&&r!==`/`?null:e.slice(n)||`/`}var kC=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,AC=e=>kC.test(e);function jC(e,t=`/`){let{pathname:n,search:r=``,hash:i=``}=typeof e==`string`?oC(e):e,a;if(n)if(AC(n))a=n;else{if(n.includes(`//`)){let e=n;n=n.replace(/\/\/+/g,`/`),tC(!1,`Pathnames cannot have embedded double slashes - normalizing ${e} -> ${n}`)}a=n.startsWith(`/`)?MC(n.substring(1),`/`):MC(n,t)}else a=t;return{pathname:a,search:zC(r),hash:BC(i)}}function MC(e,t){let n=t.replace(/\/+$/,``).split(`/`);return e.split(`/`).forEach(e=>{e===`..`?n.length>1&&n.pop():e!==`.`&&n.push(e)}),n.length>1?n.join(`/`):`/`}function NC(e,t,n,r){return`Cannot include a '${e}' character in a manually specified \`to.${t}\` field [${JSON.stringify(r)}]. Please separate it out to the \`to.${n}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function PC(e){return e.filter((e,t)=>t===0||e.route.path&&e.route.path.length>0)}function FC(e){let t=PC(e);return t.map((e,n)=>n===t.length-1?e.pathname:e.pathnameBase)}function IC(e,t,n,r=!1){let i;typeof e==`string`?i=oC(e):(i={...e},eC(!i.pathname||!i.pathname.includes(`?`),NC(`?`,`pathname`,`search`,i)),eC(!i.pathname||!i.pathname.includes(`#`),NC(`#`,`pathname`,`hash`,i)),eC(!i.search||!i.search.includes(`#`),NC(`#`,`search`,`hash`,i)));let a=e===``||i.pathname===``,o=a?`/`:i.pathname,s;if(o==null)s=n;else{let e=t.length-1;if(!r&&o.startsWith(`..`)){let t=o.split(`/`);for(;t[0]===`..`;)t.shift(),--e;i.pathname=t.join(`/`)}s=e>=0?t[e]:`/`}let c=jC(i,s),l=o&&o!==`/`&&o.endsWith(`/`),u=(a||o===`.`)&&n.endsWith(`/`);return!c.pathname.endsWith(`/`)&&(l||u)&&(c.pathname+=`/`),c}var LC=e=>e.join(`/`).replace(/\/\/+/g,`/`),RC=e=>e.replace(/\/+$/,``).replace(/^\/*/,`/`),zC=e=>!e||e===`?`?``:e.startsWith(`?`)?e:`?`+e,BC=e=>!e||e===`#`?``:e.startsWith(`#`)?e:`#`+e,VC=class{constructor(e,t,n,r=!1){this.status=e,this.statusText=t||``,this.internal=r,n instanceof Error?(this.data=n.toString(),this.error=n):this.data=n}};function HC(e){return e!=null&&typeof e.status==`number`&&typeof e.statusText==`string`&&typeof e.internal==`boolean`&&`data`in e}function UC(e){return e.map(e=>e.route.path).filter(Boolean).join(`/`).replace(/\/\/*/g,`/`)||`/`}var WC=typeof window<`u`&&window.document!==void 0&&window.document.createElement!==void 0;function GC(e,t){let n=e;if(typeof n!=`string`||!kC.test(n))return{absoluteURL:void 0,isExternal:!1,to:n};let r=n,i=!1;if(WC)try{let e=new URL(window.location.href),r=n.startsWith(`//`)?new URL(e.protocol+n):new URL(n),a=OC(r.pathname,t);r.origin===e.origin&&a!=null?n=a+r.search+r.hash:i=!0}catch{tC(!1,` contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}return{absoluteURL:r,isExternal:i,to:n}}Object.getOwnPropertyNames(Object.prototype).sort().join(`\0`);var KC=[`POST`,`PUT`,`PATCH`,`DELETE`];new Set(KC);var qC=[`GET`,...KC];new Set(qC);var JC=m.createContext(null);JC.displayName=`DataRouter`;var YC=m.createContext(null);YC.displayName=`DataRouterState`;var XC=m.createContext(!1),ZC=m.createContext({isTransitioning:!1});ZC.displayName=`ViewTransition`;var QC=m.createContext(new Map);QC.displayName=`Fetchers`;var $C=m.createContext(null);$C.displayName=`Await`;var ew=m.createContext(null);ew.displayName=`Navigation`;var tw=m.createContext(null);tw.displayName=`Location`;var nw=m.createContext({outlet:null,matches:[],isDataRoute:!1});nw.displayName=`Route`;var rw=m.createContext(null);rw.displayName=`RouteError`;var iw=`REACT_ROUTER_ERROR`,aw=`REDIRECT`,ow=`ROUTE_ERROR_RESPONSE`;function sw(e){if(e.startsWith(`${iw}:${aw}:{`))try{let t=JSON.parse(e.slice(28));if(typeof t==`object`&&t&&typeof t.status==`number`&&typeof t.statusText==`string`&&typeof t.location==`string`&&typeof t.reloadDocument==`boolean`&&typeof t.replace==`boolean`)return t}catch{}}function cw(e){if(e.startsWith(`${iw}:${ow}:{`))try{let t=JSON.parse(e.slice(40));if(typeof t==`object`&&t&&typeof t.status==`number`&&typeof t.statusText==`string`)return new VC(t.status,t.statusText,t.data)}catch{}}function lw(e,{relative:t}={}){eC(uw(),`useHref() may be used only in the context of a component.`);let{basename:n,navigator:r}=m.useContext(ew),{hash:i,pathname:a,search:o}=gw(e,{relative:t}),s=a;return n!==`/`&&(s=a===`/`?n:LC([n,a])),r.createHref({pathname:s,search:o,hash:i})}function uw(){return m.useContext(tw)!=null}function dw(){return eC(uw(),`useLocation() may be used only in the context of a component.`),m.useContext(tw).location}var fw=`You should call navigate() in a React.useEffect(), not when your component is first rendered.`;function pw(e){m.useContext(ew).static||m.useLayoutEffect(e)}function mw(){let{isDataRoute:e}=m.useContext(nw);return e?Fw():hw()}function hw(){eC(uw(),`useNavigate() may be used only in the context of a component.`);let e=m.useContext(JC),{basename:t,navigator:n}=m.useContext(ew),{matches:r}=m.useContext(nw),{pathname:i}=dw(),a=JSON.stringify(FC(r)),o=m.useRef(!1);return pw(()=>{o.current=!0}),m.useCallback((r,s={})=>{if(tC(o.current,fw),!o.current)return;if(typeof r==`number`){n.go(r);return}let c=IC(r,JSON.parse(a),i,s.relative===`path`);e==null&&t!==`/`&&(c.pathname=c.pathname===`/`?t:LC([t,c.pathname])),(s.replace?n.replace:n.push)(c,s.state,s)},[t,n,a,i,e])}m.createContext(null);function gw(e,{relative:t}={}){let{matches:n}=m.useContext(nw),{pathname:r}=dw(),i=JSON.stringify(FC(n));return m.useMemo(()=>IC(e,JSON.parse(i),r,t===`path`),[e,i,r,t])}function _w(e,t){return vw(e,t)}function vw(e,t,n,r,i){eC(uw(),`useRoutes() may be used only in the context of a component.`);let{navigator:a}=m.useContext(ew),{matches:o}=m.useContext(nw),s=o[o.length-1],c=s?s.params:{},l=s?s.pathname:`/`,u=s?s.pathnameBase:`/`,d=s&&s.route;{let e=d&&d.path||``;Lw(l,!d||e.endsWith(`*`)||e.endsWith(`*?`),`You rendered descendant (or called \`useRoutes()\`) at "${l}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. - -Please change the parent to .`)}let f=dw(),p;if(t){let e=typeof t==`string`?oC(t):t;eC(u===`/`||e.pathname?.startsWith(u),`When overriding the location using \`\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${u}" but pathname "${e.pathname}" was given in the \`location\` prop.`),p=e}else p=f;let h=p.pathname||`/`,g=h;if(u!==`/`){let e=u.replace(/^\//,``).split(`/`);g=`/`+h.replace(/^\//,``).split(`/`).slice(e.length).join(`/`)}let _=lC(e,{pathname:g});tC(d||_!=null,`No routes matched location "${p.pathname}${p.search}${p.hash}" `),tC(_==null||_[_.length-1].route.element!==void 0||_[_.length-1].route.Component!==void 0||_[_.length-1].route.lazy!==void 0,`Matched leaf route at location "${p.pathname}${p.search}${p.hash}" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page.`);let v=Tw(_&&_.map(e=>Object.assign({},e,{params:Object.assign({},c,e.params),pathname:LC([u,a.encodeLocation?a.encodeLocation(e.pathname.replace(/\?/g,`%3F`).replace(/#/g,`%23`)).pathname:e.pathname]),pathnameBase:e.pathnameBase===`/`?u:LC([u,a.encodeLocation?a.encodeLocation(e.pathnameBase.replace(/\?/g,`%3F`).replace(/#/g,`%23`)).pathname:e.pathnameBase])})),o,n,r,i);return t&&v?m.createElement(tw.Provider,{value:{location:{pathname:`/`,search:``,hash:``,state:null,key:`default`,...p},navigationType:`POP`}},v):v}function yw(){let e=Pw(),t=HC(e)?`${e.status} ${e.statusText}`:e instanceof Error?e.message:JSON.stringify(e),n=e instanceof Error?e.stack:null,r=`rgba(200,200,200, 0.5)`,i={padding:`0.5rem`,backgroundColor:r},a={padding:`2px 4px`,backgroundColor:r},o=null;return console.error(`Error handled by React Router default ErrorBoundary:`,e),o=m.createElement(m.Fragment,null,m.createElement(`p`,null,`💿 Hey developer 👋`),m.createElement(`p`,null,`You can provide a way better UX than this when your app throws errors by providing your own `,m.createElement(`code`,{style:a},`ErrorBoundary`),` or`,` `,m.createElement(`code`,{style:a},`errorElement`),` prop on your route.`)),m.createElement(m.Fragment,null,m.createElement(`h2`,null,`Unexpected Application Error!`),m.createElement(`h3`,{style:{fontStyle:`italic`}},t),n?m.createElement(`pre`,{style:i},n):null,o)}var bw=m.createElement(yw,null),xw=class extends m.Component{constructor(e){super(e),this.state={location:e.location,revalidation:e.revalidation,error:e.error}}static getDerivedStateFromError(e){return{error:e}}static getDerivedStateFromProps(e,t){return t.location!==e.location||t.revalidation!==`idle`&&e.revalidation===`idle`?{error:e.error,location:e.location,revalidation:e.revalidation}:{error:e.error===void 0?t.error:e.error,location:t.location,revalidation:e.revalidation||t.revalidation}}componentDidCatch(e,t){this.props.onError?this.props.onError(e,t):console.error(`React Router caught the following error during render`,e)}render(){let e=this.state.error;if(this.context&&typeof e==`object`&&e&&`digest`in e&&typeof e.digest==`string`){let t=cw(e.digest);t&&(e=t)}let t=e===void 0?this.props.children:m.createElement(nw.Provider,{value:this.props.routeContext},m.createElement(rw.Provider,{value:e,children:this.props.component}));return this.context?m.createElement(Cw,{error:e},t):t}};xw.contextType=XC;var Sw=new WeakMap;function Cw({children:e,error:t}){let{basename:n}=m.useContext(ew);if(typeof t==`object`&&t&&`digest`in t&&typeof t.digest==`string`){let e=sw(t.digest);if(e){let r=Sw.get(t);if(r)throw r;let i=GC(e.location,n);if(WC&&!Sw.get(t))if(i.isExternal||e.reloadDocument)window.location.href=i.absoluteURL||i.to;else{let n=Promise.resolve().then(()=>window.__reactRouterDataRouter.navigate(i.to,{replace:e.replace}));throw Sw.set(t,n),n}return m.createElement(`meta`,{httpEquiv:`refresh`,content:`0;url=${i.absoluteURL||i.to}`})}}return e}function ww({routeContext:e,match:t,children:n}){let r=m.useContext(JC);return r&&r.static&&r.staticContext&&(t.route.errorElement||t.route.ErrorBoundary)&&(r.staticContext._deepestRenderedBoundaryId=t.route.id),m.createElement(nw.Provider,{value:e},n)}function Tw(e,t=[],n=null,r=null,i=null){if(e==null){if(!n)return null;if(n.errors)e=n.matches;else if(t.length===0&&!n.initialized&&n.matches.length>0)e=n.matches;else return null}let a=e,o=n?.errors;if(o!=null){let e=a.findIndex(e=>e.route.id&&o?.[e.route.id]!==void 0);eC(e>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(o).join(`,`)}`),a=a.slice(0,Math.min(a.length,e+1))}let s=!1,c=-1;if(n)for(let e=0;e=0?a.slice(0,c+1):[a[0]];break}}}let l=n&&r?(e,t)=>{r(e,{location:n.location,params:n.matches?.[0]?.params??{},unstable_pattern:UC(n.matches),errorInfo:t})}:void 0;return a.reduceRight((e,r,i)=>{let u,d=!1,f=null,p=null;n&&(u=o&&r.route.id?o[r.route.id]:void 0,f=r.route.errorElement||bw,s&&(c<0&&i===0?(Lw(`route-fallback`,!1,"No `HydrateFallback` element provided to render during initial hydration"),d=!0,p=null):c===i&&(d=!0,p=r.route.hydrateFallbackElement||null)));let h=t.concat(a.slice(0,i+1)),g=()=>{let t;return t=u?f:d?p:r.route.Component?m.createElement(r.route.Component,null):r.route.element?r.route.element:e,m.createElement(ww,{match:r,routeContext:{outlet:e,matches:h,isDataRoute:n!=null},children:t})};return n&&(r.route.ErrorBoundary||r.route.errorElement||i===0)?m.createElement(xw,{location:n.location,revalidation:n.revalidation,component:f,error:u,children:g(),routeContext:{outlet:null,matches:h,isDataRoute:!0},onError:l}):g()},null)}function Ew(e){return`${e} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function Dw(e){let t=m.useContext(JC);return eC(t,Ew(e)),t}function Ow(e){let t=m.useContext(YC);return eC(t,Ew(e)),t}function kw(e){let t=m.useContext(nw);return eC(t,Ew(e)),t}function Aw(e){let t=kw(e),n=t.matches[t.matches.length-1];return eC(n.route.id,`${e} can only be used on routes that contain a unique "id"`),n.route.id}function jw(){return Aw(`useRouteId`)}function Mw(){return Ow(`useNavigation`).navigation}function Nw(){let{matches:e,loaderData:t}=Ow(`useMatches`);return m.useMemo(()=>e.map(e=>dC(e,t)),[e,t])}function Pw(){let e=m.useContext(rw),t=Ow(`useRouteError`),n=Aw(`useRouteError`);return e===void 0?t.errors?.[n]:e}function Fw(){let{router:e}=Dw(`useNavigate`),t=Aw(`useNavigate`),n=m.useRef(!1);return pw(()=>{n.current=!0}),m.useCallback(async(r,i={})=>{tC(n.current,fw),n.current&&(typeof r==`number`?await e.navigate(r):await e.navigate(r,{fromRouteId:t,...i}))},[e,t])}var Iw={};function Lw(e,t,n){!t&&!Iw[e]&&(Iw[e]=!0,tC(!1,n))}m.useOptimistic,m.memo(Rw);function Rw({routes:e,future:t,state:n,onError:r}){return vw(e,void 0,n,r,t)}function zw({to:e,replace:t,state:n,relative:r}){eC(uw(),` may be used only in the context of a component.`);let{static:i}=m.useContext(ew);tC(!i,` must not be used on the initial render in a . This is a no-op, but you should modify your code so the is only ever rendered in response to some user interaction or state change.`);let{matches:a}=m.useContext(nw),{pathname:o}=dw(),s=mw(),c=IC(e,FC(a),o,r===`path`),l=JSON.stringify(c);return m.useEffect(()=>{s(JSON.parse(l),{replace:t,state:n,relative:r})},[s,l,r,t,n]),null}function Bw(e){eC(!1,`A is only ever to be used as the child of element, never rendered directly. Please wrap your in a .`)}function Vw({basename:e=`/`,children:t=null,location:n,navigationType:r=`POP`,navigator:i,static:a=!1,unstable_useTransitions:o}){eC(!uw(),`You cannot render a inside another . You should never have more than one in your app.`);let s=e.replace(/^\/*/,`/`),c=m.useMemo(()=>({basename:s,navigator:i,static:a,unstable_useTransitions:o,future:{}}),[s,i,a,o]);typeof n==`string`&&(n=oC(n));let{pathname:l=`/`,search:u=``,hash:d=``,state:f=null,key:p=`default`}=n,h=m.useMemo(()=>{let e=OC(l,s);return e==null?null:{location:{pathname:e,search:u,hash:d,state:f,key:p},navigationType:r}},[s,l,u,d,f,p,r]);return tC(h!=null,` is not able to match the URL "${l}${u}${d}" because it does not start with the basename, so the won't render anything.`),h==null?null:m.createElement(ew.Provider,{value:c},m.createElement(tw.Provider,{children:t,value:h}))}function Hw({children:e,location:t}){return _w(Uw(e),t)}m.Component;function Uw(e,t=[]){let n=[];return m.Children.forEach(e,(e,r)=>{if(!m.isValidElement(e))return;let i=[...t,r];if(e.type===m.Fragment){n.push.apply(n,Uw(e.props.children,i));return}eC(e.type===Bw,`[${typeof e.type==`string`?e.type:e.type.name}] is not a component. All component children of must be a or `),eC(!e.props.index||!e.props.children,`An index route cannot have child routes.`);let a={id:e.props.id||i.join(`-`),caseSensitive:e.props.caseSensitive,element:e.props.element,Component:e.props.Component,index:e.props.index,path:e.props.path,middleware:e.props.middleware,loader:e.props.loader,action:e.props.action,hydrateFallbackElement:e.props.hydrateFallbackElement,HydrateFallback:e.props.HydrateFallback,errorElement:e.props.errorElement,ErrorBoundary:e.props.ErrorBoundary,hasErrorBoundary:e.props.hasErrorBoundary===!0||e.props.ErrorBoundary!=null||e.props.errorElement!=null,shouldRevalidate:e.props.shouldRevalidate,handle:e.props.handle,lazy:e.props.lazy};e.props.children&&(a.children=Uw(e.props.children,i)),n.push(a)}),n}var Ww=`get`,Gw=`application/x-www-form-urlencoded`;function Kw(e){return typeof HTMLElement<`u`&&e instanceof HTMLElement}function qw(e){return Kw(e)&&e.tagName.toLowerCase()===`button`}function Jw(e){return Kw(e)&&e.tagName.toLowerCase()===`form`}function Yw(e){return Kw(e)&&e.tagName.toLowerCase()===`input`}function Xw(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}function Zw(e,t){return e.button===0&&(!t||t===`_self`)&&!Xw(e)}var Qw=null;function $w(){if(Qw===null)try{new FormData(document.createElement(`form`),0),Qw=!1}catch{Qw=!0}return Qw}var eT=new Set([`application/x-www-form-urlencoded`,`multipart/form-data`,`text/plain`]);function tT(e){return e!=null&&!eT.has(e)?(tC(!1,`"${e}" is not a valid \`encType\` for \`\`/\`\` and will default to "${Gw}"`),null):e}function nT(e,t){let n,r,i,a,o;if(Jw(e)){let o=e.getAttribute(`action`);r=o?OC(o,t):null,n=e.getAttribute(`method`)||Ww,i=tT(e.getAttribute(`enctype`))||Gw,a=new FormData(e)}else if(qw(e)||Yw(e)&&(e.type===`submit`||e.type===`image`)){let o=e.form;if(o==null)throw Error(`Cannot submit a -
-
- ); -}; diff --git a/packages/ocom/ui-staff-route-root/package.json b/packages/ocom/ui-staff-route-root/package.json index 2c321a9a9..6c4a8aefc 100644 --- a/packages/ocom/ui-staff-route-root/package.json +++ b/packages/ocom/ui-staff-route-root/package.json @@ -15,11 +15,7 @@ "test:watch": "vitest" }, "dependencies": { - "@ocom/ui-staff-route-shared": "workspace:*", - "@ocom/ui-staff-route-community-management": "workspace:*", - "@ocom/ui-staff-route-finance": "workspace:*", - "@ocom/ui-staff-route-tech-admin": "workspace:*", - "@ocom/ui-staff-route-user-management": "workspace:*", + "antd": "catalog:", "react": "^19.1.1", "react-dom": "^19.1.1" }, diff --git a/packages/ocom/ui-staff-route-root/src/components/header.module.css b/packages/ocom/ui-staff-route-root/src/components/header.module.css new file mode 100644 index 000000000..99fa409f4 --- /dev/null +++ b/packages/ocom/ui-staff-route-root/src/components/header.module.css @@ -0,0 +1,11 @@ +.top-bar { + border-bottom: 1px solid #e5e5e5; + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.05); + padding: 0.5rem 0; + /*position: fixed; */ + top: 0; + min-width: 100%; + z-index: 1000; + height: 50px; + color: #000; +} diff --git a/packages/ocom/ui-staff-route-root/src/components/header.tsx b/packages/ocom/ui-staff-route-root/src/components/header.tsx new file mode 100644 index 000000000..065c684bc --- /dev/null +++ b/packages/ocom/ui-staff-route-root/src/components/header.tsx @@ -0,0 +1,27 @@ +import { Button, theme } from 'antd'; +import styles from './header.module.css'; + +export const Header: React.FC = () => { + const handleLogin = () => { + // biome-ignore lint:useLiteralKeys + globalThis.location.href = `${import.meta.env['VITE_AAD_B2C_STAFF_REDIRECT_URI']}`; + }; + + const { + token: { colorBgContainer }, + } = theme.useToken(); + + return ( +
+ +
+ ); +}; diff --git a/packages/ocom/ui-staff-route-root/src/index.tsx b/packages/ocom/ui-staff-route-root/src/index.tsx index db42a8d03..cfb258222 100644 --- a/packages/ocom/ui-staff-route-root/src/index.tsx +++ b/packages/ocom/ui-staff-route-root/src/index.tsx @@ -1,4 +1,5 @@ -import { createElement, type FC } from 'react'; import { SectionLayout } from './section-layout.tsx'; -export const Root: FC = () => createElement(SectionLayout); +export const Root: React.FC = () => { + return ; +}; diff --git a/packages/ocom/ui-staff-route-root/src/pages/login-page.tsx b/packages/ocom/ui-staff-route-root/src/pages/login-page.tsx new file mode 100644 index 000000000..651e14bcb --- /dev/null +++ b/packages/ocom/ui-staff-route-root/src/pages/login-page.tsx @@ -0,0 +1,16 @@ +import { Typography } from 'antd'; + +const { Text } = Typography; + +export const LoginPage: React.FC = () => { + return ( +
+ + Staff Portal + + + Sign in above to access the staff dashboard. + +
+ ); +}; diff --git a/packages/ocom/ui-staff-route-root/src/section-layout.tsx b/packages/ocom/ui-staff-route-root/src/section-layout.tsx index d2d7c2281..90e781b91 100644 --- a/packages/ocom/ui-staff-route-root/src/section-layout.tsx +++ b/packages/ocom/ui-staff-route-root/src/section-layout.tsx @@ -1,11 +1,11 @@ -import type { FC } from 'react'; -import { StaffRouteShell } from '@ocom/ui-staff-route-shared'; +import { Header } from './components/header.tsx'; +import { LoginPage } from './pages/login-page.tsx'; -export const SectionLayout: FC = () => { +export const SectionLayout: React.FC = () => { return ( - +
+
+ +
); }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 11d6bbc31..995f123b1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1926,21 +1926,9 @@ importers: packages/ocom/ui-staff-route-root: dependencies: - '@ocom/ui-staff-route-community-management': - specifier: workspace:* - version: link:../ui-staff-route-community-management - '@ocom/ui-staff-route-finance': - specifier: workspace:* - version: link:../ui-staff-route-finance - '@ocom/ui-staff-route-shared': - specifier: workspace:* - version: link:../ui-staff-route-shared - '@ocom/ui-staff-route-tech-admin': - specifier: workspace:* - version: link:../ui-staff-route-tech-admin - '@ocom/ui-staff-route-user-management': - specifier: workspace:* - version: link:../ui-staff-route-user-management + antd: + specifier: 'catalog:' + version: 6.3.5(luxon@3.6.1)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: specifier: ^19.1.1 version: 19.2.0 @@ -1965,16 +1953,16 @@ importers: version: 26.1.0 storybook: specifier: 'catalog:' - version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) typescript: specifier: 'catalog:' version: 6.0.3 vite: specifier: 8.0.5 - version: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + version: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) vitest: specifier: 'catalog:' - version: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/ui-staff-route-shared: dependencies: @@ -12954,7 +12942,7 @@ snapshots: minimist: 1.2.8 parsecurrency: 1.1.1 ts-morph: 27.0.2 - vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@22.19.15)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) '@ant-design/cli@6.3.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)': dependencies: @@ -18288,6 +18276,20 @@ snapshots: - vite optional: true + '@vitest/browser-playwright@4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': + dependencies: + '@vitest/browser': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) + '@vitest/mocker': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + playwright: 1.59.0 + tinyrainbow: 3.1.0 + vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + optional: true + '@vitest/browser-playwright@4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': dependencies: '@vitest/browser': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) @@ -18319,6 +18321,24 @@ snapshots: - vite optional: true + '@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': + dependencies: + '@blazediff/core': 1.9.1 + '@vitest/mocker': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/utils': 4.1.2 + magic-string: 0.30.21 + pngjs: 7.0.0 + sirv: 3.0.2 + tinyrainbow: 3.1.0 + vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + ws: 8.20.0 + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + optional: true + '@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': dependencies: '@blazediff/core': 1.9.1 @@ -18348,7 +18368,7 @@ snapshots: magicast: 0.5.2 obug: 2.1.1 tinyrainbow: 3.1.0 - vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@22.19.15)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) transitivePeerDependencies: - supports-color @@ -18369,6 +18389,14 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 + '@vitest/mocker@3.2.4(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': + dependencies: + '@vitest/spy': 3.2.4 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + '@vitest/mocker@3.2.4(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@vitest/spy': 3.2.4 @@ -18385,6 +18413,14 @@ snapshots: optionalDependencies: vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@22.19.15)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + '@vitest/mocker@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': + dependencies: + '@vitest/spy': 4.1.2 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + '@vitest/mocker@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@vitest/spy': 4.1.2 @@ -24600,6 +24636,28 @@ snapshots: graphql: 16.12.0 react: 19.2.0 + storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): + dependencies: + '@storybook/global': 5.0.0 + '@testing-library/jest-dom': 6.9.1 + '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1) + '@vitest/expect': 3.2.4 + '@vitest/mocker': 3.2.4(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/spy': 3.2.4 + better-opn: 3.0.2 + esbuild: 0.25.12 + esbuild-register: 3.6.0(esbuild@0.25.12) + recast: 0.23.11 + semver: 7.7.3 + ws: 8.20.0 + transitivePeerDependencies: + - '@testing-library/dom' + - bufferutil + - msw + - supports-color + - utf-8-validate + - vite + storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): dependencies: '@storybook/global': 5.0.0 @@ -25326,6 +25384,26 @@ snapshots: - '@emnapi/core' - '@emnapi/runtime' + vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3): + dependencies: + lightningcss: 1.32.0 + picomatch: 4.0.4 + postcss: 8.5.10 + rolldown: 1.0.0-rc.12(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1) + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 24.10.1 + esbuild: 0.25.12 + fsevents: 2.3.3 + jiti: 2.6.1 + less: 4.4.2 + terser: 5.44.1 + tsx: 4.21.0 + yaml: 2.8.3 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3): dependencies: lightningcss: 1.32.0 @@ -25376,6 +25454,36 @@ snapshots: transitivePeerDependencies: - msw + vitest@4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): + dependencies: + '@vitest/expect': 4.1.2 + '@vitest/mocker': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/pretty-format': 4.1.2 + '@vitest/runner': 4.1.2 + '@vitest/snapshot': 4.1.2 + '@vitest/spy': 4.1.2 + '@vitest/utils': 4.1.2 + es-module-lexer: 2.0.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.4 + std-env: 4.0.0 + tinybench: 2.9.0 + tinyexec: 1.0.4 + tinyglobby: 0.2.15 + tinyrainbow: 3.1.0 + vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + why-is-node-running: 2.3.0 + optionalDependencies: + '@opentelemetry/api': 1.9.0 + '@types/node': 24.10.1 + '@vitest/browser-playwright': 4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) + jsdom: 26.1.0 + transitivePeerDependencies: + - msw + vitest@4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): dependencies: '@vitest/expect': 4.1.2 From e6c5e31b60100c70876d6585cbf1b044d60a1313 Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Wed, 29 Apr 2026 16:40:32 -0400 Subject: [PATCH 21/88] remove .env from .gitignore --- apps/ui-staff/.env | 6 ++++++ apps/ui-staff/.gitignore | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 apps/ui-staff/.env diff --git a/apps/ui-staff/.env b/apps/ui-staff/.env new file mode 100644 index 000000000..70b461ad9 --- /dev/null +++ b/apps/ui-staff/.env @@ -0,0 +1,6 @@ +NODE_ENV=development +VITE_AAD_B2C_STAFF_AUTHORITY=https://mock-auth.ownercommunity.localhost:1355/staff +VITE_AAD_B2C_STAFF_CLIENTID=mock-client +VITE_AAD_B2C_STAFF_REDIRECT_URI=https://staff.ownercommunity.localhost:1355/auth-redirect +VITE_AAD_B2C_STAFF_SCOPES=openid +VITE_FUNCTION_ENDPOINT=https://data-access.ownercommunity.localhost:1355/api/graphql diff --git a/apps/ui-staff/.gitignore b/apps/ui-staff/.gitignore index 893233b1a..d3793d950 100644 --- a/apps/ui-staff/.gitignore +++ b/apps/ui-staff/.gitignore @@ -23,4 +23,4 @@ tsconfig.tsbuildinfo *.njsproj *.sln *.sw? -.env + From 78d2ac3136490944a9aa66fa263eaa1c8bbabafc Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Thu, 30 Apr 2026 09:10:22 -0400 Subject: [PATCH 22/88] refactor: update build scripts to use tsgo and improve code formatting --- apps/ui-staff/package.json | 4 +- apps/ui-staff/src/App.css | 4 +- apps/ui-staff/src/main.tsx | 8 +-- apps/ui-staff/vite.config.ts | 4 +- .../package.json | 65 ++++++++++--------- .../tsconfig.json | 30 ++++----- .../ocom/ui-staff-route-finance/package.json | 65 ++++++++++--------- .../ocom/ui-staff-route-finance/tsconfig.json | 30 ++++----- .../ocom/ui-staff-route-root/package.json | 2 +- .../ocom/ui-staff-route-shared/package.json | 6 +- .../ui-staff-route-tech-admin/package.json | 2 +- .../package.json | 2 +- 12 files changed, 114 insertions(+), 108 deletions(-) diff --git a/apps/ui-staff/package.json b/apps/ui-staff/package.json index 8d9b0cdff..6b83f79f6 100644 --- a/apps/ui-staff/package.json +++ b/apps/ui-staff/package.json @@ -8,7 +8,7 @@ "format": "biome format --write", "format:check": "biome format .", "prebuild": "pnpm run lint", - "build": "tsc --build && vite build", + "build": "tsgo --build && vite build", "dev": "node ../../build-pipeline/scripts/portless-dev.mjs staff.ownercommunity.localhost vite", "start": "vite", "preview": "vite preview", @@ -28,7 +28,7 @@ "@ocom/ui-staff-route-user-management": "workspace:*", "@ocom/ui-staff-route-finance": "workspace:*", "@ocom/ui-staff-route-tech-admin": "workspace:*", - "@ocom/ui-staff-route-shared": "workspace:*", + "@ocom/ui-staff-route-shared": "workspace:*", "antd": "catalog:", "apollo-link-rest": "^0.9.0", "less": "^4.4.0", diff --git a/apps/ui-staff/src/App.css b/apps/ui-staff/src/App.css index 92d656be5..c735afc45 100644 --- a/apps/ui-staff/src/App.css +++ b/apps/ui-staff/src/App.css @@ -1 +1,3 @@ -.App { text-align: center; } +.App { + text-align: center; +} diff --git a/apps/ui-staff/src/main.tsx b/apps/ui-staff/src/main.tsx index c8ab49201..ea263e882 100644 --- a/apps/ui-staff/src/main.tsx +++ b/apps/ui-staff/src/main.tsx @@ -33,10 +33,10 @@ const ConfigProviderWrapper = () => { -
-
-
-
+ + + +
); }; diff --git a/apps/ui-staff/vite.config.ts b/apps/ui-staff/vite.config.ts index b3716cc05..d0e1e3b07 100644 --- a/apps/ui-staff/vite.config.ts +++ b/apps/ui-staff/vite.config.ts @@ -10,6 +10,6 @@ export default defineConfig({ server: process.env.PORTLESS_URL ? undefined : { - port: 3001, - }, + port: 3001, + }, }); diff --git a/packages/ocom/ui-staff-route-community-management/package.json b/packages/ocom/ui-staff-route-community-management/package.json index 72881e15e..745ac7417 100644 --- a/packages/ocom/ui-staff-route-community-management/package.json +++ b/packages/ocom/ui-staff-route-community-management/package.json @@ -1,34 +1,35 @@ { - "name": "@ocom/ui-staff-route-community-management", - "version": "0.0.1", - "private": true, - "type": "module", - "exports": { - ".": "./src/index.tsx" - }, - "scripts": { - "prebuild": "pnpm run lint", - "build": "tsc --noEmit", - "lint": "biome lint", - "test": "vitest run --silent --reporter=dot", - "test:coverage": "vitest run --coverage --silent --reporter=dot", - "test:watch": "vitest" - }, - "dependencies": { - "@ocom/ui-staff-route-shared": "workspace:*", - "antd": "catalog:", - "react": "^19.1.1", - "react-dom": "^19.1.1" - }, - "devDependencies": { - "@cellix/config-typescript": "workspace:*", - "@cellix/config-vitest": "workspace:*", - "@types/react": "^19.1.11", - "@types/react-dom": "^19.1.6", - "jsdom": "catalog:", - "storybook": "catalog:", - "vite": "catalog:", - "vitest": "catalog:", - "typescript": "catalog:" - } + "name": "@ocom/ui-staff-route-community-management", + "version": "0.0.1", + "private": true, + "type": "module", + "exports": { + ".": "./src/index.tsx" + }, + "scripts": { + "prebuild": "pnpm run lint", + "build": "tsgo --noEmit", + "format": "biome format --write", + "lint": "biome lint", + "test": "vitest run --silent --reporter=dot", + "test:coverage": "vitest run --coverage --silent --reporter=dot", + "test:watch": "vitest" + }, + "dependencies": { + "@ocom/ui-staff-route-shared": "workspace:*", + "antd": "catalog:", + "react": "^19.1.1", + "react-dom": "^19.1.1" + }, + "devDependencies": { + "@cellix/config-typescript": "workspace:*", + "@cellix/config-vitest": "workspace:*", + "@types/react": "^19.1.11", + "@types/react-dom": "^19.1.6", + "jsdom": "catalog:", + "storybook": "catalog:", + "vite": "catalog:", + "vitest": "catalog:", + "typescript": "catalog:" + } } diff --git a/packages/ocom/ui-staff-route-community-management/tsconfig.json b/packages/ocom/ui-staff-route-community-management/tsconfig.json index 520d9c6d2..33d09517b 100644 --- a/packages/ocom/ui-staff-route-community-management/tsconfig.json +++ b/packages/ocom/ui-staff-route-community-management/tsconfig.json @@ -1,17 +1,17 @@ { - "extends": "@cellix/config-typescript/base", - "compilerOptions": { - "target": "ES2022", - "module": "ESNext", - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "verbatimModuleSyntax": true, - "jsx": "react-jsx", - "lib": ["ES2023", "DOM"], - "skipLibCheck": true, - "noEmit": true, - "types": ["vite/client"] - }, - "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.d.ts"], - "exclude": ["src/**/*.stories.ts", "src/**/*.stories.tsx", "src/**/*.test.ts", "src/**/*.test.tsx"] + "extends": "@cellix/config-typescript/base", + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "jsx": "react-jsx", + "lib": ["ES2023", "DOM"], + "skipLibCheck": true, + "noEmit": true, + "types": ["vite/client"] + }, + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.d.ts"], + "exclude": ["src/**/*.stories.ts", "src/**/*.stories.tsx", "src/**/*.test.ts", "src/**/*.test.tsx"] } diff --git a/packages/ocom/ui-staff-route-finance/package.json b/packages/ocom/ui-staff-route-finance/package.json index 2ab9c430b..69378e030 100644 --- a/packages/ocom/ui-staff-route-finance/package.json +++ b/packages/ocom/ui-staff-route-finance/package.json @@ -1,34 +1,35 @@ { - "name": "@ocom/ui-staff-route-finance", - "version": "0.0.1", - "private": true, - "type": "module", - "exports": { - ".": "./src/index.tsx" - }, - "scripts": { - "prebuild": "pnpm run lint", - "build": "tsc --noEmit", - "lint": "biome lint", - "test": "vitest run --silent --reporter=dot", - "test:coverage": "vitest run --coverage --silent --reporter=dot", - "test:watch": "vitest" - }, - "dependencies": { - "@ocom/ui-staff-route-shared": "workspace:*", - "antd": "catalog:", - "react": "^19.1.1", - "react-dom": "^19.1.1" - }, - "devDependencies": { - "@cellix/config-typescript": "workspace:*", - "@cellix/config-vitest": "workspace:*", - "@types/react": "^19.1.11", - "@types/react-dom": "^19.1.6", - "jsdom": "catalog:", - "storybook": "catalog:", - "vite": "catalog:", - "vitest": "catalog:", - "typescript": "catalog:" - } + "name": "@ocom/ui-staff-route-finance", + "version": "0.0.1", + "private": true, + "type": "module", + "exports": { + ".": "./src/index.tsx" + }, + "scripts": { + "prebuild": "pnpm run lint", + "format": "biome format --write", + "build": "tsgo --noEmit", + "lint": "biome lint", + "test": "vitest run --silent --reporter=dot", + "test:coverage": "vitest run --coverage --silent --reporter=dot", + "test:watch": "vitest" + }, + "dependencies": { + "@ocom/ui-staff-route-shared": "workspace:*", + "antd": "catalog:", + "react": "^19.1.1", + "react-dom": "^19.1.1" + }, + "devDependencies": { + "@cellix/config-typescript": "workspace:*", + "@cellix/config-vitest": "workspace:*", + "@types/react": "^19.1.11", + "@types/react-dom": "^19.1.6", + "jsdom": "catalog:", + "storybook": "catalog:", + "vite": "catalog:", + "vitest": "catalog:", + "typescript": "catalog:" + } } diff --git a/packages/ocom/ui-staff-route-finance/tsconfig.json b/packages/ocom/ui-staff-route-finance/tsconfig.json index 520d9c6d2..33d09517b 100644 --- a/packages/ocom/ui-staff-route-finance/tsconfig.json +++ b/packages/ocom/ui-staff-route-finance/tsconfig.json @@ -1,17 +1,17 @@ { - "extends": "@cellix/config-typescript/base", - "compilerOptions": { - "target": "ES2022", - "module": "ESNext", - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "verbatimModuleSyntax": true, - "jsx": "react-jsx", - "lib": ["ES2023", "DOM"], - "skipLibCheck": true, - "noEmit": true, - "types": ["vite/client"] - }, - "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.d.ts"], - "exclude": ["src/**/*.stories.ts", "src/**/*.stories.tsx", "src/**/*.test.ts", "src/**/*.test.tsx"] + "extends": "@cellix/config-typescript/base", + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "jsx": "react-jsx", + "lib": ["ES2023", "DOM"], + "skipLibCheck": true, + "noEmit": true, + "types": ["vite/client"] + }, + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.d.ts"], + "exclude": ["src/**/*.stories.ts", "src/**/*.stories.tsx", "src/**/*.test.ts", "src/**/*.test.tsx"] } diff --git a/packages/ocom/ui-staff-route-root/package.json b/packages/ocom/ui-staff-route-root/package.json index 6c4a8aefc..806b6d0f0 100644 --- a/packages/ocom/ui-staff-route-root/package.json +++ b/packages/ocom/ui-staff-route-root/package.json @@ -8,7 +8,7 @@ }, "scripts": { "prebuild": "pnpm run lint", - "build": "tsc --noEmit", + "build": "tsgo --noEmit", "lint": "biome lint", "test": "vitest run --silent --reporter=dot", "test:coverage": "vitest run --coverage --silent --reporter=dot", diff --git a/packages/ocom/ui-staff-route-shared/package.json b/packages/ocom/ui-staff-route-shared/package.json index edeecb223..72bc99641 100644 --- a/packages/ocom/ui-staff-route-shared/package.json +++ b/packages/ocom/ui-staff-route-shared/package.json @@ -8,7 +8,7 @@ }, "scripts": { "prebuild": "pnpm run lint", - "build": "tsc --noEmit", + "build": "tsgo --noEmit", "lint": "biome lint", "test": "vitest run --silent --reporter=dot", "test:coverage": "vitest run --coverage --silent --reporter=dot", @@ -25,6 +25,8 @@ "jsdom": "catalog:", "vite": "catalog:", "vitest": "catalog:", - "typescript": "catalog:" + "typescript": "catalog:", + "react-router-dom": "catalog:", + "@testing-library/react": "catalog:" } } diff --git a/packages/ocom/ui-staff-route-tech-admin/package.json b/packages/ocom/ui-staff-route-tech-admin/package.json index 2a6af1e5a..1923c2dea 100644 --- a/packages/ocom/ui-staff-route-tech-admin/package.json +++ b/packages/ocom/ui-staff-route-tech-admin/package.json @@ -8,7 +8,7 @@ }, "scripts": { "prebuild": "pnpm run lint", - "build": "tsc --noEmit", + "build": "tsgo --noEmit", "lint": "biome lint", "test": "vitest run --silent --reporter=dot", "test:coverage": "vitest run --coverage --silent --reporter=dot", diff --git a/packages/ocom/ui-staff-route-user-management/package.json b/packages/ocom/ui-staff-route-user-management/package.json index 5543b8ed5..60a30577a 100644 --- a/packages/ocom/ui-staff-route-user-management/package.json +++ b/packages/ocom/ui-staff-route-user-management/package.json @@ -8,7 +8,7 @@ }, "scripts": { "prebuild": "pnpm run lint", - "build": "tsc --noEmit", + "build": "tsgo --noEmit", "lint": "biome lint", "test": "vitest run --silent --reporter=dot", "test:coverage": "vitest run --coverage --silent --reporter=dot", From 280a381272006e4a5c37bac473dcdb187b84f2f8 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Thu, 30 Apr 2026 19:15:43 +0530 Subject: [PATCH 23/88] refactor: update package.json scripts and remove unused dependencies --- apps/ui-staff/package.json | 6 +- apps/ui-staff/src/config/oidc-config.tsx | 3 +- apps/ui-staff/src/unauthorized.tsx | 8 +- knip.json | 3 +- .../package.json | 1 + .../ocom/ui-staff-route-finance/package.json | 1 + pnpm-lock.yaml | 145 ++---------------- pnpm-workspace.yaml | 1 + 8 files changed, 25 insertions(+), 143 deletions(-) diff --git a/apps/ui-staff/package.json b/apps/ui-staff/package.json index 6b83f79f6..d91d31c91 100644 --- a/apps/ui-staff/package.json +++ b/apps/ui-staff/package.json @@ -14,9 +14,7 @@ "preview": "vite preview", "test": "vitest run --silent --reporter=dot", "test:coverage": "vitest run --coverage --silent --reporter=dot", - "test:watch": "vitest", - "storybook": "storybook dev -p 6008", - "build-storybook": "storybook build" + "test:watch": "vitest" }, "dependencies": { "@apollo/client": "^3.13.9", @@ -47,8 +45,6 @@ "@vitest/coverage-istanbul": "catalog:", "esbuild": "catalog:", "jsdom": "^26.1.0", - "storybook": "catalog:", - "storybook-addon-apollo-client": "^9.0.0", "tailwindcss": "^3.4.17", "typescript": "catalog:", "vite": "catalog:", diff --git a/apps/ui-staff/src/config/oidc-config.tsx b/apps/ui-staff/src/config/oidc-config.tsx index 726c72774..fc0f34dfb 100644 --- a/apps/ui-staff/src/config/oidc-config.tsx +++ b/apps/ui-staff/src/config/oidc-config.tsx @@ -23,9 +23,8 @@ export const oidcConfig: OIDCConfig = { noonce: true, response_type: 'code', // biome-ignore lint:useLiteralKeys - scope: import.meta.env['VITE_AAD_B2C_STAFF_SCOPES'], + scope: import.meta.env['VITE_AAD_B2C_STAFF_SCOPES'] ?? 'openid', onSigninCallback: (): void => { - console.log('onSigninCallback'); globalThis.history.replaceState({}, document.title, globalThis.location.pathname); const redirectToPath = globalThis.sessionStorage.getItem('redirectTo'); if (redirectToPath) { diff --git a/apps/ui-staff/src/unauthorized.tsx b/apps/ui-staff/src/unauthorized.tsx index 08c80a8a9..08f231676 100644 --- a/apps/ui-staff/src/unauthorized.tsx +++ b/apps/ui-staff/src/unauthorized.tsx @@ -1,6 +1,5 @@ import type React from 'react'; import { Row, Button, Typography } from 'antd'; -import { Link } from 'react-router-dom'; export const Unauthorized: React.FC = () => { return ( @@ -8,8 +7,11 @@ export const Unauthorized: React.FC = () => {
Unauthorized You do not have permission to view this page. -
diff --git a/knip.json b/knip.json index 95663f9ea..7c4a4a5e3 100644 --- a/knip.json +++ b/knip.json @@ -106,8 +106,7 @@ "packages/ocom/ui-staff-route-community-management/package.json": ["dependencies","devDependencies"], "packages/ocom/ui-staff-route-tech-admin/package.json": ["dependencies","devDependencies"], "packages/ocom/ui-staff-route-finance/package.json": ["dependencies","devDependencies"], - "packages/ocom/ui-staff-route-user-management/package.json": ["dependencies","devDependencies"], - "apps/ui-staff/src/apollo-connection.tsx": ["types"] + "packages/ocom/ui-staff-route-user-management/package.json": ["dependencies","devDependencies"] }, "ignoreDependencies": [ "@types/*", diff --git a/packages/ocom/ui-staff-route-community-management/package.json b/packages/ocom/ui-staff-route-community-management/package.json index 745ac7417..92cf5dcdd 100644 --- a/packages/ocom/ui-staff-route-community-management/package.json +++ b/packages/ocom/ui-staff-route-community-management/package.json @@ -10,6 +10,7 @@ "prebuild": "pnpm run lint", "build": "tsgo --noEmit", "format": "biome format --write", + "format:check": "biome format .", "lint": "biome lint", "test": "vitest run --silent --reporter=dot", "test:coverage": "vitest run --coverage --silent --reporter=dot", diff --git a/packages/ocom/ui-staff-route-finance/package.json b/packages/ocom/ui-staff-route-finance/package.json index 69378e030..0a22fc623 100644 --- a/packages/ocom/ui-staff-route-finance/package.json +++ b/packages/ocom/ui-staff-route-finance/package.json @@ -9,6 +9,7 @@ "scripts": { "prebuild": "pnpm run lint", "format": "biome format --write", + "format:check": "biome format .", "build": "tsgo --noEmit", "lint": "biome lint", "test": "vitest run --silent --reporter=dot", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 995f123b1..6e562bf91 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,6 +12,9 @@ catalogs: '@azure/functions': specifier: 4.11.0 version: 4.11.0 + '@testing-library/react': + specifier: ^16.3.0 + version: 16.3.0 '@types/node': specifier: ^22.19.5 version: 22.19.15 @@ -570,12 +573,6 @@ importers: rollup-plugin-visualizer: specifier: ^6.0.5 version: 6.0.5(rolldown@1.0.0-rc.12(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1))(rollup@4.59.0) - storybook: - specifier: 'catalog:' - version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - storybook-addon-apollo-client: - specifier: ^9.0.0 - version: 9.0.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(react@19.2.0) tailwindcss: specifier: ^3.4.17 version: 3.4.18(tsx@4.21.0)(yaml@2.8.3) @@ -1953,16 +1950,16 @@ importers: version: 26.1.0 storybook: specifier: 'catalog:' - version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) typescript: specifier: 'catalog:' version: 6.0.3 vite: specifier: 8.0.5 - version: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + version: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) vitest: specifier: 'catalog:' - version: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/ui-staff-route-shared: dependencies: @@ -1976,6 +1973,9 @@ importers: '@cellix/config-vitest': specifier: workspace:* version: link:../../cellix/config-vitest + '@testing-library/react': + specifier: 'catalog:' + version: 16.3.0(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@types/react': specifier: ^19.1.11 version: 19.2.7 @@ -1985,6 +1985,9 @@ importers: jsdom: specifier: 'catalog:' version: 26.1.0 + react-router-dom: + specifier: 'catalog:' + version: 7.12.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) typescript: specifier: 'catalog:' version: 6.0.3 @@ -12942,7 +12945,7 @@ snapshots: minimist: 1.2.8 parsecurrency: 1.1.1 ts-morph: 27.0.2 - vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@22.19.15)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) '@ant-design/cli@6.3.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)': dependencies: @@ -18276,20 +18279,6 @@ snapshots: - vite optional: true - '@vitest/browser-playwright@4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': - dependencies: - '@vitest/browser': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) - '@vitest/mocker': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - playwright: 1.59.0 - tinyrainbow: 3.1.0 - vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - transitivePeerDependencies: - - bufferutil - - msw - - utf-8-validate - - vite - optional: true - '@vitest/browser-playwright@4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': dependencies: '@vitest/browser': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) @@ -18321,24 +18310,6 @@ snapshots: - vite optional: true - '@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': - dependencies: - '@blazediff/core': 1.9.1 - '@vitest/mocker': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@vitest/utils': 4.1.2 - magic-string: 0.30.21 - pngjs: 7.0.0 - sirv: 3.0.2 - tinyrainbow: 3.1.0 - vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - ws: 8.20.0 - transitivePeerDependencies: - - bufferutil - - msw - - utf-8-validate - - vite - optional: true - '@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': dependencies: '@blazediff/core': 1.9.1 @@ -18368,7 +18339,7 @@ snapshots: magicast: 0.5.2 obug: 2.1.1 tinyrainbow: 3.1.0 - vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@22.19.15)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) transitivePeerDependencies: - supports-color @@ -18389,14 +18360,6 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@3.2.4(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': - dependencies: - '@vitest/spy': 3.2.4 - estree-walker: 3.0.3 - magic-string: 0.30.21 - optionalDependencies: - vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) - '@vitest/mocker@3.2.4(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@vitest/spy': 3.2.4 @@ -18413,14 +18376,6 @@ snapshots: optionalDependencies: vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@22.19.15)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) - '@vitest/mocker@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': - dependencies: - '@vitest/spy': 4.1.2 - estree-walker: 3.0.3 - magic-string: 0.30.21 - optionalDependencies: - vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) - '@vitest/mocker@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@vitest/spy': 4.1.2 @@ -24636,28 +24591,6 @@ snapshots: graphql: 16.12.0 react: 19.2.0 - storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): - dependencies: - '@storybook/global': 5.0.0 - '@testing-library/jest-dom': 6.9.1 - '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1) - '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@vitest/spy': 3.2.4 - better-opn: 3.0.2 - esbuild: 0.25.12 - esbuild-register: 3.6.0(esbuild@0.25.12) - recast: 0.23.11 - semver: 7.7.3 - ws: 8.20.0 - transitivePeerDependencies: - - '@testing-library/dom' - - bufferutil - - msw - - supports-color - - utf-8-validate - - vite - storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): dependencies: '@storybook/global': 5.0.0 @@ -25384,26 +25317,6 @@ snapshots: - '@emnapi/core' - '@emnapi/runtime' - vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3): - dependencies: - lightningcss: 1.32.0 - picomatch: 4.0.4 - postcss: 8.5.10 - rolldown: 1.0.0-rc.12(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1) - tinyglobby: 0.2.15 - optionalDependencies: - '@types/node': 24.10.1 - esbuild: 0.25.12 - fsevents: 2.3.3 - jiti: 2.6.1 - less: 4.4.2 - terser: 5.44.1 - tsx: 4.21.0 - yaml: 2.8.3 - transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' - vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3): dependencies: lightningcss: 1.32.0 @@ -25454,36 +25367,6 @@ snapshots: transitivePeerDependencies: - msw - vitest@4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): - dependencies: - '@vitest/expect': 4.1.2 - '@vitest/mocker': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@vitest/pretty-format': 4.1.2 - '@vitest/runner': 4.1.2 - '@vitest/snapshot': 4.1.2 - '@vitest/spy': 4.1.2 - '@vitest/utils': 4.1.2 - es-module-lexer: 2.0.0 - expect-type: 1.3.0 - magic-string: 0.30.21 - obug: 2.1.1 - pathe: 2.0.3 - picomatch: 4.0.4 - std-env: 4.0.0 - tinybench: 2.9.0 - tinyexec: 1.0.4 - tinyglobby: 0.2.15 - tinyrainbow: 3.1.0 - vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) - why-is-node-running: 2.3.0 - optionalDependencies: - '@opentelemetry/api': 1.9.0 - '@types/node': 24.10.1 - '@vitest/browser-playwright': 4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) - jsdom: 26.1.0 - transitivePeerDependencies: - - msw - vitest@4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): dependencies: '@vitest/expect': 4.1.2 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 141f90b88..64d083751 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -12,6 +12,7 @@ catalog: archunit: ^2.1.63 esbuild: 0.27.4 graphql: ^16.10.0 + '@testing-library/react': ^16.3.0 jsdom: ^26.1.0 mongodb: 6.18.0 mongoose: 8.17.0 From 7a40958c7d3ad6b22755c04e0758dcb4616ccf94 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Thu, 30 Apr 2026 19:35:21 +0530 Subject: [PATCH 24/88] refactor: update entry points and project patterns in knip.json and package.json --- knip.json | 14 ++++++-------- packages/ocom/ui-staff-route-shared/package.json | 4 +--- pnpm-workspace.yaml | 1 - 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/knip.json b/knip.json index 7c4a4a5e3..f23bf85cb 100644 --- a/knip.json +++ b/knip.json @@ -56,19 +56,19 @@ "project": ["src/**/*.ts"] }, "packages/ocom/ui-community-route-shared": { - "entry": ["src/components/index.ts"], - "project": ["src/components/**/*.{ts,tsx}"] + "entry": ["src/index.tsx"], + "project": ["src/**/*.{ts,tsx}"] }, "packages/ocom/ui-community-route-admin": { - "entry": ["src/index.ts", "src/index.tsx"], + "entry": ["src/index.tsx"], "project": ["src/**/*.{ts,tsx}"] }, "packages/ocom/ui-community-route-*": { - "entry": ["src/index.ts"], + "entry": ["src/index.tsx"], "project": ["src/**/*.{ts,tsx}"] }, "packages/ocom/ui-staff-route-*": { - "entry": ["src/index.ts"], + "entry": ["src/index.tsx"], "project": ["src/**/*.{ts,tsx}"] }, "packages/ocom/*": { @@ -121,9 +121,7 @@ "@graphql-typed-document-node/core", "@vitest/coverage-v8", "ts-scope-trimmer-plugin", - "chrome-devtools-mcp", - "storybook-addon-apollo-client", - "tailwindcss" + "chrome-devtools-mcp" ], "ignoreBinaries": ["func"] } diff --git a/packages/ocom/ui-staff-route-shared/package.json b/packages/ocom/ui-staff-route-shared/package.json index 72bc99641..ea9b6d319 100644 --- a/packages/ocom/ui-staff-route-shared/package.json +++ b/packages/ocom/ui-staff-route-shared/package.json @@ -25,8 +25,6 @@ "jsdom": "catalog:", "vite": "catalog:", "vitest": "catalog:", - "typescript": "catalog:", - "react-router-dom": "catalog:", - "@testing-library/react": "catalog:" + "typescript": "catalog:" } } diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 64d083751..141f90b88 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -12,7 +12,6 @@ catalog: archunit: ^2.1.63 esbuild: 0.27.4 graphql: ^16.10.0 - '@testing-library/react': ^16.3.0 jsdom: ^26.1.0 mongodb: 6.18.0 mongoose: 8.17.0 From 47c125eac1713476e02fb4d62714f766f7603dad Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Thu, 30 Apr 2026 19:38:58 +0530 Subject: [PATCH 25/88] refactor: remove unused dependencies from pnpm-lock.yaml --- pnpm-lock.yaml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6e562bf91..1537da8a2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,9 +12,6 @@ catalogs: '@azure/functions': specifier: 4.11.0 version: 4.11.0 - '@testing-library/react': - specifier: ^16.3.0 - version: 16.3.0 '@types/node': specifier: ^22.19.5 version: 22.19.15 @@ -1973,9 +1970,6 @@ importers: '@cellix/config-vitest': specifier: workspace:* version: link:../../cellix/config-vitest - '@testing-library/react': - specifier: 'catalog:' - version: 16.3.0(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@types/react': specifier: ^19.1.11 version: 19.2.7 @@ -1985,9 +1979,6 @@ importers: jsdom: specifier: 'catalog:' version: 26.1.0 - react-router-dom: - specifier: 'catalog:' - version: 7.12.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) typescript: specifier: 'catalog:' version: 6.0.3 From c204df3fd0bb64aed09d673ed09f24f8b3fbbeb7 Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Thu, 30 Apr 2026 11:00:31 -0400 Subject: [PATCH 26/88] fix: correct token property name in ThemeProvider and adjust children rendering --- apps/ui-staff/src/contexts/theme-context.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ui-staff/src/contexts/theme-context.tsx b/apps/ui-staff/src/contexts/theme-context.tsx index 62e172f9f..e70cc0e90 100644 --- a/apps/ui-staff/src/contexts/theme-context.tsx +++ b/apps/ui-staff/src/contexts/theme-context.tsx @@ -113,7 +113,7 @@ export const ThemeProvider = ({ children }: { children: ReactNode }) => { } else { const valueToSet = { type: 'light', - tokens: theme.defaultSeed, + token: theme.defaultSeed, hardCodedTokens: { textColor: '#000000', backgroundColor: '#ffffff', @@ -161,7 +161,7 @@ export const ThemeProvider = ({ children }: { children: ReactNode }) => { Hit Cmd+Shift+K to hide

- {children} + {children} ); From fedc557d2504453a23e8b77809de30da7b9fb6be Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Thu, 30 Apr 2026 11:05:46 -0400 Subject: [PATCH 27/88] fix: correct typo in OIDCConfig type and instance from 'noonce' to 'nonce' --- apps/ui-community/src/config/oidc-config.tsx | 4 ++-- apps/ui-staff/src/config/oidc-config.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/ui-community/src/config/oidc-config.tsx b/apps/ui-community/src/config/oidc-config.tsx index 8ec5d17fd..f86713c0a 100644 --- a/apps/ui-community/src/config/oidc-config.tsx +++ b/apps/ui-community/src/config/oidc-config.tsx @@ -3,7 +3,7 @@ type OIDCConfig = { client_id: string; redirect_uri: string; code_verifier: boolean; - noonce: boolean; + nonce: boolean; response_type: string; scope: string; onSigninCallback: () => void; @@ -20,7 +20,7 @@ export const oidcConfig: OIDCConfig = { // biome-ignore lint:useLiteralKeys import.meta.env['VITE_AAD_B2C_REDIRECT_URI'] ?? 'https://ownercommunity.localhost/auth-redirect', code_verifier: true, - noonce: true, + nonce: true, response_type: 'code', // biome-ignore lint:useLiteralKeys scope: import.meta.env['VITE_AAD_B2C_ACCOUNT_SCOPES'], diff --git a/apps/ui-staff/src/config/oidc-config.tsx b/apps/ui-staff/src/config/oidc-config.tsx index fc0f34dfb..45c52db39 100644 --- a/apps/ui-staff/src/config/oidc-config.tsx +++ b/apps/ui-staff/src/config/oidc-config.tsx @@ -3,7 +3,7 @@ type OIDCConfig = { client_id: string; redirect_uri: string; code_verifier: boolean; - noonce: boolean; + nonce: boolean; response_type: string; scope: string; onSigninCallback: () => void; @@ -20,7 +20,7 @@ export const oidcConfig: OIDCConfig = { // biome-ignore lint:useLiteralKeys import.meta.env['VITE_AAD_B2C_STAFF_REDIRECT_URI'] ?? 'https://staff.ownercommunity.localhost:1355/auth-redirect', code_verifier: true, - noonce: true, + nonce: true, response_type: 'code', // biome-ignore lint:useLiteralKeys scope: import.meta.env['VITE_AAD_B2C_STAFF_SCOPES'] ?? 'openid', From 29cdc6f9fed5dccfc1f92a70c694db6504a222ee Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Thu, 30 Apr 2026 12:10:12 -0400 Subject: [PATCH 28/88] refactor: update environment variable references and improve type definitions --- apps/ui-community/src/config/oidc-config.tsx | 2 +- .../ui/organisms/apollo-connection/apollo-client-links.tsx | 4 ++-- apps/ui-staff/src/contexts/theme-context.tsx | 2 +- packages/ocom/ui-staff-route-root/src/components/header.tsx | 1 + packages/ocom/ui-staff-route-root/src/pages/login-page.tsx | 1 + 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/ui-community/src/config/oidc-config.tsx b/apps/ui-community/src/config/oidc-config.tsx index f86713c0a..2217771d2 100644 --- a/apps/ui-community/src/config/oidc-config.tsx +++ b/apps/ui-community/src/config/oidc-config.tsx @@ -23,7 +23,7 @@ export const oidcConfig: OIDCConfig = { nonce: true, response_type: 'code', // biome-ignore lint:useLiteralKeys - scope: import.meta.env['VITE_AAD_B2C_ACCOUNT_SCOPES'], + scope: import.meta.env['VITE_AAD_B2C_ACCOUNT_SCOPES'] ?? 'openid', onSigninCallback: (): void => { console.log('onSigninCallback'); globalThis.history.replaceState({}, document.title, globalThis.location.pathname); diff --git a/apps/ui-staff/src/components/ui/organisms/apollo-connection/apollo-client-links.tsx b/apps/ui-staff/src/components/ui/organisms/apollo-connection/apollo-client-links.tsx index 89e745862..dcf8307f4 100644 --- a/apps/ui-staff/src/components/ui/organisms/apollo-connection/apollo-client-links.tsx +++ b/apps/ui-staff/src/components/ui/organisms/apollo-connection/apollo-client-links.tsx @@ -35,9 +35,9 @@ export const ApolloLinkToAddAuthHeader = (auth: AuthContextProps): ApolloLink => if (!access_token && typeof globalThis !== 'undefined' && !import.meta.env.PROD) { try { // biome-ignore lint:useLiteralKeys - const authority = import.meta.env['VITE_AAD_B2C_ACCOUNT_AUTHORITY'] ?? ''; + const authority = import.meta.env['VITE_AAD_B2C_STAFF_AUTHORITY'] ?? ''; // biome-ignore lint:useLiteralKeys - const client_id = import.meta.env['VITE_AAD_B2C_ACCOUNT_CLIENTID'] ?? ''; + const client_id = import.meta.env['VITE_AAD_B2C_STAFF_CLIENTID'] ?? ''; const storageKey = `oidc.user:${authority}:${client_id}`; const raw = globalThis.sessionStorage.getItem(storageKey) ?? globalThis.localStorage.getItem(storageKey); if (raw) { diff --git a/apps/ui-staff/src/contexts/theme-context.tsx b/apps/ui-staff/src/contexts/theme-context.tsx index e70cc0e90..51be6f9c2 100644 --- a/apps/ui-staff/src/contexts/theme-context.tsx +++ b/apps/ui-staff/src/contexts/theme-context.tsx @@ -13,7 +13,7 @@ interface ThemeContextType { type: string; } | undefined; - setTheme: (tokens: Partial, types: string) => void; + setTheme: (tokens: Partial, type: string) => void; } export const ThemeContext = createContext({ diff --git a/packages/ocom/ui-staff-route-root/src/components/header.tsx b/packages/ocom/ui-staff-route-root/src/components/header.tsx index 065c684bc..4d6273a36 100644 --- a/packages/ocom/ui-staff-route-root/src/components/header.tsx +++ b/packages/ocom/ui-staff-route-root/src/components/header.tsx @@ -1,5 +1,6 @@ import { Button, theme } from 'antd'; import styles from './header.module.css'; +import type React from 'react' export const Header: React.FC = () => { const handleLogin = () => { diff --git a/packages/ocom/ui-staff-route-root/src/pages/login-page.tsx b/packages/ocom/ui-staff-route-root/src/pages/login-page.tsx index 651e14bcb..7fd0a50fd 100644 --- a/packages/ocom/ui-staff-route-root/src/pages/login-page.tsx +++ b/packages/ocom/ui-staff-route-root/src/pages/login-page.tsx @@ -1,4 +1,5 @@ import { Typography } from 'antd'; +import type React from 'react' const { Text } = Typography; From ba591832101a4b74ee018602fdc739c64a974157 Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Thu, 30 Apr 2026 14:17:30 -0400 Subject: [PATCH 29/88] format --- apps/ui-community/src/config/oidc-config.tsx | 2 +- .../apollo-client-links.spec.ts | 6 +++--- .../src/contexts/theme-context.test.tsx | 20 ------------------- apps/ui-staff/src/contexts/theme-context.tsx | 20 +++++++++---------- 4 files changed, 14 insertions(+), 34 deletions(-) delete mode 100644 apps/ui-staff/src/contexts/theme-context.test.tsx diff --git a/apps/ui-community/src/config/oidc-config.tsx b/apps/ui-community/src/config/oidc-config.tsx index 2217771d2..515c12cd3 100644 --- a/apps/ui-community/src/config/oidc-config.tsx +++ b/apps/ui-community/src/config/oidc-config.tsx @@ -23,7 +23,7 @@ export const oidcConfig: OIDCConfig = { nonce: true, response_type: 'code', // biome-ignore lint:useLiteralKeys - scope: import.meta.env['VITE_AAD_B2C_ACCOUNT_SCOPES'] ?? 'openid', + scope: import.meta.env['VITE_AAD_B2C_ACCOUNT_SCOPES'] ?? 'openid', onSigninCallback: (): void => { console.log('onSigninCallback'); globalThis.history.replaceState({}, document.title, globalThis.location.pathname); diff --git a/apps/ui-staff/src/components/ui/organisms/apollo-connection/apollo-client-links.spec.ts b/apps/ui-staff/src/components/ui/organisms/apollo-connection/apollo-client-links.spec.ts index 5111f862c..b9e39a790 100644 --- a/apps/ui-staff/src/components/ui/organisms/apollo-connection/apollo-client-links.spec.ts +++ b/apps/ui-staff/src/components/ui/organisms/apollo-connection/apollo-client-links.spec.ts @@ -1,5 +1,5 @@ -import { describe, it, expect } from 'vitest'; import type { Operation } from '@apollo/client'; +import { describe, expect, it } from 'vitest'; import { ApolloLinkToAddCustomHeader } from './apollo-client-links'; describe('ApolloLinkToAddCustomHeader', () => { @@ -10,8 +10,8 @@ describe('ApolloLinkToAddCustomHeader', () => { type OpContext = Record & { headers?: Record }; type MockOperation = { _context: OpContext; - setContext: ((fnOrObj: ((prev: OpContext) => OpContext) | OpContext) => void); - getContext: (() => OpContext); + setContext: (fnOrObj: ((prev: OpContext) => OpContext) | OpContext) => void; + getContext: () => OpContext; operationName: string; query: unknown; variables: unknown; diff --git a/apps/ui-staff/src/contexts/theme-context.test.tsx b/apps/ui-staff/src/contexts/theme-context.test.tsx deleted file mode 100644 index d84b34725..000000000 --- a/apps/ui-staff/src/contexts/theme-context.test.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import React from 'react'; -import { renderToString } from 'react-dom/server'; -import { ThemeProvider, ThemeContext } from './theme-context'; - -describe('ThemeContext', () => { - it('provides currentTokens and setTheme without throwing', () => { - const Consumer = () => { - const ctx = React.useContext(ThemeContext as unknown as { currentTokens?: { type?: string } }); - return React.createElement('div', {}, ctx?.currentTokens?.type || 'no-type'); - }; - - const html = renderToString( - React.createElement(ThemeProvider, {}, React.createElement(Consumer)), - ); - expect(typeof html).toBe('string'); - expect(html.length).toBeGreaterThan(0); - expect(html).toContain('light'); - }); -}); diff --git a/apps/ui-staff/src/contexts/theme-context.tsx b/apps/ui-staff/src/contexts/theme-context.tsx index 51be6f9c2..11bff049b 100644 --- a/apps/ui-staff/src/contexts/theme-context.tsx +++ b/apps/ui-staff/src/contexts/theme-context.tsx @@ -5,13 +5,13 @@ import { createContext, type ReactNode, useCallback, useEffect, useState } from interface ThemeContextType { currentTokens: | { - token: Partial; - hardCodedTokens: { - textColor: string | undefined; - backgroundColor: string | undefined; - }; - type: string; - } + token: Partial; + hardCodedTokens: { + textColor: string | undefined; + backgroundColor: string | undefined; + }; + type: string; + } | undefined; setTheme: (tokens: Partial, type: string) => void; } @@ -160,9 +160,9 @@ export const ThemeProvider = ({ children }: { children: ReactNode }) => {

Hit Cmd+Shift+K to hide

- - {children} - + {children} + + ); }; From a67eb06ea1997c27d64cb41167d24bf074e9b43a Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Thu, 30 Apr 2026 16:00:09 -0400 Subject: [PATCH 30/88] feat: integrate react-oidc-context for authentication in header components --- .../ocom/ui-community-route-root/package.json | 3 +- .../src/components/header.tsx | 15 ++++- .../ui-community-route-root/tsconfig.json | 4 +- .../ocom/ui-staff-route-root/package.json | 63 ++++++++++--------- .../src/components/header.tsx | 18 +++++- .../ocom/ui-staff-route-root/tsconfig.json | 30 ++++----- pnpm-lock.yaml | 6 ++ 7 files changed, 87 insertions(+), 52 deletions(-) diff --git a/packages/ocom/ui-community-route-root/package.json b/packages/ocom/ui-community-route-root/package.json index afbaa34a1..3632bdde8 100644 --- a/packages/ocom/ui-community-route-root/package.json +++ b/packages/ocom/ui-community-route-root/package.json @@ -17,7 +17,8 @@ "dependencies": { "antd": "catalog:", "react": "^19.1.1", - "react-dom": "^19.1.1" + "react-dom": "^19.1.1", + "react-oidc-context": "^3.3.0" }, "devDependencies": { "@cellix/config-typescript": "workspace:*", diff --git a/packages/ocom/ui-community-route-root/src/components/header.tsx b/packages/ocom/ui-community-route-root/src/components/header.tsx index e6c020544..5999bcff1 100644 --- a/packages/ocom/ui-community-route-root/src/components/header.tsx +++ b/packages/ocom/ui-community-route-root/src/components/header.tsx @@ -1,8 +1,21 @@ import { Button, theme } from 'antd'; +import type React from 'react'; +import { useAuth } from 'react-oidc-context'; import styles from './header.module.css'; export const Header: React.FC = () => { - const handleLogin = () => { + const auth = useAuth(); + const handleLogin = async () => { + try { + if (auth?.signinRedirect) { + await auth.signinRedirect(); + return; + } + } catch (_err) { + // swallow and fall back below + } + + // fall back to direct navigation if the OIDC helper is unavailable or fails // biome-ignore lint:useLiteralKeys globalThis.location.href = `${import.meta.env['VITE_AAD_B2C_REDIRECT_URI']}`; }; diff --git a/packages/ocom/ui-community-route-root/tsconfig.json b/packages/ocom/ui-community-route-root/tsconfig.json index 54218e909..e98135a39 100644 --- a/packages/ocom/ui-community-route-root/tsconfig.json +++ b/packages/ocom/ui-community-route-root/tsconfig.json @@ -12,6 +12,6 @@ "noEmit": true, "types": ["vite/client"] }, - "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.d.ts", "src/*.ts", "src/*.tsx"], - "exclude": ["src/**/*.stories.ts", "src/**/*.stories.tsx", "src/**/*.test.ts", "src/**/*.test.tsx"] + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.d.ts"], + "exclude": ["src/**/*.stories.ts", "src/**/*.stories.tsx", "src/**/*.test.ts", "src/**/*.test.tsx", "src/**/*.spec.ts", "src/**/*.spec.tsx"] } diff --git a/packages/ocom/ui-staff-route-root/package.json b/packages/ocom/ui-staff-route-root/package.json index 806b6d0f0..a5247dba1 100644 --- a/packages/ocom/ui-staff-route-root/package.json +++ b/packages/ocom/ui-staff-route-root/package.json @@ -1,33 +1,34 @@ { - "name": "@ocom/ui-staff-route-root", - "version": "0.0.1", - "private": true, - "type": "module", - "exports": { - ".": "./src/index.tsx" - }, - "scripts": { - "prebuild": "pnpm run lint", - "build": "tsgo --noEmit", - "lint": "biome lint", - "test": "vitest run --silent --reporter=dot", - "test:coverage": "vitest run --coverage --silent --reporter=dot", - "test:watch": "vitest" - }, - "dependencies": { - "antd": "catalog:", - "react": "^19.1.1", - "react-dom": "^19.1.1" - }, - "devDependencies": { - "@cellix/config-typescript": "workspace:*", - "@cellix/config-vitest": "workspace:*", - "@types/react": "^19.1.11", - "@types/react-dom": "^19.1.6", - "jsdom": "catalog:", - "storybook": "catalog:", - "vite": "catalog:", - "vitest": "catalog:", - "typescript": "catalog:" - } + "name": "@ocom/ui-staff-route-root", + "version": "0.0.1", + "private": true, + "type": "module", + "exports": { + ".": "./src/index.tsx" + }, + "scripts": { + "prebuild": "pnpm run lint", + "build": "tsgo --noEmit", + "lint": "biome lint", + "test": "vitest run --silent --reporter=dot", + "test:coverage": "vitest run --coverage --silent --reporter=dot", + "test:watch": "vitest" + }, + "dependencies": { + "antd": "catalog:", + "react": "^19.1.1", + "react-dom": "^19.1.1", + "react-oidc-context": "^3.3.0" + }, + "devDependencies": { + "@cellix/config-typescript": "workspace:*", + "@cellix/config-vitest": "workspace:*", + "@types/react": "^19.1.11", + "@types/react-dom": "^19.1.6", + "jsdom": "catalog:", + "storybook": "catalog:", + "vite": "catalog:", + "vitest": "catalog:", + "typescript": "catalog:" + } } diff --git a/packages/ocom/ui-staff-route-root/src/components/header.tsx b/packages/ocom/ui-staff-route-root/src/components/header.tsx index 4d6273a36..00cd20e02 100644 --- a/packages/ocom/ui-staff-route-root/src/components/header.tsx +++ b/packages/ocom/ui-staff-route-root/src/components/header.tsx @@ -1,9 +1,23 @@ import { Button, theme } from 'antd'; +import type React from 'react'; +import { useAuth } from 'react-oidc-context'; import styles from './header.module.css'; -import type React from 'react' export const Header: React.FC = () => { - const handleLogin = () => { + const auth = useAuth(); + const handleLogin = async () => { + // If react-oidc-context is available, prefer its signinRedirect flow so + // the OIDC library manages state and returns to the app correctly. + try { + if (auth?.signinRedirect) { + await auth.signinRedirect(); + return; + } + } catch (_err) { + // swallow and fall back below + } + + // fall back to direct navigation if the OIDC helper is unavailable or fails // biome-ignore lint:useLiteralKeys globalThis.location.href = `${import.meta.env['VITE_AAD_B2C_STAFF_REDIRECT_URI']}`; }; diff --git a/packages/ocom/ui-staff-route-root/tsconfig.json b/packages/ocom/ui-staff-route-root/tsconfig.json index 520d9c6d2..e98135a39 100644 --- a/packages/ocom/ui-staff-route-root/tsconfig.json +++ b/packages/ocom/ui-staff-route-root/tsconfig.json @@ -1,17 +1,17 @@ { - "extends": "@cellix/config-typescript/base", - "compilerOptions": { - "target": "ES2022", - "module": "ESNext", - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "verbatimModuleSyntax": true, - "jsx": "react-jsx", - "lib": ["ES2023", "DOM"], - "skipLibCheck": true, - "noEmit": true, - "types": ["vite/client"] - }, - "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.d.ts"], - "exclude": ["src/**/*.stories.ts", "src/**/*.stories.tsx", "src/**/*.test.ts", "src/**/*.test.tsx"] + "extends": "@cellix/config-typescript/base", + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "jsx": "react-jsx", + "lib": ["ES2023", "DOM"], + "skipLibCheck": true, + "noEmit": true, + "types": ["vite/client"] + }, + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.d.ts"], + "exclude": ["src/**/*.stories.ts", "src/**/*.stories.tsx", "src/**/*.test.ts", "src/**/*.test.tsx", "src/**/*.spec.ts", "src/**/*.spec.tsx"] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1537da8a2..78ca4d6ad 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1615,6 +1615,9 @@ importers: react-dom: specifier: ^19.1.1 version: 19.2.0(react@19.2.0) + react-oidc-context: + specifier: ^3.3.0 + version: 3.3.0(oidc-client-ts@3.4.1)(react@19.2.0) devDependencies: '@cellix/config-typescript': specifier: workspace:* @@ -1929,6 +1932,9 @@ importers: react-dom: specifier: ^19.1.1 version: 19.2.0(react@19.2.0) + react-oidc-context: + specifier: ^3.3.0 + version: 3.3.0(oidc-client-ts@3.4.1)(react@19.2.0) devDependencies: '@cellix/config-typescript': specifier: workspace:* From b4a3b77e01b2adf262210438423f0b5112f93d94 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Apr 2026 20:48:14 +0000 Subject: [PATCH 31/88] Changes before error encountered Agent-Logs-Url: https://github.com/CellixJs/cellixjs/sessions/b332a369-259e-49fd-b45e-84b75c4b82b5 Co-authored-by: ttrang-nguyen <126544378+ttrang-nguyen@users.noreply.github.com> --- apps/ui-community/src/config/oidc-config.tsx | 1 - apps/ui-community/src/contexts/theme-context.tsx | 16 +++++++++++++--- apps/ui-staff/src/contexts/theme-context.tsx | 16 +++++++++++++--- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/apps/ui-community/src/config/oidc-config.tsx b/apps/ui-community/src/config/oidc-config.tsx index 515c12cd3..c6df18f9d 100644 --- a/apps/ui-community/src/config/oidc-config.tsx +++ b/apps/ui-community/src/config/oidc-config.tsx @@ -25,7 +25,6 @@ export const oidcConfig: OIDCConfig = { // biome-ignore lint:useLiteralKeys scope: import.meta.env['VITE_AAD_B2C_ACCOUNT_SCOPES'] ?? 'openid', onSigninCallback: (): void => { - console.log('onSigninCallback'); globalThis.history.replaceState({}, document.title, globalThis.location.pathname); const redirectToPath = globalThis.sessionStorage.getItem('redirectTo'); if (redirectToPath) { diff --git a/apps/ui-community/src/contexts/theme-context.tsx b/apps/ui-community/src/contexts/theme-context.tsx index 17e164d2a..fc4711d8f 100644 --- a/apps/ui-community/src/contexts/theme-context.tsx +++ b/apps/ui-community/src/contexts/theme-context.tsx @@ -97,7 +97,17 @@ export const ThemeProvider = ({ children }: { children: ReactNode }) => { }, []); useEffect(() => { - const extractFromLocal = JSON.parse(localStorage.getItem('themeProp') || '{}'); + type StoredTheme = { + type?: 'light' | 'dark' | 'custom'; + hardCodedTokens?: { textColor?: string; backgroundColor?: string }; + token?: unknown; + }; + let extractFromLocal: StoredTheme = {}; + try { + extractFromLocal = JSON.parse(localStorage.getItem('themeProp') ?? '{}') as StoredTheme; + } catch { + localStorage.removeItem('themeProp'); + } if (extractFromLocal && extractFromLocal.type === 'dark') { setTheme( { @@ -119,8 +129,8 @@ export const ThemeProvider = ({ children }: { children: ReactNode }) => { } else if (extractFromLocal && extractFromLocal.type === 'custom') { setTheme( { - colorTextBase: extractFromLocal.hardCodedTokens.textColor, - colorBgBase: extractFromLocal.hardCodedTokens.backgroundColor, + colorTextBase: extractFromLocal.hardCodedTokens?.textColor, + colorBgBase: extractFromLocal.hardCodedTokens?.backgroundColor, }, 'custom', ); diff --git a/apps/ui-staff/src/contexts/theme-context.tsx b/apps/ui-staff/src/contexts/theme-context.tsx index 11bff049b..0af0e12ee 100644 --- a/apps/ui-staff/src/contexts/theme-context.tsx +++ b/apps/ui-staff/src/contexts/theme-context.tsx @@ -82,7 +82,17 @@ export const ThemeProvider = ({ children }: { children: ReactNode }) => { }, []); useEffect(() => { - const extractFromLocal = JSON.parse(localStorage.getItem('themeProp') || '{}'); + type StoredTheme = { + type?: 'light' | 'dark' | 'custom'; + hardCodedTokens?: { textColor?: string; backgroundColor?: string }; + token?: unknown; + }; + let extractFromLocal: StoredTheme = {}; + try { + extractFromLocal = JSON.parse(localStorage.getItem('themeProp') ?? '{}') as StoredTheme; + } catch { + localStorage.removeItem('themeProp'); + } if (extractFromLocal && extractFromLocal.type === 'dark') { setTheme( { @@ -104,8 +114,8 @@ export const ThemeProvider = ({ children }: { children: ReactNode }) => { } else if (extractFromLocal && extractFromLocal.type === 'custom') { setTheme( { - colorTextBase: extractFromLocal.hardCodedTokens.textColor, - colorBgBase: extractFromLocal.hardCodedTokens.backgroundColor, + colorTextBase: extractFromLocal.hardCodedTokens?.textColor, + colorBgBase: extractFromLocal.hardCodedTokens?.backgroundColor, }, 'custom', ); From 13b4897d3ed37d822904bec19a7800c4e043ec4d Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Fri, 1 May 2026 18:44:59 +0530 Subject: [PATCH 32/88] test: add unit tests for resolver-builder module and mergeResolvers functionality --- .../schema/builder/resolver-builder.test.ts | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 packages/ocom/graphql/src/schema/builder/resolver-builder.test.ts diff --git a/packages/ocom/graphql/src/schema/builder/resolver-builder.test.ts b/packages/ocom/graphql/src/schema/builder/resolver-builder.test.ts new file mode 100644 index 000000000..6b43ad53c --- /dev/null +++ b/packages/ocom/graphql/src/schema/builder/resolver-builder.test.ts @@ -0,0 +1,93 @@ +import { describe, expect, it, vi } from 'vitest'; + +// Hoisted mocks — resolved before any static import of the module under test + +vi.mock('@graphql-tools/merge', () => ({ + mergeResolvers: vi.fn().mockReturnValue({ + Query: { + hello: vi.fn(), + currentCommunity: vi.fn(), + endUserRole: vi.fn(), + }, + Mutation: { + communityCreate: vi.fn(), + }, + }), +})); + +vi.mock('./resolver-manifest.generated.ts', () => ({ + ocomGraphqlResolvers: [ + { Query: { hello: vi.fn() } }, + { Query: { currentCommunity: vi.fn() }, Mutation: { communityCreate: vi.fn() } }, + ], + ocomGraphqlPermissions: [], +})); + +vi.mock('../types/end-user-role.resolvers.ts', () => ({ + default: { Query: { endUserRole: vi.fn() } }, +})); + +import { mergeResolvers } from '@graphql-tools/merge'; +import { permissions, resolvers } from './resolver-builder.ts'; + +describe('resolver-builder', () => { + describe('resolvers — mergeResolverModules with non-empty modules', () => { + it('passes all resolver modules to mergeResolvers', () => { + expect(vi.mocked(mergeResolvers)).toHaveBeenCalledOnce(); + const [calledModules] = vi.mocked(mergeResolvers).mock.calls[0] ?? []; + expect(Array.isArray(calledModules)).toBe(true); + expect((calledModules as unknown[]).length).toBeGreaterThan(0); + }); + + it('returns the merged object produced by mergeResolvers', () => { + expect(resolvers).toBeDefined(); + expect(typeof resolvers).toBe('object'); + }); + + it('exposes Query resolvers from the merged result', () => { + expect(resolvers.Query).toBeDefined(); + expect(typeof resolvers.Query?.hello).toBe('function'); + expect(typeof resolvers.Query?.currentCommunity).toBe('function'); + expect(typeof resolvers.Query?.endUserRole).toBe('function'); + }); + + it('exposes Mutation resolvers from the merged result', () => { + expect(resolvers.Mutation).toBeDefined(); + expect(typeof resolvers.Mutation?.communityCreate).toBe('function'); + }); + }); + + describe('permissions — mergeResolverModules with empty modules', () => { + it('returns an empty object when ocomGraphqlPermissions is empty', () => { + expect(permissions).toEqual({}); + }); + + it('does not invoke mergeResolvers for an empty permissions array', () => { + // mergeResolvers is called exactly once: for resolvers (non-empty), never for permissions (empty) + expect(vi.mocked(mergeResolvers)).toHaveBeenCalledTimes(1); + }); + }); + + describe('mergeResolverModules — non-empty permissions path', () => { + it('calls mergeResolvers and returns its result when permission modules are present', async () => { + vi.resetModules(); + + const permResolver = { Query: { permCheck: vi.fn() } }; + const mergeResolversMock = vi.fn().mockReturnValue(permResolver); + + vi.doMock('@graphql-tools/merge', () => ({ mergeResolvers: mergeResolversMock })); + vi.doMock('./resolver-manifest.generated.ts', () => ({ + ocomGraphqlResolvers: [], + ocomGraphqlPermissions: [permResolver], + })); + vi.doMock('../types/end-user-role.resolvers.ts', () => ({ default: {} })); + + const { permissions: dynamicPermissions } = await import('./resolver-builder.ts'); + + expect(mergeResolversMock).toHaveBeenCalled(); + expect(dynamicPermissions).toEqual(permResolver); + + vi.resetModules(); + }); + }); +}); From 93df96eb3ca6397af1295d80f725d0e9c5c384d1 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Fri, 1 May 2026 19:21:42 +0530 Subject: [PATCH 33/88] Renaming: ui-community-route-shared -> ui-community-shared ui-staff-route-shared -> ui-staff-shared ui-components -> ui-shared --- .github/agents/planner.agent.md | 2 +- .github/skills/plan-feature/SKILL.md | 2 +- TURBOREPO.md | 2 +- .../decisions/0027-typescript-6-upgrade.md | 2 +- apps/ui-community/tsconfig.app.json | 2 +- apps/ui-staff/package.json | 2 +- apps/ui-staff/src/App.tsx | 2 +- codegen.yml | 10 +-- knip.json | 2 +- .../src/dependency-rules.test.ts | 4 +- packages/cellix/ui-core/manifest.md | 2 +- .../archunit-tests/src/code-quality.test.ts | 4 +- .../src/dependency-rules.test.ts | 6 +- .../src/naming-conventions.test.ts | 2 +- packages/ocom/archunit-tests/turbo.json | 2 +- .../ui-community-route-accounts/package.json | 2 +- .../src/section-layout.tsx | 2 +- .../ui-community-route-admin/package.json | 4 +- .../ui-community-route-admin/src/index.tsx | 2 +- .../src/pages/members-detail.tsx | 2 +- .../src/pages/members-profile.tsx | 2 +- .../src/section-layout.container.tsx | 2 +- .../src/section-layout.tsx | 2 +- .../.storybook/main.ts | 0 .../.storybook/preview.tsx | 0 .../.storybook/vitest.setup.ts | 0 .../package.json | 4 +- .../member-profile.container.graphql | 0 .../components/member-profile.container.tsx | 0 .../src/components/member-profile.stories.tsx | 0 .../src/components/member-profile.tsx | 0 .../src/components/menu-component.stories.tsx | 0 .../src/components/menu-component.tsx | 2 +- .../src/index.tsx | 0 .../tsconfig.json | 0 .../tsconfig.vitest.json | 0 .../vitest.config.ts | 0 .../{ui-components => ui-shared}/.gitignore | 0 .../.storybook/main.ts | 0 .../.storybook/preview.tsx | 2 +- .../.storybook/vitest.setup.ts | 0 .../{ui-components => ui-shared}/README.md | 30 ++++----- .../{ui-components => ui-shared}/package.json | 2 +- .../src/components/index.ts | 0 .../src/components/molecules/README.md | 2 +- .../src/components/molecules/index.tsx | 0 .../molecules/logged-in-user/index.tsx | 0 .../logged-in-user/logged-in-user.stories.tsx | 0 .../logged-in-user/logged-in.stories.tsx | 0 .../molecules/logged-in-user/logged-in.tsx | 0 .../logged-in-user/not-logged-in.stories.tsx | 0 .../logged-in-user/not-logged-in.tsx | 0 .../src/components/organisms/README.md | 2 +- ...communities-dropdown.container.stories.tsx | 0 .../communities-dropdown.container.tsx | 0 .../communities-dropdown.stories.tsx | 0 .../dropdown-menu/communities-dropdown.tsx | 0 .../header/handle-logout.stories.tsx | 0 .../organisms/header/handle-logout.tsx | 0 .../organisms/header/index.module.css | 0 .../src/components/organisms/header/index.tsx | 0 ...ed-in-user-community.container.stories.tsx | 0 .../logged-in-user-community.container.tsx | 0 .../logged-in-user-community.stories.tsx | 0 .../header/logged-in-user-community.tsx | 0 .../logged-in-user-root.container.stories.tsx | 0 .../header/logged-in-user-root.container.tsx | 0 .../header/logged-in-user-root.stories.tsx | 0 .../organisms/header/logged-in-user-root.tsx | 0 .../header/logged-in-user.container.graphql | 0 .../logged-in-user.container.stories.tsx | 0 .../header/logged-in-user.container.tsx | 0 .../src/components/organisms/index.tsx | 0 .../navigation/menu-component.stories.tsx | 0 .../organisms/navigation/menu-component.tsx | 0 .../organisms/vertical-tabs/index.stories.tsx | 0 .../organisms/vertical-tabs/index.tsx | 0 .../{ui-components => ui-shared}/src/index.ts | 0 .../tsconfig.json | 0 .../tsconfig.vitest.json | 0 .../vitest.config.ts | 0 .../vitest.shims.d.ts | 0 .../package.json | 2 +- .../src/section-layout.tsx | 2 +- .../ocom/ui-staff-route-finance/package.json | 2 +- .../src/section-layout.tsx | 2 +- .../ui-staff-route-tech-admin/package.json | 2 +- .../src/section-layout.tsx | 2 +- .../package.json | 2 +- .../src/section-layout.tsx | 2 +- .../package.json | 2 +- .../src/index.tsx | 0 .../src/section-layout.tsx | 0 .../src/staff-route-shell.tsx | 0 .../src/vite-env.d.ts | 0 .../tsconfig.json | 0 .../vitest.config.ts | 0 pnpm-lock.yaml | 64 +++++++++---------- sonar-project.properties | 4 +- 99 files changed, 97 insertions(+), 97 deletions(-) rename packages/ocom/{ui-community-route-shared => ui-community-shared}/.storybook/main.ts (100%) rename packages/ocom/{ui-community-route-shared => ui-community-shared}/.storybook/preview.tsx (100%) rename packages/ocom/{ui-community-route-shared => ui-community-shared}/.storybook/vitest.setup.ts (100%) rename packages/ocom/{ui-community-route-shared => ui-community-shared}/package.json (93%) rename packages/ocom/{ui-community-route-shared => ui-community-shared}/src/components/member-profile.container.graphql (100%) rename packages/ocom/{ui-community-route-shared => ui-community-shared}/src/components/member-profile.container.tsx (100%) rename packages/ocom/{ui-community-route-shared => ui-community-shared}/src/components/member-profile.stories.tsx (100%) rename packages/ocom/{ui-community-route-shared => ui-community-shared}/src/components/member-profile.tsx (100%) rename packages/ocom/{ui-community-route-shared => ui-community-shared}/src/components/menu-component.stories.tsx (100%) rename packages/ocom/{ui-community-route-shared => ui-community-shared}/src/components/menu-component.tsx (64%) rename packages/ocom/{ui-community-route-shared => ui-community-shared}/src/index.tsx (100%) rename packages/ocom/{ui-community-route-shared => ui-community-shared}/tsconfig.json (100%) rename packages/ocom/{ui-community-route-shared => ui-community-shared}/tsconfig.vitest.json (100%) rename packages/ocom/{ui-community-route-shared => ui-community-shared}/vitest.config.ts (100%) rename packages/ocom/{ui-components => ui-shared}/.gitignore (100%) rename packages/ocom/{ui-components => ui-shared}/.storybook/main.ts (100%) rename packages/ocom/{ui-components => ui-shared}/.storybook/preview.tsx (95%) rename packages/ocom/{ui-components => ui-shared}/.storybook/vitest.setup.ts (100%) rename packages/ocom/{ui-components => ui-shared}/README.md (87%) rename packages/ocom/{ui-components => ui-shared}/package.json (98%) rename packages/ocom/{ui-components => ui-shared}/src/components/index.ts (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/molecules/README.md (97%) rename packages/ocom/{ui-components => ui-shared}/src/components/molecules/index.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/molecules/logged-in-user/index.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/molecules/logged-in-user/logged-in-user.stories.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/molecules/logged-in-user/logged-in.stories.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/molecules/logged-in-user/logged-in.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/molecules/logged-in-user/not-logged-in.stories.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/molecules/logged-in-user/not-logged-in.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/organisms/README.md (96%) rename packages/ocom/{ui-components => ui-shared}/src/components/organisms/dropdown-menu/communities-dropdown.container.stories.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/organisms/dropdown-menu/communities-dropdown.container.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/organisms/dropdown-menu/communities-dropdown.stories.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/organisms/dropdown-menu/communities-dropdown.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/organisms/header/handle-logout.stories.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/organisms/header/handle-logout.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/organisms/header/index.module.css (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/organisms/header/index.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/organisms/header/logged-in-user-community.container.stories.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/organisms/header/logged-in-user-community.container.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/organisms/header/logged-in-user-community.stories.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/organisms/header/logged-in-user-community.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/organisms/header/logged-in-user-root.container.stories.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/organisms/header/logged-in-user-root.container.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/organisms/header/logged-in-user-root.stories.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/organisms/header/logged-in-user-root.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/organisms/header/logged-in-user.container.graphql (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/organisms/header/logged-in-user.container.stories.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/organisms/header/logged-in-user.container.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/organisms/index.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/organisms/navigation/menu-component.stories.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/organisms/navigation/menu-component.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/organisms/vertical-tabs/index.stories.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/components/organisms/vertical-tabs/index.tsx (100%) rename packages/ocom/{ui-components => ui-shared}/src/index.ts (100%) rename packages/ocom/{ui-components => ui-shared}/tsconfig.json (100%) rename packages/ocom/{ui-components => ui-shared}/tsconfig.vitest.json (100%) rename packages/ocom/{ui-components => ui-shared}/vitest.config.ts (100%) rename packages/ocom/{ui-components => ui-shared}/vitest.shims.d.ts (100%) rename packages/ocom/{ui-staff-route-shared => ui-staff-shared}/package.json (94%) rename packages/ocom/{ui-staff-route-shared => ui-staff-shared}/src/index.tsx (100%) rename packages/ocom/{ui-staff-route-shared => ui-staff-shared}/src/section-layout.tsx (100%) rename packages/ocom/{ui-staff-route-shared => ui-staff-shared}/src/staff-route-shell.tsx (100%) rename packages/ocom/{ui-staff-route-shared => ui-staff-shared}/src/vite-env.d.ts (100%) rename packages/ocom/{ui-staff-route-shared => ui-staff-shared}/tsconfig.json (100%) rename packages/ocom/{ui-staff-route-shared => ui-staff-shared}/vitest.config.ts (100%) diff --git a/.github/agents/planner.agent.md b/.github/agents/planner.agent.md index 689eb93af..d2409bba0 100644 --- a/.github/agents/planner.agent.md +++ b/.github/agents/planner.agent.md @@ -122,7 +122,7 @@ Write the plan as a structured markdown file: ### Package Dependency Order ``` @cellix/domain-seedwork → @ocom/domain → @ocom/persistence → @ocom/graphql → @apps/api -@cellix/ui-core → @ocom/ui-components → @ocom/ui-community-route-* → @apps/ui-community +@cellix/ui-core → @ocom/ui-shared → @ocom/ui-community-route-* → @apps/ui-community ``` ### Bounded Context Structure diff --git a/.github/skills/plan-feature/SKILL.md b/.github/skills/plan-feature/SKILL.md index dfda8f667..96fd2d309 100644 --- a/.github/skills/plan-feature/SKILL.md +++ b/.github/skills/plan-feature/SKILL.md @@ -28,7 +28,7 @@ Reusable procedure for planning a new feature or significant change. - Map the change to the package dependency order: ``` @cellix/domain-seedwork -> @ocom/domain -> @ocom/persistence -> @ocom/graphql -> @apps/api - @cellix/ui-core -> @ocom/ui-components -> @ocom/ui-community-route-* -> @apps/ui-community + @cellix/ui-core -> @ocom/ui-shared -> @ocom/ui-community-route-* -> @apps/ui-community ``` ### 3. Identify Instruction Files diff --git a/TURBOREPO.md b/TURBOREPO.md index 5a1f16917..cef8a591d 100644 --- a/TURBOREPO.md +++ b/TURBOREPO.md @@ -14,7 +14,7 @@ The CellixJS monorepo uses Turborepo to: ### Frontend Packages - `ui-community` - Community UI application -- `ui-components` - Shared UI components +- `ui-shared` - Shared UI components - `cellix-ui-core` - Core UI library ### Backend Packages diff --git a/apps/docs/docs/decisions/0027-typescript-6-upgrade.md b/apps/docs/docs/decisions/0027-typescript-6-upgrade.md index d9d91b8a0..dfc219214 100644 --- a/apps/docs/docs/decisions/0027-typescript-6-upgrade.md +++ b/apps/docs/docs/decisions/0027-typescript-6-upgrade.md @@ -66,7 +66,7 @@ TypeScript 6.0 merges `lib.dom.iterable.d.ts` and `lib.dom.asynciterable.d.ts` i - `packages/cellix/ui-core/tsconfig.json` - `apps/ui-community/tsconfig.json` -- `packages/ocom/ui-components/tsconfig.json` +- `packages/ocom/ui-shared/tsconfig.json` ### 4. `apps/docs` tsconfig: `baseUrl` removed, `ignoreDeprecations: "6.0"` added diff --git a/apps/ui-community/tsconfig.app.json b/apps/ui-community/tsconfig.app.json index 31e16117e..2ae9dfded 100644 --- a/apps/ui-community/tsconfig.app.json +++ b/apps/ui-community/tsconfig.app.json @@ -24,5 +24,5 @@ "noUncheckedSideEffectImports": true }, "include": ["src"], - "references": [{ "path": "../../packages/cellix/ui-core" }, { "path": "../../packages/ocom/ui-components" }] + "references": [{ "path": "../../packages/cellix/ui-core" }, { "path": "../../packages/ocom/ui-shared" }] } diff --git a/apps/ui-staff/package.json b/apps/ui-staff/package.json index d91d31c91..e1a705536 100644 --- a/apps/ui-staff/package.json +++ b/apps/ui-staff/package.json @@ -26,7 +26,7 @@ "@ocom/ui-staff-route-user-management": "workspace:*", "@ocom/ui-staff-route-finance": "workspace:*", "@ocom/ui-staff-route-tech-admin": "workspace:*", - "@ocom/ui-staff-route-shared": "workspace:*", + "@ocom/ui-staff-shared": "workspace:*", "antd": "catalog:", "apollo-link-rest": "^0.9.0", "less": "^4.4.0", diff --git a/apps/ui-staff/src/App.tsx b/apps/ui-staff/src/App.tsx index 7b2e2f139..8ae188208 100644 --- a/apps/ui-staff/src/App.tsx +++ b/apps/ui-staff/src/App.tsx @@ -2,7 +2,7 @@ import { RequireAuth } from '@cellix/ui-core'; import { Root } from '@ocom/ui-staff-route-root'; import { Root as CommunityManagement } from '@ocom/ui-staff-route-community-management'; import { Root as Finance } from '@ocom/ui-staff-route-finance'; -import { StaffAuthProvider } from '@ocom/ui-staff-route-shared'; +import { StaffAuthProvider } from '@ocom/ui-staff-shared'; import { Root as TechAdmin } from '@ocom/ui-staff-route-tech-admin'; import { Root as UserManagement } from '@ocom/ui-staff-route-user-management'; import { useAuth } from 'react-oidc-context'; diff --git a/codegen.yml b/codegen.yml index 16c98419f..cd441b5ae 100644 --- a/codegen.yml +++ b/codegen.yml @@ -112,9 +112,9 @@ generates: - typed-document-node # UI community client types - './packages/ocom/ui-community-route-shared/src/generated.tsx': + './packages/ocom/ui-community-shared/src/generated.tsx': documents: - - './packages/ocom/ui-community-route-shared/src/**/**.graphql' + - './packages/ocom/ui-community-shared/src/**/**.graphql' config: withHooks: true withHOC: false @@ -126,9 +126,9 @@ generates: - typescript-operations - typed-document-node - # UI components client types - './packages/ocom/ui-components/src/generated.tsx': - documents: './packages/ocom/ui-components/src/components/**/**.graphql' + # UI shared components client types + './packages/ocom/ui-shared/src/generated.tsx': + documents: './packages/ocom/ui-shared/src/components/**/**.graphql' config: withHooks: true withHOC: false diff --git a/knip.json b/knip.json index f23bf85cb..c6eb0ffde 100644 --- a/knip.json +++ b/knip.json @@ -75,7 +75,7 @@ "entry": ["src/index.ts"], "project": ["src/**/*.ts"] }, - "packages/ocom/ui-components": { + "packages/ocom/ui-shared": { "entry": ["src/index.ts"], "project": ["src/**/*.{ts,tsx}"] } diff --git a/packages/cellix/archunit-tests/src/dependency-rules.test.ts b/packages/cellix/archunit-tests/src/dependency-rules.test.ts index 36f40cd4e..e0454ac5c 100644 --- a/packages/cellix/archunit-tests/src/dependency-rules.test.ts +++ b/packages/cellix/archunit-tests/src/dependency-rules.test.ts @@ -14,12 +14,12 @@ describe('Cellix Dependency Rules', () => { }); describe('Framework Boundaries', () => { - it('ui-core should not depend on ocom ui-components', async () => { + it('ui-core should not depend on ocom ui-shared', async () => { const rule = projectFiles() .inFolder('../ui-core/src') .shouldNot() .dependOnFiles() - .inPath('../../ocom/ui-components/src/**'); + .inPath('../../ocom/ui-shared/src/**'); await expect(rule).toPassAsync(); }); diff --git a/packages/cellix/ui-core/manifest.md b/packages/cellix/ui-core/manifest.md index a19ad29ef..308c6b43a 100644 --- a/packages/cellix/ui-core/manifest.md +++ b/packages/cellix/ui-core/manifest.md @@ -41,7 +41,7 @@ - Depends on React and Ant Design for component composition - `RequireAuth` depends on `react-router-dom` and `react-oidc-context` -- `@ocom/ui-components` builds on top of this package for OCOM-specific UI composition +- `@ocom/ui-shared` builds on top of this package for OCOM-specific UI composition - Cellix frontend apps consume this package through the root entrypoint ## Testing strategy diff --git a/packages/ocom/archunit-tests/src/code-quality.test.ts b/packages/ocom/archunit-tests/src/code-quality.test.ts index efe63c609..5bf108c83 100644 --- a/packages/ocom/archunit-tests/src/code-quality.test.ts +++ b/packages/ocom/archunit-tests/src/code-quality.test.ts @@ -35,7 +35,7 @@ describe('Code Quality', () => { describe('UI (ui packages)', () => { it.skip('should have higher cohesion (LCOM96b)', async () => { const rule = metrics(tsconfigPath) - .inPath('../ui-components/src/**') + .inPath('../ui-shared/src/**') .inPath('../../../apps/ui-community/src/**') .lcom() .lcom96b() @@ -47,7 +47,7 @@ describe('Code Quality', () => { it.skip('should limit imports and surface area in UI code', async () => { const rule = metrics(tsconfigPath) - .inPath('../ui-components/src/**') + .inPath('../ui-shared/src/**') .inPath('../../../apps/ui-community/src/**') .count() .imports() diff --git a/packages/ocom/archunit-tests/src/dependency-rules.test.ts b/packages/ocom/archunit-tests/src/dependency-rules.test.ts index 1bd8147d6..3d8ac0d39 100644 --- a/packages/ocom/archunit-tests/src/dependency-rules.test.ts +++ b/packages/ocom/archunit-tests/src/dependency-rules.test.ts @@ -84,10 +84,10 @@ describe('Dependency Rules', () => { }); }); - describe('ui-community', () => { - it('ui-components should not depend on ui-community app', async () => { + describe('ui-shared', () => { + it('ui-shared should not depend on ui-community app', async () => { const rule = projectFiles() - .inFolder('../ui-components') + .inFolder('../ui-shared') .shouldNot() .dependOnFiles() .inFolder('../../../apps/ui-community'); diff --git a/packages/ocom/archunit-tests/src/naming-conventions.test.ts b/packages/ocom/archunit-tests/src/naming-conventions.test.ts index a1adebf73..cde3eff99 100644 --- a/packages/ocom/archunit-tests/src/naming-conventions.test.ts +++ b/packages/ocom/archunit-tests/src/naming-conventions.test.ts @@ -7,7 +7,7 @@ describe('Naming Conventions', () => { // This is intentionally permissive so new UI packages are automatically covered. // Restrict to UI packages only. UI packages in this repo follow the // pattern `ui-*` and exist under packages/*/ui-* and apps/ui-* - // Examples: packages/cellix/ui-core, packages/ocom/ui-components, apps/ui-community + // Examples: packages/cellix/ui-core, packages/ocom/ui-shared, apps/ui-community const rule = projectFiles() // Match files that live inside a ui-* package's src folder. // inFolder matches the folder path (without filename) so it's diff --git a/packages/ocom/archunit-tests/turbo.json b/packages/ocom/archunit-tests/turbo.json index cf3147eb7..68a3dc2aa 100644 --- a/packages/ocom/archunit-tests/turbo.json +++ b/packages/ocom/archunit-tests/turbo.json @@ -13,7 +13,7 @@ "@ocom/service-otel#build", "@ocom/service-blob-storage#build", "@ocom/service-token-validation#build", - "@ocom/ui-components#build", + "@ocom/ui-shared#build", "@apps/api#build", "@apps/ui-community#build" ], diff --git a/packages/ocom/ui-community-route-accounts/package.json b/packages/ocom/ui-community-route-accounts/package.json index 7dbdaa93c..7b891a020 100644 --- a/packages/ocom/ui-community-route-accounts/package.json +++ b/packages/ocom/ui-community-route-accounts/package.json @@ -21,7 +21,7 @@ "@cellix/ui-core": "workspace:*", "@graphql-typed-document-node/core": "^3.2.0", "@dr.pogodin/react-helmet": "^3.0.2", - "@ocom/ui-components": "workspace:*", + "@ocom/ui-shared": "workspace:*", "antd": "catalog:", "react": "^19.1.1", "react-dom": "^19.1.1", diff --git a/packages/ocom/ui-community-route-accounts/src/section-layout.tsx b/packages/ocom/ui-community-route-accounts/src/section-layout.tsx index 42f3f61ac..c204ae9ab 100644 --- a/packages/ocom/ui-community-route-accounts/src/section-layout.tsx +++ b/packages/ocom/ui-community-route-accounts/src/section-layout.tsx @@ -1,4 +1,4 @@ -import { LoggedInUserContainer } from '@ocom/ui-components'; +import { LoggedInUserContainer } from '@ocom/ui-shared'; import { Layout, theme } from 'antd'; import { Outlet } from 'react-router-dom'; diff --git a/packages/ocom/ui-community-route-admin/package.json b/packages/ocom/ui-community-route-admin/package.json index 4152ada99..41167bcaf 100644 --- a/packages/ocom/ui-community-route-admin/package.json +++ b/packages/ocom/ui-community-route-admin/package.json @@ -21,8 +21,8 @@ "@cellix/ui-core": "workspace:*", "@graphql-typed-document-node/core": "^3.2.0", "@dr.pogodin/react-helmet": "^3.0.2", - "@ocom/ui-components": "workspace:*", - "@ocom/ui-community-route-shared": "workspace:*", + "@ocom/ui-shared": "workspace:*", + "@ocom/ui-community-shared": "workspace:*", "antd": "catalog:", "dayjs": "^1.11.19", "react": "^19.1.1", diff --git a/packages/ocom/ui-community-route-admin/src/index.tsx b/packages/ocom/ui-community-route-admin/src/index.tsx index cc690f9dd..cf4099d70 100644 --- a/packages/ocom/ui-community-route-admin/src/index.tsx +++ b/packages/ocom/ui-community-route-admin/src/index.tsx @@ -1,5 +1,5 @@ import { HomeOutlined, SettingOutlined, TeamOutlined } from '@ant-design/icons'; -import type { PageLayoutProps } from '@ocom/ui-components'; +import type { PageLayoutProps } from '@ocom/ui-shared'; import type React from 'react'; import { Route, Routes } from 'react-router-dom'; import { Home } from './pages/home.tsx'; diff --git a/packages/ocom/ui-community-route-admin/src/pages/members-detail.tsx b/packages/ocom/ui-community-route-admin/src/pages/members-detail.tsx index e2a27125f..9c8f4556f 100644 --- a/packages/ocom/ui-community-route-admin/src/pages/members-detail.tsx +++ b/packages/ocom/ui-community-route-admin/src/pages/members-detail.tsx @@ -1,6 +1,6 @@ import { IdcardOutlined, ProfileOutlined, TeamOutlined } from '@ant-design/icons'; import { PageHeader } from '@ant-design/pro-layout'; -import { VerticalTabs } from '@ocom/ui-components'; +import { VerticalTabs } from '@ocom/ui-shared'; import { useNavigate, useParams } from 'react-router-dom'; import { SubPageLayout } from '../sub-page-layout.tsx'; import { MembersAccounts } from './members-accounts.tsx'; diff --git a/packages/ocom/ui-community-route-admin/src/pages/members-profile.tsx b/packages/ocom/ui-community-route-admin/src/pages/members-profile.tsx index 868a9ffec..f2247b920 100644 --- a/packages/ocom/ui-community-route-admin/src/pages/members-profile.tsx +++ b/packages/ocom/ui-community-route-admin/src/pages/members-profile.tsx @@ -1,5 +1,5 @@ import type React from 'react'; -import { MemberProfileContainer } from '@ocom/ui-community-route-shared'; +import { MemberProfileContainer } from '@ocom/ui-community-shared'; export const MembersProfile: React.FC = () => { return ; diff --git a/packages/ocom/ui-community-route-admin/src/section-layout.container.tsx b/packages/ocom/ui-community-route-admin/src/section-layout.container.tsx index 9b5bac7f6..f446d084d 100644 --- a/packages/ocom/ui-community-route-admin/src/section-layout.container.tsx +++ b/packages/ocom/ui-community-route-admin/src/section-layout.container.tsx @@ -1,6 +1,6 @@ import { useQuery } from '@apollo/client'; import { ComponentQueryLoader } from '@cellix/ui-core'; -import type { PageLayoutProps } from '@ocom/ui-components'; +import type { PageLayoutProps } from '@ocom/ui-shared'; import { useParams } from 'react-router-dom'; import { AdminSectionLayoutContainerMembersForCurrentEndUserDocument, type Member } from './generated.tsx'; import { SectionLayout } from './section-layout.tsx'; diff --git a/packages/ocom/ui-community-route-admin/src/section-layout.tsx b/packages/ocom/ui-community-route-admin/src/section-layout.tsx index da7bfb5c0..85e655538 100644 --- a/packages/ocom/ui-community-route-admin/src/section-layout.tsx +++ b/packages/ocom/ui-community-route-admin/src/section-layout.tsx @@ -1,4 +1,4 @@ -import { CommunitiesDropdownContainer, LoggedInUserContainer, MenuComponent, type MenuComponentProps, type PageLayoutProps } from '@ocom/ui-components'; +import { CommunitiesDropdownContainer, LoggedInUserContainer, MenuComponent, type MenuComponentProps, type PageLayoutProps } from '@ocom/ui-shared'; import { Layout, theme } from 'antd'; import { useState } from 'react'; import { Link, Outlet, useParams } from 'react-router-dom'; diff --git a/packages/ocom/ui-community-route-shared/.storybook/main.ts b/packages/ocom/ui-community-shared/.storybook/main.ts similarity index 100% rename from packages/ocom/ui-community-route-shared/.storybook/main.ts rename to packages/ocom/ui-community-shared/.storybook/main.ts diff --git a/packages/ocom/ui-community-route-shared/.storybook/preview.tsx b/packages/ocom/ui-community-shared/.storybook/preview.tsx similarity index 100% rename from packages/ocom/ui-community-route-shared/.storybook/preview.tsx rename to packages/ocom/ui-community-shared/.storybook/preview.tsx diff --git a/packages/ocom/ui-community-route-shared/.storybook/vitest.setup.ts b/packages/ocom/ui-community-shared/.storybook/vitest.setup.ts similarity index 100% rename from packages/ocom/ui-community-route-shared/.storybook/vitest.setup.ts rename to packages/ocom/ui-community-shared/.storybook/vitest.setup.ts diff --git a/packages/ocom/ui-community-route-shared/package.json b/packages/ocom/ui-community-shared/package.json similarity index 93% rename from packages/ocom/ui-community-route-shared/package.json rename to packages/ocom/ui-community-shared/package.json index a4322df8a..663c55b82 100644 --- a/packages/ocom/ui-community-route-shared/package.json +++ b/packages/ocom/ui-community-shared/package.json @@ -1,5 +1,5 @@ { - "name": "@ocom/ui-community-route-shared", + "name": "@ocom/ui-community-shared", "version": "0.0.1", "private": true, "type": "module", @@ -15,7 +15,7 @@ "test:watch": "vitest" }, "dependencies": { - "@ocom/ui-components": "workspace:*", + "@ocom/ui-shared": "workspace:*", "@apollo/client": "^3.13.9", "@graphql-typed-document-node/core": "^3.2.0", "@cellix/ui-core": "workspace:*", diff --git a/packages/ocom/ui-community-route-shared/src/components/member-profile.container.graphql b/packages/ocom/ui-community-shared/src/components/member-profile.container.graphql similarity index 100% rename from packages/ocom/ui-community-route-shared/src/components/member-profile.container.graphql rename to packages/ocom/ui-community-shared/src/components/member-profile.container.graphql diff --git a/packages/ocom/ui-community-route-shared/src/components/member-profile.container.tsx b/packages/ocom/ui-community-shared/src/components/member-profile.container.tsx similarity index 100% rename from packages/ocom/ui-community-route-shared/src/components/member-profile.container.tsx rename to packages/ocom/ui-community-shared/src/components/member-profile.container.tsx diff --git a/packages/ocom/ui-community-route-shared/src/components/member-profile.stories.tsx b/packages/ocom/ui-community-shared/src/components/member-profile.stories.tsx similarity index 100% rename from packages/ocom/ui-community-route-shared/src/components/member-profile.stories.tsx rename to packages/ocom/ui-community-shared/src/components/member-profile.stories.tsx diff --git a/packages/ocom/ui-community-route-shared/src/components/member-profile.tsx b/packages/ocom/ui-community-shared/src/components/member-profile.tsx similarity index 100% rename from packages/ocom/ui-community-route-shared/src/components/member-profile.tsx rename to packages/ocom/ui-community-shared/src/components/member-profile.tsx diff --git a/packages/ocom/ui-community-route-shared/src/components/menu-component.stories.tsx b/packages/ocom/ui-community-shared/src/components/menu-component.stories.tsx similarity index 100% rename from packages/ocom/ui-community-route-shared/src/components/menu-component.stories.tsx rename to packages/ocom/ui-community-shared/src/components/menu-component.stories.tsx diff --git a/packages/ocom/ui-community-route-shared/src/components/menu-component.tsx b/packages/ocom/ui-community-shared/src/components/menu-component.tsx similarity index 64% rename from packages/ocom/ui-community-route-shared/src/components/menu-component.tsx rename to packages/ocom/ui-community-shared/src/components/menu-component.tsx index a2299f7ca..06d6922df 100644 --- a/packages/ocom/ui-community-route-shared/src/components/menu-component.tsx +++ b/packages/ocom/ui-community-shared/src/components/menu-component.tsx @@ -1 +1 @@ -export { MenuComponent, type MenuComponentProps, type PageLayoutProps } from '@ocom/ui-components'; +export { MenuComponent, type MenuComponentProps, type PageLayoutProps } from '@ocom/ui-shared'; diff --git a/packages/ocom/ui-community-route-shared/src/index.tsx b/packages/ocom/ui-community-shared/src/index.tsx similarity index 100% rename from packages/ocom/ui-community-route-shared/src/index.tsx rename to packages/ocom/ui-community-shared/src/index.tsx diff --git a/packages/ocom/ui-community-route-shared/tsconfig.json b/packages/ocom/ui-community-shared/tsconfig.json similarity index 100% rename from packages/ocom/ui-community-route-shared/tsconfig.json rename to packages/ocom/ui-community-shared/tsconfig.json diff --git a/packages/ocom/ui-community-route-shared/tsconfig.vitest.json b/packages/ocom/ui-community-shared/tsconfig.vitest.json similarity index 100% rename from packages/ocom/ui-community-route-shared/tsconfig.vitest.json rename to packages/ocom/ui-community-shared/tsconfig.vitest.json diff --git a/packages/ocom/ui-community-route-shared/vitest.config.ts b/packages/ocom/ui-community-shared/vitest.config.ts similarity index 100% rename from packages/ocom/ui-community-route-shared/vitest.config.ts rename to packages/ocom/ui-community-shared/vitest.config.ts diff --git a/packages/ocom/ui-components/.gitignore b/packages/ocom/ui-shared/.gitignore similarity index 100% rename from packages/ocom/ui-components/.gitignore rename to packages/ocom/ui-shared/.gitignore diff --git a/packages/ocom/ui-components/.storybook/main.ts b/packages/ocom/ui-shared/.storybook/main.ts similarity index 100% rename from packages/ocom/ui-components/.storybook/main.ts rename to packages/ocom/ui-shared/.storybook/main.ts diff --git a/packages/ocom/ui-components/.storybook/preview.tsx b/packages/ocom/ui-shared/.storybook/preview.tsx similarity index 95% rename from packages/ocom/ui-components/.storybook/preview.tsx rename to packages/ocom/ui-shared/.storybook/preview.tsx index fe00fec3f..a7fdbb1ab 100644 --- a/packages/ocom/ui-components/.storybook/preview.tsx +++ b/packages/ocom/ui-shared/.storybook/preview.tsx @@ -1,4 +1,4 @@ -// Global preview for Storybook in @ocom/ui-components +// Global preview for Storybook in @ocom/ui-shared // Import Ant Design base styles so components render correctly import { MockedProvider } from '@apollo/client/testing'; import type { Decorator, Parameters } from '@storybook/react'; diff --git a/packages/ocom/ui-components/.storybook/vitest.setup.ts b/packages/ocom/ui-shared/.storybook/vitest.setup.ts similarity index 100% rename from packages/ocom/ui-components/.storybook/vitest.setup.ts rename to packages/ocom/ui-shared/.storybook/vitest.setup.ts diff --git a/packages/ocom/ui-components/README.md b/packages/ocom/ui-shared/README.md similarity index 87% rename from packages/ocom/ui-components/README.md rename to packages/ocom/ui-shared/README.md index 6b896c75b..acb13913e 100644 --- a/packages/ocom/ui-components/README.md +++ b/packages/ocom/ui-shared/README.md @@ -1,4 +1,4 @@ -# @ocom/ui-components +# @ocom/ui-shared Owner Community specific UI components library that provides reusable UI components for OCOM application portals. This package demonstrates how shared UI components can be developed and maintained across different client-facing portals within the Cellix framework implementation. @@ -9,16 +9,16 @@ Owner Community specific UI components library that provides reusable UI compone ## Install ```sh -npm i -w @ocom/ui-components +npm i -w @ocom/ui-shared # or if you only need it at compile-time -npm i -D -w @ocom/ui-components +npm i -D -w @ocom/ui-shared ``` ## Entry points - Public API is exposed via the package root: ```ts -import { LoggedInUser, LoggedInUserContainer } from '@ocom/ui-components'; +import { LoggedInUser, LoggedInUserContainer } from '@ocom/ui-shared'; ``` - Deep imports into `src/**` are not part of the public API and are not recommended. @@ -37,7 +37,7 @@ For detailed API documentation, see: ## Folder structure ``` -packages/ui-components/ +packages/ui-shared/ ├── src/ │ ├── components/ # UI components organized by atomic design principles │ │ ├── molecules/ # Smaller, focused components @@ -82,7 +82,7 @@ To develop and test components in isolation: ```sh # Start Storybook development server -npm run storybook -w @ocom/ui-components +npm run storybook -w @ocom/ui-shared ``` ## Testing @@ -91,25 +91,25 @@ Components are tested with Vitest: ```sh # Run tests -npm run test -w @ocom/ui-components +npm run test -w @ocom/ui-shared # Run tests with coverage -npm run test:coverage -w @ocom/ui-components +npm run test:coverage -w @ocom/ui-shared # Watch mode for development -npm run test:watch -w @ocom/ui-components +npm run test:watch -w @ocom/ui-shared ``` ## Scripts Common scripts from `package.json` (executed in this workspace): -- Build: `npm run build -w @ocom/ui-components` -- Clean: `npm run clean -w @ocom/ui-components` -- Test: `npm run test -w @ocom/ui-components` -- Lint/Format: `npm run lint -w @ocom/ui-components` / `npm run format -w @ocom/ui-components` -- Storybook: `npm run storybook -w @ocom/ui-components` -- Build Storybook: `npm run build-storybook -w @ocom/ui-components` +- Build: `npm run build -w @ocom/ui-shared` +- Clean: `npm run clean -w @ocom/ui-shared` +- Test: `npm run test -w @ocom/ui-shared` +- Lint/Format: `npm run lint -w @ocom/ui-shared` / `npm run format -w @ocom/ui-shared` +- Storybook: `npm run storybook -w @ocom/ui-shared` +- Build Storybook: `npm run build-storybook -w @ocom/ui-shared` ## Dependencies diff --git a/packages/ocom/ui-components/package.json b/packages/ocom/ui-shared/package.json similarity index 98% rename from packages/ocom/ui-components/package.json rename to packages/ocom/ui-shared/package.json index 0a4f40b20..af999b462 100644 --- a/packages/ocom/ui-components/package.json +++ b/packages/ocom/ui-shared/package.json @@ -1,5 +1,5 @@ { - "name": "@ocom/ui-components", + "name": "@ocom/ui-shared", "version": "1.0.0", "private": true, "type": "module", diff --git a/packages/ocom/ui-components/src/components/index.ts b/packages/ocom/ui-shared/src/components/index.ts similarity index 100% rename from packages/ocom/ui-components/src/components/index.ts rename to packages/ocom/ui-shared/src/components/index.ts diff --git a/packages/ocom/ui-components/src/components/molecules/README.md b/packages/ocom/ui-shared/src/components/molecules/README.md similarity index 97% rename from packages/ocom/ui-components/src/components/molecules/README.md rename to packages/ocom/ui-shared/src/components/molecules/README.md index 21061551c..2b7569f97 100644 --- a/packages/ocom/ui-components/src/components/molecules/README.md +++ b/packages/ocom/ui-shared/src/components/molecules/README.md @@ -19,7 +19,7 @@ A component that displays the user's authentication state and provides appropria #### Usage ```tsx -import { LoggedInUser } from '@ocom/ui-components'; +import { LoggedInUser } from '@ocom/ui-shared'; const Header = () => { const handleLogin = () => { diff --git a/packages/ocom/ui-components/src/components/molecules/index.tsx b/packages/ocom/ui-shared/src/components/molecules/index.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/molecules/index.tsx rename to packages/ocom/ui-shared/src/components/molecules/index.tsx diff --git a/packages/ocom/ui-components/src/components/molecules/logged-in-user/index.tsx b/packages/ocom/ui-shared/src/components/molecules/logged-in-user/index.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/molecules/logged-in-user/index.tsx rename to packages/ocom/ui-shared/src/components/molecules/logged-in-user/index.tsx diff --git a/packages/ocom/ui-components/src/components/molecules/logged-in-user/logged-in-user.stories.tsx b/packages/ocom/ui-shared/src/components/molecules/logged-in-user/logged-in-user.stories.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/molecules/logged-in-user/logged-in-user.stories.tsx rename to packages/ocom/ui-shared/src/components/molecules/logged-in-user/logged-in-user.stories.tsx diff --git a/packages/ocom/ui-components/src/components/molecules/logged-in-user/logged-in.stories.tsx b/packages/ocom/ui-shared/src/components/molecules/logged-in-user/logged-in.stories.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/molecules/logged-in-user/logged-in.stories.tsx rename to packages/ocom/ui-shared/src/components/molecules/logged-in-user/logged-in.stories.tsx diff --git a/packages/ocom/ui-components/src/components/molecules/logged-in-user/logged-in.tsx b/packages/ocom/ui-shared/src/components/molecules/logged-in-user/logged-in.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/molecules/logged-in-user/logged-in.tsx rename to packages/ocom/ui-shared/src/components/molecules/logged-in-user/logged-in.tsx diff --git a/packages/ocom/ui-components/src/components/molecules/logged-in-user/not-logged-in.stories.tsx b/packages/ocom/ui-shared/src/components/molecules/logged-in-user/not-logged-in.stories.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/molecules/logged-in-user/not-logged-in.stories.tsx rename to packages/ocom/ui-shared/src/components/molecules/logged-in-user/not-logged-in.stories.tsx diff --git a/packages/ocom/ui-components/src/components/molecules/logged-in-user/not-logged-in.tsx b/packages/ocom/ui-shared/src/components/molecules/logged-in-user/not-logged-in.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/molecules/logged-in-user/not-logged-in.tsx rename to packages/ocom/ui-shared/src/components/molecules/logged-in-user/not-logged-in.tsx diff --git a/packages/ocom/ui-components/src/components/organisms/README.md b/packages/ocom/ui-shared/src/components/organisms/README.md similarity index 96% rename from packages/ocom/ui-components/src/components/organisms/README.md rename to packages/ocom/ui-shared/src/components/organisms/README.md index c26f65b64..d7f6a052f 100644 --- a/packages/ocom/ui-components/src/components/organisms/README.md +++ b/packages/ocom/ui-shared/src/components/organisms/README.md @@ -19,7 +19,7 @@ A container component that fetches user authentication data and renders the appr #### Usage ```tsx -import { LoggedInUserContainer } from '@ocom/ui-components'; +import { LoggedInUserContainer } from '@ocom/ui-shared'; const Header = () => { return ( diff --git a/packages/ocom/ui-components/src/components/organisms/dropdown-menu/communities-dropdown.container.stories.tsx b/packages/ocom/ui-shared/src/components/organisms/dropdown-menu/communities-dropdown.container.stories.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/organisms/dropdown-menu/communities-dropdown.container.stories.tsx rename to packages/ocom/ui-shared/src/components/organisms/dropdown-menu/communities-dropdown.container.stories.tsx diff --git a/packages/ocom/ui-components/src/components/organisms/dropdown-menu/communities-dropdown.container.tsx b/packages/ocom/ui-shared/src/components/organisms/dropdown-menu/communities-dropdown.container.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/organisms/dropdown-menu/communities-dropdown.container.tsx rename to packages/ocom/ui-shared/src/components/organisms/dropdown-menu/communities-dropdown.container.tsx diff --git a/packages/ocom/ui-components/src/components/organisms/dropdown-menu/communities-dropdown.stories.tsx b/packages/ocom/ui-shared/src/components/organisms/dropdown-menu/communities-dropdown.stories.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/organisms/dropdown-menu/communities-dropdown.stories.tsx rename to packages/ocom/ui-shared/src/components/organisms/dropdown-menu/communities-dropdown.stories.tsx diff --git a/packages/ocom/ui-components/src/components/organisms/dropdown-menu/communities-dropdown.tsx b/packages/ocom/ui-shared/src/components/organisms/dropdown-menu/communities-dropdown.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/organisms/dropdown-menu/communities-dropdown.tsx rename to packages/ocom/ui-shared/src/components/organisms/dropdown-menu/communities-dropdown.tsx diff --git a/packages/ocom/ui-components/src/components/organisms/header/handle-logout.stories.tsx b/packages/ocom/ui-shared/src/components/organisms/header/handle-logout.stories.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/organisms/header/handle-logout.stories.tsx rename to packages/ocom/ui-shared/src/components/organisms/header/handle-logout.stories.tsx diff --git a/packages/ocom/ui-components/src/components/organisms/header/handle-logout.tsx b/packages/ocom/ui-shared/src/components/organisms/header/handle-logout.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/organisms/header/handle-logout.tsx rename to packages/ocom/ui-shared/src/components/organisms/header/handle-logout.tsx diff --git a/packages/ocom/ui-components/src/components/organisms/header/index.module.css b/packages/ocom/ui-shared/src/components/organisms/header/index.module.css similarity index 100% rename from packages/ocom/ui-components/src/components/organisms/header/index.module.css rename to packages/ocom/ui-shared/src/components/organisms/header/index.module.css diff --git a/packages/ocom/ui-components/src/components/organisms/header/index.tsx b/packages/ocom/ui-shared/src/components/organisms/header/index.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/organisms/header/index.tsx rename to packages/ocom/ui-shared/src/components/organisms/header/index.tsx diff --git a/packages/ocom/ui-components/src/components/organisms/header/logged-in-user-community.container.stories.tsx b/packages/ocom/ui-shared/src/components/organisms/header/logged-in-user-community.container.stories.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/organisms/header/logged-in-user-community.container.stories.tsx rename to packages/ocom/ui-shared/src/components/organisms/header/logged-in-user-community.container.stories.tsx diff --git a/packages/ocom/ui-components/src/components/organisms/header/logged-in-user-community.container.tsx b/packages/ocom/ui-shared/src/components/organisms/header/logged-in-user-community.container.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/organisms/header/logged-in-user-community.container.tsx rename to packages/ocom/ui-shared/src/components/organisms/header/logged-in-user-community.container.tsx diff --git a/packages/ocom/ui-components/src/components/organisms/header/logged-in-user-community.stories.tsx b/packages/ocom/ui-shared/src/components/organisms/header/logged-in-user-community.stories.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/organisms/header/logged-in-user-community.stories.tsx rename to packages/ocom/ui-shared/src/components/organisms/header/logged-in-user-community.stories.tsx diff --git a/packages/ocom/ui-components/src/components/organisms/header/logged-in-user-community.tsx b/packages/ocom/ui-shared/src/components/organisms/header/logged-in-user-community.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/organisms/header/logged-in-user-community.tsx rename to packages/ocom/ui-shared/src/components/organisms/header/logged-in-user-community.tsx diff --git a/packages/ocom/ui-components/src/components/organisms/header/logged-in-user-root.container.stories.tsx b/packages/ocom/ui-shared/src/components/organisms/header/logged-in-user-root.container.stories.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/organisms/header/logged-in-user-root.container.stories.tsx rename to packages/ocom/ui-shared/src/components/organisms/header/logged-in-user-root.container.stories.tsx diff --git a/packages/ocom/ui-components/src/components/organisms/header/logged-in-user-root.container.tsx b/packages/ocom/ui-shared/src/components/organisms/header/logged-in-user-root.container.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/organisms/header/logged-in-user-root.container.tsx rename to packages/ocom/ui-shared/src/components/organisms/header/logged-in-user-root.container.tsx diff --git a/packages/ocom/ui-components/src/components/organisms/header/logged-in-user-root.stories.tsx b/packages/ocom/ui-shared/src/components/organisms/header/logged-in-user-root.stories.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/organisms/header/logged-in-user-root.stories.tsx rename to packages/ocom/ui-shared/src/components/organisms/header/logged-in-user-root.stories.tsx diff --git a/packages/ocom/ui-components/src/components/organisms/header/logged-in-user-root.tsx b/packages/ocom/ui-shared/src/components/organisms/header/logged-in-user-root.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/organisms/header/logged-in-user-root.tsx rename to packages/ocom/ui-shared/src/components/organisms/header/logged-in-user-root.tsx diff --git a/packages/ocom/ui-components/src/components/organisms/header/logged-in-user.container.graphql b/packages/ocom/ui-shared/src/components/organisms/header/logged-in-user.container.graphql similarity index 100% rename from packages/ocom/ui-components/src/components/organisms/header/logged-in-user.container.graphql rename to packages/ocom/ui-shared/src/components/organisms/header/logged-in-user.container.graphql diff --git a/packages/ocom/ui-components/src/components/organisms/header/logged-in-user.container.stories.tsx b/packages/ocom/ui-shared/src/components/organisms/header/logged-in-user.container.stories.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/organisms/header/logged-in-user.container.stories.tsx rename to packages/ocom/ui-shared/src/components/organisms/header/logged-in-user.container.stories.tsx diff --git a/packages/ocom/ui-components/src/components/organisms/header/logged-in-user.container.tsx b/packages/ocom/ui-shared/src/components/organisms/header/logged-in-user.container.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/organisms/header/logged-in-user.container.tsx rename to packages/ocom/ui-shared/src/components/organisms/header/logged-in-user.container.tsx diff --git a/packages/ocom/ui-components/src/components/organisms/index.tsx b/packages/ocom/ui-shared/src/components/organisms/index.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/organisms/index.tsx rename to packages/ocom/ui-shared/src/components/organisms/index.tsx diff --git a/packages/ocom/ui-components/src/components/organisms/navigation/menu-component.stories.tsx b/packages/ocom/ui-shared/src/components/organisms/navigation/menu-component.stories.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/organisms/navigation/menu-component.stories.tsx rename to packages/ocom/ui-shared/src/components/organisms/navigation/menu-component.stories.tsx diff --git a/packages/ocom/ui-components/src/components/organisms/navigation/menu-component.tsx b/packages/ocom/ui-shared/src/components/organisms/navigation/menu-component.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/organisms/navigation/menu-component.tsx rename to packages/ocom/ui-shared/src/components/organisms/navigation/menu-component.tsx diff --git a/packages/ocom/ui-components/src/components/organisms/vertical-tabs/index.stories.tsx b/packages/ocom/ui-shared/src/components/organisms/vertical-tabs/index.stories.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/organisms/vertical-tabs/index.stories.tsx rename to packages/ocom/ui-shared/src/components/organisms/vertical-tabs/index.stories.tsx diff --git a/packages/ocom/ui-components/src/components/organisms/vertical-tabs/index.tsx b/packages/ocom/ui-shared/src/components/organisms/vertical-tabs/index.tsx similarity index 100% rename from packages/ocom/ui-components/src/components/organisms/vertical-tabs/index.tsx rename to packages/ocom/ui-shared/src/components/organisms/vertical-tabs/index.tsx diff --git a/packages/ocom/ui-components/src/index.ts b/packages/ocom/ui-shared/src/index.ts similarity index 100% rename from packages/ocom/ui-components/src/index.ts rename to packages/ocom/ui-shared/src/index.ts diff --git a/packages/ocom/ui-components/tsconfig.json b/packages/ocom/ui-shared/tsconfig.json similarity index 100% rename from packages/ocom/ui-components/tsconfig.json rename to packages/ocom/ui-shared/tsconfig.json diff --git a/packages/ocom/ui-components/tsconfig.vitest.json b/packages/ocom/ui-shared/tsconfig.vitest.json similarity index 100% rename from packages/ocom/ui-components/tsconfig.vitest.json rename to packages/ocom/ui-shared/tsconfig.vitest.json diff --git a/packages/ocom/ui-components/vitest.config.ts b/packages/ocom/ui-shared/vitest.config.ts similarity index 100% rename from packages/ocom/ui-components/vitest.config.ts rename to packages/ocom/ui-shared/vitest.config.ts diff --git a/packages/ocom/ui-components/vitest.shims.d.ts b/packages/ocom/ui-shared/vitest.shims.d.ts similarity index 100% rename from packages/ocom/ui-components/vitest.shims.d.ts rename to packages/ocom/ui-shared/vitest.shims.d.ts diff --git a/packages/ocom/ui-staff-route-community-management/package.json b/packages/ocom/ui-staff-route-community-management/package.json index 92cf5dcdd..238a3caf6 100644 --- a/packages/ocom/ui-staff-route-community-management/package.json +++ b/packages/ocom/ui-staff-route-community-management/package.json @@ -17,7 +17,7 @@ "test:watch": "vitest" }, "dependencies": { - "@ocom/ui-staff-route-shared": "workspace:*", + "@ocom/ui-staff-shared": "workspace:*", "antd": "catalog:", "react": "^19.1.1", "react-dom": "^19.1.1" diff --git a/packages/ocom/ui-staff-route-community-management/src/section-layout.tsx b/packages/ocom/ui-staff-route-community-management/src/section-layout.tsx index ac61362bd..ea711ec73 100644 --- a/packages/ocom/ui-staff-route-community-management/src/section-layout.tsx +++ b/packages/ocom/ui-staff-route-community-management/src/section-layout.tsx @@ -1,5 +1,5 @@ import type { FC } from 'react'; -import { StaffRouteShell } from '@ocom/ui-staff-route-shared'; +import { StaffRouteShell } from '@ocom/ui-staff-shared'; export const SectionLayout: FC = () => { return ( diff --git a/packages/ocom/ui-staff-route-finance/package.json b/packages/ocom/ui-staff-route-finance/package.json index 0a22fc623..e447d758d 100644 --- a/packages/ocom/ui-staff-route-finance/package.json +++ b/packages/ocom/ui-staff-route-finance/package.json @@ -17,7 +17,7 @@ "test:watch": "vitest" }, "dependencies": { - "@ocom/ui-staff-route-shared": "workspace:*", + "@ocom/ui-staff-shared": "workspace:*", "antd": "catalog:", "react": "^19.1.1", "react-dom": "^19.1.1" diff --git a/packages/ocom/ui-staff-route-finance/src/section-layout.tsx b/packages/ocom/ui-staff-route-finance/src/section-layout.tsx index e66d288d6..fbf595cde 100644 --- a/packages/ocom/ui-staff-route-finance/src/section-layout.tsx +++ b/packages/ocom/ui-staff-route-finance/src/section-layout.tsx @@ -1,5 +1,5 @@ import type { FC } from 'react'; -import { StaffRouteShell } from '@ocom/ui-staff-route-shared'; +import { StaffRouteShell } from '@ocom/ui-staff-shared'; export const SectionLayout: FC = () => { return ( diff --git a/packages/ocom/ui-staff-route-tech-admin/package.json b/packages/ocom/ui-staff-route-tech-admin/package.json index 1923c2dea..679775efe 100644 --- a/packages/ocom/ui-staff-route-tech-admin/package.json +++ b/packages/ocom/ui-staff-route-tech-admin/package.json @@ -15,7 +15,7 @@ "test:watch": "vitest" }, "dependencies": { - "@ocom/ui-staff-route-shared": "workspace:*", + "@ocom/ui-staff-shared": "workspace:*", "antd": "catalog:", "react": "^19.1.1" }, diff --git a/packages/ocom/ui-staff-route-tech-admin/src/section-layout.tsx b/packages/ocom/ui-staff-route-tech-admin/src/section-layout.tsx index 5b44c01e5..0d5f0de95 100644 --- a/packages/ocom/ui-staff-route-tech-admin/src/section-layout.tsx +++ b/packages/ocom/ui-staff-route-tech-admin/src/section-layout.tsx @@ -1,5 +1,5 @@ import type { FC } from 'react'; -import { StaffRouteShell } from '@ocom/ui-staff-route-shared'; +import { StaffRouteShell } from '@ocom/ui-staff-shared'; export const SectionLayout: FC = () => { return ( diff --git a/packages/ocom/ui-staff-route-user-management/package.json b/packages/ocom/ui-staff-route-user-management/package.json index 60a30577a..082009e4e 100644 --- a/packages/ocom/ui-staff-route-user-management/package.json +++ b/packages/ocom/ui-staff-route-user-management/package.json @@ -15,7 +15,7 @@ "test:watch": "vitest" }, "dependencies": { - "@ocom/ui-staff-route-shared": "workspace:*", + "@ocom/ui-staff-shared": "workspace:*", "react": "^19.1.1" }, "devDependencies": { diff --git a/packages/ocom/ui-staff-route-user-management/src/section-layout.tsx b/packages/ocom/ui-staff-route-user-management/src/section-layout.tsx index 9230cd667..092c4de9b 100644 --- a/packages/ocom/ui-staff-route-user-management/src/section-layout.tsx +++ b/packages/ocom/ui-staff-route-user-management/src/section-layout.tsx @@ -1,5 +1,5 @@ import type { FC } from 'react'; -import { StaffRouteShell } from '@ocom/ui-staff-route-shared'; +import { StaffRouteShell } from '@ocom/ui-staff-shared'; export const SectionLayout: FC = () => { return ( diff --git a/packages/ocom/ui-staff-route-shared/package.json b/packages/ocom/ui-staff-shared/package.json similarity index 94% rename from packages/ocom/ui-staff-route-shared/package.json rename to packages/ocom/ui-staff-shared/package.json index ea9b6d319..a1c3bf6f5 100644 --- a/packages/ocom/ui-staff-route-shared/package.json +++ b/packages/ocom/ui-staff-shared/package.json @@ -1,5 +1,5 @@ { - "name": "@ocom/ui-staff-route-shared", + "name": "@ocom/ui-staff-shared", "version": "0.0.1", "private": true, "type": "module", diff --git a/packages/ocom/ui-staff-route-shared/src/index.tsx b/packages/ocom/ui-staff-shared/src/index.tsx similarity index 100% rename from packages/ocom/ui-staff-route-shared/src/index.tsx rename to packages/ocom/ui-staff-shared/src/index.tsx diff --git a/packages/ocom/ui-staff-route-shared/src/section-layout.tsx b/packages/ocom/ui-staff-shared/src/section-layout.tsx similarity index 100% rename from packages/ocom/ui-staff-route-shared/src/section-layout.tsx rename to packages/ocom/ui-staff-shared/src/section-layout.tsx diff --git a/packages/ocom/ui-staff-route-shared/src/staff-route-shell.tsx b/packages/ocom/ui-staff-shared/src/staff-route-shell.tsx similarity index 100% rename from packages/ocom/ui-staff-route-shared/src/staff-route-shell.tsx rename to packages/ocom/ui-staff-shared/src/staff-route-shell.tsx diff --git a/packages/ocom/ui-staff-route-shared/src/vite-env.d.ts b/packages/ocom/ui-staff-shared/src/vite-env.d.ts similarity index 100% rename from packages/ocom/ui-staff-route-shared/src/vite-env.d.ts rename to packages/ocom/ui-staff-shared/src/vite-env.d.ts diff --git a/packages/ocom/ui-staff-route-shared/tsconfig.json b/packages/ocom/ui-staff-shared/tsconfig.json similarity index 100% rename from packages/ocom/ui-staff-route-shared/tsconfig.json rename to packages/ocom/ui-staff-shared/tsconfig.json diff --git a/packages/ocom/ui-staff-route-shared/vitest.config.ts b/packages/ocom/ui-staff-shared/vitest.config.ts similarity index 100% rename from packages/ocom/ui-staff-route-shared/vitest.config.ts rename to packages/ocom/ui-staff-shared/vitest.config.ts diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 78ca4d6ad..3c3243f28 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -512,15 +512,15 @@ importers: '@ocom/ui-staff-route-root': specifier: workspace:* version: link:../../packages/ocom/ui-staff-route-root - '@ocom/ui-staff-route-shared': - specifier: workspace:* - version: link:../../packages/ocom/ui-staff-route-shared '@ocom/ui-staff-route-tech-admin': specifier: workspace:* version: link:../../packages/ocom/ui-staff-route-tech-admin '@ocom/ui-staff-route-user-management': specifier: workspace:* version: link:../../packages/ocom/ui-staff-route-user-management + '@ocom/ui-staff-shared': + specifier: workspace:* + version: link:../../packages/ocom/ui-staff-shared antd: specifier: 'catalog:' version: 6.3.5(luxon@3.6.1)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -1451,9 +1451,9 @@ importers: '@graphql-typed-document-node/core': specifier: ^3.2.0 version: 3.2.0(graphql@16.12.0) - '@ocom/ui-components': + '@ocom/ui-shared': specifier: workspace:* - version: link:../ui-components + version: link:../ui-shared antd: specifier: 'catalog:' version: 6.3.5(luxon@3.6.1)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -1536,12 +1536,12 @@ importers: '@graphql-typed-document-node/core': specifier: ^3.2.0 version: 3.2.0(graphql@16.12.0) - '@ocom/ui-community-route-shared': + '@ocom/ui-community-shared': specifier: workspace:* - version: link:../ui-community-route-shared - '@ocom/ui-components': + version: link:../ui-community-shared + '@ocom/ui-shared': specifier: workspace:* - version: link:../ui-components + version: link:../ui-shared antd: specifier: 'catalog:' version: 6.3.5(luxon@3.6.1)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -1665,7 +1665,7 @@ importers: specifier: 'catalog:' version: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - packages/ocom/ui-community-route-shared: + packages/ocom/ui-community-shared: dependencies: '@apollo/client': specifier: ^3.13.9 @@ -1676,9 +1676,9 @@ importers: '@graphql-typed-document-node/core': specifier: ^3.2.0 version: 3.2.0(graphql@16.12.0) - '@ocom/ui-components': + '@ocom/ui-shared': specifier: workspace:* - version: link:../ui-components + version: link:../ui-shared antd: specifier: 'catalog:' version: 6.3.5(luxon@3.6.1)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -1744,7 +1744,7 @@ importers: specifier: 'catalog:' version: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - packages/ocom/ui-components: + packages/ocom/ui-shared: dependencies: '@ant-design/icons': specifier: ^6.0.2 @@ -1794,7 +1794,7 @@ importers: version: 9.1.16(@types/react@19.2.7)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) '@storybook/addon-vitest': specifier: ^9.1.3 - version: 9.1.16(@vitest/browser-playwright@4.1.2)(@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2))(@vitest/runner@4.1.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vitest@4.1.2) + version: 9.1.20(@vitest/browser-playwright@4.1.2)(@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2))(@vitest/runner@4.1.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vitest@4.1.2) '@storybook/react': specifier: ^9.1.9 version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3) @@ -1837,9 +1837,9 @@ importers: packages/ocom/ui-staff-route-community-management: dependencies: - '@ocom/ui-staff-route-shared': + '@ocom/ui-staff-shared': specifier: workspace:* - version: link:../ui-staff-route-shared + version: link:../ui-staff-shared antd: specifier: 'catalog:' version: 6.3.5(luxon@3.6.1)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -1880,9 +1880,9 @@ importers: packages/ocom/ui-staff-route-finance: dependencies: - '@ocom/ui-staff-route-shared': + '@ocom/ui-staff-shared': specifier: workspace:* - version: link:../ui-staff-route-shared + version: link:../ui-staff-shared antd: specifier: 'catalog:' version: 6.3.5(luxon@3.6.1)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -1964,8 +1964,14 @@ importers: specifier: 'catalog:' version: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - packages/ocom/ui-staff-route-shared: + packages/ocom/ui-staff-route-tech-admin: dependencies: + '@ocom/ui-staff-shared': + specifier: workspace:* + version: link:../ui-staff-shared + antd: + specifier: 'catalog:' + version: 6.3.5(luxon@3.6.1)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: specifier: ^19.1.1 version: 19.2.0 @@ -1985,6 +1991,9 @@ importers: jsdom: specifier: 'catalog:' version: 26.1.0 + storybook: + specifier: 'catalog:' + version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) typescript: specifier: 'catalog:' version: 6.0.3 @@ -1995,14 +2004,11 @@ importers: specifier: 'catalog:' version: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - packages/ocom/ui-staff-route-tech-admin: + packages/ocom/ui-staff-route-user-management: dependencies: - '@ocom/ui-staff-route-shared': + '@ocom/ui-staff-shared': specifier: workspace:* - version: link:../ui-staff-route-shared - antd: - specifier: 'catalog:' - version: 6.3.5(luxon@3.6.1)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: link:../ui-staff-shared react: specifier: ^19.1.1 version: 19.2.0 @@ -2035,11 +2041,8 @@ importers: specifier: 'catalog:' version: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - packages/ocom/ui-staff-route-user-management: + packages/ocom/ui-staff-shared: dependencies: - '@ocom/ui-staff-route-shared': - specifier: workspace:* - version: link:../ui-staff-route-shared react: specifier: ^19.1.1 version: 19.2.0 @@ -2059,9 +2062,6 @@ importers: jsdom: specifier: 'catalog:' version: 26.1.0 - storybook: - specifier: 'catalog:' - version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) typescript: specifier: 'catalog:' version: 6.0.3 diff --git a/sonar-project.properties b/sonar-project.properties index abab4e3fa..4f2163922 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -37,7 +37,7 @@ packages/ocom/service-blob-storage/src,\ packages/ocom/service-mongoose/src,\ packages/ocom/service-otel/src,\ packages/ocom/service-token-validation/src,\ -packages/ocom/ui-components/src +packages/ocom/ui-shared/src sonar.tests=apps/api/src,\ apps/docs/src,\ @@ -69,7 +69,7 @@ packages/ocom/service-blob-storage/src,\ packages/ocom/service-mongoose/src,\ packages/ocom/service-otel/src,\ packages/ocom/service-token-validation/src,\ -packages/ocom/ui-components/src +packages/ocom/ui-shared/src # Test file patterns sonar.test.inclusions=**/*.test.ts,**/*.test.tsx,**/*.spec.ts,**/*.spec.tsx,**/*.stories.tsx From 7767f71603375c448cad46f7792f4e01619d5387 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Fri, 1 May 2026 19:24:42 +0530 Subject: [PATCH 34/88] fix: rename ui-community-route-shared to ui-community-shared in knip.json --- knip.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/knip.json b/knip.json index c6eb0ffde..e43ca7e72 100644 --- a/knip.json +++ b/knip.json @@ -55,7 +55,7 @@ "packages/ocom/archunit-tests": { "project": ["src/**/*.ts"] }, - "packages/ocom/ui-community-route-shared": { + "packages/ocom/ui-community-shared": { "entry": ["src/index.tsx"], "project": ["src/**/*.{ts,tsx}"] }, From 89121202947a631ed1cdf4669d0926987500d665 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 14:59:41 +0000 Subject: [PATCH 35/88] fix: correct Biome formatting in resolver-builder.test.ts Agent-Logs-Url: https://github.com/CellixJs/cellixjs/sessions/3d00d38e-39b6-480b-8f35-9451c37a4c08 Co-authored-by: rohit-r-kumar <175348946+rohit-r-kumar@users.noreply.github.com> --- apps/ui-community/src/contexts/theme-context.tsx | 2 +- .../ocom/graphql/src/schema/builder/resolver-builder.test.ts | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/apps/ui-community/src/contexts/theme-context.tsx b/apps/ui-community/src/contexts/theme-context.tsx index fc4711d8f..43f4f2c64 100644 --- a/apps/ui-community/src/contexts/theme-context.tsx +++ b/apps/ui-community/src/contexts/theme-context.tsx @@ -138,7 +138,7 @@ export const ThemeProvider = ({ children }: { children: ReactNode }) => { } else { const valueToSet = { type: 'light', - tokens: theme.defaultSeed, + token: theme.defaultSeed, hardCodedTokens: { textColor: '#000000', backgroundColor: '#ffffff', diff --git a/packages/ocom/graphql/src/schema/builder/resolver-builder.test.ts b/packages/ocom/graphql/src/schema/builder/resolver-builder.test.ts index 6b43ad53c..33abcf6dc 100644 --- a/packages/ocom/graphql/src/schema/builder/resolver-builder.test.ts +++ b/packages/ocom/graphql/src/schema/builder/resolver-builder.test.ts @@ -16,10 +16,7 @@ vi.mock('@graphql-tools/merge', () => ({ })); vi.mock('./resolver-manifest.generated.ts', () => ({ - ocomGraphqlResolvers: [ - { Query: { hello: vi.fn() } }, - { Query: { currentCommunity: vi.fn() }, Mutation: { communityCreate: vi.fn() } }, - ], + ocomGraphqlResolvers: [{ Query: { hello: vi.fn() } }, { Query: { currentCommunity: vi.fn() }, Mutation: { communityCreate: vi.fn() } }], ocomGraphqlPermissions: [], })); From 27cb61e03b95e014f0ad689a03dd92a9580db0c4 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Fri, 1 May 2026 21:39:14 +0530 Subject: [PATCH 36/88] feat(ui-staff): add Entra app-role route authorization (#214) - Add StaffAppRoles constants (Staff.TechAdmin, Staff.Finance, Staff.ServiceLineOwner, Staff.CaseManager) - Add centralized staffRouteRoles mapping route paths to required roles - Extract extractRoles helper to staff-app-roles.ts (shared utility) - Add RequireRole component that reads StaffAuthContext and redirects to /unauthorized when user lacks the required role - Wrap each /staff/* route in App.tsx with RequireRole using the centralized mapping - Filter nav links in StaffRouteShell to only show sections the user can access based on their roles - Add react-router-dom and react-dom to ui-staff-shared dependencies - Add unit tests for StaffAppRoles, staffRouteRoles, extractRoles, and RequireRole component Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- apps/ui-staff/src/App.tsx | 34 ++- packages/ocom/ui-staff-shared/package.json | 58 ++-- packages/ocom/ui-staff-shared/src/index.tsx | 5 +- .../ui-staff-shared/src/require-role.test.tsx | 80 ++++++ .../ocom/ui-staff-shared/src/require-role.tsx | 34 +++ .../src/staff-app-roles.test.ts | 67 +++++ .../ui-staff-shared/src/staff-app-roles.ts | 48 ++++ .../ui-staff-shared/src/staff-route-shell.tsx | 46 +--- pnpm-lock.yaml | 258 +++++++++++++++++- 9 files changed, 548 insertions(+), 82 deletions(-) create mode 100644 packages/ocom/ui-staff-shared/src/require-role.test.tsx create mode 100644 packages/ocom/ui-staff-shared/src/require-role.tsx create mode 100644 packages/ocom/ui-staff-shared/src/staff-app-roles.test.ts create mode 100644 packages/ocom/ui-staff-shared/src/staff-app-roles.ts diff --git a/apps/ui-staff/src/App.tsx b/apps/ui-staff/src/App.tsx index 8ae188208..3e166073f 100644 --- a/apps/ui-staff/src/App.tsx +++ b/apps/ui-staff/src/App.tsx @@ -1,10 +1,10 @@ import { RequireAuth } from '@cellix/ui-core'; -import { Root } from '@ocom/ui-staff-route-root'; import { Root as CommunityManagement } from '@ocom/ui-staff-route-community-management'; import { Root as Finance } from '@ocom/ui-staff-route-finance'; -import { StaffAuthProvider } from '@ocom/ui-staff-shared'; +import { Root } from '@ocom/ui-staff-route-root'; import { Root as TechAdmin } from '@ocom/ui-staff-route-tech-admin'; import { Root as UserManagement } from '@ocom/ui-staff-route-user-management'; +import { RequireRole, StaffAuthProvider, staffRouteRoles } from '@ocom/ui-staff-shared'; import { useAuth } from 'react-oidc-context'; import { Route, Routes } from 'react-router-dom'; import './App.css'; @@ -40,23 +40,43 @@ export default function App() { } + element={ + + + + } /> } + element={ + + + + } /> } + element={ + + + + } /> } + element={ + + + + } /> } + element={ + + + + } /> diff --git a/packages/ocom/ui-staff-shared/package.json b/packages/ocom/ui-staff-shared/package.json index a1c3bf6f5..787fa3226 100644 --- a/packages/ocom/ui-staff-shared/package.json +++ b/packages/ocom/ui-staff-shared/package.json @@ -1,30 +1,32 @@ { - "name": "@ocom/ui-staff-shared", - "version": "0.0.1", - "private": true, - "type": "module", - "exports": { - ".": "./src/index.tsx" - }, - "scripts": { - "prebuild": "pnpm run lint", - "build": "tsgo --noEmit", - "lint": "biome lint", - "test": "vitest run --silent --reporter=dot", - "test:coverage": "vitest run --coverage --silent --reporter=dot", - "test:watch": "vitest" - }, - "dependencies": { - "react": "^19.1.1" - }, - "devDependencies": { - "@cellix/config-typescript": "workspace:*", - "@cellix/config-vitest": "workspace:*", - "@types/react": "^19.1.11", - "@types/react-dom": "^19.1.6", - "jsdom": "catalog:", - "vite": "catalog:", - "vitest": "catalog:", - "typescript": "catalog:" - } + "name": "@ocom/ui-staff-shared", + "version": "0.0.1", + "private": true, + "type": "module", + "exports": { + ".": "./src/index.tsx" + }, + "scripts": { + "prebuild": "pnpm run lint", + "build": "tsgo --noEmit", + "lint": "biome lint", + "test": "vitest run --silent --reporter=dot", + "test:coverage": "vitest run --coverage --silent --reporter=dot", + "test:watch": "vitest" + }, + "dependencies": { + "react": "^19.1.1", + "react-router-dom": "catalog:" + }, + "devDependencies": { + "@cellix/config-typescript": "workspace:*", + "@cellix/config-vitest": "workspace:*", + "@types/react": "^19.1.11", + "@types/react-dom": "^19.1.6", + "jsdom": "catalog:", + "react-dom": "^19.1.1", + "vite": "catalog:", + "vitest": "catalog:", + "typescript": "catalog:" + } } diff --git a/packages/ocom/ui-staff-shared/src/index.tsx b/packages/ocom/ui-staff-shared/src/index.tsx index 456f74eb3..e441af05e 100644 --- a/packages/ocom/ui-staff-shared/src/index.tsx +++ b/packages/ocom/ui-staff-shared/src/index.tsx @@ -1,5 +1,8 @@ import { createElement, type FC } from 'react'; import { SectionLayout } from './section-layout.tsx'; -export { StaffRouteShell, type StaffRouteShellProps, StaffAuthContext, StaffAuthProvider, type StaffAuth } from './staff-route-shell.tsx'; + +export { RequireRole, type RequireRoleProps } from './require-role.tsx'; +export { extractRoles, type StaffAppRole, StaffAppRoles, staffRouteRoles } from './staff-app-roles.ts'; +export { type StaffAuth, StaffAuthContext, StaffAuthProvider, StaffRouteShell, type StaffRouteShellProps } from './staff-route-shell.tsx'; export const Root: FC = () => createElement(SectionLayout); diff --git a/packages/ocom/ui-staff-shared/src/require-role.test.tsx b/packages/ocom/ui-staff-shared/src/require-role.test.tsx new file mode 100644 index 000000000..dac0b8b6f --- /dev/null +++ b/packages/ocom/ui-staff-shared/src/require-role.test.tsx @@ -0,0 +1,80 @@ +import type * as React from 'react'; +import { renderToString } from 'react-dom/server'; +import { MemoryRouter } from 'react-router-dom'; +import { describe, expect, it } from 'vitest'; +import { RequireRole } from './require-role.tsx'; +import { StaffAuthProvider } from './staff-route-shell.tsx'; + +const Protected: React.FC = () =>
protected content
; + +describe('RequireRole', () => { + it('renders children when user has a required role', () => { + const identity = { raw: { roles: ['Staff.TechAdmin'] } }; + const html = renderToString( + + + + + + + , + ); + expect(html).toContain('protected content'); + }); + + it('renders children when user holds one of multiple required roles', () => { + const identity = { raw: { roles: ['Staff.CaseManager'] } }; + const html = renderToString( + + + + + + + , + ); + expect(html).toContain('protected content'); + }); + + it('redirects to /unauthorized when user lacks required role', () => { + const identity = { raw: { roles: ['Staff.Finance'] } }; + const html = renderToString( + + + + + + + , + ); + expect(html).not.toContain('protected content'); + }); + + it('redirects when user has no roles at all', () => { + const identity = { raw: {} }; + const html = renderToString( + + + + + + + , + ); + expect(html).not.toContain('protected content'); + }); + + it('renders children when roles array is empty (no restriction)', () => { + const identity = { raw: {} }; + const html = renderToString( + + + + + + + , + ); + expect(html).toContain('protected content'); + }); +}); diff --git a/packages/ocom/ui-staff-shared/src/require-role.tsx b/packages/ocom/ui-staff-shared/src/require-role.tsx new file mode 100644 index 000000000..557b62623 --- /dev/null +++ b/packages/ocom/ui-staff-shared/src/require-role.tsx @@ -0,0 +1,34 @@ +import { type FC, type ReactNode, useContext } from 'react'; +import { Navigate } from 'react-router-dom'; +import { extractRoles } from './staff-app-roles.ts'; +import { StaffAuthContext } from './staff-route-shell.tsx'; + +export interface RequireRoleProps { + /** At least one of these roles must be present in the authenticated user's token. */ + roles: readonly string[]; + children: ReactNode; +} + +/** + * Guards a UI branch behind one or more Entra app roles. + * + * Reads the authenticated identity from {@link StaffAuthContext} and redirects + * to `/unauthorized` when the user lacks every required role. + * Must be rendered inside a {@link StaffAuthProvider} and a React Router context. + */ +export const RequireRole: FC = ({ roles, children }) => { + const auth = useContext(StaffAuthContext); + const userRoles = auth?.roles ?? extractRoles(auth?.raw); + const isAuthorized = roles.length === 0 || (userRoles !== undefined && roles.some((r) => userRoles.includes(r))); + + if (!isAuthorized) { + return ( + + ); + } + + return <>{children}; +}; diff --git a/packages/ocom/ui-staff-shared/src/staff-app-roles.test.ts b/packages/ocom/ui-staff-shared/src/staff-app-roles.test.ts new file mode 100644 index 000000000..ffccefcac --- /dev/null +++ b/packages/ocom/ui-staff-shared/src/staff-app-roles.test.ts @@ -0,0 +1,67 @@ +import { describe, expect, it } from 'vitest'; +import { extractRoles, StaffAppRoles, staffRouteRoles } from './staff-app-roles.ts'; + +describe('StaffAppRoles', () => { + it('contains the four expected Entra app role values', () => { + expect(StaffAppRoles.TechAdmin).toBe('Staff.TechAdmin'); + expect(StaffAppRoles.Finance).toBe('Staff.Finance'); + expect(StaffAppRoles.ServiceLineOwner).toBe('Staff.ServiceLineOwner'); + expect(StaffAppRoles.CaseManager).toBe('Staff.CaseManager'); + }); +}); + +describe('staffRouteRoles', () => { + it('gates /staff/community to CaseManager and ServiceLineOwner', () => { + expect(staffRouteRoles['/staff/community']).toContain(StaffAppRoles.CaseManager); + expect(staffRouteRoles['/staff/community']).toContain(StaffAppRoles.ServiceLineOwner); + }); + + it('gates /staff/users to CaseManager and ServiceLineOwner', () => { + expect(staffRouteRoles['/staff/users']).toContain(StaffAppRoles.CaseManager); + expect(staffRouteRoles['/staff/users']).toContain(StaffAppRoles.ServiceLineOwner); + }); + + it('gates /staff/finance to Finance only', () => { + expect(staffRouteRoles['/staff/finance']).toEqual([StaffAppRoles.Finance]); + }); + + it('gates /staff/tech to TechAdmin only', () => { + expect(staffRouteRoles['/staff/tech']).toEqual([StaffAppRoles.TechAdmin]); + }); +}); + +describe('extractRoles', () => { + it('returns undefined for undefined input', () => { + expect(extractRoles(undefined)).toBeUndefined(); + }); + + it('returns undefined for empty raw object', () => { + expect(extractRoles({})).toBeUndefined(); + }); + + it('extracts roles from the "roles" claim', () => { + const result = extractRoles({ roles: ['Staff.TechAdmin', 'Staff.Finance'] }); + expect(result).toContain('Staff.TechAdmin'); + expect(result).toContain('Staff.Finance'); + }); + + it('extracts a single role string from the "roles" claim', () => { + const result = extractRoles({ roles: 'Staff.CaseManager' }); + expect(result).toEqual(['Staff.CaseManager']); + }); + + it('extracts roles from the "app_roles" claim', () => { + const result = extractRoles({ app_roles: ['Staff.Finance'] }); + expect(result).toContain('Staff.Finance'); + }); + + it('extracts roles from realm_access.roles', () => { + const result = extractRoles({ realm_access: { roles: ['Staff.ServiceLineOwner'] } }); + expect(result).toContain('Staff.ServiceLineOwner'); + }); + + it('deduplicates roles across multiple claims', () => { + const result = extractRoles({ roles: ['Staff.TechAdmin'], role: 'Staff.TechAdmin' }); + expect(result).toEqual(['Staff.TechAdmin']); + }); +}); diff --git a/packages/ocom/ui-staff-shared/src/staff-app-roles.ts b/packages/ocom/ui-staff-shared/src/staff-app-roles.ts new file mode 100644 index 000000000..2f2c56651 --- /dev/null +++ b/packages/ocom/ui-staff-shared/src/staff-app-roles.ts @@ -0,0 +1,48 @@ +export const StaffAppRoles = { + TechAdmin: 'Staff.TechAdmin', + Finance: 'Staff.Finance', + ServiceLineOwner: 'Staff.ServiceLineOwner', + CaseManager: 'Staff.CaseManager', +} as const; + +export type StaffAppRole = (typeof StaffAppRoles)[keyof typeof StaffAppRoles]; + +/** + * Centralized mapping of top-level staff routes to the Entra app roles required to access them. + * A user must hold at least one of the listed roles to be admitted to the route. + */ +export const staffRouteRoles = { + '/staff/community': [StaffAppRoles.CaseManager, StaffAppRoles.ServiceLineOwner], + '/staff/users': [StaffAppRoles.CaseManager, StaffAppRoles.ServiceLineOwner], + '/staff/finance': [StaffAppRoles.Finance], + '/staff/tech': [StaffAppRoles.TechAdmin], +} satisfies Record; + +/** + * Extracts role strings from an OIDC token raw profile. + * Checks common claim names used by Entra and other providers. + */ +export const extractRoles = (raw: Record | undefined): string[] | undefined => { + if (!raw) return undefined; + const candidates: Array = [ + // biome-ignore lint/complexity/useLiteralKeys: dynamic profile keys from OIDC token claims + raw['roles'] as string | string[] | undefined, + // biome-ignore lint/complexity/useLiteralKeys: dynamic profile keys from OIDC token claims + raw['role'] as string | string[] | undefined, + // biome-ignore lint/complexity/useLiteralKeys: dynamic profile keys from OIDC token claims + raw['groups'] as string | string[] | undefined, + // biome-ignore lint/complexity/useLiteralKeys: dynamic profile keys from OIDC token claims + raw['app_roles'] as string | string[] | undefined, + // biome-ignore lint/complexity/useLiteralKeys: dynamic profile keys from OIDC token claims + (raw['realm_access'] as Record | undefined)?.['roles'] as string[] | undefined, + ]; + const roles: string[] = []; + for (const c of candidates) { + if (Array.isArray(c)) { + roles.push(...(c.filter((x) => typeof x === 'string') as string[])); + } else if (typeof c === 'string') { + roles.push(c); + } + } + return roles.length ? Array.from(new Set(roles)) : undefined; +}; diff --git a/packages/ocom/ui-staff-shared/src/staff-route-shell.tsx b/packages/ocom/ui-staff-shared/src/staff-route-shell.tsx index 30d342d5a..f9efab61c 100644 --- a/packages/ocom/ui-staff-shared/src/staff-route-shell.tsx +++ b/packages/ocom/ui-staff-shared/src/staff-route-shell.tsx @@ -1,4 +1,5 @@ -import { type FC, createContext, useContext, type ReactNode } from 'react'; +import { createContext, type FC, type ReactNode, useContext } from 'react'; +import { extractRoles, staffRouteRoles } from './staff-app-roles.ts'; export interface StaffRouteShellProps { title: string; @@ -16,44 +17,23 @@ export type StaffAuth = { export const StaffAuthContext = createContext(undefined); -export const StaffAuthProvider: FC<{ value: StaffAuth; children?: ReactNode }> = ({ value, children }) => ( - {children} -); +export const StaffAuthProvider: FC<{ value: StaffAuth; children?: ReactNode }> = ({ value, children }) => {children}; -const navLinks = [ - { label: 'Community Management', href: '/staff/community' }, - { label: 'User Management', href: '/staff/users' }, - { label: 'Finance', href: '/staff/finance' }, - { label: 'Tech Admin', href: '/staff/tech' }, +const allNavLinks = [ + { label: 'Community Management', href: '/staff/community', roles: staffRouteRoles['/staff/community'] }, + { label: 'User Management', href: '/staff/users', roles: staffRouteRoles['/staff/users'] }, + { label: 'Finance', href: '/staff/finance', roles: staffRouteRoles['/staff/finance'] }, + { label: 'Tech Admin', href: '/staff/tech', roles: staffRouteRoles['/staff/tech'] }, ]; -const extractRoles = (raw: Record | undefined): string[] | undefined => { - if (!raw) return undefined; - const r = raw as Record; - const candidates: Array = [ - (r['roles'] as string | string[] | undefined), - (r['role'] as string | string[] | undefined), - (r['groups'] as string | string[] | undefined), - (r['app_roles'] as string | string[] | undefined), - ((r['realm_access'] as Record | undefined)?.['roles'] as string[] | undefined), - ]; - const roles: string[] = []; - for (const c of candidates) { - if (Array.isArray(c)) { - roles.push(...c.filter((x) => typeof x === 'string') as string[]); - } else if (typeof c === 'string') { - roles.push(c); - } - } - return roles.length ? Array.from(new Set(roles)) : undefined; -}; - export const StaffRouteShell: FC = ({ title, description }) => { const auth = useContext(StaffAuthContext); const raw = auth?.raw as Record | undefined; + // biome-ignore lint/complexity/useLiteralKeys: dynamic OIDC profile claim names const fallbackName = raw ? ((raw['name'] as string | undefined) ?? (raw['preferred_username'] as string | undefined) ?? (raw['email'] as string | undefined)) : undefined; const name = auth?.name ?? auth?.username ?? auth?.email ?? fallbackName; const roles = auth?.roles ?? extractRoles(auth?.raw); + const navLinks = allNavLinks.filter((link) => link.roles.length === 0 || (roles !== undefined && link.roles.some((r) => roles.includes(r)))); return (
@@ -65,7 +45,7 @@ export const StaffRouteShell: FC = ({ title, description }
Placeholder
- { name ? ( + {name ? (
Signed in as
{name}
@@ -124,11 +104,11 @@ export const StaffRouteShell: FC = ({ title, description } {description}
Identity
- { name ?
{name}
:
No authenticated identity available
} + {name ?
{name}
:
No authenticated identity available
}
Resolved Roles
- { roles?.length ? ( + {roles?.length ? (
    {roles.map((r) => (
  • {r}
  • diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3c3243f28..180aba1fd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -884,25 +884,25 @@ importers: version: link:../config-vitest '@chromatic-com/storybook': specifier: ^4.1.1 - version: 4.1.3(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) + version: 4.1.3(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) '@storybook/addon-a11y': specifier: ^9.1.3 - version: 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) + version: 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) '@storybook/addon-docs': specifier: ^9.1.3 - version: 9.1.16(@types/react@19.2.7)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) + version: 9.1.16(@types/react@19.2.7)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) '@storybook/addon-onboarding': specifier: ^9.1.3 - version: 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) + version: 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) '@storybook/addon-vitest': specifier: ^9.1.3 - version: 9.1.20(@vitest/browser-playwright@4.1.2)(@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2))(@vitest/runner@4.1.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vitest@4.1.2) + version: 9.1.20(@vitest/browser-playwright@4.1.2)(@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2))(@vitest/runner@4.1.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vitest@4.1.2) '@storybook/react': specifier: ^9.1.9 - version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3) + version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3) '@storybook/react-vite': specifier: ^9.1.3 - version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.59.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.59.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) '@testing-library/react': specifier: ^16.3.0 version: 16.3.0(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -914,10 +914,10 @@ importers: version: 19.2.3(@types/react@19.2.7) '@vitest/browser': specifier: ^4.1.2 - version: 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) + version: 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) '@vitest/browser-playwright': specifier: ^4.1.2 - version: 4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) + version: 4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) '@vitest/coverage-istanbul': specifier: 'catalog:' version: 4.1.2(vitest@4.1.2) @@ -935,13 +935,13 @@ importers: version: 6.0.1 storybook: specifier: 'catalog:' - version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) typescript: specifier: 'catalog:' version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/application-services: dependencies: @@ -2046,6 +2046,9 @@ importers: react: specifier: ^19.1.1 version: 19.2.0 + react-router-dom: + specifier: 'catalog:' + version: 7.12.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) devDependencies: '@cellix/config-typescript': specifier: workspace:* @@ -2062,6 +2065,9 @@ importers: jsdom: specifier: 'catalog:' version: 26.1.0 + react-dom: + specifier: ^19.1.1 + version: 19.2.0(react@19.2.0) typescript: specifier: 'catalog:' version: 6.0.3 @@ -12942,7 +12948,7 @@ snapshots: minimist: 1.2.8 parsecurrency: 1.1.1 ts-morph: 27.0.2 - vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@22.19.15)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) '@ant-design/cli@6.3.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)': dependencies: @@ -14282,6 +14288,18 @@ snapshots: '@blazediff/core@1.9.1': {} + '@chromatic-com/storybook@4.1.3(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': + dependencies: + '@neoconfetti/react': 1.0.0 + chromatic: 13.3.4 + filesize: 10.1.6 + jsonfile: 6.2.0 + storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + strip-ansi: 7.1.2 + transitivePeerDependencies: + - '@chromatic-com/cypress' + - '@chromatic-com/playwright' + '@chromatic-com/storybook@4.1.3(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: '@neoconfetti/react': 1.0.0 @@ -16271,6 +16289,15 @@ snapshots: '@types/yargs': 17.0.35 chalk: 4.1.2 + '@joshwooding/vite-plugin-react-docgen-typescript@0.6.1(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': + dependencies: + glob: 10.5.0 + magic-string: 0.30.21 + react-docgen-typescript: 2.4.0(typescript@6.0.3) + vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + optionalDependencies: + typescript: 6.0.3 + '@joshwooding/vite-plugin-react-docgen-typescript@0.6.1(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: glob: 10.5.0 @@ -17669,12 +17696,31 @@ snapshots: '@standard-schema/spec@1.1.0': {} + '@storybook/addon-a11y@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': + dependencies: + '@storybook/global': 5.0.0 + axe-core: 4.11.0 + storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@storybook/addon-a11y@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: '@storybook/global': 5.0.0 axe-core: 4.11.0 storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@storybook/addon-docs@9.1.16(@types/react@19.2.7)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': + dependencies: + '@mdx-js/react': 3.1.1(@types/react@19.2.7)(react@19.2.0) + '@storybook/csf-plugin': 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) + '@storybook/icons': 1.6.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@storybook/react-dom-shim': 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + ts-dedent: 2.2.0 + transitivePeerDependencies: + - '@types/react' + '@storybook/addon-docs@9.1.16(@types/react@19.2.7)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: '@mdx-js/react': 3.1.1(@types/react@19.2.7)(react@19.2.0) @@ -17688,6 +17734,10 @@ snapshots: transitivePeerDependencies: - '@types/react' + '@storybook/addon-onboarding@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': + dependencies: + storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@storybook/addon-onboarding@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) @@ -17708,6 +17758,22 @@ snapshots: - react - react-dom + '@storybook/addon-vitest@9.1.20(@vitest/browser-playwright@4.1.2)(@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2))(@vitest/runner@4.1.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vitest@4.1.2)': + dependencies: + '@storybook/global': 5.0.0 + '@storybook/icons': 1.6.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + prompts: 2.4.2 + storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + ts-dedent: 2.2.0 + optionalDependencies: + '@vitest/browser': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) + '@vitest/browser-playwright': 4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) + '@vitest/runner': 4.1.2 + vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + transitivePeerDependencies: + - react + - react-dom + '@storybook/addon-vitest@9.1.20(@vitest/browser-playwright@4.1.2)(@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2))(@vitest/runner@4.1.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vitest@4.1.2)': dependencies: '@storybook/global': 5.0.0 @@ -17724,6 +17790,13 @@ snapshots: - react - react-dom + '@storybook/builder-vite@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': + dependencies: + '@storybook/csf-plugin': 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) + storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + ts-dedent: 2.2.0 + vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + '@storybook/builder-vite@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@storybook/csf-plugin': 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) @@ -17731,6 +17804,11 @@ snapshots: ts-dedent: 2.2.0 vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + '@storybook/csf-plugin@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': + dependencies: + storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + unplugin: 1.16.1 + '@storybook/csf-plugin@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) @@ -17743,12 +17821,38 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) + '@storybook/react-dom-shim@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': + dependencies: + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@storybook/react-dom-shim@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@storybook/react-vite@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.59.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': + dependencies: + '@joshwooding/vite-plugin-react-docgen-typescript': 0.6.1(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@rollup/pluginutils': 5.3.0(rollup@4.59.0) + '@storybook/builder-vite': 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@storybook/react': 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3) + find-up: 7.0.0 + magic-string: 0.30.21 + react: 19.2.0 + react-docgen: 8.0.2 + react-dom: 19.2.0(react@19.2.0) + resolve: 1.22.11 + storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + tsconfig-paths: 4.2.0 + vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + transitivePeerDependencies: + - rollup + - supports-color + - typescript + '@storybook/react-vite@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.59.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@joshwooding/vite-plugin-react-docgen-typescript': 0.6.1(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) @@ -17769,6 +17873,16 @@ snapshots: - supports-color - typescript + '@storybook/react@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)': + dependencies: + '@storybook/global': 5.0.0 + '@storybook/react-dom-shim': 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + optionalDependencies: + typescript: 6.0.3 + '@storybook/react@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)': dependencies: '@storybook/global': 5.0.0 @@ -18276,6 +18390,19 @@ snapshots: - vite optional: true + '@vitest/browser-playwright@4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': + dependencies: + '@vitest/browser': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) + '@vitest/mocker': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + playwright: 1.59.0 + tinyrainbow: 3.1.0 + vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + '@vitest/browser-playwright@4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': dependencies: '@vitest/browser': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) @@ -18307,6 +18434,23 @@ snapshots: - vite optional: true + '@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': + dependencies: + '@blazediff/core': 1.9.1 + '@vitest/mocker': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/utils': 4.1.2 + magic-string: 0.30.21 + pngjs: 7.0.0 + sirv: 3.0.2 + tinyrainbow: 3.1.0 + vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + ws: 8.20.0 + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + '@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': dependencies: '@blazediff/core': 1.9.1 @@ -18336,7 +18480,7 @@ snapshots: magicast: 0.5.2 obug: 2.1.1 tinyrainbow: 3.1.0 - vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@22.19.15)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) transitivePeerDependencies: - supports-color @@ -18357,6 +18501,14 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 + '@vitest/mocker@3.2.4(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': + dependencies: + '@vitest/spy': 3.2.4 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + '@vitest/mocker@3.2.4(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@vitest/spy': 3.2.4 @@ -18373,6 +18525,14 @@ snapshots: optionalDependencies: vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@22.19.15)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + '@vitest/mocker@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': + dependencies: + '@vitest/spy': 4.1.2 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + '@vitest/mocker@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@vitest/spy': 4.1.2 @@ -24588,6 +24748,28 @@ snapshots: graphql: 16.12.0 react: 19.2.0 + storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): + dependencies: + '@storybook/global': 5.0.0 + '@testing-library/jest-dom': 6.9.1 + '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1) + '@vitest/expect': 3.2.4 + '@vitest/mocker': 3.2.4(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/spy': 3.2.4 + better-opn: 3.0.2 + esbuild: 0.25.12 + esbuild-register: 3.6.0(esbuild@0.25.12) + recast: 0.23.11 + semver: 7.7.3 + ws: 8.20.0 + transitivePeerDependencies: + - '@testing-library/dom' + - bufferutil + - msw + - supports-color + - utf-8-validate + - vite + storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): dependencies: '@storybook/global': 5.0.0 @@ -25314,6 +25496,26 @@ snapshots: - '@emnapi/core' - '@emnapi/runtime' + vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3): + dependencies: + lightningcss: 1.32.0 + picomatch: 4.0.4 + postcss: 8.5.10 + rolldown: 1.0.0-rc.12(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1) + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 24.10.1 + esbuild: 0.25.12 + fsevents: 2.3.3 + jiti: 2.6.1 + less: 4.4.2 + terser: 5.44.1 + tsx: 4.21.0 + yaml: 2.8.3 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3): dependencies: lightningcss: 1.32.0 @@ -25364,6 +25566,36 @@ snapshots: transitivePeerDependencies: - msw + vitest@4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): + dependencies: + '@vitest/expect': 4.1.2 + '@vitest/mocker': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/pretty-format': 4.1.2 + '@vitest/runner': 4.1.2 + '@vitest/snapshot': 4.1.2 + '@vitest/spy': 4.1.2 + '@vitest/utils': 4.1.2 + es-module-lexer: 2.0.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.4 + std-env: 4.0.0 + tinybench: 2.9.0 + tinyexec: 1.0.4 + tinyglobby: 0.2.15 + tinyrainbow: 3.1.0 + vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + why-is-node-running: 2.3.0 + optionalDependencies: + '@opentelemetry/api': 1.9.0 + '@types/node': 24.10.1 + '@vitest/browser-playwright': 4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) + jsdom: 26.1.0 + transitivePeerDependencies: + - msw + vitest@4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): dependencies: '@vitest/expect': 4.1.2 From ac69b4ef5b46fe0e8ec007055d8cda74a7ecb31e Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Mon, 4 May 2026 21:55:04 +0530 Subject: [PATCH 37/88] test(ui-staff): add route-authorization scenario tests for all 4 Entra app roles (#214) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tests cover every role × route combination: - Staff.TechAdmin: /staff/tech allowed, all others blocked - Staff.Finance: /staff/finance allowed, all others blocked - Staff.CaseManager: /staff/community + /staff/users allowed, others blocked - Staff.ServiceLineOwner: /staff/community + /staff/users allowed, others blocked - No roles: all /staff/* routes blocked Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- apps/ui-staff/package.json | 2 +- apps/ui-staff/src/App.test.tsx | 183 +++++++++++++++++++++++++++++---- 2 files changed, 163 insertions(+), 22 deletions(-) diff --git a/apps/ui-staff/package.json b/apps/ui-staff/package.json index e1a705536..130b030e5 100644 --- a/apps/ui-staff/package.json +++ b/apps/ui-staff/package.json @@ -9,7 +9,7 @@ "format:check": "biome format .", "prebuild": "pnpm run lint", "build": "tsgo --build && vite build", - "dev": "node ../../build-pipeline/scripts/portless-dev.mjs staff.ownercommunity.localhost vite", + "dev": "pnpm exec portless staff.ownercommunity.localhost --force vite", "start": "vite", "preview": "vite preview", "test": "vitest run --silent --reporter=dot", diff --git a/apps/ui-staff/src/App.test.tsx b/apps/ui-staff/src/App.test.tsx index 09dbae32b..eca1e2973 100644 --- a/apps/ui-staff/src/App.test.tsx +++ b/apps/ui-staff/src/App.test.tsx @@ -1,43 +1,184 @@ import * as React from 'react'; import { renderToString } from 'react-dom/server'; import { MemoryRouter } from 'react-router-dom'; -import { describe, expect, it, vi } from 'vitest'; +import { describe, expect, it, vi, beforeEach } from 'vitest'; -// Mock RequireAuth from @cellix/ui-core so tests don't depend on oidc context behavior +// Mock RequireAuth so tests don't depend on OIDC context behavior vi.mock('@cellix/ui-core', () => ({ RequireAuth: ({ children }: { children: React.ReactNode }) => React.createElement(React.Fragment, {}, children), })); +// Mock ApolloConnection so tests don't need a GraphQL server +vi.mock('./components/ui/organisms/apollo-connection/index.tsx', () => ({ + ApolloConnection: ({ children }: { children: React.ReactNode }) => React.createElement(React.Fragment, {}, children), +})); + +// Mock route packages with identifiable content per section +vi.mock('@ocom/ui-staff-route-root', () => ({ Root: () => React.createElement('div', {}, 'root-section') })); +vi.mock('@ocom/ui-staff-route-community-management', () => ({ Root: () => React.createElement('div', {}, 'community-management-section') })); +vi.mock('@ocom/ui-staff-route-user-management', () => ({ Root: () => React.createElement('div', {}, 'user-management-section') })); +vi.mock('@ocom/ui-staff-route-finance', () => ({ Root: () => React.createElement('div', {}, 'finance-section') })); +vi.mock('@ocom/ui-staff-route-tech-admin', () => ({ Root: () => React.createElement('div', {}, 'tech-admin-section') })); + +// Helper to mock useAuth with a specific roles claim in the OIDC profile +function mockAuthWithRoles(roles: string[]) { + vi.doMock('react-oidc-context', () => ({ + useAuth: () => ({ + user: { profile: { roles, email: 'staff@test.com', given_name: 'Staff', family_name: 'User' } }, + signoutRedirect: vi.fn(), + }), + })); +} + +function mockAuthNoUser() { + vi.doMock('react-oidc-context', () => ({ + useAuth: () => ({ + user: null, + signoutRedirect: vi.fn(), + }), + })); +} + +async function renderAppAt(path: string): Promise { + // Re-import App after mock changes so module is fresh + const { default: App } = await import('./App'); + return renderToString( + + + , + ); +} + import App from './App'; -describe('App', () => { +describe('App – static routes', () => { it('renders root section without throwing', () => { - const html = renderToString( - - - , - ); + const html = renderToString(); expect(typeof html).toBe('string'); expect(html.length).toBeGreaterThan(0); }); it('renders auth-redirect route without throwing', () => { - const html = renderToString( - - - , - ); + const html = renderToString(); expect(typeof html).toBe('string'); - // Navigate may render no markup during SSR; ensure render does not throw and returns a string }); - it('renders unauthorized route without throwing and contains Unauthorized text', () => { - const html = renderToString( - - - , - ); - expect(typeof html).toBe('string'); + it('/unauthorized renders the Unauthorized page', () => { + const html = renderToString(); expect(html).toContain('Unauthorized'); }); }); + +describe('App – role authorization: Staff.TechAdmin', () => { + beforeEach(() => { mockAuthWithRoles(['Staff.TechAdmin']); vi.resetModules(); }); + + it('/staff/tech → renders tech-admin section', async () => { + expect(await renderAppAt('/staff/tech')).toContain('tech-admin-section'); + }); + + it('/staff/community → redirects to /unauthorized (not rendered)', async () => { + const html = await renderAppAt('/staff/community'); + expect(html).not.toContain('community-management-section'); + }); + + it('/staff/users → redirects to /unauthorized (not rendered)', async () => { + const html = await renderAppAt('/staff/users'); + expect(html).not.toContain('user-management-section'); + }); + + it('/staff/finance → redirects to /unauthorized (not rendered)', async () => { + const html = await renderAppAt('/staff/finance'); + expect(html).not.toContain('finance-section'); + }); +}); + +describe('App – role authorization: Staff.Finance', () => { + beforeEach(() => { mockAuthWithRoles(['Staff.Finance']); vi.resetModules(); }); + + it('/staff/finance → renders finance section', async () => { + expect(await renderAppAt('/staff/finance')).toContain('finance-section'); + }); + + it('/staff/community → redirects to /unauthorized (not rendered)', async () => { + const html = await renderAppAt('/staff/community'); + expect(html).not.toContain('community-management-section'); + }); + + it('/staff/users → redirects to /unauthorized (not rendered)', async () => { + const html = await renderAppAt('/staff/users'); + expect(html).not.toContain('user-management-section'); + }); + + it('/staff/tech → redirects to /unauthorized (not rendered)', async () => { + const html = await renderAppAt('/staff/tech'); + expect(html).not.toContain('tech-admin-section'); + }); +}); + +describe('App – role authorization: Staff.CaseManager', () => { + beforeEach(() => { mockAuthWithRoles(['Staff.CaseManager']); vi.resetModules(); }); + + it('/staff/community → renders community-management section', async () => { + expect(await renderAppAt('/staff/community')).toContain('community-management-section'); + }); + + it('/staff/users → renders user-management section', async () => { + expect(await renderAppAt('/staff/users')).toContain('user-management-section'); + }); + + it('/staff/finance → redirects to /unauthorized (not rendered)', async () => { + const html = await renderAppAt('/staff/finance'); + expect(html).not.toContain('finance-section'); + }); + + it('/staff/tech → redirects to /unauthorized (not rendered)', async () => { + const html = await renderAppAt('/staff/tech'); + expect(html).not.toContain('tech-admin-section'); + }); +}); + +describe('App – role authorization: Staff.ServiceLineOwner', () => { + beforeEach(() => { mockAuthWithRoles(['Staff.ServiceLineOwner']); vi.resetModules(); }); + + it('/staff/community → renders community-management section', async () => { + expect(await renderAppAt('/staff/community')).toContain('community-management-section'); + }); + + it('/staff/users → renders user-management section', async () => { + expect(await renderAppAt('/staff/users')).toContain('user-management-section'); + }); + + it('/staff/finance → redirects to /unauthorized (not rendered)', async () => { + const html = await renderAppAt('/staff/finance'); + expect(html).not.toContain('finance-section'); + }); + + it('/staff/tech → redirects to /unauthorized (not rendered)', async () => { + const html = await renderAppAt('/staff/tech'); + expect(html).not.toContain('tech-admin-section'); + }); +}); + +describe('App – role authorization: no roles', () => { + beforeEach(() => { mockAuthNoUser(); vi.resetModules(); }); + + it('/staff/community → redirects to /unauthorized', async () => { + const html = await renderAppAt('/staff/community'); + expect(html).not.toContain('community-management-section'); + }); + + it('/staff/users → redirects to /unauthorized', async () => { + const html = await renderAppAt('/staff/users'); + expect(html).not.toContain('user-management-section'); + }); + + it('/staff/finance → redirects to /unauthorized', async () => { + const html = await renderAppAt('/staff/finance'); + expect(html).not.toContain('finance-section'); + }); + + it('/staff/tech → redirects to /unauthorized', async () => { + const html = await renderAppAt('/staff/tech'); + expect(html).not.toContain('tech-admin-section'); + }); +}); From 440c0222aac1222c5435292a6feb5be90a6cd437 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Mon, 4 May 2026 21:59:19 +0530 Subject: [PATCH 38/88] chore(ui-staff-routes): remove unused deps flagged by knip Remove antd and react-dom from dependencies where unused, and storybook from devDependencies across all ui-staff-route-* packages. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../package.json | 5 +- .../ocom/ui-staff-route-finance/package.json | 5 +- .../ocom/ui-staff-route-root/package.json | 1 - .../ui-staff-route-tech-admin/package.json | 2 - .../package.json | 1 - pnpm-lock.yaml | 282 +----------------- 6 files changed, 15 insertions(+), 281 deletions(-) diff --git a/packages/ocom/ui-staff-route-community-management/package.json b/packages/ocom/ui-staff-route-community-management/package.json index 238a3caf6..963bf382f 100644 --- a/packages/ocom/ui-staff-route-community-management/package.json +++ b/packages/ocom/ui-staff-route-community-management/package.json @@ -18,9 +18,7 @@ }, "dependencies": { "@ocom/ui-staff-shared": "workspace:*", - "antd": "catalog:", - "react": "^19.1.1", - "react-dom": "^19.1.1" + "react": "^19.1.1" }, "devDependencies": { "@cellix/config-typescript": "workspace:*", @@ -28,7 +26,6 @@ "@types/react": "^19.1.11", "@types/react-dom": "^19.1.6", "jsdom": "catalog:", - "storybook": "catalog:", "vite": "catalog:", "vitest": "catalog:", "typescript": "catalog:" diff --git a/packages/ocom/ui-staff-route-finance/package.json b/packages/ocom/ui-staff-route-finance/package.json index e447d758d..ebcbda229 100644 --- a/packages/ocom/ui-staff-route-finance/package.json +++ b/packages/ocom/ui-staff-route-finance/package.json @@ -18,9 +18,7 @@ }, "dependencies": { "@ocom/ui-staff-shared": "workspace:*", - "antd": "catalog:", - "react": "^19.1.1", - "react-dom": "^19.1.1" + "react": "^19.1.1" }, "devDependencies": { "@cellix/config-typescript": "workspace:*", @@ -28,7 +26,6 @@ "@types/react": "^19.1.11", "@types/react-dom": "^19.1.6", "jsdom": "catalog:", - "storybook": "catalog:", "vite": "catalog:", "vitest": "catalog:", "typescript": "catalog:" diff --git a/packages/ocom/ui-staff-route-root/package.json b/packages/ocom/ui-staff-route-root/package.json index a5247dba1..ba3e1ac88 100644 --- a/packages/ocom/ui-staff-route-root/package.json +++ b/packages/ocom/ui-staff-route-root/package.json @@ -26,7 +26,6 @@ "@types/react": "^19.1.11", "@types/react-dom": "^19.1.6", "jsdom": "catalog:", - "storybook": "catalog:", "vite": "catalog:", "vitest": "catalog:", "typescript": "catalog:" diff --git a/packages/ocom/ui-staff-route-tech-admin/package.json b/packages/ocom/ui-staff-route-tech-admin/package.json index 679775efe..de373dad0 100644 --- a/packages/ocom/ui-staff-route-tech-admin/package.json +++ b/packages/ocom/ui-staff-route-tech-admin/package.json @@ -16,7 +16,6 @@ }, "dependencies": { "@ocom/ui-staff-shared": "workspace:*", - "antd": "catalog:", "react": "^19.1.1" }, "devDependencies": { @@ -25,7 +24,6 @@ "@types/react": "^19.1.11", "@types/react-dom": "^19.1.6", "jsdom": "catalog:", - "storybook": "catalog:", "vite": "catalog:", "vitest": "catalog:", "typescript": "catalog:" diff --git a/packages/ocom/ui-staff-route-user-management/package.json b/packages/ocom/ui-staff-route-user-management/package.json index 082009e4e..5761918e4 100644 --- a/packages/ocom/ui-staff-route-user-management/package.json +++ b/packages/ocom/ui-staff-route-user-management/package.json @@ -24,7 +24,6 @@ "@types/react": "^19.1.11", "@types/react-dom": "^19.1.6", "jsdom": "catalog:", - "storybook": "catalog:", "vite": "catalog:", "vitest": "catalog:", "typescript": "catalog:" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8044cbbc0..5599d2074 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -890,25 +890,25 @@ importers: version: link:../config-vitest '@chromatic-com/storybook': specifier: ^4.1.1 - version: 4.1.3(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) + version: 4.1.3(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) '@storybook/addon-a11y': specifier: ^9.1.3 - version: 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) + version: 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) '@storybook/addon-docs': specifier: ^9.1.3 - version: 9.1.16(@types/react@19.2.7)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) + version: 9.1.16(@types/react@19.2.7)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) '@storybook/addon-onboarding': specifier: ^9.1.3 - version: 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) + version: 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) '@storybook/addon-vitest': specifier: ^9.1.3 - version: 9.1.20(@vitest/browser-playwright@4.1.2)(@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2))(@vitest/runner@4.1.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vitest@4.1.2) + version: 9.1.20(@vitest/browser-playwright@4.1.2)(@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2))(@vitest/runner@4.1.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vitest@4.1.2) '@storybook/react': specifier: ^9.1.9 - version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3) + version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3) '@storybook/react-vite': specifier: ^9.1.3 - version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.59.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.59.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) '@testing-library/react': specifier: ^16.3.0 version: 16.3.0(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -920,10 +920,10 @@ importers: version: 19.2.3(@types/react@19.2.7) '@vitest/browser': specifier: ^4.1.2 - version: 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) + version: 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) '@vitest/browser-playwright': specifier: ^4.1.2 - version: 4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) + version: 4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) '@vitest/coverage-istanbul': specifier: 'catalog:' version: 4.1.2(vitest@4.1.2) @@ -941,13 +941,13 @@ importers: version: 6.0.1 storybook: specifier: 'catalog:' - version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) typescript: specifier: 'catalog:' version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/application-services: dependencies: @@ -1846,15 +1846,9 @@ importers: '@ocom/ui-staff-shared': specifier: workspace:* version: link:../ui-staff-shared - antd: - specifier: 'catalog:' - version: 6.3.5(luxon@3.6.1)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: specifier: ^19.1.1 version: 19.2.0 - react-dom: - specifier: ^19.1.1 - version: 19.2.0(react@19.2.0) devDependencies: '@cellix/config-typescript': specifier: workspace:* @@ -1871,9 +1865,6 @@ importers: jsdom: specifier: 'catalog:' version: 26.1.0 - storybook: - specifier: 'catalog:' - version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) typescript: specifier: 'catalog:' version: 6.0.3 @@ -1889,15 +1880,9 @@ importers: '@ocom/ui-staff-shared': specifier: workspace:* version: link:../ui-staff-shared - antd: - specifier: 'catalog:' - version: 6.3.5(luxon@3.6.1)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: specifier: ^19.1.1 version: 19.2.0 - react-dom: - specifier: ^19.1.1 - version: 19.2.0(react@19.2.0) devDependencies: '@cellix/config-typescript': specifier: workspace:* @@ -1914,9 +1899,6 @@ importers: jsdom: specifier: 'catalog:' version: 26.1.0 - storybook: - specifier: 'catalog:' - version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) typescript: specifier: 'catalog:' version: 6.0.3 @@ -1957,9 +1939,6 @@ importers: jsdom: specifier: 'catalog:' version: 26.1.0 - storybook: - specifier: 'catalog:' - version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) typescript: specifier: 'catalog:' version: 6.0.3 @@ -1975,9 +1954,6 @@ importers: '@ocom/ui-staff-shared': specifier: workspace:* version: link:../ui-staff-shared - antd: - specifier: 'catalog:' - version: 6.3.5(luxon@3.6.1)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: specifier: ^19.1.1 version: 19.2.0 @@ -1997,9 +1973,6 @@ importers: jsdom: specifier: 'catalog:' version: 26.1.0 - storybook: - specifier: 'catalog:' - version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) typescript: specifier: 'catalog:' version: 6.0.3 @@ -2034,9 +2007,6 @@ importers: jsdom: specifier: 'catalog:' version: 26.1.0 - storybook: - specifier: 'catalog:' - version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) typescript: specifier: 'catalog:' version: 6.0.3 @@ -12954,7 +12924,7 @@ snapshots: minimist: 1.2.8 parsecurrency: 1.1.1 ts-morph: 27.0.2 - vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@22.19.15)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) '@ant-design/cli@6.3.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)': dependencies: @@ -14294,18 +14264,6 @@ snapshots: '@blazediff/core@1.9.1': {} - '@chromatic-com/storybook@4.1.3(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': - dependencies: - '@neoconfetti/react': 1.0.0 - chromatic: 13.3.4 - filesize: 10.1.6 - jsonfile: 6.2.0 - storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - strip-ansi: 7.1.2 - transitivePeerDependencies: - - '@chromatic-com/cypress' - - '@chromatic-com/playwright' - '@chromatic-com/storybook@4.1.3(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: '@neoconfetti/react': 1.0.0 @@ -16295,15 +16253,6 @@ snapshots: '@types/yargs': 17.0.35 chalk: 4.1.2 - '@joshwooding/vite-plugin-react-docgen-typescript@0.6.1(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': - dependencies: - glob: 10.5.0 - magic-string: 0.30.21 - react-docgen-typescript: 2.4.0(typescript@6.0.3) - vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) - optionalDependencies: - typescript: 6.0.3 - '@joshwooding/vite-plugin-react-docgen-typescript@0.6.1(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: glob: 10.5.0 @@ -17702,31 +17651,12 @@ snapshots: '@standard-schema/spec@1.1.0': {} - '@storybook/addon-a11y@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': - dependencies: - '@storybook/global': 5.0.0 - axe-core: 4.11.0 - storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@storybook/addon-a11y@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: '@storybook/global': 5.0.0 axe-core: 4.11.0 storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@storybook/addon-docs@9.1.16(@types/react@19.2.7)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': - dependencies: - '@mdx-js/react': 3.1.1(@types/react@19.2.7)(react@19.2.0) - '@storybook/csf-plugin': 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) - '@storybook/icons': 1.6.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@storybook/react-dom-shim': 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) - react: 19.2.0 - react-dom: 19.2.0(react@19.2.0) - storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - ts-dedent: 2.2.0 - transitivePeerDependencies: - - '@types/react' - '@storybook/addon-docs@9.1.16(@types/react@19.2.7)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: '@mdx-js/react': 3.1.1(@types/react@19.2.7)(react@19.2.0) @@ -17740,10 +17670,6 @@ snapshots: transitivePeerDependencies: - '@types/react' - '@storybook/addon-onboarding@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': - dependencies: - storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@storybook/addon-onboarding@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) @@ -17764,22 +17690,6 @@ snapshots: - react - react-dom - '@storybook/addon-vitest@9.1.20(@vitest/browser-playwright@4.1.2)(@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2))(@vitest/runner@4.1.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vitest@4.1.2)': - dependencies: - '@storybook/global': 5.0.0 - '@storybook/icons': 1.6.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - prompts: 2.4.2 - storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - ts-dedent: 2.2.0 - optionalDependencies: - '@vitest/browser': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) - '@vitest/browser-playwright': 4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) - '@vitest/runner': 4.1.2 - vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - transitivePeerDependencies: - - react - - react-dom - '@storybook/addon-vitest@9.1.20(@vitest/browser-playwright@4.1.2)(@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2))(@vitest/runner@4.1.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vitest@4.1.2)': dependencies: '@storybook/global': 5.0.0 @@ -17796,13 +17706,6 @@ snapshots: - react - react-dom - '@storybook/builder-vite@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': - dependencies: - '@storybook/csf-plugin': 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) - storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - ts-dedent: 2.2.0 - vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) - '@storybook/builder-vite@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@storybook/csf-plugin': 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) @@ -17810,11 +17713,6 @@ snapshots: ts-dedent: 2.2.0 vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) - '@storybook/csf-plugin@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': - dependencies: - storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - unplugin: 1.16.1 - '@storybook/csf-plugin@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) @@ -17827,38 +17725,12 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@storybook/react-dom-shim@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': - dependencies: - react: 19.2.0 - react-dom: 19.2.0(react@19.2.0) - storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@storybook/react-dom-shim@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@storybook/react-vite@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.59.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': - dependencies: - '@joshwooding/vite-plugin-react-docgen-typescript': 0.6.1(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@rollup/pluginutils': 5.3.0(rollup@4.59.0) - '@storybook/builder-vite': 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@storybook/react': 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3) - find-up: 7.0.0 - magic-string: 0.30.21 - react: 19.2.0 - react-docgen: 8.0.2 - react-dom: 19.2.0(react@19.2.0) - resolve: 1.22.11 - storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - tsconfig-paths: 4.2.0 - vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) - transitivePeerDependencies: - - rollup - - supports-color - - typescript - '@storybook/react-vite@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.59.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@joshwooding/vite-plugin-react-docgen-typescript': 0.6.1(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) @@ -17879,16 +17751,6 @@ snapshots: - supports-color - typescript - '@storybook/react@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)': - dependencies: - '@storybook/global': 5.0.0 - '@storybook/react-dom-shim': 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) - react: 19.2.0 - react-dom: 19.2.0(react@19.2.0) - storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - optionalDependencies: - typescript: 6.0.3 - '@storybook/react@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)': dependencies: '@storybook/global': 5.0.0 @@ -18396,19 +18258,6 @@ snapshots: - vite optional: true - '@vitest/browser-playwright@4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': - dependencies: - '@vitest/browser': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) - '@vitest/mocker': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - playwright: 1.59.0 - tinyrainbow: 3.1.0 - vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - transitivePeerDependencies: - - bufferutil - - msw - - utf-8-validate - - vite - '@vitest/browser-playwright@4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': dependencies: '@vitest/browser': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) @@ -18440,23 +18289,6 @@ snapshots: - vite optional: true - '@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': - dependencies: - '@blazediff/core': 1.9.1 - '@vitest/mocker': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@vitest/utils': 4.1.2 - magic-string: 0.30.21 - pngjs: 7.0.0 - sirv: 3.0.2 - tinyrainbow: 3.1.0 - vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - ws: 8.20.0 - transitivePeerDependencies: - - bufferutil - - msw - - utf-8-validate - - vite - '@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': dependencies: '@blazediff/core': 1.9.1 @@ -18486,7 +18318,7 @@ snapshots: magicast: 0.5.2 obug: 2.1.1 tinyrainbow: 3.1.0 - vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@22.19.15)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) transitivePeerDependencies: - supports-color @@ -18507,14 +18339,6 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@3.2.4(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': - dependencies: - '@vitest/spy': 3.2.4 - estree-walker: 3.0.3 - magic-string: 0.30.21 - optionalDependencies: - vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) - '@vitest/mocker@3.2.4(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@vitest/spy': 3.2.4 @@ -18531,14 +18355,6 @@ snapshots: optionalDependencies: vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@22.19.15)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) - '@vitest/mocker@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': - dependencies: - '@vitest/spy': 4.1.2 - estree-walker: 3.0.3 - magic-string: 0.30.21 - optionalDependencies: - vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) - '@vitest/mocker@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@vitest/spy': 4.1.2 @@ -24754,28 +24570,6 @@ snapshots: graphql: 16.12.0 react: 19.2.0 - storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): - dependencies: - '@storybook/global': 5.0.0 - '@testing-library/jest-dom': 6.9.1 - '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1) - '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@vitest/spy': 3.2.4 - better-opn: 3.0.2 - esbuild: 0.25.12 - esbuild-register: 3.6.0(esbuild@0.25.12) - recast: 0.23.11 - semver: 7.7.3 - ws: 8.20.0 - transitivePeerDependencies: - - '@testing-library/dom' - - bufferutil - - msw - - supports-color - - utf-8-validate - - vite - storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): dependencies: '@storybook/global': 5.0.0 @@ -25502,26 +25296,6 @@ snapshots: - '@emnapi/core' - '@emnapi/runtime' - vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3): - dependencies: - lightningcss: 1.32.0 - picomatch: 4.0.4 - postcss: 8.5.10 - rolldown: 1.0.0-rc.12(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1) - tinyglobby: 0.2.15 - optionalDependencies: - '@types/node': 24.10.1 - esbuild: 0.25.12 - fsevents: 2.3.3 - jiti: 2.6.1 - less: 4.4.2 - terser: 5.44.1 - tsx: 4.21.0 - yaml: 2.8.3 - transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' - vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3): dependencies: lightningcss: 1.32.0 @@ -25572,36 +25346,6 @@ snapshots: transitivePeerDependencies: - msw - vitest@4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): - dependencies: - '@vitest/expect': 4.1.2 - '@vitest/mocker': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@vitest/pretty-format': 4.1.2 - '@vitest/runner': 4.1.2 - '@vitest/snapshot': 4.1.2 - '@vitest/spy': 4.1.2 - '@vitest/utils': 4.1.2 - es-module-lexer: 2.0.0 - expect-type: 1.3.0 - magic-string: 0.30.21 - obug: 2.1.1 - pathe: 2.0.3 - picomatch: 4.0.4 - std-env: 4.0.0 - tinybench: 2.9.0 - tinyexec: 1.0.4 - tinyglobby: 0.2.15 - tinyrainbow: 3.1.0 - vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) - why-is-node-running: 2.3.0 - optionalDependencies: - '@opentelemetry/api': 1.9.0 - '@types/node': 24.10.1 - '@vitest/browser-playwright': 4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) - jsdom: 26.1.0 - transitivePeerDependencies: - - msw - vitest@4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): dependencies: '@vitest/expect': 4.1.2 From 3bfe580d68d764836a2ef46071c6653c2ad48345 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Mon, 4 May 2026 22:06:27 +0530 Subject: [PATCH 39/88] Revert package.json --- apps/ui-staff/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ui-staff/package.json b/apps/ui-staff/package.json index 130b030e5..e1a705536 100644 --- a/apps/ui-staff/package.json +++ b/apps/ui-staff/package.json @@ -9,7 +9,7 @@ "format:check": "biome format .", "prebuild": "pnpm run lint", "build": "tsgo --build && vite build", - "dev": "pnpm exec portless staff.ownercommunity.localhost --force vite", + "dev": "node ../../build-pipeline/scripts/portless-dev.mjs staff.ownercommunity.localhost vite", "start": "vite", "preview": "vite preview", "test": "vitest run --silent --reporter=dot", From f1e381af18d2f9bf3ece684e8d9abf5de05ed02e Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Mon, 4 May 2026 22:46:53 +0530 Subject: [PATCH 40/88] test(ui-staff): add Playwright e2e tests for role-based route authorization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Covers all 4 Entra app-role × 4 route combinations (20 access tests) plus 3 nav-link visibility tests = 23 tests total. Strategy: inject a fake OIDC session into sessionStorage via page.addInitScript() before the app loads. oidc-client-ts restores stored users without re-validating the JWT signature, so each test can control the user's roles independently without restarting the mock auth server. Test matrix: - Staff.TechAdmin: /tech ✓, /finance ✗, /community ✗, /users ✗ - Staff.Finance: /finance ✓, /tech ✗, /community ✗, /users ✗ - Staff.CaseManager: /community ✓, /users ✓, /finance ✗, /tech ✗ - Staff.ServiceLineOwner:/community ✓, /users ✓, /finance ✗, /tech ✗ - No roles: all 4 routes ✗ Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- apps/ui-staff/e2e/role-authorization.spec.ts | 285 +++++++++++++++++++ apps/ui-staff/package.json | 2 +- apps/ui-staff/playwright.config.ts | 24 ++ 3 files changed, 310 insertions(+), 1 deletion(-) create mode 100644 apps/ui-staff/e2e/role-authorization.spec.ts create mode 100644 apps/ui-staff/playwright.config.ts diff --git a/apps/ui-staff/e2e/role-authorization.spec.ts b/apps/ui-staff/e2e/role-authorization.spec.ts new file mode 100644 index 000000000..3f89a333c --- /dev/null +++ b/apps/ui-staff/e2e/role-authorization.spec.ts @@ -0,0 +1,285 @@ +/** + * Playwright e2e tests: Entra app-role route authorization for the ui-staff portal. + * + * Strategy: inject a fake OIDC session directly into sessionStorage before page load. + * This lets us test every role × route combination without restarting the mock auth server. + * + * The OIDC authority / client_id values must match apps/ui-staff/src/config/oidc-config.tsx. + */ +import { expect, test, type Page } from '@playwright/test'; + +// --- Constants matching oidc-config.tsx --- +const AUTHORITY = 'https://mock-auth.ownercommunity.localhost:1355/staff'; +const CLIENT_ID = 'mock-client'; +const STORAGE_KEY = `oidc.user:${AUTHORITY}:${CLIENT_ID}`; + +// --- Helpers --- + +function b64url(obj: Record): string { + return Buffer.from(JSON.stringify(obj)).toString('base64url'); +} + +/** + * Builds a minimal but structurally valid OIDC User JSON suitable for + * sessionStorage injection. oidc-client-ts restores stored users without + * re-validating the JWT signature, so the token strings only need to be + * three-part base64url values. + */ +function buildOidcSession(roles: string[], name = 'Test User', email = 'testuser@example.com'): string { + const now = Math.floor(Date.now() / 1000); + const exp = now + 3600; // 1 hour from now — prevents automatic silent refresh + const profile = { + sub: 'test-user-id', + iss: AUTHORITY, + aud: CLIENT_ID, + exp, + iat: now, + name, + email, + roles, + }; + const header = b64url({ alg: 'RS256', typ: 'JWT' }); + const payload = b64url(profile); + // Signature is not validated on storage restore — use a placeholder + const fakeJwt = `${header}.${payload}.fakeSignatureForE2ETesting`; + + return JSON.stringify({ + id_token: fakeJwt, + session_state: null, + access_token: fakeJwt, + refresh_token: null, + token_type: 'Bearer', + scope: 'openid', + profile, + expires_at: exp, + }); +} + +/** Injects an OIDC session into sessionStorage before any page script runs. */ +async function injectOidcSession(page: Page, roles: string[]): Promise { + const sessionValue = buildOidcSession(roles); + await page.addInitScript( + ({ key, value }: { key: string; value: string }) => { + sessionStorage.setItem(key, value); + }, + { key: STORAGE_KEY, value: sessionValue }, + ); +} + +// --- Test matrix --- + +const ROUTES = { + community: '/staff/community', + users: '/staff/users', + finance: '/staff/finance', + tech: '/staff/tech', +} as const; + +const ROLES = { + TechAdmin: 'Staff.TechAdmin', + Finance: 'Staff.Finance', + ServiceLineOwner: 'Staff.ServiceLineOwner', + CaseManager: 'Staff.CaseManager', +} as const; + +/** + * Navigates to a path and waits for the React app to have rendered meaningful content. + * Guards against the portless proxy returning a 404 before the app is registered. + */ +async function navigateTo(page: Page, path: string): Promise { + await page.goto(path, { waitUntil: 'domcontentloaded' }); + // Wait for the React root to contain rendered content (i.e., the app mounted) + await page.waitForFunction(() => { + const root = document.getElementById('root'); + return root && root.childElementCount > 0; + }, { timeout: 8000 }); +} + +/** The section title is rendered as a heading — use heading role to avoid matching nav labels. */ +async function expectAuthorized(page: Page, sectionTitle: string): Promise { + // The StaffRouteShell renders the section title as a plain div with fontSize 22px, + // so we find it by its exact text within the header area. + await expect(page.getByText(sectionTitle, { exact: true }).first()).toBeVisible({ timeout: 8000 }); + await expect(page.locator('h2').filter({ hasText: 'Unauthorized' })).not.toBeVisible(); +} + +async function expectUnauthorized(page: Page): Promise { + await expect(page.locator('h2').filter({ hasText: 'Unauthorized' })).toBeVisible({ timeout: 8000 }); + await expect(page.getByText('You do not have permission to view this page.')).toBeVisible(); +} + +// ============================================================ +// Staff.TechAdmin +// ============================================================ +test.describe('Staff.TechAdmin role', () => { + test.beforeEach(async ({ page }) => { + await injectOidcSession(page, [ROLES.TechAdmin]); + }); + + test('can access /staff/tech', async ({ page }) => { + await navigateTo(page, ROUTES.tech); + await expectAuthorized(page, 'Tech Admin'); + }); + + test('is denied /staff/finance', async ({ page }) => { + await navigateTo(page, ROUTES.finance); + await expectUnauthorized(page); + }); + + test('is denied /staff/community', async ({ page }) => { + await navigateTo(page, ROUTES.community); + await expectUnauthorized(page); + }); + + test('is denied /staff/users', async ({ page }) => { + await navigateTo(page, ROUTES.users); + await expectUnauthorized(page); + }); +}); + +// ============================================================ +// Staff.Finance +// ============================================================ +test.describe('Staff.Finance role', () => { + test.beforeEach(async ({ page }) => { + await injectOidcSession(page, [ROLES.Finance]); + }); + + test('can access /staff/finance', async ({ page }) => { + await navigateTo(page, ROUTES.finance); + await expectAuthorized(page, 'Finance'); + }); + + test('is denied /staff/tech', async ({ page }) => { + await navigateTo(page, ROUTES.tech); + await expectUnauthorized(page); + }); + + test('is denied /staff/community', async ({ page }) => { + await navigateTo(page, ROUTES.community); + await expectUnauthorized(page); + }); + + test('is denied /staff/users', async ({ page }) => { + await navigateTo(page, ROUTES.users); + await expectUnauthorized(page); + }); +}); + +// ============================================================ +// Staff.CaseManager +// ============================================================ +test.describe('Staff.CaseManager role', () => { + test.beforeEach(async ({ page }) => { + await injectOidcSession(page, [ROLES.CaseManager]); + }); + + test('can access /staff/community', async ({ page }) => { + await navigateTo(page, ROUTES.community); + await expectAuthorized(page, 'Community Management'); + }); + + test('can access /staff/users', async ({ page }) => { + await navigateTo(page, ROUTES.users); + await expectAuthorized(page, 'User Management'); + }); + + test('is denied /staff/finance', async ({ page }) => { + await navigateTo(page, ROUTES.finance); + await expectUnauthorized(page); + }); + + test('is denied /staff/tech', async ({ page }) => { + await navigateTo(page, ROUTES.tech); + await expectUnauthorized(page); + }); +}); + +// ============================================================ +// Staff.ServiceLineOwner +// ============================================================ +test.describe('Staff.ServiceLineOwner role', () => { + test.beforeEach(async ({ page }) => { + await injectOidcSession(page, [ROLES.ServiceLineOwner]); + }); + + test('can access /staff/community', async ({ page }) => { + await navigateTo(page, ROUTES.community); + await expectAuthorized(page, 'Community Management'); + }); + + test('can access /staff/users', async ({ page }) => { + await navigateTo(page, ROUTES.users); + await expectAuthorized(page, 'User Management'); + }); + + test('is denied /staff/finance', async ({ page }) => { + await navigateTo(page, ROUTES.finance); + await expectUnauthorized(page); + }); + + test('is denied /staff/tech', async ({ page }) => { + await navigateTo(page, ROUTES.tech); + await expectUnauthorized(page); + }); +}); + +// ============================================================ +// No roles (authenticated but no app roles) +// ============================================================ +test.describe('No app roles (authenticated, no roles)', () => { + test.beforeEach(async ({ page }) => { + await injectOidcSession(page, []); + }); + + test('is denied /staff/community', async ({ page }) => { + await navigateTo(page, ROUTES.community); + await expectUnauthorized(page); + }); + + test('is denied /staff/users', async ({ page }) => { + await navigateTo(page, ROUTES.users); + await expectUnauthorized(page); + }); + + test('is denied /staff/finance', async ({ page }) => { + await navigateTo(page, ROUTES.finance); + await expectUnauthorized(page); + }); + + test('is denied /staff/tech', async ({ page }) => { + await navigateTo(page, ROUTES.tech); + await expectUnauthorized(page); + }); +}); + +// ============================================================ +// Nav link visibility +// ============================================================ +test.describe('Nav link visibility in StaffRouteShell', () => { + test('TechAdmin sees only Tech Admin nav link', async ({ page }) => { + await injectOidcSession(page, [ROLES.TechAdmin]); + await navigateTo(page, ROUTES.tech); + await expect(page.getByRole('link', { name: 'Tech Admin' })).toBeVisible({ timeout: 5000 }); + await expect(page.getByRole('link', { name: 'Finance' })).not.toBeVisible(); + await expect(page.getByRole('link', { name: 'Community Management' })).not.toBeVisible(); + await expect(page.getByRole('link', { name: 'User Management' })).not.toBeVisible(); + }); + + test('Finance sees only Finance nav link', async ({ page }) => { + await injectOidcSession(page, [ROLES.Finance]); + await navigateTo(page, ROUTES.finance); + await expect(page.getByRole('link', { name: 'Finance' })).toBeVisible({ timeout: 5000 }); + await expect(page.getByRole('link', { name: 'Tech Admin' })).not.toBeVisible(); + await expect(page.getByRole('link', { name: 'Community Management' })).not.toBeVisible(); + }); + + test('CaseManager sees Community Management and User Management nav links', async ({ page }) => { + await injectOidcSession(page, [ROLES.CaseManager]); + await navigateTo(page, ROUTES.community); + await expect(page.getByRole('link', { name: 'Community Management' })).toBeVisible({ timeout: 5000 }); + await expect(page.getByRole('link', { name: 'User Management' })).toBeVisible({ timeout: 5000 }); + await expect(page.getByRole('link', { name: 'Finance' })).not.toBeVisible(); + await expect(page.getByRole('link', { name: 'Tech Admin' })).not.toBeVisible(); + }); +}); diff --git a/apps/ui-staff/package.json b/apps/ui-staff/package.json index e1a705536..130b030e5 100644 --- a/apps/ui-staff/package.json +++ b/apps/ui-staff/package.json @@ -9,7 +9,7 @@ "format:check": "biome format .", "prebuild": "pnpm run lint", "build": "tsgo --build && vite build", - "dev": "node ../../build-pipeline/scripts/portless-dev.mjs staff.ownercommunity.localhost vite", + "dev": "pnpm exec portless staff.ownercommunity.localhost --force vite", "start": "vite", "preview": "vite preview", "test": "vitest run --silent --reporter=dot", diff --git a/apps/ui-staff/playwright.config.ts b/apps/ui-staff/playwright.config.ts new file mode 100644 index 000000000..a22e590e5 --- /dev/null +++ b/apps/ui-staff/playwright.config.ts @@ -0,0 +1,24 @@ +import { defineConfig, devices } from '@playwright/test'; + +/** + * Playwright e2e configuration for the ui-staff portal. + * Tests inject OIDC sessions into sessionStorage directly — no real auth flow required. + * The dev server must be running (`pnpm run dev`) before executing these tests. + */ +export default defineConfig({ + testDir: './e2e', + fullyParallel: false, + retries: 0, + reporter: 'list', + use: { + baseURL: 'https://staff.ownercommunity.localhost:1355', + ignoreHTTPSErrors: true, + trace: 'on-first-retry', + }, + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + ], +}); From 8bbf225214c996bf368bfb3cfeeec3401fe0410f Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Tue, 5 May 2026 00:38:59 +0530 Subject: [PATCH 41/88] chore: remove react-dom version from pnpm-lock.yaml --- pnpm-lock.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2395fe533..b42e9048f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2291,9 +2291,6 @@ importers: jsdom: specifier: 'catalog:' version: 26.1.0 - react-dom: - specifier: ^19.1.1 - version: 19.2.0(react@19.2.0) typescript: specifier: 'catalog:' version: 6.0.3 From 08f44c3f5ac45e9749790b94296ff46434aba28b Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Tue, 5 May 2026 19:07:16 +0530 Subject: [PATCH 42/88] Refactor code structure for improved readability and maintainability --- packages/ocom/ui-staff-shared/package.json | 1 + pnpm-lock.yaml | 263 +++++++++++++++++++-- 2 files changed, 247 insertions(+), 17 deletions(-) diff --git a/packages/ocom/ui-staff-shared/package.json b/packages/ocom/ui-staff-shared/package.json index d6d6a0bcd..787fa3226 100644 --- a/packages/ocom/ui-staff-shared/package.json +++ b/packages/ocom/ui-staff-shared/package.json @@ -24,6 +24,7 @@ "@types/react": "^19.1.11", "@types/react-dom": "^19.1.6", "jsdom": "catalog:", + "react-dom": "^19.1.1", "vite": "catalog:", "vitest": "catalog:", "typescript": "catalog:" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b42e9048f..03912bb0f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -920,25 +920,25 @@ importers: version: link:../config-vitest '@chromatic-com/storybook': specifier: ^4.1.1 - version: 4.1.3(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) + version: 4.1.3(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) '@storybook/addon-a11y': specifier: ^9.1.3 - version: 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) + version: 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) '@storybook/addon-docs': specifier: ^9.1.3 - version: 9.1.16(@types/react@19.2.7)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) + version: 9.1.16(@types/react@19.2.7)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) '@storybook/addon-onboarding': specifier: ^9.1.3 - version: 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) + version: 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) '@storybook/addon-vitest': specifier: ^9.1.3 - version: 9.1.20(@vitest/browser-playwright@4.1.2)(@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2))(@vitest/runner@4.1.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vitest@4.1.2) + version: 9.1.20(@vitest/browser-playwright@4.1.2)(@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2))(@vitest/runner@4.1.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vitest@4.1.2) '@storybook/react': specifier: ^9.1.9 - version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3) + version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3) '@storybook/react-vite': specifier: ^9.1.3 - version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.59.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.59.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) '@testing-library/react': specifier: ^16.3.0 version: 16.3.0(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -950,10 +950,10 @@ importers: version: 19.2.3(@types/react@19.2.7) '@vitest/browser': specifier: ^4.1.2 - version: 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) + version: 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) '@vitest/browser-playwright': specifier: ^4.1.2 - version: 4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) + version: 4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) '@vitest/coverage-istanbul': specifier: 'catalog:' version: 4.1.2(vitest@4.1.2) @@ -971,13 +971,13 @@ importers: version: 6.0.1 storybook: specifier: 'catalog:' - version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) typescript: specifier: 'catalog:' version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom-verification/acceptance-api: dependencies: @@ -2291,6 +2291,9 @@ importers: jsdom: specifier: 'catalog:' version: 26.1.0 + react-dom: + specifier: ^19.1.1 + version: 19.2.0(react@19.2.0) typescript: specifier: 'catalog:' version: 6.0.3 @@ -13266,7 +13269,7 @@ snapshots: minimist: 1.2.8 parsecurrency: 1.1.1 ts-morph: 27.0.2 - vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@22.19.15)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) '@ant-design/cli@6.3.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)': dependencies: @@ -14608,6 +14611,18 @@ snapshots: '@blazediff/core@1.9.1': {} + '@chromatic-com/storybook@4.1.3(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': + dependencies: + '@neoconfetti/react': 1.0.0 + chromatic: 13.3.4 + filesize: 10.1.6 + jsonfile: 6.2.0 + storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + strip-ansi: 7.1.2 + transitivePeerDependencies: + - '@chromatic-com/cypress' + - '@chromatic-com/playwright' + '@chromatic-com/storybook@4.1.3(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: '@neoconfetti/react': 1.0.0 @@ -14936,7 +14951,7 @@ snapshots: '@cucumber/gherkin-utils': 11.0.0 '@cucumber/html-formatter': 23.0.0(@cucumber/messages@32.2.0) '@cucumber/junit-xml-formatter': 0.13.3(@cucumber/messages@32.2.0) - '@cucumber/message-streams': 4.1.1(@cucumber/messages@32.2.0) + '@cucumber/message-streams': 4.1.1(@cucumber/messages@32.3.1) '@cucumber/messages': 32.2.0 '@cucumber/pretty-formatter': 1.0.1(@cucumber/cucumber@12.8.1)(@cucumber/messages@32.2.0) '@cucumber/tag-expressions': 9.1.0 @@ -14972,7 +14987,7 @@ snapshots: '@cucumber/gherkin-streams@6.0.0(@cucumber/gherkin@38.0.0)(@cucumber/message-streams@4.1.1(@cucumber/messages@32.2.0))(@cucumber/messages@32.2.0)': dependencies: '@cucumber/gherkin': 38.0.0 - '@cucumber/message-streams': 4.1.1(@cucumber/messages@32.2.0) + '@cucumber/message-streams': 4.1.1(@cucumber/messages@32.3.1) '@cucumber/messages': 32.2.0 commander: 14.0.0 source-map-support: 0.5.21 @@ -15021,9 +15036,9 @@ snapshots: luxon: 3.7.2 xmlbuilder: 15.1.1 - '@cucumber/message-streams@4.1.1(@cucumber/messages@32.2.0)': + '@cucumber/message-streams@4.1.1(@cucumber/messages@32.3.1)': dependencies: - '@cucumber/messages': 32.2.0 + '@cucumber/messages': 32.3.1 mime: 3.0.0 '@cucumber/messages@26.0.1': @@ -16643,6 +16658,15 @@ snapshots: '@types/yargs': 17.0.35 chalk: 4.1.2 + '@joshwooding/vite-plugin-react-docgen-typescript@0.6.1(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': + dependencies: + glob: 10.5.0 + magic-string: 0.30.21 + react-docgen-typescript: 2.4.0(typescript@6.0.3) + vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + optionalDependencies: + typescript: 6.0.3 + '@joshwooding/vite-plugin-react-docgen-typescript@0.6.1(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: glob: 10.5.0 @@ -18041,12 +18065,31 @@ snapshots: '@standard-schema/spec@1.1.0': {} + '@storybook/addon-a11y@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': + dependencies: + '@storybook/global': 5.0.0 + axe-core: 4.11.0 + storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@storybook/addon-a11y@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: '@storybook/global': 5.0.0 axe-core: 4.11.0 storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@storybook/addon-docs@9.1.16(@types/react@19.2.7)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': + dependencies: + '@mdx-js/react': 3.1.1(@types/react@19.2.7)(react@19.2.0) + '@storybook/csf-plugin': 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) + '@storybook/icons': 1.6.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@storybook/react-dom-shim': 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + ts-dedent: 2.2.0 + transitivePeerDependencies: + - '@types/react' + '@storybook/addon-docs@9.1.16(@types/react@19.2.7)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: '@mdx-js/react': 3.1.1(@types/react@19.2.7)(react@19.2.0) @@ -18060,6 +18103,10 @@ snapshots: transitivePeerDependencies: - '@types/react' + '@storybook/addon-onboarding@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': + dependencies: + storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@storybook/addon-onboarding@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) @@ -18080,6 +18127,22 @@ snapshots: - react - react-dom + '@storybook/addon-vitest@9.1.20(@vitest/browser-playwright@4.1.2)(@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2))(@vitest/runner@4.1.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vitest@4.1.2)': + dependencies: + '@storybook/global': 5.0.0 + '@storybook/icons': 1.6.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + prompts: 2.4.2 + storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + ts-dedent: 2.2.0 + optionalDependencies: + '@vitest/browser': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) + '@vitest/browser-playwright': 4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) + '@vitest/runner': 4.1.2 + vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + transitivePeerDependencies: + - react + - react-dom + '@storybook/addon-vitest@9.1.20(@vitest/browser-playwright@4.1.2)(@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2))(@vitest/runner@4.1.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vitest@4.1.2)': dependencies: '@storybook/global': 5.0.0 @@ -18096,6 +18159,13 @@ snapshots: - react - react-dom + '@storybook/builder-vite@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': + dependencies: + '@storybook/csf-plugin': 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) + storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + ts-dedent: 2.2.0 + vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + '@storybook/builder-vite@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@storybook/csf-plugin': 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) @@ -18103,6 +18173,11 @@ snapshots: ts-dedent: 2.2.0 vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + '@storybook/csf-plugin@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': + dependencies: + storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + unplugin: 1.16.1 + '@storybook/csf-plugin@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) @@ -18115,12 +18190,38 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) + '@storybook/react-dom-shim@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': + dependencies: + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@storybook/react-dom-shim@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@storybook/react-vite@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.59.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': + dependencies: + '@joshwooding/vite-plugin-react-docgen-typescript': 0.6.1(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@rollup/pluginutils': 5.3.0(rollup@4.59.0) + '@storybook/builder-vite': 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@storybook/react': 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3) + find-up: 7.0.0 + magic-string: 0.30.21 + react: 19.2.0 + react-docgen: 8.0.2 + react-dom: 19.2.0(react@19.2.0) + resolve: 1.22.11 + storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + tsconfig-paths: 4.2.0 + vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + transitivePeerDependencies: + - rollup + - supports-color + - typescript + '@storybook/react-vite@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.59.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@joshwooding/vite-plugin-react-docgen-typescript': 0.6.1(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) @@ -18141,6 +18242,16 @@ snapshots: - supports-color - typescript + '@storybook/react@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)': + dependencies: + '@storybook/global': 5.0.0 + '@storybook/react-dom-shim': 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + optionalDependencies: + typescript: 6.0.3 + '@storybook/react@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)': dependencies: '@storybook/global': 5.0.0 @@ -18648,6 +18759,19 @@ snapshots: - vite optional: true + '@vitest/browser-playwright@4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': + dependencies: + '@vitest/browser': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) + '@vitest/mocker': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + playwright: 1.59.0 + tinyrainbow: 3.1.0 + vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + '@vitest/browser-playwright@4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': dependencies: '@vitest/browser': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) @@ -18679,6 +18803,23 @@ snapshots: - vite optional: true + '@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': + dependencies: + '@blazediff/core': 1.9.1 + '@vitest/mocker': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/utils': 4.1.2 + magic-string: 0.30.21 + pngjs: 7.0.0 + sirv: 3.0.2 + tinyrainbow: 3.1.0 + vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + ws: 8.20.0 + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + '@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': dependencies: '@blazediff/core': 1.9.1 @@ -18708,7 +18849,7 @@ snapshots: magicast: 0.5.2 obug: 2.1.1 tinyrainbow: 3.1.0 - vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@22.19.15)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) transitivePeerDependencies: - supports-color @@ -18729,6 +18870,14 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 + '@vitest/mocker@3.2.4(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': + dependencies: + '@vitest/spy': 3.2.4 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + '@vitest/mocker@3.2.4(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@vitest/spy': 3.2.4 @@ -18745,6 +18894,14 @@ snapshots: optionalDependencies: vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@22.19.15)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + '@vitest/mocker@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': + dependencies: + '@vitest/spy': 4.1.2 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + '@vitest/mocker@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@vitest/spy': 4.1.2 @@ -25009,6 +25166,28 @@ snapshots: graphql: 16.12.0 react: 19.2.0 + storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): + dependencies: + '@storybook/global': 5.0.0 + '@testing-library/jest-dom': 6.9.1 + '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1) + '@vitest/expect': 3.2.4 + '@vitest/mocker': 3.2.4(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/spy': 3.2.4 + better-opn: 3.0.2 + esbuild: 0.25.12 + esbuild-register: 3.6.0(esbuild@0.25.12) + recast: 0.23.11 + semver: 7.7.4 + ws: 8.20.0 + transitivePeerDependencies: + - '@testing-library/dom' + - bufferutil + - msw + - supports-color + - utf-8-validate + - vite + storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): dependencies: '@storybook/global': 5.0.0 @@ -25761,6 +25940,26 @@ snapshots: - '@emnapi/core' - '@emnapi/runtime' + vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3): + dependencies: + lightningcss: 1.32.0 + picomatch: 4.0.4 + postcss: 8.5.10 + rolldown: 1.0.0-rc.12(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1) + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 24.10.1 + esbuild: 0.25.12 + fsevents: 2.3.3 + jiti: 2.6.1 + less: 4.4.2 + terser: 5.44.1 + tsx: 4.21.0 + yaml: 2.8.3 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3): dependencies: lightningcss: 1.32.0 @@ -25811,6 +26010,36 @@ snapshots: transitivePeerDependencies: - msw + vitest@4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): + dependencies: + '@vitest/expect': 4.1.2 + '@vitest/mocker': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/pretty-format': 4.1.2 + '@vitest/runner': 4.1.2 + '@vitest/snapshot': 4.1.2 + '@vitest/spy': 4.1.2 + '@vitest/utils': 4.1.2 + es-module-lexer: 2.0.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.4 + std-env: 4.0.0 + tinybench: 2.9.0 + tinyexec: 1.0.4 + tinyglobby: 0.2.15 + tinyrainbow: 3.1.0 + vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + why-is-node-running: 2.3.0 + optionalDependencies: + '@opentelemetry/api': 1.9.0 + '@types/node': 24.10.1 + '@vitest/browser-playwright': 4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) + jsdom: 26.1.0 + transitivePeerDependencies: + - msw + vitest@4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): dependencies: '@vitest/expect': 4.1.2 From a87bbfa7aa978bd3fa9cfccbda3f5bd82cb13b0f Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Tue, 5 May 2026 19:31:40 +0530 Subject: [PATCH 43/88] feat: implement theme storage functions and update theme context to use them --- .../src/contexts/theme-context.tsx | 17 ++++------------ apps/ui-staff/src/contexts/theme-context.tsx | 3 ++- packages/cellix/ui-core/src/index.ts | 1 + packages/cellix/ui-core/src/theme-storage.ts | 20 +++++++++++++++++++ 4 files changed, 27 insertions(+), 14 deletions(-) create mode 100644 packages/cellix/ui-core/src/theme-storage.ts diff --git a/apps/ui-community/src/contexts/theme-context.tsx b/apps/ui-community/src/contexts/theme-context.tsx index 43f4f2c64..65c6c4739 100644 --- a/apps/ui-community/src/contexts/theme-context.tsx +++ b/apps/ui-community/src/contexts/theme-context.tsx @@ -1,5 +1,6 @@ import { Button, theme } from 'antd'; import type { SeedToken } from 'antd/lib/theme/interface/index.js'; +import { loadStoredTheme, saveStoredTheme } from '@cellix/ui-core'; import { createContext, type ReactNode, useCallback, useEffect, useState } from 'react'; // import ModalPopUp from './components/modal-popup.tsx'; @@ -91,23 +92,13 @@ export const ThemeProvider = ({ children }: { children: ReactNode }) => { type: 'custom', }; } - localStorage.setItem('themeProp', JSON.stringify(valueToSet)); + saveStoredTheme(valueToSet); return valueToSet; }); }, []); useEffect(() => { - type StoredTheme = { - type?: 'light' | 'dark' | 'custom'; - hardCodedTokens?: { textColor?: string; backgroundColor?: string }; - token?: unknown; - }; - let extractFromLocal: StoredTheme = {}; - try { - extractFromLocal = JSON.parse(localStorage.getItem('themeProp') ?? '{}') as StoredTheme; - } catch { - localStorage.removeItem('themeProp'); - } + const extractFromLocal = loadStoredTheme(); if (extractFromLocal && extractFromLocal.type === 'dark') { setTheme( { @@ -144,7 +135,7 @@ export const ThemeProvider = ({ children }: { children: ReactNode }) => { backgroundColor: '#ffffff', }, }; - localStorage.setItem('themeProp', JSON.stringify(valueToSet)); + saveStoredTheme(valueToSet); setTheme(theme.defaultSeed, 'light'); return; } diff --git a/apps/ui-staff/src/contexts/theme-context.tsx b/apps/ui-staff/src/contexts/theme-context.tsx index 0af0e12ee..e9c3db6d4 100644 --- a/apps/ui-staff/src/contexts/theme-context.tsx +++ b/apps/ui-staff/src/contexts/theme-context.tsx @@ -1,5 +1,6 @@ import { Button, theme } from 'antd'; import type { SeedToken } from 'antd/lib/theme/interface/index.js'; +import { loadStoredTheme, saveStoredTheme } from '@cellix/ui-core'; import { createContext, type ReactNode, useCallback, useEffect, useState } from 'react'; interface ThemeContextType { @@ -76,7 +77,7 @@ export const ThemeProvider = ({ children }: { children: ReactNode }) => { type: 'custom', }; } - localStorage.setItem('themeProp', JSON.stringify(valueToSet)); + saveStoredTheme(valueToSet); return valueToSet; }); }, []); diff --git a/packages/cellix/ui-core/src/index.ts b/packages/cellix/ui-core/src/index.ts index 9edf82f72..227b5c2f4 100644 --- a/packages/cellix/ui-core/src/index.ts +++ b/packages/cellix/ui-core/src/index.ts @@ -1 +1,2 @@ export * from './components/index.ts'; +export * from './theme-storage.ts'; diff --git a/packages/cellix/ui-core/src/theme-storage.ts b/packages/cellix/ui-core/src/theme-storage.ts new file mode 100644 index 000000000..0ff4303e8 --- /dev/null +++ b/packages/cellix/ui-core/src/theme-storage.ts @@ -0,0 +1,20 @@ +export type StoredTheme = { + type?: 'light' | 'dark' | 'custom'; + hardCodedTokens?: { textColor?: string; backgroundColor?: string }; + token?: unknown; +}; + +const THEME_STORAGE_KEY = 'themeProp'; + +export function loadStoredTheme(): StoredTheme { + try { + return JSON.parse(localStorage.getItem(THEME_STORAGE_KEY) ?? '{}') as StoredTheme; + } catch { + localStorage.removeItem(THEME_STORAGE_KEY); + return {}; + } +} + +export function saveStoredTheme(value: StoredTheme): void { + localStorage.setItem(THEME_STORAGE_KEY, JSON.stringify(value)); +} From bf378d6ccc3a9647b3b1965f32e5f32b845be561 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Tue, 5 May 2026 20:13:02 +0530 Subject: [PATCH 44/88] fix: refine theme context type and improve theme storage handling --- apps/ui-community/src/contexts/theme-context.tsx | 8 +++++--- apps/ui-staff/src/contexts/theme-context.tsx | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/ui-community/src/contexts/theme-context.tsx b/apps/ui-community/src/contexts/theme-context.tsx index 65c6c4739..aab0a6713 100644 --- a/apps/ui-community/src/contexts/theme-context.tsx +++ b/apps/ui-community/src/contexts/theme-context.tsx @@ -16,7 +16,7 @@ interface ThemeContextType { textColor: string | undefined; backgroundColor: string | undefined; }; - type: string; + type: 'light' | 'dark' | 'custom'; } | undefined; setTheme: (tokens: Partial, types: string) => void; @@ -92,7 +92,9 @@ export const ThemeProvider = ({ children }: { children: ReactNode }) => { type: 'custom', }; } - saveStoredTheme(valueToSet); + if (valueToSet) { + saveStoredTheme(valueToSet); + } return valueToSet; }); }, []); @@ -128,7 +130,7 @@ export const ThemeProvider = ({ children }: { children: ReactNode }) => { return; } else { const valueToSet = { - type: 'light', + type: 'light' as const, token: theme.defaultSeed, hardCodedTokens: { textColor: '#000000', diff --git a/apps/ui-staff/src/contexts/theme-context.tsx b/apps/ui-staff/src/contexts/theme-context.tsx index e9c3db6d4..0a218f4c1 100644 --- a/apps/ui-staff/src/contexts/theme-context.tsx +++ b/apps/ui-staff/src/contexts/theme-context.tsx @@ -1,6 +1,6 @@ import { Button, theme } from 'antd'; import type { SeedToken } from 'antd/lib/theme/interface/index.js'; -import { loadStoredTheme, saveStoredTheme } from '@cellix/ui-core'; +import { saveStoredTheme } from '@cellix/ui-core'; import { createContext, type ReactNode, useCallback, useEffect, useState } from 'react'; interface ThemeContextType { From 085ed0ff92fb3125ca693131a3b4d3ca35711d65 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Tue, 5 May 2026 21:03:10 +0530 Subject: [PATCH 45/88] fix: enhance theme context type and streamline theme storage handling --- apps/ui-staff/src/contexts/theme-context.tsx | 29 ++++---------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/apps/ui-staff/src/contexts/theme-context.tsx b/apps/ui-staff/src/contexts/theme-context.tsx index 0a218f4c1..f91b9ac6d 100644 --- a/apps/ui-staff/src/contexts/theme-context.tsx +++ b/apps/ui-staff/src/contexts/theme-context.tsx @@ -1,6 +1,6 @@ import { Button, theme } from 'antd'; import type { SeedToken } from 'antd/lib/theme/interface/index.js'; -import { saveStoredTheme } from '@cellix/ui-core'; +import { type StoredTheme, loadStoredTheme, saveStoredTheme } from '@cellix/ui-core'; import { createContext, type ReactNode, useCallback, useEffect, useState } from 'react'; interface ThemeContextType { @@ -11,7 +11,7 @@ interface ThemeContextType { textColor: string | undefined; backgroundColor: string | undefined; }; - type: string; + type: StoredTheme['type']; } | undefined; setTheme: (tokens: Partial, type: string) => void; @@ -77,23 +77,15 @@ export const ThemeProvider = ({ children }: { children: ReactNode }) => { type: 'custom', }; } - saveStoredTheme(valueToSet); + if (valueToSet) { + saveStoredTheme(valueToSet); + } return valueToSet; }); }, []); useEffect(() => { - type StoredTheme = { - type?: 'light' | 'dark' | 'custom'; - hardCodedTokens?: { textColor?: string; backgroundColor?: string }; - token?: unknown; - }; - let extractFromLocal: StoredTheme = {}; - try { - extractFromLocal = JSON.parse(localStorage.getItem('themeProp') ?? '{}') as StoredTheme; - } catch { - localStorage.removeItem('themeProp'); - } + const extractFromLocal: StoredTheme = loadStoredTheme(); if (extractFromLocal && extractFromLocal.type === 'dark') { setTheme( { @@ -122,15 +114,6 @@ export const ThemeProvider = ({ children }: { children: ReactNode }) => { ); return; } else { - const valueToSet = { - type: 'light', - token: theme.defaultSeed, - hardCodedTokens: { - textColor: '#000000', - backgroundColor: '#ffffff', - }, - }; - localStorage.setItem('themeProp', JSON.stringify(valueToSet)); setTheme(theme.defaultSeed, 'light'); return; } From f51991e0603628c14a30d531668ded064a59db65 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Tue, 5 May 2026 21:27:23 +0530 Subject: [PATCH 46/88] fix: correct import order for theme storage functions in theme context --- apps/ui-staff/src/contexts/theme-context.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ui-staff/src/contexts/theme-context.tsx b/apps/ui-staff/src/contexts/theme-context.tsx index f91b9ac6d..8f1a72cd3 100644 --- a/apps/ui-staff/src/contexts/theme-context.tsx +++ b/apps/ui-staff/src/contexts/theme-context.tsx @@ -1,6 +1,6 @@ +import { loadStoredTheme, type StoredTheme, saveStoredTheme } from '@cellix/ui-core'; import { Button, theme } from 'antd'; import type { SeedToken } from 'antd/lib/theme/interface/index.js'; -import { type StoredTheme, loadStoredTheme, saveStoredTheme } from '@cellix/ui-core'; import { createContext, type ReactNode, useCallback, useEffect, useState } from 'react'; interface ThemeContextType { From 8f64ac2d9a7433856e0d0a986b1af4a841779542 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Tue, 5 May 2026 23:07:23 +0530 Subject: [PATCH 47/88] feat: implement staff RBAC with backend user/role creation and permission-based routing - Add StaffRoleSectionPermissions domain value object with 4 permission flags: canManageCommunities, canManageUser, canManageFinance, canManageTechAdmin - Wire sectionPermissions into StaffRolePermissions domain model and persistence adapter - Add Mongoose schema subdocument for StaffRoleSectionPermissions - Create idempotent createDefaultRoles app service (4 roles mapped to AAD app roles) - Create createIfNotExists and queryByExternalId StaffUser app services - Add StaffUser readonly read-repository with role population - Wire StaffPortal passport lookup via StaffUserReadRepo.getByExternalId - Add currentStaffUserAndCreateIfNotExists GraphQL query with full type definitions - Refactor RequireRole to check backend permissions (permKey) with JWT role fallback - Refactor StaffRouteShell nav filtering to use permKey for permission-aware links - Add useStaffPermissions Apollo hook; refactor App.tsx to build StaffAuth from backend - Add BDD tests for StaffRoleSectionPermissions (12 scenarios, all permission flags) - Add sectionPermissions scenario to staff-role-permissions BDD test suite - Fix ReadonlyDataSource index test to include StaffUser mock model and assertions - Exclude e2e directory from Vitest coverage to fix pre-existing Playwright conflict - Mock useStaffPermissions in App.test.tsx so unit tests use JWT role fallback path Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- apps/ui-staff/e2e/role-authorization.spec.ts | 13 +- apps/ui-staff/src/App.test.tsx | 51 +++- apps/ui-staff/src/App.tsx | 122 ++++++---- .../src/hooks/use-staff-permissions.ts | 65 +++++ apps/ui-staff/vitest.config.ts | 1 + .../src/contexts/user/index.ts | 3 + .../user/staff-role/create-default-roles.ts | 89 +++++++ .../src/contexts/user/staff-role/index.ts | 3 + .../user/staff-user/create-if-not-exists.ts | 62 +++++ .../src/contexts/user/staff-user/index.ts | 16 ++ .../user/staff-user/query-by-external-id.ts | 12 + .../ocom/application-services/src/index.ts | 3 +- .../src/models/role/staff-role.model.ts | 15 ++ .../features/staff-role-permissions.feature | 7 +- .../staff-role-section-permissions.feature | 65 +++++ .../domain/contexts/user/staff-role/index.ts | 4 + .../staff-role/staff-role-permissions.test.ts | 15 ++ .../user/staff-role/staff-role-permissions.ts | 10 +- .../staff-role-section-permissions.test.ts | 224 ++++++++++++++++++ .../staff-role-section-permissions.ts | 61 +++++ .../src/schema/builder/resolver-builder.ts | 3 +- .../src/schema/types/staff-user.graphql | 42 ++++ .../src/schema/types/staff-user.resolvers.ts | 24 ++ .../staff-role/staff-role.domain-adapter.ts | 60 ++++- .../src/datasources/readonly/index.test.ts | 16 +- .../src/datasources/readonly/index.ts | 4 + .../src/datasources/readonly/user/index.ts | 2 + .../readonly/user/staff-user/index.ts | 11 + .../staff-user/staff-user.read-repository.ts | 35 +++ .../ocom/ui-staff-shared/src/require-role.tsx | 30 ++- .../ui-staff-shared/src/staff-route-shell.tsx | 27 ++- 31 files changed, 1010 insertions(+), 85 deletions(-) create mode 100644 apps/ui-staff/src/hooks/use-staff-permissions.ts create mode 100644 packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts create mode 100644 packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.ts create mode 100644 packages/ocom/application-services/src/contexts/user/staff-user/index.ts create mode 100644 packages/ocom/application-services/src/contexts/user/staff-user/query-by-external-id.ts create mode 100644 packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-section-permissions.feature create mode 100644 packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-section-permissions.test.ts create mode 100644 packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-section-permissions.ts create mode 100644 packages/ocom/graphql/src/schema/types/staff-user.graphql create mode 100644 packages/ocom/graphql/src/schema/types/staff-user.resolvers.ts create mode 100644 packages/ocom/persistence/src/datasources/readonly/user/staff-user/index.ts create mode 100644 packages/ocom/persistence/src/datasources/readonly/user/staff-user/staff-user.read-repository.ts diff --git a/apps/ui-staff/e2e/role-authorization.spec.ts b/apps/ui-staff/e2e/role-authorization.spec.ts index 3f89a333c..4675ea423 100644 --- a/apps/ui-staff/e2e/role-authorization.spec.ts +++ b/apps/ui-staff/e2e/role-authorization.spec.ts @@ -6,7 +6,7 @@ * * The OIDC authority / client_id values must match apps/ui-staff/src/config/oidc-config.tsx. */ -import { expect, test, type Page } from '@playwright/test'; +import { expect, type Page, test } from '@playwright/test'; // --- Constants matching oidc-config.tsx --- const AUTHORITY = 'https://mock-auth.ownercommunity.localhost:1355/staff'; @@ -89,10 +89,13 @@ const ROLES = { async function navigateTo(page: Page, path: string): Promise { await page.goto(path, { waitUntil: 'domcontentloaded' }); // Wait for the React root to contain rendered content (i.e., the app mounted) - await page.waitForFunction(() => { - const root = document.getElementById('root'); - return root && root.childElementCount > 0; - }, { timeout: 8000 }); + await page.waitForFunction( + () => { + const root = document.getElementById('root'); + return root && root.childElementCount > 0; + }, + { timeout: 8000 }, + ); } /** The section title is rendered as a heading — use heading role to avoid matching nav labels. */ diff --git a/apps/ui-staff/src/App.test.tsx b/apps/ui-staff/src/App.test.tsx index eca1e2973..57b9167e0 100644 --- a/apps/ui-staff/src/App.test.tsx +++ b/apps/ui-staff/src/App.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { renderToString } from 'react-dom/server'; import { MemoryRouter } from 'react-router-dom'; -import { describe, expect, it, vi, beforeEach } from 'vitest'; +import { beforeEach, describe, expect, it, vi } from 'vitest'; // Mock RequireAuth so tests don't depend on OIDC context behavior vi.mock('@cellix/ui-core', () => ({ @@ -13,6 +13,12 @@ vi.mock('./components/ui/organisms/apollo-connection/index.tsx', () => ({ ApolloConnection: ({ children }: { children: React.ReactNode }) => React.createElement(React.Fragment, {}, children), })); +// Mock useStaffPermissions so tests don't need an Apollo client; returning +// undefined permissions causes RequireRole to fall back to JWT role checking. +vi.mock('./hooks/use-staff-permissions', () => ({ + useStaffPermissions: () => ({ permissions: undefined, loading: false, error: undefined }), +})); + // Mock route packages with identifiable content per section vi.mock('@ocom/ui-staff-route-root', () => ({ Root: () => React.createElement('div', {}, 'root-section') })); vi.mock('@ocom/ui-staff-route-community-management', () => ({ Root: () => React.createElement('div', {}, 'community-management-section') })); @@ -53,24 +59,39 @@ import App from './App'; describe('App – static routes', () => { it('renders root section without throwing', () => { - const html = renderToString(); + const html = renderToString( + + + , + ); expect(typeof html).toBe('string'); expect(html.length).toBeGreaterThan(0); }); it('renders auth-redirect route without throwing', () => { - const html = renderToString(); + const html = renderToString( + + + , + ); expect(typeof html).toBe('string'); }); it('/unauthorized renders the Unauthorized page', () => { - const html = renderToString(); + const html = renderToString( + + + , + ); expect(html).toContain('Unauthorized'); }); }); describe('App – role authorization: Staff.TechAdmin', () => { - beforeEach(() => { mockAuthWithRoles(['Staff.TechAdmin']); vi.resetModules(); }); + beforeEach(() => { + mockAuthWithRoles(['Staff.TechAdmin']); + vi.resetModules(); + }); it('/staff/tech → renders tech-admin section', async () => { expect(await renderAppAt('/staff/tech')).toContain('tech-admin-section'); @@ -93,7 +114,10 @@ describe('App – role authorization: Staff.TechAdmin', () => { }); describe('App – role authorization: Staff.Finance', () => { - beforeEach(() => { mockAuthWithRoles(['Staff.Finance']); vi.resetModules(); }); + beforeEach(() => { + mockAuthWithRoles(['Staff.Finance']); + vi.resetModules(); + }); it('/staff/finance → renders finance section', async () => { expect(await renderAppAt('/staff/finance')).toContain('finance-section'); @@ -116,7 +140,10 @@ describe('App – role authorization: Staff.Finance', () => { }); describe('App – role authorization: Staff.CaseManager', () => { - beforeEach(() => { mockAuthWithRoles(['Staff.CaseManager']); vi.resetModules(); }); + beforeEach(() => { + mockAuthWithRoles(['Staff.CaseManager']); + vi.resetModules(); + }); it('/staff/community → renders community-management section', async () => { expect(await renderAppAt('/staff/community')).toContain('community-management-section'); @@ -138,7 +165,10 @@ describe('App – role authorization: Staff.CaseManager', () => { }); describe('App – role authorization: Staff.ServiceLineOwner', () => { - beforeEach(() => { mockAuthWithRoles(['Staff.ServiceLineOwner']); vi.resetModules(); }); + beforeEach(() => { + mockAuthWithRoles(['Staff.ServiceLineOwner']); + vi.resetModules(); + }); it('/staff/community → renders community-management section', async () => { expect(await renderAppAt('/staff/community')).toContain('community-management-section'); @@ -160,7 +190,10 @@ describe('App – role authorization: Staff.ServiceLineOwner', () => { }); describe('App – role authorization: no roles', () => { - beforeEach(() => { mockAuthNoUser(); vi.resetModules(); }); + beforeEach(() => { + mockAuthNoUser(); + vi.resetModules(); + }); it('/staff/community → redirects to /unauthorized', async () => { const html = await renderAppAt('/staff/community'); diff --git a/apps/ui-staff/src/App.tsx b/apps/ui-staff/src/App.tsx index 3e166073f..510fd11d1 100644 --- a/apps/ui-staff/src/App.tsx +++ b/apps/ui-staff/src/App.tsx @@ -10,16 +10,75 @@ import { Route, Routes } from 'react-router-dom'; import './App.css'; import { AuthLanding } from './components/ui/molecules/auth-landing/index.tsx'; import { ApolloConnection } from './components/ui/organisms/apollo-connection/index.tsx'; +import { useStaffPermissions } from './hooks/use-staff-permissions.ts'; import { Unauthorized } from './unauthorized.tsx'; +function StaffRoutes() { + return ( + + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + ); +} + export default function App() { const rootSection = ; const auth = useAuth(); - // Build a best-effort identity object to supply to shared placeholders - - // Provide a best-effort raw profile to the shared staff shell. StaffRouteShell will - // attempt to extract display name and roles from this raw profile. const identity = { raw: (auth?.user?.profile as Record) ?? undefined, onLogout: () => @@ -36,50 +95,7 @@ export default function App() { const staffSection = ( - - - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - + ); @@ -106,3 +122,13 @@ export default function App() { ); } + +function StaffSection({ identity }: { identity: Parameters[0]['value'] }) { + const { permissions } = useStaffPermissions(); + + return ( + + + + ); +} diff --git a/apps/ui-staff/src/hooks/use-staff-permissions.ts b/apps/ui-staff/src/hooks/use-staff-permissions.ts new file mode 100644 index 000000000..8e86546c7 --- /dev/null +++ b/apps/ui-staff/src/hooks/use-staff-permissions.ts @@ -0,0 +1,65 @@ +import { gql, useQuery } from '@apollo/client'; + +const CURRENT_STAFF_USER_QUERY = gql` + query CurrentStaffUserAndCreateIfNotExists { + currentStaffUserAndCreateIfNotExists { + id + externalId + firstName + lastName + email + displayName + role { + id + roleName + permissions { + sectionPermissions { + canManageCommunities + canManageUser + canManageFinance + canManageTechAdmin + } + } + } + } + } +`; + +interface StaffPermissions { + canManageCommunities: boolean; + canManageUser: boolean; + canManageFinance: boolean; + canManageTechAdmin: boolean; +} + +interface StaffUserQueryResult { + currentStaffUserAndCreateIfNotExists: { + id: string; + externalId: string; + firstName: string; + lastName: string; + email: string; + displayName: string; + role?: { + id: string; + roleName: string; + permissions: { + sectionPermissions: StaffPermissions; + }; + }; + }; +} + +export const useStaffPermissions = (): { permissions: StaffPermissions | undefined; loading: boolean; error: Error | undefined } => { + const { data, loading, error } = useQuery(CURRENT_STAFF_USER_QUERY, { + fetchPolicy: 'cache-first', + }); + + const sectionPermissions = data?.currentStaffUserAndCreateIfNotExists?.role?.permissions?.sectionPermissions; + + return { + permissions: sectionPermissions ?? undefined, + loading, + error, + }; +}; diff --git a/apps/ui-staff/vitest.config.ts b/apps/ui-staff/vitest.config.ts index 17bec4371..198b98ee6 100644 --- a/apps/ui-staff/vitest.config.ts +++ b/apps/ui-staff/vitest.config.ts @@ -7,6 +7,7 @@ export default mergeConfig( test: { environment: 'jsdom', passWithNoTests: true, + exclude: ['**/node_modules/**', '**/dist/**', 'e2e/**'], }, }), ); diff --git a/packages/ocom/application-services/src/contexts/user/index.ts b/packages/ocom/application-services/src/contexts/user/index.ts index e7a3c1f62..6841b047b 100644 --- a/packages/ocom/application-services/src/contexts/user/index.ts +++ b/packages/ocom/application-services/src/contexts/user/index.ts @@ -1,15 +1,18 @@ import type { DataSources } from '@ocom/persistence'; import { EndUser as EndUserApi, type EndUserApplicationService } from './end-user/index.ts'; import { StaffRole as StaffRoleApi, type StaffRoleApplicationService } from './staff-role/index.ts'; +import { StaffUser as StaffUserApi, type StaffUserApplicationService } from './staff-user/index.ts'; export interface UserContextApplicationService { EndUser: EndUserApplicationService; StaffRole: StaffRoleApplicationService; + StaffUser: StaffUserApplicationService; } export const User = (dataSources: DataSources): UserContextApplicationService => { return { EndUser: EndUserApi(dataSources), StaffRole: StaffRoleApi(dataSources), + StaffUser: StaffUserApi(dataSources), }; }; diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts new file mode 100644 index 000000000..a96dd910a --- /dev/null +++ b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts @@ -0,0 +1,89 @@ +import type { Domain } from '@ocom/domain'; +import type { DataSources } from '@ocom/persistence'; + +export const StaffAppRoleNames = { + CaseManager: 'Staff.CaseManager', + ServiceLineOwner: 'Staff.ServiceLineOwner', + Finance: 'Staff.Finance', + TechAdmin: 'Staff.TechAdmin', +} as const; + +export type StaffAppRoleName = (typeof StaffAppRoleNames)[keyof typeof StaffAppRoleNames]; + +interface DefaultRoleSpec { + roleName: StaffAppRoleName; + isDefault: boolean; + sectionPermissions: { + canManageCommunities: boolean; + canManageUser: boolean; + canManageFinance: boolean; + canManageTechAdmin: boolean; + }; +} + +const DEFAULT_ROLE_SPECS: DefaultRoleSpec[] = [ + { + roleName: StaffAppRoleNames.CaseManager, + isDefault: false, + sectionPermissions: { canManageCommunities: true, canManageUser: true, canManageFinance: false, canManageTechAdmin: false }, + }, + { + roleName: StaffAppRoleNames.ServiceLineOwner, + isDefault: false, + sectionPermissions: { canManageCommunities: true, canManageUser: true, canManageFinance: false, canManageTechAdmin: false }, + }, + { + roleName: StaffAppRoleNames.Finance, + isDefault: false, + sectionPermissions: { canManageCommunities: false, canManageUser: false, canManageFinance: true, canManageTechAdmin: false }, + }, + { + roleName: StaffAppRoleNames.TechAdmin, + isDefault: false, + sectionPermissions: { canManageCommunities: false, canManageUser: false, canManageFinance: false, canManageTechAdmin: true }, + }, +]; + +const roleExists = async (repository: Domain.Contexts.User.StaffRole.StaffRoleRepository, roleName: string): Promise => { + try { + await repository.getByRoleName(roleName); + return true; + } catch (error) { + if (error instanceof Error && (error.name === 'NotFoundError' || error.message.toLowerCase().includes('not found'))) { + return false; + } + throw error; + } +}; + +const applySectionPermissions = (staffRole: Domain.Contexts.User.StaffRole.StaffRole, sectionPerms: DefaultRoleSpec['sectionPermissions']): void => { + const { sectionPermissions } = staffRole.permissions; + sectionPermissions.canManageCommunities = sectionPerms.canManageCommunities; + sectionPermissions.canManageUser = sectionPerms.canManageUser; + sectionPermissions.canManageFinance = sectionPerms.canManageFinance; + sectionPermissions.canManageTechAdmin = sectionPerms.canManageTechAdmin; +}; + +export const createDefaultRoles = (dataSources: DataSources) => { + return async (): Promise => { + const created: Domain.Contexts.User.StaffRole.StaffRoleEntityReference[] = []; + + await dataSources.domainDataSource.User.StaffRole.StaffRoleUnitOfWork.withScopedTransaction(async (repository) => { + for (const spec of DEFAULT_ROLE_SPECS) { + const exists = await roleExists(repository, spec.roleName); + if (exists) { + continue; + } + + const staffRole = await repository.getNewInstance(spec.roleName); + staffRole.isDefault = spec.isDefault; + applySectionPermissions(staffRole, spec.sectionPermissions); + + const saved = await repository.save(staffRole); + created.push(saved); + } + }); + + return created; + }; +}; diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/index.ts b/packages/ocom/application-services/src/contexts/user/staff-role/index.ts index 40c815cac..e032256e8 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-role/index.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-role/index.ts @@ -1,12 +1,14 @@ import type { Domain } from '@ocom/domain'; import type { DataSources } from '@ocom/persistence'; import { create, type StaffRoleCreateCommand } from './create.ts'; +import { createDefaultRoles } from './create-default-roles.ts'; import { deleteAndReassign, type StaffRoleDeleteAndReassignCommand } from './delete-and-reassign.ts'; import { queryById, type StaffRoleQueryByIdCommand } from './query-by-id.ts'; import { queryByRoleName, type StaffRoleQueryByRoleNameCommand } from './query-by-role-name.ts'; export interface StaffRoleApplicationService { create: (command: StaffRoleCreateCommand) => Promise; + createDefaultRoles: () => Promise; deleteAndReassign: (command: StaffRoleDeleteAndReassignCommand) => Promise; queryById: (command: StaffRoleQueryByIdCommand) => Promise; queryByRoleName: (command: StaffRoleQueryByRoleNameCommand) => Promise; @@ -15,6 +17,7 @@ export interface StaffRoleApplicationService { export const StaffRole = (dataSources: DataSources): StaffRoleApplicationService => { return { create: create(dataSources), + createDefaultRoles: createDefaultRoles(dataSources), deleteAndReassign: deleteAndReassign(dataSources), queryById: queryById(dataSources), queryByRoleName: queryByRoleName(dataSources), diff --git a/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.ts b/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.ts new file mode 100644 index 000000000..0e865a31d --- /dev/null +++ b/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.ts @@ -0,0 +1,62 @@ +import type { Domain } from '@ocom/domain'; +import type { DataSources } from '@ocom/persistence'; +import { createDefaultRoles, type StaffAppRoleName, StaffAppRoleNames } from '../staff-role/create-default-roles.ts'; + +export interface StaffUserCreateIfNotExistsCommand { + externalId: string; + firstName: string; + lastName: string; + email: string; + aadRoles: string[]; +} + +const findMatchingRoleName = (aadRoles: string[]): StaffAppRoleName | undefined => { + const knownRoles = Object.values(StaffAppRoleNames) as StaffAppRoleName[]; + return aadRoles.find((r): r is StaffAppRoleName => knownRoles.includes(r as StaffAppRoleName)); +}; + +const getRoleByName = async (dataSources: DataSources, roleName: string): Promise => { + let found: Domain.Contexts.User.StaffRole.StaffRoleEntityReference | null = null; + await dataSources.domainDataSource.User.StaffRole.StaffRoleUnitOfWork.withScopedTransaction(async (repo) => { + try { + found = await repo.getByRoleName(roleName); + } catch { + found = null; + } + }); + return found; +}; + +export const createIfNotExists = (dataSources: DataSources) => { + return async (command: StaffUserCreateIfNotExistsCommand): Promise => { + const existing = await dataSources.readonlyDataSource.User.StaffUser.StaffUserReadRepo.getByExternalId(command.externalId); + if (existing) { + return existing; + } + + // Ensure the 4 default roles exist before creating the user + await createDefaultRoles(dataSources)(); + + // Find which default role matches the user's AAD roles + const matchingRoleName = findMatchingRoleName(command.aadRoles); + const matchingRole = matchingRoleName ? await getRoleByName(dataSources, matchingRoleName) : null; + + let createdUser: Domain.Contexts.User.StaffUser.StaffUserEntityReference | undefined; + + await dataSources.domainDataSource.User.StaffUser.StaffUserUnitOfWork.withScopedTransaction(async (repository) => { + const newUser = await repository.getNewInstance(command.externalId, command.firstName, command.lastName, command.email); + + if (matchingRole) { + newUser.role = matchingRole; + } + + createdUser = await repository.save(newUser); + }); + + if (!createdUser) { + throw new Error('Unable to create staff user'); + } + + return createdUser; + }; +}; diff --git a/packages/ocom/application-services/src/contexts/user/staff-user/index.ts b/packages/ocom/application-services/src/contexts/user/staff-user/index.ts new file mode 100644 index 000000000..2c5b0d00b --- /dev/null +++ b/packages/ocom/application-services/src/contexts/user/staff-user/index.ts @@ -0,0 +1,16 @@ +import type { Domain } from '@ocom/domain'; +import type { DataSources } from '@ocom/persistence'; +import { createIfNotExists, type StaffUserCreateIfNotExistsCommand } from './create-if-not-exists.ts'; +import { queryByExternalId, type StaffUserQueryByExternalIdCommand } from './query-by-external-id.ts'; + +export interface StaffUserApplicationService { + createIfNotExists: (command: StaffUserCreateIfNotExistsCommand) => Promise; + queryByExternalId: (command: StaffUserQueryByExternalIdCommand) => Promise; +} + +export const StaffUser = (dataSources: DataSources): StaffUserApplicationService => { + return { + createIfNotExists: createIfNotExists(dataSources), + queryByExternalId: queryByExternalId(dataSources), + }; +}; diff --git a/packages/ocom/application-services/src/contexts/user/staff-user/query-by-external-id.ts b/packages/ocom/application-services/src/contexts/user/staff-user/query-by-external-id.ts new file mode 100644 index 000000000..23cd50e5f --- /dev/null +++ b/packages/ocom/application-services/src/contexts/user/staff-user/query-by-external-id.ts @@ -0,0 +1,12 @@ +import type { Domain } from '@ocom/domain'; +import type { DataSources } from '@ocom/persistence'; + +export interface StaffUserQueryByExternalIdCommand { + externalId: string; +} + +export const queryByExternalId = (dataSources: DataSources) => { + return async (command: StaffUserQueryByExternalIdCommand): Promise => { + return await dataSources.readonlyDataSource.User.StaffUser.StaffUserReadRepo.getByExternalId(command.externalId); + }; +}; diff --git a/packages/ocom/application-services/src/index.ts b/packages/ocom/application-services/src/index.ts index ccfdc57d1..58e37f066 100644 --- a/packages/ocom/application-services/src/index.ts +++ b/packages/ocom/application-services/src/index.ts @@ -59,8 +59,7 @@ export const buildApplicationServicesFactory = (infrastructureServicesRegistry: passport = Domain.PassportFactory.forMember(endUser, member, community); } } else if (openIdConfigKey === 'StaffPortal') { - const staffUser = undefined; - // const staffUser = await readonlyDataSource.User.StaffUser.StaffUserReadRepo.getByExternalId(verifiedJwt.sub); + const staffUser = await readonlyDataSource.User.StaffUser.StaffUserReadRepo.getByExternalId(verifiedJwt.sub); if (staffUser) { passport = Domain.PassportFactory.forStaffUser(staffUser); } diff --git a/packages/ocom/data-sources-mongoose-models/src/models/role/staff-role.model.ts b/packages/ocom/data-sources-mongoose-models/src/models/role/staff-role.model.ts index 43a2cd4ee..e718f02aa 100644 --- a/packages/ocom/data-sources-mongoose-models/src/models/role/staff-role.model.ts +++ b/packages/ocom/data-sources-mongoose-models/src/models/role/staff-role.model.ts @@ -1,6 +1,14 @@ import { type Model, type ObjectId, Schema, type SchemaDefinition } from 'mongoose'; import { type Role, type RoleModelType, roleOptions } from './role.model.ts'; +export interface StaffRoleSectionPermissions { + id?: ObjectId; + canManageCommunities: boolean; + canManageUser: boolean; + canManageFinance: boolean; + canManageTechAdmin: boolean; +} + export interface StaffRoleServicePermissions { id?: ObjectId; canManageServices: boolean; @@ -43,6 +51,7 @@ export interface StaffRoleCommunityPermissions { export interface StaffRolePermissions { id?: ObjectId; + sectionPermissions: StaffRoleSectionPermissions; servicePermissions: StaffRoleServicePermissions; serviceTicketPermissions: StaffRoleServiceTicketPermissions; violationTicketPermissions: StaffRoleViolationTicketPermissions; @@ -61,6 +70,12 @@ export interface StaffRole extends Role { const StaffRoleSchema = new Schema, StaffRole>( { permissions: { + sectionPermissions: { + canManageCommunities: { type: Boolean, required: true, default: false }, + canManageUser: { type: Boolean, required: true, default: false }, + canManageFinance: { type: Boolean, required: true, default: false }, + canManageTechAdmin: { type: Boolean, required: true, default: false }, + } as SchemaDefinition, servicePermissions: { canManageServices: { type: Boolean, required: true, default: false }, } as SchemaDefinition, diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-permissions.feature b/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-permissions.feature index aae26b8e3..ddbf5d7ee 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-permissions.feature +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-permissions.feature @@ -27,4 +27,9 @@ Feature: StaffRolePermissions Scenario: Accessing violationTicketPermissions Given a StaffRolePermissions entity When I access the violationTicketPermissions property - Then I should receive a StaffRoleViolationTicketPermissions entity instance \ No newline at end of file + Then I should receive a StaffRoleViolationTicketPermissions entity instance + + Scenario: Accessing sectionPermissions + Given a StaffRolePermissions entity + When I access the sectionPermissions property + Then I should receive a StaffRoleSectionPermissions entity instance \ No newline at end of file diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-section-permissions.feature b/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-section-permissions.feature new file mode 100644 index 000000000..08dc1fb43 --- /dev/null +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-section-permissions.feature @@ -0,0 +1,65 @@ +Feature: StaffRoleSectionPermissions + + Background: + Given valid StaffRoleSectionPermissionsProps with all permission flags set to false + And a valid UserVisa + + Scenario: Changing canManageCommunities with manage staff roles permission + Given a StaffRoleSectionPermissions entity with permission to manage staff roles + When I set canManageCommunities to true + Then the property should be updated to true + + Scenario: Changing canManageCommunities with system account permission + Given a StaffRoleSectionPermissions entity with system account permission + When I set canManageCommunities to true + Then the property should be updated to true + + Scenario: Changing canManageCommunities without permission + Given a StaffRoleSectionPermissions entity without permission to manage staff roles or system account + When I try to set canManageCommunities to true + Then a PermissionError should be thrown + + Scenario: Changing canManageUser with manage staff roles permission + Given a StaffRoleSectionPermissions entity with permission to manage staff roles + When I set canManageUser to true + Then the property should be updated to true + + Scenario: Changing canManageUser with system account permission + Given a StaffRoleSectionPermissions entity with system account permission + When I set canManageUser to true + Then the property should be updated to true + + Scenario: Changing canManageUser without permission + Given a StaffRoleSectionPermissions entity without permission to manage staff roles or system account + When I try to set canManageUser to true + Then a PermissionError should be thrown + + Scenario: Changing canManageFinance with manage staff roles permission + Given a StaffRoleSectionPermissions entity with permission to manage staff roles + When I set canManageFinance to true + Then the property should be updated to true + + Scenario: Changing canManageFinance with system account permission + Given a StaffRoleSectionPermissions entity with system account permission + When I set canManageFinance to true + Then the property should be updated to true + + Scenario: Changing canManageFinance without permission + Given a StaffRoleSectionPermissions entity without permission to manage staff roles or system account + When I try to set canManageFinance to true + Then a PermissionError should be thrown + + Scenario: Changing canManageTechAdmin with manage staff roles permission + Given a StaffRoleSectionPermissions entity with permission to manage staff roles + When I set canManageTechAdmin to true + Then the property should be updated to true + + Scenario: Changing canManageTechAdmin with system account permission + Given a StaffRoleSectionPermissions entity with system account permission + When I set canManageTechAdmin to true + Then the property should be updated to true + + Scenario: Changing canManageTechAdmin without permission + Given a StaffRoleSectionPermissions entity without permission to manage staff roles or system account + When I try to set canManageTechAdmin to true + Then a PermissionError should be thrown diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/index.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/index.ts index b86eaf818..585643108 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/index.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/index.ts @@ -17,6 +17,10 @@ export type { StaffRolePropertyPermissionsEntityReference, StaffRolePropertyPermissionsProps, } from './staff-role-property-permissions.ts'; +export type { + StaffRoleSectionPermissionsEntityReference, + StaffRoleSectionPermissionsProps, +} from './staff-role-section-permissions.ts'; export type { StaffRoleServicePermissionsEntityReference, StaffRoleServicePermissionsProps, diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-permissions.test.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-permissions.test.ts index b09ad76ed..bc4b652c2 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-permissions.test.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-permissions.test.ts @@ -5,6 +5,7 @@ import { expect, vi } from 'vitest'; import { StaffRoleCommunityPermissions } from './staff-role-community-permissions.ts'; import { StaffRolePermissions } from './staff-role-permissions.ts'; import { StaffRolePropertyPermissions } from './staff-role-property-permissions.ts'; +import { StaffRoleSectionPermissions } from './staff-role-section-permissions.ts'; import { StaffRoleServicePermissions } from './staff-role-service-permissions.ts'; import { StaffRoleServiceTicketPermissions } from './staff-role-service-ticket-permissions.ts'; import { StaffRoleViolationTicketPermissions } from './staff-role-violation-ticket-permissions.ts'; @@ -26,6 +27,7 @@ function makeProps() { serviceTicketPermissions: {} as StaffRoleServiceTicketPermissions, servicePermissions: {} as StaffRoleServicePermissions, violationTicketPermissions: {} as StaffRoleViolationTicketPermissions, + sectionPermissions: {} as StaffRoleSectionPermissions, }; } @@ -113,4 +115,17 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { expect(violationTicketPermissions).toBeInstanceOf(StaffRoleViolationTicketPermissions); }); }); + + Scenario('Accessing sectionPermissions', ({ Given, When, Then }) => { + let sectionPermissions: StaffRoleSectionPermissions; + Given('a StaffRolePermissions entity', () => { + entity = new StaffRolePermissions(props, visa); + }); + When('I access the sectionPermissions property', () => { + sectionPermissions = entity.sectionPermissions; + }); + Then('I should receive a StaffRoleSectionPermissions entity instance', () => { + expect(sectionPermissions).toBeInstanceOf(StaffRoleSectionPermissions); + }); + }); }); diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-permissions.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-permissions.ts index 22e8ee188..bee2a83cd 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-permissions.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-permissions.ts @@ -1,8 +1,9 @@ -import { ValueObject } from '@cellix/domain-seedwork/value-object'; import type { ValueObjectProps } from '@cellix/domain-seedwork/value-object'; +import { ValueObject } from '@cellix/domain-seedwork/value-object'; import type { UserVisa } from '../user.visa.ts'; import { StaffRoleCommunityPermissions, type StaffRoleCommunityPermissionsEntityReference, type StaffRoleCommunityPermissionsProps } from './staff-role-community-permissions.ts'; import { StaffRolePropertyPermissions, type StaffRolePropertyPermissionsEntityReference, type StaffRolePropertyPermissionsProps } from './staff-role-property-permissions.ts'; +import { StaffRoleSectionPermissions, type StaffRoleSectionPermissionsEntityReference, type StaffRoleSectionPermissionsProps } from './staff-role-section-permissions.ts'; import { StaffRoleServicePermissions, type StaffRoleServicePermissionsEntityReference, type StaffRoleServicePermissionsProps } from './staff-role-service-permissions.ts'; import { StaffRoleServiceTicketPermissions, type StaffRoleServiceTicketPermissionsEntityReference, type StaffRoleServiceTicketPermissionsProps } from './staff-role-service-ticket-permissions.ts'; import { StaffRoleViolationTicketPermissions, type StaffRoleViolationTicketPermissionsEntityReference, type StaffRoleViolationTicketPermissionsProps } from './staff-role-violation-ticket-permissions.ts'; @@ -13,15 +14,17 @@ export interface StaffRolePermissionsProps extends ValueObjectProps { readonly serviceTicketPermissions: StaffRoleServiceTicketPermissionsProps; readonly servicePermissions: StaffRoleServicePermissionsProps; readonly violationTicketPermissions: StaffRoleViolationTicketPermissionsProps; + readonly sectionPermissions: StaffRoleSectionPermissionsProps; } export interface StaffRolePermissionsEntityReference - extends Readonly> { + extends Readonly> { readonly communityPermissions: StaffRoleCommunityPermissionsEntityReference; readonly propertyPermissions: StaffRolePropertyPermissionsEntityReference; readonly serviceTicketPermissions: StaffRoleServiceTicketPermissionsEntityReference; readonly servicePermissions: StaffRoleServicePermissionsEntityReference; readonly violationTicketPermissions: StaffRoleViolationTicketPermissionsEntityReference; + readonly sectionPermissions: StaffRoleSectionPermissionsEntityReference; } export class StaffRolePermissions extends ValueObject implements StaffRolePermissionsEntityReference { @@ -47,4 +50,7 @@ export class StaffRolePermissions extends ValueObject get violationTicketPermissions(): StaffRoleViolationTicketPermissions { return new StaffRoleViolationTicketPermissions(this.props.violationTicketPermissions, this.visa); } + get sectionPermissions(): StaffRoleSectionPermissions { + return new StaffRoleSectionPermissions(this.props.sectionPermissions, this.visa); + } } diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-section-permissions.test.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-section-permissions.test.ts new file mode 100644 index 000000000..e5a4c1b58 --- /dev/null +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-section-permissions.test.ts @@ -0,0 +1,224 @@ +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; +import { PermissionError } from '@cellix/domain-seedwork/domain-entity'; +import { expect, vi } from 'vitest'; + +import { StaffRoleSectionPermissions } from './staff-role-section-permissions.ts'; + +const test = { for: describeFeature }; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const feature = await loadFeature(path.resolve(__dirname, 'features/staff-role-section-permissions.feature')); + +function makeVisa({ canManageStaffRolesAndPermissions = true, isSystemAccount = false } = {}) { + return vi.mocked({ + determineIf: vi.fn((fn) => fn({ canManageStaffRolesAndPermissions, isSystemAccount })), + }); +} + +function makeProps(overrides = {}) { + return { + canManageCommunities: false, + canManageUser: false, + canManageFinance: false, + canManageTechAdmin: false, + ...overrides, + }; +} + +test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { + let visa: ReturnType; + let props: ReturnType; + let entity: StaffRoleSectionPermissions; + + BeforeEachScenario(() => { + visa = makeVisa(); + props = makeProps(); + entity = new StaffRoleSectionPermissions(props, visa); + }); + + Background(({ Given, And }) => { + Given('valid StaffRoleSectionPermissionsProps with all permission flags set to false', () => { + props = makeProps(); + }); + And('a valid UserVisa', () => { + visa = makeVisa(); + }); + }); + + // canManageCommunities + Scenario('Changing canManageCommunities with manage staff roles permission', ({ Given, When, Then }) => { + Given('a StaffRoleSectionPermissions entity with permission to manage staff roles', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: true, isSystemAccount: false }); + entity = new StaffRoleSectionPermissions(makeProps(), visa); + }); + When('I set canManageCommunities to true', () => { + entity.canManageCommunities = true; + }); + Then('the property should be updated to true', () => { + expect(entity.canManageCommunities).toBe(true); + }); + }); + + Scenario('Changing canManageCommunities with system account permission', ({ Given, When, Then }) => { + Given('a StaffRoleSectionPermissions entity with system account permission', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: true }); + entity = new StaffRoleSectionPermissions(makeProps(), visa); + }); + When('I set canManageCommunities to true', () => { + entity.canManageCommunities = true; + }); + Then('the property should be updated to true', () => { + expect(entity.canManageCommunities).toBe(true); + }); + }); + + Scenario('Changing canManageCommunities without permission', ({ Given, When, Then }) => { + let setWithoutPermission: () => void; + Given('a StaffRoleSectionPermissions entity without permission to manage staff roles or system account', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: false }); + entity = new StaffRoleSectionPermissions(makeProps(), visa); + }); + When('I try to set canManageCommunities to true', () => { + setWithoutPermission = () => { + entity.canManageCommunities = true; + }; + }); + Then('a PermissionError should be thrown', () => { + expect(setWithoutPermission).toThrow(PermissionError); + expect(setWithoutPermission).toThrow('Cannot set permission'); + }); + }); + + // canManageUser + Scenario('Changing canManageUser with manage staff roles permission', ({ Given, When, Then }) => { + Given('a StaffRoleSectionPermissions entity with permission to manage staff roles', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: true, isSystemAccount: false }); + entity = new StaffRoleSectionPermissions(makeProps(), visa); + }); + When('I set canManageUser to true', () => { + entity.canManageUser = true; + }); + Then('the property should be updated to true', () => { + expect(entity.canManageUser).toBe(true); + }); + }); + + Scenario('Changing canManageUser with system account permission', ({ Given, When, Then }) => { + Given('a StaffRoleSectionPermissions entity with system account permission', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: true }); + entity = new StaffRoleSectionPermissions(makeProps(), visa); + }); + When('I set canManageUser to true', () => { + entity.canManageUser = true; + }); + Then('the property should be updated to true', () => { + expect(entity.canManageUser).toBe(true); + }); + }); + + Scenario('Changing canManageUser without permission', ({ Given, When, Then }) => { + let setWithoutPermission: () => void; + Given('a StaffRoleSectionPermissions entity without permission to manage staff roles or system account', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: false }); + entity = new StaffRoleSectionPermissions(makeProps(), visa); + }); + When('I try to set canManageUser to true', () => { + setWithoutPermission = () => { + entity.canManageUser = true; + }; + }); + Then('a PermissionError should be thrown', () => { + expect(setWithoutPermission).toThrow(PermissionError); + expect(setWithoutPermission).toThrow('Cannot set permission'); + }); + }); + + // canManageFinance + Scenario('Changing canManageFinance with manage staff roles permission', ({ Given, When, Then }) => { + Given('a StaffRoleSectionPermissions entity with permission to manage staff roles', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: true, isSystemAccount: false }); + entity = new StaffRoleSectionPermissions(makeProps(), visa); + }); + When('I set canManageFinance to true', () => { + entity.canManageFinance = true; + }); + Then('the property should be updated to true', () => { + expect(entity.canManageFinance).toBe(true); + }); + }); + + Scenario('Changing canManageFinance with system account permission', ({ Given, When, Then }) => { + Given('a StaffRoleSectionPermissions entity with system account permission', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: true }); + entity = new StaffRoleSectionPermissions(makeProps(), visa); + }); + When('I set canManageFinance to true', () => { + entity.canManageFinance = true; + }); + Then('the property should be updated to true', () => { + expect(entity.canManageFinance).toBe(true); + }); + }); + + Scenario('Changing canManageFinance without permission', ({ Given, When, Then }) => { + let setWithoutPermission: () => void; + Given('a StaffRoleSectionPermissions entity without permission to manage staff roles or system account', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: false }); + entity = new StaffRoleSectionPermissions(makeProps(), visa); + }); + When('I try to set canManageFinance to true', () => { + setWithoutPermission = () => { + entity.canManageFinance = true; + }; + }); + Then('a PermissionError should be thrown', () => { + expect(setWithoutPermission).toThrow(PermissionError); + expect(setWithoutPermission).toThrow('Cannot set permission'); + }); + }); + + // canManageTechAdmin + Scenario('Changing canManageTechAdmin with manage staff roles permission', ({ Given, When, Then }) => { + Given('a StaffRoleSectionPermissions entity with permission to manage staff roles', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: true, isSystemAccount: false }); + entity = new StaffRoleSectionPermissions(makeProps(), visa); + }); + When('I set canManageTechAdmin to true', () => { + entity.canManageTechAdmin = true; + }); + Then('the property should be updated to true', () => { + expect(entity.canManageTechAdmin).toBe(true); + }); + }); + + Scenario('Changing canManageTechAdmin with system account permission', ({ Given, When, Then }) => { + Given('a StaffRoleSectionPermissions entity with system account permission', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: true }); + entity = new StaffRoleSectionPermissions(makeProps(), visa); + }); + When('I set canManageTechAdmin to true', () => { + entity.canManageTechAdmin = true; + }); + Then('the property should be updated to true', () => { + expect(entity.canManageTechAdmin).toBe(true); + }); + }); + + Scenario('Changing canManageTechAdmin without permission', ({ Given, When, Then }) => { + let setWithoutPermission: () => void; + Given('a StaffRoleSectionPermissions entity without permission to manage staff roles or system account', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: false }); + entity = new StaffRoleSectionPermissions(makeProps(), visa); + }); + When('I try to set canManageTechAdmin to true', () => { + setWithoutPermission = () => { + entity.canManageTechAdmin = true; + }; + }); + Then('a PermissionError should be thrown', () => { + expect(setWithoutPermission).toThrow(PermissionError); + expect(setWithoutPermission).toThrow('Cannot set permission'); + }); + }); +}); diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-section-permissions.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-section-permissions.ts new file mode 100644 index 000000000..503b7f811 --- /dev/null +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-section-permissions.ts @@ -0,0 +1,61 @@ +import { PermissionError } from '@cellix/domain-seedwork/domain-entity'; +import type { ValueObjectProps } from '@cellix/domain-seedwork/value-object'; +import { ValueObject } from '@cellix/domain-seedwork/value-object'; +import type { UserVisa } from '../user.visa.ts'; + +interface StaffRoleSectionPermissionsSpec { + canManageCommunities: boolean; + canManageUser: boolean; + canManageFinance: boolean; + canManageTechAdmin: boolean; +} + +export interface StaffRoleSectionPermissionsProps extends StaffRoleSectionPermissionsSpec, ValueObjectProps {} +export interface StaffRoleSectionPermissionsEntityReference extends Readonly {} + +export class StaffRoleSectionPermissions extends ValueObject implements StaffRoleSectionPermissionsEntityReference { + private readonly visa: UserVisa; + + constructor(props: StaffRoleSectionPermissionsProps, visa: UserVisa) { + super(props); + this.visa = visa; + } + + private validateVisa() { + if (!this.visa.determineIf((permissions) => permissions.canManageStaffRolesAndPermissions || permissions.isSystemAccount)) { + throw new PermissionError('Cannot set permission'); + } + } + + get canManageCommunities(): boolean { + return this.props.canManageCommunities; + } + set canManageCommunities(value: boolean) { + this.validateVisa(); + this.props.canManageCommunities = value; + } + + get canManageUser(): boolean { + return this.props.canManageUser; + } + set canManageUser(value: boolean) { + this.validateVisa(); + this.props.canManageUser = value; + } + + get canManageFinance(): boolean { + return this.props.canManageFinance; + } + set canManageFinance(value: boolean) { + this.validateVisa(); + this.props.canManageFinance = value; + } + + get canManageTechAdmin(): boolean { + return this.props.canManageTechAdmin; + } + set canManageTechAdmin(value: boolean) { + this.validateVisa(); + this.props.canManageTechAdmin = value; + } +} diff --git a/packages/ocom/graphql/src/schema/builder/resolver-builder.ts b/packages/ocom/graphql/src/schema/builder/resolver-builder.ts index 8fc71a151..5992cc548 100644 --- a/packages/ocom/graphql/src/schema/builder/resolver-builder.ts +++ b/packages/ocom/graphql/src/schema/builder/resolver-builder.ts @@ -1,5 +1,4 @@ import { mergeResolvers } from '@graphql-tools/merge'; -import endUserRoleResolvers from '../types/end-user-role.resolvers.ts'; import type { Resolvers } from './generated.ts'; import { ocomGraphqlPermissions, ocomGraphqlResolvers } from './resolver-manifest.generated.ts'; @@ -7,5 +6,5 @@ function mergeResolverModules(modules: Resolvers[]): Resolvers { return (modules.length === 0 ? {} : mergeResolvers(modules)) as Resolvers; } -export const resolvers: Resolvers = mergeResolverModules([...ocomGraphqlResolvers, endUserRoleResolvers]); +export const resolvers: Resolvers = mergeResolverModules([...ocomGraphqlResolvers]); export const permissions: Resolvers = mergeResolverModules(ocomGraphqlPermissions); diff --git a/packages/ocom/graphql/src/schema/types/staff-user.graphql b/packages/ocom/graphql/src/schema/types/staff-user.graphql new file mode 100644 index 000000000..1cf3a56de --- /dev/null +++ b/packages/ocom/graphql/src/schema/types/staff-user.graphql @@ -0,0 +1,42 @@ +type StaffRoleSectionPermissions { + canManageCommunities: Boolean! + canManageUser: Boolean! + canManageFinance: Boolean! + canManageTechAdmin: Boolean! +} + +type StaffRolePermissions { + sectionPermissions: StaffRoleSectionPermissions! +} + +type StaffRole implements MongoBase { + roleName: String! + isDefault: Boolean! + roleType: String + permissions: StaffRolePermissions! + + id: ObjectID! + schemaVersion: String + createdAt: DateTime + updatedAt: DateTime +} + +type StaffUser implements MongoBase { + externalId: String! + firstName: String! + lastName: String! + email: String! + displayName: String! + accessBlocked: Boolean! + tags: [String!]! + role: StaffRole + + id: ObjectID! + schemaVersion: String + createdAt: DateTime + updatedAt: DateTime +} + +extend type Query { + currentStaffUserAndCreateIfNotExists: StaffUser! +} diff --git a/packages/ocom/graphql/src/schema/types/staff-user.resolvers.ts b/packages/ocom/graphql/src/schema/types/staff-user.resolvers.ts new file mode 100644 index 000000000..c935de243 --- /dev/null +++ b/packages/ocom/graphql/src/schema/types/staff-user.resolvers.ts @@ -0,0 +1,24 @@ +import type { GraphQLResolveInfo } from 'graphql'; +import type { Resolvers, StaffUser } from '../builder/generated.ts'; +import type { GraphContext } from '../context.ts'; + +const staffUser: Resolvers = { + Query: { + currentStaffUserAndCreateIfNotExists: async (_parent, _args, context: GraphContext, _info: GraphQLResolveInfo) => { + const jwt = context.applicationServices.verifiedUser?.verifiedJwt; + if (!jwt) { + throw new Error('Unauthorized'); + } + const result = await context.applicationServices.User.StaffUser.createIfNotExists({ + externalId: jwt.sub, + firstName: jwt.given_name ?? '', + lastName: jwt.family_name ?? '', + email: jwt.email ?? '', + aadRoles: jwt.roles ?? [], + }); + return result as unknown as StaffUser; + }, + }, +}; + +export default staffUser; diff --git a/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.ts b/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.ts index 751577717..290b4a86a 100644 --- a/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.ts +++ b/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.ts @@ -1,15 +1,15 @@ import { MongooseSeedwork } from '@cellix/mongoose-seedwork'; - -import { Domain } from '@ocom/domain'; import type { StaffRole, StaffRoleCommunityPermissions, StaffRolePermissions, StaffRolePropertyPermissions, + StaffRoleSectionPermissions, StaffRoleServicePermissions, StaffRoleServiceTicketPermissions, StaffRoleViolationTicketPermissions, } from '@ocom/data-sources-mongoose-models/role/staff-role'; +import { Domain } from '@ocom/domain'; export class StaffRoleConverter extends MongooseSeedwork.MongoTypeConverter> { constructor() { @@ -53,6 +53,18 @@ export class StaffRolePermissionsAdapter implements Domain.Contexts.User.StaffRo this.doc = permissions; } + get sectionPermissions(): Domain.Contexts.User.StaffRole.StaffRoleSectionPermissionsProps { + if (!this.doc.sectionPermissions) { + this.doc.sectionPermissions = { + canManageCommunities: false, + canManageUser: false, + canManageFinance: false, + canManageTechAdmin: false, + }; + } + return new StaffRoleSectionPermissionsAdapter(this.doc.sectionPermissions); + } + get communityPermissions(): Domain.Contexts.User.StaffRole.StaffRoleCommunityPermissionsProps { if (!this.doc.communityPermissions) { this.doc.communityPermissions = { @@ -269,3 +281,47 @@ export class StaffRoleViolationTicketPermissionsAdapter implements Domain.Contex this.doc.canWorkOnTickets = value; } } + +class StaffRoleSectionPermissionsAdapter implements Domain.Contexts.User.StaffRole.StaffRoleSectionPermissionsProps { + private readonly doc: StaffRoleSectionPermissions; + + constructor(permissions: StaffRoleSectionPermissions) { + this.doc = permissions; + } + + private ensureValue(value: boolean | undefined): boolean { + return value ?? false; + } + + get id(): string | undefined { + return this.doc.id?.toString(); + } + + get canManageCommunities(): boolean { + return this.ensureValue(this.doc.canManageCommunities); + } + set canManageCommunities(value: boolean) { + this.doc.canManageCommunities = value; + } + + get canManageUser(): boolean { + return this.ensureValue(this.doc.canManageUser); + } + set canManageUser(value: boolean) { + this.doc.canManageUser = value; + } + + get canManageFinance(): boolean { + return this.ensureValue(this.doc.canManageFinance); + } + set canManageFinance(value: boolean) { + this.doc.canManageFinance = value; + } + + get canManageTechAdmin(): boolean { + return this.ensureValue(this.doc.canManageTechAdmin); + } + set canManageTechAdmin(value: boolean) { + this.doc.canManageTechAdmin = value; + } +} diff --git a/packages/ocom/persistence/src/datasources/readonly/index.test.ts b/packages/ocom/persistence/src/datasources/readonly/index.test.ts index 04d231428..536162ec4 100644 --- a/packages/ocom/persistence/src/datasources/readonly/index.test.ts +++ b/packages/ocom/persistence/src/datasources/readonly/index.test.ts @@ -1,13 +1,13 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; -import { expect, vi } from 'vitest'; - -import type { Domain } from '@ocom/domain'; -import { ReadonlyDataSourceImplementation } from './index.ts'; import type { CommunityModelType } from '@ocom/data-sources-mongoose-models/community'; import type { MemberModelType } from '@ocom/data-sources-mongoose-models/member'; import type { EndUserModelType } from '@ocom/data-sources-mongoose-models/user/end-user'; +import type { StaffUserModelType } from '@ocom/data-sources-mongoose-models/user/staff-user'; +import type { Domain } from '@ocom/domain'; +import { expect, vi } from 'vitest'; +import { ReadonlyDataSourceImplementation } from './index.ts'; const test = { for: describeFeature }; const __dirname = path.dirname(fileURLToPath(import.meta.url)); @@ -32,6 +32,12 @@ function makeMockModelsContext() { create: vi.fn(), aggregate: vi.fn(), } as unknown as EndUserModelType, + StaffUser: { + findById: vi.fn(), + findOne: vi.fn(), + find: vi.fn(), + create: vi.fn(), + } as unknown as StaffUserModelType, } as unknown as Parameters[0]; } @@ -101,6 +107,8 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { And('the User property should have the correct structure', () => { expect(result.User).toHaveProperty('EndUser'); expect(result.User.EndUser).toHaveProperty('EndUserReadRepo'); + expect(result.User).toHaveProperty('StaffUser'); + expect(result.User.StaffUser).toHaveProperty('StaffUserReadRepo'); }); }); }); diff --git a/packages/ocom/persistence/src/datasources/readonly/index.ts b/packages/ocom/persistence/src/datasources/readonly/index.ts index d8940adb8..9342ba8ad 100644 --- a/packages/ocom/persistence/src/datasources/readonly/index.ts +++ b/packages/ocom/persistence/src/datasources/readonly/index.ts @@ -5,6 +5,7 @@ import { CommunityContext } from './community/index.ts'; import type * as Member from './community/member/index.ts'; import type * as EndUser from './user/end-user/index.ts'; import { UserContext } from './user/index.ts'; +import type * as StaffUser from './user/staff-user/index.ts'; export interface ReadonlyDataSource { Community: { @@ -19,6 +20,9 @@ export interface ReadonlyDataSource { EndUser: { EndUserReadRepo: EndUser.EndUserReadRepository; }; + StaffUser: { + StaffUserReadRepo: StaffUser.StaffUserReadRepository; + }; }; } diff --git a/packages/ocom/persistence/src/datasources/readonly/user/index.ts b/packages/ocom/persistence/src/datasources/readonly/user/index.ts index 54cb3892a..ab40bc6e7 100644 --- a/packages/ocom/persistence/src/datasources/readonly/user/index.ts +++ b/packages/ocom/persistence/src/datasources/readonly/user/index.ts @@ -1,7 +1,9 @@ import type { Domain } from '@ocom/domain'; import type { ModelsContext } from '../../../index.ts'; import { EndUserReadRepositoryImpl } from './end-user/index.ts'; +import { StaffUserReadRepositoryImpl } from './staff-user/index.ts'; export const UserContext = (models: ModelsContext, passport: Domain.Passport) => ({ EndUser: EndUserReadRepositoryImpl(models, passport), + StaffUser: StaffUserReadRepositoryImpl(models, passport), }); diff --git a/packages/ocom/persistence/src/datasources/readonly/user/staff-user/index.ts b/packages/ocom/persistence/src/datasources/readonly/user/staff-user/index.ts new file mode 100644 index 000000000..75eef71cf --- /dev/null +++ b/packages/ocom/persistence/src/datasources/readonly/user/staff-user/index.ts @@ -0,0 +1,11 @@ +import type { Domain } from '@ocom/domain'; +import type { ModelsContext } from '../../../../index.ts'; +import { getStaffUserReadRepository } from './staff-user.read-repository.ts'; + +export type { StaffUserReadRepository } from './staff-user.read-repository.ts'; + +export const StaffUserReadRepositoryImpl = (models: ModelsContext, passport: Domain.Passport) => { + return { + StaffUserReadRepo: getStaffUserReadRepository(models, passport), + }; +}; diff --git a/packages/ocom/persistence/src/datasources/readonly/user/staff-user/staff-user.read-repository.ts b/packages/ocom/persistence/src/datasources/readonly/user/staff-user/staff-user.read-repository.ts new file mode 100644 index 000000000..0824f8934 --- /dev/null +++ b/packages/ocom/persistence/src/datasources/readonly/user/staff-user/staff-user.read-repository.ts @@ -0,0 +1,35 @@ +import type { StaffUserModelType } from '@ocom/data-sources-mongoose-models/user/staff-user'; +import type { Domain } from '@ocom/domain'; +import type { ModelsContext } from '../../../../index.ts'; +import { StaffUserConverter } from '../../../domain/user/staff-user/staff-user.domain-adapter.ts'; + +export interface StaffUserReadRepository { + getByExternalId: (externalId: string) => Promise; +} + +class StaffUserReadRepositoryImpl implements StaffUserReadRepository { + private readonly model: StaffUserModelType; + private readonly converter: StaffUserConverter; + private readonly passport: Domain.Passport; + + constructor(models: ModelsContext, passport: Domain.Passport) { + if (!models.StaffUser) { + throw new Error('StaffUser model is not available in the mongoose context'); + } + this.model = models.StaffUser; + this.converter = new StaffUserConverter(); + this.passport = passport; + } + + async getByExternalId(externalId: string): Promise { + const doc = await this.model.findOne({ externalId }).populate('role').exec(); + if (!doc) { + return null; + } + return this.converter.toDomain(doc, this.passport); + } +} + +export const getStaffUserReadRepository = (models: ModelsContext, passport: Domain.Passport): StaffUserReadRepository => { + return new StaffUserReadRepositoryImpl(models, passport); +}; diff --git a/packages/ocom/ui-staff-shared/src/require-role.tsx b/packages/ocom/ui-staff-shared/src/require-role.tsx index 557b62623..309d7e227 100644 --- a/packages/ocom/ui-staff-shared/src/require-role.tsx +++ b/packages/ocom/ui-staff-shared/src/require-role.tsx @@ -1,23 +1,43 @@ import { type FC, type ReactNode, useContext } from 'react'; import { Navigate } from 'react-router-dom'; import { extractRoles } from './staff-app-roles.ts'; +import type { StaffAuth } from './staff-route-shell.tsx'; import { StaffAuthContext } from './staff-route-shell.tsx'; export interface RequireRoleProps { /** At least one of these roles must be present in the authenticated user's token. */ roles: readonly string[]; + /** When provided, gate by this backend permission flag instead of JWT roles. */ + permKey?: keyof NonNullable; children: ReactNode; } /** - * Guards a UI branch behind one or more Entra app roles. + * Guards a UI branch behind one or more Entra app roles, or a backend permission flag. * - * Reads the authenticated identity from {@link StaffAuthContext} and redirects - * to `/unauthorized` when the user lacks every required role. - * Must be rendered inside a {@link StaffAuthProvider} and a React Router context. + * When `permKey` is supplied and the `StaffAuthContext` already has a `permissions` object + * (populated from the backend), the permission flag takes precedence over JWT role strings. + * Falls back to the JWT role check when permissions are not yet available. */ -export const RequireRole: FC = ({ roles, children }) => { +export const RequireRole: FC = ({ roles, permKey, children }) => { const auth = useContext(StaffAuthContext); + const perms = auth?.permissions; + + // Prefer backend permission flag when it has been fetched + if (permKey !== undefined && perms !== undefined) { + const isAuthorized = perms[permKey] === true; + if (!isAuthorized) { + return ( + + ); + } + return <>{children}; + } + + // Fallback: check JWT roles const userRoles = auth?.roles ?? extractRoles(auth?.raw); const isAuthorized = roles.length === 0 || (userRoles !== undefined && roles.some((r) => userRoles.includes(r))); diff --git a/packages/ocom/ui-staff-shared/src/staff-route-shell.tsx b/packages/ocom/ui-staff-shared/src/staff-route-shell.tsx index f9efab61c..aa5d5f70c 100644 --- a/packages/ocom/ui-staff-shared/src/staff-route-shell.tsx +++ b/packages/ocom/ui-staff-shared/src/staff-route-shell.tsx @@ -13,6 +13,12 @@ export type StaffAuth = { roles?: string[]; raw?: Record; onLogout?: () => Promise | void; + permissions?: { + canManageCommunities?: boolean; + canManageUser?: boolean; + canManageFinance?: boolean; + canManageTechAdmin?: boolean; + }; }; export const StaffAuthContext = createContext(undefined); @@ -20,10 +26,10 @@ export const StaffAuthContext = createContext(undefined); export const StaffAuthProvider: FC<{ value: StaffAuth; children?: ReactNode }> = ({ value, children }) => {children}; const allNavLinks = [ - { label: 'Community Management', href: '/staff/community', roles: staffRouteRoles['/staff/community'] }, - { label: 'User Management', href: '/staff/users', roles: staffRouteRoles['/staff/users'] }, - { label: 'Finance', href: '/staff/finance', roles: staffRouteRoles['/staff/finance'] }, - { label: 'Tech Admin', href: '/staff/tech', roles: staffRouteRoles['/staff/tech'] }, + { label: 'Community Management', href: '/staff/community', roles: staffRouteRoles['/staff/community'], permKey: 'canManageCommunities' as const }, + { label: 'User Management', href: '/staff/users', roles: staffRouteRoles['/staff/users'], permKey: 'canManageUser' as const }, + { label: 'Finance', href: '/staff/finance', roles: staffRouteRoles['/staff/finance'], permKey: 'canManageFinance' as const }, + { label: 'Tech Admin', href: '/staff/tech', roles: staffRouteRoles['/staff/tech'], permKey: 'canManageTechAdmin' as const }, ]; export const StaffRouteShell: FC = ({ title, description }) => { @@ -33,7 +39,18 @@ export const StaffRouteShell: FC = ({ title, description } const fallbackName = raw ? ((raw['name'] as string | undefined) ?? (raw['preferred_username'] as string | undefined) ?? (raw['email'] as string | undefined)) : undefined; const name = auth?.name ?? auth?.username ?? auth?.email ?? fallbackName; const roles = auth?.roles ?? extractRoles(auth?.raw); - const navLinks = allNavLinks.filter((link) => link.roles.length === 0 || (roles !== undefined && link.roles.some((r) => roles.includes(r)))); + const perms = auth?.permissions; + + const isNavLinkVisible = (link: { roles: readonly string[]; permKey?: keyof NonNullable }): boolean => { + if (link.roles.length === 0) return true; + // Prefer backend permission flags when available + if (perms && link.permKey !== undefined) { + return perms[link.permKey] === true; + } + return roles !== undefined && link.roles.some((r) => roles.includes(r)); + }; + + const navLinks = allNavLinks.filter((link) => isNavLinkVisible(link)); return (
    From d1b3d25b59a14842200a4689070da40a81c96bcd Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Thu, 7 May 2026 00:24:01 +0530 Subject: [PATCH 48/88] feat: add staff user query and permissions handling in community and admin sections --- .../community-list.container.graphql | 12 +++++++++++ .../components/community-list.container.tsx | 5 +++++ .../src/components/community-list.tsx | 16 ++++++++------- .../ui-community-route-admin/src/index.tsx | 17 ++++++++++++---- .../src/section-layout.container.tsx | 10 +++++++++- .../src/section-layout.graphql | 20 +++++++++++++++++++ .../src/section-layout.tsx | 10 +++++++++- 7 files changed, 77 insertions(+), 13 deletions(-) diff --git a/packages/ocom/ui-community-route-accounts/src/components/community-list.container.graphql b/packages/ocom/ui-community-route-accounts/src/components/community-list.container.graphql index 70e350053..6b3f040a5 100644 --- a/packages/ocom/ui-community-route-accounts/src/components/community-list.container.graphql +++ b/packages/ocom/ui-community-route-accounts/src/components/community-list.container.graphql @@ -10,6 +10,18 @@ query AccountsCommunityListContainerMembersForCurrentEndUser { } } +query AccountsCommunityListContainerCurrentStaffUser { + currentStaffUserAndCreateIfNotExists { + role { + permissions { + sectionPermissions { + canManageCommunities + } + } + } + } +} + fragment AccountsCommunityListContainerMemberFields on Member { memberName community { diff --git a/packages/ocom/ui-community-route-accounts/src/components/community-list.container.tsx b/packages/ocom/ui-community-route-accounts/src/components/community-list.container.tsx index 019795b72..e4830def4 100644 --- a/packages/ocom/ui-community-route-accounts/src/components/community-list.container.tsx +++ b/packages/ocom/ui-community-route-accounts/src/components/community-list.container.tsx @@ -2,6 +2,7 @@ import { useQuery } from '@apollo/client'; import { ComponentQueryLoader } from '@cellix/ui-core'; import { AccountsCommunityListContainerCommunitiesForCurrentEndUserDocument, + AccountsCommunityListContainerCurrentStaffUserDocument, type AccountsCommunityListContainerCommunityFieldsFragment, type AccountsCommunityListContainerMemberFieldsFragment, AccountsCommunityListContainerMembersForCurrentEndUserDocument, @@ -19,6 +20,9 @@ export const CommunityListContainer: React.FC = () => { fetchPolicy: 'network-only', }); + const { data: staffUserData } = useQuery(AccountsCommunityListContainerCurrentStaffUserDocument); + const canCreateCommunity = staffUserData?.currentStaffUserAndCreateIfNotExists?.role?.permissions?.sectionPermissions?.canManageCommunities ?? false; + const members: AccountsCommunityListContainerMemberFieldsFragment[][] = []; if (membersData?.membersForCurrentEndUser && membersData?.membersForCurrentEndUser.length > 0 && communityData?.communitiesForCurrentEndUser) { for (const community of communityData.communitiesForCurrentEndUser) { @@ -36,6 +40,7 @@ export const CommunityListContainer: React.FC = () => { communities: communityData?.communitiesForCurrentEndUser as AccountsCommunityListContainerCommunityFieldsFragment[], members: members as AccountsCommunityListContainerMemberFieldsFragment[][], }} + canCreateCommunity={canCreateCommunity} /> } noDataComponent={
    No Data...
    } diff --git a/packages/ocom/ui-community-route-accounts/src/components/community-list.tsx b/packages/ocom/ui-community-route-accounts/src/components/community-list.tsx index c0f38203c..40f2c5125 100644 --- a/packages/ocom/ui-community-route-accounts/src/components/community-list.tsx +++ b/packages/ocom/ui-community-route-accounts/src/components/community-list.tsx @@ -11,12 +11,12 @@ export interface CommunityListProps { communities: AccountsCommunityListContainerCommunityFieldsFragment[]; members: AccountsCommunityListContainerMemberFieldsFragment[][]; }; + canCreateCommunity?: boolean; } export const CommunityList: React.FC = (props) => { const [communityList, setCommunityList] = useState(props.data.communities); const navigate = useNavigate(); - const onChange = (event: ChangeEvent) => { const searchValue = event.target.value; if (searchValue === '') { @@ -120,12 +120,14 @@ export const CommunityList: React.FC = (props) => {

    Navigate to a Community

    - + {props.canCreateCommunity && ( + + )}
    { const pageLayouts: PageLayoutProps[] = [ { @@ -21,7 +26,10 @@ export const Admin: React.FC = () => { icon: , id: 2, parent: 'ROOT', - // hasPermissions: (member: Member) => member?.isAdmin ?? false + hasPermissions: (data: unknown) => { + const adminData = data as AdminMenuData; + return adminData?.staffPermissions?.canManageUser ?? false; + }, }, { path: '/community/:communityId/admin/:memberId/settings/*', @@ -29,9 +37,10 @@ export const Admin: React.FC = () => { icon: , id: 3, parent: 'ROOT', - // Note: Permission check would be: - // hasPermissions: (member: Member) => member?.role?.permissions?.communityPermissions?.canManageCommunitySettings ?? false - // Currently schema doesn't include role/permissions, so we allow all admin users to access settings + hasPermissions: (data: unknown) => { + const adminData = data as AdminMenuData; + return adminData?.staffPermissions?.canManageCommunities ?? false; + }, }, ]; diff --git a/packages/ocom/ui-community-route-admin/src/section-layout.container.tsx b/packages/ocom/ui-community-route-admin/src/section-layout.container.tsx index f446d084d..50e2793c2 100644 --- a/packages/ocom/ui-community-route-admin/src/section-layout.container.tsx +++ b/packages/ocom/ui-community-route-admin/src/section-layout.container.tsx @@ -2,7 +2,11 @@ import { useQuery } from '@apollo/client'; import { ComponentQueryLoader } from '@cellix/ui-core'; import type { PageLayoutProps } from '@ocom/ui-shared'; import { useParams } from 'react-router-dom'; -import { AdminSectionLayoutContainerMembersForCurrentEndUserDocument, type Member } from './generated.tsx'; +import { + AdminSectionLayoutContainerCurrentStaffUserDocument, + AdminSectionLayoutContainerMembersForCurrentEndUserDocument, + type Member, +} from './generated.tsx'; import { SectionLayout } from './section-layout.tsx'; interface SectionLayoutContainerProps { @@ -13,6 +17,9 @@ export const SectionLayoutContainer: React.FC = (pr const params = useParams(); const { data: membersData, loading: membersLoading, error: membersError } = useQuery(AdminSectionLayoutContainerMembersForCurrentEndUserDocument); + const { data: staffUserData } = useQuery(AdminSectionLayoutContainerCurrentStaffUserDocument); + + const staffSectionPermissions = staffUserData?.currentStaffUserAndCreateIfNotExists?.role?.permissions?.sectionPermissions ?? null; return ( = (pr pageLayouts={props.pageLayouts} // biome-ignore lint:useLiteralKeys memberData={membersData?.membersForCurrentEndUser.find((member) => member.id === params['memberId']) as Member} + staffSectionPermissions={staffSectionPermissions} /> } error={membersError} diff --git a/packages/ocom/ui-community-route-admin/src/section-layout.graphql b/packages/ocom/ui-community-route-admin/src/section-layout.graphql index 4dbdc6cac..deef4e766 100644 --- a/packages/ocom/ui-community-route-admin/src/section-layout.graphql +++ b/packages/ocom/ui-community-route-admin/src/section-layout.graphql @@ -4,6 +4,12 @@ query AdminSectionLayoutContainerMembersForCurrentEndUser { } } +query AdminSectionLayoutContainerCurrentStaffUser { + currentStaffUserAndCreateIfNotExists { + ...AdminSectionLayoutContainerStaffUserFields + } +} + fragment AdminSectionLayoutContainerMemberFields on Member { id memberName @@ -13,3 +19,17 @@ fragment AdminSectionLayoutContainerMemberFields on Member { name } } + +fragment AdminSectionLayoutContainerStaffUserFields on StaffUser { + id + role { + permissions { + sectionPermissions { + canManageCommunities + canManageUser + canManageFinance + canManageTechAdmin + } + } + } +} diff --git a/packages/ocom/ui-community-route-admin/src/section-layout.tsx b/packages/ocom/ui-community-route-admin/src/section-layout.tsx index 85e655538..e0fa24948 100644 --- a/packages/ocom/ui-community-route-admin/src/section-layout.tsx +++ b/packages/ocom/ui-community-route-admin/src/section-layout.tsx @@ -21,9 +21,17 @@ const handleToggler = (isExpanded: boolean, setIsExpanded: (value: boolean) => v } }; +export interface AdminStaffSectionPermissions { + canManageCommunities: boolean; + canManageUser: boolean; + canManageFinance: boolean; + canManageTechAdmin: boolean; +} + interface AdminSectionLayoutProps { pageLayouts: PageLayoutProps[]; memberData: Member; + staffSectionPermissions: AdminStaffSectionPermissions | null; } export const SectionLayout: React.FC = (props) => { @@ -36,7 +44,7 @@ export const SectionLayout: React.FC = (props) => { const menuComponentProps: MenuComponentProps = { pageLayouts: props.pageLayouts, - memberData: props.memberData, + memberData: { member: props.memberData, staffPermissions: props.staffSectionPermissions }, theme: 'light', mode: 'inline', }; From a6f530ff792e543f19b022e249b2f81df93c7143 Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Wed, 6 May 2026 15:19:27 -0400 Subject: [PATCH 49/88] feat: add staff user role csv file --- staff-user-role.csv | 132 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 staff-user-role.csv diff --git a/staff-user-role.csv b/staff-user-role.csv new file mode 100644 index 000000000..dcc670065 --- /dev/null +++ b/staff-user-role.csv @@ -0,0 +1,132 @@ +3Navigate Home,,,,,,,,,,,,,,,,, +collection:roles,,,,,,,,,,,,,,,,, +Staff User Role,Staff,,,,,,,,,,,,,,,, +Properties,,,DataType,Rules,,,,,,,,,,,,, +roleName,U,,"required, string, maxLength 256",,,,,,,,,,,,,, +isDefault,U,,"required, boolean, default false","omitted in the common case for user-created roles, only specified for system-created default roles",,,,,,,,,,,,, +roleType,U,,"required, string, default value = ""staff-user-role""",,,,,,,,,,,,,, +enterpriseAppRole,U,,"required, string,enum","""Staff.CaseManager"" | ""Staff.Finance"" | ""Staff.ServiceLineOwner"" | ""Staff.TechAdmin""",,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +permissions {,,,,,,,,,,,,,,,,, + communityPermissions {,,,,,,,,,,,,,,,,, + canManageCommunities,U,,"boolean, default false",,,,,,,,,,,,,, + canChanageCommunityOwner,U,,"boolean, default false",,,,,,,,,,,,,, + canDeleteCommunities,U,,"boolean, default false",,,,,,,,,,,,,, + canReIndexSearchCollections,U,,"boolean, default false",,,,,,,,,,,,,, + },,,,,,,,,,,,,,,,, + financePermissions {,,,,,,,,,,,,,,,,, + canManageFinance,U,,"boolean, default false",,,,,,,,,,,,,, + canViewGLBatchSummaries,U,,"boolean, default false",,,,,,,,,,,,,, + canViewFinanceConfigs,U,,"boolean, default false",,,,,,,,,,,,,, + canCreateFinanceConfigs,U,,"boolean, default false",,,,,,,,,,,,,, + },,,,,,,,,,,,,,,,, + servicePermissions {,,,,,,,,,,,,,,,,, + canManageServices,U,,"boolean, default false",,,,,,,,,,,,,, + },,,,,,,,,,,,,,,,, + serviceTicketPermissions {,,,,,,,,,,,,,,,,, + canManageTickets,U,,"boolean, default false",,,,,,,,,,,,,, + canCreateTickets,U,,"boolean, default false",,,,,,,,,,,,,, + canAssignTickets,U,,"boolean, default false",,,,,,,,,,,,,, + canUpdateTickets,U,,"boolean, default false",,,,,,,,,,,,,, + },,,,,,,,,,,,,,,,, + techAdminPermissions {,,,,,,,,,,,,,,,,, + canManageTechAdmin,U,,"boolean, default false",,,,,,,,,,,,,, + canViewDatabaseExplorer,U,,"boolean, default false",,,,,,,,,,,,,, + canViewBlobExplorer,U,,"boolean, default false",,,,,,,,,,,,,, + canViewQueueDashboard,U,,"boolean, default false",,,,,,,,,,,,,, + canSendQueueMessages,U,,"boolean, default false",,,,,,,,,,,,,, + },,,,,,,,,,,,,,,,, + userPermissions {,,,,,,,,,,,,,,,,, + canManageUsers,U,,"boolean, default false",,,,,,,,,,,,,, + },,,,,,,,,,,,,,,,, + violationTicketPermissions {,,,,,,,,,,,,,,,,, + canManageTickets,U,,"boolean, default false",,,,,,,,,,,,,, + canCreateTickets,U,,"boolean, default false",,,,,,,,,,,,,, + canAssignTickets,U,,"boolean, default false",,,,,,,,,,,,,, + canUpdateTickets,U,,"boolean, default false",,,,,,,,,,,,,, + },,,,,,,,,,,,,,,,, +},,,,,,,,,,,,,,,,, +schemaVersion,R,,"required, string, default value = ""1.0.0""",,,,,,,,,,,,,, +_id,R,,"required, unique identifier",,,,,,,,,,,,,, +createdAt,R,,"required, timestamp",,,,,,,,,,,,,, +updatedAt,R,,"required, timestamp",,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,, From 9ce1e954a6f3628fc42788d2e32c610c3b42beed Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Wed, 6 May 2026 16:26:18 -0400 Subject: [PATCH 50/88] update staff role permissions and community list story --- .../src/models/role/staff-role.model.ts | 65 +++++++++++++++++-- .../staff-role/staff-role.domain-adapter.ts | 3 + .../src/components/community-list.stories.tsx | 1 + 3 files changed, 64 insertions(+), 5 deletions(-) diff --git a/packages/ocom/data-sources-mongoose-models/src/models/role/staff-role.model.ts b/packages/ocom/data-sources-mongoose-models/src/models/role/staff-role.model.ts index e718f02aa..f66cf5bbc 100644 --- a/packages/ocom/data-sources-mongoose-models/src/models/role/staff-role.model.ts +++ b/packages/ocom/data-sources-mongoose-models/src/models/role/staff-role.model.ts @@ -1,6 +1,8 @@ import { type Model, type ObjectId, Schema, type SchemaDefinition } from 'mongoose'; import { type Role, type RoleModelType, roleOptions } from './role.model.ts'; +export const StaffEnterpriseAppRoles = ['Staff.CaseManager', 'Staff.Finance', 'Staff.ServiceLineOwner', 'Staff.TechAdmin'] as const; + export interface StaffRoleSectionPermissions { id?: ObjectId; canManageCommunities: boolean; @@ -20,6 +22,7 @@ export interface StaffRoleServiceTicketPermissions { canCreateTickets: boolean; canManageTickets: boolean; canAssignTickets: boolean; + canUpdateTickets: boolean; canWorkOnTickets: boolean; // isSystemAccount: false; } @@ -29,6 +32,7 @@ export interface StaffRoleViolationTicketPermissions { canCreateTickets: boolean; canManageTickets: boolean; canAssignTickets: boolean; + canUpdateTickets: boolean; canWorkOnTickets: boolean; // isSystemAccount: false; } @@ -42,6 +46,7 @@ export interface StaffRolePropertyPermissions { export interface StaffRoleCommunityPermissions { id?: ObjectId; + canManageCommunities: boolean; canManageStaffRolesAndPermissions: boolean; canManageAllCommunities: boolean; canDeleteCommunities: boolean; @@ -49,6 +54,28 @@ export interface StaffRoleCommunityPermissions { canReIndexSearchCollections: boolean; } +export interface StaffRoleFinancePermissions { + id?: ObjectId; + canManageFinance: boolean; + canViewGLBatchSummaries: boolean; + canViewFinanceConfigs: boolean; + canCreateFinanceConfigs: boolean; +} + +export interface StaffRoleTechAdminPermissions { + id?: ObjectId; + canManageTechAdmin: boolean; + canViewDatabaseExplorer: boolean; + canViewBlobExplorer: boolean; + canViewQueueDashboard: boolean; + canSendQueueMessages: boolean; +} + +export interface StaffRoleUserPermissions { + id?: ObjectId; + canManageUsers: boolean; +} + export interface StaffRolePermissions { id?: ObjectId; sectionPermissions: StaffRoleSectionPermissions; @@ -56,6 +83,9 @@ export interface StaffRolePermissions { serviceTicketPermissions: StaffRoleServiceTicketPermissions; violationTicketPermissions: StaffRoleViolationTicketPermissions; communityPermissions: StaffRoleCommunityPermissions; + financePermissions: StaffRoleFinancePermissions; + techAdminPermissions: StaffRoleTechAdminPermissions; + userPermissions: StaffRoleUserPermissions; propertyPermissions: StaffRolePropertyPermissions; } @@ -63,6 +93,7 @@ export interface StaffRole extends Role { permissions: StaffRolePermissions; roleName: string; + enterpriseAppRole?: string; roleType?: string; isDefault: boolean; } @@ -83,15 +114,18 @@ const StaffRoleSchema = new Schema, StaffRole>( canCreateTickets: { type: Boolean, required: true, default: false }, canManageTickets: { type: Boolean, required: true, default: false }, canAssignTickets: { type: Boolean, required: true, default: false }, + canUpdateTickets: { type: Boolean, required: true, default: false }, canWorkOnTickets: { type: Boolean, required: true, default: false, index: true }, } as SchemaDefinition, violationTicketPermissions: { canCreateTickets: { type: Boolean, required: true, default: false }, canManageTickets: { type: Boolean, required: true, default: false }, canAssignTickets: { type: Boolean, required: true, default: false }, + canUpdateTickets: { type: Boolean, required: true, default: false }, canWorkOnTickets: { type: Boolean, required: true, default: false, index: true }, } as SchemaDefinition, communityPermissions: { + canManageCommunities: { type: Boolean, required: true, default: false }, canManageStaffRolesAndPermissions: { type: Boolean, required: true, @@ -114,19 +148,40 @@ const StaffRoleSchema = new Schema, StaffRole>( default: false, }, } as SchemaDefinition, + financePermissions: { + canManageFinance: { type: Boolean, required: true, default: false }, + canViewGLBatchSummaries: { type: Boolean, required: true, default: false }, + canViewFinanceConfigs: { type: Boolean, required: true, default: false }, + canCreateFinanceConfigs: { type: Boolean, required: true, default: false }, + } as SchemaDefinition, + techAdminPermissions: { + canManageTechAdmin: { type: Boolean, required: true, default: false }, + canViewDatabaseExplorer: { type: Boolean, required: true, default: false }, + canViewBlobExplorer: { type: Boolean, required: true, default: false }, + canViewQueueDashboard: { type: Boolean, required: true, default: false }, + canSendQueueMessages: { type: Boolean, required: true, default: false }, + } as SchemaDefinition, + userPermissions: { + canManageUsers: { type: Boolean, required: true, default: false }, + } as SchemaDefinition, propertyPermissions: { - // canManageProperties: { type: Boolean, required: true, default: false }, - // canEditOwnProperty: { type: Boolean, required: true, default: false }, + canManageProperties: { type: Boolean, required: true, default: false }, + canEditOwnProperty: { type: Boolean, required: true, default: false }, } as SchemaDefinition, } as SchemaDefinition, - schemaVersion: { type: String, default: '1.0.0' }, - roleName: { type: String, required: true, maxlength: 50 }, + schemaVersion: { type: String, default: '1.0.0', immutable: true }, + roleName: { type: String, required: true, maxlength: 256 }, + roleType: { type: String, required: true, default: 'staff-user-role' }, + enterpriseAppRole: { + type: String, + required: true, + }, isDefault: { type: Boolean, required: true, default: false }, }, roleOptions, ).index({ roleName: 1 }, { unique: true }); -export const StaffRoleModelName: string = 'staff-roles'; +export const StaffRoleModelName: string = 'staff-user-role'; export const StaffRoleModelFactory = (RoleModel: RoleModelType) => { return RoleModel.discriminator(StaffRoleModelName, StaffRoleSchema); diff --git a/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.ts b/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.ts index 290b4a86a..58c44c20e 100644 --- a/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.ts +++ b/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.ts @@ -68,6 +68,7 @@ export class StaffRolePermissionsAdapter implements Domain.Contexts.User.StaffRo get communityPermissions(): Domain.Contexts.User.StaffRole.StaffRoleCommunityPermissionsProps { if (!this.doc.communityPermissions) { this.doc.communityPermissions = { + canManageCommunities: false, canManageStaffRolesAndPermissions: false, canManageAllCommunities: false, canDeleteCommunities: false, @@ -103,6 +104,7 @@ export class StaffRolePermissionsAdapter implements Domain.Contexts.User.StaffRo canCreateTickets: false, canManageTickets: false, canAssignTickets: false, + canUpdateTickets: false, canWorkOnTickets: false, }; } @@ -115,6 +117,7 @@ export class StaffRolePermissionsAdapter implements Domain.Contexts.User.StaffRo canCreateTickets: false, canManageTickets: false, canAssignTickets: false, + canUpdateTickets: false, canWorkOnTickets: false, }; } diff --git a/packages/ocom/ui-community-route-accounts/src/components/community-list.stories.tsx b/packages/ocom/ui-community-route-accounts/src/components/community-list.stories.tsx index 4930c0c3b..3fc91da04 100644 --- a/packages/ocom/ui-community-route-accounts/src/components/community-list.stories.tsx +++ b/packages/ocom/ui-community-route-accounts/src/components/community-list.stories.tsx @@ -80,6 +80,7 @@ const mockData = { export const Default: Story = { args: { data: mockData, + canCreateCommunity: true, } satisfies CommunityListProps, play: async ({ canvasElement }) => { const canvas = within(canvasElement); From 063dda5196c1f3a697e1fc9a55e9d637c647abfc Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Thu, 7 May 2026 20:19:11 +0530 Subject: [PATCH 51/88] refactor: update community permissions structure and related queries - Changed to in GraphQL queries and components. - Updated permission checks in and to reflect new permission structure. - Renamed to in admin permissions. - Introduced new finance and tech admin permission features with corresponding tests. - Added user permissions management with appropriate validation and tests. - Created Storybook stories for various permission scenarios in . --- .../user/staff-role/create-default-roles.ts | 43 ++-- .../src/models/role/staff-role.model.ts | 15 -- .../staff-role-community-permissions.feature | 16 +- .../staff-role-finance-permissions.feature | 50 ++++ .../features/staff-role-permissions.feature | 16 +- .../staff-role-section-permissions.feature | 65 ----- .../staff-role-tech-admin-permissions.feature | 60 +++++ .../staff-role-user-permissions.feature | 20 ++ .../domain/contexts/user/staff-role/index.ts | 16 +- .../staff-role-community-permissions.test.ts | 45 ++++ .../staff-role-community-permissions.ts | 8 + .../staff-role-finance-permissions.test.ts | 180 ++++++++++++++ .../staff-role-finance-permissions.ts | 61 +++++ .../staff-role/staff-role-permissions.test.ts | 230 ++++++++++-------- .../user/staff-role/staff-role-permissions.ts | 24 +- .../staff-role-section-permissions.test.ts | 224 ----------------- .../staff-role-section-permissions.ts | 61 ----- .../staff-role-tech-admin-permissions.test.ts | 211 ++++++++++++++++ .../staff-role-tech-admin-permissions.ts | 70 ++++++ .../staff-role-user-permissions.test.ts | 87 +++++++ .../staff-role/staff-role-user-permissions.ts | 34 +++ .../src/schema/types/staff-user.graphql | 30 ++- .../staff-role/staff-role.domain-adapter.ts | 161 +++++++++--- .../community-list.container.graphql | 2 +- .../components/community-list.container.tsx | 2 +- .../ui-community-route-admin/src/index.tsx | 2 +- .../src/section-layout.container.tsx | 9 +- .../src/section-layout.graphql | 10 +- .../src/section-layout.stories.tsx | 163 +++++++++++++ .../src/section-layout.tsx | 2 +- 30 files changed, 1383 insertions(+), 534 deletions(-) create mode 100644 packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-finance-permissions.feature delete mode 100644 packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-section-permissions.feature create mode 100644 packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-tech-admin-permissions.feature create mode 100644 packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-user-permissions.feature create mode 100644 packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-finance-permissions.test.ts create mode 100644 packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-finance-permissions.ts delete mode 100644 packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-section-permissions.test.ts delete mode 100644 packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-section-permissions.ts create mode 100644 packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-tech-admin-permissions.test.ts create mode 100644 packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-tech-admin-permissions.ts create mode 100644 packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-user-permissions.test.ts create mode 100644 packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-user-permissions.ts create mode 100644 packages/ocom/ui-community-route-admin/src/section-layout.stories.tsx diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts index a96dd910a..ef5131d33 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts @@ -13,34 +13,44 @@ export type StaffAppRoleName = (typeof StaffAppRoleNames)[keyof typeof StaffAppR interface DefaultRoleSpec { roleName: StaffAppRoleName; isDefault: boolean; - sectionPermissions: { - canManageCommunities: boolean; - canManageUser: boolean; - canManageFinance: boolean; - canManageTechAdmin: boolean; - }; + communityPermissions: { canManageCommunities: boolean }; + financePermissions: { canManageFinance: boolean }; + techAdminPermissions: { canManageTechAdmin: boolean }; + userPermissions: { canManageUsers: boolean }; } const DEFAULT_ROLE_SPECS: DefaultRoleSpec[] = [ { roleName: StaffAppRoleNames.CaseManager, isDefault: false, - sectionPermissions: { canManageCommunities: true, canManageUser: true, canManageFinance: false, canManageTechAdmin: false }, + communityPermissions: { canManageCommunities: true }, + financePermissions: { canManageFinance: false }, + techAdminPermissions: { canManageTechAdmin: false }, + userPermissions: { canManageUsers: true }, }, { roleName: StaffAppRoleNames.ServiceLineOwner, isDefault: false, - sectionPermissions: { canManageCommunities: true, canManageUser: true, canManageFinance: false, canManageTechAdmin: false }, + communityPermissions: { canManageCommunities: true }, + financePermissions: { canManageFinance: false }, + techAdminPermissions: { canManageTechAdmin: false }, + userPermissions: { canManageUsers: true }, }, { roleName: StaffAppRoleNames.Finance, isDefault: false, - sectionPermissions: { canManageCommunities: false, canManageUser: false, canManageFinance: true, canManageTechAdmin: false }, + communityPermissions: { canManageCommunities: false }, + financePermissions: { canManageFinance: true }, + techAdminPermissions: { canManageTechAdmin: false }, + userPermissions: { canManageUsers: false }, }, { roleName: StaffAppRoleNames.TechAdmin, isDefault: false, - sectionPermissions: { canManageCommunities: false, canManageUser: false, canManageFinance: false, canManageTechAdmin: true }, + communityPermissions: { canManageCommunities: false }, + financePermissions: { canManageFinance: false }, + techAdminPermissions: { canManageTechAdmin: true }, + userPermissions: { canManageUsers: false }, }, ]; @@ -56,12 +66,11 @@ const roleExists = async (repository: Domain.Contexts.User.StaffRole.StaffRoleRe } }; -const applySectionPermissions = (staffRole: Domain.Contexts.User.StaffRole.StaffRole, sectionPerms: DefaultRoleSpec['sectionPermissions']): void => { - const { sectionPermissions } = staffRole.permissions; - sectionPermissions.canManageCommunities = sectionPerms.canManageCommunities; - sectionPermissions.canManageUser = sectionPerms.canManageUser; - sectionPermissions.canManageFinance = sectionPerms.canManageFinance; - sectionPermissions.canManageTechAdmin = sectionPerms.canManageTechAdmin; +const applyDefaultPermissions = (staffRole: Domain.Contexts.User.StaffRole.StaffRole, spec: DefaultRoleSpec): void => { + staffRole.permissions.communityPermissions.canManageCommunities = spec.communityPermissions.canManageCommunities; + staffRole.permissions.financePermissions.canManageFinance = spec.financePermissions.canManageFinance; + staffRole.permissions.techAdminPermissions.canManageTechAdmin = spec.techAdminPermissions.canManageTechAdmin; + staffRole.permissions.userPermissions.canManageUsers = spec.userPermissions.canManageUsers; }; export const createDefaultRoles = (dataSources: DataSources) => { @@ -77,7 +86,7 @@ export const createDefaultRoles = (dataSources: DataSources) => { const staffRole = await repository.getNewInstance(spec.roleName); staffRole.isDefault = spec.isDefault; - applySectionPermissions(staffRole, spec.sectionPermissions); + applyDefaultPermissions(staffRole, spec); const saved = await repository.save(staffRole); created.push(saved); diff --git a/packages/ocom/data-sources-mongoose-models/src/models/role/staff-role.model.ts b/packages/ocom/data-sources-mongoose-models/src/models/role/staff-role.model.ts index f66cf5bbc..656767713 100644 --- a/packages/ocom/data-sources-mongoose-models/src/models/role/staff-role.model.ts +++ b/packages/ocom/data-sources-mongoose-models/src/models/role/staff-role.model.ts @@ -3,14 +3,6 @@ import { type Role, type RoleModelType, roleOptions } from './role.model.ts'; export const StaffEnterpriseAppRoles = ['Staff.CaseManager', 'Staff.Finance', 'Staff.ServiceLineOwner', 'Staff.TechAdmin'] as const; -export interface StaffRoleSectionPermissions { - id?: ObjectId; - canManageCommunities: boolean; - canManageUser: boolean; - canManageFinance: boolean; - canManageTechAdmin: boolean; -} - export interface StaffRoleServicePermissions { id?: ObjectId; canManageServices: boolean; @@ -78,7 +70,6 @@ export interface StaffRoleUserPermissions { export interface StaffRolePermissions { id?: ObjectId; - sectionPermissions: StaffRoleSectionPermissions; servicePermissions: StaffRoleServicePermissions; serviceTicketPermissions: StaffRoleServiceTicketPermissions; violationTicketPermissions: StaffRoleViolationTicketPermissions; @@ -101,12 +92,6 @@ export interface StaffRole extends Role { const StaffRoleSchema = new Schema, StaffRole>( { permissions: { - sectionPermissions: { - canManageCommunities: { type: Boolean, required: true, default: false }, - canManageUser: { type: Boolean, required: true, default: false }, - canManageFinance: { type: Boolean, required: true, default: false }, - canManageTechAdmin: { type: Boolean, required: true, default: false }, - } as SchemaDefinition, servicePermissions: { canManageServices: { type: Boolean, required: true, default: false }, } as SchemaDefinition, diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-community-permissions.feature b/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-community-permissions.feature index 547bbc02c..ba7c3c123 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-community-permissions.feature +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-community-permissions.feature @@ -77,4 +77,18 @@ Feature: StaffRoleCommunityPermissions Scenario: Changing canReIndexSearchCollections without permission Given a StaffRoleCommunityPermissions entity without permission to manage staff roles or system account When I try to set canReIndexSearchCollections to true - Then a PermissionError should be thrown \ No newline at end of file + Then a PermissionError should be thrown + Scenario: Changing canManageCommunities with manage staff roles permission + Given a StaffRoleCommunityPermissions entity with permission to manage staff roles + When I set canManageCommunities to true + Then the property should be updated to true + + Scenario: Changing canManageCommunities with system account permission + Given a StaffRoleCommunityPermissions entity with system account permission + When I set canManageCommunities to true + Then the property should be updated to true + + Scenario: Changing canManageCommunities without permission + Given a StaffRoleCommunityPermissions entity without permission to manage staff roles or system account + When I try to set canManageCommunities to true + Then a PermissionError should be thrown diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-finance-permissions.feature b/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-finance-permissions.feature new file mode 100644 index 000000000..1d1b1f4dc --- /dev/null +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-finance-permissions.feature @@ -0,0 +1,50 @@ +Feature: StaffRoleFinancePermissions + + Background: + Given valid StaffRoleFinancePermissionsProps with all permission flags set to false + And a valid UserVisa + + Scenario: Changing canManageFinance with manage staff roles permission + Given a StaffRoleFinancePermissions entity with permission to manage staff roles + When I set canManageFinance to true + Then the property should be updated to true + + Scenario: Changing canManageFinance with system account permission + Given a StaffRoleFinancePermissions entity with system account permission + When I set canManageFinance to true + Then the property should be updated to true + + Scenario: Changing canManageFinance without permission + Given a StaffRoleFinancePermissions entity without permission to manage staff roles or system account + When I try to set canManageFinance to true + Then a PermissionError should be thrown + + Scenario: Changing canViewGLBatchSummaries with manage staff roles permission + Given a StaffRoleFinancePermissions entity with permission to manage staff roles + When I set canViewGLBatchSummaries to true + Then the property should be updated to true + + Scenario: Changing canViewGLBatchSummaries without permission + Given a StaffRoleFinancePermissions entity without permission to manage staff roles or system account + When I try to set canViewGLBatchSummaries to true + Then a PermissionError should be thrown + + Scenario: Changing canViewFinanceConfigs with manage staff roles permission + Given a StaffRoleFinancePermissions entity with permission to manage staff roles + When I set canViewFinanceConfigs to true + Then the property should be updated to true + + Scenario: Changing canViewFinanceConfigs without permission + Given a StaffRoleFinancePermissions entity without permission to manage staff roles or system account + When I try to set canViewFinanceConfigs to true + Then a PermissionError should be thrown + + Scenario: Changing canCreateFinanceConfigs with manage staff roles permission + Given a StaffRoleFinancePermissions entity with permission to manage staff roles + When I set canCreateFinanceConfigs to true + Then the property should be updated to true + + Scenario: Changing canCreateFinanceConfigs without permission + Given a StaffRoleFinancePermissions entity without permission to manage staff roles or system account + When I try to set canCreateFinanceConfigs to true + Then a PermissionError should be thrown diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-permissions.feature b/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-permissions.feature index ddbf5d7ee..901786338 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-permissions.feature +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-permissions.feature @@ -29,7 +29,17 @@ Feature: StaffRolePermissions When I access the violationTicketPermissions property Then I should receive a StaffRoleViolationTicketPermissions entity instance - Scenario: Accessing sectionPermissions + Scenario: Accessing financePermissions Given a StaffRolePermissions entity - When I access the sectionPermissions property - Then I should receive a StaffRoleSectionPermissions entity instance \ No newline at end of file + When I access the financePermissions property + Then I should receive a StaffRoleFinancePermissions entity instance + + Scenario: Accessing techAdminPermissions + Given a StaffRolePermissions entity + When I access the techAdminPermissions property + Then I should receive a StaffRoleTechAdminPermissions entity instance + + Scenario: Accessing userPermissions + Given a StaffRolePermissions entity + When I access the userPermissions property + Then I should receive a StaffRoleUserPermissions entity instance diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-section-permissions.feature b/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-section-permissions.feature deleted file mode 100644 index 08dc1fb43..000000000 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-section-permissions.feature +++ /dev/null @@ -1,65 +0,0 @@ -Feature: StaffRoleSectionPermissions - - Background: - Given valid StaffRoleSectionPermissionsProps with all permission flags set to false - And a valid UserVisa - - Scenario: Changing canManageCommunities with manage staff roles permission - Given a StaffRoleSectionPermissions entity with permission to manage staff roles - When I set canManageCommunities to true - Then the property should be updated to true - - Scenario: Changing canManageCommunities with system account permission - Given a StaffRoleSectionPermissions entity with system account permission - When I set canManageCommunities to true - Then the property should be updated to true - - Scenario: Changing canManageCommunities without permission - Given a StaffRoleSectionPermissions entity without permission to manage staff roles or system account - When I try to set canManageCommunities to true - Then a PermissionError should be thrown - - Scenario: Changing canManageUser with manage staff roles permission - Given a StaffRoleSectionPermissions entity with permission to manage staff roles - When I set canManageUser to true - Then the property should be updated to true - - Scenario: Changing canManageUser with system account permission - Given a StaffRoleSectionPermissions entity with system account permission - When I set canManageUser to true - Then the property should be updated to true - - Scenario: Changing canManageUser without permission - Given a StaffRoleSectionPermissions entity without permission to manage staff roles or system account - When I try to set canManageUser to true - Then a PermissionError should be thrown - - Scenario: Changing canManageFinance with manage staff roles permission - Given a StaffRoleSectionPermissions entity with permission to manage staff roles - When I set canManageFinance to true - Then the property should be updated to true - - Scenario: Changing canManageFinance with system account permission - Given a StaffRoleSectionPermissions entity with system account permission - When I set canManageFinance to true - Then the property should be updated to true - - Scenario: Changing canManageFinance without permission - Given a StaffRoleSectionPermissions entity without permission to manage staff roles or system account - When I try to set canManageFinance to true - Then a PermissionError should be thrown - - Scenario: Changing canManageTechAdmin with manage staff roles permission - Given a StaffRoleSectionPermissions entity with permission to manage staff roles - When I set canManageTechAdmin to true - Then the property should be updated to true - - Scenario: Changing canManageTechAdmin with system account permission - Given a StaffRoleSectionPermissions entity with system account permission - When I set canManageTechAdmin to true - Then the property should be updated to true - - Scenario: Changing canManageTechAdmin without permission - Given a StaffRoleSectionPermissions entity without permission to manage staff roles or system account - When I try to set canManageTechAdmin to true - Then a PermissionError should be thrown diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-tech-admin-permissions.feature b/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-tech-admin-permissions.feature new file mode 100644 index 000000000..514dc404d --- /dev/null +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-tech-admin-permissions.feature @@ -0,0 +1,60 @@ +Feature: StaffRoleTechAdminPermissions + + Background: + Given valid StaffRoleTechAdminPermissionsProps with all permission flags set to false + And a valid UserVisa + + Scenario: Changing canManageTechAdmin with manage staff roles permission + Given a StaffRoleTechAdminPermissions entity with permission to manage staff roles + When I set canManageTechAdmin to true + Then the property should be updated to true + + Scenario: Changing canManageTechAdmin with system account permission + Given a StaffRoleTechAdminPermissions entity with system account permission + When I set canManageTechAdmin to true + Then the property should be updated to true + + Scenario: Changing canManageTechAdmin without permission + Given a StaffRoleTechAdminPermissions entity without permission to manage staff roles or system account + When I try to set canManageTechAdmin to true + Then a PermissionError should be thrown + + Scenario: Changing canViewDatabaseExplorer with manage staff roles permission + Given a StaffRoleTechAdminPermissions entity with permission to manage staff roles + When I set canViewDatabaseExplorer to true + Then the property should be updated to true + + Scenario: Changing canViewDatabaseExplorer without permission + Given a StaffRoleTechAdminPermissions entity without permission to manage staff roles or system account + When I try to set canViewDatabaseExplorer to true + Then a PermissionError should be thrown + + Scenario: Changing canViewBlobExplorer with manage staff roles permission + Given a StaffRoleTechAdminPermissions entity with permission to manage staff roles + When I set canViewBlobExplorer to true + Then the property should be updated to true + + Scenario: Changing canViewBlobExplorer without permission + Given a StaffRoleTechAdminPermissions entity without permission to manage staff roles or system account + When I try to set canViewBlobExplorer to true + Then a PermissionError should be thrown + + Scenario: Changing canViewQueueDashboard with manage staff roles permission + Given a StaffRoleTechAdminPermissions entity with permission to manage staff roles + When I set canViewQueueDashboard to true + Then the property should be updated to true + + Scenario: Changing canViewQueueDashboard without permission + Given a StaffRoleTechAdminPermissions entity without permission to manage staff roles or system account + When I try to set canViewQueueDashboard to true + Then a PermissionError should be thrown + + Scenario: Changing canSendQueueMessages with manage staff roles permission + Given a StaffRoleTechAdminPermissions entity with permission to manage staff roles + When I set canSendQueueMessages to true + Then the property should be updated to true + + Scenario: Changing canSendQueueMessages without permission + Given a StaffRoleTechAdminPermissions entity without permission to manage staff roles or system account + When I try to set canSendQueueMessages to true + Then a PermissionError should be thrown diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-user-permissions.feature b/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-user-permissions.feature new file mode 100644 index 000000000..21cd6b942 --- /dev/null +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role-user-permissions.feature @@ -0,0 +1,20 @@ +Feature: StaffRoleUserPermissions + + Background: + Given valid StaffRoleUserPermissionsProps with all permission flags set to false + And a valid UserVisa + + Scenario: Changing canManageUsers with manage staff roles permission + Given a StaffRoleUserPermissions entity with permission to manage staff roles + When I set canManageUsers to true + Then the property should be updated to true + + Scenario: Changing canManageUsers with system account permission + Given a StaffRoleUserPermissions entity with system account permission + When I set canManageUsers to true + Then the property should be updated to true + + Scenario: Changing canManageUsers without permission + Given a StaffRoleUserPermissions entity without permission to manage staff roles or system account + When I try to set canManageUsers to true + Then a PermissionError should be thrown diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/index.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/index.ts index 585643108..c049103f8 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/index.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/index.ts @@ -9,6 +9,10 @@ export type { StaffRoleCommunityPermissionsEntityReference, StaffRoleCommunityPermissionsProps, } from './staff-role-community-permissions.ts'; +export type { + StaffRoleFinancePermissionsEntityReference, + StaffRoleFinancePermissionsProps, +} from './staff-role-finance-permissions.ts'; export type { StaffRolePermissionsEntityReference, StaffRolePermissionsProps, @@ -17,10 +21,6 @@ export type { StaffRolePropertyPermissionsEntityReference, StaffRolePropertyPermissionsProps, } from './staff-role-property-permissions.ts'; -export type { - StaffRoleSectionPermissionsEntityReference, - StaffRoleSectionPermissionsProps, -} from './staff-role-section-permissions.ts'; export type { StaffRoleServicePermissionsEntityReference, StaffRoleServicePermissionsProps, @@ -29,6 +29,14 @@ export type { StaffRoleServiceTicketPermissionsEntityReference, StaffRoleServiceTicketPermissionsProps, } from './staff-role-service-ticket-permissions.ts'; +export type { + StaffRoleTechAdminPermissionsEntityReference, + StaffRoleTechAdminPermissionsProps, +} from './staff-role-tech-admin-permissions.ts'; +export type { + StaffRoleUserPermissionsEntityReference, + StaffRoleUserPermissionsProps, +} from './staff-role-user-permissions.ts'; export type { StaffRoleViolationTicketPermissionsEntityReference, StaffRoleViolationTicketPermissionsProps, diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-community-permissions.test.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-community-permissions.test.ts index dae792d73..0d3d58952 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-community-permissions.test.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-community-permissions.test.ts @@ -18,6 +18,7 @@ function makeVisa({ canManageStaffRolesAndPermissions = true, isSystemAccount = function makeProps(overrides = {}) { return { + canManageCommunities: false, canManageStaffRolesAndPermissions: false, canManageAllCommunities: false, canDeleteCommunities: false, @@ -311,4 +312,48 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { expect(setWithoutPermission).toThrow('Cannot set permission'); }); }); + + // canManageCommunities + Scenario('Changing canManageCommunities with manage staff roles permission', ({ Given, When, Then }) => { + Given('a StaffRoleCommunityPermissions entity with permission to manage staff roles', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: true, isSystemAccount: false }); + entity = new StaffRoleCommunityPermissions(makeProps(), visa); + }); + When('I set canManageCommunities to true', () => { + entity.canManageCommunities = true; + }); + Then('the property should be updated to true', () => { + expect(entity.canManageCommunities).toBe(true); + }); + }); + + Scenario('Changing canManageCommunities with system account permission', ({ Given, When, Then }) => { + Given('a StaffRoleCommunityPermissions entity with system account permission', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: true }); + entity = new StaffRoleCommunityPermissions(makeProps(), visa); + }); + When('I set canManageCommunities to true', () => { + entity.canManageCommunities = true; + }); + Then('the property should be updated to true', () => { + expect(entity.canManageCommunities).toBe(true); + }); + }); + + Scenario('Changing canManageCommunities without permission', ({ Given, When, Then }) => { + let setWithoutPermission: () => void; + Given('a StaffRoleCommunityPermissions entity without permission to manage staff roles or system account', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: false }); + entity = new StaffRoleCommunityPermissions(makeProps(), visa); + }); + When('I try to set canManageCommunities to true', () => { + setWithoutPermission = () => { + entity.canManageCommunities = true; + }; + }); + Then('a PermissionError should be thrown', () => { + expect(setWithoutPermission).toThrow(PermissionError); + expect(setWithoutPermission).toThrow('Cannot set permission'); + }); + }); }); diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-community-permissions.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-community-permissions.ts index c8887d0fc..fbc58c0dc 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-community-permissions.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-community-permissions.ts @@ -4,6 +4,7 @@ import type { ValueObjectProps } from '@cellix/domain-seedwork/value-object'; import type { UserVisa } from '../user.visa.ts'; interface StaffRoleCommunityPermissionsSpec { + canManageCommunities: boolean; canManageStaffRolesAndPermissions: boolean; canManageAllCommunities: boolean; canDeleteCommunities: boolean; @@ -28,6 +29,13 @@ export class StaffRoleCommunityPermissions extends ValueObject fn({ canManageStaffRolesAndPermissions, isSystemAccount })), + }); +} + +function makeProps(overrides = {}) { + return { + canManageFinance: false, + canViewGLBatchSummaries: false, + canViewFinanceConfigs: false, + canCreateFinanceConfigs: false, + ...overrides, + }; +} + +test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { + let visa: ReturnType; + let props: ReturnType; + let entity: StaffRoleFinancePermissions; + + BeforeEachScenario(() => { + visa = makeVisa(); + props = makeProps(); + entity = new StaffRoleFinancePermissions(props, visa); + }); + + Background(({ Given, And }) => { + Given('valid StaffRoleFinancePermissionsProps with all permission flags set to false', () => { + props = makeProps(); + }); + And('a valid UserVisa', () => { + visa = makeVisa(); + }); + }); + + Scenario('Changing canManageFinance with manage staff roles permission', ({ Given, When, Then }) => { + Given('a StaffRoleFinancePermissions entity with permission to manage staff roles', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: true, isSystemAccount: false }); + entity = new StaffRoleFinancePermissions(makeProps(), visa); + }); + When('I set canManageFinance to true', () => { + entity.canManageFinance = true; + }); + Then('the property should be updated to true', () => { + expect(entity.canManageFinance).toBe(true); + }); + }); + + Scenario('Changing canManageFinance with system account permission', ({ Given, When, Then }) => { + Given('a StaffRoleFinancePermissions entity with system account permission', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: true }); + entity = new StaffRoleFinancePermissions(makeProps(), visa); + }); + When('I set canManageFinance to true', () => { + entity.canManageFinance = true; + }); + Then('the property should be updated to true', () => { + expect(entity.canManageFinance).toBe(true); + }); + }); + + Scenario('Changing canManageFinance without permission', ({ Given, When, Then }) => { + let setWithoutPermission: () => void; + Given('a StaffRoleFinancePermissions entity without permission to manage staff roles or system account', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: false }); + entity = new StaffRoleFinancePermissions(makeProps(), visa); + }); + When('I try to set canManageFinance to true', () => { + setWithoutPermission = () => { + entity.canManageFinance = true; + }; + }); + Then('a PermissionError should be thrown', () => { + expect(setWithoutPermission).toThrow(PermissionError); + expect(setWithoutPermission).toThrow('Cannot set permission'); + }); + }); + + Scenario('Changing canViewGLBatchSummaries with manage staff roles permission', ({ Given, When, Then }) => { + Given('a StaffRoleFinancePermissions entity with permission to manage staff roles', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: true, isSystemAccount: false }); + entity = new StaffRoleFinancePermissions(makeProps(), visa); + }); + When('I set canViewGLBatchSummaries to true', () => { + entity.canViewGLBatchSummaries = true; + }); + Then('the property should be updated to true', () => { + expect(entity.canViewGLBatchSummaries).toBe(true); + }); + }); + + Scenario('Changing canViewGLBatchSummaries without permission', ({ Given, When, Then }) => { + let setWithoutPermission: () => void; + Given('a StaffRoleFinancePermissions entity without permission to manage staff roles or system account', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: false }); + entity = new StaffRoleFinancePermissions(makeProps(), visa); + }); + When('I try to set canViewGLBatchSummaries to true', () => { + setWithoutPermission = () => { + entity.canViewGLBatchSummaries = true; + }; + }); + Then('a PermissionError should be thrown', () => { + expect(setWithoutPermission).toThrow(PermissionError); + expect(setWithoutPermission).toThrow('Cannot set permission'); + }); + }); + + Scenario('Changing canViewFinanceConfigs with manage staff roles permission', ({ Given, When, Then }) => { + Given('a StaffRoleFinancePermissions entity with permission to manage staff roles', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: true, isSystemAccount: false }); + entity = new StaffRoleFinancePermissions(makeProps(), visa); + }); + When('I set canViewFinanceConfigs to true', () => { + entity.canViewFinanceConfigs = true; + }); + Then('the property should be updated to true', () => { + expect(entity.canViewFinanceConfigs).toBe(true); + }); + }); + + Scenario('Changing canViewFinanceConfigs without permission', ({ Given, When, Then }) => { + let setWithoutPermission: () => void; + Given('a StaffRoleFinancePermissions entity without permission to manage staff roles or system account', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: false }); + entity = new StaffRoleFinancePermissions(makeProps(), visa); + }); + When('I try to set canViewFinanceConfigs to true', () => { + setWithoutPermission = () => { + entity.canViewFinanceConfigs = true; + }; + }); + Then('a PermissionError should be thrown', () => { + expect(setWithoutPermission).toThrow(PermissionError); + expect(setWithoutPermission).toThrow('Cannot set permission'); + }); + }); + + Scenario('Changing canCreateFinanceConfigs with manage staff roles permission', ({ Given, When, Then }) => { + Given('a StaffRoleFinancePermissions entity with permission to manage staff roles', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: true, isSystemAccount: false }); + entity = new StaffRoleFinancePermissions(makeProps(), visa); + }); + When('I set canCreateFinanceConfigs to true', () => { + entity.canCreateFinanceConfigs = true; + }); + Then('the property should be updated to true', () => { + expect(entity.canCreateFinanceConfigs).toBe(true); + }); + }); + + Scenario('Changing canCreateFinanceConfigs without permission', ({ Given, When, Then }) => { + let setWithoutPermission: () => void; + Given('a StaffRoleFinancePermissions entity without permission to manage staff roles or system account', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: false }); + entity = new StaffRoleFinancePermissions(makeProps(), visa); + }); + When('I try to set canCreateFinanceConfigs to true', () => { + setWithoutPermission = () => { + entity.canCreateFinanceConfigs = true; + }; + }); + Then('a PermissionError should be thrown', () => { + expect(setWithoutPermission).toThrow(PermissionError); + expect(setWithoutPermission).toThrow('Cannot set permission'); + }); + }); +}); diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-finance-permissions.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-finance-permissions.ts new file mode 100644 index 000000000..e07d6be7d --- /dev/null +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-finance-permissions.ts @@ -0,0 +1,61 @@ +import { PermissionError } from '@cellix/domain-seedwork/domain-entity'; +import type { ValueObjectProps } from '@cellix/domain-seedwork/value-object'; +import { ValueObject } from '@cellix/domain-seedwork/value-object'; +import type { UserVisa } from '../user.visa.ts'; + +interface StaffRoleFinancePermissionsSpec { + canManageFinance: boolean; + canViewGLBatchSummaries: boolean; + canViewFinanceConfigs: boolean; + canCreateFinanceConfigs: boolean; +} + +export interface StaffRoleFinancePermissionsProps extends StaffRoleFinancePermissionsSpec, ValueObjectProps {} +export interface StaffRoleFinancePermissionsEntityReference extends Readonly {} + +export class StaffRoleFinancePermissions extends ValueObject implements StaffRoleFinancePermissionsEntityReference { + private readonly visa: UserVisa; + + constructor(props: StaffRoleFinancePermissionsProps, visa: UserVisa) { + super(props); + this.visa = visa; + } + + private validateVisa() { + if (!this.visa.determineIf((permissions) => permissions.canManageStaffRolesAndPermissions || permissions.isSystemAccount)) { + throw new PermissionError('Cannot set permission'); + } + } + + get canManageFinance(): boolean { + return this.props.canManageFinance; + } + set canManageFinance(value: boolean) { + this.validateVisa(); + this.props.canManageFinance = value; + } + + get canViewGLBatchSummaries(): boolean { + return this.props.canViewGLBatchSummaries; + } + set canViewGLBatchSummaries(value: boolean) { + this.validateVisa(); + this.props.canViewGLBatchSummaries = value; + } + + get canViewFinanceConfigs(): boolean { + return this.props.canViewFinanceConfigs; + } + set canViewFinanceConfigs(value: boolean) { + this.validateVisa(); + this.props.canViewFinanceConfigs = value; + } + + get canCreateFinanceConfigs(): boolean { + return this.props.canCreateFinanceConfigs; + } + set canCreateFinanceConfigs(value: boolean) { + this.validateVisa(); + this.props.canCreateFinanceConfigs = value; + } +} diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-permissions.test.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-permissions.test.ts index bc4b652c2..d3af6b628 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-permissions.test.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-permissions.test.ts @@ -3,11 +3,13 @@ import { fileURLToPath } from 'node:url'; import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; import { expect, vi } from 'vitest'; import { StaffRoleCommunityPermissions } from './staff-role-community-permissions.ts'; +import { StaffRoleFinancePermissions } from './staff-role-finance-permissions.ts'; import { StaffRolePermissions } from './staff-role-permissions.ts'; import { StaffRolePropertyPermissions } from './staff-role-property-permissions.ts'; -import { StaffRoleSectionPermissions } from './staff-role-section-permissions.ts'; import { StaffRoleServicePermissions } from './staff-role-service-permissions.ts'; import { StaffRoleServiceTicketPermissions } from './staff-role-service-ticket-permissions.ts'; +import { StaffRoleTechAdminPermissions } from './staff-role-tech-admin-permissions.ts'; +import { StaffRoleUserPermissions } from './staff-role-user-permissions.ts'; import { StaffRoleViolationTicketPermissions } from './staff-role-violation-ticket-permissions.ts'; const test = { for: describeFeature }; @@ -15,117 +17,145 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url)); const feature = await loadFeature(path.resolve(__dirname, 'features/staff-role-permissions.feature')); function makeVisa() { - return vi.mocked({ - determineIf: vi.fn(() => true), - }); +return vi.mocked({ +determineIf: vi.fn(() => true), +}); } function makeProps() { - return { - communityPermissions: {} as StaffRoleCommunityPermissions, - propertyPermissions: {} as StaffRolePropertyPermissions, - serviceTicketPermissions: {} as StaffRoleServiceTicketPermissions, - servicePermissions: {} as StaffRoleServicePermissions, - violationTicketPermissions: {} as StaffRoleViolationTicketPermissions, - sectionPermissions: {} as StaffRoleSectionPermissions, - }; +return { +communityPermissions: {} as StaffRoleCommunityPermissions, +propertyPermissions: {} as StaffRolePropertyPermissions, +serviceTicketPermissions: {} as StaffRoleServiceTicketPermissions, +servicePermissions: {} as StaffRoleServicePermissions, +violationTicketPermissions: {} as StaffRoleViolationTicketPermissions, +financePermissions: {} as StaffRoleFinancePermissions, +techAdminPermissions: {} as StaffRoleTechAdminPermissions, +userPermissions: {} as StaffRoleUserPermissions, +}; } test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { - let visa: ReturnType; - let props: ReturnType; - let entity: StaffRolePermissions; +let visa: ReturnType; +let props: ReturnType; +let entity: StaffRolePermissions; - BeforeEachScenario(() => { - visa = makeVisa(); - props = makeProps(); - entity = new StaffRolePermissions(props, visa); - }); +BeforeEachScenario(() => { +visa = makeVisa(); +props = makeProps(); +entity = new StaffRolePermissions(props, visa); +}); - Background(({ Given, And }) => { - Given('valid StaffRolePermissionsProps with all required permission props', () => { - props = makeProps(); - }); - And('a valid UserVisa', () => { - visa = makeVisa(); - }); - }); +Background(({ Given, And }) => { +Given('valid StaffRolePermissionsProps with all required permission props', () => { +props = makeProps(); +}); +And('a valid UserVisa', () => { +visa = makeVisa(); +}); +}); - Scenario('Accessing communityPermissions', ({ Given, When, Then }) => { - let communityPermissions: StaffRoleCommunityPermissions; - Given('a StaffRolePermissions entity', () => { - entity = new StaffRolePermissions(props, visa); - }); - When('I access the communityPermissions property', () => { - communityPermissions = entity.communityPermissions; - }); - Then('I should receive a StaffRoleCommunityPermissions entity instance', () => { - expect(communityPermissions).toBeInstanceOf(StaffRoleCommunityPermissions); - }); - }); +Scenario('Accessing communityPermissions', ({ Given, When, Then }) => { +let communityPermissions: StaffRoleCommunityPermissions; +Given('a StaffRolePermissions entity', () => { +entity = new StaffRolePermissions(props, visa); +}); +When('I access the communityPermissions property', () => { +communityPermissions = entity.communityPermissions; +}); +Then('I should receive a StaffRoleCommunityPermissions entity instance', () => { +expect(communityPermissions).toBeInstanceOf(StaffRoleCommunityPermissions); +}); +}); - Scenario('Accessing propertyPermissions', ({ Given, When, Then }) => { - let propertyPermissions: StaffRolePropertyPermissions; - Given('a StaffRolePermissions entity', () => { - entity = new StaffRolePermissions(props, visa); - }); - When('I access the propertyPermissions property', () => { - propertyPermissions = entity.propertyPermissions; - }); - Then('I should receive a StaffRolePropertyPermissions entity instance', () => { - expect(propertyPermissions).toBeInstanceOf(StaffRolePropertyPermissions); - }); - }); +Scenario('Accessing propertyPermissions', ({ Given, When, Then }) => { +let propertyPermissions: StaffRolePropertyPermissions; +Given('a StaffRolePermissions entity', () => { +entity = new StaffRolePermissions(props, visa); +}); +When('I access the propertyPermissions property', () => { +propertyPermissions = entity.propertyPermissions; +}); +Then('I should receive a StaffRolePropertyPermissions entity instance', () => { +expect(propertyPermissions).toBeInstanceOf(StaffRolePropertyPermissions); +}); +}); - Scenario('Accessing serviceTicketPermissions', ({ Given, When, Then }) => { - let serviceTicketPermissions: StaffRoleServiceTicketPermissions; - Given('a StaffRolePermissions entity', () => { - entity = new StaffRolePermissions(props, visa); - }); - When('I access the serviceTicketPermissions property', () => { - serviceTicketPermissions = entity.serviceTicketPermissions; - }); - Then('I should receive a StaffRoleServiceTicketPermissions entity instance', () => { - expect(serviceTicketPermissions).toBeInstanceOf(StaffRoleServiceTicketPermissions); - }); - }); +Scenario('Accessing serviceTicketPermissions', ({ Given, When, Then }) => { +let serviceTicketPermissions: StaffRoleServiceTicketPermissions; +Given('a StaffRolePermissions entity', () => { +entity = new StaffRolePermissions(props, visa); +}); +When('I access the serviceTicketPermissions property', () => { +serviceTicketPermissions = entity.serviceTicketPermissions; +}); +Then('I should receive a StaffRoleServiceTicketPermissions entity instance', () => { +expect(serviceTicketPermissions).toBeInstanceOf(StaffRoleServiceTicketPermissions); +}); +}); - Scenario('Accessing servicePermissions', ({ Given, When, Then }) => { - let servicePermissions: StaffRoleServicePermissions; - Given('a StaffRolePermissions entity', () => { - entity = new StaffRolePermissions(props, visa); - }); - When('I access the servicePermissions property', () => { - servicePermissions = entity.servicePermissions; - }); - Then('I should receive a StaffRoleServicePermissions entity instance', () => { - expect(servicePermissions).toBeInstanceOf(StaffRoleServicePermissions); - }); - }); +Scenario('Accessing servicePermissions', ({ Given, When, Then }) => { +let servicePermissions: StaffRoleServicePermissions; +Given('a StaffRolePermissions entity', () => { +entity = new StaffRolePermissions(props, visa); +}); +When('I access the servicePermissions property', () => { +servicePermissions = entity.servicePermissions; +}); +Then('I should receive a StaffRoleServicePermissions entity instance', () => { +expect(servicePermissions).toBeInstanceOf(StaffRoleServicePermissions); +}); +}); + +Scenario('Accessing violationTicketPermissions', ({ Given, When, Then }) => { +let violationTicketPermissions: StaffRoleViolationTicketPermissions; +Given('a StaffRolePermissions entity', () => { +entity = new StaffRolePermissions(props, visa); +}); +When('I access the violationTicketPermissions property', () => { +violationTicketPermissions = entity.violationTicketPermissions; +}); +Then('I should receive a StaffRoleViolationTicketPermissions entity instance', () => { +expect(violationTicketPermissions).toBeInstanceOf(StaffRoleViolationTicketPermissions); +}); +}); - Scenario('Accessing violationTicketPermissions', ({ Given, When, Then }) => { - let violationTicketPermissions: StaffRoleViolationTicketPermissions; - Given('a StaffRolePermissions entity', () => { - entity = new StaffRolePermissions(props, visa); - }); - When('I access the violationTicketPermissions property', () => { - violationTicketPermissions = entity.violationTicketPermissions; - }); - Then('I should receive a StaffRoleViolationTicketPermissions entity instance', () => { - expect(violationTicketPermissions).toBeInstanceOf(StaffRoleViolationTicketPermissions); - }); - }); +Scenario('Accessing financePermissions', ({ Given, When, Then }) => { +let financePermissions: StaffRoleFinancePermissions; +Given('a StaffRolePermissions entity', () => { +entity = new StaffRolePermissions(props, visa); +}); +When('I access the financePermissions property', () => { +financePermissions = entity.financePermissions; +}); +Then('I should receive a StaffRoleFinancePermissions entity instance', () => { +expect(financePermissions).toBeInstanceOf(StaffRoleFinancePermissions); +}); +}); - Scenario('Accessing sectionPermissions', ({ Given, When, Then }) => { - let sectionPermissions: StaffRoleSectionPermissions; - Given('a StaffRolePermissions entity', () => { - entity = new StaffRolePermissions(props, visa); - }); - When('I access the sectionPermissions property', () => { - sectionPermissions = entity.sectionPermissions; - }); - Then('I should receive a StaffRoleSectionPermissions entity instance', () => { - expect(sectionPermissions).toBeInstanceOf(StaffRoleSectionPermissions); - }); - }); +Scenario('Accessing techAdminPermissions', ({ Given, When, Then }) => { +let techAdminPermissions: StaffRoleTechAdminPermissions; +Given('a StaffRolePermissions entity', () => { +entity = new StaffRolePermissions(props, visa); +}); +When('I access the techAdminPermissions property', () => { +techAdminPermissions = entity.techAdminPermissions; +}); +Then('I should receive a StaffRoleTechAdminPermissions entity instance', () => { +expect(techAdminPermissions).toBeInstanceOf(StaffRoleTechAdminPermissions); +}); +}); + +Scenario('Accessing userPermissions', ({ Given, When, Then }) => { +let userPermissions: StaffRoleUserPermissions; +Given('a StaffRolePermissions entity', () => { +entity = new StaffRolePermissions(props, visa); +}); +When('I access the userPermissions property', () => { +userPermissions = entity.userPermissions; +}); +Then('I should receive a StaffRoleUserPermissions entity instance', () => { +expect(userPermissions).toBeInstanceOf(StaffRoleUserPermissions); +}); +}); }); diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-permissions.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-permissions.ts index bee2a83cd..3cbb36ab1 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-permissions.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-permissions.ts @@ -2,10 +2,12 @@ import type { ValueObjectProps } from '@cellix/domain-seedwork/value-object'; import { ValueObject } from '@cellix/domain-seedwork/value-object'; import type { UserVisa } from '../user.visa.ts'; import { StaffRoleCommunityPermissions, type StaffRoleCommunityPermissionsEntityReference, type StaffRoleCommunityPermissionsProps } from './staff-role-community-permissions.ts'; +import { StaffRoleFinancePermissions, type StaffRoleFinancePermissionsEntityReference, type StaffRoleFinancePermissionsProps } from './staff-role-finance-permissions.ts'; import { StaffRolePropertyPermissions, type StaffRolePropertyPermissionsEntityReference, type StaffRolePropertyPermissionsProps } from './staff-role-property-permissions.ts'; -import { StaffRoleSectionPermissions, type StaffRoleSectionPermissionsEntityReference, type StaffRoleSectionPermissionsProps } from './staff-role-section-permissions.ts'; import { StaffRoleServicePermissions, type StaffRoleServicePermissionsEntityReference, type StaffRoleServicePermissionsProps } from './staff-role-service-permissions.ts'; import { StaffRoleServiceTicketPermissions, type StaffRoleServiceTicketPermissionsEntityReference, type StaffRoleServiceTicketPermissionsProps } from './staff-role-service-ticket-permissions.ts'; +import { StaffRoleTechAdminPermissions, type StaffRoleTechAdminPermissionsEntityReference, type StaffRoleTechAdminPermissionsProps } from './staff-role-tech-admin-permissions.ts'; +import { StaffRoleUserPermissions, type StaffRoleUserPermissionsEntityReference, type StaffRoleUserPermissionsProps } from './staff-role-user-permissions.ts'; import { StaffRoleViolationTicketPermissions, type StaffRoleViolationTicketPermissionsEntityReference, type StaffRoleViolationTicketPermissionsProps } from './staff-role-violation-ticket-permissions.ts'; export interface StaffRolePermissionsProps extends ValueObjectProps { @@ -14,17 +16,21 @@ export interface StaffRolePermissionsProps extends ValueObjectProps { readonly serviceTicketPermissions: StaffRoleServiceTicketPermissionsProps; readonly servicePermissions: StaffRoleServicePermissionsProps; readonly violationTicketPermissions: StaffRoleViolationTicketPermissionsProps; - readonly sectionPermissions: StaffRoleSectionPermissionsProps; + readonly financePermissions: StaffRoleFinancePermissionsProps; + readonly techAdminPermissions: StaffRoleTechAdminPermissionsProps; + readonly userPermissions: StaffRoleUserPermissionsProps; } export interface StaffRolePermissionsEntityReference - extends Readonly> { + extends Readonly> { readonly communityPermissions: StaffRoleCommunityPermissionsEntityReference; readonly propertyPermissions: StaffRolePropertyPermissionsEntityReference; readonly serviceTicketPermissions: StaffRoleServiceTicketPermissionsEntityReference; readonly servicePermissions: StaffRoleServicePermissionsEntityReference; readonly violationTicketPermissions: StaffRoleViolationTicketPermissionsEntityReference; - readonly sectionPermissions: StaffRoleSectionPermissionsEntityReference; + readonly financePermissions: StaffRoleFinancePermissionsEntityReference; + readonly techAdminPermissions: StaffRoleTechAdminPermissionsEntityReference; + readonly userPermissions: StaffRoleUserPermissionsEntityReference; } export class StaffRolePermissions extends ValueObject implements StaffRolePermissionsEntityReference { @@ -50,7 +56,13 @@ export class StaffRolePermissions extends ValueObject get violationTicketPermissions(): StaffRoleViolationTicketPermissions { return new StaffRoleViolationTicketPermissions(this.props.violationTicketPermissions, this.visa); } - get sectionPermissions(): StaffRoleSectionPermissions { - return new StaffRoleSectionPermissions(this.props.sectionPermissions, this.visa); + get financePermissions(): StaffRoleFinancePermissions { + return new StaffRoleFinancePermissions(this.props.financePermissions, this.visa); + } + get techAdminPermissions(): StaffRoleTechAdminPermissions { + return new StaffRoleTechAdminPermissions(this.props.techAdminPermissions, this.visa); + } + get userPermissions(): StaffRoleUserPermissions { + return new StaffRoleUserPermissions(this.props.userPermissions, this.visa); } } diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-section-permissions.test.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-section-permissions.test.ts deleted file mode 100644 index e5a4c1b58..000000000 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-section-permissions.test.ts +++ /dev/null @@ -1,224 +0,0 @@ -import path from 'node:path'; -import { fileURLToPath } from 'node:url'; -import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; -import { PermissionError } from '@cellix/domain-seedwork/domain-entity'; -import { expect, vi } from 'vitest'; - -import { StaffRoleSectionPermissions } from './staff-role-section-permissions.ts'; - -const test = { for: describeFeature }; -const __dirname = path.dirname(fileURLToPath(import.meta.url)); -const feature = await loadFeature(path.resolve(__dirname, 'features/staff-role-section-permissions.feature')); - -function makeVisa({ canManageStaffRolesAndPermissions = true, isSystemAccount = false } = {}) { - return vi.mocked({ - determineIf: vi.fn((fn) => fn({ canManageStaffRolesAndPermissions, isSystemAccount })), - }); -} - -function makeProps(overrides = {}) { - return { - canManageCommunities: false, - canManageUser: false, - canManageFinance: false, - canManageTechAdmin: false, - ...overrides, - }; -} - -test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { - let visa: ReturnType; - let props: ReturnType; - let entity: StaffRoleSectionPermissions; - - BeforeEachScenario(() => { - visa = makeVisa(); - props = makeProps(); - entity = new StaffRoleSectionPermissions(props, visa); - }); - - Background(({ Given, And }) => { - Given('valid StaffRoleSectionPermissionsProps with all permission flags set to false', () => { - props = makeProps(); - }); - And('a valid UserVisa', () => { - visa = makeVisa(); - }); - }); - - // canManageCommunities - Scenario('Changing canManageCommunities with manage staff roles permission', ({ Given, When, Then }) => { - Given('a StaffRoleSectionPermissions entity with permission to manage staff roles', () => { - visa = makeVisa({ canManageStaffRolesAndPermissions: true, isSystemAccount: false }); - entity = new StaffRoleSectionPermissions(makeProps(), visa); - }); - When('I set canManageCommunities to true', () => { - entity.canManageCommunities = true; - }); - Then('the property should be updated to true', () => { - expect(entity.canManageCommunities).toBe(true); - }); - }); - - Scenario('Changing canManageCommunities with system account permission', ({ Given, When, Then }) => { - Given('a StaffRoleSectionPermissions entity with system account permission', () => { - visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: true }); - entity = new StaffRoleSectionPermissions(makeProps(), visa); - }); - When('I set canManageCommunities to true', () => { - entity.canManageCommunities = true; - }); - Then('the property should be updated to true', () => { - expect(entity.canManageCommunities).toBe(true); - }); - }); - - Scenario('Changing canManageCommunities without permission', ({ Given, When, Then }) => { - let setWithoutPermission: () => void; - Given('a StaffRoleSectionPermissions entity without permission to manage staff roles or system account', () => { - visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: false }); - entity = new StaffRoleSectionPermissions(makeProps(), visa); - }); - When('I try to set canManageCommunities to true', () => { - setWithoutPermission = () => { - entity.canManageCommunities = true; - }; - }); - Then('a PermissionError should be thrown', () => { - expect(setWithoutPermission).toThrow(PermissionError); - expect(setWithoutPermission).toThrow('Cannot set permission'); - }); - }); - - // canManageUser - Scenario('Changing canManageUser with manage staff roles permission', ({ Given, When, Then }) => { - Given('a StaffRoleSectionPermissions entity with permission to manage staff roles', () => { - visa = makeVisa({ canManageStaffRolesAndPermissions: true, isSystemAccount: false }); - entity = new StaffRoleSectionPermissions(makeProps(), visa); - }); - When('I set canManageUser to true', () => { - entity.canManageUser = true; - }); - Then('the property should be updated to true', () => { - expect(entity.canManageUser).toBe(true); - }); - }); - - Scenario('Changing canManageUser with system account permission', ({ Given, When, Then }) => { - Given('a StaffRoleSectionPermissions entity with system account permission', () => { - visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: true }); - entity = new StaffRoleSectionPermissions(makeProps(), visa); - }); - When('I set canManageUser to true', () => { - entity.canManageUser = true; - }); - Then('the property should be updated to true', () => { - expect(entity.canManageUser).toBe(true); - }); - }); - - Scenario('Changing canManageUser without permission', ({ Given, When, Then }) => { - let setWithoutPermission: () => void; - Given('a StaffRoleSectionPermissions entity without permission to manage staff roles or system account', () => { - visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: false }); - entity = new StaffRoleSectionPermissions(makeProps(), visa); - }); - When('I try to set canManageUser to true', () => { - setWithoutPermission = () => { - entity.canManageUser = true; - }; - }); - Then('a PermissionError should be thrown', () => { - expect(setWithoutPermission).toThrow(PermissionError); - expect(setWithoutPermission).toThrow('Cannot set permission'); - }); - }); - - // canManageFinance - Scenario('Changing canManageFinance with manage staff roles permission', ({ Given, When, Then }) => { - Given('a StaffRoleSectionPermissions entity with permission to manage staff roles', () => { - visa = makeVisa({ canManageStaffRolesAndPermissions: true, isSystemAccount: false }); - entity = new StaffRoleSectionPermissions(makeProps(), visa); - }); - When('I set canManageFinance to true', () => { - entity.canManageFinance = true; - }); - Then('the property should be updated to true', () => { - expect(entity.canManageFinance).toBe(true); - }); - }); - - Scenario('Changing canManageFinance with system account permission', ({ Given, When, Then }) => { - Given('a StaffRoleSectionPermissions entity with system account permission', () => { - visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: true }); - entity = new StaffRoleSectionPermissions(makeProps(), visa); - }); - When('I set canManageFinance to true', () => { - entity.canManageFinance = true; - }); - Then('the property should be updated to true', () => { - expect(entity.canManageFinance).toBe(true); - }); - }); - - Scenario('Changing canManageFinance without permission', ({ Given, When, Then }) => { - let setWithoutPermission: () => void; - Given('a StaffRoleSectionPermissions entity without permission to manage staff roles or system account', () => { - visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: false }); - entity = new StaffRoleSectionPermissions(makeProps(), visa); - }); - When('I try to set canManageFinance to true', () => { - setWithoutPermission = () => { - entity.canManageFinance = true; - }; - }); - Then('a PermissionError should be thrown', () => { - expect(setWithoutPermission).toThrow(PermissionError); - expect(setWithoutPermission).toThrow('Cannot set permission'); - }); - }); - - // canManageTechAdmin - Scenario('Changing canManageTechAdmin with manage staff roles permission', ({ Given, When, Then }) => { - Given('a StaffRoleSectionPermissions entity with permission to manage staff roles', () => { - visa = makeVisa({ canManageStaffRolesAndPermissions: true, isSystemAccount: false }); - entity = new StaffRoleSectionPermissions(makeProps(), visa); - }); - When('I set canManageTechAdmin to true', () => { - entity.canManageTechAdmin = true; - }); - Then('the property should be updated to true', () => { - expect(entity.canManageTechAdmin).toBe(true); - }); - }); - - Scenario('Changing canManageTechAdmin with system account permission', ({ Given, When, Then }) => { - Given('a StaffRoleSectionPermissions entity with system account permission', () => { - visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: true }); - entity = new StaffRoleSectionPermissions(makeProps(), visa); - }); - When('I set canManageTechAdmin to true', () => { - entity.canManageTechAdmin = true; - }); - Then('the property should be updated to true', () => { - expect(entity.canManageTechAdmin).toBe(true); - }); - }); - - Scenario('Changing canManageTechAdmin without permission', ({ Given, When, Then }) => { - let setWithoutPermission: () => void; - Given('a StaffRoleSectionPermissions entity without permission to manage staff roles or system account', () => { - visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: false }); - entity = new StaffRoleSectionPermissions(makeProps(), visa); - }); - When('I try to set canManageTechAdmin to true', () => { - setWithoutPermission = () => { - entity.canManageTechAdmin = true; - }; - }); - Then('a PermissionError should be thrown', () => { - expect(setWithoutPermission).toThrow(PermissionError); - expect(setWithoutPermission).toThrow('Cannot set permission'); - }); - }); -}); diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-section-permissions.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-section-permissions.ts deleted file mode 100644 index 503b7f811..000000000 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-section-permissions.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { PermissionError } from '@cellix/domain-seedwork/domain-entity'; -import type { ValueObjectProps } from '@cellix/domain-seedwork/value-object'; -import { ValueObject } from '@cellix/domain-seedwork/value-object'; -import type { UserVisa } from '../user.visa.ts'; - -interface StaffRoleSectionPermissionsSpec { - canManageCommunities: boolean; - canManageUser: boolean; - canManageFinance: boolean; - canManageTechAdmin: boolean; -} - -export interface StaffRoleSectionPermissionsProps extends StaffRoleSectionPermissionsSpec, ValueObjectProps {} -export interface StaffRoleSectionPermissionsEntityReference extends Readonly {} - -export class StaffRoleSectionPermissions extends ValueObject implements StaffRoleSectionPermissionsEntityReference { - private readonly visa: UserVisa; - - constructor(props: StaffRoleSectionPermissionsProps, visa: UserVisa) { - super(props); - this.visa = visa; - } - - private validateVisa() { - if (!this.visa.determineIf((permissions) => permissions.canManageStaffRolesAndPermissions || permissions.isSystemAccount)) { - throw new PermissionError('Cannot set permission'); - } - } - - get canManageCommunities(): boolean { - return this.props.canManageCommunities; - } - set canManageCommunities(value: boolean) { - this.validateVisa(); - this.props.canManageCommunities = value; - } - - get canManageUser(): boolean { - return this.props.canManageUser; - } - set canManageUser(value: boolean) { - this.validateVisa(); - this.props.canManageUser = value; - } - - get canManageFinance(): boolean { - return this.props.canManageFinance; - } - set canManageFinance(value: boolean) { - this.validateVisa(); - this.props.canManageFinance = value; - } - - get canManageTechAdmin(): boolean { - return this.props.canManageTechAdmin; - } - set canManageTechAdmin(value: boolean) { - this.validateVisa(); - this.props.canManageTechAdmin = value; - } -} diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-tech-admin-permissions.test.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-tech-admin-permissions.test.ts new file mode 100644 index 000000000..e143bbc32 --- /dev/null +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-tech-admin-permissions.test.ts @@ -0,0 +1,211 @@ +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; +import { PermissionError } from '@cellix/domain-seedwork/domain-entity'; +import { expect, vi } from 'vitest'; +import { StaffRoleTechAdminPermissions } from './staff-role-tech-admin-permissions.ts'; + +const test = { for: describeFeature }; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const feature = await loadFeature(path.resolve(__dirname, 'features/staff-role-tech-admin-permissions.feature')); + +function makeVisa({ canManageStaffRolesAndPermissions = true, isSystemAccount = false } = {}) { + return vi.mocked({ + determineIf: vi.fn((fn) => fn({ canManageStaffRolesAndPermissions, isSystemAccount })), + }); +} + +function makeProps(overrides = {}) { + return { + canManageTechAdmin: false, + canViewDatabaseExplorer: false, + canViewBlobExplorer: false, + canViewQueueDashboard: false, + canSendQueueMessages: false, + ...overrides, + }; +} + +test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { + let visa: ReturnType; + let props: ReturnType; + let entity: StaffRoleTechAdminPermissions; + + BeforeEachScenario(() => { + visa = makeVisa(); + props = makeProps(); + entity = new StaffRoleTechAdminPermissions(props, visa); + }); + + Background(({ Given, And }) => { + Given('valid StaffRoleTechAdminPermissionsProps with all permission flags set to false', () => { + props = makeProps(); + }); + And('a valid UserVisa', () => { + visa = makeVisa(); + }); + }); + + Scenario('Changing canManageTechAdmin with manage staff roles permission', ({ Given, When, Then }) => { + Given('a StaffRoleTechAdminPermissions entity with permission to manage staff roles', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: true, isSystemAccount: false }); + entity = new StaffRoleTechAdminPermissions(makeProps(), visa); + }); + When('I set canManageTechAdmin to true', () => { + entity.canManageTechAdmin = true; + }); + Then('the property should be updated to true', () => { + expect(entity.canManageTechAdmin).toBe(true); + }); + }); + + Scenario('Changing canManageTechAdmin with system account permission', ({ Given, When, Then }) => { + Given('a StaffRoleTechAdminPermissions entity with system account permission', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: true }); + entity = new StaffRoleTechAdminPermissions(makeProps(), visa); + }); + When('I set canManageTechAdmin to true', () => { + entity.canManageTechAdmin = true; + }); + Then('the property should be updated to true', () => { + expect(entity.canManageTechAdmin).toBe(true); + }); + }); + + Scenario('Changing canManageTechAdmin without permission', ({ Given, When, Then }) => { + let setWithoutPermission: () => void; + Given('a StaffRoleTechAdminPermissions entity without permission to manage staff roles or system account', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: false }); + entity = new StaffRoleTechAdminPermissions(makeProps(), visa); + }); + When('I try to set canManageTechAdmin to true', () => { + setWithoutPermission = () => { + entity.canManageTechAdmin = true; + }; + }); + Then('a PermissionError should be thrown', () => { + expect(setWithoutPermission).toThrow(PermissionError); + expect(setWithoutPermission).toThrow('Cannot set permission'); + }); + }); + + Scenario('Changing canViewDatabaseExplorer with manage staff roles permission', ({ Given, When, Then }) => { + Given('a StaffRoleTechAdminPermissions entity with permission to manage staff roles', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: true, isSystemAccount: false }); + entity = new StaffRoleTechAdminPermissions(makeProps(), visa); + }); + When('I set canViewDatabaseExplorer to true', () => { + entity.canViewDatabaseExplorer = true; + }); + Then('the property should be updated to true', () => { + expect(entity.canViewDatabaseExplorer).toBe(true); + }); + }); + + Scenario('Changing canViewDatabaseExplorer without permission', ({ Given, When, Then }) => { + let setWithoutPermission: () => void; + Given('a StaffRoleTechAdminPermissions entity without permission to manage staff roles or system account', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: false }); + entity = new StaffRoleTechAdminPermissions(makeProps(), visa); + }); + When('I try to set canViewDatabaseExplorer to true', () => { + setWithoutPermission = () => { + entity.canViewDatabaseExplorer = true; + }; + }); + Then('a PermissionError should be thrown', () => { + expect(setWithoutPermission).toThrow(PermissionError); + expect(setWithoutPermission).toThrow('Cannot set permission'); + }); + }); + + Scenario('Changing canViewBlobExplorer with manage staff roles permission', ({ Given, When, Then }) => { + Given('a StaffRoleTechAdminPermissions entity with permission to manage staff roles', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: true, isSystemAccount: false }); + entity = new StaffRoleTechAdminPermissions(makeProps(), visa); + }); + When('I set canViewBlobExplorer to true', () => { + entity.canViewBlobExplorer = true; + }); + Then('the property should be updated to true', () => { + expect(entity.canViewBlobExplorer).toBe(true); + }); + }); + + Scenario('Changing canViewBlobExplorer without permission', ({ Given, When, Then }) => { + let setWithoutPermission: () => void; + Given('a StaffRoleTechAdminPermissions entity without permission to manage staff roles or system account', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: false }); + entity = new StaffRoleTechAdminPermissions(makeProps(), visa); + }); + When('I try to set canViewBlobExplorer to true', () => { + setWithoutPermission = () => { + entity.canViewBlobExplorer = true; + }; + }); + Then('a PermissionError should be thrown', () => { + expect(setWithoutPermission).toThrow(PermissionError); + expect(setWithoutPermission).toThrow('Cannot set permission'); + }); + }); + + Scenario('Changing canViewQueueDashboard with manage staff roles permission', ({ Given, When, Then }) => { + Given('a StaffRoleTechAdminPermissions entity with permission to manage staff roles', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: true, isSystemAccount: false }); + entity = new StaffRoleTechAdminPermissions(makeProps(), visa); + }); + When('I set canViewQueueDashboard to true', () => { + entity.canViewQueueDashboard = true; + }); + Then('the property should be updated to true', () => { + expect(entity.canViewQueueDashboard).toBe(true); + }); + }); + + Scenario('Changing canViewQueueDashboard without permission', ({ Given, When, Then }) => { + let setWithoutPermission: () => void; + Given('a StaffRoleTechAdminPermissions entity without permission to manage staff roles or system account', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: false }); + entity = new StaffRoleTechAdminPermissions(makeProps(), visa); + }); + When('I try to set canViewQueueDashboard to true', () => { + setWithoutPermission = () => { + entity.canViewQueueDashboard = true; + }; + }); + Then('a PermissionError should be thrown', () => { + expect(setWithoutPermission).toThrow(PermissionError); + expect(setWithoutPermission).toThrow('Cannot set permission'); + }); + }); + + Scenario('Changing canSendQueueMessages with manage staff roles permission', ({ Given, When, Then }) => { + Given('a StaffRoleTechAdminPermissions entity with permission to manage staff roles', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: true, isSystemAccount: false }); + entity = new StaffRoleTechAdminPermissions(makeProps(), visa); + }); + When('I set canSendQueueMessages to true', () => { + entity.canSendQueueMessages = true; + }); + Then('the property should be updated to true', () => { + expect(entity.canSendQueueMessages).toBe(true); + }); + }); + + Scenario('Changing canSendQueueMessages without permission', ({ Given, When, Then }) => { + let setWithoutPermission: () => void; + Given('a StaffRoleTechAdminPermissions entity without permission to manage staff roles or system account', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: false }); + entity = new StaffRoleTechAdminPermissions(makeProps(), visa); + }); + When('I try to set canSendQueueMessages to true', () => { + setWithoutPermission = () => { + entity.canSendQueueMessages = true; + }; + }); + Then('a PermissionError should be thrown', () => { + expect(setWithoutPermission).toThrow(PermissionError); + expect(setWithoutPermission).toThrow('Cannot set permission'); + }); + }); +}); diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-tech-admin-permissions.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-tech-admin-permissions.ts new file mode 100644 index 000000000..9d225e6c7 --- /dev/null +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-tech-admin-permissions.ts @@ -0,0 +1,70 @@ +import { PermissionError } from '@cellix/domain-seedwork/domain-entity'; +import type { ValueObjectProps } from '@cellix/domain-seedwork/value-object'; +import { ValueObject } from '@cellix/domain-seedwork/value-object'; +import type { UserVisa } from '../user.visa.ts'; + +interface StaffRoleTechAdminPermissionsSpec { + canManageTechAdmin: boolean; + canViewDatabaseExplorer: boolean; + canViewBlobExplorer: boolean; + canViewQueueDashboard: boolean; + canSendQueueMessages: boolean; +} + +export interface StaffRoleTechAdminPermissionsProps extends StaffRoleTechAdminPermissionsSpec, ValueObjectProps {} +export interface StaffRoleTechAdminPermissionsEntityReference extends Readonly {} + +export class StaffRoleTechAdminPermissions extends ValueObject implements StaffRoleTechAdminPermissionsEntityReference { + private readonly visa: UserVisa; + + constructor(props: StaffRoleTechAdminPermissionsProps, visa: UserVisa) { + super(props); + this.visa = visa; + } + + private validateVisa() { + if (!this.visa.determineIf((permissions) => permissions.canManageStaffRolesAndPermissions || permissions.isSystemAccount)) { + throw new PermissionError('Cannot set permission'); + } + } + + get canManageTechAdmin(): boolean { + return this.props.canManageTechAdmin; + } + set canManageTechAdmin(value: boolean) { + this.validateVisa(); + this.props.canManageTechAdmin = value; + } + + get canViewDatabaseExplorer(): boolean { + return this.props.canViewDatabaseExplorer; + } + set canViewDatabaseExplorer(value: boolean) { + this.validateVisa(); + this.props.canViewDatabaseExplorer = value; + } + + get canViewBlobExplorer(): boolean { + return this.props.canViewBlobExplorer; + } + set canViewBlobExplorer(value: boolean) { + this.validateVisa(); + this.props.canViewBlobExplorer = value; + } + + get canViewQueueDashboard(): boolean { + return this.props.canViewQueueDashboard; + } + set canViewQueueDashboard(value: boolean) { + this.validateVisa(); + this.props.canViewQueueDashboard = value; + } + + get canSendQueueMessages(): boolean { + return this.props.canSendQueueMessages; + } + set canSendQueueMessages(value: boolean) { + this.validateVisa(); + this.props.canSendQueueMessages = value; + } +} diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-user-permissions.test.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-user-permissions.test.ts new file mode 100644 index 000000000..969d1e7ab --- /dev/null +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-user-permissions.test.ts @@ -0,0 +1,87 @@ +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; +import { PermissionError } from '@cellix/domain-seedwork/domain-entity'; +import { expect, vi } from 'vitest'; +import { StaffRoleUserPermissions } from './staff-role-user-permissions.ts'; + +const test = { for: describeFeature }; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const feature = await loadFeature(path.resolve(__dirname, 'features/staff-role-user-permissions.feature')); + +function makeVisa({ canManageStaffRolesAndPermissions = true, isSystemAccount = false } = {}) { + return vi.mocked({ + determineIf: vi.fn((fn) => fn({ canManageStaffRolesAndPermissions, isSystemAccount })), + }); +} + +function makeProps(overrides = {}) { + return { + canManageUsers: false, + ...overrides, + }; +} + +test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { + let visa: ReturnType; + let props: ReturnType; + let entity: StaffRoleUserPermissions; + + BeforeEachScenario(() => { + visa = makeVisa(); + props = makeProps(); + entity = new StaffRoleUserPermissions(props, visa); + }); + + Background(({ Given, And }) => { + Given('valid StaffRoleUserPermissionsProps with all permission flags set to false', () => { + props = makeProps(); + }); + And('a valid UserVisa', () => { + visa = makeVisa(); + }); + }); + + Scenario('Changing canManageUsers with manage staff roles permission', ({ Given, When, Then }) => { + Given('a StaffRoleUserPermissions entity with permission to manage staff roles', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: true, isSystemAccount: false }); + entity = new StaffRoleUserPermissions(makeProps(), visa); + }); + When('I set canManageUsers to true', () => { + entity.canManageUsers = true; + }); + Then('the property should be updated to true', () => { + expect(entity.canManageUsers).toBe(true); + }); + }); + + Scenario('Changing canManageUsers with system account permission', ({ Given, When, Then }) => { + Given('a StaffRoleUserPermissions entity with system account permission', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: true }); + entity = new StaffRoleUserPermissions(makeProps(), visa); + }); + When('I set canManageUsers to true', () => { + entity.canManageUsers = true; + }); + Then('the property should be updated to true', () => { + expect(entity.canManageUsers).toBe(true); + }); + }); + + Scenario('Changing canManageUsers without permission', ({ Given, When, Then }) => { + let setWithoutPermission: () => void; + Given('a StaffRoleUserPermissions entity without permission to manage staff roles or system account', () => { + visa = makeVisa({ canManageStaffRolesAndPermissions: false, isSystemAccount: false }); + entity = new StaffRoleUserPermissions(makeProps(), visa); + }); + When('I try to set canManageUsers to true', () => { + setWithoutPermission = () => { + entity.canManageUsers = true; + }; + }); + Then('a PermissionError should be thrown', () => { + expect(setWithoutPermission).toThrow(PermissionError); + expect(setWithoutPermission).toThrow('Cannot set permission'); + }); + }); +}); diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-user-permissions.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-user-permissions.ts new file mode 100644 index 000000000..358c7a7c4 --- /dev/null +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-user-permissions.ts @@ -0,0 +1,34 @@ +import { PermissionError } from '@cellix/domain-seedwork/domain-entity'; +import type { ValueObjectProps } from '@cellix/domain-seedwork/value-object'; +import { ValueObject } from '@cellix/domain-seedwork/value-object'; +import type { UserVisa } from '../user.visa.ts'; + +interface StaffRoleUserPermissionsSpec { + canManageUsers: boolean; +} + +export interface StaffRoleUserPermissionsProps extends StaffRoleUserPermissionsSpec, ValueObjectProps {} +export interface StaffRoleUserPermissionsEntityReference extends Readonly {} + +export class StaffRoleUserPermissions extends ValueObject implements StaffRoleUserPermissionsEntityReference { + private readonly visa: UserVisa; + + constructor(props: StaffRoleUserPermissionsProps, visa: UserVisa) { + super(props); + this.visa = visa; + } + + private validateVisa() { + if (!this.visa.determineIf((permissions) => permissions.canManageStaffRolesAndPermissions || permissions.isSystemAccount)) { + throw new PermissionError('Cannot set permission'); + } + } + + get canManageUsers(): boolean { + return this.props.canManageUsers; + } + set canManageUsers(value: boolean) { + this.validateVisa(); + this.props.canManageUsers = value; + } +} diff --git a/packages/ocom/graphql/src/schema/types/staff-user.graphql b/packages/ocom/graphql/src/schema/types/staff-user.graphql index 1cf3a56de..1def99be8 100644 --- a/packages/ocom/graphql/src/schema/types/staff-user.graphql +++ b/packages/ocom/graphql/src/schema/types/staff-user.graphql @@ -1,12 +1,36 @@ -type StaffRoleSectionPermissions { +type StaffRoleCommunityPermissions { canManageCommunities: Boolean! - canManageUser: Boolean! + canManageStaffRolesAndPermissions: Boolean! + canManageAllCommunities: Boolean! + canDeleteCommunities: Boolean! + canChangeCommunityOwner: Boolean! + canReIndexSearchCollections: Boolean! +} + +type StaffRoleFinancePermissions { canManageFinance: Boolean! + canViewGLBatchSummaries: Boolean! + canViewFinanceConfigs: Boolean! + canCreateFinanceConfigs: Boolean! +} + +type StaffRoleTechAdminPermissions { canManageTechAdmin: Boolean! + canViewDatabaseExplorer: Boolean! + canViewBlobExplorer: Boolean! + canViewQueueDashboard: Boolean! + canSendQueueMessages: Boolean! +} + +type StaffRoleUserPermissions { + canManageUsers: Boolean! } type StaffRolePermissions { - sectionPermissions: StaffRoleSectionPermissions! + communityPermissions: StaffRoleCommunityPermissions! + financePermissions: StaffRoleFinancePermissions! + techAdminPermissions: StaffRoleTechAdminPermissions! + userPermissions: StaffRoleUserPermissions! } type StaffRole implements MongoBase { diff --git a/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.ts b/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.ts index 58c44c20e..b66459b8c 100644 --- a/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.ts +++ b/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.ts @@ -2,11 +2,13 @@ import { MongooseSeedwork } from '@cellix/mongoose-seedwork'; import type { StaffRole, StaffRoleCommunityPermissions, + StaffRoleFinancePermissions, StaffRolePermissions, StaffRolePropertyPermissions, - StaffRoleSectionPermissions, StaffRoleServicePermissions, StaffRoleServiceTicketPermissions, + StaffRoleTechAdminPermissions, + StaffRoleUserPermissions, StaffRoleViolationTicketPermissions, } from '@ocom/data-sources-mongoose-models/role/staff-role'; import { Domain } from '@ocom/domain'; @@ -53,18 +55,6 @@ export class StaffRolePermissionsAdapter implements Domain.Contexts.User.StaffRo this.doc = permissions; } - get sectionPermissions(): Domain.Contexts.User.StaffRole.StaffRoleSectionPermissionsProps { - if (!this.doc.sectionPermissions) { - this.doc.sectionPermissions = { - canManageCommunities: false, - canManageUser: false, - canManageFinance: false, - canManageTechAdmin: false, - }; - } - return new StaffRoleSectionPermissionsAdapter(this.doc.sectionPermissions); - } - get communityPermissions(): Domain.Contexts.User.StaffRole.StaffRoleCommunityPermissionsProps { if (!this.doc.communityPermissions) { this.doc.communityPermissions = { @@ -123,6 +113,40 @@ export class StaffRolePermissionsAdapter implements Domain.Contexts.User.StaffRo } return new StaffRoleViolationTicketPermissionsAdapter(this.doc.violationTicketPermissions); } + + get financePermissions(): Domain.Contexts.User.StaffRole.StaffRoleFinancePermissionsProps { + if (!this.doc.financePermissions) { + this.doc.financePermissions = { + canManageFinance: false, + canViewGLBatchSummaries: false, + canViewFinanceConfigs: false, + canCreateFinanceConfigs: false, + }; + } + return new StaffRoleFinancePermissionsAdapter(this.doc.financePermissions); + } + + get techAdminPermissions(): Domain.Contexts.User.StaffRole.StaffRoleTechAdminPermissionsProps { + if (!this.doc.techAdminPermissions) { + this.doc.techAdminPermissions = { + canManageTechAdmin: false, + canViewDatabaseExplorer: false, + canViewBlobExplorer: false, + canViewQueueDashboard: false, + canSendQueueMessages: false, + }; + } + return new StaffRoleTechAdminPermissionsAdapter(this.doc.techAdminPermissions); + } + + get userPermissions(): Domain.Contexts.User.StaffRole.StaffRoleUserPermissionsProps { + if (!this.doc.userPermissions) { + this.doc.userPermissions = { + canManageUsers: false, + }; + } + return new StaffRoleUserPermissionsAdapter(this.doc.userPermissions); + } } export class StaffRoleCommunityPermissionsAdapter implements Domain.Contexts.User.StaffRole.StaffRoleCommunityPermissionsProps { @@ -140,6 +164,13 @@ export class StaffRoleCommunityPermissionsAdapter implements Domain.Contexts.Use return this.doc.id?.toString(); } + get canManageCommunities(): boolean { + return this.ensureValue(this.doc.canManageCommunities); + } + set canManageCommunities(value: boolean) { + this.doc.canManageCommunities = value; + } + get canManageStaffRolesAndPermissions(): boolean { return this.ensureValue(this.doc.canManageStaffRolesAndPermissions); } @@ -285,10 +316,10 @@ export class StaffRoleViolationTicketPermissionsAdapter implements Domain.Contex } } -class StaffRoleSectionPermissionsAdapter implements Domain.Contexts.User.StaffRole.StaffRoleSectionPermissionsProps { - private readonly doc: StaffRoleSectionPermissions; +class StaffRoleFinancePermissionsAdapter implements Domain.Contexts.User.StaffRole.StaffRoleFinancePermissionsProps { + private readonly doc: StaffRoleFinancePermissions; - constructor(permissions: StaffRoleSectionPermissions) { + constructor(permissions: StaffRoleFinancePermissions) { this.doc = permissions; } @@ -300,25 +331,48 @@ class StaffRoleSectionPermissionsAdapter implements Domain.Contexts.User.StaffRo return this.doc.id?.toString(); } - get canManageCommunities(): boolean { - return this.ensureValue(this.doc.canManageCommunities); + get canManageFinance(): boolean { + return this.ensureValue(this.doc.canManageFinance); } - set canManageCommunities(value: boolean) { - this.doc.canManageCommunities = value; + set canManageFinance(value: boolean) { + this.doc.canManageFinance = value; } - get canManageUser(): boolean { - return this.ensureValue(this.doc.canManageUser); + get canViewGLBatchSummaries(): boolean { + return this.ensureValue(this.doc.canViewGLBatchSummaries); } - set canManageUser(value: boolean) { - this.doc.canManageUser = value; + set canViewGLBatchSummaries(value: boolean) { + this.doc.canViewGLBatchSummaries = value; } - get canManageFinance(): boolean { - return this.ensureValue(this.doc.canManageFinance); + get canViewFinanceConfigs(): boolean { + return this.ensureValue(this.doc.canViewFinanceConfigs); } - set canManageFinance(value: boolean) { - this.doc.canManageFinance = value; + set canViewFinanceConfigs(value: boolean) { + this.doc.canViewFinanceConfigs = value; + } + + get canCreateFinanceConfigs(): boolean { + return this.ensureValue(this.doc.canCreateFinanceConfigs); + } + set canCreateFinanceConfigs(value: boolean) { + this.doc.canCreateFinanceConfigs = value; + } +} + +class StaffRoleTechAdminPermissionsAdapter implements Domain.Contexts.User.StaffRole.StaffRoleTechAdminPermissionsProps { + private readonly doc: StaffRoleTechAdminPermissions; + + constructor(permissions: StaffRoleTechAdminPermissions) { + this.doc = permissions; + } + + private ensureValue(value: boolean | undefined): boolean { + return value ?? false; + } + + get id(): string | undefined { + return this.doc.id?.toString(); } get canManageTechAdmin(): boolean { @@ -327,4 +381,55 @@ class StaffRoleSectionPermissionsAdapter implements Domain.Contexts.User.StaffRo set canManageTechAdmin(value: boolean) { this.doc.canManageTechAdmin = value; } + + get canViewDatabaseExplorer(): boolean { + return this.ensureValue(this.doc.canViewDatabaseExplorer); + } + set canViewDatabaseExplorer(value: boolean) { + this.doc.canViewDatabaseExplorer = value; + } + + get canViewBlobExplorer(): boolean { + return this.ensureValue(this.doc.canViewBlobExplorer); + } + set canViewBlobExplorer(value: boolean) { + this.doc.canViewBlobExplorer = value; + } + + get canViewQueueDashboard(): boolean { + return this.ensureValue(this.doc.canViewQueueDashboard); + } + set canViewQueueDashboard(value: boolean) { + this.doc.canViewQueueDashboard = value; + } + + get canSendQueueMessages(): boolean { + return this.ensureValue(this.doc.canSendQueueMessages); + } + set canSendQueueMessages(value: boolean) { + this.doc.canSendQueueMessages = value; + } +} + +class StaffRoleUserPermissionsAdapter implements Domain.Contexts.User.StaffRole.StaffRoleUserPermissionsProps { + private readonly doc: StaffRoleUserPermissions; + + constructor(permissions: StaffRoleUserPermissions) { + this.doc = permissions; + } + + private ensureValue(value: boolean | undefined): boolean { + return value ?? false; + } + + get id(): string | undefined { + return this.doc.id?.toString(); + } + + get canManageUsers(): boolean { + return this.ensureValue(this.doc.canManageUsers); + } + set canManageUsers(value: boolean) { + this.doc.canManageUsers = value; + } } diff --git a/packages/ocom/ui-community-route-accounts/src/components/community-list.container.graphql b/packages/ocom/ui-community-route-accounts/src/components/community-list.container.graphql index 6b3f040a5..808f658a4 100644 --- a/packages/ocom/ui-community-route-accounts/src/components/community-list.container.graphql +++ b/packages/ocom/ui-community-route-accounts/src/components/community-list.container.graphql @@ -14,7 +14,7 @@ query AccountsCommunityListContainerCurrentStaffUser { currentStaffUserAndCreateIfNotExists { role { permissions { - sectionPermissions { + communityPermissions { canManageCommunities } } diff --git a/packages/ocom/ui-community-route-accounts/src/components/community-list.container.tsx b/packages/ocom/ui-community-route-accounts/src/components/community-list.container.tsx index e4830def4..e7df386a8 100644 --- a/packages/ocom/ui-community-route-accounts/src/components/community-list.container.tsx +++ b/packages/ocom/ui-community-route-accounts/src/components/community-list.container.tsx @@ -21,7 +21,7 @@ export const CommunityListContainer: React.FC = () => { }); const { data: staffUserData } = useQuery(AccountsCommunityListContainerCurrentStaffUserDocument); - const canCreateCommunity = staffUserData?.currentStaffUserAndCreateIfNotExists?.role?.permissions?.sectionPermissions?.canManageCommunities ?? false; + const canCreateCommunity = staffUserData?.currentStaffUserAndCreateIfNotExists?.role?.permissions?.communityPermissions?.canManageCommunities ?? false; const members: AccountsCommunityListContainerMemberFieldsFragment[][] = []; if (membersData?.membersForCurrentEndUser && membersData?.membersForCurrentEndUser.length > 0 && communityData?.communitiesForCurrentEndUser) { diff --git a/packages/ocom/ui-community-route-admin/src/index.tsx b/packages/ocom/ui-community-route-admin/src/index.tsx index 365ffed9f..61788f252 100644 --- a/packages/ocom/ui-community-route-admin/src/index.tsx +++ b/packages/ocom/ui-community-route-admin/src/index.tsx @@ -28,7 +28,7 @@ export const Admin: React.FC = () => { parent: 'ROOT', hasPermissions: (data: unknown) => { const adminData = data as AdminMenuData; - return adminData?.staffPermissions?.canManageUser ?? false; + return adminData?.staffPermissions?.canManageUsers ?? false; }, }, { diff --git a/packages/ocom/ui-community-route-admin/src/section-layout.container.tsx b/packages/ocom/ui-community-route-admin/src/section-layout.container.tsx index 50e2793c2..fcbd4d4cf 100644 --- a/packages/ocom/ui-community-route-admin/src/section-layout.container.tsx +++ b/packages/ocom/ui-community-route-admin/src/section-layout.container.tsx @@ -19,7 +19,14 @@ export const SectionLayoutContainer: React.FC = (pr const { data: membersData, loading: membersLoading, error: membersError } = useQuery(AdminSectionLayoutContainerMembersForCurrentEndUserDocument); const { data: staffUserData } = useQuery(AdminSectionLayoutContainerCurrentStaffUserDocument); - const staffSectionPermissions = staffUserData?.currentStaffUserAndCreateIfNotExists?.role?.permissions?.sectionPermissions ?? null; + const staffSectionPermissions = staffUserData?.currentStaffUserAndCreateIfNotExists?.role?.permissions + ? { + canManageCommunities: staffUserData.currentStaffUserAndCreateIfNotExists.role.permissions.communityPermissions.canManageCommunities, + canManageUsers: staffUserData.currentStaffUserAndCreateIfNotExists.role.permissions.userPermissions.canManageUsers, + canManageFinance: staffUserData.currentStaffUserAndCreateIfNotExists.role.permissions.financePermissions.canManageFinance, + canManageTechAdmin: staffUserData.currentStaffUserAndCreateIfNotExists.role.permissions.techAdminPermissions.canManageTechAdmin, + } + : null; return ( [ + { + path: '/community/:communityId/admin/:memberId', + title: 'Home', + icon: , + id: 'ROOT', + }, + { + path: '/community/:communityId/admin/:memberId/members/*', + title: 'Members', + icon: , + id: 2, + parent: 'ROOT', + hasPermissions: () => permissions?.canManageUsers ?? false, + }, + { + path: '/community/:communityId/admin/:memberId/settings/*', + title: 'Settings', + icon: , + id: 3, + parent: 'ROOT', + hasPermissions: () => permissions?.canManageCommunities ?? false, + }, +]; + +const meta: Meta = { + title: 'Admin/Layouts/SectionLayout', + component: SectionLayout, + decorators: [ + (Story) => ( + + + + } + /> + + + + ), + ], + parameters: { + layout: 'fullscreen', + }, +}; + +export default meta; +type Story = StoryObj; + +export const AllPermissions: Story = { + args: { + pageLayouts: makePageLayouts(allPermissions), + memberData: mockMember, + staffSectionPermissions: allPermissions, + }, + play: ({ canvasElement }: { canvasElement: HTMLElement }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText('Home')).toBeInTheDocument(); + expect(canvas.getByText('Members')).toBeInTheDocument(); + expect(canvas.getByText('Settings')).toBeInTheDocument(); + }, +}; + +export const NoPermissions: Story = { + args: { + pageLayouts: makePageLayouts(noPermissions), + memberData: mockMember, + staffSectionPermissions: noPermissions, + }, + play: ({ canvasElement }: { canvasElement: HTMLElement }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText('Home')).toBeInTheDocument(); + expect(canvas.queryByText('Members')).not.toBeInTheDocument(); + expect(canvas.queryByText('Settings')).not.toBeInTheDocument(); + }, +}; + +export const CommunityPermissionsOnly: Story = { + args: { + pageLayouts: makePageLayouts({ ...noPermissions, canManageCommunities: true }), + memberData: mockMember, + staffSectionPermissions: { ...noPermissions, canManageCommunities: true }, + }, + play: ({ canvasElement }: { canvasElement: HTMLElement }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText('Home')).toBeInTheDocument(); + expect(canvas.queryByText('Members')).not.toBeInTheDocument(); + expect(canvas.getByText('Settings')).toBeInTheDocument(); + }, +}; + +export const UserPermissionsOnly: Story = { + args: { + pageLayouts: makePageLayouts({ ...noPermissions, canManageUsers: true }), + memberData: mockMember, + staffSectionPermissions: { ...noPermissions, canManageUsers: true }, + }, + play: ({ canvasElement }: { canvasElement: HTMLElement }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText('Home')).toBeInTheDocument(); + expect(canvas.getByText('Members')).toBeInTheDocument(); + expect(canvas.queryByText('Settings')).not.toBeInTheDocument(); + }, +}; + +export const NullPermissions: Story = { + args: { + pageLayouts: makePageLayouts(null), + memberData: mockMember, + staffSectionPermissions: null, + }, + play: ({ canvasElement }: { canvasElement: HTMLElement }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText('Home')).toBeInTheDocument(); + expect(canvas.queryByText('Members')).not.toBeInTheDocument(); + expect(canvas.queryByText('Settings')).not.toBeInTheDocument(); + }, +}; diff --git a/packages/ocom/ui-community-route-admin/src/section-layout.tsx b/packages/ocom/ui-community-route-admin/src/section-layout.tsx index e0fa24948..76086aa4d 100644 --- a/packages/ocom/ui-community-route-admin/src/section-layout.tsx +++ b/packages/ocom/ui-community-route-admin/src/section-layout.tsx @@ -23,7 +23,7 @@ const handleToggler = (isExpanded: boolean, setIsExpanded: (value: boolean) => v export interface AdminStaffSectionPermissions { canManageCommunities: boolean; - canManageUser: boolean; + canManageUsers: boolean; canManageFinance: boolean; canManageTechAdmin: boolean; } From ff7909491f9d3be72f070d40d8d875f96138cf1a Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Thu, 7 May 2026 23:42:13 +0530 Subject: [PATCH 52/88] refactor: improve staff role permissions test structure and enhance type references --- .../staff-role/staff-role-permissions.test.ts | 250 +++++++++--------- .../user/staff-role/staff-role-permissions.ts | 7 +- 2 files changed, 131 insertions(+), 126 deletions(-) diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-permissions.test.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-permissions.test.ts index d3af6b628..c73dcecf7 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-permissions.test.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-permissions.test.ts @@ -17,145 +17,145 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url)); const feature = await loadFeature(path.resolve(__dirname, 'features/staff-role-permissions.feature')); function makeVisa() { -return vi.mocked({ -determineIf: vi.fn(() => true), -}); + return vi.mocked({ + determineIf: vi.fn(() => true), + }); } function makeProps() { -return { -communityPermissions: {} as StaffRoleCommunityPermissions, -propertyPermissions: {} as StaffRolePropertyPermissions, -serviceTicketPermissions: {} as StaffRoleServiceTicketPermissions, -servicePermissions: {} as StaffRoleServicePermissions, -violationTicketPermissions: {} as StaffRoleViolationTicketPermissions, -financePermissions: {} as StaffRoleFinancePermissions, -techAdminPermissions: {} as StaffRoleTechAdminPermissions, -userPermissions: {} as StaffRoleUserPermissions, -}; + return { + communityPermissions: {} as StaffRoleCommunityPermissions, + propertyPermissions: {} as StaffRolePropertyPermissions, + serviceTicketPermissions: {} as StaffRoleServiceTicketPermissions, + servicePermissions: {} as StaffRoleServicePermissions, + violationTicketPermissions: {} as StaffRoleViolationTicketPermissions, + financePermissions: {} as StaffRoleFinancePermissions, + techAdminPermissions: {} as StaffRoleTechAdminPermissions, + userPermissions: {} as StaffRoleUserPermissions, + }; } test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { -let visa: ReturnType; -let props: ReturnType; -let entity: StaffRolePermissions; + let visa: ReturnType; + let props: ReturnType; + let entity: StaffRolePermissions; -BeforeEachScenario(() => { -visa = makeVisa(); -props = makeProps(); -entity = new StaffRolePermissions(props, visa); -}); + BeforeEachScenario(() => { + visa = makeVisa(); + props = makeProps(); + entity = new StaffRolePermissions(props, visa); + }); -Background(({ Given, And }) => { -Given('valid StaffRolePermissionsProps with all required permission props', () => { -props = makeProps(); -}); -And('a valid UserVisa', () => { -visa = makeVisa(); -}); -}); + Background(({ Given, And }) => { + Given('valid StaffRolePermissionsProps with all required permission props', () => { + props = makeProps(); + }); + And('a valid UserVisa', () => { + visa = makeVisa(); + }); + }); -Scenario('Accessing communityPermissions', ({ Given, When, Then }) => { -let communityPermissions: StaffRoleCommunityPermissions; -Given('a StaffRolePermissions entity', () => { -entity = new StaffRolePermissions(props, visa); -}); -When('I access the communityPermissions property', () => { -communityPermissions = entity.communityPermissions; -}); -Then('I should receive a StaffRoleCommunityPermissions entity instance', () => { -expect(communityPermissions).toBeInstanceOf(StaffRoleCommunityPermissions); -}); -}); + Scenario('Accessing communityPermissions', ({ Given, When, Then }) => { + let communityPermissions: StaffRoleCommunityPermissions; + Given('a StaffRolePermissions entity', () => { + entity = new StaffRolePermissions(props, visa); + }); + When('I access the communityPermissions property', () => { + communityPermissions = entity.communityPermissions; + }); + Then('I should receive a StaffRoleCommunityPermissions entity instance', () => { + expect(communityPermissions).toBeInstanceOf(StaffRoleCommunityPermissions); + }); + }); -Scenario('Accessing propertyPermissions', ({ Given, When, Then }) => { -let propertyPermissions: StaffRolePropertyPermissions; -Given('a StaffRolePermissions entity', () => { -entity = new StaffRolePermissions(props, visa); -}); -When('I access the propertyPermissions property', () => { -propertyPermissions = entity.propertyPermissions; -}); -Then('I should receive a StaffRolePropertyPermissions entity instance', () => { -expect(propertyPermissions).toBeInstanceOf(StaffRolePropertyPermissions); -}); -}); + Scenario('Accessing propertyPermissions', ({ Given, When, Then }) => { + let propertyPermissions: StaffRolePropertyPermissions; + Given('a StaffRolePermissions entity', () => { + entity = new StaffRolePermissions(props, visa); + }); + When('I access the propertyPermissions property', () => { + propertyPermissions = entity.propertyPermissions; + }); + Then('I should receive a StaffRolePropertyPermissions entity instance', () => { + expect(propertyPermissions).toBeInstanceOf(StaffRolePropertyPermissions); + }); + }); -Scenario('Accessing serviceTicketPermissions', ({ Given, When, Then }) => { -let serviceTicketPermissions: StaffRoleServiceTicketPermissions; -Given('a StaffRolePermissions entity', () => { -entity = new StaffRolePermissions(props, visa); -}); -When('I access the serviceTicketPermissions property', () => { -serviceTicketPermissions = entity.serviceTicketPermissions; -}); -Then('I should receive a StaffRoleServiceTicketPermissions entity instance', () => { -expect(serviceTicketPermissions).toBeInstanceOf(StaffRoleServiceTicketPermissions); -}); -}); + Scenario('Accessing serviceTicketPermissions', ({ Given, When, Then }) => { + let serviceTicketPermissions: StaffRoleServiceTicketPermissions; + Given('a StaffRolePermissions entity', () => { + entity = new StaffRolePermissions(props, visa); + }); + When('I access the serviceTicketPermissions property', () => { + serviceTicketPermissions = entity.serviceTicketPermissions; + }); + Then('I should receive a StaffRoleServiceTicketPermissions entity instance', () => { + expect(serviceTicketPermissions).toBeInstanceOf(StaffRoleServiceTicketPermissions); + }); + }); -Scenario('Accessing servicePermissions', ({ Given, When, Then }) => { -let servicePermissions: StaffRoleServicePermissions; -Given('a StaffRolePermissions entity', () => { -entity = new StaffRolePermissions(props, visa); -}); -When('I access the servicePermissions property', () => { -servicePermissions = entity.servicePermissions; -}); -Then('I should receive a StaffRoleServicePermissions entity instance', () => { -expect(servicePermissions).toBeInstanceOf(StaffRoleServicePermissions); -}); -}); + Scenario('Accessing servicePermissions', ({ Given, When, Then }) => { + let servicePermissions: StaffRoleServicePermissions; + Given('a StaffRolePermissions entity', () => { + entity = new StaffRolePermissions(props, visa); + }); + When('I access the servicePermissions property', () => { + servicePermissions = entity.servicePermissions; + }); + Then('I should receive a StaffRoleServicePermissions entity instance', () => { + expect(servicePermissions).toBeInstanceOf(StaffRoleServicePermissions); + }); + }); -Scenario('Accessing violationTicketPermissions', ({ Given, When, Then }) => { -let violationTicketPermissions: StaffRoleViolationTicketPermissions; -Given('a StaffRolePermissions entity', () => { -entity = new StaffRolePermissions(props, visa); -}); -When('I access the violationTicketPermissions property', () => { -violationTicketPermissions = entity.violationTicketPermissions; -}); -Then('I should receive a StaffRoleViolationTicketPermissions entity instance', () => { -expect(violationTicketPermissions).toBeInstanceOf(StaffRoleViolationTicketPermissions); -}); -}); + Scenario('Accessing violationTicketPermissions', ({ Given, When, Then }) => { + let violationTicketPermissions: StaffRoleViolationTicketPermissions; + Given('a StaffRolePermissions entity', () => { + entity = new StaffRolePermissions(props, visa); + }); + When('I access the violationTicketPermissions property', () => { + violationTicketPermissions = entity.violationTicketPermissions; + }); + Then('I should receive a StaffRoleViolationTicketPermissions entity instance', () => { + expect(violationTicketPermissions).toBeInstanceOf(StaffRoleViolationTicketPermissions); + }); + }); -Scenario('Accessing financePermissions', ({ Given, When, Then }) => { -let financePermissions: StaffRoleFinancePermissions; -Given('a StaffRolePermissions entity', () => { -entity = new StaffRolePermissions(props, visa); -}); -When('I access the financePermissions property', () => { -financePermissions = entity.financePermissions; -}); -Then('I should receive a StaffRoleFinancePermissions entity instance', () => { -expect(financePermissions).toBeInstanceOf(StaffRoleFinancePermissions); -}); -}); + Scenario('Accessing financePermissions', ({ Given, When, Then }) => { + let financePermissions: StaffRoleFinancePermissions; + Given('a StaffRolePermissions entity', () => { + entity = new StaffRolePermissions(props, visa); + }); + When('I access the financePermissions property', () => { + financePermissions = entity.financePermissions; + }); + Then('I should receive a StaffRoleFinancePermissions entity instance', () => { + expect(financePermissions).toBeInstanceOf(StaffRoleFinancePermissions); + }); + }); -Scenario('Accessing techAdminPermissions', ({ Given, When, Then }) => { -let techAdminPermissions: StaffRoleTechAdminPermissions; -Given('a StaffRolePermissions entity', () => { -entity = new StaffRolePermissions(props, visa); -}); -When('I access the techAdminPermissions property', () => { -techAdminPermissions = entity.techAdminPermissions; -}); -Then('I should receive a StaffRoleTechAdminPermissions entity instance', () => { -expect(techAdminPermissions).toBeInstanceOf(StaffRoleTechAdminPermissions); -}); -}); + Scenario('Accessing techAdminPermissions', ({ Given, When, Then }) => { + let techAdminPermissions: StaffRoleTechAdminPermissions; + Given('a StaffRolePermissions entity', () => { + entity = new StaffRolePermissions(props, visa); + }); + When('I access the techAdminPermissions property', () => { + techAdminPermissions = entity.techAdminPermissions; + }); + Then('I should receive a StaffRoleTechAdminPermissions entity instance', () => { + expect(techAdminPermissions).toBeInstanceOf(StaffRoleTechAdminPermissions); + }); + }); -Scenario('Accessing userPermissions', ({ Given, When, Then }) => { -let userPermissions: StaffRoleUserPermissions; -Given('a StaffRolePermissions entity', () => { -entity = new StaffRolePermissions(props, visa); -}); -When('I access the userPermissions property', () => { -userPermissions = entity.userPermissions; -}); -Then('I should receive a StaffRoleUserPermissions entity instance', () => { -expect(userPermissions).toBeInstanceOf(StaffRoleUserPermissions); -}); -}); + Scenario('Accessing userPermissions', ({ Given, When, Then }) => { + let userPermissions: StaffRoleUserPermissions; + Given('a StaffRolePermissions entity', () => { + entity = new StaffRolePermissions(props, visa); + }); + When('I access the userPermissions property', () => { + userPermissions = entity.userPermissions; + }); + Then('I should receive a StaffRoleUserPermissions entity instance', () => { + expect(userPermissions).toBeInstanceOf(StaffRoleUserPermissions); + }); + }); }); diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-permissions.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-permissions.ts index 3cbb36ab1..7e45a39f6 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-permissions.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-permissions.ts @@ -22,7 +22,12 @@ export interface StaffRolePermissionsProps extends ValueObjectProps { } export interface StaffRolePermissionsEntityReference - extends Readonly> { + extends Readonly< + Omit< + StaffRolePermissionsProps, + 'communityPermissions' | 'propertyPermissions' | 'serviceTicketPermissions' | 'servicePermissions' | 'violationTicketPermissions' | 'financePermissions' | 'techAdminPermissions' | 'userPermissions' + > + > { readonly communityPermissions: StaffRoleCommunityPermissionsEntityReference; readonly propertyPermissions: StaffRolePropertyPermissionsEntityReference; readonly serviceTicketPermissions: StaffRoleServiceTicketPermissionsEntityReference; From b2f97f7ddc538abac6b5718885da3193e76dddde Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Thu, 7 May 2026 14:56:12 -0400 Subject: [PATCH 53/88] refactor: remove default roleType from StaffRoleSchema --- .../src/models/role/staff-role.model.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/ocom/data-sources-mongoose-models/src/models/role/staff-role.model.ts b/packages/ocom/data-sources-mongoose-models/src/models/role/staff-role.model.ts index 656767713..0a25365cf 100644 --- a/packages/ocom/data-sources-mongoose-models/src/models/role/staff-role.model.ts +++ b/packages/ocom/data-sources-mongoose-models/src/models/role/staff-role.model.ts @@ -156,7 +156,6 @@ const StaffRoleSchema = new Schema, StaffRole>( } as SchemaDefinition, schemaVersion: { type: String, default: '1.0.0', immutable: true }, roleName: { type: String, required: true, maxlength: 256 }, - roleType: { type: String, required: true, default: 'staff-user-role' }, enterpriseAppRole: { type: String, required: true, From 17f83e1d420f93616a9e99adf9cb6c45423a1a80 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Fri, 8 May 2026 00:29:46 +0530 Subject: [PATCH 54/88] add mongoose vulnerability exception with detailed reasoning --- .snyk | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.snyk b/.snyk index 48d289e07..48c89be80 100644 --- a/.snyk +++ b/.snyk @@ -66,3 +66,8 @@ ignore: reason: 'Apollo usage-reporting-protobuf depends on @apollo/protobufjs and Snyk reports no fixed version. We are accepting this temporarily until Apollo provides a non-vulnerable upgrade path.' expires: '2026-07-31T00:00:00.000Z' created: '2026-04-30T00:00:00.000Z' + 'SNYK-JS-MONGOOSE-16425765': + - '* > mongoose@8.17.0': + reason: 'Mongoose 8.22.1 has TypeScript constraint errors in type definitions (types/inferrawdoctype.d.ts, types/inferschematype.d.ts) that break compilation. Patch attempts failed due to external library type incompatibilities. Risk is Low: requires control of query field names and values.' + expires: '2026-11-07T00:00:00.000Z' + created: '2026-05-07T09:00:00.000Z' \ No newline at end of file From 6a053ba002e2ded9491965cf45858542ff4dc0ff Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Fri, 8 May 2026 19:37:49 +0530 Subject: [PATCH 55/88] feat: Add staff user resolvers and tests for querying and creating staff users - Implemented GraphQL resolvers for querying and creating staff user entities. - Added feature tests for staff user resolvers, covering scenarios for JWT verification and AAD roles. - Created a read repository for staff users with tests for model presence and document retrieval. - Enhanced staff role domain adapter with additional permission scenarios and tests. --- .../staff-role/create-default-roles.test.ts | 397 ++++++++++++++++ .../features/create-default-roles.feature | 61 +++ .../staff-user/create-if-not-exists.test.ts | 328 +++++++++++++ .../features/create-if-not-exists.feature | 39 ++ .../features/query-by-external-id.feature | 11 + .../staff-user/query-by-external-id.test.ts | 82 ++++ .../features/staff-user.resolvers.feature | 22 + .../schema/types/staff-user.resolvers.test.ts | 191 ++++++++ .../staff-role.domain-adapter.feature | 147 +++++- .../staff-role.domain-adapter.test.ts | 440 ++++++++++++++++++ .../staff-role/staff-role.domain-adapter.ts | 6 +- .../staff-user.read-repository.feature | 23 + .../staff-user.read-repository.test.ts | 141 ++++++ 13 files changed, 1884 insertions(+), 4 deletions(-) create mode 100644 packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts create mode 100644 packages/ocom/application-services/src/contexts/user/staff-role/features/create-default-roles.feature create mode 100644 packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.test.ts create mode 100644 packages/ocom/application-services/src/contexts/user/staff-user/features/create-if-not-exists.feature create mode 100644 packages/ocom/application-services/src/contexts/user/staff-user/features/query-by-external-id.feature create mode 100644 packages/ocom/application-services/src/contexts/user/staff-user/query-by-external-id.test.ts create mode 100644 packages/ocom/graphql/src/schema/types/features/staff-user.resolvers.feature create mode 100644 packages/ocom/graphql/src/schema/types/staff-user.resolvers.test.ts create mode 100644 packages/ocom/persistence/src/datasources/readonly/user/staff-user/features/staff-user.read-repository.feature create mode 100644 packages/ocom/persistence/src/datasources/readonly/user/staff-user/staff-user.read-repository.test.ts diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts new file mode 100644 index 000000000..77e66e1a5 --- /dev/null +++ b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts @@ -0,0 +1,397 @@ +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; +import type { Domain } from '@ocom/domain'; +import type { DataSources } from '@ocom/persistence'; +import { expect, vi } from 'vitest'; +import { StaffAppRoleNames, createDefaultRoles } from './create-default-roles.ts'; + +const test = { for: describeFeature }; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const feature = await loadFeature(path.resolve(__dirname, 'features/create-default-roles.feature')); + +type StaffRolePermissions = { + communityPermissions: { canManageCommunities: boolean }; + financePermissions: { canManageFinance: boolean }; + techAdminPermissions: { canManageTechAdmin: boolean }; + userPermissions: { canManageUsers: boolean }; +}; + +function makeMockStaffRole( + roleName: string, + permissions: StaffRolePermissions = { + communityPermissions: { canManageCommunities: false }, + financePermissions: { canManageFinance: false }, + techAdminPermissions: { canManageTechAdmin: false }, + userPermissions: { canManageUsers: false }, + }, +): Domain.Contexts.User.StaffRole.StaffRole { + return { + id: `id-${roleName}`, + roleName, + isDefault: false, + permissions, + roleType: null, + createdAt: new Date(), + updatedAt: new Date(), + schemaVersion: '1.0', + } as unknown as Domain.Contexts.User.StaffRole.StaffRole; +} + +function makeMockRepo( + existingRoleNames: string[] = [], + overrides: Partial = {}, +): StaffRoleRepo { + const savedRoles: Domain.Contexts.User.StaffRole.StaffRole[] = []; + + return { + // biome-ignore lint/suspicious/noExplicitAny: test helper captures saved roles for inspection + _savedRoles: savedRoles as any, + getByRoleName: vi.fn().mockImplementation((roleName: string) => { + if (existingRoleNames.includes(roleName)) { + return Promise.resolve(makeMockStaffRole(roleName)); + } + return Promise.reject(new Error(`NotFoundError: ${roleName} not found`)); + }), + getNewInstance: vi.fn().mockImplementation((roleName: string) => { + const role = makeMockStaffRole(roleName); + savedRoles.push(role); + return Promise.resolve(role); + }), + save: vi.fn().mockImplementation((role: Domain.Contexts.User.StaffRole.StaffRole) => { + return Promise.resolve(role as Domain.Contexts.User.StaffRole.StaffRoleEntityReference); + }), + ...overrides, + } as unknown as StaffRoleRepo; +} + +type StaffRoleRepo = Domain.Contexts.User.StaffRole.StaffRoleRepository; + +function makeDataSources(repo: StaffRoleRepo): DataSources { + return { + domainDataSource: { + User: { + StaffRole: { + StaffRoleUnitOfWork: { + withScopedTransaction: vi.fn().mockImplementation(async (callback: (r: StaffRoleRepo) => Promise) => { + await callback(repo); + }), + }, + }, + }, + }, + } as unknown as DataSources; +} + +test.for(feature, ({ Scenario, BeforeEachScenario }) => { + let dataSources: DataSources; + let mockRepo: StaffRoleRepo; + let result: Domain.Contexts.User.StaffRole.StaffRoleEntityReference[]; + + BeforeEachScenario(() => { + result = []; + mockRepo = undefined as unknown as typeof mockRepo; + dataSources = undefined as unknown as DataSources; + }); + + // ─── All four missing ────────────────────────────────────────────────────── + + Scenario('Creates all four default roles when none exist', ({ Given, When, Then, And }) => { + Given('no staff roles exist', () => { + mockRepo = makeMockRepo([]); + dataSources = makeDataSources(mockRepo); + }); + + When('I call createDefaultRoles', async () => { + result = await createDefaultRoles(dataSources)(); + }); + + Then('it should create all four roles: "Staff.CaseManager", "Staff.ServiceLineOwner", "Staff.Finance", "Staff.TechAdmin"', () => { + expect(vi.mocked(mockRepo.getNewInstance)).toHaveBeenCalledTimes(4); + const names = vi.mocked(mockRepo.getNewInstance).mock.calls.map(([n]) => n); + expect(names).toContain(StaffAppRoleNames.CaseManager); + expect(names).toContain(StaffAppRoleNames.ServiceLineOwner); + expect(names).toContain(StaffAppRoleNames.Finance); + expect(names).toContain(StaffAppRoleNames.TechAdmin); + }); + + And('it should return all four created role references', () => { + expect(result).toHaveLength(4); + }); + }); + + // ─── Partial skip ───────────────────────────────────────────────────────── + + Scenario('Skips roles that already exist', ({ Given, When, Then, And }) => { + Given('the role "Staff.CaseManager" already exists', () => { + mockRepo = makeMockRepo([StaffAppRoleNames.CaseManager]); + dataSources = makeDataSources(mockRepo); + }); + + When('I call createDefaultRoles', async () => { + result = await createDefaultRoles(dataSources)(); + }); + + Then('it should only create the three missing roles', () => { + expect(vi.mocked(mockRepo.getNewInstance)).toHaveBeenCalledTimes(3); + }); + + And('it should not attempt to create "Staff.CaseManager" again', () => { + const names = vi.mocked(mockRepo.getNewInstance).mock.calls.map(([n]) => n); + expect(names).not.toContain(StaffAppRoleNames.CaseManager); + }); + }); + + // ─── All exist ──────────────────────────────────────────────────────────── + + Scenario('Returns empty array when all roles already exist', ({ Given, When, Then, And }) => { + Given('all four default roles already exist', () => { + mockRepo = makeMockRepo(Object.values(StaffAppRoleNames)); + dataSources = makeDataSources(mockRepo); + }); + + When('I call createDefaultRoles', async () => { + result = await createDefaultRoles(dataSources)(); + }); + + Then('it should return an empty array', () => { + expect(result).toHaveLength(0); + }); + + And('it should not call getNewInstance or save', () => { + expect(vi.mocked(mockRepo.getNewInstance)).not.toHaveBeenCalled(); + expect(vi.mocked(mockRepo.save)).not.toHaveBeenCalled(); + }); + }); + + // ─── CaseManager permissions ────────────────────────────────────────────── + + Scenario('CaseManager role has correct permissions', ({ Given, When, Then, And }) => { + let capturedRoles: Map>; + + Given('no staff roles exist', () => { + capturedRoles = new Map(); + mockRepo = { + getByRoleName: vi.fn().mockRejectedValue(new Error('not found')), + getNewInstance: vi.fn().mockImplementation((roleName: string) => { + const role = makeMockStaffRole(roleName); + capturedRoles.set(roleName, role); + return Promise.resolve(role); + }), + save: vi.fn().mockImplementation((role: Domain.Contexts.User.StaffRole.StaffRole) => + Promise.resolve(role as Domain.Contexts.User.StaffRole.StaffRoleEntityReference), + ), + } as unknown as typeof mockRepo; + dataSources = makeDataSources(mockRepo); + }); + + When('I call createDefaultRoles', async () => { + await createDefaultRoles(dataSources)(); + }); + + Then('the "Staff.CaseManager" role should have canManageCommunities true', () => { + const role = capturedRoles.get(StaffAppRoleNames.CaseManager); + expect(role?.permissions.communityPermissions.canManageCommunities).toBe(true); + }); + + And('the "Staff.CaseManager" role should have canManageFinance false', () => { + const role = capturedRoles.get(StaffAppRoleNames.CaseManager); + expect(role?.permissions.financePermissions.canManageFinance).toBe(false); + }); + + And('the "Staff.CaseManager" role should have canManageTechAdmin false', () => { + const role = capturedRoles.get(StaffAppRoleNames.CaseManager); + expect(role?.permissions.techAdminPermissions.canManageTechAdmin).toBe(false); + }); + + And('the "Staff.CaseManager" role should have canManageUsers true', () => { + const role = capturedRoles.get(StaffAppRoleNames.CaseManager); + expect(role?.permissions.userPermissions.canManageUsers).toBe(true); + }); + }); + + // ─── Finance permissions ────────────────────────────────────────────────── + + Scenario('Finance role has correct permissions', ({ Given, When, Then, And }) => { + let capturedRoles: Map>; + + Given('no staff roles exist', () => { + capturedRoles = new Map(); + mockRepo = { + getByRoleName: vi.fn().mockRejectedValue(new Error('not found')), + getNewInstance: vi.fn().mockImplementation((roleName: string) => { + const role = makeMockStaffRole(roleName); + capturedRoles.set(roleName, role); + return Promise.resolve(role); + }), + save: vi.fn().mockImplementation((role: Domain.Contexts.User.StaffRole.StaffRole) => + Promise.resolve(role as Domain.Contexts.User.StaffRole.StaffRoleEntityReference), + ), + } as unknown as typeof mockRepo; + dataSources = makeDataSources(mockRepo); + }); + + When('I call createDefaultRoles', async () => { + await createDefaultRoles(dataSources)(); + }); + + Then('the "Staff.Finance" role should have canManageCommunities false', () => { + const role = capturedRoles.get(StaffAppRoleNames.Finance); + expect(role?.permissions.communityPermissions.canManageCommunities).toBe(false); + }); + + And('the "Staff.Finance" role should have canManageFinance true', () => { + const role = capturedRoles.get(StaffAppRoleNames.Finance); + expect(role?.permissions.financePermissions.canManageFinance).toBe(true); + }); + + And('the "Staff.Finance" role should have canManageTechAdmin false', () => { + const role = capturedRoles.get(StaffAppRoleNames.Finance); + expect(role?.permissions.techAdminPermissions.canManageTechAdmin).toBe(false); + }); + + And('the "Staff.Finance" role should have canManageUsers false', () => { + const role = capturedRoles.get(StaffAppRoleNames.Finance); + expect(role?.permissions.userPermissions.canManageUsers).toBe(false); + }); + }); + + // ─── TechAdmin permissions ──────────────────────────────────────────────── + + Scenario('TechAdmin role has correct permissions', ({ Given, When, Then, And }) => { + let capturedRoles: Map>; + + Given('no staff roles exist', () => { + capturedRoles = new Map(); + mockRepo = { + getByRoleName: vi.fn().mockRejectedValue(new Error('not found')), + getNewInstance: vi.fn().mockImplementation((roleName: string) => { + const role = makeMockStaffRole(roleName); + capturedRoles.set(roleName, role); + return Promise.resolve(role); + }), + save: vi.fn().mockImplementation((role: Domain.Contexts.User.StaffRole.StaffRole) => + Promise.resolve(role as Domain.Contexts.User.StaffRole.StaffRoleEntityReference), + ), + } as unknown as typeof mockRepo; + dataSources = makeDataSources(mockRepo); + }); + + When('I call createDefaultRoles', async () => { + await createDefaultRoles(dataSources)(); + }); + + Then('the "Staff.TechAdmin" role should have canManageCommunities false', () => { + const role = capturedRoles.get(StaffAppRoleNames.TechAdmin); + expect(role?.permissions.communityPermissions.canManageCommunities).toBe(false); + }); + + And('the "Staff.TechAdmin" role should have canManageFinance false', () => { + const role = capturedRoles.get(StaffAppRoleNames.TechAdmin); + expect(role?.permissions.financePermissions.canManageFinance).toBe(false); + }); + + And('the "Staff.TechAdmin" role should have canManageTechAdmin true', () => { + const role = capturedRoles.get(StaffAppRoleNames.TechAdmin); + expect(role?.permissions.techAdminPermissions.canManageTechAdmin).toBe(true); + }); + + And('the "Staff.TechAdmin" role should have canManageUsers false', () => { + const role = capturedRoles.get(StaffAppRoleNames.TechAdmin); + expect(role?.permissions.userPermissions.canManageUsers).toBe(false); + }); + }); + + // ─── ServiceLineOwner permissions ───────────────────────────────────────── + + Scenario('ServiceLineOwner role has correct permissions', ({ Given, When, Then, And }) => { + let capturedRoles: Map>; + + Given('no staff roles exist', () => { + capturedRoles = new Map(); + mockRepo = { + getByRoleName: vi.fn().mockRejectedValue(new Error('not found')), + getNewInstance: vi.fn().mockImplementation((roleName: string) => { + const role = makeMockStaffRole(roleName); + capturedRoles.set(roleName, role); + return Promise.resolve(role); + }), + save: vi.fn().mockImplementation((role: Domain.Contexts.User.StaffRole.StaffRole) => + Promise.resolve(role as Domain.Contexts.User.StaffRole.StaffRoleEntityReference), + ), + } as unknown as typeof mockRepo; + dataSources = makeDataSources(mockRepo); + }); + + When('I call createDefaultRoles', async () => { + await createDefaultRoles(dataSources)(); + }); + + Then('the "Staff.ServiceLineOwner" role should have canManageCommunities true', () => { + const role = capturedRoles.get(StaffAppRoleNames.ServiceLineOwner); + expect(role?.permissions.communityPermissions.canManageCommunities).toBe(true); + }); + + And('the "Staff.ServiceLineOwner" role should have canManageFinance false', () => { + const role = capturedRoles.get(StaffAppRoleNames.ServiceLineOwner); + expect(role?.permissions.financePermissions.canManageFinance).toBe(false); + }); + + And('the "Staff.ServiceLineOwner" role should have canManageTechAdmin false', () => { + const role = capturedRoles.get(StaffAppRoleNames.ServiceLineOwner); + expect(role?.permissions.techAdminPermissions.canManageTechAdmin).toBe(false); + }); + + And('the "Staff.ServiceLineOwner" role should have canManageUsers true', () => { + const role = capturedRoles.get(StaffAppRoleNames.ServiceLineOwner); + expect(role?.permissions.userPermissions.canManageUsers).toBe(true); + }); + }); + + // ─── isDefault false ────────────────────────────────────────────────────── + + Scenario('All created roles have isDefault set to false', ({ Given, When, Then }) => { + Given('no staff roles exist', () => { + mockRepo = makeMockRepo([]); + dataSources = makeDataSources(mockRepo); + }); + + When('I call createDefaultRoles', async () => { + result = await createDefaultRoles(dataSources)(); + }); + + Then('all created roles should have isDefault false', () => { + for (const role of result) { + expect(role.isDefault).toBe(false); + } + }); + }); + + // ─── Error propagation ──────────────────────────────────────────────────── + + Scenario('Propagates unexpected repository errors', ({ Given, When, Then }) => { + let thrownError: unknown; + + Given('no staff roles exist', () => { + mockRepo = { + getByRoleName: vi.fn().mockRejectedValue(new Error('Database connection failed')), + getNewInstance: vi.fn(), + save: vi.fn(), + } as unknown as typeof mockRepo; + dataSources = makeDataSources(mockRepo); + }); + + When('the repository throws an unexpected error', async () => { + try { + await createDefaultRoles(dataSources)(); + } catch (error) { + thrownError = error; + } + }); + + Then('createDefaultRoles should propagate the error', () => { + expect(thrownError).toBeInstanceOf(Error); + expect((thrownError as Error).message).toBe('Database connection failed'); + }); + }); +}); diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/features/create-default-roles.feature b/packages/ocom/application-services/src/contexts/user/staff-role/features/create-default-roles.feature new file mode 100644 index 000000000..dc923cca5 --- /dev/null +++ b/packages/ocom/application-services/src/contexts/user/staff-role/features/create-default-roles.feature @@ -0,0 +1,61 @@ +Feature: Creating default staff roles + + Scenario: Creates all four default roles when none exist + Given no staff roles exist + When I call createDefaultRoles + Then it should create all four roles: "Staff.CaseManager", "Staff.ServiceLineOwner", "Staff.Finance", "Staff.TechAdmin" + And it should return all four created role references + + Scenario: Skips roles that already exist + Given the role "Staff.CaseManager" already exists + When I call createDefaultRoles + Then it should only create the three missing roles + And it should not attempt to create "Staff.CaseManager" again + + Scenario: Returns empty array when all roles already exist + Given all four default roles already exist + When I call createDefaultRoles + Then it should return an empty array + And it should not call getNewInstance or save + + Scenario: CaseManager role has correct permissions + Given no staff roles exist + When I call createDefaultRoles + Then the "Staff.CaseManager" role should have canManageCommunities true + And the "Staff.CaseManager" role should have canManageFinance false + And the "Staff.CaseManager" role should have canManageTechAdmin false + And the "Staff.CaseManager" role should have canManageUsers true + + Scenario: Finance role has correct permissions + Given no staff roles exist + When I call createDefaultRoles + Then the "Staff.Finance" role should have canManageCommunities false + And the "Staff.Finance" role should have canManageFinance true + And the "Staff.Finance" role should have canManageTechAdmin false + And the "Staff.Finance" role should have canManageUsers false + + Scenario: TechAdmin role has correct permissions + Given no staff roles exist + When I call createDefaultRoles + Then the "Staff.TechAdmin" role should have canManageCommunities false + And the "Staff.TechAdmin" role should have canManageFinance false + And the "Staff.TechAdmin" role should have canManageTechAdmin true + And the "Staff.TechAdmin" role should have canManageUsers false + + Scenario: ServiceLineOwner role has correct permissions + Given no staff roles exist + When I call createDefaultRoles + Then the "Staff.ServiceLineOwner" role should have canManageCommunities true + And the "Staff.ServiceLineOwner" role should have canManageFinance false + And the "Staff.ServiceLineOwner" role should have canManageTechAdmin false + And the "Staff.ServiceLineOwner" role should have canManageUsers true + + Scenario: All created roles have isDefault set to false + Given no staff roles exist + When I call createDefaultRoles + Then all created roles should have isDefault false + + Scenario: Propagates unexpected repository errors + Given no staff roles exist + When the repository throws an unexpected error + Then createDefaultRoles should propagate the error diff --git a/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.test.ts b/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.test.ts new file mode 100644 index 000000000..9f866d775 --- /dev/null +++ b/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.test.ts @@ -0,0 +1,328 @@ +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; +import type { Domain } from '@ocom/domain'; +import type { DataSources } from '@ocom/persistence'; +import { expect, vi } from 'vitest'; +import { StaffAppRoleNames } from '../staff-role/create-default-roles.ts'; +import { createIfNotExists, type StaffUserCreateIfNotExistsCommand } from './create-if-not-exists.ts'; + +const test = { for: describeFeature }; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const feature = await loadFeature(path.resolve(__dirname, 'features/create-if-not-exists.feature')); + +// ─── Helpers ───────────────────────────────────────────────────────────────── + +function makeMockStaffUserRef(externalId: string): Domain.Contexts.User.StaffUser.StaffUserEntityReference { + return { + id: `id-${externalId}`, + externalId, + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + displayName: 'Test User', + accessBlocked: false, + tags: [], + userType: 'staff', + role: undefined, + createdAt: new Date(), + updatedAt: new Date(), + schemaVersion: '1.0', + } as unknown as Domain.Contexts.User.StaffUser.StaffUserEntityReference; +} + +function makeMockStaffRoleRef(roleName: string): Domain.Contexts.User.StaffRole.StaffRoleEntityReference { + return { + id: `role-id-${roleName}`, + roleName, + isDefault: false, + roleType: null, + permissions: { + communityPermissions: { canManageCommunities: false }, + financePermissions: { canManageFinance: false }, + techAdminPermissions: { canManageTechAdmin: false }, + userPermissions: { canManageUsers: false }, + }, + createdAt: new Date(), + updatedAt: new Date(), + schemaVersion: '1.0', + } as unknown as Domain.Contexts.User.StaffRole.StaffRoleEntityReference; +} + +interface MockStaffUserInstance extends Domain.Contexts.User.StaffUser.StaffUserEntityReference { + role: Domain.Contexts.User.StaffRole.StaffRoleEntityReference | undefined; +} + +function makeMockNewUser(externalId: string): MockStaffUserInstance { + let _role: Domain.Contexts.User.StaffRole.StaffRoleEntityReference | undefined = undefined; + return { + id: `new-id-${externalId}`, + externalId, + firstName: 'First', + lastName: 'Last', + email: 'first@example.com', + displayName: 'First Last', + accessBlocked: false, + tags: [], + userType: 'staff', + get role() { + return _role; + }, + set role(r: Domain.Contexts.User.StaffRole.StaffRoleEntityReference | undefined) { + _role = r; + }, + createdAt: new Date(), + updatedAt: new Date(), + schemaVersion: '1.0', + } as unknown as MockStaffUserInstance; +} + +function makeDataSources(overrides: { + existingUser?: Domain.Contexts.User.StaffUser.StaffUserEntityReference | null; + newUser?: MockStaffUserInstance; + savedUser?: Domain.Contexts.User.StaffUser.StaffUserEntityReference; + roleByName?: Domain.Contexts.User.StaffRole.StaffRoleEntityReference | null; + saveShouldFail?: boolean; +}): DataSources { + const newUser = overrides.newUser ?? makeMockNewUser('default'); + const savedUser = overrides.savedUser ?? (newUser as unknown as Domain.Contexts.User.StaffUser.StaffUserEntityReference); + + const staffUserRepo = { + getByExternalId: vi.fn().mockResolvedValue(overrides.existingUser ?? null), + getNewInstance: vi.fn().mockResolvedValue(newUser), + save: overrides.saveShouldFail + ? vi.fn().mockResolvedValue(undefined) + : vi.fn().mockResolvedValue(savedUser), + delete: vi.fn(), + } as unknown as Domain.Contexts.User.StaffUser.StaffUserRepository; + + const staffRoleRepo = { + getByRoleName: vi.fn().mockImplementation((name: string) => { + if (overrides.roleByName && overrides.roleByName.roleName === name) { + return Promise.resolve(overrides.roleByName); + } + return Promise.reject(new Error(`NotFoundError: ${name} not found`)); + }), + getNewInstance: vi.fn().mockImplementation((name: string) => + Promise.resolve(makeMockStaffRoleRef(name)), + ), + save: vi.fn().mockImplementation((r: unknown) => Promise.resolve(r)), + } as unknown as Domain.Contexts.User.StaffRole.StaffRoleRepository; + + return { + readonlyDataSource: { + User: { + StaffUser: { + StaffUserReadRepo: { + getByExternalId: vi.fn().mockResolvedValue(overrides.existingUser ?? null), + }, + }, + }, + }, + domainDataSource: { + User: { + StaffUser: { + StaffUserUnitOfWork: { + withScopedTransaction: vi.fn().mockImplementation( + async (cb: (repo: typeof staffUserRepo) => Promise) => { + await cb(staffUserRepo); + }, + ), + }, + }, + StaffRole: { + StaffRoleUnitOfWork: { + withScopedTransaction: vi.fn().mockImplementation( + async (cb: (repo: typeof staffRoleRepo) => Promise) => { + await cb(staffRoleRepo); + }, + ), + }, + }, + }, + }, + _staffUserRepo: staffUserRepo, + _staffRoleRepo: staffRoleRepo, + } as unknown as DataSources; +} + +// ─── Tests ──────────────────────────────────────────────────────────────────── + +test.for(feature, ({ Scenario, BeforeEachScenario }) => { + let dataSources: DataSources & { _staffUserRepo?: typeof Object; _staffRoleRepo?: typeof Object }; + let command: StaffUserCreateIfNotExistsCommand; + let result: Domain.Contexts.User.StaffUser.StaffUserEntityReference | undefined; + let thrownError: unknown; + let existingUser: Domain.Contexts.User.StaffUser.StaffUserEntityReference | null; + let newUser: MockStaffUserInstance; + + BeforeEachScenario(() => { + result = undefined; + thrownError = undefined; + existingUser = null; + newUser = makeMockNewUser('default'); + command = { + externalId: 'ext-default', + firstName: 'First', + lastName: 'Last', + email: 'first@example.com', + aadRoles: [], + }; + }); + + // ─── Returns existing user ──────────────────────────────────────────────── + + Scenario('Returns existing user when user already exists', ({ Given, When, Then, And }) => { + Given('a staff user with externalId "ext-123" already exists', () => { + existingUser = makeMockStaffUserRef('ext-123'); + dataSources = makeDataSources({ existingUser }); + command = { ...command, externalId: 'ext-123' }; + }); + + When('I call createIfNotExists with externalId "ext-123"', async () => { + result = await createIfNotExists(dataSources)(command); + }); + + Then('it should return the existing user', () => { + expect(result).toBe(existingUser); + }); + + And('it should not create a new user', () => { + const repo = (dataSources as unknown as { _staffUserRepo: { getNewInstance: ReturnType } })._staffUserRepo; + expect(repo.getNewInstance).not.toHaveBeenCalled(); + }); + }); + + // ─── Creates new user (no role) ─────────────────────────────────────────── + + Scenario('Creates a new user when user does not exist', ({ Given, When, Then, And }) => { + Given('no staff user with externalId "ext-456" exists', () => { + newUser = makeMockNewUser('ext-456'); + dataSources = makeDataSources({ existingUser: null, newUser }); + command = { ...command, externalId: 'ext-456', aadRoles: [] }; + }); + + And('no matching AAD role is provided', () => { + // aadRoles is already [] + }); + + When('I call createIfNotExists with externalId "ext-456"', async () => { + result = await createIfNotExists(dataSources)(command); + }); + + Then('it should call createDefaultRoles', () => { + const roleUow = (dataSources as unknown as { + domainDataSource: { User: { StaffRole: { StaffRoleUnitOfWork: { withScopedTransaction: ReturnType } } } }; + }).domainDataSource.User.StaffRole.StaffRoleUnitOfWork; + expect(roleUow.withScopedTransaction).toHaveBeenCalled(); + }); + + And('it should create a new user with the provided details', () => { + const repo = (dataSources as unknown as { _staffUserRepo: { getNewInstance: ReturnType } })._staffUserRepo; + expect(repo.getNewInstance).toHaveBeenCalledWith('ext-456', 'First', 'Last', 'first@example.com'); + }); + + And('it should return the newly created user', () => { + expect(result).toBeDefined(); + expect(result?.externalId).toBe('ext-456'); + }); + }); + + // ─── Assigns matching role ──────────────────────────────────────────────── + + Scenario('Creates a new user with a matching role when AAD role matches', ({ Given, When, Then, And }) => { + let roleRef: Domain.Contexts.User.StaffRole.StaffRoleEntityReference; + + Given('no staff user with externalId "ext-789" exists', () => { + roleRef = makeMockStaffRoleRef(StaffAppRoleNames.CaseManager); + newUser = makeMockNewUser('ext-789'); + dataSources = makeDataSources({ existingUser: null, newUser, roleByName: roleRef }); + command = { ...command, externalId: 'ext-789' }; + }); + + And('the AAD roles include "Staff.CaseManager"', () => { + command = { ...command, aadRoles: [StaffAppRoleNames.CaseManager] }; + }); + + And('the "Staff.CaseManager" role exists in the repository', () => { + // role was set up in Given + }); + + When('I call createIfNotExists with externalId "ext-789"', async () => { + result = await createIfNotExists(dataSources)(command); + }); + + Then('it should assign the "Staff.CaseManager" role to the new user', () => { + expect(newUser.role).toBeDefined(); + expect(newUser.role?.roleName).toBe(StaffAppRoleNames.CaseManager); + }); + }); + + // ─── No role when AAD role unknown ──────────────────────────────────────── + + Scenario('Creates a new user without a role when no AAD role matches', ({ Given, When, Then, And }) => { + Given('no staff user with externalId "ext-000" exists', () => { + newUser = makeMockNewUser('ext-000'); + dataSources = makeDataSources({ existingUser: null, newUser }); + command = { ...command, externalId: 'ext-000' }; + }); + + And('the AAD roles include "Unknown.Role"', () => { + command = { ...command, aadRoles: ['Unknown.Role'] }; + }); + + When('I call createIfNotExists with externalId "ext-000"', async () => { + result = await createIfNotExists(dataSources)(command); + }); + + Then('it should create the user without assigning a role', () => { + expect(newUser.role).toBeUndefined(); + }); + }); + + // ─── No role when empty AAD roles ──────────────────────────────────────── + + Scenario('Creates a new user without a role when AAD roles list is empty', ({ Given, When, Then, And }) => { + Given('no staff user with externalId "ext-111" exists', () => { + newUser = makeMockNewUser('ext-111'); + dataSources = makeDataSources({ existingUser: null, newUser }); + command = { ...command, externalId: 'ext-111' }; + }); + + And('the AAD roles list is empty', () => { + command = { ...command, aadRoles: [] }; + }); + + When('I call createIfNotExists with externalId "ext-111"', async () => { + result = await createIfNotExists(dataSources)(command); + }); + + Then('it should create the user without assigning a role', () => { + expect(newUser.role).toBeUndefined(); + }); + }); + + // ─── Throws when save returns undefined ─────────────────────────────────── + + Scenario('Throws when repository fails to save the new user', ({ Given, When, Then }) => { + Given('no staff user with externalId "ext-err" exists', () => { + // save returns undefined to simulate a failed save (createdUser stays undefined) + newUser = makeMockNewUser('ext-err'); + dataSources = makeDataSources({ existingUser: null, newUser, saveShouldFail: true }); + command = { ...command, externalId: 'ext-err', aadRoles: [] }; + }); + + When('I call createIfNotExists with externalId "ext-err"', async () => { + try { + await createIfNotExists(dataSources)(command); + } catch (error) { + thrownError = error; + } + }); + + Then('it should throw an error with message "Unable to create staff user"', () => { + expect(thrownError).toBeInstanceOf(Error); + expect((thrownError as Error).message).toBe('Unable to create staff user'); + }); + }); +}); diff --git a/packages/ocom/application-services/src/contexts/user/staff-user/features/create-if-not-exists.feature b/packages/ocom/application-services/src/contexts/user/staff-user/features/create-if-not-exists.feature new file mode 100644 index 000000000..cebfbebf5 --- /dev/null +++ b/packages/ocom/application-services/src/contexts/user/staff-user/features/create-if-not-exists.feature @@ -0,0 +1,39 @@ +Feature: Create staff user if not exists + + Scenario: Returns existing user when user already exists + Given a staff user with externalId "ext-123" already exists + When I call createIfNotExists with externalId "ext-123" + Then it should return the existing user + And it should not create a new user + + Scenario: Creates a new user when user does not exist + Given no staff user with externalId "ext-456" exists + And no matching AAD role is provided + When I call createIfNotExists with externalId "ext-456" + Then it should call createDefaultRoles + And it should create a new user with the provided details + And it should return the newly created user + + Scenario: Creates a new user with a matching role when AAD role matches + Given no staff user with externalId "ext-789" exists + And the AAD roles include "Staff.CaseManager" + And the "Staff.CaseManager" role exists in the repository + When I call createIfNotExists with externalId "ext-789" + Then it should assign the "Staff.CaseManager" role to the new user + + Scenario: Creates a new user without a role when no AAD role matches + Given no staff user with externalId "ext-000" exists + And the AAD roles include "Unknown.Role" + When I call createIfNotExists with externalId "ext-000" + Then it should create the user without assigning a role + + Scenario: Creates a new user without a role when AAD roles list is empty + Given no staff user with externalId "ext-111" exists + And the AAD roles list is empty + When I call createIfNotExists with externalId "ext-111" + Then it should create the user without assigning a role + + Scenario: Throws when repository fails to save the new user + Given no staff user with externalId "ext-err" exists + When I call createIfNotExists with externalId "ext-err" + Then it should throw an error with message "Unable to create staff user" diff --git a/packages/ocom/application-services/src/contexts/user/staff-user/features/query-by-external-id.feature b/packages/ocom/application-services/src/contexts/user/staff-user/features/query-by-external-id.feature new file mode 100644 index 000000000..097572fd4 --- /dev/null +++ b/packages/ocom/application-services/src/contexts/user/staff-user/features/query-by-external-id.feature @@ -0,0 +1,11 @@ +Feature: Query staff user by external ID + + Scenario: Returns a staff user when the external ID exists + Given a staff user with externalId "ext-123" exists in the read repository + When I call queryByExternalId with externalId "ext-123" + Then it should return the matching staff user + + Scenario: Returns null when no staff user matches the external ID + Given no staff user with externalId "ext-missing" exists in the read repository + When I call queryByExternalId with externalId "ext-missing" + Then it should return null diff --git a/packages/ocom/application-services/src/contexts/user/staff-user/query-by-external-id.test.ts b/packages/ocom/application-services/src/contexts/user/staff-user/query-by-external-id.test.ts new file mode 100644 index 000000000..2cbcc5f4d --- /dev/null +++ b/packages/ocom/application-services/src/contexts/user/staff-user/query-by-external-id.test.ts @@ -0,0 +1,82 @@ +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; +import type { Domain } from '@ocom/domain'; +import type { DataSources } from '@ocom/persistence'; +import { expect, vi } from 'vitest'; +import { queryByExternalId } from './query-by-external-id.ts'; + +const test = { for: describeFeature }; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const feature = await loadFeature(path.resolve(__dirname, 'features/query-by-external-id.feature')); + +function makeMockStaffUserRef(externalId: string): Domain.Contexts.User.StaffUser.StaffUserEntityReference { + return { + id: `id-${externalId}`, + externalId, + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + displayName: 'Test User', + accessBlocked: false, + tags: [], + userType: 'staff', + role: undefined, + createdAt: new Date(), + updatedAt: new Date(), + schemaVersion: '1.0', + } as unknown as Domain.Contexts.User.StaffUser.StaffUserEntityReference; +} + +function makeDataSources(existingUser: Domain.Contexts.User.StaffUser.StaffUserEntityReference | null): DataSources { + return { + readonlyDataSource: { + User: { + StaffUser: { + StaffUserReadRepo: { + getByExternalId: vi.fn().mockResolvedValue(existingUser), + }, + }, + }, + }, + } as unknown as DataSources; +} + +test.for(feature, ({ Scenario }) => { + Scenario('Returns a staff user when the external ID exists', ({ Given, When, Then }) => { + let dataSources: DataSources; + let result: Domain.Contexts.User.StaffUser.StaffUserEntityReference | null; + let expectedUser: Domain.Contexts.User.StaffUser.StaffUserEntityReference; + + Given('a staff user with externalId "ext-123" exists in the read repository', () => { + expectedUser = makeMockStaffUserRef('ext-123'); + dataSources = makeDataSources(expectedUser); + }); + + When('I call queryByExternalId with externalId "ext-123"', async () => { + result = await queryByExternalId(dataSources)({ externalId: 'ext-123' }); + }); + + Then('it should return the matching staff user', () => { + expect(result).toBe(expectedUser); + expect(result?.externalId).toBe('ext-123'); + }); + }); + + Scenario('Returns null when no staff user matches the external ID', ({ Given, When, Then }) => { + let dataSources: DataSources; + let result: Domain.Contexts.User.StaffUser.StaffUserEntityReference | null; + + Given('no staff user with externalId "ext-missing" exists in the read repository', () => { + dataSources = makeDataSources(null); + }); + + When('I call queryByExternalId with externalId "ext-missing"', async () => { + result = await queryByExternalId(dataSources)({ externalId: 'ext-missing' }); + }); + + Then('it should return null', () => { + expect(result).toBeNull(); + }); + }); +}); diff --git a/packages/ocom/graphql/src/schema/types/features/staff-user.resolvers.feature b/packages/ocom/graphql/src/schema/types/features/staff-user.resolvers.feature new file mode 100644 index 000000000..265800347 --- /dev/null +++ b/packages/ocom/graphql/src/schema/types/features/staff-user.resolvers.feature @@ -0,0 +1,22 @@ +Feature: Staff User Resolvers + + As an API consumer + I want to query and create staff user entities + So that I can retrieve a staff user or ensure one exists via the GraphQL API + + Scenario: Querying the current staff user and creating if not exists + Given a user with a verifiedJwt in their context + When the currentStaffUserAndCreateIfNotExists query is executed + Then it should call User.StaffUser.createIfNotExists with the JWT claims + And it should return the corresponding StaffUser entity + + Scenario: Querying the current staff user with AAD roles + Given a user with a verifiedJwt that includes AAD roles in their context + When the currentStaffUserAndCreateIfNotExists query is executed + Then it should call User.StaffUser.createIfNotExists with the AAD roles + And it should return the corresponding StaffUser entity + + Scenario: Querying the current staff user with no JWT + Given a user without a verifiedJwt in their context + When the currentStaffUserAndCreateIfNotExists query is executed + Then it should throw an "Unauthorized" error diff --git a/packages/ocom/graphql/src/schema/types/staff-user.resolvers.test.ts b/packages/ocom/graphql/src/schema/types/staff-user.resolvers.test.ts new file mode 100644 index 000000000..dbffd72c2 --- /dev/null +++ b/packages/ocom/graphql/src/schema/types/staff-user.resolvers.test.ts @@ -0,0 +1,191 @@ +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; +import type { Domain } from '@ocom/domain'; +import { type FieldNode, type GraphQLObjectType, type GraphQLResolveInfo, type GraphQLSchema, Kind, type OperationDefinitionNode } from 'graphql'; +import { expect, vi } from 'vitest'; +import type { GraphContext } from '../context.ts'; +import staffUserResolvers from './staff-user.resolvers.ts'; + +const test = { for: describeFeature }; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const feature = await loadFeature(path.resolve(__dirname, 'features/staff-user.resolvers.feature')); + +type StaffUserEntity = Domain.Contexts.User.StaffUser.StaffUserEntityReference; + +function createMockStaffUser(overrides: Partial = {}): StaffUserEntity { + return { + id: 'mock-staff-user-id', + externalId: 'mock-external-id', + firstName: 'Jane', + lastName: 'Smith', + displayName: 'Jane Smith', + email: 'jane@example.com', + accessBlocked: false, + tags: [], + userType: 'staff', + role: undefined, + createdAt: new Date(), + updatedAt: new Date(), + schemaVersion: '1.0', + ...overrides, + } as unknown as StaffUserEntity; +} + +function makeMockInfo(fieldName: string): GraphQLResolveInfo { + const mockFieldNode: FieldNode = { + kind: Kind.FIELD, + name: { kind: Kind.NAME, value: fieldName }, + }; + return { + fieldName, + fieldNodes: [mockFieldNode], + returnType: {} as GraphQLObjectType, + parentType: {} as GraphQLObjectType, + path: { key: fieldName, prev: undefined, typename: undefined }, + schema: {} as GraphQLSchema, + fragments: {}, + rootValue: {}, + operation: {} as OperationDefinitionNode, + variableValues: {}, + } as unknown as GraphQLResolveInfo; +} + +function makeMockGraphContext(overrides: Partial = {}): GraphContext { + return { + applicationServices: { + User: { + StaffUser: { + createIfNotExists: vi.fn(), + queryByExternalId: vi.fn(), + }, + }, + verifiedUser: { + verifiedJwt: { + sub: 'default-user-sub', + given_name: 'Jane', + family_name: 'Smith', + email: 'jane@example.com', + roles: [], + }, + }, + ...overrides.applicationServices, + }, + ...overrides, + } as unknown as GraphContext; +} + +type QueryResolver = ( + parent: object, + args: Record, + context: GraphContext, + info: GraphQLResolveInfo, +) => Promise; + +const callCurrentStaffUserQuery = (context: GraphContext) => + (staffUserResolvers.Query?.currentStaffUserAndCreateIfNotExists as unknown as QueryResolver)( + {}, + {}, + context, + makeMockInfo('currentStaffUserAndCreateIfNotExists'), + ); + +test.for(feature, ({ Scenario, BeforeEachScenario }) => { + let context: GraphContext; + let result: StaffUserEntity | null; + + BeforeEachScenario(() => { + context = makeMockGraphContext(); + vi.clearAllMocks(); + result = null; + }); + + Scenario('Querying the current staff user and creating if not exists', ({ Given, When, Then, And }) => { + const mockStaffUser = createMockStaffUser(); + + Given('a user with a verifiedJwt in their context', () => { + // Already set up in BeforeEachScenario with default jwt + }); + + When('the currentStaffUserAndCreateIfNotExists query is executed', async () => { + vi.mocked(context.applicationServices.User.StaffUser.createIfNotExists).mockResolvedValue(mockStaffUser); + result = await callCurrentStaffUserQuery(context); + }); + + Then('it should call User.StaffUser.createIfNotExists with the JWT claims', () => { + expect(context.applicationServices.User.StaffUser.createIfNotExists).toHaveBeenCalledWith({ + externalId: 'default-user-sub', + firstName: 'Jane', + lastName: 'Smith', + email: 'jane@example.com', + aadRoles: [], + }); + }); + + And('it should return the corresponding StaffUser entity', () => { + expect(result).toEqual(mockStaffUser); + }); + }); + + Scenario('Querying the current staff user with AAD roles', ({ Given, When, Then, And }) => { + const mockStaffUser = createMockStaffUser(); + const aadRoles = ['Staff.CaseManager', 'Staff.Finance']; + + Given('a user with a verifiedJwt that includes AAD roles in their context', () => { + context = makeMockGraphContext({ + applicationServices: { + User: { + StaffUser: { + createIfNotExists: vi.fn(), + queryByExternalId: vi.fn(), + }, + }, + verifiedUser: { + verifiedJwt: { + sub: 'roles-user-sub', + given_name: 'Bob', + family_name: 'Jones', + email: 'bob@example.com', + roles: aadRoles, + }, + }, + } as unknown as GraphContext['applicationServices'], + }); + }); + + When('the currentStaffUserAndCreateIfNotExists query is executed', async () => { + vi.mocked(context.applicationServices.User.StaffUser.createIfNotExists).mockResolvedValue(mockStaffUser); + result = await callCurrentStaffUserQuery(context); + }); + + Then('it should call User.StaffUser.createIfNotExists with the AAD roles', () => { + expect(context.applicationServices.User.StaffUser.createIfNotExists).toHaveBeenCalledWith({ + externalId: 'roles-user-sub', + firstName: 'Bob', + lastName: 'Jones', + email: 'bob@example.com', + aadRoles, + }); + }); + + And('it should return the corresponding StaffUser entity', () => { + expect(result).toEqual(mockStaffUser); + }); + }); + + Scenario('Querying the current staff user with no JWT', ({ Given, When, Then }) => { + Given('a user without a verifiedJwt in their context', () => { + if (context.applicationServices.verifiedUser) { + context.applicationServices.verifiedUser.verifiedJwt = undefined; + } + }); + + When('the currentStaffUserAndCreateIfNotExists query is executed', async () => { + await expect(callCurrentStaffUserQuery(context)).rejects.toThrow('Unauthorized'); + }); + + Then('it should throw an "Unauthorized" error', () => { + // Already asserted in When + }); + }); +}); diff --git a/packages/ocom/persistence/src/datasources/domain/user/staff-role/features/staff-role.domain-adapter.feature b/packages/ocom/persistence/src/datasources/domain/user/staff-role/features/staff-role.domain-adapter.feature index 7b6f611eb..f0646f041 100644 --- a/packages/ocom/persistence/src/datasources/domain/user/staff-role/features/staff-role.domain-adapter.feature +++ b/packages/ocom/persistence/src/datasources/domain/user/staff-role/features/staff-role.domain-adapter.feature @@ -151,4 +151,149 @@ Feature: StaffRoleDomainAdapter And the canAssignTickets property should return false And the canWorkOnTickets property should return false When I set the canCreateTickets property to true - Then the violationTicketPermissions' canCreateTickets should be true \ No newline at end of file + Then the violationTicketPermissions' canCreateTickets should be true + + Scenario: Getting and setting canManageCommunities from communityPermissions + Given a StaffRoleDomainAdapter for the document + When I get the permissions property + And I get the communityPermissions property + And I get the canManageCommunities property + Then it should return false + When I set the canManageCommunities property to true + Then the communityPermissions' canManageCommunities should be true + + Scenario: Getting financePermissions from permissions + Given a StaffRoleDomainAdapter for the document + When I get the permissions property + And I get the financePermissions property + Then it should return a StaffRoleFinancePermissionsAdapter instance + + Scenario: Getting and setting canManageFinance from financePermissions + Given a StaffRoleDomainAdapter for the document + When I get the permissions property + And I get the financePermissions property + Then the canManageFinance property should return false + When I set the canManageFinance property to true + Then the financePermissions' canManageFinance should be true + + Scenario: Getting and setting canViewGLBatchSummaries from financePermissions + Given a StaffRoleDomainAdapter for the document + When I get the permissions property + And I get the financePermissions property + Then the canViewGLBatchSummaries property should return false + When I set the canViewGLBatchSummaries property to true + Then the financePermissions' canViewGLBatchSummaries should be true + + Scenario: Getting and setting canViewFinanceConfigs from financePermissions + Given a StaffRoleDomainAdapter for the document + When I get the permissions property + And I get the financePermissions property + Then the canViewFinanceConfigs property should return false + When I set the canViewFinanceConfigs property to true + Then the financePermissions' canViewFinanceConfigs should be true + + Scenario: Getting and setting canCreateFinanceConfigs from financePermissions + Given a StaffRoleDomainAdapter for the document + When I get the permissions property + And I get the financePermissions property + Then the canCreateFinanceConfigs property should return false + When I set the canCreateFinanceConfigs property to true + Then the financePermissions' canCreateFinanceConfigs should be true + + Scenario: Getting techAdminPermissions from permissions + Given a StaffRoleDomainAdapter for the document + When I get the permissions property + And I get the techAdminPermissions property + Then it should return a StaffRoleTechAdminPermissionsAdapter instance + + Scenario: Getting and setting canManageTechAdmin from techAdminPermissions + Given a StaffRoleDomainAdapter for the document + When I get the permissions property + And I get the techAdminPermissions property + Then the canManageTechAdmin property should return false + When I set the canManageTechAdmin property to true + Then the techAdminPermissions' canManageTechAdmin should be true + + Scenario: Getting and setting canViewDatabaseExplorer from techAdminPermissions + Given a StaffRoleDomainAdapter for the document + When I get the permissions property + And I get the techAdminPermissions property + Then the canViewDatabaseExplorer property should return false + When I set the canViewDatabaseExplorer property to true + Then the techAdminPermissions' canViewDatabaseExplorer should be true + + Scenario: Getting and setting canViewBlobExplorer from techAdminPermissions + Given a StaffRoleDomainAdapter for the document + When I get the permissions property + And I get the techAdminPermissions property + Then the canViewBlobExplorer property should return false + When I set the canViewBlobExplorer property to true + Then the techAdminPermissions' canViewBlobExplorer should be true + + Scenario: Getting and setting canViewQueueDashboard from techAdminPermissions + Given a StaffRoleDomainAdapter for the document + When I get the permissions property + And I get the techAdminPermissions property + Then the canViewQueueDashboard property should return false + When I set the canViewQueueDashboard property to true + Then the techAdminPermissions' canViewQueueDashboard should be true + + Scenario: Getting and setting canSendQueueMessages from techAdminPermissions + Given a StaffRoleDomainAdapter for the document + When I get the permissions property + And I get the techAdminPermissions property + Then the canSendQueueMessages property should return false + When I set the canSendQueueMessages property to true + Then the techAdminPermissions' canSendQueueMessages should be true + + Scenario: Getting userPermissions from permissions + Given a StaffRoleDomainAdapter for the document + When I get the permissions property + And I get the userPermissions property + Then it should return a StaffRoleUserPermissionsAdapter instance + + Scenario: Getting and setting canManageUsers from userPermissions + Given a StaffRoleDomainAdapter for the document + When I get the permissions property + And I get the userPermissions property + Then the canManageUsers property should return false + When I set the canManageUsers property to true + Then the userPermissions' canManageUsers should be true + + Scenario: Lazy-initialising permissions when document has no permissions object + Given a StaffRoleDomainAdapter wrapping a document with no permissions object + When I get the permissions property + Then it should return a StaffRolePermissionsAdapter instance + + Scenario: Lazy-initialising communityPermissions when sub-document is absent + Given a StaffRoleDomainAdapter wrapping a document with no communityPermissions sub-document + When I get the permissions property + And I get the communityPermissions property + Then it should return a StaffRoleCommunityPermissionsAdapter instance + And canManageCommunities should default to false + + Scenario: Lazy-initialising financePermissions when sub-document is absent + Given a StaffRoleDomainAdapter wrapping a document with no financePermissions sub-document + When I get the permissions property + And I get the financePermissions property + Then it should return a StaffRoleFinancePermissionsAdapter instance + And canManageFinance should default to false + + Scenario: Lazy-initialising techAdminPermissions when sub-document is absent + Given a StaffRoleDomainAdapter wrapping a document with no techAdminPermissions sub-document + When I get the permissions property + And I get the techAdminPermissions property + Then it should return a StaffRoleTechAdminPermissionsAdapter instance + And canManageTechAdmin should default to false + + Scenario: Lazy-initialising userPermissions when sub-document is absent + Given a StaffRoleDomainAdapter wrapping a document with no userPermissions sub-document + When I get the permissions property + And I get the userPermissions property + Then it should return a StaffRoleUserPermissionsAdapter instance + And canManageUsers should default to false + + Scenario: Getting roleType returns null when document roleType is undefined + Given a StaffRoleDomainAdapter wrapping a document with no roleType + When I get the roleType property + Then it should return null \ No newline at end of file diff --git a/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.test.ts b/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.test.ts index 8f7abbf56..924cb4202 100644 --- a/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.test.ts +++ b/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.test.ts @@ -15,6 +15,9 @@ import { StaffRoleServicePermissionsAdapter, StaffRoleServiceTicketPermissionsAdapter, StaffRoleViolationTicketPermissionsAdapter, + StaffRoleFinancePermissionsAdapter, + StaffRoleTechAdminPermissionsAdapter, + StaffRoleUserPermissionsAdapter, } from './staff-role.domain-adapter.ts'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); @@ -498,6 +501,443 @@ test.for(domainAdapterFeature, ({ Scenario, Background, BeforeEachScenario }) => expect(doc.permissions?.violationTicketPermissions?.canCreateTickets).toBe(true); }); }); + + // ─── canManageCommunities ───────────────────────────────────────────────── + + Scenario('Getting and setting canManageCommunities from communityPermissions', ({ Given, When, And, Then }) => { + let permissions: StaffRolePermissionsAdapter; + let communityPermissions: StaffRoleCommunityPermissionsAdapter; + Given('a StaffRoleDomainAdapter for the document', () => { + adapter = new StaffRoleDomainAdapter(doc); + }); + When('I get the permissions property', () => { + permissions = adapter.permissions as StaffRolePermissionsAdapter; + }); + And('I get the communityPermissions property', () => { + communityPermissions = permissions.communityPermissions as StaffRoleCommunityPermissionsAdapter; + }); + And('I get the canManageCommunities property', () => { + result = communityPermissions.canManageCommunities; + }); + Then('it should return false', () => { + expect(result).toBe(false); + }); + When('I set the canManageCommunities property to true', () => { + communityPermissions.canManageCommunities = true; + }); + Then("the communityPermissions' canManageCommunities should be true", () => { + expect(doc.permissions?.communityPermissions?.canManageCommunities).toBe(true); + }); + }); + + // ─── financePermissions ─────────────────────────────────────────────────── + + Scenario('Getting financePermissions from permissions', ({ Given, When, And, Then }) => { + let permissions: StaffRolePermissionsAdapter; + Given('a StaffRoleDomainAdapter for the document', () => { + adapter = new StaffRoleDomainAdapter(doc); + }); + When('I get the permissions property', () => { + permissions = adapter.permissions as StaffRolePermissionsAdapter; + }); + And('I get the financePermissions property', () => { + result = permissions.financePermissions; + }); + Then('it should return a StaffRoleFinancePermissionsAdapter instance', () => { + expect(result).toBeInstanceOf(StaffRoleFinancePermissionsAdapter); + }); + }); + + Scenario('Getting and setting canManageFinance from financePermissions', ({ Given, When, And, Then }) => { + let permissions: StaffRolePermissionsAdapter; + let financePermissions: StaffRoleFinancePermissionsAdapter; + Given('a StaffRoleDomainAdapter for the document', () => { + adapter = new StaffRoleDomainAdapter(doc); + }); + When('I get the permissions property', () => { + permissions = adapter.permissions as StaffRolePermissionsAdapter; + }); + And('I get the financePermissions property', () => { + financePermissions = permissions.financePermissions as StaffRoleFinancePermissionsAdapter; + }); + Then('the canManageFinance property should return false', () => { + expect(financePermissions.canManageFinance).toBe(false); + }); + When('I set the canManageFinance property to true', () => { + financePermissions.canManageFinance = true; + }); + Then("the financePermissions' canManageFinance should be true", () => { + expect(doc.permissions?.financePermissions?.canManageFinance).toBe(true); + }); + }); + + Scenario('Getting and setting canViewGLBatchSummaries from financePermissions', ({ Given, When, And, Then }) => { + let permissions: StaffRolePermissionsAdapter; + let financePermissions: StaffRoleFinancePermissionsAdapter; + Given('a StaffRoleDomainAdapter for the document', () => { + adapter = new StaffRoleDomainAdapter(doc); + }); + When('I get the permissions property', () => { + permissions = adapter.permissions as StaffRolePermissionsAdapter; + }); + And('I get the financePermissions property', () => { + financePermissions = permissions.financePermissions as StaffRoleFinancePermissionsAdapter; + }); + Then('the canViewGLBatchSummaries property should return false', () => { + expect(financePermissions.canViewGLBatchSummaries).toBe(false); + }); + When('I set the canViewGLBatchSummaries property to true', () => { + financePermissions.canViewGLBatchSummaries = true; + }); + Then("the financePermissions' canViewGLBatchSummaries should be true", () => { + expect(doc.permissions?.financePermissions?.canViewGLBatchSummaries).toBe(true); + }); + }); + + Scenario('Getting and setting canViewFinanceConfigs from financePermissions', ({ Given, When, And, Then }) => { + let permissions: StaffRolePermissionsAdapter; + let financePermissions: StaffRoleFinancePermissionsAdapter; + Given('a StaffRoleDomainAdapter for the document', () => { + adapter = new StaffRoleDomainAdapter(doc); + }); + When('I get the permissions property', () => { + permissions = adapter.permissions as StaffRolePermissionsAdapter; + }); + And('I get the financePermissions property', () => { + financePermissions = permissions.financePermissions as StaffRoleFinancePermissionsAdapter; + }); + Then('the canViewFinanceConfigs property should return false', () => { + expect(financePermissions.canViewFinanceConfigs).toBe(false); + }); + When('I set the canViewFinanceConfigs property to true', () => { + financePermissions.canViewFinanceConfigs = true; + }); + Then("the financePermissions' canViewFinanceConfigs should be true", () => { + expect(doc.permissions?.financePermissions?.canViewFinanceConfigs).toBe(true); + }); + }); + + Scenario('Getting and setting canCreateFinanceConfigs from financePermissions', ({ Given, When, And, Then }) => { + let permissions: StaffRolePermissionsAdapter; + let financePermissions: StaffRoleFinancePermissionsAdapter; + Given('a StaffRoleDomainAdapter for the document', () => { + adapter = new StaffRoleDomainAdapter(doc); + }); + When('I get the permissions property', () => { + permissions = adapter.permissions as StaffRolePermissionsAdapter; + }); + And('I get the financePermissions property', () => { + financePermissions = permissions.financePermissions as StaffRoleFinancePermissionsAdapter; + }); + Then('the canCreateFinanceConfigs property should return false', () => { + expect(financePermissions.canCreateFinanceConfigs).toBe(false); + }); + When('I set the canCreateFinanceConfigs property to true', () => { + financePermissions.canCreateFinanceConfigs = true; + }); + Then("the financePermissions' canCreateFinanceConfigs should be true", () => { + expect(doc.permissions?.financePermissions?.canCreateFinanceConfigs).toBe(true); + }); + }); + + // ─── techAdminPermissions ───────────────────────────────────────────────── + + Scenario('Getting techAdminPermissions from permissions', ({ Given, When, And, Then }) => { + let permissions: StaffRolePermissionsAdapter; + Given('a StaffRoleDomainAdapter for the document', () => { + adapter = new StaffRoleDomainAdapter(doc); + }); + When('I get the permissions property', () => { + permissions = adapter.permissions as StaffRolePermissionsAdapter; + }); + And('I get the techAdminPermissions property', () => { + result = permissions.techAdminPermissions; + }); + Then('it should return a StaffRoleTechAdminPermissionsAdapter instance', () => { + expect(result).toBeInstanceOf(StaffRoleTechAdminPermissionsAdapter); + }); + }); + + Scenario('Getting and setting canManageTechAdmin from techAdminPermissions', ({ Given, When, And, Then }) => { + let permissions: StaffRolePermissionsAdapter; + let techAdminPermissions: StaffRoleTechAdminPermissionsAdapter; + Given('a StaffRoleDomainAdapter for the document', () => { + adapter = new StaffRoleDomainAdapter(doc); + }); + When('I get the permissions property', () => { + permissions = adapter.permissions as StaffRolePermissionsAdapter; + }); + And('I get the techAdminPermissions property', () => { + techAdminPermissions = permissions.techAdminPermissions as StaffRoleTechAdminPermissionsAdapter; + }); + Then('the canManageTechAdmin property should return false', () => { + expect(techAdminPermissions.canManageTechAdmin).toBe(false); + }); + When('I set the canManageTechAdmin property to true', () => { + techAdminPermissions.canManageTechAdmin = true; + }); + Then("the techAdminPermissions' canManageTechAdmin should be true", () => { + expect(doc.permissions?.techAdminPermissions?.canManageTechAdmin).toBe(true); + }); + }); + + Scenario('Getting and setting canViewDatabaseExplorer from techAdminPermissions', ({ Given, When, And, Then }) => { + let permissions: StaffRolePermissionsAdapter; + let techAdminPermissions: StaffRoleTechAdminPermissionsAdapter; + Given('a StaffRoleDomainAdapter for the document', () => { + adapter = new StaffRoleDomainAdapter(doc); + }); + When('I get the permissions property', () => { + permissions = adapter.permissions as StaffRolePermissionsAdapter; + }); + And('I get the techAdminPermissions property', () => { + techAdminPermissions = permissions.techAdminPermissions as StaffRoleTechAdminPermissionsAdapter; + }); + Then('the canViewDatabaseExplorer property should return false', () => { + expect(techAdminPermissions.canViewDatabaseExplorer).toBe(false); + }); + When('I set the canViewDatabaseExplorer property to true', () => { + techAdminPermissions.canViewDatabaseExplorer = true; + }); + Then("the techAdminPermissions' canViewDatabaseExplorer should be true", () => { + expect(doc.permissions?.techAdminPermissions?.canViewDatabaseExplorer).toBe(true); + }); + }); + + Scenario('Getting and setting canViewBlobExplorer from techAdminPermissions', ({ Given, When, And, Then }) => { + let permissions: StaffRolePermissionsAdapter; + let techAdminPermissions: StaffRoleTechAdminPermissionsAdapter; + Given('a StaffRoleDomainAdapter for the document', () => { + adapter = new StaffRoleDomainAdapter(doc); + }); + When('I get the permissions property', () => { + permissions = adapter.permissions as StaffRolePermissionsAdapter; + }); + And('I get the techAdminPermissions property', () => { + techAdminPermissions = permissions.techAdminPermissions as StaffRoleTechAdminPermissionsAdapter; + }); + Then('the canViewBlobExplorer property should return false', () => { + expect(techAdminPermissions.canViewBlobExplorer).toBe(false); + }); + When('I set the canViewBlobExplorer property to true', () => { + techAdminPermissions.canViewBlobExplorer = true; + }); + Then("the techAdminPermissions' canViewBlobExplorer should be true", () => { + expect(doc.permissions?.techAdminPermissions?.canViewBlobExplorer).toBe(true); + }); + }); + + Scenario('Getting and setting canViewQueueDashboard from techAdminPermissions', ({ Given, When, And, Then }) => { + let permissions: StaffRolePermissionsAdapter; + let techAdminPermissions: StaffRoleTechAdminPermissionsAdapter; + Given('a StaffRoleDomainAdapter for the document', () => { + adapter = new StaffRoleDomainAdapter(doc); + }); + When('I get the permissions property', () => { + permissions = adapter.permissions as StaffRolePermissionsAdapter; + }); + And('I get the techAdminPermissions property', () => { + techAdminPermissions = permissions.techAdminPermissions as StaffRoleTechAdminPermissionsAdapter; + }); + Then('the canViewQueueDashboard property should return false', () => { + expect(techAdminPermissions.canViewQueueDashboard).toBe(false); + }); + When('I set the canViewQueueDashboard property to true', () => { + techAdminPermissions.canViewQueueDashboard = true; + }); + Then("the techAdminPermissions' canViewQueueDashboard should be true", () => { + expect(doc.permissions?.techAdminPermissions?.canViewQueueDashboard).toBe(true); + }); + }); + + Scenario('Getting and setting canSendQueueMessages from techAdminPermissions', ({ Given, When, And, Then }) => { + let permissions: StaffRolePermissionsAdapter; + let techAdminPermissions: StaffRoleTechAdminPermissionsAdapter; + Given('a StaffRoleDomainAdapter for the document', () => { + adapter = new StaffRoleDomainAdapter(doc); + }); + When('I get the permissions property', () => { + permissions = adapter.permissions as StaffRolePermissionsAdapter; + }); + And('I get the techAdminPermissions property', () => { + techAdminPermissions = permissions.techAdminPermissions as StaffRoleTechAdminPermissionsAdapter; + }); + Then('the canSendQueueMessages property should return false', () => { + expect(techAdminPermissions.canSendQueueMessages).toBe(false); + }); + When('I set the canSendQueueMessages property to true', () => { + techAdminPermissions.canSendQueueMessages = true; + }); + Then("the techAdminPermissions' canSendQueueMessages should be true", () => { + expect(doc.permissions?.techAdminPermissions?.canSendQueueMessages).toBe(true); + }); + }); + + // ─── userPermissions ────────────────────────────────────────────────────── + + Scenario('Getting userPermissions from permissions', ({ Given, When, And, Then }) => { + let permissions: StaffRolePermissionsAdapter; + Given('a StaffRoleDomainAdapter for the document', () => { + adapter = new StaffRoleDomainAdapter(doc); + }); + When('I get the permissions property', () => { + permissions = adapter.permissions as StaffRolePermissionsAdapter; + }); + And('I get the userPermissions property', () => { + result = permissions.userPermissions; + }); + Then('it should return a StaffRoleUserPermissionsAdapter instance', () => { + expect(result).toBeInstanceOf(StaffRoleUserPermissionsAdapter); + }); + }); + + Scenario('Getting and setting canManageUsers from userPermissions', ({ Given, When, And, Then }) => { + let permissions: StaffRolePermissionsAdapter; + let userPermissions: StaffRoleUserPermissionsAdapter; + Given('a StaffRoleDomainAdapter for the document', () => { + adapter = new StaffRoleDomainAdapter(doc); + }); + When('I get the permissions property', () => { + permissions = adapter.permissions as StaffRolePermissionsAdapter; + }); + And('I get the userPermissions property', () => { + userPermissions = permissions.userPermissions as StaffRoleUserPermissionsAdapter; + }); + Then('the canManageUsers property should return false', () => { + expect(userPermissions.canManageUsers).toBe(false); + }); + When('I set the canManageUsers property to true', () => { + userPermissions.canManageUsers = true; + }); + Then("the userPermissions' canManageUsers should be true", () => { + expect(doc.permissions?.userPermissions?.canManageUsers).toBe(true); + }); + }); + + // ─── Lazy-init paths ────────────────────────────────────────────────────── + + Scenario('Lazy-initialising permissions when document has no permissions object', ({ Given, When, Then }) => { + Given('a StaffRoleDomainAdapter wrapping a document with no permissions object', () => { + const docWithoutPermissions = makeStaffRoleDoc(); + docWithoutPermissions.set = vi.fn().mockImplementation((key: string, value: unknown) => { + (docWithoutPermissions as unknown as Record)[key] = value; + }); + (docWithoutPermissions as unknown as Record)['permissions'] = undefined; + adapter = new StaffRoleDomainAdapter(docWithoutPermissions); + }); + When('I get the permissions property', () => { + result = adapter.permissions; + }); + Then('it should return a StaffRolePermissionsAdapter instance', () => { + expect(result).toBeInstanceOf(StaffRolePermissionsAdapter); + }); + }); + + Scenario('Lazy-initialising communityPermissions when sub-document is absent', ({ Given, When, And, Then }) => { + let permissions: StaffRolePermissionsAdapter; + Given('a StaffRoleDomainAdapter wrapping a document with no communityPermissions sub-document', () => { + const docWithout = makeStaffRoleDoc(); + if (docWithout.permissions) { + (docWithout.permissions as unknown as Record)['communityPermissions'] = undefined; + } + adapter = new StaffRoleDomainAdapter(docWithout); + }); + When('I get the permissions property', () => { + permissions = adapter.permissions as StaffRolePermissionsAdapter; + }); + And('I get the communityPermissions property', () => { + result = permissions.communityPermissions; + }); + Then('it should return a StaffRoleCommunityPermissionsAdapter instance', () => { + expect(result).toBeInstanceOf(StaffRoleCommunityPermissionsAdapter); + }); + And('canManageCommunities should default to false', () => { + expect((result as StaffRoleCommunityPermissionsAdapter).canManageCommunities).toBe(false); + }); + }); + + Scenario('Lazy-initialising financePermissions when sub-document is absent', ({ Given, When, And, Then }) => { + let permissions: StaffRolePermissionsAdapter; + Given('a StaffRoleDomainAdapter wrapping a document with no financePermissions sub-document', () => { + const docWithout = makeStaffRoleDoc(); + if (docWithout.permissions) { + (docWithout.permissions as unknown as Record)['financePermissions'] = undefined; + } + adapter = new StaffRoleDomainAdapter(docWithout); + }); + When('I get the permissions property', () => { + permissions = adapter.permissions as StaffRolePermissionsAdapter; + }); + And('I get the financePermissions property', () => { + result = permissions.financePermissions; + }); + Then('it should return a StaffRoleFinancePermissionsAdapter instance', () => { + expect(result).toBeInstanceOf(StaffRoleFinancePermissionsAdapter); + }); + And('canManageFinance should default to false', () => { + expect((result as StaffRoleFinancePermissionsAdapter).canManageFinance).toBe(false); + }); + }); + + Scenario('Lazy-initialising techAdminPermissions when sub-document is absent', ({ Given, When, And, Then }) => { + let permissions: StaffRolePermissionsAdapter; + Given('a StaffRoleDomainAdapter wrapping a document with no techAdminPermissions sub-document', () => { + const docWithout = makeStaffRoleDoc(); + if (docWithout.permissions) { + (docWithout.permissions as unknown as Record)['techAdminPermissions'] = undefined; + } + adapter = new StaffRoleDomainAdapter(docWithout); + }); + When('I get the permissions property', () => { + permissions = adapter.permissions as StaffRolePermissionsAdapter; + }); + And('I get the techAdminPermissions property', () => { + result = permissions.techAdminPermissions; + }); + Then('it should return a StaffRoleTechAdminPermissionsAdapter instance', () => { + expect(result).toBeInstanceOf(StaffRoleTechAdminPermissionsAdapter); + }); + And('canManageTechAdmin should default to false', () => { + expect((result as StaffRoleTechAdminPermissionsAdapter).canManageTechAdmin).toBe(false); + }); + }); + + Scenario('Lazy-initialising userPermissions when sub-document is absent', ({ Given, When, And, Then }) => { + let permissions: StaffRolePermissionsAdapter; + Given('a StaffRoleDomainAdapter wrapping a document with no userPermissions sub-document', () => { + const docWithout = makeStaffRoleDoc(); + if (docWithout.permissions) { + (docWithout.permissions as unknown as Record)['userPermissions'] = undefined; + } + adapter = new StaffRoleDomainAdapter(docWithout); + }); + When('I get the permissions property', () => { + permissions = adapter.permissions as StaffRolePermissionsAdapter; + }); + And('I get the userPermissions property', () => { + result = permissions.userPermissions; + }); + Then('it should return a StaffRoleUserPermissionsAdapter instance', () => { + expect(result).toBeInstanceOf(StaffRoleUserPermissionsAdapter); + }); + And('canManageUsers should default to false', () => { + expect((result as StaffRoleUserPermissionsAdapter).canManageUsers).toBe(false); + }); + }); + + Scenario('Getting roleType returns null when document roleType is undefined', ({ Given, When, Then }) => { + Given('a StaffRoleDomainAdapter wrapping a document with no roleType', () => { + const docWithout = makeStaffRoleDoc(); + (docWithout as unknown as Record)['roleType'] = undefined; + adapter = new StaffRoleDomainAdapter(docWithout); + }); + When('I get the roleType property', () => { + result = adapter.roleType; + }); + Then('it should return null', () => { + expect(result).toBeNull(); + }); + }); }); test.for(typeConverterFeature, ({ Scenario, Background, BeforeEachScenario }) => { diff --git a/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.ts b/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.ts index b66459b8c..bef4efeeb 100644 --- a/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.ts +++ b/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.ts @@ -316,7 +316,7 @@ export class StaffRoleViolationTicketPermissionsAdapter implements Domain.Contex } } -class StaffRoleFinancePermissionsAdapter implements Domain.Contexts.User.StaffRole.StaffRoleFinancePermissionsProps { +export class StaffRoleFinancePermissionsAdapter implements Domain.Contexts.User.StaffRole.StaffRoleFinancePermissionsProps { private readonly doc: StaffRoleFinancePermissions; constructor(permissions: StaffRoleFinancePermissions) { @@ -360,7 +360,7 @@ class StaffRoleFinancePermissionsAdapter implements Domain.Contexts.User.StaffRo } } -class StaffRoleTechAdminPermissionsAdapter implements Domain.Contexts.User.StaffRole.StaffRoleTechAdminPermissionsProps { +export class StaffRoleTechAdminPermissionsAdapter implements Domain.Contexts.User.StaffRole.StaffRoleTechAdminPermissionsProps { private readonly doc: StaffRoleTechAdminPermissions; constructor(permissions: StaffRoleTechAdminPermissions) { @@ -411,7 +411,7 @@ class StaffRoleTechAdminPermissionsAdapter implements Domain.Contexts.User.Staff } } -class StaffRoleUserPermissionsAdapter implements Domain.Contexts.User.StaffRole.StaffRoleUserPermissionsProps { +export class StaffRoleUserPermissionsAdapter implements Domain.Contexts.User.StaffRole.StaffRoleUserPermissionsProps { private readonly doc: StaffRoleUserPermissions; constructor(permissions: StaffRoleUserPermissions) { diff --git a/packages/ocom/persistence/src/datasources/readonly/user/staff-user/features/staff-user.read-repository.feature b/packages/ocom/persistence/src/datasources/readonly/user/staff-user/features/staff-user.read-repository.feature new file mode 100644 index 000000000..9aa56131b --- /dev/null +++ b/packages/ocom/persistence/src/datasources/readonly/user/staff-user/features/staff-user.read-repository.feature @@ -0,0 +1,23 @@ +Feature: StaffUserReadRepository + + Scenario: Creating StaffUserReadRepository throws when StaffUser model is missing + Given models context does not contain a StaffUser model + When I call getStaffUserReadRepository with those models and a passport + Then it should throw an error with message "StaffUser model is not available in the mongoose context" + + Scenario: Creating StaffUserReadRepository succeeds when StaffUser model is present + Given models context contains a StaffUser model + When I call getStaffUserReadRepository with those models and a passport + Then I should receive a StaffUserReadRepository instance + And the repository should have a getByExternalId method + + Scenario: getByExternalId returns entity when document is found + Given a StaffUser document exists with externalId "ext-abc" + When I call getByExternalId with "ext-abc" + Then I should receive a StaffUserEntityReference object + And the converter toDomain should have been called with the document and passport + + Scenario: getByExternalId returns null when no document is found + Given no StaffUser document exists with externalId "missing-ext" + When I call getByExternalId with "missing-ext" + Then I should receive null diff --git a/packages/ocom/persistence/src/datasources/readonly/user/staff-user/staff-user.read-repository.test.ts b/packages/ocom/persistence/src/datasources/readonly/user/staff-user/staff-user.read-repository.test.ts new file mode 100644 index 000000000..c317f0709 --- /dev/null +++ b/packages/ocom/persistence/src/datasources/readonly/user/staff-user/staff-user.read-repository.test.ts @@ -0,0 +1,141 @@ +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; +import { expect, vi } from 'vitest'; + +import type { Domain } from '@ocom/domain'; +import type { StaffUser, StaffUserModelType } from '@ocom/data-sources-mongoose-models/user/staff-user'; +import type { ModelsContext } from '../../../../index.ts'; +import { StaffUserConverter } from '../../../domain/user/staff-user/staff-user.domain-adapter.ts'; +import { getStaffUserReadRepository } from './staff-user.read-repository.ts'; +import type { StaffUserReadRepository } from './staff-user.read-repository.ts'; + +const test = { for: describeFeature }; + +vi.mock('../../../domain/user/staff-user/staff-user.domain-adapter.ts', () => ({ + StaffUserConverter: vi.fn(), +})); + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const feature = await loadFeature(path.resolve(__dirname, 'features/staff-user.read-repository.feature')); + +function makeMockPassport() { + return { + user: { + forStaffUser: vi.fn(() => ({ + determineIf: vi.fn(() => true), + })), + }, + } as unknown as Domain.Passport; +} + +function makeMockStaffUserDocument() { + return { + _id: 'doc-id', + id: 'doc-id', + externalId: 'ext-abc', + firstName: 'Alice', + lastName: 'Smith', + email: 'alice@example.com', + } as unknown as StaffUser; +} + +function makeMockModel(doc: StaffUser | null) { + return { + findOne: vi.fn().mockReturnValue({ + populate: vi.fn().mockReturnValue({ + exec: vi.fn().mockResolvedValue(doc), + }), + }), + } as unknown as StaffUserModelType; +} + +test.for(feature, ({ Scenario, BeforeEachScenario }) => { + let models: ModelsContext; + let passport: Domain.Passport; + let repository: StaffUserReadRepository; + let mockStaffUserDoc: StaffUser; + let result: Domain.Contexts.User.StaffUser.StaffUserEntityReference | null | unknown; + let mockConverter: { toDomain: ReturnType }; + let thrownError: unknown; + + BeforeEachScenario(() => { + passport = makeMockPassport(); + mockStaffUserDoc = makeMockStaffUserDocument(); + thrownError = undefined; + result = undefined; + + mockConverter = { + toDomain: vi.fn((_doc: StaffUser, _passport: Domain.Passport) => ({ + id: mockStaffUserDoc.id, + externalId: mockStaffUserDoc.externalId, + })), + }; + + vi.mocked(StaffUserConverter).mockImplementation(function MockStaffUserConverter() { + return mockConverter as unknown as StaffUserConverter; + }); + }); + + Scenario('Creating StaffUserReadRepository throws when StaffUser model is missing', ({ Given, When, Then }) => { + Given('models context does not contain a StaffUser model', () => { + models = {} as ModelsContext; + }); + When('I call getStaffUserReadRepository with those models and a passport', () => { + try { + repository = getStaffUserReadRepository(models, passport); + } catch (err) { + thrownError = err; + } + }); + Then('it should throw an error with message "StaffUser model is not available in the mongoose context"', () => { + expect(thrownError).toBeInstanceOf(Error); + expect((thrownError as Error).message).toBe('StaffUser model is not available in the mongoose context'); + }); + }); + + Scenario('Creating StaffUserReadRepository succeeds when StaffUser model is present', ({ Given, When, Then, And }) => { + Given('models context contains a StaffUser model', () => { + models = { StaffUser: makeMockModel(mockStaffUserDoc) } as unknown as ModelsContext; + }); + When('I call getStaffUserReadRepository with those models and a passport', () => { + repository = getStaffUserReadRepository(models, passport); + }); + Then('I should receive a StaffUserReadRepository instance', () => { + expect(repository).toBeDefined(); + }); + And('the repository should have a getByExternalId method', () => { + expect(typeof repository.getByExternalId).toBe('function'); + }); + }); + + Scenario('getByExternalId returns entity when document is found', ({ Given, When, Then, And }) => { + Given('a StaffUser document exists with externalId "ext-abc"', () => { + models = { StaffUser: makeMockModel(mockStaffUserDoc) } as unknown as ModelsContext; + repository = getStaffUserReadRepository(models, passport); + }); + When('I call getByExternalId with "ext-abc"', async () => { + result = await repository.getByExternalId('ext-abc'); + }); + Then('I should receive a StaffUserEntityReference object', () => { + expect(result).toBeDefined(); + expect(result).not.toBeNull(); + }); + And('the converter toDomain should have been called with the document and passport', () => { + expect(mockConverter.toDomain).toHaveBeenCalledWith(mockStaffUserDoc, passport); + }); + }); + + Scenario('getByExternalId returns null when no document is found', ({ Given, When, Then }) => { + Given('no StaffUser document exists with externalId "missing-ext"', () => { + models = { StaffUser: makeMockModel(null) } as unknown as ModelsContext; + repository = getStaffUserReadRepository(models, passport); + }); + When('I call getByExternalId with "missing-ext"', async () => { + result = await repository.getByExternalId('missing-ext'); + }); + Then('I should receive null', () => { + expect(result).toBeNull(); + }); + }); +}); From 56324cb95c5a2a9ac9c32d59e3c9e75ed05aa7de Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Fri, 8 May 2026 19:58:17 +0530 Subject: [PATCH 56/88] refactor: Simplify function definitions and improve readability in tests --- .../staff-role/create-default-roles.test.ts | 21 +++--------- .../staff-user/create-if-not-exists.test.ts | 32 ++++++++----------- .../schema/types/staff-user.resolvers.test.ts | 17 ++-------- 3 files changed, 21 insertions(+), 49 deletions(-) diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts index 77e66e1a5..01ebdb942 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts @@ -38,10 +38,7 @@ function makeMockStaffRole( } as unknown as Domain.Contexts.User.StaffRole.StaffRole; } -function makeMockRepo( - existingRoleNames: string[] = [], - overrides: Partial = {}, -): StaffRoleRepo { +function makeMockRepo(existingRoleNames: string[] = [], overrides: Partial = {}): StaffRoleRepo { const savedRoles: Domain.Contexts.User.StaffRole.StaffRole[] = []; return { @@ -178,9 +175,7 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { capturedRoles.set(roleName, role); return Promise.resolve(role); }), - save: vi.fn().mockImplementation((role: Domain.Contexts.User.StaffRole.StaffRole) => - Promise.resolve(role as Domain.Contexts.User.StaffRole.StaffRoleEntityReference), - ), + save: vi.fn().mockImplementation((role: Domain.Contexts.User.StaffRole.StaffRole) => Promise.resolve(role as Domain.Contexts.User.StaffRole.StaffRoleEntityReference)), } as unknown as typeof mockRepo; dataSources = makeDataSources(mockRepo); }); @@ -224,9 +219,7 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { capturedRoles.set(roleName, role); return Promise.resolve(role); }), - save: vi.fn().mockImplementation((role: Domain.Contexts.User.StaffRole.StaffRole) => - Promise.resolve(role as Domain.Contexts.User.StaffRole.StaffRoleEntityReference), - ), + save: vi.fn().mockImplementation((role: Domain.Contexts.User.StaffRole.StaffRole) => Promise.resolve(role as Domain.Contexts.User.StaffRole.StaffRoleEntityReference)), } as unknown as typeof mockRepo; dataSources = makeDataSources(mockRepo); }); @@ -270,9 +263,7 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { capturedRoles.set(roleName, role); return Promise.resolve(role); }), - save: vi.fn().mockImplementation((role: Domain.Contexts.User.StaffRole.StaffRole) => - Promise.resolve(role as Domain.Contexts.User.StaffRole.StaffRoleEntityReference), - ), + save: vi.fn().mockImplementation((role: Domain.Contexts.User.StaffRole.StaffRole) => Promise.resolve(role as Domain.Contexts.User.StaffRole.StaffRoleEntityReference)), } as unknown as typeof mockRepo; dataSources = makeDataSources(mockRepo); }); @@ -316,9 +307,7 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { capturedRoles.set(roleName, role); return Promise.resolve(role); }), - save: vi.fn().mockImplementation((role: Domain.Contexts.User.StaffRole.StaffRole) => - Promise.resolve(role as Domain.Contexts.User.StaffRole.StaffRoleEntityReference), - ), + save: vi.fn().mockImplementation((role: Domain.Contexts.User.StaffRole.StaffRole) => Promise.resolve(role as Domain.Contexts.User.StaffRole.StaffRoleEntityReference)), } as unknown as typeof mockRepo; dataSources = makeDataSources(mockRepo); }); diff --git a/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.test.ts b/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.test.ts index 9f866d775..54f6d9106 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.test.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.test.ts @@ -90,9 +90,7 @@ function makeDataSources(overrides: { const staffUserRepo = { getByExternalId: vi.fn().mockResolvedValue(overrides.existingUser ?? null), getNewInstance: vi.fn().mockResolvedValue(newUser), - save: overrides.saveShouldFail - ? vi.fn().mockResolvedValue(undefined) - : vi.fn().mockResolvedValue(savedUser), + save: overrides.saveShouldFail ? vi.fn().mockResolvedValue(undefined) : vi.fn().mockResolvedValue(savedUser), delete: vi.fn(), } as unknown as Domain.Contexts.User.StaffUser.StaffUserRepository; @@ -103,9 +101,7 @@ function makeDataSources(overrides: { } return Promise.reject(new Error(`NotFoundError: ${name} not found`)); }), - getNewInstance: vi.fn().mockImplementation((name: string) => - Promise.resolve(makeMockStaffRoleRef(name)), - ), + getNewInstance: vi.fn().mockImplementation((name: string) => Promise.resolve(makeMockStaffRoleRef(name))), save: vi.fn().mockImplementation((r: unknown) => Promise.resolve(r)), } as unknown as Domain.Contexts.User.StaffRole.StaffRoleRepository; @@ -123,20 +119,16 @@ function makeDataSources(overrides: { User: { StaffUser: { StaffUserUnitOfWork: { - withScopedTransaction: vi.fn().mockImplementation( - async (cb: (repo: typeof staffUserRepo) => Promise) => { - await cb(staffUserRepo); - }, - ), + withScopedTransaction: vi.fn().mockImplementation(async (cb: (repo: typeof staffUserRepo) => Promise) => { + await cb(staffUserRepo); + }), }, }, StaffRole: { StaffRoleUnitOfWork: { - withScopedTransaction: vi.fn().mockImplementation( - async (cb: (repo: typeof staffRoleRepo) => Promise) => { - await cb(staffRoleRepo); - }, - ), + withScopedTransaction: vi.fn().mockImplementation(async (cb: (repo: typeof staffRoleRepo) => Promise) => { + await cb(staffRoleRepo); + }), }, }, }, @@ -211,9 +203,11 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { }); Then('it should call createDefaultRoles', () => { - const roleUow = (dataSources as unknown as { - domainDataSource: { User: { StaffRole: { StaffRoleUnitOfWork: { withScopedTransaction: ReturnType } } } }; - }).domainDataSource.User.StaffRole.StaffRoleUnitOfWork; + const roleUow = ( + dataSources as unknown as { + domainDataSource: { User: { StaffRole: { StaffRoleUnitOfWork: { withScopedTransaction: ReturnType } } } }; + } + ).domainDataSource.User.StaffRole.StaffRoleUnitOfWork; expect(roleUow.withScopedTransaction).toHaveBeenCalled(); }); diff --git a/packages/ocom/graphql/src/schema/types/staff-user.resolvers.test.ts b/packages/ocom/graphql/src/schema/types/staff-user.resolvers.test.ts index dbffd72c2..66b97abcf 100644 --- a/packages/ocom/graphql/src/schema/types/staff-user.resolvers.test.ts +++ b/packages/ocom/graphql/src/schema/types/staff-user.resolvers.test.ts @@ -75,20 +75,9 @@ function makeMockGraphContext(overrides: Partial = {}): GraphConte } as unknown as GraphContext; } -type QueryResolver = ( - parent: object, - args: Record, - context: GraphContext, - info: GraphQLResolveInfo, -) => Promise; - -const callCurrentStaffUserQuery = (context: GraphContext) => - (staffUserResolvers.Query?.currentStaffUserAndCreateIfNotExists as unknown as QueryResolver)( - {}, - {}, - context, - makeMockInfo('currentStaffUserAndCreateIfNotExists'), - ); +type QueryResolver = (parent: object, args: Record, context: GraphContext, info: GraphQLResolveInfo) => Promise; + +const callCurrentStaffUserQuery = (context: GraphContext) => (staffUserResolvers.Query?.currentStaffUserAndCreateIfNotExists as unknown as QueryResolver)({}, {}, context, makeMockInfo('currentStaffUserAndCreateIfNotExists')); test.for(feature, ({ Scenario, BeforeEachScenario }) => { let context: GraphContext; From 7a817015303dca954e1b110807e287203d0acecd Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Fri, 8 May 2026 20:01:31 +0530 Subject: [PATCH 57/88] Refactor code structure for improved readability and maintainability --- .../ui-staff-shared/src/staff-route-shell.tsx | 1 - pnpm-lock.yaml | 263 ++---------------- 2 files changed, 17 insertions(+), 247 deletions(-) diff --git a/packages/ocom/ui-staff-shared/src/staff-route-shell.tsx b/packages/ocom/ui-staff-shared/src/staff-route-shell.tsx index d93b20a73..9d96be083 100644 --- a/packages/ocom/ui-staff-shared/src/staff-route-shell.tsx +++ b/packages/ocom/ui-staff-shared/src/staff-route-shell.tsx @@ -2,7 +2,6 @@ import { DashboardOutlined } from '@ant-design/icons'; import type { PageLayoutProps } from '@ocom/ui-shared'; import { createContext, type FC, type ReactNode, useContext, useMemo } from 'react'; import { SectionLayout, type SectionLayoutProps } from './section-layout.tsx'; -import { extractRoles, staffRouteRoles } from './staff-app-roles.ts'; export interface StaffRouteShellProps { title: string; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3a86ffcee..700f84c90 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -932,25 +932,25 @@ importers: version: link:../config-vitest '@chromatic-com/storybook': specifier: ^4.1.1 - version: 4.1.3(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) + version: 4.1.3(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) '@storybook/addon-a11y': specifier: ^9.1.3 - version: 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) + version: 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) '@storybook/addon-docs': specifier: ^9.1.3 - version: 9.1.16(@types/react@19.2.7)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) + version: 9.1.16(@types/react@19.2.7)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) '@storybook/addon-onboarding': specifier: ^9.1.3 - version: 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) + version: 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) '@storybook/addon-vitest': specifier: ^9.1.3 - version: 9.1.20(@vitest/browser-playwright@4.1.2)(@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2))(@vitest/runner@4.1.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vitest@4.1.2) + version: 9.1.20(@vitest/browser-playwright@4.1.2)(@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2))(@vitest/runner@4.1.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vitest@4.1.2) '@storybook/react': specifier: ^9.1.9 - version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3) + version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3) '@storybook/react-vite': specifier: ^9.1.3 - version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.59.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.59.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) '@testing-library/react': specifier: ^16.3.0 version: 16.3.0(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -962,10 +962,10 @@ importers: version: 19.2.3(@types/react@19.2.7) '@vitest/browser': specifier: ^4.1.2 - version: 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) + version: 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) '@vitest/browser-playwright': specifier: ^4.1.2 - version: 4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) + version: 4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) '@vitest/coverage-istanbul': specifier: 'catalog:' version: 4.1.2(vitest@4.1.2) @@ -983,13 +983,13 @@ importers: version: 6.0.1 storybook: specifier: 'catalog:' - version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) typescript: specifier: 'catalog:' version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom-verification/acceptance-api: dependencies: @@ -2351,9 +2351,6 @@ importers: jsdom: specifier: 'catalog:' version: 26.1.0 - react-dom: - specifier: ^19.1.1 - version: 19.2.0(react@19.2.0) typescript: specifier: 'catalog:' version: 6.0.3 @@ -13329,7 +13326,7 @@ snapshots: minimist: 1.2.8 parsecurrency: 1.1.1 ts-morph: 27.0.2 - vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@22.19.15)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) '@ant-design/cli@6.3.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)': dependencies: @@ -14671,18 +14668,6 @@ snapshots: '@blazediff/core@1.9.1': {} - '@chromatic-com/storybook@4.1.3(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': - dependencies: - '@neoconfetti/react': 1.0.0 - chromatic: 13.3.4 - filesize: 10.1.6 - jsonfile: 6.2.0 - storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - strip-ansi: 7.1.2 - transitivePeerDependencies: - - '@chromatic-com/cypress' - - '@chromatic-com/playwright' - '@chromatic-com/storybook@4.1.3(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: '@neoconfetti/react': 1.0.0 @@ -15011,7 +14996,7 @@ snapshots: '@cucumber/gherkin-utils': 11.0.0 '@cucumber/html-formatter': 23.0.0(@cucumber/messages@32.2.0) '@cucumber/junit-xml-formatter': 0.13.3(@cucumber/messages@32.2.0) - '@cucumber/message-streams': 4.1.1(@cucumber/messages@32.3.1) + '@cucumber/message-streams': 4.1.1(@cucumber/messages@32.2.0) '@cucumber/messages': 32.2.0 '@cucumber/pretty-formatter': 1.0.1(@cucumber/cucumber@12.8.1)(@cucumber/messages@32.2.0) '@cucumber/tag-expressions': 9.1.0 @@ -15047,7 +15032,7 @@ snapshots: '@cucumber/gherkin-streams@6.0.0(@cucumber/gherkin@38.0.0)(@cucumber/message-streams@4.1.1(@cucumber/messages@32.2.0))(@cucumber/messages@32.2.0)': dependencies: '@cucumber/gherkin': 38.0.0 - '@cucumber/message-streams': 4.1.1(@cucumber/messages@32.3.1) + '@cucumber/message-streams': 4.1.1(@cucumber/messages@32.2.0) '@cucumber/messages': 32.2.0 commander: 14.0.0 source-map-support: 0.5.21 @@ -15096,9 +15081,9 @@ snapshots: luxon: 3.7.2 xmlbuilder: 15.1.1 - '@cucumber/message-streams@4.1.1(@cucumber/messages@32.3.1)': + '@cucumber/message-streams@4.1.1(@cucumber/messages@32.2.0)': dependencies: - '@cucumber/messages': 32.3.1 + '@cucumber/messages': 32.2.0 mime: 3.0.0 '@cucumber/messages@26.0.1': @@ -16718,15 +16703,6 @@ snapshots: '@types/yargs': 17.0.35 chalk: 4.1.2 - '@joshwooding/vite-plugin-react-docgen-typescript@0.6.1(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': - dependencies: - glob: 10.5.0 - magic-string: 0.30.21 - react-docgen-typescript: 2.4.0(typescript@6.0.3) - vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) - optionalDependencies: - typescript: 6.0.3 - '@joshwooding/vite-plugin-react-docgen-typescript@0.6.1(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: glob: 10.5.0 @@ -18125,31 +18101,12 @@ snapshots: '@standard-schema/spec@1.1.0': {} - '@storybook/addon-a11y@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': - dependencies: - '@storybook/global': 5.0.0 - axe-core: 4.11.0 - storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@storybook/addon-a11y@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: '@storybook/global': 5.0.0 axe-core: 4.11.0 storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@storybook/addon-docs@9.1.16(@types/react@19.2.7)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': - dependencies: - '@mdx-js/react': 3.1.1(@types/react@19.2.7)(react@19.2.0) - '@storybook/csf-plugin': 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) - '@storybook/icons': 1.6.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@storybook/react-dom-shim': 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) - react: 19.2.0 - react-dom: 19.2.0(react@19.2.0) - storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - ts-dedent: 2.2.0 - transitivePeerDependencies: - - '@types/react' - '@storybook/addon-docs@9.1.16(@types/react@19.2.7)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: '@mdx-js/react': 3.1.1(@types/react@19.2.7)(react@19.2.0) @@ -18163,10 +18120,6 @@ snapshots: transitivePeerDependencies: - '@types/react' - '@storybook/addon-onboarding@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': - dependencies: - storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@storybook/addon-onboarding@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) @@ -18187,22 +18140,6 @@ snapshots: - react - react-dom - '@storybook/addon-vitest@9.1.20(@vitest/browser-playwright@4.1.2)(@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2))(@vitest/runner@4.1.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vitest@4.1.2)': - dependencies: - '@storybook/global': 5.0.0 - '@storybook/icons': 1.6.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - prompts: 2.4.2 - storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - ts-dedent: 2.2.0 - optionalDependencies: - '@vitest/browser': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) - '@vitest/browser-playwright': 4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) - '@vitest/runner': 4.1.2 - vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - transitivePeerDependencies: - - react - - react-dom - '@storybook/addon-vitest@9.1.20(@vitest/browser-playwright@4.1.2)(@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2))(@vitest/runner@4.1.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vitest@4.1.2)': dependencies: '@storybook/global': 5.0.0 @@ -18219,13 +18156,6 @@ snapshots: - react - react-dom - '@storybook/builder-vite@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': - dependencies: - '@storybook/csf-plugin': 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) - storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - ts-dedent: 2.2.0 - vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) - '@storybook/builder-vite@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@storybook/csf-plugin': 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) @@ -18233,11 +18163,6 @@ snapshots: ts-dedent: 2.2.0 vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) - '@storybook/csf-plugin@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': - dependencies: - storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - unplugin: 1.16.1 - '@storybook/csf-plugin@9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) @@ -18250,38 +18175,12 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@storybook/react-dom-shim@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': - dependencies: - react: 19.2.0 - react-dom: 19.2.0(react@19.2.0) - storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@storybook/react-dom-shim@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@storybook/react-vite@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.59.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': - dependencies: - '@joshwooding/vite-plugin-react-docgen-typescript': 0.6.1(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@rollup/pluginutils': 5.3.0(rollup@4.59.0) - '@storybook/builder-vite': 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@storybook/react': 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3) - find-up: 7.0.0 - magic-string: 0.30.21 - react: 19.2.0 - react-docgen: 8.0.2 - react-dom: 19.2.0(react@19.2.0) - resolve: 1.22.11 - storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - tsconfig-paths: 4.2.0 - vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) - transitivePeerDependencies: - - rollup - - supports-color - - typescript - '@storybook/react-vite@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.59.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@joshwooding/vite-plugin-react-docgen-typescript': 0.6.1(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) @@ -18302,16 +18201,6 @@ snapshots: - supports-color - typescript - '@storybook/react@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)': - dependencies: - '@storybook/global': 5.0.0 - '@storybook/react-dom-shim': 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))) - react: 19.2.0 - react-dom: 19.2.0(react@19.2.0) - storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - optionalDependencies: - typescript: 6.0.3 - '@storybook/react@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)': dependencies: '@storybook/global': 5.0.0 @@ -18819,19 +18708,6 @@ snapshots: - vite optional: true - '@vitest/browser-playwright@4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': - dependencies: - '@vitest/browser': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) - '@vitest/mocker': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - playwright: 1.59.0 - tinyrainbow: 3.1.0 - vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - transitivePeerDependencies: - - bufferutil - - msw - - utf-8-validate - - vite - '@vitest/browser-playwright@4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': dependencies: '@vitest/browser': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) @@ -18863,23 +18739,6 @@ snapshots: - vite optional: true - '@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': - dependencies: - '@blazediff/core': 1.9.1 - '@vitest/mocker': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@vitest/utils': 4.1.2 - magic-string: 0.30.21 - pngjs: 7.0.0 - sirv: 3.0.2 - tinyrainbow: 3.1.0 - vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - ws: 8.20.0 - transitivePeerDependencies: - - bufferutil - - msw - - utf-8-validate - - vite - '@vitest/browser@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2)': dependencies: '@blazediff/core': 1.9.1 @@ -18909,7 +18768,7 @@ snapshots: magicast: 0.5.2 obug: 2.1.1 tinyrainbow: 3.1.0 - vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@22.19.15)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) transitivePeerDependencies: - supports-color @@ -18930,14 +18789,6 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@3.2.4(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': - dependencies: - '@vitest/spy': 3.2.4 - estree-walker: 3.0.3 - magic-string: 0.30.21 - optionalDependencies: - vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) - '@vitest/mocker@3.2.4(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@vitest/spy': 3.2.4 @@ -18954,14 +18805,6 @@ snapshots: optionalDependencies: vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@22.19.15)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) - '@vitest/mocker@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': - dependencies: - '@vitest/spy': 4.1.2 - estree-walker: 3.0.3 - magic-string: 0.30.21 - optionalDependencies: - vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) - '@vitest/mocker@4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@vitest/spy': 4.1.2 @@ -25226,28 +25069,6 @@ snapshots: graphql: 16.12.0 react: 19.2.0 - storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): - dependencies: - '@storybook/global': 5.0.0 - '@testing-library/jest-dom': 6.9.1 - '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1) - '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@vitest/spy': 3.2.4 - better-opn: 3.0.2 - esbuild: 0.25.12 - esbuild-register: 3.6.0(esbuild@0.25.12) - recast: 0.23.11 - semver: 7.7.4 - ws: 8.20.0 - transitivePeerDependencies: - - '@testing-library/dom' - - bufferutil - - msw - - supports-color - - utf-8-validate - - vite - storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): dependencies: '@storybook/global': 5.0.0 @@ -26000,26 +25821,6 @@ snapshots: - '@emnapi/core' - '@emnapi/runtime' - vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3): - dependencies: - lightningcss: 1.32.0 - picomatch: 4.0.4 - postcss: 8.5.10 - rolldown: 1.0.0-rc.12(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1) - tinyglobby: 0.2.15 - optionalDependencies: - '@types/node': 24.10.1 - esbuild: 0.25.12 - fsevents: 2.3.3 - jiti: 2.6.1 - less: 4.4.2 - terser: 5.44.1 - tsx: 4.21.0 - yaml: 2.8.3 - transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' - vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3): dependencies: lightningcss: 1.32.0 @@ -26070,36 +25871,6 @@ snapshots: transitivePeerDependencies: - msw - vitest@4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): - dependencies: - '@vitest/expect': 4.1.2 - '@vitest/mocker': 4.1.2(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@vitest/pretty-format': 4.1.2 - '@vitest/runner': 4.1.2 - '@vitest/snapshot': 4.1.2 - '@vitest/spy': 4.1.2 - '@vitest/utils': 4.1.2 - es-module-lexer: 2.0.0 - expect-type: 1.3.0 - magic-string: 0.30.21 - obug: 2.1.1 - pathe: 2.0.3 - picomatch: 4.0.4 - std-env: 4.0.0 - tinybench: 2.9.0 - tinyexec: 1.0.4 - tinyglobby: 0.2.15 - tinyrainbow: 3.1.0 - vite: 8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) - why-is-node-running: 2.3.0 - optionalDependencies: - '@opentelemetry/api': 1.9.0 - '@types/node': 24.10.1 - '@vitest/browser-playwright': 4.1.2(playwright@1.59.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.25.12)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.2) - jsdom: 26.1.0 - transitivePeerDependencies: - - msw - vitest@4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): dependencies: '@vitest/expect': 4.1.2 From 9bcf52b0742fcfbcab17d36870d8ddb10e91af4b Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Fri, 8 May 2026 20:05:26 +0530 Subject: [PATCH 58/88] refactor: Remove unused imports from theme context --- apps/ui-staff/src/contexts/theme-context.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ui-staff/src/contexts/theme-context.tsx b/apps/ui-staff/src/contexts/theme-context.tsx index fff424a3b..b23f6c46e 100644 --- a/apps/ui-staff/src/contexts/theme-context.tsx +++ b/apps/ui-staff/src/contexts/theme-context.tsx @@ -1,4 +1,4 @@ -import { loadStoredTheme, type StoredTheme, saveStoredTheme } from '@cellix/ui-core'; +import { type StoredTheme } from '@cellix/ui-core'; import { Button, theme } from 'antd'; import type { SeedToken } from 'antd/lib/theme/interface/index.js'; import { createContext, type ReactNode, useCallback, useEffect, useState } from 'react'; From be4b4761a2cc26de0a3bae332e7c3d3b397ca98b Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Fri, 8 May 2026 13:31:46 -0400 Subject: [PATCH 59/88] feat: Update staff route management and authorization roles for community and user management --- apps/ui-staff/e2e/role-authorization.spec.ts | 32 +++++++++---------- apps/ui-staff/src/App.tsx | 19 +++-------- .../ui/molecules/auth-landing/index.tsx | 25 ++++++++++++++- .../src/index.tsx | 4 +-- .../ocom/ui-staff-route-finance/src/index.tsx | 4 +-- .../src/index.tsx | 4 +-- .../src/staff-app-roles.test.ts | 18 ++++++----- .../ui-staff-shared/src/staff-app-roles.ts | 6 ++-- 8 files changed, 63 insertions(+), 49 deletions(-) diff --git a/apps/ui-staff/e2e/role-authorization.spec.ts b/apps/ui-staff/e2e/role-authorization.spec.ts index 4675ea423..c51484f05 100644 --- a/apps/ui-staff/e2e/role-authorization.spec.ts +++ b/apps/ui-staff/e2e/role-authorization.spec.ts @@ -69,8 +69,8 @@ async function injectOidcSession(page: Page, roles: string[]): Promise { // --- Test matrix --- const ROUTES = { - community: '/staff/community', - users: '/staff/users', + community: '/staff/community-management', + users: '/staff/user-management', finance: '/staff/finance', tech: '/staff/tech', } as const; @@ -124,19 +124,19 @@ test.describe('Staff.TechAdmin role', () => { await expectAuthorized(page, 'Tech Admin'); }); - test('is denied /staff/finance', async ({ page }) => { + test('can access /staff/finance', async ({ page }) => { await navigateTo(page, ROUTES.finance); - await expectUnauthorized(page); + await expectAuthorized(page, 'Finance'); }); - test('is denied /staff/community', async ({ page }) => { + test('can access /staff/community-management', async ({ page }) => { await navigateTo(page, ROUTES.community); - await expectUnauthorized(page); + await expectAuthorized(page, 'Community Management'); }); - test('is denied /staff/users', async ({ page }) => { + test('can access /staff/user-management', async ({ page }) => { await navigateTo(page, ROUTES.users); - await expectUnauthorized(page); + await expectAuthorized(page, 'User Management'); }); }); @@ -158,12 +158,12 @@ test.describe('Staff.Finance role', () => { await expectUnauthorized(page); }); - test('is denied /staff/community', async ({ page }) => { + test('is denied /staff/community-management', async ({ page }) => { await navigateTo(page, ROUTES.community); await expectUnauthorized(page); }); - test('is denied /staff/users', async ({ page }) => { + test('is denied /staff/user-management', async ({ page }) => { await navigateTo(page, ROUTES.users); await expectUnauthorized(page); }); @@ -177,12 +177,12 @@ test.describe('Staff.CaseManager role', () => { await injectOidcSession(page, [ROLES.CaseManager]); }); - test('can access /staff/community', async ({ page }) => { + test('can access /staff/community-management', async ({ page }) => { await navigateTo(page, ROUTES.community); await expectAuthorized(page, 'Community Management'); }); - test('can access /staff/users', async ({ page }) => { + test('can access /staff/user-management', async ({ page }) => { await navigateTo(page, ROUTES.users); await expectAuthorized(page, 'User Management'); }); @@ -206,12 +206,12 @@ test.describe('Staff.ServiceLineOwner role', () => { await injectOidcSession(page, [ROLES.ServiceLineOwner]); }); - test('can access /staff/community', async ({ page }) => { + test('can access /staff/community-management', async ({ page }) => { await navigateTo(page, ROUTES.community); await expectAuthorized(page, 'Community Management'); }); - test('can access /staff/users', async ({ page }) => { + test('can access /staff/user-management', async ({ page }) => { await navigateTo(page, ROUTES.users); await expectAuthorized(page, 'User Management'); }); @@ -235,12 +235,12 @@ test.describe('No app roles (authenticated, no roles)', () => { await injectOidcSession(page, []); }); - test('is denied /staff/community', async ({ page }) => { + test('is denied /staff/community-management', async ({ page }) => { await navigateTo(page, ROUTES.community); await expectUnauthorized(page); }); - test('is denied /staff/users', async ({ page }) => { + test('is denied /staff/user-management', async ({ page }) => { await navigateTo(page, ROUTES.users); await expectUnauthorized(page); }); diff --git a/apps/ui-staff/src/App.tsx b/apps/ui-staff/src/App.tsx index c6b2b0397..21ab6eccb 100644 --- a/apps/ui-staff/src/App.tsx +++ b/apps/ui-staff/src/App.tsx @@ -19,10 +19,10 @@ function StaffRoutes() { return ( @@ -30,21 +30,10 @@ function StaffRoutes() { } /> - - - } - /> - diff --git a/apps/ui-staff/src/components/ui/molecules/auth-landing/index.tsx b/apps/ui-staff/src/components/ui/molecules/auth-landing/index.tsx index 251645e9b..50bddccc3 100644 --- a/apps/ui-staff/src/components/ui/molecules/auth-landing/index.tsx +++ b/apps/ui-staff/src/components/ui/molecules/auth-landing/index.tsx @@ -1,5 +1,28 @@ +import { useAuth } from 'react-oidc-context'; import { Navigate } from 'react-router-dom'; +import { extractRoles, staffRouteRoles } from '@ocom/ui-staff-shared'; export const AuthLanding: React.FC = () => { - return ; + const auth = useAuth(); + + // Extract roles from the OIDC profile + const roles = extractRoles((auth?.user?.profile as Record) ?? undefined); + + // Find the first accessible route based on user roles + // Order: tech > finance > community-management, user-management + const routePaths = ['/staff/tech', '/staff/finance', '/staff/community-management', '/staff/user-management']; + + let targetRoute = '/unauthorized'; + + if (roles && roles.length > 0) { + for (const route of routePaths) { + const requiredRoles = staffRouteRoles[route as keyof typeof staffRouteRoles]; + if (requiredRoles && requiredRoles.some((role) => roles.includes(role))) { + targetRoute = route; + break; + } + } + } + + return ; }; diff --git a/packages/ocom/ui-staff-route-community-management/src/index.tsx b/packages/ocom/ui-staff-route-community-management/src/index.tsx index 90ceaf1cc..3bbe9a551 100644 --- a/packages/ocom/ui-staff-route-community-management/src/index.tsx +++ b/packages/ocom/ui-staff-route-community-management/src/index.tsx @@ -16,7 +16,7 @@ export const Root: React.FC = () => { } /> @@ -26,7 +26,7 @@ export const Root: React.FC = () => { } /> diff --git a/packages/ocom/ui-staff-route-finance/src/index.tsx b/packages/ocom/ui-staff-route-finance/src/index.tsx index c7116f4ad..fb0360d17 100644 --- a/packages/ocom/ui-staff-route-finance/src/index.tsx +++ b/packages/ocom/ui-staff-route-finance/src/index.tsx @@ -16,7 +16,7 @@ export const Root: React.FC = () => { } /> @@ -26,7 +26,7 @@ export const Root: React.FC = () => { } /> diff --git a/packages/ocom/ui-staff-route-user-management/src/index.tsx b/packages/ocom/ui-staff-route-user-management/src/index.tsx index 33b2a3f38..f2c3911df 100644 --- a/packages/ocom/ui-staff-route-user-management/src/index.tsx +++ b/packages/ocom/ui-staff-route-user-management/src/index.tsx @@ -16,7 +16,7 @@ export const Root: React.FC = () => { } /> @@ -26,7 +26,7 @@ export const Root: React.FC = () => { } /> diff --git a/packages/ocom/ui-staff-shared/src/staff-app-roles.test.ts b/packages/ocom/ui-staff-shared/src/staff-app-roles.test.ts index ffccefcac..1dfffb7ac 100644 --- a/packages/ocom/ui-staff-shared/src/staff-app-roles.test.ts +++ b/packages/ocom/ui-staff-shared/src/staff-app-roles.test.ts @@ -11,18 +11,20 @@ describe('StaffAppRoles', () => { }); describe('staffRouteRoles', () => { - it('gates /staff/community to CaseManager and ServiceLineOwner', () => { - expect(staffRouteRoles['/staff/community']).toContain(StaffAppRoles.CaseManager); - expect(staffRouteRoles['/staff/community']).toContain(StaffAppRoles.ServiceLineOwner); + it('gates /staff/community-management to CaseManager, ServiceLineOwner, and TechAdmin', () => { + expect(staffRouteRoles['/staff/community-management']).toContain(StaffAppRoles.CaseManager); + expect(staffRouteRoles['/staff/community-management']).toContain(StaffAppRoles.ServiceLineOwner); + expect(staffRouteRoles['/staff/community-management']).toContain(StaffAppRoles.TechAdmin); }); - it('gates /staff/users to CaseManager and ServiceLineOwner', () => { - expect(staffRouteRoles['/staff/users']).toContain(StaffAppRoles.CaseManager); - expect(staffRouteRoles['/staff/users']).toContain(StaffAppRoles.ServiceLineOwner); + it('gates /staff/user-management to CaseManager, ServiceLineOwner, and TechAdmin', () => { + expect(staffRouteRoles['/staff/user-management']).toContain(StaffAppRoles.CaseManager); + expect(staffRouteRoles['/staff/user-management']).toContain(StaffAppRoles.ServiceLineOwner); + expect(staffRouteRoles['/staff/user-management']).toContain(StaffAppRoles.TechAdmin); }); - it('gates /staff/finance to Finance only', () => { - expect(staffRouteRoles['/staff/finance']).toEqual([StaffAppRoles.Finance]); + it('gates /staff/finance to Finance and TechAdmin', () => { + expect(staffRouteRoles['/staff/finance']).toEqual([StaffAppRoles.Finance, StaffAppRoles.TechAdmin]); }); it('gates /staff/tech to TechAdmin only', () => { diff --git a/packages/ocom/ui-staff-shared/src/staff-app-roles.ts b/packages/ocom/ui-staff-shared/src/staff-app-roles.ts index 2f2c56651..d3f459698 100644 --- a/packages/ocom/ui-staff-shared/src/staff-app-roles.ts +++ b/packages/ocom/ui-staff-shared/src/staff-app-roles.ts @@ -12,9 +12,9 @@ export type StaffAppRole = (typeof StaffAppRoles)[keyof typeof StaffAppRoles]; * A user must hold at least one of the listed roles to be admitted to the route. */ export const staffRouteRoles = { - '/staff/community': [StaffAppRoles.CaseManager, StaffAppRoles.ServiceLineOwner], - '/staff/users': [StaffAppRoles.CaseManager, StaffAppRoles.ServiceLineOwner], - '/staff/finance': [StaffAppRoles.Finance], + '/staff/community-management': [StaffAppRoles.CaseManager, StaffAppRoles.ServiceLineOwner, StaffAppRoles.TechAdmin], + '/staff/user-management': [StaffAppRoles.CaseManager, StaffAppRoles.ServiceLineOwner, StaffAppRoles.TechAdmin], + '/staff/finance': [StaffAppRoles.Finance, StaffAppRoles.TechAdmin], '/staff/tech': [StaffAppRoles.TechAdmin], } satisfies Record; From 825c79ab4abe0c332d146cd748a0109704c10b6a Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Sat, 9 May 2026 00:58:18 +0530 Subject: [PATCH 60/88] feat: Implement role-based access control for staff routes and permissions --- apps/ui-staff/src/App.tsx | 118 ++++++++---------- .../src/hooks/use-staff-permissions.ts | 32 +++-- .../src/section-layout.stories.tsx | 76 +++++++---- .../ui-staff-shared/src/section-layout.tsx | 74 +++++++---- .../ui-staff-shared/src/staff-route-shell.tsx | 44 +------ 5 files changed, 179 insertions(+), 165 deletions(-) diff --git a/apps/ui-staff/src/App.tsx b/apps/ui-staff/src/App.tsx index 21ab6eccb..9c4a9a0ec 100644 --- a/apps/ui-staff/src/App.tsx +++ b/apps/ui-staff/src/App.tsx @@ -5,9 +5,11 @@ import { Root as Finance } from '@ocom/ui-staff-route-finance'; import { Root } from '@ocom/ui-staff-route-root'; import { Root as TechAdmin } from '@ocom/ui-staff-route-tech-admin'; import { Root as UserManagement } from '@ocom/ui-staff-route-user-management'; -import { RequireRole, StaffAuthProvider, staffRouteRoles } from '@ocom/ui-staff-shared'; +import { StaffAuthContext, StaffAuthProvider } from '@ocom/ui-staff-shared'; +import { Spin } from 'antd'; +import { useContext } from 'react'; import { useAuth } from 'react-oidc-context'; -import { Route, Routes } from 'react-router-dom'; +import { Navigate, Route, Routes } from 'react-router-dom'; import './App.css'; import { AuthLanding } from './components/ui/molecules/auth-landing/index.tsx'; import { client } from './components/ui/organisms/apollo-connection/apollo-client-links.tsx'; @@ -16,50 +18,42 @@ import { useStaffPermissions } from './hooks/use-staff-permissions.ts'; import { Unauthorized } from './unauthorized.tsx'; function StaffRoutes() { + const auth = useContext(StaffAuthContext); + const perms = auth?.permissions; + return ( + {perms?.canManageCommunities === true && ( + } + /> + )} + {perms?.canManageUsers === true && ( + } + /> + )} + {perms?.canManageFinance === true && ( + } + /> + )} + {perms?.canManageTechAdmin === true && ( + } + /> + )} - - - } - /> - - - - } - /> - - - - } - /> - - - + } /> @@ -81,8 +75,6 @@ export default function App() { ); - // Staff section acts as the parent route element and must render an Outlet so - // nested child routes declared in the top-level Routes are rendered in place. const staffSectionElement = ( @@ -105,40 +97,28 @@ export default function App() { element={} /> - {/* Parent staff route: child routes must be declared as nested Route elements - so relative paths like "users/*" resolve against /staff. */} + {/* StaffSection renders StaffAuthProvider + StaffRoutes which handles all + authenticated sub-routes with permission guards. No nested Route children + are needed here because StaffRoutes defines its own Routes block. */} - } - /> - } - /> - } - /> - } - /> - } - /> - + /> ); } function StaffSection({ identity }: { identity: Parameters[0]['value'] }) { - const { permissions } = useStaffPermissions(); + const { permissions, loading } = useStaffPermissions(); + + if (loading) { + return ( +
    + +
    + ); + } return ( diff --git a/apps/ui-staff/src/hooks/use-staff-permissions.ts b/apps/ui-staff/src/hooks/use-staff-permissions.ts index 8e86546c7..2fb9ec9d7 100644 --- a/apps/ui-staff/src/hooks/use-staff-permissions.ts +++ b/apps/ui-staff/src/hooks/use-staff-permissions.ts @@ -13,10 +13,16 @@ const CURRENT_STAFF_USER_QUERY = gql` id roleName permissions { - sectionPermissions { + communityPermissions { canManageCommunities - canManageUser + } + userPermissions { + canManageUsers + } + financePermissions { canManageFinance + } + techAdminPermissions { canManageTechAdmin } } @@ -25,9 +31,9 @@ const CURRENT_STAFF_USER_QUERY = gql` } `; -interface StaffPermissions { +export interface StaffPermissions { canManageCommunities: boolean; - canManageUser: boolean; + canManageUsers: boolean; canManageFinance: boolean; canManageTechAdmin: boolean; } @@ -44,7 +50,10 @@ interface StaffUserQueryResult { id: string; roleName: string; permissions: { - sectionPermissions: StaffPermissions; + communityPermissions: { canManageCommunities: boolean }; + userPermissions: { canManageUsers: boolean }; + financePermissions: { canManageFinance: boolean }; + techAdminPermissions: { canManageTechAdmin: boolean }; }; }; }; @@ -55,10 +64,19 @@ export const useStaffPermissions = (): { permissions: StaffPermissions | undefin fetchPolicy: 'cache-first', }); - const sectionPermissions = data?.currentStaffUserAndCreateIfNotExists?.role?.permissions?.sectionPermissions; + const rolePermissions = data?.currentStaffUserAndCreateIfNotExists?.role?.permissions; + + const permissions: StaffPermissions | undefined = rolePermissions + ? { + canManageCommunities: rolePermissions.communityPermissions.canManageCommunities, + canManageUsers: rolePermissions.userPermissions.canManageUsers, + canManageFinance: rolePermissions.financePermissions.canManageFinance, + canManageTechAdmin: rolePermissions.techAdminPermissions.canManageTechAdmin, + } + : undefined; return { - permissions: sectionPermissions ?? undefined, + permissions, loading, error, }; diff --git a/packages/ocom/ui-staff-shared/src/section-layout.stories.tsx b/packages/ocom/ui-staff-shared/src/section-layout.stories.tsx index bd43e89e1..8c691b4a1 100644 --- a/packages/ocom/ui-staff-shared/src/section-layout.stories.tsx +++ b/packages/ocom/ui-staff-shared/src/section-layout.stories.tsx @@ -18,36 +18,55 @@ const renderIntoDocument = (node: React.ReactNode) => { }; describe('SectionLayout merging behaviour', () => { - it('renders canonical staff navigation merged with consumer pageLayouts', async () => { - const consumerLayouts = [ - { - path: '/staff/community-management', - title: 'Community Management', - icon: , - id: 'ROOT', - }, - ]; + it('renders only the menu items the user has permission for', async () => { + const container = renderIntoDocument( + + + + } + /> + + + , + ); + + await new Promise((r) => setTimeout(r, 10)); + + expect(container.textContent).toContain('Communities'); + expect(container.textContent).not.toContain('Users'); + expect(container.textContent).toContain('Finance'); + expect(container.textContent).not.toContain('Tech Admin'); + }); + it('shows no menu items when permissions are undefined (loading or no role assigned)', async () => { const container = renderIntoDocument( } + element={} /> , ); - // Wait a tick for ant design components to mount await new Promise((r) => setTimeout(r, 10)); - // Top-level menu items expected - expect(container.textContent).not.toContain('Home'); - expect(container.textContent).toContain('Communities'); - expect(container.textContent).toContain('Users'); - expect(container.textContent).toContain('Finance'); - expect(container.textContent).toContain('Tech Admin'); + expect(container.textContent).not.toContain('Communities'); + expect(container.textContent).not.toContain('Users'); + expect(container.textContent).not.toContain('Finance'); + expect(container.textContent).not.toContain('Tech Admin'); }); it('preserves default parent when consumer entry omits parent field', async () => { @@ -63,12 +82,23 @@ describe('SectionLayout merging behaviour', () => { const container = renderIntoDocument( - - } - /> - + + + } + /> + + , ); diff --git a/packages/ocom/ui-staff-shared/src/section-layout.tsx b/packages/ocom/ui-staff-shared/src/section-layout.tsx index cd27b722f..c2df395c8 100644 --- a/packages/ocom/ui-staff-shared/src/section-layout.tsx +++ b/packages/ocom/ui-staff-shared/src/section-layout.tsx @@ -54,34 +54,54 @@ export const SectionLayout: React.FC = (props) => { // Merge canonical staff navigation with consumer-provided pageLayouts. // Defaults are added only when the consumer hasn't provided an entry with the same id. // Consumer-provided entries override defaults when ids conflict. + // Build default page layouts from backend permissions. + // A menu item is only included when the corresponding permission is explicitly true. + // false, null, or undefined all result in the item being hidden and the route being unavailable. + const perms = auth?.permissions; const defaultPageLayouts: PageLayoutProps[] = [ - { - path: '/staff/community-management', - title: 'Communities', - icon: , - id: 'ROOT', - }, - { - path: '/staff/user-management/*', - title: 'Users', - icon: , - id: 'users', - parent: 'ROOT', - }, - { - path: '/staff/finance/*', - title: 'Finance', - icon: , - id: 'finance', - parent: 'ROOT', - }, - { - path: '/staff/tech/*', - title: 'Tech Admin', - icon: , - id: 'tech', - parent: 'ROOT', - }, + ...(perms?.canManageCommunities === true + ? [ + { + path: '/staff/community-management', + title: 'Communities', + icon: , + id: 'ROOT', + }, + ] + : []), + ...(perms?.canManageUsers === true + ? [ + { + path: '/staff/user-management/*', + title: 'Users', + icon: , + id: 'users', + parent: 'ROOT', + }, + ] + : []), + ...(perms?.canManageFinance === true + ? [ + { + path: '/staff/finance/*', + title: 'Finance', + icon: , + id: 'finance', + parent: 'ROOT', + }, + ] + : []), + ...(perms?.canManageTechAdmin === true + ? [ + { + path: '/staff/tech/*', + title: 'Tech Admin', + icon: , + id: 'tech', + parent: 'ROOT', + }, + ] + : []), ]; // Build a map from default entries, then overlay consumer entries so consumers can override defaults. diff --git a/packages/ocom/ui-staff-shared/src/staff-route-shell.tsx b/packages/ocom/ui-staff-shared/src/staff-route-shell.tsx index 9d96be083..0b16503c3 100644 --- a/packages/ocom/ui-staff-shared/src/staff-route-shell.tsx +++ b/packages/ocom/ui-staff-shared/src/staff-route-shell.tsx @@ -1,6 +1,4 @@ -import { DashboardOutlined } from '@ant-design/icons'; -import type { PageLayoutProps } from '@ocom/ui-shared'; -import { createContext, type FC, type ReactNode, useContext, useMemo } from 'react'; +import { createContext, type FC, type ReactNode, useContext } from 'react'; import { SectionLayout, type SectionLayoutProps } from './section-layout.tsx'; export interface StaffRouteShellProps { @@ -17,7 +15,7 @@ export type StaffAuth = { onLogout?: () => Promise | void; permissions?: { canManageCommunities?: boolean; - canManageUser?: boolean; + canManageUsers?: boolean; canManageFinance?: boolean; canManageTechAdmin?: boolean; }; @@ -30,42 +28,10 @@ export const StaffAuthProvider: FC<{ value: StaffAuth; children?: ReactNode }> = export const StaffRouteShell: FC = ({ title, description }) => { const auth = useContext(StaffAuthContext); - // Default page layouts for staff portal with ROOT entry and parent relationships - const pageLayouts: PageLayoutProps[] = useMemo( - () => [ - { - path: '/staff/community-management', - title: 'Communities', - icon: , - id: 'ROOT', - }, - { - path: '/staff/user-management/*', - title: 'User Management', - icon: , - id: 'users', - parent: 'ROOT', - }, - { - path: '/staff/finance/*', - title: 'Finance', - icon: , - id: 'finance', - parent: 'ROOT', - }, - { - path: '/staff/tech/*', - title: 'Tech Admin', - icon: , - id: 'tech', - parent: 'ROOT', - }, - ], - [], - ); - + // Navigation items are built from backend permissions in SectionLayout. + // Pass an empty array so SectionLayout is the single source of truth for the menu. const sectionLayoutProps: SectionLayoutProps = { - pageLayouts, + pageLayouts: [], memberData: auth, title, description: description ?? '', From b9d03cc1b0fe9eb4c0603eef503df8ba139bb18d Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Sat, 9 May 2026 01:03:26 +0530 Subject: [PATCH 61/88] feat: Implement role-based access control for staff routes and permissions --- apps/ui-staff/src/hooks/use-staff-permissions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ui-staff/src/hooks/use-staff-permissions.ts b/apps/ui-staff/src/hooks/use-staff-permissions.ts index 2fb9ec9d7..6a63b93ad 100644 --- a/apps/ui-staff/src/hooks/use-staff-permissions.ts +++ b/apps/ui-staff/src/hooks/use-staff-permissions.ts @@ -31,7 +31,7 @@ const CURRENT_STAFF_USER_QUERY = gql` } `; -export interface StaffPermissions { +interface StaffPermissions { canManageCommunities: boolean; canManageUsers: boolean; canManageFinance: boolean; From c0091c0bcc0dde8711b16cb93c3d30fa7fd2e3f0 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Mon, 11 May 2026 20:06:42 +0530 Subject: [PATCH 62/88] refactor: Rename VITE_FUNCTION_ENDPOINT to VITE_COMMON_API_ENDPOINT across multiple files --- .../src/components/ui/organisms/apollo-connection/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ui-community/src/components/ui/organisms/apollo-connection/index.tsx b/apps/ui-community/src/components/ui/organisms/apollo-connection/index.tsx index a72d55267..4bc5af3d4 100644 --- a/apps/ui-community/src/components/ui/organisms/apollo-connection/index.tsx +++ b/apps/ui-community/src/components/ui/organisms/apollo-connection/index.tsx @@ -22,7 +22,7 @@ export const ApolloConnection: FC = (props: ApolloConnect ApolloLinkToAddCustomHeader('x-member-id', memberId), TerminatingApolloLinkForGraphqlServer({ // biome-ignore lint:useLiteralKeys - uri: `${import.meta.env['VITE_FUNCTION_ENDPOINT']}`, + uri: `${import.meta.env['VITE_COMMON_API_ENDPOINT']}`, batchMax: 15, batchInterval: 50, }), From fd1379384624a3bf858c853547fa73e6a29e4c6e Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Mon, 11 May 2026 20:06:48 +0530 Subject: [PATCH 63/88] refactor: Rename VITE_FUNCTION_ENDPOINT to VITE_COMMON_API_ENDPOINT across multiple files --- .../src/components/ui/organisms/apollo-connection/index.tsx | 2 +- .../e2e-tests/src/shared/support/servers/test-api-server.ts | 2 +- .../e2e-tests/src/shared/support/servers/test-vite-server.ts | 2 +- .../verification-shared/src/settings/local-settings.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/ui-staff/src/components/ui/organisms/apollo-connection/index.tsx b/apps/ui-staff/src/components/ui/organisms/apollo-connection/index.tsx index 46e127095..3d2cac753 100644 --- a/apps/ui-staff/src/components/ui/organisms/apollo-connection/index.tsx +++ b/apps/ui-staff/src/components/ui/organisms/apollo-connection/index.tsx @@ -47,7 +47,7 @@ export const ApolloConnection: FC = (props: ApolloConnect ApolloLinkToAddCustomHeader('x-member-id', memberId), TerminatingApolloLinkForGraphqlServer({ // biome-ignore lint:useLiteralKeys - uri: `${import.meta.env['VITE_FUNCTION_ENDPOINT']}`, + uri: `${import.meta.env['VITE_COMMON_API_ENDPOINT']}`, batchMax: 15, batchInterval: 50, }), diff --git a/packages/ocom-verification/e2e-tests/src/shared/support/servers/test-api-server.ts b/packages/ocom-verification/e2e-tests/src/shared/support/servers/test-api-server.ts index 51657939f..2845662ee 100644 --- a/packages/ocom-verification/e2e-tests/src/shared/support/servers/test-api-server.ts +++ b/packages/ocom-verification/e2e-tests/src/shared/support/servers/test-api-server.ts @@ -46,7 +46,7 @@ export class TestApiServer extends PortlessServer { COSMOSDB_CONNECTION_STRING: getMongoConnectionString(), ACCOUNT_PORTAL_OIDC_ISSUER: apiSettings.accountPortalOidcIssuer, ACCOUNT_PORTAL_OIDC_ENDPOINT: apiSettings.accountPortalOidcEndpoint, - VITE_FUNCTION_ENDPOINT: buildUrl('data-access.ownercommunity.localhost', '/api/graphql'), + VITE_COMMON_API_ENDPOINT: buildUrl('data-access.ownercommunity.localhost', '/api/graphql'), }; } diff --git a/packages/ocom-verification/e2e-tests/src/shared/support/servers/test-vite-server.ts b/packages/ocom-verification/e2e-tests/src/shared/support/servers/test-vite-server.ts index 133873441..62a50a2a2 100644 --- a/packages/ocom-verification/e2e-tests/src/shared/support/servers/test-vite-server.ts +++ b/packages/ocom-verification/e2e-tests/src/shared/support/servers/test-vite-server.ts @@ -31,7 +31,7 @@ export class TestViteServer extends PortlessServer { VITE_BASE_URL: uiBase, VITE_AAD_B2C_ACCOUNT_AUTHORITY: apiSettings.accountPortalOidcIssuer, VITE_AAD_B2C_REDIRECT_URI: `${uiBase}/auth-redirect`, - VITE_FUNCTION_ENDPOINT: apiEndpoint, + VITE_COMMON_API_ENDPOINT: apiEndpoint, }; } diff --git a/packages/ocom-verification/verification-shared/src/settings/local-settings.ts b/packages/ocom-verification/verification-shared/src/settings/local-settings.ts index 99b4c30f9..e63d67f3c 100644 --- a/packages/ocom-verification/verification-shared/src/settings/local-settings.ts +++ b/packages/ocom-verification/verification-shared/src/settings/local-settings.ts @@ -28,5 +28,5 @@ export const apiSettings = { export const uiSettings = { baseUrl: requireSetting(uiValues, 'VITE_BASE_URL', 'VITE_BASE_URL is required in .env'), - graphqlEndpoint: requireSetting(uiValues, 'VITE_FUNCTION_ENDPOINT', 'VITE_FUNCTION_ENDPOINT is required in .env'), + graphqlEndpoint: requireSetting(uiValues, 'VITE_COMMON_API_ENDPOINT', 'VITE_COMMON_API_ENDPOINT is required in .env'), } as const; From a18025d8f5aea8be26791ea8ee8122cf29804e8e Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Mon, 11 May 2026 11:07:47 -0400 Subject: [PATCH 64/88] feat: Update dependencies for improved security and functionality --- .snyk | 6 ++++++ package.json | 3 ++- .../server-oauth2-mock-seedwork/package.json | 2 +- pnpm-lock.yaml | 19 ++++++++++--------- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/.snyk b/.snyk index 682829b53..2414d24ed 100644 --- a/.snyk +++ b/.snyk @@ -71,3 +71,9 @@ ignore: reason: 'Mongoose 8.22.1 has TypeScript constraint errors in type definitions (types/inferrawdoctype.d.ts, types/inferschematype.d.ts) that break compilation. Patch attempts failed due to external library type incompatibilities. Risk is Low: requires control of query field names and values.' expires: '2026-11-07T00:00:00.000Z' created: '2026-05-07T09:00:00.000Z' + 'SNYK-JS-BABELPLUGINTRANSFORMMODULESSYSTEMJS-16624576': + - '* > @babel/plugin-transform-modules-systemjs@7.28.5': + reason: 'Transitive dependency in Docusaurus; not exploitable in current usage.' + expires: '2026-06-28T00:00:00.000Z' + created: '2026-05-11T10:00:00.000Z' + diff --git a/package.json b/package.json index 8a866e7e9..ea3c6172c 100644 --- a/package.json +++ b/package.json @@ -124,7 +124,8 @@ "playwright-core": "1.59.0", "playwright": "1.59.0", "postcss": "8.5.10", - "protobufjs": "7.5.5" + "protobufjs": "7.5.5", + "ip-address": "^10.1.1" }, "patchedDependencies": { "@azure/functions@4.11.0": "patches/@azure__functions@4.11.0.patch" diff --git a/packages/cellix/server-oauth2-mock-seedwork/package.json b/packages/cellix/server-oauth2-mock-seedwork/package.json index d148bdb78..ef0015814 100644 --- a/packages/cellix/server-oauth2-mock-seedwork/package.json +++ b/packages/cellix/server-oauth2-mock-seedwork/package.json @@ -19,7 +19,7 @@ }, "dependencies": { "express": "^4.22.0", - "express-rate-limit": "^8.3.2", + "express-rate-limit": "^8.5.1", "jose": "^5.9.6" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 700f84c90..a5a992bce 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -125,6 +125,7 @@ overrides: playwright: 1.59.0 postcss: 8.5.10 protobufjs: 7.5.5 + ip-address: ^10.1.1 patchedDependencies: '@azure/functions@4.11.0': @@ -884,8 +885,8 @@ importers: specifier: ^4.22.0 version: 4.22.1 express-rate-limit: - specifier: ^8.3.2 - version: 8.3.2(express@4.22.1) + specifier: ^8.5.1 + version: 8.5.1(express@4.22.1) jose: specifier: ^5.9.6 version: 5.10.0 @@ -8371,8 +8372,8 @@ packages: resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} engines: {node: '>=12.0.0'} - express-rate-limit@8.3.2: - resolution: {integrity: sha512-77VmFeJkO0/rvimEDuUC5H30oqUC4EyOhyGccfqoLebB0oiEYfM7nwPrsDsBL1gsTpwfzX8SFy2MT3TDyRq+bg==} + express-rate-limit@8.5.1: + resolution: {integrity: sha512-5O6KYmyJEpuPJV5hNTXKbAHWRqrzyu+OI3vUnSd2kXFubIVpG7ezpgxQy76Zo5GQZtrQBg86hF+CM/NX+cioiQ==} engines: {node: '>= 16'} peerDependencies: express: '>= 4.11' @@ -9097,8 +9098,8 @@ packages: invariant@2.2.4: resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} - ip-address@10.1.0: - resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} + ip-address@10.2.0: + resolution: {integrity: sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==} engines: {node: '>= 12'} ipaddr.js@1.9.1: @@ -20690,10 +20691,10 @@ snapshots: expect-type@1.3.0: {} - express-rate-limit@8.3.2(express@4.22.1): + express-rate-limit@8.5.1(express@4.22.1): dependencies: express: 4.22.1 - ip-address: 10.1.0 + ip-address: 10.2.0 express@4.22.1: dependencies: @@ -21595,7 +21596,7 @@ snapshots: dependencies: loose-envify: 1.4.0 - ip-address@10.1.0: {} + ip-address@10.2.0: {} ipaddr.js@1.9.1: {} From 53cdd3e083cc1df26cca154bd74dbb302fc81a3c Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Mon, 11 May 2026 14:47:29 -0400 Subject: [PATCH 65/88] feat: Enhance role-based access control in staff routes and permissions --- apps/ui-staff/src/App.tsx | 49 +++++++++-- .../src/models/role/staff-role.model.ts | 3 + .../src/index.test.ts | 2 +- .../service-token-validation/src/index.ts | 26 ++++-- .../src/section-layout.stories.tsx | 26 ++++++ .../ui-staff-shared/src/section-layout.tsx | 86 +++++++++---------- 6 files changed, 129 insertions(+), 63 deletions(-) diff --git a/apps/ui-staff/src/App.tsx b/apps/ui-staff/src/App.tsx index 9c4a9a0ec..3572b552e 100644 --- a/apps/ui-staff/src/App.tsx +++ b/apps/ui-staff/src/App.tsx @@ -5,7 +5,7 @@ import { Root as Finance } from '@ocom/ui-staff-route-finance'; import { Root } from '@ocom/ui-staff-route-root'; import { Root as TechAdmin } from '@ocom/ui-staff-route-tech-admin'; import { Root as UserManagement } from '@ocom/ui-staff-route-user-management'; -import { StaffAuthContext, StaffAuthProvider } from '@ocom/ui-staff-shared'; +import { extractRoles, StaffAuthContext, StaffAuthProvider, staffRouteRoles } from '@ocom/ui-staff-shared'; import { Spin } from 'antd'; import { useContext } from 'react'; import { useAuth } from 'react-oidc-context'; @@ -20,30 +20,61 @@ import { Unauthorized } from './unauthorized.tsx'; function StaffRoutes() { const auth = useContext(StaffAuthContext); const perms = auth?.permissions; + const roles = auth?.roles ?? extractRoles(auth?.raw); + + const hasAnyRoleFor = (route: keyof typeof staffRouteRoles): boolean => { + const requiredRoles = staffRouteRoles[route]; + return roles?.some((userRole) => requiredRoles.some((requiredRole) => requiredRole === userRole)) === true; + }; + + const canManageCommunities = perms?.canManageCommunities ?? hasAnyRoleFor('/staff/community-management'); + const canManageUsers = perms?.canManageUsers ?? hasAnyRoleFor('/staff/user-management'); + const canManageFinance = perms?.canManageFinance ?? hasAnyRoleFor('/staff/finance'); + const canManageTechAdmin = perms?.canManageTechAdmin ?? hasAnyRoleFor('/staff/tech'); + + let defaultStaffRoute = '/unauthorized'; + if (canManageTechAdmin) { + defaultStaffRoute = '/staff/tech'; + } else if (canManageFinance) { + defaultStaffRoute = '/staff/finance'; + } else if (canManageCommunities) { + defaultStaffRoute = '/staff/community-management'; + } else if (canManageUsers) { + defaultStaffRoute = '/staff/user-management'; + } return ( - {perms?.canManageCommunities === true && ( + + } + /> + {canManageCommunities && ( } /> )} - {perms?.canManageUsers === true && ( + {canManageUsers && ( } /> )} - {perms?.canManageFinance === true && ( + {canManageFinance && ( } /> )} - {perms?.canManageTechAdmin === true && ( + {canManageTechAdmin && ( } /> )} diff --git a/packages/ocom/data-sources-mongoose-models/src/models/role/staff-role.model.ts b/packages/ocom/data-sources-mongoose-models/src/models/role/staff-role.model.ts index 0a25365cf..fd4ab056f 100644 --- a/packages/ocom/data-sources-mongoose-models/src/models/role/staff-role.model.ts +++ b/packages/ocom/data-sources-mongoose-models/src/models/role/staff-role.model.ts @@ -159,6 +159,9 @@ const StaffRoleSchema = new Schema, StaffRole>( enterpriseAppRole: { type: String, required: true, + default(this: StaffRole) { + return this.roleName; + }, }, isDefault: { type: Boolean, required: true, default: false }, }, diff --git a/packages/ocom/service-token-validation/src/index.test.ts b/packages/ocom/service-token-validation/src/index.test.ts index 8bf1747cb..203525c8e 100644 --- a/packages/ocom/service-token-validation/src/index.test.ts +++ b/packages/ocom/service-token-validation/src/index.test.ts @@ -228,7 +228,7 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { // Mock successful verification on second attempt mockGetVerifiedJwt - .mockResolvedValueOnce(null) // First provider fails + .mockRejectedValueOnce(Object.assign(new Error('signature verification failed'), { name: 'JWSSignatureVerificationFailed' })) // First provider fails with signature mismatch .mockResolvedValueOnce({ // Second provider succeeds payload: { sub: 'user123', aud: 'audience2' }, diff --git a/packages/ocom/service-token-validation/src/index.ts b/packages/ocom/service-token-validation/src/index.ts index b002722c6..c8824fa05 100644 --- a/packages/ocom/service-token-validation/src/index.ts +++ b/packages/ocom/service-token-validation/src/index.ts @@ -39,12 +39,18 @@ export class ServiceTokenValidation implements ServiceBase { async verifyJwt(token: string): Promise | null> { // Try each config key for verification for (const configKey of this.tokenSettings.keys()) { - const result = await this.tokenVerifier.getVerifiedJwt(token, configKey); - if (result?.payload) { - return { - verifiedJwt: result.payload as ClaimsType, - openIdConfigKey: configKey, - }; + try { + const result = await this.tokenVerifier.getVerifiedJwt(token, configKey); + if (result?.payload) { + return { + verifiedJwt: result.payload as ClaimsType, + openIdConfigKey: configKey, + }; + } + } catch (error) { + if (!this.isRetryableVerificationError(error)) { + throw error; + } } } return null; @@ -74,4 +80,12 @@ export class ServiceTokenValidation implements ServiceBase { return defaultValue; } } + + private isRetryableVerificationError(error: unknown): boolean { + if (!(error instanceof Error)) { + return false; + } + + return ['JWSSignatureVerificationFailed', 'JWTClaimValidationFailed', 'JWTExpired', 'JWTInvalid', 'JWSInvalid'].includes(error.name); + } } diff --git a/packages/ocom/ui-staff-shared/src/section-layout.stories.tsx b/packages/ocom/ui-staff-shared/src/section-layout.stories.tsx index 8c691b4a1..38e57f685 100644 --- a/packages/ocom/ui-staff-shared/src/section-layout.stories.tsx +++ b/packages/ocom/ui-staff-shared/src/section-layout.stories.tsx @@ -69,6 +69,32 @@ describe('SectionLayout merging behaviour', () => { expect(container.textContent).not.toContain('Tech Admin'); }); + it('renders finance menu from JWT role when backend permissions are unavailable', async () => { + const container = renderIntoDocument( + + + + } + /> + + + , + ); + + await new Promise((r) => setTimeout(r, 10)); + + expect(container.textContent).not.toContain('Communities'); + expect(container.textContent).not.toContain('Users'); + expect(container.textContent).toContain('Finance'); + expect(container.textContent).not.toContain('Tech Admin'); + }); + it('preserves default parent when consumer entry omits parent field', async () => { const consumerLayouts = [ { diff --git a/packages/ocom/ui-staff-shared/src/section-layout.tsx b/packages/ocom/ui-staff-shared/src/section-layout.tsx index c2df395c8..9064a6332 100644 --- a/packages/ocom/ui-staff-shared/src/section-layout.tsx +++ b/packages/ocom/ui-staff-shared/src/section-layout.tsx @@ -3,6 +3,7 @@ import { MenuComponent, type MenuComponentProps, type PageLayoutProps } from '@o import { Button, Layout, theme } from 'antd'; import { useContext, useState } from 'react'; import { Outlet } from 'react-router-dom'; +import { extractRoles, staffRouteRoles } from './staff-app-roles.ts'; import { StaffAuthContext } from './staff-route-shell.tsx'; import './section-layout.css'; @@ -55,54 +56,45 @@ export const SectionLayout: React.FC = (props) => { // Defaults are added only when the consumer hasn't provided an entry with the same id. // Consumer-provided entries override defaults when ids conflict. // Build default page layouts from backend permissions. - // A menu item is only included when the corresponding permission is explicitly true. - // false, null, or undefined all result in the item being hidden and the route being unavailable. + // Fallback to JWT app roles when backend permissions are unavailable. const perms = auth?.permissions; - const defaultPageLayouts: PageLayoutProps[] = [ - ...(perms?.canManageCommunities === true - ? [ - { - path: '/staff/community-management', - title: 'Communities', - icon: , - id: 'ROOT', - }, - ] - : []), - ...(perms?.canManageUsers === true - ? [ - { - path: '/staff/user-management/*', - title: 'Users', - icon: , - id: 'users', - parent: 'ROOT', - }, - ] - : []), - ...(perms?.canManageFinance === true - ? [ - { - path: '/staff/finance/*', - title: 'Finance', - icon: , - id: 'finance', - parent: 'ROOT', - }, - ] - : []), - ...(perms?.canManageTechAdmin === true - ? [ - { - path: '/staff/tech/*', - title: 'Tech Admin', - icon: , - id: 'tech', - parent: 'ROOT', - }, - ] - : []), - ]; + const roles = auth?.roles ?? extractRoles(auth?.raw); + const hasAnyRoleFor = (route: keyof typeof staffRouteRoles): boolean => { + const requiredRoles = staffRouteRoles[route]; + return roles?.some((userRole) => requiredRoles.some((requiredRole) => requiredRole === userRole)) === true; + }; + + const canManageCommunities = perms?.canManageCommunities ?? hasAnyRoleFor('/staff/community-management'); + const canManageUsers = perms?.canManageUsers ?? hasAnyRoleFor('/staff/user-management'); + const canManageFinance = perms?.canManageFinance ?? hasAnyRoleFor('/staff/finance'); + const canManageTechAdmin = perms?.canManageTechAdmin ?? hasAnyRoleFor('/staff/tech'); + const nestedParentProps = canManageCommunities ? { parent: 'ROOT' as const } : {}; + + // Construct default page layouts ensuring a ROOT entry always exists so MenuComponent renders. + // If Communities is allowed, keep the historic behaviour: Communities is ROOT and others are its children. + // Otherwise, promote the first available section to ROOT so a finance-only user sees a single Finance item. + const defaultPageLayouts: PageLayoutProps[] = []; + + if (canManageCommunities) { + // Communities as canonical root, others as children + defaultPageLayouts.push({ path: '/staff/community-management', title: 'Communities', icon: , id: 'ROOT' }); + if (canManageUsers) defaultPageLayouts.push({ path: '/staff/user-management/*', title: 'Users', icon: , id: 'users', ...nestedParentProps }); + if (canManageFinance) defaultPageLayouts.push({ path: '/staff/finance/*', title: 'Finance', icon: , id: 'finance', ...nestedParentProps }); + if (canManageTechAdmin) defaultPageLayouts.push({ path: '/staff/tech/*', title: 'Tech Admin', icon: , id: 'tech', ...nestedParentProps }); + } else { + // No Communities root. Promote the first available section to ROOT to render a single top-level item. + if (canManageFinance) { + defaultPageLayouts.push({ path: '/staff/finance/*', title: 'Finance', icon: , id: 'ROOT' }); + // add others as children if present + if (canManageUsers) defaultPageLayouts.push({ path: '/staff/user-management/*', title: 'Users', icon: , id: 'users', parent: 'ROOT' }); + if (canManageTechAdmin) defaultPageLayouts.push({ path: '/staff/tech/*', title: 'Tech Admin', icon: , id: 'tech', parent: 'ROOT' }); + } else if (canManageUsers) { + defaultPageLayouts.push({ path: '/staff/user-management/*', title: 'Users', icon: , id: 'ROOT' }); + if (canManageTechAdmin) defaultPageLayouts.push({ path: '/staff/tech/*', title: 'Tech Admin', icon: , id: 'tech', parent: 'ROOT' }); + } else if (canManageTechAdmin) { + defaultPageLayouts.push({ path: '/staff/tech/*', title: 'Tech Admin', icon: , id: 'ROOT' }); + } + } // Build a map from default entries, then overlay consumer entries so consumers can override defaults. // When consumers provide an entry with the same id, merge it with the default so that From 2c6ff5e1f4d7ce281741f94518271603ff700f46 Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Tue, 12 May 2026 12:33:18 -0400 Subject: [PATCH 66/88] Removed staff-user-role csv file, refactored createDefaultRoles, updatedAuthLnading component --- apps/ui-staff/e2e/role-authorization.spec.ts | 288 ------------------ apps/ui-staff/playwright.config.ts | 24 -- apps/ui-staff/src/App.tsx | 17 +- .../ui/molecules/auth-landing/index.tsx | 50 +-- codegen.yml | 1 + .../staff-role/create-default-roles.test.ts | 7 +- .../user/staff-role/create-default-roles.ts | 66 +--- .../features/create-default-roles.feature | 4 +- .../staff-role/staff-role-defaults.test.ts | 121 ++++++++ .../contexts/user/staff-role/staff-role.ts | 82 +++++ .../src/schema/types/staff-user.resolvers.ts | 4 +- packages/ocom/ui-staff-shared/package.json | 1 + packages/ocom/ui-staff-shared/src/index.tsx | 27 +- .../ui-staff-shared/src/require-role.test.tsx | 104 +++++-- .../ocom/ui-staff-shared/src/require-role.tsx | 89 ++++-- .../ui-staff-shared/src/section-layout.tsx | 16 +- pnpm-lock.yaml | 3 + staff-user-role.csv | 132 -------- 18 files changed, 410 insertions(+), 626 deletions(-) delete mode 100644 apps/ui-staff/e2e/role-authorization.spec.ts delete mode 100644 apps/ui-staff/playwright.config.ts create mode 100644 packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-defaults.test.ts delete mode 100644 staff-user-role.csv diff --git a/apps/ui-staff/e2e/role-authorization.spec.ts b/apps/ui-staff/e2e/role-authorization.spec.ts deleted file mode 100644 index c51484f05..000000000 --- a/apps/ui-staff/e2e/role-authorization.spec.ts +++ /dev/null @@ -1,288 +0,0 @@ -/** - * Playwright e2e tests: Entra app-role route authorization for the ui-staff portal. - * - * Strategy: inject a fake OIDC session directly into sessionStorage before page load. - * This lets us test every role × route combination without restarting the mock auth server. - * - * The OIDC authority / client_id values must match apps/ui-staff/src/config/oidc-config.tsx. - */ -import { expect, type Page, test } from '@playwright/test'; - -// --- Constants matching oidc-config.tsx --- -const AUTHORITY = 'https://mock-auth.ownercommunity.localhost:1355/staff'; -const CLIENT_ID = 'mock-client'; -const STORAGE_KEY = `oidc.user:${AUTHORITY}:${CLIENT_ID}`; - -// --- Helpers --- - -function b64url(obj: Record): string { - return Buffer.from(JSON.stringify(obj)).toString('base64url'); -} - -/** - * Builds a minimal but structurally valid OIDC User JSON suitable for - * sessionStorage injection. oidc-client-ts restores stored users without - * re-validating the JWT signature, so the token strings only need to be - * three-part base64url values. - */ -function buildOidcSession(roles: string[], name = 'Test User', email = 'testuser@example.com'): string { - const now = Math.floor(Date.now() / 1000); - const exp = now + 3600; // 1 hour from now — prevents automatic silent refresh - const profile = { - sub: 'test-user-id', - iss: AUTHORITY, - aud: CLIENT_ID, - exp, - iat: now, - name, - email, - roles, - }; - const header = b64url({ alg: 'RS256', typ: 'JWT' }); - const payload = b64url(profile); - // Signature is not validated on storage restore — use a placeholder - const fakeJwt = `${header}.${payload}.fakeSignatureForE2ETesting`; - - return JSON.stringify({ - id_token: fakeJwt, - session_state: null, - access_token: fakeJwt, - refresh_token: null, - token_type: 'Bearer', - scope: 'openid', - profile, - expires_at: exp, - }); -} - -/** Injects an OIDC session into sessionStorage before any page script runs. */ -async function injectOidcSession(page: Page, roles: string[]): Promise { - const sessionValue = buildOidcSession(roles); - await page.addInitScript( - ({ key, value }: { key: string; value: string }) => { - sessionStorage.setItem(key, value); - }, - { key: STORAGE_KEY, value: sessionValue }, - ); -} - -// --- Test matrix --- - -const ROUTES = { - community: '/staff/community-management', - users: '/staff/user-management', - finance: '/staff/finance', - tech: '/staff/tech', -} as const; - -const ROLES = { - TechAdmin: 'Staff.TechAdmin', - Finance: 'Staff.Finance', - ServiceLineOwner: 'Staff.ServiceLineOwner', - CaseManager: 'Staff.CaseManager', -} as const; - -/** - * Navigates to a path and waits for the React app to have rendered meaningful content. - * Guards against the portless proxy returning a 404 before the app is registered. - */ -async function navigateTo(page: Page, path: string): Promise { - await page.goto(path, { waitUntil: 'domcontentloaded' }); - // Wait for the React root to contain rendered content (i.e., the app mounted) - await page.waitForFunction( - () => { - const root = document.getElementById('root'); - return root && root.childElementCount > 0; - }, - { timeout: 8000 }, - ); -} - -/** The section title is rendered as a heading — use heading role to avoid matching nav labels. */ -async function expectAuthorized(page: Page, sectionTitle: string): Promise { - // The StaffRouteShell renders the section title as a plain div with fontSize 22px, - // so we find it by its exact text within the header area. - await expect(page.getByText(sectionTitle, { exact: true }).first()).toBeVisible({ timeout: 8000 }); - await expect(page.locator('h2').filter({ hasText: 'Unauthorized' })).not.toBeVisible(); -} - -async function expectUnauthorized(page: Page): Promise { - await expect(page.locator('h2').filter({ hasText: 'Unauthorized' })).toBeVisible({ timeout: 8000 }); - await expect(page.getByText('You do not have permission to view this page.')).toBeVisible(); -} - -// ============================================================ -// Staff.TechAdmin -// ============================================================ -test.describe('Staff.TechAdmin role', () => { - test.beforeEach(async ({ page }) => { - await injectOidcSession(page, [ROLES.TechAdmin]); - }); - - test('can access /staff/tech', async ({ page }) => { - await navigateTo(page, ROUTES.tech); - await expectAuthorized(page, 'Tech Admin'); - }); - - test('can access /staff/finance', async ({ page }) => { - await navigateTo(page, ROUTES.finance); - await expectAuthorized(page, 'Finance'); - }); - - test('can access /staff/community-management', async ({ page }) => { - await navigateTo(page, ROUTES.community); - await expectAuthorized(page, 'Community Management'); - }); - - test('can access /staff/user-management', async ({ page }) => { - await navigateTo(page, ROUTES.users); - await expectAuthorized(page, 'User Management'); - }); -}); - -// ============================================================ -// Staff.Finance -// ============================================================ -test.describe('Staff.Finance role', () => { - test.beforeEach(async ({ page }) => { - await injectOidcSession(page, [ROLES.Finance]); - }); - - test('can access /staff/finance', async ({ page }) => { - await navigateTo(page, ROUTES.finance); - await expectAuthorized(page, 'Finance'); - }); - - test('is denied /staff/tech', async ({ page }) => { - await navigateTo(page, ROUTES.tech); - await expectUnauthorized(page); - }); - - test('is denied /staff/community-management', async ({ page }) => { - await navigateTo(page, ROUTES.community); - await expectUnauthorized(page); - }); - - test('is denied /staff/user-management', async ({ page }) => { - await navigateTo(page, ROUTES.users); - await expectUnauthorized(page); - }); -}); - -// ============================================================ -// Staff.CaseManager -// ============================================================ -test.describe('Staff.CaseManager role', () => { - test.beforeEach(async ({ page }) => { - await injectOidcSession(page, [ROLES.CaseManager]); - }); - - test('can access /staff/community-management', async ({ page }) => { - await navigateTo(page, ROUTES.community); - await expectAuthorized(page, 'Community Management'); - }); - - test('can access /staff/user-management', async ({ page }) => { - await navigateTo(page, ROUTES.users); - await expectAuthorized(page, 'User Management'); - }); - - test('is denied /staff/finance', async ({ page }) => { - await navigateTo(page, ROUTES.finance); - await expectUnauthorized(page); - }); - - test('is denied /staff/tech', async ({ page }) => { - await navigateTo(page, ROUTES.tech); - await expectUnauthorized(page); - }); -}); - -// ============================================================ -// Staff.ServiceLineOwner -// ============================================================ -test.describe('Staff.ServiceLineOwner role', () => { - test.beforeEach(async ({ page }) => { - await injectOidcSession(page, [ROLES.ServiceLineOwner]); - }); - - test('can access /staff/community-management', async ({ page }) => { - await navigateTo(page, ROUTES.community); - await expectAuthorized(page, 'Community Management'); - }); - - test('can access /staff/user-management', async ({ page }) => { - await navigateTo(page, ROUTES.users); - await expectAuthorized(page, 'User Management'); - }); - - test('is denied /staff/finance', async ({ page }) => { - await navigateTo(page, ROUTES.finance); - await expectUnauthorized(page); - }); - - test('is denied /staff/tech', async ({ page }) => { - await navigateTo(page, ROUTES.tech); - await expectUnauthorized(page); - }); -}); - -// ============================================================ -// No roles (authenticated but no app roles) -// ============================================================ -test.describe('No app roles (authenticated, no roles)', () => { - test.beforeEach(async ({ page }) => { - await injectOidcSession(page, []); - }); - - test('is denied /staff/community-management', async ({ page }) => { - await navigateTo(page, ROUTES.community); - await expectUnauthorized(page); - }); - - test('is denied /staff/user-management', async ({ page }) => { - await navigateTo(page, ROUTES.users); - await expectUnauthorized(page); - }); - - test('is denied /staff/finance', async ({ page }) => { - await navigateTo(page, ROUTES.finance); - await expectUnauthorized(page); - }); - - test('is denied /staff/tech', async ({ page }) => { - await navigateTo(page, ROUTES.tech); - await expectUnauthorized(page); - }); -}); - -// ============================================================ -// Nav link visibility -// ============================================================ -test.describe('Nav link visibility in StaffRouteShell', () => { - test('TechAdmin sees only Tech Admin nav link', async ({ page }) => { - await injectOidcSession(page, [ROLES.TechAdmin]); - await navigateTo(page, ROUTES.tech); - await expect(page.getByRole('link', { name: 'Tech Admin' })).toBeVisible({ timeout: 5000 }); - await expect(page.getByRole('link', { name: 'Finance' })).not.toBeVisible(); - await expect(page.getByRole('link', { name: 'Community Management' })).not.toBeVisible(); - await expect(page.getByRole('link', { name: 'User Management' })).not.toBeVisible(); - }); - - test('Finance sees only Finance nav link', async ({ page }) => { - await injectOidcSession(page, [ROLES.Finance]); - await navigateTo(page, ROUTES.finance); - await expect(page.getByRole('link', { name: 'Finance' })).toBeVisible({ timeout: 5000 }); - await expect(page.getByRole('link', { name: 'Tech Admin' })).not.toBeVisible(); - await expect(page.getByRole('link', { name: 'Community Management' })).not.toBeVisible(); - }); - - test('CaseManager sees Community Management and User Management nav links', async ({ page }) => { - await injectOidcSession(page, [ROLES.CaseManager]); - await navigateTo(page, ROUTES.community); - await expect(page.getByRole('link', { name: 'Community Management' })).toBeVisible({ timeout: 5000 }); - await expect(page.getByRole('link', { name: 'User Management' })).toBeVisible({ timeout: 5000 }); - await expect(page.getByRole('link', { name: 'Finance' })).not.toBeVisible(); - await expect(page.getByRole('link', { name: 'Tech Admin' })).not.toBeVisible(); - }); -}); diff --git a/apps/ui-staff/playwright.config.ts b/apps/ui-staff/playwright.config.ts deleted file mode 100644 index a22e590e5..000000000 --- a/apps/ui-staff/playwright.config.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { defineConfig, devices } from '@playwright/test'; - -/** - * Playwright e2e configuration for the ui-staff portal. - * Tests inject OIDC sessions into sessionStorage directly — no real auth flow required. - * The dev server must be running (`pnpm run dev`) before executing these tests. - */ -export default defineConfig({ - testDir: './e2e', - fullyParallel: false, - retries: 0, - reporter: 'list', - use: { - baseURL: 'https://staff.ownercommunity.localhost:1355', - ignoreHTTPSErrors: true, - trace: 'on-first-retry', - }, - projects: [ - { - name: 'chromium', - use: { ...devices['Desktop Chrome'] }, - }, - ], -}); diff --git a/apps/ui-staff/src/App.tsx b/apps/ui-staff/src/App.tsx index 3572b552e..71773aed9 100644 --- a/apps/ui-staff/src/App.tsx +++ b/apps/ui-staff/src/App.tsx @@ -5,7 +5,7 @@ import { Root as Finance } from '@ocom/ui-staff-route-finance'; import { Root } from '@ocom/ui-staff-route-root'; import { Root as TechAdmin } from '@ocom/ui-staff-route-tech-admin'; import { Root as UserManagement } from '@ocom/ui-staff-route-user-management'; -import { extractRoles, StaffAuthContext, StaffAuthProvider, staffRouteRoles } from '@ocom/ui-staff-shared'; +import { StaffAuthContext, StaffAuthProvider } from '@ocom/ui-staff-shared'; import { Spin } from 'antd'; import { useContext } from 'react'; import { useAuth } from 'react-oidc-context'; @@ -20,17 +20,10 @@ import { Unauthorized } from './unauthorized.tsx'; function StaffRoutes() { const auth = useContext(StaffAuthContext); const perms = auth?.permissions; - const roles = auth?.roles ?? extractRoles(auth?.raw); - - const hasAnyRoleFor = (route: keyof typeof staffRouteRoles): boolean => { - const requiredRoles = staffRouteRoles[route]; - return roles?.some((userRole) => requiredRoles.some((requiredRole) => requiredRole === userRole)) === true; - }; - - const canManageCommunities = perms?.canManageCommunities ?? hasAnyRoleFor('/staff/community-management'); - const canManageUsers = perms?.canManageUsers ?? hasAnyRoleFor('/staff/user-management'); - const canManageFinance = perms?.canManageFinance ?? hasAnyRoleFor('/staff/finance'); - const canManageTechAdmin = perms?.canManageTechAdmin ?? hasAnyRoleFor('/staff/tech'); + const canManageCommunities = perms?.canManageCommunities === true; + const canManageUsers = perms?.canManageUsers === true; + const canManageFinance = perms?.canManageFinance === true; + const canManageTechAdmin = perms?.canManageTechAdmin === true; let defaultStaffRoute = '/unauthorized'; if (canManageTechAdmin) { diff --git a/apps/ui-staff/src/components/ui/molecules/auth-landing/index.tsx b/apps/ui-staff/src/components/ui/molecules/auth-landing/index.tsx index 50bddccc3..41fc0aa53 100644 --- a/apps/ui-staff/src/components/ui/molecules/auth-landing/index.tsx +++ b/apps/ui-staff/src/components/ui/molecules/auth-landing/index.tsx @@ -1,28 +1,42 @@ -import { useAuth } from 'react-oidc-context'; +import { Spin } from 'antd'; import { Navigate } from 'react-router-dom'; -import { extractRoles, staffRouteRoles } from '@ocom/ui-staff-shared'; +import { useStaffPermissions } from '../../../../hooks/use-staff-permissions.ts'; export const AuthLanding: React.FC = () => { - const auth = useAuth(); + const { permissions, loading, error } = useStaffPermissions(); - // Extract roles from the OIDC profile - const roles = extractRoles((auth?.user?.profile as Record) ?? undefined); + if (loading) { + return ( +
    + +
    + ); + } - // Find the first accessible route based on user roles - // Order: tech > finance > community-management, user-management - const routePaths = ['/staff/tech', '/staff/finance', '/staff/community-management', '/staff/user-management']; + if (error) { + return ( + + ); + } let targetRoute = '/unauthorized'; - - if (roles && roles.length > 0) { - for (const route of routePaths) { - const requiredRoles = staffRouteRoles[route as keyof typeof staffRouteRoles]; - if (requiredRoles && requiredRoles.some((role) => roles.includes(role))) { - targetRoute = route; - break; - } - } + if (permissions?.canManageTechAdmin) { + targetRoute = '/staff/tech'; + } else if (permissions?.canManageFinance) { + targetRoute = '/staff/finance'; + } else if (permissions?.canManageCommunities) { + targetRoute = '/staff/community-management'; + } else if (permissions?.canManageUsers) { + targetRoute = '/staff/user-management'; } - return ; + return ( + + ); }; diff --git a/codegen.yml b/codegen.yml index cd441b5ae..3bc21582c 100644 --- a/codegen.yml +++ b/codegen.yml @@ -72,6 +72,7 @@ generates: Community: "import('@ocom/domain').Domain.Contexts.Community.Community.CommunityEntityReference" EndUser: "import('@ocom/domain').Domain.Contexts.User.EndUser.EndUserEntityReference" EndUserRole: "import('@ocom/domain').Domain.Contexts.Community.Role.EndUserRole.EndUserRoleEntityReference" + StaffUser: "import('@ocom/domain').Domain.Contexts.User.StaffUser.StaffUserEntityReference" plugins: - typescript - typescript-resolvers diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts index 01ebdb942..6e599d168 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts @@ -114,6 +114,7 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { And('it should return all four created role references', () => { expect(result).toHaveLength(4); + for (const r of result) expect(r.isDefault).toBe(true); }); }); @@ -339,7 +340,7 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { // ─── isDefault false ────────────────────────────────────────────────────── - Scenario('All created roles have isDefault set to false', ({ Given, When, Then }) => { + Scenario('All created roles have isDefault set to true', ({ Given, When, Then }) => { Given('no staff roles exist', () => { mockRepo = makeMockRepo([]); dataSources = makeDataSources(mockRepo); @@ -349,9 +350,9 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { result = await createDefaultRoles(dataSources)(); }); - Then('all created roles should have isDefault false', () => { + Then('all created roles should have isDefault true', () => { for (const role of result) { - expect(role.isDefault).toBe(false); + expect(role.isDefault).toBe(true); } }); }); diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts index ef5131d33..7330560e8 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts @@ -1,4 +1,5 @@ import type { Domain } from '@ocom/domain'; +import { Domain as DomainRuntime } from '@ocom/domain'; import type { DataSources } from '@ocom/persistence'; export const StaffAppRoleNames = { @@ -10,50 +11,6 @@ export const StaffAppRoleNames = { export type StaffAppRoleName = (typeof StaffAppRoleNames)[keyof typeof StaffAppRoleNames]; -interface DefaultRoleSpec { - roleName: StaffAppRoleName; - isDefault: boolean; - communityPermissions: { canManageCommunities: boolean }; - financePermissions: { canManageFinance: boolean }; - techAdminPermissions: { canManageTechAdmin: boolean }; - userPermissions: { canManageUsers: boolean }; -} - -const DEFAULT_ROLE_SPECS: DefaultRoleSpec[] = [ - { - roleName: StaffAppRoleNames.CaseManager, - isDefault: false, - communityPermissions: { canManageCommunities: true }, - financePermissions: { canManageFinance: false }, - techAdminPermissions: { canManageTechAdmin: false }, - userPermissions: { canManageUsers: true }, - }, - { - roleName: StaffAppRoleNames.ServiceLineOwner, - isDefault: false, - communityPermissions: { canManageCommunities: true }, - financePermissions: { canManageFinance: false }, - techAdminPermissions: { canManageTechAdmin: false }, - userPermissions: { canManageUsers: true }, - }, - { - roleName: StaffAppRoleNames.Finance, - isDefault: false, - communityPermissions: { canManageCommunities: false }, - financePermissions: { canManageFinance: true }, - techAdminPermissions: { canManageTechAdmin: false }, - userPermissions: { canManageUsers: false }, - }, - { - roleName: StaffAppRoleNames.TechAdmin, - isDefault: false, - communityPermissions: { canManageCommunities: false }, - financePermissions: { canManageFinance: false }, - techAdminPermissions: { canManageTechAdmin: true }, - userPermissions: { canManageUsers: false }, - }, -]; - const roleExists = async (repository: Domain.Contexts.User.StaffRole.StaffRoleRepository, roleName: string): Promise => { try { await repository.getByRoleName(roleName); @@ -66,29 +23,22 @@ const roleExists = async (repository: Domain.Contexts.User.StaffRole.StaffRoleRe } }; -const applyDefaultPermissions = (staffRole: Domain.Contexts.User.StaffRole.StaffRole, spec: DefaultRoleSpec): void => { - staffRole.permissions.communityPermissions.canManageCommunities = spec.communityPermissions.canManageCommunities; - staffRole.permissions.financePermissions.canManageFinance = spec.financePermissions.canManageFinance; - staffRole.permissions.techAdminPermissions.canManageTechAdmin = spec.techAdminPermissions.canManageTechAdmin; - staffRole.permissions.userPermissions.canManageUsers = spec.userPermissions.canManageUsers; -}; - export const createDefaultRoles = (dataSources: DataSources) => { return async (): Promise => { const created: Domain.Contexts.User.StaffRole.StaffRoleEntityReference[] = []; await dataSources.domainDataSource.User.StaffRole.StaffRoleUnitOfWork.withScopedTransaction(async (repository) => { - for (const spec of DEFAULT_ROLE_SPECS) { - const exists = await roleExists(repository, spec.roleName); + const defaultRoleSpecs = DomainRuntime.Contexts.User.StaffRole.StaffRole.getDefaultRoleSpecs(); + for (const defaultRoleSpec of defaultRoleSpecs) { + const { roleName } = defaultRoleSpec; + const exists = await roleExists(repository, roleName); if (exists) { continue; } - const staffRole = await repository.getNewInstance(spec.roleName); - staffRole.isDefault = spec.isDefault; - applyDefaultPermissions(staffRole, spec); - - const saved = await repository.save(staffRole); + const staffRole = await repository.getNewInstance(roleName); + defaultRoleSpec.apply(staffRole); + const saved: Domain.Contexts.User.StaffRole.StaffRoleEntityReference = await repository.save(staffRole); created.push(saved); } }); diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/features/create-default-roles.feature b/packages/ocom/application-services/src/contexts/user/staff-role/features/create-default-roles.feature index dc923cca5..d334f032f 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-role/features/create-default-roles.feature +++ b/packages/ocom/application-services/src/contexts/user/staff-role/features/create-default-roles.feature @@ -50,10 +50,10 @@ Feature: Creating default staff roles And the "Staff.ServiceLineOwner" role should have canManageTechAdmin false And the "Staff.ServiceLineOwner" role should have canManageUsers true - Scenario: All created roles have isDefault set to false + Scenario: All created roles have isDefault set to true Given no staff roles exist When I call createDefaultRoles - Then all created roles should have isDefault false + Then all created roles should have isDefault true Scenario: Propagates unexpected repository errors Given no staff roles exist diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-defaults.test.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-defaults.test.ts new file mode 100644 index 000000000..093bf22a6 --- /dev/null +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-defaults.test.ts @@ -0,0 +1,121 @@ +import { expect, test } from 'vitest'; +import type { Passport } from '../../passport.ts'; +import { StaffRole, type StaffRoleProps } from './staff-role.ts'; + +function makePassport(): Passport { + return { + user: { + forStaffRole: () => ({ + determineIf: (fn: (p: { canManageStaffRolesAndPermissions: boolean; isSystemAccount: boolean }) => boolean) => fn({ canManageStaffRolesAndPermissions: true, isSystemAccount: false }), + }), + }, + } as unknown as Passport; +} + +function makeBaseProps(overrides: Partial = {}): StaffRoleProps { + const emptyPermissions = { + communityPermissions: { + canManageCommunities: false, + canManageStaffRolesAndPermissions: false, + canManageAllCommunities: false, + canDeleteCommunities: false, + canChangeCommunityOwner: false, + canReIndexSearchCollections: false, + }, + propertyPermissions: { + canManageProperties: false, + canEditOwnProperty: false, + }, + serviceTicketPermissions: { + canCreateTickets: false, + canManageTickets: false, + canAssignTickets: false, + canWorkOnTickets: false, + }, + servicePermissions: { + canManageServices: false, + }, + violationTicketPermissions: { + canCreateTickets: false, + canManageTickets: false, + canAssignTickets: false, + canWorkOnTickets: false, + }, + financePermissions: { + canManageFinance: false, + canViewGLBatchSummaries: false, + canViewFinanceConfigs: false, + canCreateFinanceConfigs: false, + }, + techAdminPermissions: { + canManageTechAdmin: false, + }, + userPermissions: { + canManageUsers: false, + }, + } as const; + + return { + id: 'role-1', + roleName: 'Support', + isDefault: false, + permissions: emptyPermissions as unknown as StaffRoleProps['permissions'], + roleType: 'staff-role', + createdAt: new Date(), + updatedAt: new Date(), + schemaVersion: '1.0', + ...overrides, + }; +} + +test('applyDefaultSpec sets CaseManager permissions correctly and marks default', () => { + const passport = makePassport(); + const role = StaffRole.getNewInstance(makeBaseProps(), passport, 'Staff.CaseManager', false); + + StaffRole.applyDefaultSpec(role, 'Staff.CaseManager'); + + expect(role.permissions.communityPermissions.canManageCommunities).toBe(true); + expect(role.permissions.financePermissions.canManageFinance).toBe(false); + expect(role.permissions.techAdminPermissions.canManageTechAdmin).toBe(false); + expect(role.permissions.userPermissions.canManageUsers).toBe(true); + expect(role.isDefault).toBe(true); +}); + +test('applyDefaultSpec sets Finance permissions correctly and marks default', () => { + const passport = makePassport(); + const role = StaffRole.getNewInstance(makeBaseProps(), passport, 'Staff.Finance', false); + + StaffRole.applyDefaultSpec(role, 'Staff.Finance'); + + expect(role.permissions.communityPermissions.canManageCommunities).toBe(false); + expect(role.permissions.financePermissions.canManageFinance).toBe(true); + expect(role.permissions.techAdminPermissions.canManageTechAdmin).toBe(false); + expect(role.permissions.userPermissions.canManageUsers).toBe(false); + expect(role.isDefault).toBe(true); +}); + +test('applyDefaultSpec sets ServiceLineOwner permissions correctly and marks default', () => { + const passport = makePassport(); + const role = StaffRole.getNewInstance(makeBaseProps(), passport, 'Staff.ServiceLineOwner', false); + + StaffRole.applyDefaultSpec(role, 'Staff.ServiceLineOwner'); + + expect(role.permissions.communityPermissions.canManageCommunities).toBe(true); + expect(role.permissions.financePermissions.canManageFinance).toBe(false); + expect(role.permissions.techAdminPermissions.canManageTechAdmin).toBe(false); + expect(role.permissions.userPermissions.canManageUsers).toBe(true); + expect(role.isDefault).toBe(true); +}); + +test('applyDefaultSpec sets TechAdmin permissions correctly and marks default', () => { + const passport = makePassport(); + const role = StaffRole.getNewInstance(makeBaseProps(), passport, 'Staff.TechAdmin', false); + + StaffRole.applyDefaultSpec(role, 'Staff.TechAdmin'); + + expect(role.permissions.communityPermissions.canManageCommunities).toBe(false); + expect(role.permissions.financePermissions.canManageFinance).toBe(false); + expect(role.permissions.techAdminPermissions.canManageTechAdmin).toBe(true); + expect(role.permissions.userPermissions.canManageUsers).toBe(false); + expect(role.isDefault).toBe(true); +}); diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts index 49912c977..e2de1dbcc 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts @@ -21,6 +21,11 @@ export interface StaffRoleEntityReference extends Readonly) => void; +}>; + export class StaffRole extends AggregateRoot implements StaffRoleEntityReference { private isNew: boolean = false; private readonly visa: UserVisa; @@ -37,6 +42,83 @@ export class StaffRole extends AggregateRoot spec.roleName); + } + + public static getDefaultRoleSpecs(): DefaultRoleSpec[] { + return [ + { roleName: 'Staff.CaseManager', apply: StaffRole.applyCaseManagerDefaultSpec }, + { roleName: 'Staff.ServiceLineOwner', apply: StaffRole.applyServiceLineOwnerDefaultSpec }, + { roleName: 'Staff.Finance', apply: StaffRole.applyFinanceDefaultSpec }, + { roleName: 'Staff.TechAdmin', apply: StaffRole.applyTechAdminDefaultSpec }, + ]; + } + + public static applyCaseManagerDefaultSpec(staffRole: StaffRole): void { + staffRole.permissions.communityPermissions.canManageCommunities = true; + staffRole.permissions.financePermissions.canManageFinance = false; + staffRole.permissions.techAdminPermissions.canManageTechAdmin = false; + staffRole.permissions.userPermissions.canManageUsers = true; + staffRole.isDefault = true; + } + + public static applyServiceLineOwnerDefaultSpec(staffRole: StaffRole): void { + staffRole.permissions.communityPermissions.canManageCommunities = true; + staffRole.permissions.financePermissions.canManageFinance = false; + staffRole.permissions.techAdminPermissions.canManageTechAdmin = false; + staffRole.permissions.userPermissions.canManageUsers = true; + staffRole.isDefault = true; + } + + public static applyFinanceDefaultSpec(staffRole: StaffRole): void { + staffRole.permissions.communityPermissions.canManageCommunities = false; + staffRole.permissions.financePermissions.canManageFinance = true; + staffRole.permissions.techAdminPermissions.canManageTechAdmin = false; + staffRole.permissions.userPermissions.canManageUsers = false; + staffRole.isDefault = true; + } + + public static applyTechAdminDefaultSpec(staffRole: StaffRole): void { + staffRole.permissions.communityPermissions.canManageCommunities = false; + staffRole.permissions.financePermissions.canManageFinance = false; + staffRole.permissions.techAdminPermissions.canManageTechAdmin = true; + staffRole.permissions.userPermissions.canManageUsers = false; + staffRole.isDefault = true; + } + + /** + * Applies the domain-defined default permissions for a given default role name onto the provided StaffRole instance. + * This keeps the default-spec knowledge inside the domain layer and avoids leaking permission shapes to the application layer. + */ + public static applyDefaultSpec(staffRole: StaffRole, roleName: string): void { + // Do not unmark defaults here. applyDefaultSpec should only mark canonical defaults as default and + // set permission shapes directly on the underlying props to avoid visa-guarded setters during bootstrapping. + + // When bootstrapping defaults, mutate the aggregate directly. We intentionally avoid clearing isDefault here. + + switch (roleName) { + case 'Staff.CaseManager': + StaffRole.applyCaseManagerDefaultSpec(staffRole); + break; + case 'Staff.ServiceLineOwner': + StaffRole.applyServiceLineOwnerDefaultSpec(staffRole); + break; + case 'Staff.Finance': + StaffRole.applyFinanceDefaultSpec(staffRole); + break; + case 'Staff.TechAdmin': + StaffRole.applyTechAdminDefaultSpec(staffRole); + break; + default: + // Unknown default spec: do nothing + break; + } + } public deleteAndReassignTo(roleRef: StaffRoleEntityReference) { if (this.isDefault) { throw new PermissionError('You cannot delete a default staff role'); diff --git a/packages/ocom/graphql/src/schema/types/staff-user.resolvers.ts b/packages/ocom/graphql/src/schema/types/staff-user.resolvers.ts index c935de243..38be5afa1 100644 --- a/packages/ocom/graphql/src/schema/types/staff-user.resolvers.ts +++ b/packages/ocom/graphql/src/schema/types/staff-user.resolvers.ts @@ -1,5 +1,5 @@ import type { GraphQLResolveInfo } from 'graphql'; -import type { Resolvers, StaffUser } from '../builder/generated.ts'; +import type { Resolvers } from '../builder/generated.ts'; import type { GraphContext } from '../context.ts'; const staffUser: Resolvers = { @@ -16,7 +16,7 @@ const staffUser: Resolvers = { email: jwt.email ?? '', aadRoles: jwt.roles ?? [], }); - return result as unknown as StaffUser; + return result; }, }, }; diff --git a/packages/ocom/ui-staff-shared/package.json b/packages/ocom/ui-staff-shared/package.json index 84dcca5dc..a41405043 100644 --- a/packages/ocom/ui-staff-shared/package.json +++ b/packages/ocom/ui-staff-shared/package.json @@ -15,6 +15,7 @@ "test:watch": "vitest" }, "dependencies": { + "@apollo/client": "^3.13.9", "@ant-design/icons": "catalog:", "@ocom/ui-shared": "workspace:*", "react": "catalog:", diff --git a/packages/ocom/ui-staff-shared/src/index.tsx b/packages/ocom/ui-staff-shared/src/index.tsx index 4d5f0aaf0..539232dbf 100644 --- a/packages/ocom/ui-staff-shared/src/index.tsx +++ b/packages/ocom/ui-staff-shared/src/index.tsx @@ -21,20 +21,13 @@ import { StaffAuthContext } from './staff-route-shell.tsx'; export const PlaceholderPage: React.FC = ({ sectionName, description, expectedRoles, explicitRoles }) => { const auth = React.useContext(StaffAuthContext); - const resolvedRoles = React.useMemo(() => { + const resolvedPermissions = React.useMemo(() => { if (explicitRoles && explicitRoles.length > 0) return explicitRoles; - if (auth) { - const a = auth as StaffAuth; - if (Array.isArray(a.roles) && a.roles.length > 0) return a.roles as string[]; - type RawProfile = { roles?: unknown; role?: unknown }; - const raw = a.raw as RawProfile | undefined; - if (raw) { - const maybe = raw.roles ?? raw.role ?? undefined; - if (Array.isArray(maybe)) return maybe as string[]; - if (typeof maybe === 'string') return [maybe]; - } - } - return []; + const perms = auth?.permissions; + if (!perms) return []; + return Object.entries(perms) + .filter(([, isEnabled]) => isEnabled === true) + .map(([permKey]) => permKey); }, [auth, explicitRoles]); const identitySummary = React.useMemo<{ displayName: string; identifier: string | undefined } | null>(() => { @@ -72,11 +65,11 @@ export const PlaceholderPage: React.FC = ({ sectionName, descr )}
    -
    Resolved Roles
    - {resolvedRoles && resolvedRoles.length > 0 ? ( +
    Resolved Permissions
    + {resolvedPermissions.length > 0 ? (
      - {resolvedRoles.map((r) => ( -
    • {r}
    • + {resolvedPermissions.map((permission) => ( +
    • {permission}
    • ))}
    ) : ( diff --git a/packages/ocom/ui-staff-shared/src/require-role.test.tsx b/packages/ocom/ui-staff-shared/src/require-role.test.tsx index dac0b8b6f..25db78a99 100644 --- a/packages/ocom/ui-staff-shared/src/require-role.test.tsx +++ b/packages/ocom/ui-staff-shared/src/require-role.test.tsx @@ -1,33 +1,48 @@ import type * as React from 'react'; import { renderToString } from 'react-dom/server'; import { MemoryRouter } from 'react-router-dom'; -import { describe, expect, it } from 'vitest'; +import { beforeEach, describe, expect, it, vi } from 'vitest'; import { RequireRole } from './require-role.tsx'; import { StaffAuthProvider } from './staff-route-shell.tsx'; +const useQueryMock = vi.fn(); +vi.mock('@apollo/client', () => ({ + gql: (strings: TemplateStringsArray, ...values: unknown[]) => String.raw({ raw: strings }, ...values), + useQuery: (...args: unknown[]) => useQueryMock(...args), +})); + const Protected: React.FC = () =>
    protected content
    ; describe('RequireRole', () => { - it('renders children when user has a required role', () => { - const identity = { raw: { roles: ['Staff.TechAdmin'] } }; - const html = renderToString( - - - - - - - , - ); - expect(html).toContain('protected content'); + beforeEach(() => { + useQueryMock.mockReset(); }); - it('renders children when user holds one of multiple required roles', () => { - const identity = { raw: { roles: ['Staff.CaseManager'] } }; + it('renders children when the permission key is true', () => { + useQueryMock.mockReturnValue({ + loading: false, + error: undefined, + data: { + staffUserCurrent: { + role: { + permissions: { + communityPermissions: { canManageCommunities: false }, + userPermissions: { canManageUsers: false }, + financePermissions: { canManageFinance: false }, + techAdminPermissions: { canManageTechAdmin: true }, + }, + }, + }, + }, + }); + const identity = {}; const html = renderToString( - + @@ -36,12 +51,31 @@ describe('RequireRole', () => { expect(html).toContain('protected content'); }); - it('redirects to /unauthorized when user lacks required role', () => { - const identity = { raw: { roles: ['Staff.Finance'] } }; + it('redirects to /unauthorized when the permission key is false', () => { + useQueryMock.mockReturnValue({ + loading: false, + error: undefined, + data: { + staffUserCurrent: { + role: { + permissions: { + communityPermissions: { canManageCommunities: false }, + userPermissions: { canManageUsers: false }, + financePermissions: { canManageFinance: true }, + techAdminPermissions: { canManageTechAdmin: false }, + }, + }, + }, + }, + }); + const identity = {}; const html = renderToString( - + @@ -50,12 +84,20 @@ describe('RequireRole', () => { expect(html).not.toContain('protected content'); }); - it('redirects when user has no roles at all', () => { - const identity = { raw: {} }; + it('redirects to /unauthorized when query returns an error', () => { + useQueryMock.mockReturnValue({ + loading: false, + error: new Error('network error'), + data: undefined, + }); + const identity = {}; const html = renderToString( - + - + @@ -64,17 +106,25 @@ describe('RequireRole', () => { expect(html).not.toContain('protected content'); }); - it('renders children when roles array is empty (no restriction)', () => { - const identity = { raw: {} }; + it('does not render protected content while loading', () => { + useQueryMock.mockReturnValue({ + loading: true, + error: undefined, + data: undefined, + }); + const identity = {}; const html = renderToString( - + , ); - expect(html).toContain('protected content'); + expect(html).not.toContain('protected content'); }); }); diff --git a/packages/ocom/ui-staff-shared/src/require-role.tsx b/packages/ocom/ui-staff-shared/src/require-role.tsx index 309d7e227..71f2b6d02 100644 --- a/packages/ocom/ui-staff-shared/src/require-role.tsx +++ b/packages/ocom/ui-staff-shared/src/require-role.tsx @@ -1,47 +1,74 @@ -import { type FC, type ReactNode, useContext } from 'react'; +import { gql, useQuery } from '@apollo/client'; +import type { FC, ReactNode } from 'react'; import { Navigate } from 'react-router-dom'; -import { extractRoles } from './staff-app-roles.ts'; import type { StaffAuth } from './staff-route-shell.tsx'; -import { StaffAuthContext } from './staff-route-shell.tsx'; export interface RequireRoleProps { - /** At least one of these roles must be present in the authenticated user's token. */ + /** Deprecated. Frontend authorization must use backend permission flags. */ roles: readonly string[]; - /** When provided, gate by this backend permission flag instead of JWT roles. */ + /** Gate by backend permission flag. */ permKey?: keyof NonNullable; children: ReactNode; } -/** - * Guards a UI branch behind one or more Entra app roles, or a backend permission flag. - * - * When `permKey` is supplied and the `StaffAuthContext` already has a `permissions` object - * (populated from the backend), the permission flag takes precedence over JWT role strings. - * Falls back to the JWT role check when permissions are not yet available. - */ -export const RequireRole: FC = ({ roles, permKey, children }) => { - const auth = useContext(StaffAuthContext); - const perms = auth?.permissions; - - // Prefer backend permission flag when it has been fetched - if (permKey !== undefined && perms !== undefined) { - const isAuthorized = perms[permKey] === true; - if (!isAuthorized) { - return ( - - ); +const STAFF_USER_CURRENT_QUERY = gql` + query RequireRoleStaffUserCurrent { + staffUserCurrent: currentStaffUserAndCreateIfNotExists { + role { + permissions { + communityPermissions { + canManageCommunities + } + userPermissions { + canManageUsers + } + financePermissions { + canManageFinance + } + techAdminPermissions { + canManageTechAdmin + } + } + } } - return <>{children}; + } +`; + +interface StaffUserCurrentQueryResult { + staffUserCurrent: { + role?: { + permissions: { + communityPermissions: { canManageCommunities: boolean }; + userPermissions: { canManageUsers: boolean }; + financePermissions: { canManageFinance: boolean }; + techAdminPermissions: { canManageTechAdmin: boolean }; + }; + }; + }; +} + +export const RequireRole: FC = ({ roles, permKey, children }) => { + void roles; + const { data, loading, error } = useQuery(STAFF_USER_CURRENT_QUERY, { + fetchPolicy: 'cache-first', + }); + + if (loading) { + return null; } - // Fallback: check JWT roles - const userRoles = auth?.roles ?? extractRoles(auth?.raw); - const isAuthorized = roles.length === 0 || (userRoles !== undefined && roles.some((r) => userRoles.includes(r))); + const rolePermissions = data?.staffUserCurrent?.role?.permissions; + const permissions: NonNullable | undefined = rolePermissions + ? { + canManageCommunities: rolePermissions.communityPermissions.canManageCommunities, + canManageUsers: rolePermissions.userPermissions.canManageUsers, + canManageFinance: rolePermissions.financePermissions.canManageFinance, + canManageTechAdmin: rolePermissions.techAdminPermissions.canManageTechAdmin, + } + : undefined; + const isAuthorized = permKey !== undefined && permissions?.[permKey] === true; - if (!isAuthorized) { + if (error || !isAuthorized) { return ( = (props) => { // Defaults are added only when the consumer hasn't provided an entry with the same id. // Consumer-provided entries override defaults when ids conflict. // Build default page layouts from backend permissions. - // Fallback to JWT app roles when backend permissions are unavailable. const perms = auth?.permissions; - const roles = auth?.roles ?? extractRoles(auth?.raw); - const hasAnyRoleFor = (route: keyof typeof staffRouteRoles): boolean => { - const requiredRoles = staffRouteRoles[route]; - return roles?.some((userRole) => requiredRoles.some((requiredRole) => requiredRole === userRole)) === true; - }; - - const canManageCommunities = perms?.canManageCommunities ?? hasAnyRoleFor('/staff/community-management'); - const canManageUsers = perms?.canManageUsers ?? hasAnyRoleFor('/staff/user-management'); - const canManageFinance = perms?.canManageFinance ?? hasAnyRoleFor('/staff/finance'); - const canManageTechAdmin = perms?.canManageTechAdmin ?? hasAnyRoleFor('/staff/tech'); + const canManageCommunities = perms?.canManageCommunities === true; + const canManageUsers = perms?.canManageUsers === true; + const canManageFinance = perms?.canManageFinance === true; + const canManageTechAdmin = perms?.canManageTechAdmin === true; const nestedParentProps = canManageCommunities ? { parent: 'ROOT' as const } : {}; // Construct default page layouts ensuring a ROOT entry always exists so MenuComponent renders. diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a5a992bce..35f3c93af 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2321,6 +2321,9 @@ importers: '@ant-design/icons': specifier: 'catalog:' version: 6.1.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@apollo/client': + specifier: ^3.13.9 + version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@ocom/ui-shared': specifier: workspace:* version: link:../ui-shared diff --git a/staff-user-role.csv b/staff-user-role.csv deleted file mode 100644 index dcc670065..000000000 --- a/staff-user-role.csv +++ /dev/null @@ -1,132 +0,0 @@ -3Navigate Home,,,,,,,,,,,,,,,,, -collection:roles,,,,,,,,,,,,,,,,, -Staff User Role,Staff,,,,,,,,,,,,,,,, -Properties,,,DataType,Rules,,,,,,,,,,,,, -roleName,U,,"required, string, maxLength 256",,,,,,,,,,,,,, -isDefault,U,,"required, boolean, default false","omitted in the common case for user-created roles, only specified for system-created default roles",,,,,,,,,,,,, -roleType,U,,"required, string, default value = ""staff-user-role""",,,,,,,,,,,,,, -enterpriseAppRole,U,,"required, string,enum","""Staff.CaseManager"" | ""Staff.Finance"" | ""Staff.ServiceLineOwner"" | ""Staff.TechAdmin""",,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -permissions {,,,,,,,,,,,,,,,,, - communityPermissions {,,,,,,,,,,,,,,,,, - canManageCommunities,U,,"boolean, default false",,,,,,,,,,,,,, - canChanageCommunityOwner,U,,"boolean, default false",,,,,,,,,,,,,, - canDeleteCommunities,U,,"boolean, default false",,,,,,,,,,,,,, - canReIndexSearchCollections,U,,"boolean, default false",,,,,,,,,,,,,, - },,,,,,,,,,,,,,,,, - financePermissions {,,,,,,,,,,,,,,,,, - canManageFinance,U,,"boolean, default false",,,,,,,,,,,,,, - canViewGLBatchSummaries,U,,"boolean, default false",,,,,,,,,,,,,, - canViewFinanceConfigs,U,,"boolean, default false",,,,,,,,,,,,,, - canCreateFinanceConfigs,U,,"boolean, default false",,,,,,,,,,,,,, - },,,,,,,,,,,,,,,,, - servicePermissions {,,,,,,,,,,,,,,,,, - canManageServices,U,,"boolean, default false",,,,,,,,,,,,,, - },,,,,,,,,,,,,,,,, - serviceTicketPermissions {,,,,,,,,,,,,,,,,, - canManageTickets,U,,"boolean, default false",,,,,,,,,,,,,, - canCreateTickets,U,,"boolean, default false",,,,,,,,,,,,,, - canAssignTickets,U,,"boolean, default false",,,,,,,,,,,,,, - canUpdateTickets,U,,"boolean, default false",,,,,,,,,,,,,, - },,,,,,,,,,,,,,,,, - techAdminPermissions {,,,,,,,,,,,,,,,,, - canManageTechAdmin,U,,"boolean, default false",,,,,,,,,,,,,, - canViewDatabaseExplorer,U,,"boolean, default false",,,,,,,,,,,,,, - canViewBlobExplorer,U,,"boolean, default false",,,,,,,,,,,,,, - canViewQueueDashboard,U,,"boolean, default false",,,,,,,,,,,,,, - canSendQueueMessages,U,,"boolean, default false",,,,,,,,,,,,,, - },,,,,,,,,,,,,,,,, - userPermissions {,,,,,,,,,,,,,,,,, - canManageUsers,U,,"boolean, default false",,,,,,,,,,,,,, - },,,,,,,,,,,,,,,,, - violationTicketPermissions {,,,,,,,,,,,,,,,,, - canManageTickets,U,,"boolean, default false",,,,,,,,,,,,,, - canCreateTickets,U,,"boolean, default false",,,,,,,,,,,,,, - canAssignTickets,U,,"boolean, default false",,,,,,,,,,,,,, - canUpdateTickets,U,,"boolean, default false",,,,,,,,,,,,,, - },,,,,,,,,,,,,,,,, -},,,,,,,,,,,,,,,,, -schemaVersion,R,,"required, string, default value = ""1.0.0""",,,,,,,,,,,,,, -_id,R,,"required, unique identifier",,,,,,,,,,,,,, -createdAt,R,,"required, timestamp",,,,,,,,,,,,,, -updatedAt,R,,"required, timestamp",,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,, From 7af12a21e36528a7a76472a5407e0ae731b59f02 Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Tue, 12 May 2026 14:01:21 -0400 Subject: [PATCH 67/88] fix snyk issue --- package.json | 4 +- pnpm-lock.yaml | 228 ++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 209 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index ea3c6172c..fdd3a892c 100644 --- a/package.json +++ b/package.json @@ -125,7 +125,9 @@ "playwright": "1.59.0", "postcss": "8.5.10", "protobufjs": "7.5.5", - "ip-address": "^10.1.1" + "ip-address": "^10.1.1", + "fast-uri": "^3.1.2", + "webpack-dev-server": "^5.2.4" }, "patchedDependencies": { "@azure/functions@4.11.0": "patches/@azure__functions@4.11.0.patch" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 35f3c93af..e0ffc99a6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -126,6 +126,8 @@ overrides: postcss: 8.5.10 protobufjs: 7.5.5 ip-address: ^10.1.1 + fast-uri: ^3.1.2 + webpack-dev-server: ^5.2.4 patchedDependencies: '@azure/functions@4.11.0': @@ -4799,6 +4801,10 @@ packages: '@neoconfetti/react@1.0.0': resolution: {integrity: sha512-klcSooChXXOzIm+SE5IISIAn3bYzYfPjbX7D7HoqZL84oAfgREeSg5vSIaSFH+DaGzzvImTyWe1OyrJ67vik4A==} + '@noble/hashes@1.4.0': + resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} + engines: {node: '>= 16'} + '@noble/hashes@1.8.0': resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} engines: {node: ^14.21.3 || >=16} @@ -5389,6 +5395,43 @@ packages: resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==} engines: {node: '>= 10.0.0'} + '@peculiar/asn1-cms@2.7.0': + resolution: {integrity: sha512-hew63shtzzvBcSHbhm+cyAmKe6AIfinT9hzEqSPjDC6opTTMKmTkQ0gHuN2KsWlvqiKw1S/fS94fhag/FJkioQ==} + + '@peculiar/asn1-csr@2.7.0': + resolution: {integrity: sha512-VVsAyGqErT9D1SY4aEqozThXMVI+ssVRiv2DDeYuvpBKLIgZ3hYs3Ay3u/VSoKq6ESFi9cf6rf3IOOzfwh7oMA==} + + '@peculiar/asn1-ecc@2.7.0': + resolution: {integrity: sha512-n7KEs/Q/wrB415cxy4fHOBhegp4NdJ15fkJPwcB/3/8iNBQC2L/N7SChJPKDJPZGYH0jD4Tg4/0vnHmwghnbKw==} + + '@peculiar/asn1-pfx@2.7.0': + resolution: {integrity: sha512-V/nrlQVmhg7lYAsM7E13UDL5erAwFv6kCIVFqNaMIHSVi7dngcT839JkRTkQBqznMG98l2XjxYk74ZztAohZzA==} + + '@peculiar/asn1-pkcs8@2.7.0': + resolution: {integrity: sha512-9GTl1nE8Mx1kTZ+7QyYatDyKsm34QcWRBFkY1iPvWC3X4Dona5s/tlLiQsx5WzVdZqiMBZNYT0buyw4/vbhnjw==} + + '@peculiar/asn1-pkcs9@2.7.0': + resolution: {integrity: sha512-Bh7m+OuIaSEllPQcSd9OSp93F4ROWH7sbITWV8MI+8dwsjE5111/87VxiWVvYFKyww3vp39geLv9ENqhwWHcew==} + + '@peculiar/asn1-rsa@2.7.0': + resolution: {integrity: sha512-/qvENQrXyTZURjMqSeofHul0JJt2sNSzSwk36pl2olkHbaioMQgrASDZAlHXl0xUlnVbHj0uGgOrBMTb5x2aJQ==} + + '@peculiar/asn1-schema@2.7.0': + resolution: {integrity: sha512-W8ZfWzLmQnrcky+eh3tni4IozMdqBDiHWU0N+vve/UGjMaUs8c0L7A2oEdkBXS8rTpWDpK/aoI3DG/L/hxmxPg==} + + '@peculiar/asn1-x509-attr@2.7.0': + resolution: {integrity: sha512-NS8e7SOgXipkzUPLF/sce7ukpMpWjhxYsH0n6Y+bHYo4TTxOb95Zv7hqwSuL212mj5YxovjdOKQOgH1As3E94w==} + + '@peculiar/asn1-x509@2.7.0': + resolution: {integrity: sha512-mUn9RRrkGDnG4ALfunDmzyRW5dg+sWCj/pfnCCqEHYbkGxEpvUt6iVJv8Yw1cyp6SWZ26ZE5oSmI5SqEaen15g==} + + '@peculiar/utils@2.0.3': + resolution: {integrity: sha512-+oL3HPFRIZ1St2K50lWCXiioIgSoxzz7R1J3uF6neO2yl1sgmpgY6XXJH4BdpoDkMWznQTeYF6oWNDZLCdQ4eQ==} + + '@peculiar/x509@1.14.3': + resolution: {integrity: sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA==} + engines: {node: '>=20.0.0'} + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -6536,9 +6579,6 @@ packages: '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} - '@types/node-forge@1.3.14': - resolution: {integrity: sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==} - '@types/node@17.0.45': resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} @@ -7083,6 +7123,10 @@ packages: asap@2.0.6: resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + asn1js@3.0.10: + resolution: {integrity: sha512-S2s3aOytiKdFRdulw2qPE51MzjzVOisppcVv7jVFR+Kw0kxwvFrDcYA0h7Ndqbmj0HkMIXYWaoj7fli8kgx1eg==} + engines: {node: '>=12.0.0'} + assertion-error-formatter@3.0.0: resolution: {integrity: sha512-6YyAVLrEze0kQ7CmJfUgrLHb+Y7XghmL2Ie7ijVa2Y9ynP3LV+VDiwFk62Dn0qtqbmY0BT0ss6p1xxpiF2PYbQ==} @@ -7319,6 +7363,10 @@ packages: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} + bytestreamjs@2.0.1: + resolution: {integrity: sha512-U1Z/ob71V/bXfVABvNr/Kumf5VyeQRBEm6Txb0PQ6S7V5GpBM3w4Cbqz/xPDicR5tN0uvDifng8C+5qECeGwyQ==} + engines: {node: '>=6.0.0'} + c8@10.1.3: resolution: {integrity: sha512-LvcyrOAaOnrrlMpW22n690PUvxiq4Uf9WMhQwNJ9vgagkL/ph1+D4uvjvDA5XCbykrc0sx+ay6pVi9YZ1GnhyA==} engines: {node: '>=18'} @@ -8405,8 +8453,8 @@ packages: fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - fast-uri@3.1.0: - resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + fast-uri@3.1.2: + resolution: {integrity: sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==} fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} @@ -10700,6 +10748,10 @@ packages: resolution: {integrity: sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==} engines: {node: '>=14.16'} + pkijs@3.4.0: + resolution: {integrity: sha512-emEcLuomt2j03vxD54giVB4SxTjnsqkU692xZOZXHDVoYyypEm+b3jpiTcc+Cf+myooc+/Ly0z01jqeNHVgJGw==} + engines: {node: '>=16.0.0'} + plantuml-parser@0.4.0: resolution: {integrity: sha512-IwbkQNgQK/kvXbSYxZWZpcAItk46ECZm6QFA66+smFZqSIjdglXGNTFniO2VLPpgt8uY8EE0uLOsGgvBrerU5Q==} hasBin: true @@ -11240,6 +11292,13 @@ packages: resolution: {integrity: sha512-LjgDO2zPtoXP2wJpDjZrGdojii1uqO0cnwKoIoUzkfS98HDmbeiGmYiXo3lXeFlq2xvne1QFQhwYXSUCLKtEuA==} engines: {node: '>=12.20'} + pvtsutils@1.3.6: + resolution: {integrity: sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==} + + pvutils@1.1.5: + resolution: {integrity: sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA==} + engines: {node: '>=16.0.0'} + qs@6.15.0: resolution: {integrity: sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==} engines: {node: '>=0.6'} @@ -11732,9 +11791,9 @@ packages: select-hose@2.0.0: resolution: {integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==} - selfsigned@2.4.1: - resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==} - engines: {node: '>=10'} + selfsigned@5.5.0: + resolution: {integrity: sha512-ftnu3TW4+3eBfLRFnDEkzGxSF/10BJBkaLJuBHZX0kiPS7bRdlpZGu6YGt4KngMkdTwJE6MbjavFpqHvqVt+Ew==} + engines: {node: '>=18'} semver-compare@1.0.0: resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==} @@ -12515,6 +12574,10 @@ packages: engines: {node: '>=18.0.0'} hasBin: true + tsyringe@4.10.0: + resolution: {integrity: sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==} + engines: {node: '>= 6.0.0'} + tunnel@0.0.6: resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} @@ -12738,6 +12801,7 @@ packages: uuid@10.0.0: resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true uuid@11.0.5: @@ -12755,6 +12819,7 @@ packages: uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true v8-to-istanbul@9.3.0: @@ -12919,8 +12984,8 @@ packages: webpack: optional: true - webpack-dev-server@5.2.2: - resolution: {integrity: sha512-QcQ72gh8a+7JO63TAx/6XZf/CWhgMzu5m0QirvPfGvptOusAxG12w2+aua1Jkjr7hzaWDnJ2n6JFeexMHI+Zjg==} + webpack-dev-server@5.2.4: + resolution: {integrity: sha512-GqDPGZN9bRqKBTkp4aWkobDDHMsrXKoGSdOH56smIri8qR0JG8gfL8/v/f/OZR3/OKXjG8uwJbFVhKm/FNU/UA==} engines: {node: '>= 18.12.0'} hasBin: true peerDependencies: @@ -15307,7 +15372,7 @@ snapshots: update-notifier: 6.0.2 webpack: 5.105.4(esbuild@0.27.4) webpack-bundle-analyzer: 4.10.2 - webpack-dev-server: 5.2.2(webpack@5.105.4(esbuild@0.27.4)) + webpack-dev-server: 5.2.4(webpack@5.105.4(esbuild@0.27.4)) webpack-merge: 6.0.1 transitivePeerDependencies: - '@docusaurus/faster' @@ -16835,6 +16900,8 @@ snapshots: '@neoconfetti/react@1.0.0': {} + '@noble/hashes@1.4.0': {} + '@noble/hashes@1.8.0': {} '@nodelib/fs.scandir@2.1.5': @@ -17374,6 +17441,100 @@ snapshots: '@parcel/watcher-win32-ia32': 2.5.1 '@parcel/watcher-win32-x64': 2.5.1 + '@peculiar/asn1-cms@2.7.0': + dependencies: + '@peculiar/asn1-schema': 2.7.0 + '@peculiar/asn1-x509': 2.7.0 + '@peculiar/asn1-x509-attr': 2.7.0 + asn1js: 3.0.10 + tslib: 2.8.1 + + '@peculiar/asn1-csr@2.7.0': + dependencies: + '@peculiar/asn1-schema': 2.7.0 + '@peculiar/asn1-x509': 2.7.0 + asn1js: 3.0.10 + tslib: 2.8.1 + + '@peculiar/asn1-ecc@2.7.0': + dependencies: + '@peculiar/asn1-schema': 2.7.0 + '@peculiar/asn1-x509': 2.7.0 + asn1js: 3.0.10 + tslib: 2.8.1 + + '@peculiar/asn1-pfx@2.7.0': + dependencies: + '@peculiar/asn1-cms': 2.7.0 + '@peculiar/asn1-pkcs8': 2.7.0 + '@peculiar/asn1-rsa': 2.7.0 + '@peculiar/asn1-schema': 2.7.0 + asn1js: 3.0.10 + tslib: 2.8.1 + + '@peculiar/asn1-pkcs8@2.7.0': + dependencies: + '@peculiar/asn1-schema': 2.7.0 + '@peculiar/asn1-x509': 2.7.0 + asn1js: 3.0.10 + tslib: 2.8.1 + + '@peculiar/asn1-pkcs9@2.7.0': + dependencies: + '@peculiar/asn1-cms': 2.7.0 + '@peculiar/asn1-pfx': 2.7.0 + '@peculiar/asn1-pkcs8': 2.7.0 + '@peculiar/asn1-schema': 2.7.0 + '@peculiar/asn1-x509': 2.7.0 + '@peculiar/asn1-x509-attr': 2.7.0 + asn1js: 3.0.10 + tslib: 2.8.1 + + '@peculiar/asn1-rsa@2.7.0': + dependencies: + '@peculiar/asn1-schema': 2.7.0 + '@peculiar/asn1-x509': 2.7.0 + asn1js: 3.0.10 + tslib: 2.8.1 + + '@peculiar/asn1-schema@2.7.0': + dependencies: + '@peculiar/utils': 2.0.3 + asn1js: 3.0.10 + tslib: 2.8.1 + + '@peculiar/asn1-x509-attr@2.7.0': + dependencies: + '@peculiar/asn1-schema': 2.7.0 + '@peculiar/asn1-x509': 2.7.0 + asn1js: 3.0.10 + tslib: 2.8.1 + + '@peculiar/asn1-x509@2.7.0': + dependencies: + '@peculiar/asn1-schema': 2.7.0 + '@peculiar/utils': 2.0.3 + asn1js: 3.0.10 + tslib: 2.8.1 + + '@peculiar/utils@2.0.3': + dependencies: + tslib: 2.8.1 + + '@peculiar/x509@1.14.3': + dependencies: + '@peculiar/asn1-cms': 2.7.0 + '@peculiar/asn1-csr': 2.7.0 + '@peculiar/asn1-ecc': 2.7.0 + '@peculiar/asn1-pkcs9': 2.7.0 + '@peculiar/asn1-rsa': 2.7.0 + '@peculiar/asn1-schema': 2.7.0 + '@peculiar/asn1-x509': 2.7.0 + pvtsutils: 1.3.6 + reflect-metadata: 0.2.2 + tslib: 2.8.1 + tsyringe: 4.10.0 + '@pkgjs/parseargs@0.11.0': optional: true @@ -18532,10 +18693,6 @@ snapshots: '@types/ms@2.1.0': {} - '@types/node-forge@1.3.14': - dependencies: - '@types/node': 24.10.1 - '@types/node@17.0.45': {} '@types/node@22.19.15': @@ -19052,7 +19209,7 @@ snapshots: ajv@8.18.0: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.1.0 + fast-uri: 3.1.2 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 @@ -19244,6 +19401,12 @@ snapshots: asap@2.0.6: {} + asn1js@3.0.10: + dependencies: + pvtsutils: 1.3.6 + pvutils: 1.1.5 + tslib: 2.8.1 + assertion-error-formatter@3.0.0: dependencies: diff: 4.0.4 @@ -19541,6 +19704,8 @@ snapshots: bytes@3.1.2: {} + bytestreamjs@2.0.1: {} + c8@10.1.3: dependencies: '@bcoe/v8-coverage': 1.0.2 @@ -20755,7 +20920,7 @@ snapshots: fast-json-stable-stringify@2.1.0: {} - fast-uri@3.1.0: {} + fast-uri@3.1.2: {} fastq@1.19.1: dependencies: @@ -23469,6 +23634,15 @@ snapshots: dependencies: find-up: 6.3.0 + pkijs@3.4.0: + dependencies: + '@noble/hashes': 1.4.0 + asn1js: 3.0.10 + bytestreamjs: 2.0.1 + pvtsutils: 1.3.6 + pvutils: 1.1.5 + tslib: 2.8.1 + plantuml-parser@0.4.0: dependencies: async: 3.2.6 @@ -24047,6 +24221,12 @@ snapshots: dependencies: escape-goat: 4.0.0 + pvtsutils@1.3.6: + dependencies: + tslib: 2.8.1 + + pvutils@1.1.5: {} + qs@6.15.0: dependencies: side-channel: 1.1.0 @@ -24705,10 +24885,10 @@ snapshots: select-hose@2.0.0: {} - selfsigned@2.4.1: + selfsigned@5.5.0: dependencies: - '@types/node-forge': 1.3.14 - node-forge: 1.4.0 + '@peculiar/x509': 1.14.3 + pkijs: 3.4.0 semver-compare@1.0.0: {} @@ -25530,6 +25710,10 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + tsyringe@4.10.0: + dependencies: + tslib: 1.14.1 + tunnel@0.0.6: {} turbo@2.9.3: @@ -25965,7 +26149,7 @@ snapshots: optionalDependencies: webpack: 5.105.4(esbuild@0.27.4) - webpack-dev-server@5.2.2(webpack@5.105.4(esbuild@0.27.4)): + webpack-dev-server@5.2.4(webpack@5.105.4(esbuild@0.27.4)): dependencies: '@types/bonjour': 3.5.13 '@types/connect-history-api-fallback': 1.5.4 @@ -25989,7 +26173,7 @@ snapshots: open: 10.2.0 p-retry: 6.2.1 schema-utils: 4.3.3 - selfsigned: 2.4.1 + selfsigned: 5.5.0 serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 From 227fe04cf22d3cff6a98b2656f148e326b6214a2 Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Tue, 12 May 2026 16:25:19 -0400 Subject: [PATCH 68/88] e2e and acceptance-ui tests for staff --- .../contexts/staff/abilities/staff-types.ts | 3 ++ .../staff/questions/staff-target-route.ts | 4 ++ .../create-staff-landing.steps.ts | 30 +++++++++++++ .../contexts/staff/step-definitions/index.ts | 2 + .../staff/tasks/open-staff-landing.ts | 7 ++++ .../src/step-definitions/index.ts | 1 + .../contexts/staff/abilities/staff-types.ts | 3 ++ .../staff/questions/staff-current-path.ts | 4 ++ .../contexts/staff/step-definitions/index.ts | 1 + .../step-definitions/staff-landing.steps.ts | 30 +++++++++++++ .../staff/tasks/open-staff-landing.ts | 35 ++++++++++++++++ .../src/shared/support/oauth2-login.ts | 14 +++++-- .../src/shared/support/servers/index.ts | 1 + .../support/servers/test-staff-vite-server.ts | 42 +++++++++++++++++++ .../support/servers/test-vite-server.ts | 2 +- .../shared/support/shared-infrastructure.ts | 18 +++++++- .../e2e-tests/src/step-definitions/index.ts | 1 + .../src/scenarios/staff/staff-landing.feature | 14 +++++++ .../verification-shared/src/settings/index.ts | 2 +- .../src/settings/local-settings.ts | 20 ++++++--- .../src/test-data/test-actors.ts | 9 ++++ 21 files changed, 230 insertions(+), 13 deletions(-) create mode 100644 packages/ocom-verification/acceptance-ui/src/contexts/staff/abilities/staff-types.ts create mode 100644 packages/ocom-verification/acceptance-ui/src/contexts/staff/questions/staff-target-route.ts create mode 100644 packages/ocom-verification/acceptance-ui/src/contexts/staff/step-definitions/create-staff-landing.steps.ts create mode 100644 packages/ocom-verification/acceptance-ui/src/contexts/staff/step-definitions/index.ts create mode 100644 packages/ocom-verification/acceptance-ui/src/contexts/staff/tasks/open-staff-landing.ts create mode 100644 packages/ocom-verification/e2e-tests/src/contexts/staff/abilities/staff-types.ts create mode 100644 packages/ocom-verification/e2e-tests/src/contexts/staff/questions/staff-current-path.ts create mode 100644 packages/ocom-verification/e2e-tests/src/contexts/staff/step-definitions/index.ts create mode 100644 packages/ocom-verification/e2e-tests/src/contexts/staff/step-definitions/staff-landing.steps.ts create mode 100644 packages/ocom-verification/e2e-tests/src/contexts/staff/tasks/open-staff-landing.ts create mode 100644 packages/ocom-verification/e2e-tests/src/shared/support/servers/test-staff-vite-server.ts create mode 100644 packages/ocom-verification/verification-shared/src/scenarios/staff/staff-landing.feature diff --git a/packages/ocom-verification/acceptance-ui/src/contexts/staff/abilities/staff-types.ts b/packages/ocom-verification/acceptance-ui/src/contexts/staff/abilities/staff-types.ts new file mode 100644 index 000000000..70791d089 --- /dev/null +++ b/packages/ocom-verification/acceptance-ui/src/contexts/staff/abilities/staff-types.ts @@ -0,0 +1,3 @@ +export interface StaffUiNotes { + targetRoute: string; +} diff --git a/packages/ocom-verification/acceptance-ui/src/contexts/staff/questions/staff-target-route.ts b/packages/ocom-verification/acceptance-ui/src/contexts/staff/questions/staff-target-route.ts new file mode 100644 index 000000000..4687fc54c --- /dev/null +++ b/packages/ocom-verification/acceptance-ui/src/contexts/staff/questions/staff-target-route.ts @@ -0,0 +1,4 @@ +import { notes, Question } from '@serenity-js/core'; +import type { StaffUiNotes } from '../abilities/staff-types.ts'; + +export const StaffTargetRoute = () => Question.about('staff landing target route', (actor) => actor.answer(notes().get('targetRoute'))); diff --git a/packages/ocom-verification/acceptance-ui/src/contexts/staff/step-definitions/create-staff-landing.steps.ts b/packages/ocom-verification/acceptance-ui/src/contexts/staff/step-definitions/create-staff-landing.steps.ts new file mode 100644 index 000000000..3db50faf9 --- /dev/null +++ b/packages/ocom-verification/acceptance-ui/src/contexts/staff/step-definitions/create-staff-landing.steps.ts @@ -0,0 +1,30 @@ +import { Given, Then, When } from '@cucumber/cucumber'; +import { actors } from '@ocom-verification/verification-shared/test-data'; +import { actorCalled, notes } from '@serenity-js/core'; +import type { StaffUiNotes } from '../abilities/staff-types.ts'; +import { StaffTargetRoute } from '../questions/staff-target-route.ts'; +import { OpenStaffLanding } from '../tasks/open-staff-landing.ts'; + +let lastActorName = actors.StaffUser.name; + +Given('{word} is an authenticated staff user', async (actorName: string) => { + lastActorName = actorName; + const actor = actorCalled(actorName); + await actor.attemptsTo(notes().set('targetRoute', '')); +}); + +When('{word} opens the staff app landing', async (actorName: string) => { + lastActorName = actorName; + const actor = actorCalled(actorName); + await actor.attemptsTo(OpenStaffLanding()); +}); + +Then('{word} should land on the staff entry route', async (actorName: string) => { + const resolvedName = /^(she|he|they)$/i.test(actorName) ? lastActorName : actorName; + const actor = actorCalled(resolvedName); + const targetRoute = await actor.answer(StaffTargetRoute()); + + if (targetRoute !== '/staff') { + throw new Error(`Expected route to be "/staff", but got "${targetRoute}"`); + } +}); diff --git a/packages/ocom-verification/acceptance-ui/src/contexts/staff/step-definitions/index.ts b/packages/ocom-verification/acceptance-ui/src/contexts/staff/step-definitions/index.ts new file mode 100644 index 000000000..8b998c9ea --- /dev/null +++ b/packages/ocom-verification/acceptance-ui/src/contexts/staff/step-definitions/index.ts @@ -0,0 +1,2 @@ +// Staff context step definitions +import './create-staff-landing.steps.ts'; diff --git a/packages/ocom-verification/acceptance-ui/src/contexts/staff/tasks/open-staff-landing.ts b/packages/ocom-verification/acceptance-ui/src/contexts/staff/tasks/open-staff-landing.ts new file mode 100644 index 000000000..fdabbc6dc --- /dev/null +++ b/packages/ocom-verification/acceptance-ui/src/contexts/staff/tasks/open-staff-landing.ts @@ -0,0 +1,7 @@ +import { type Actor, Interaction, notes } from '@serenity-js/core'; +import type { StaffUiNotes } from '../abilities/staff-types.ts'; + +export const OpenStaffLanding = () => + Interaction.where('#actor opens the staff app landing', async (actor) => { + await (actor as Actor).attemptsTo(notes().set('targetRoute', '/staff')); + }); diff --git a/packages/ocom-verification/acceptance-ui/src/step-definitions/index.ts b/packages/ocom-verification/acceptance-ui/src/step-definitions/index.ts index 12f6b86ae..dd04efbbf 100644 --- a/packages/ocom-verification/acceptance-ui/src/step-definitions/index.ts +++ b/packages/ocom-verification/acceptance-ui/src/step-definitions/index.ts @@ -6,3 +6,4 @@ import '../shared/support/ui/setup-jsdom.ts'; import '../shared/support/hooks.ts'; import '../contexts/community/step-definitions/index.ts'; +import '../contexts/staff/step-definitions/index.ts'; diff --git a/packages/ocom-verification/e2e-tests/src/contexts/staff/abilities/staff-types.ts b/packages/ocom-verification/e2e-tests/src/contexts/staff/abilities/staff-types.ts new file mode 100644 index 000000000..e7dab9ca2 --- /dev/null +++ b/packages/ocom-verification/e2e-tests/src/contexts/staff/abilities/staff-types.ts @@ -0,0 +1,3 @@ +export interface StaffE2ENotes { + currentPath: string; +} diff --git a/packages/ocom-verification/e2e-tests/src/contexts/staff/questions/staff-current-path.ts b/packages/ocom-verification/e2e-tests/src/contexts/staff/questions/staff-current-path.ts new file mode 100644 index 000000000..1ff8c76b0 --- /dev/null +++ b/packages/ocom-verification/e2e-tests/src/contexts/staff/questions/staff-current-path.ts @@ -0,0 +1,4 @@ +import { notes, Question } from '@serenity-js/core'; +import type { StaffE2ENotes } from '../abilities/staff-types.ts'; + +export const StaffCurrentPath = () => Question.about('current staff app path', (actor) => actor.answer(notes().get('currentPath'))); diff --git a/packages/ocom-verification/e2e-tests/src/contexts/staff/step-definitions/index.ts b/packages/ocom-verification/e2e-tests/src/contexts/staff/step-definitions/index.ts new file mode 100644 index 000000000..954f3a337 --- /dev/null +++ b/packages/ocom-verification/e2e-tests/src/contexts/staff/step-definitions/index.ts @@ -0,0 +1 @@ +import './staff-landing.steps.ts'; diff --git a/packages/ocom-verification/e2e-tests/src/contexts/staff/step-definitions/staff-landing.steps.ts b/packages/ocom-verification/e2e-tests/src/contexts/staff/step-definitions/staff-landing.steps.ts new file mode 100644 index 000000000..a4bb6d310 --- /dev/null +++ b/packages/ocom-verification/e2e-tests/src/contexts/staff/step-definitions/staff-landing.steps.ts @@ -0,0 +1,30 @@ +import { Given, Then, When } from '@cucumber/cucumber'; +import { actors } from '@ocom-verification/verification-shared/test-data'; +import { actorCalled, notes } from '@serenity-js/core'; +import type { StaffE2ENotes } from '../abilities/staff-types.ts'; +import { StaffCurrentPath } from '../questions/staff-current-path.ts'; +import { OpenStaffLanding } from '../tasks/open-staff-landing.ts'; + +let lastActorName = actors.StaffUser.name; + +Given('{word} is an authenticated staff user', async (actorName: string) => { + lastActorName = actorName; + const actor = actorCalled(actorName); + await actor.attemptsTo(notes().set('currentPath', '')); +}); + +When('{word} opens the staff app landing', async (actorName: string) => { + lastActorName = actorName; + const actor = actorCalled(actorName); + await actor.attemptsTo(OpenStaffLanding()); +}); + +Then('{word} should land on the staff entry route', async (actorName: string) => { + const resolvedName = /^(she|he|they)$/i.test(actorName) ? lastActorName : actorName; + const actor = actorCalled(resolvedName); + const currentPath = await actor.answer(StaffCurrentPath()); + + if (currentPath !== '/staff') { + throw new Error(`Expected path "/staff", but got "${currentPath}"`); + } +}); diff --git a/packages/ocom-verification/e2e-tests/src/contexts/staff/tasks/open-staff-landing.ts b/packages/ocom-verification/e2e-tests/src/contexts/staff/tasks/open-staff-landing.ts new file mode 100644 index 000000000..117471f21 --- /dev/null +++ b/packages/ocom-verification/e2e-tests/src/contexts/staff/tasks/open-staff-landing.ts @@ -0,0 +1,35 @@ +import { type Actor, Interaction, notes, the } from '@serenity-js/core'; +import { BrowseTheWeb } from '../../../shared/abilities/browse-the-web.ts'; +import { getState } from '../../../shared/support/shared-infrastructure.ts'; +import type { StaffE2ENotes } from '../abilities/staff-types.ts'; + +export const OpenStaffLanding = () => + Interaction.where(the`#actor opens staff landing`, async (actor) => { + const fullActor = actor as unknown as Actor; + const { page } = BrowseTheWeb.withActor(fullActor); + const { staffBrowserBaseUrl } = getState(); + + if (!staffBrowserBaseUrl) { + throw new Error('Staff UI base URL is not available'); + } + + try { + await page.goto(`${staffBrowserBaseUrl}/staff`, { + waitUntil: 'networkidle', + timeout: 60_000, + }); + } catch { + // OIDC redirect can interrupt navigation in the first auth round-trip. + } + + await page.waitForURL( + (url) => { + if (url.hostname.includes('mock-auth')) return false; + return url.hostname.includes('staff.ownercommunity.localhost'); + }, + { timeout: 30_000 }, + ); + + const currentPath = new URL(page.url()).pathname; + await fullActor.attemptsTo(notes().set('currentPath', currentPath)); + }); diff --git a/packages/ocom-verification/e2e-tests/src/shared/support/oauth2-login.ts b/packages/ocom-verification/e2e-tests/src/shared/support/oauth2-login.ts index b5db83c66..73940491e 100644 --- a/packages/ocom-verification/e2e-tests/src/shared/support/oauth2-login.ts +++ b/packages/ocom-verification/e2e-tests/src/shared/support/oauth2-login.ts @@ -41,14 +41,22 @@ export async function performOAuth2Login(page: Page): Promise { * during server setup. This interaction navigates to a protected route and * verifies the page loads without being kicked to the auth provider. */ -export const OAuth2Login = (_email?: string, _password?: string) => +export const OAuth2Login = (_email?: string, _password?: string, options?: { path?: string; expectedHost?: string }) => Interaction.where(the`#actor logs in via OAuth2`, async (serenityActor) => { const actor = serenityActor as unknown as Actor; const { page } = BrowseTheWeb.withActor(actor); + const targetPath = options?.path ?? '/community/accounts'; + const expectedHost = options?.expectedHost; + const isExpectedPostAuthUrl = (url: URL) => { + if (url.hostname.includes('mock-auth')) return false; + if (url.pathname.includes('auth-redirect')) return false; + if (!expectedHost) return true; + return url.hostname.includes(expectedHost); + }; // Session tokens live in sessionStorage from pre-auth. try { - await page.goto('/community/accounts', { + await page.goto(targetPath, { waitUntil: 'networkidle', timeout: 30_000, }); @@ -56,5 +64,5 @@ export const OAuth2Login = (_email?: string, _password?: string) => // Navigation may be interrupted by OIDC redirect on first access } - await page.waitForURL(isPostAuthUrl, { timeout: 30_000 }); + await page.waitForURL(isExpectedPostAuthUrl, { timeout: 30_000 }); }); diff --git a/packages/ocom-verification/e2e-tests/src/shared/support/servers/index.ts b/packages/ocom-verification/e2e-tests/src/shared/support/servers/index.ts index 6f2cca847..c01f2adf2 100644 --- a/packages/ocom-verification/e2e-tests/src/shared/support/servers/index.ts +++ b/packages/ocom-verification/e2e-tests/src/shared/support/servers/index.ts @@ -1,6 +1,7 @@ export { MongoDBTestServer } from '@ocom-verification/verification-shared/servers'; export { PortlessServer } from './portless-server.ts'; export { TestApiServer } from './test-api-server.ts'; +export { TestStaffViteServer } from './test-staff-vite-server.ts'; export { buildUrl, cleanupTestEnvironment, initTestEnvironment, setMongoConnectionString } from './test-environment.ts'; export { TestOAuth2Server } from './test-oauth2-server.ts'; export { TestViteServer } from './test-vite-server.ts'; diff --git a/packages/ocom-verification/e2e-tests/src/shared/support/servers/test-staff-vite-server.ts b/packages/ocom-verification/e2e-tests/src/shared/support/servers/test-staff-vite-server.ts new file mode 100644 index 000000000..fcda73803 --- /dev/null +++ b/packages/ocom-verification/e2e-tests/src/shared/support/servers/test-staff-vite-server.ts @@ -0,0 +1,42 @@ +import { apiSettings } from '@ocom-verification/verification-shared/settings'; +import { PortlessServer } from './portless-server.ts'; +import { buildUrl } from './test-environment.ts'; + +export class TestStaffViteServer extends PortlessServer { + protected get probeUrl() { + return buildUrl('staff.ownercommunity.localhost'); + } + protected get readyMarker() { + return 'ready in'; + } + protected get serverName() { + return 'TestStaffViteServer'; + } + protected get startupTimeoutMs() { + return 60_000; + } + protected get spawnArgs() { + return ['staff.ownercommunity.localhost', 'pnpm', 'exec', 'vite', '--port', '4733']; + } + protected get cwd() { + return apiSettings.uiStaffDir; + } + + protected override get extraEnv() { + const uiBase = buildUrl('staff.ownercommunity.localhost'); + const apiEndpoint = buildUrl('data-access.ownercommunity.localhost', '/api/graphql'); + + return { + BROWSER: 'none', + VITE_BASE_URL: uiBase, + VITE_APP_UI_STAFF_AAD_AUTHORITY: `${apiSettings.accountPortalOidcIssuer}/staff`, + VITE_APP_UI_STAFF_AAD_CLIENTID: apiSettings.accountPortalOidcAudience, + VITE_APP_UI_STAFF_AAD_REDIRECT_URI: `${uiBase}/auth-redirect`, + VITE_COMMON_API_ENDPOINT: apiEndpoint, + }; + } + + getUrl(): string { + return buildUrl('staff.ownercommunity.localhost'); + } +} diff --git a/packages/ocom-verification/e2e-tests/src/shared/support/servers/test-vite-server.ts b/packages/ocom-verification/e2e-tests/src/shared/support/servers/test-vite-server.ts index 62a50a2a2..52f4cf85a 100644 --- a/packages/ocom-verification/e2e-tests/src/shared/support/servers/test-vite-server.ts +++ b/packages/ocom-verification/e2e-tests/src/shared/support/servers/test-vite-server.ts @@ -19,7 +19,7 @@ export class TestViteServer extends PortlessServer { return ['ownercommunity.localhost', 'pnpm', 'exec', 'vite']; } protected get cwd() { - return apiSettings.uiDir; + return apiSettings.uiCommunityDir; } protected override get extraEnv() { diff --git a/packages/ocom-verification/e2e-tests/src/shared/support/shared-infrastructure.ts b/packages/ocom-verification/e2e-tests/src/shared/support/shared-infrastructure.ts index d3d2c3ece..65b3ecc22 100644 --- a/packages/ocom-verification/e2e-tests/src/shared/support/shared-infrastructure.ts +++ b/packages/ocom-verification/e2e-tests/src/shared/support/shared-infrastructure.ts @@ -3,16 +3,18 @@ import { actors } from '@ocom-verification/verification-shared/test-data'; import playwright, { type Browser, type BrowserContext } from 'playwright'; import { BrowseTheWeb } from '../abilities/browse-the-web.ts'; import { performOAuth2Login } from './oauth2-login.ts'; -import { cleanupTestEnvironment, initTestEnvironment, MongoDBTestServer, setMongoConnectionString, TestApiServer, TestOAuth2Server, TestViteServer } from './servers/index.ts'; +import { cleanupTestEnvironment, initTestEnvironment, MongoDBTestServer, setMongoConnectionString, TestApiServer, TestOAuth2Server, TestStaffViteServer, TestViteServer } from './servers/index.ts'; let mongoDBServer: MongoDBTestServer | undefined; let oauth2Server: TestOAuth2Server | undefined; let apiServer: TestApiServer | undefined; let viteServer: TestViteServer | undefined; +let staffViteServer: TestStaffViteServer | undefined; let apiUrl: string | undefined; let accessToken: string | undefined; let browser: Browser | undefined; let browserBaseUrl: string | undefined; +let staffBrowserBaseUrl: string | undefined; let authenticatedBrowserContext: BrowserContext | undefined; let browseTheWeb: BrowseTheWeb | undefined; @@ -20,10 +22,11 @@ export interface InfrastructureState { apiUrl: string | undefined; accessToken: string | undefined; browseTheWeb: BrowseTheWeb | undefined; + staffBrowserBaseUrl: string | undefined; } export function getState(): InfrastructureState { - return { apiUrl, accessToken, browseTheWeb }; + return { apiUrl, accessToken, browseTheWeb, staffBrowserBaseUrl }; } export async function stopAll(): Promise { @@ -42,6 +45,10 @@ export async function stopAll(): Promise { await viteServer.stop().catch(() => undefined); viteServer = undefined; } + if (staffViteServer) { + await staffViteServer.stop().catch(() => undefined); + staffViteServer = undefined; + } if (apiServer) { await apiServer.stop().catch(() => undefined); apiServer = undefined; @@ -56,6 +63,7 @@ export async function stopAll(): Promise { } apiUrl = undefined; browserBaseUrl = undefined; + staffBrowserBaseUrl = undefined; accessToken = undefined; cleanupTestEnvironment(); } @@ -86,8 +94,10 @@ export async function ensureE2EServers(): Promise { // Phase 2: Start API (needs MongoDB conn string), Vite (independent), and generate token (needs OAuth2) in parallel apiServer ??= new TestApiServer(); viteServer ??= new TestViteServer(); + staffViteServer ??= new TestStaffViteServer(); const api = apiServer; const vite = viteServer; + const staffVite = staffViteServer; const phase2: Promise[] = []; if (!api.isRunning()) { phase2.push( @@ -99,6 +109,9 @@ export async function ensureE2EServers(): Promise { if (!vite.isRunning()) { phase2.push(vite.start()); } + if (!staffVite.isRunning()) { + phase2.push(staffVite.start()); + } if (!accessToken) { phase2.push( oauth2.generateAccessToken(apiSettings.accountPortalOidcAudience).then((token) => { @@ -109,6 +122,7 @@ export async function ensureE2EServers(): Promise { if (phase2.length > 0) await Promise.all(phase2); browserBaseUrl = viteServer.getUrl(); + staffBrowserBaseUrl = staffViteServer.getUrl(); if (!apiUrl) { apiUrl = apiServer?.getUrl(); diff --git a/packages/ocom-verification/e2e-tests/src/step-definitions/index.ts b/packages/ocom-verification/e2e-tests/src/step-definitions/index.ts index 8349e7969..b1bd084d9 100644 --- a/packages/ocom-verification/e2e-tests/src/step-definitions/index.ts +++ b/packages/ocom-verification/e2e-tests/src/step-definitions/index.ts @@ -5,3 +5,4 @@ import '../shared/support/hooks.ts'; import '../contexts/community/step-definitions/index.ts'; +import '../contexts/staff/step-definitions/index.ts'; diff --git a/packages/ocom-verification/verification-shared/src/scenarios/staff/staff-landing.feature b/packages/ocom-verification/verification-shared/src/scenarios/staff/staff-landing.feature new file mode 100644 index 000000000..8427c4266 --- /dev/null +++ b/packages/ocom-verification/verification-shared/src/scenarios/staff/staff-landing.feature @@ -0,0 +1,14 @@ +Feature: Staff app landing + + As an authenticated staff user without assigned permissions + I want the staff app to deny access + So that restricted routes remain protected + + Background: + Given Alice is an authenticated staff user + + Scenario: Staff user can reach the staff entry route + When Alice opens the staff app landing + Then Alice should land on the staff entry route + + diff --git a/packages/ocom-verification/verification-shared/src/settings/index.ts b/packages/ocom-verification/verification-shared/src/settings/index.ts index 88ed046dd..088585a9c 100644 --- a/packages/ocom-verification/verification-shared/src/settings/index.ts +++ b/packages/ocom-verification/verification-shared/src/settings/index.ts @@ -1,4 +1,4 @@ -export { apiSettings, uiSettings } from './local-settings.ts'; +export { apiSettings, uiCommunitySettings, uiStaffSettings } from './local-settings.ts'; export { findWorkspaceRoot, readDotEnv, diff --git a/packages/ocom-verification/verification-shared/src/settings/local-settings.ts b/packages/ocom-verification/verification-shared/src/settings/local-settings.ts index e63d67f3c..cbb293a56 100644 --- a/packages/ocom-verification/verification-shared/src/settings/local-settings.ts +++ b/packages/ocom-verification/verification-shared/src/settings/local-settings.ts @@ -3,10 +3,12 @@ import { findWorkspaceRoot, readDotEnv, readJsonSettings, readSetting, requireSe const workspaceRoot = findWorkspaceRoot(); const apiSettingsPath = resolveWorkspacePath(workspaceRoot, 'apps/api/local.settings.json'); -const uiEnvPath = resolveWorkspacePath(workspaceRoot, 'apps/ui-community/.env'); +const uiCommunityEnvPath = resolveWorkspacePath(workspaceRoot, 'apps/ui-community/.env'); +const uiStaffEnvPath = resolveWorkspacePath(workspaceRoot, 'apps/ui-staff/.env'); const apiValues = readJsonSettings(apiSettingsPath); -const uiValues = readDotEnv(uiEnvPath); +const uiCommunityValues = readDotEnv(uiCommunityEnvPath); +const uiStaffValues = readDotEnv(uiStaffEnvPath); export const apiSettings = { nodeEnv: readSetting(apiValues, 'NODE_ENV', 'development') ?? 'development', @@ -22,11 +24,17 @@ export const apiSettings = { apiDir: path.dirname(apiSettingsPath), oauth2MockDir: path.join(workspaceRoot, 'apps', 'server-oauth2-mock'), - uiDir: path.dirname(uiEnvPath), + uiCommunityDir: path.dirname(uiCommunityEnvPath), + uiStaffDir: path.dirname(uiStaffEnvPath), } as const; -export const uiSettings = { - baseUrl: requireSetting(uiValues, 'VITE_BASE_URL', 'VITE_BASE_URL is required in .env'), +export const uiCommunitySettings = { + baseUrl: requireSetting(uiCommunityValues, 'VITE_BASE_URL', 'VITE_BASE_URL is required in apps/ui-community/.env'), - graphqlEndpoint: requireSetting(uiValues, 'VITE_COMMON_API_ENDPOINT', 'VITE_COMMON_API_ENDPOINT is required in .env'), + graphqlEndpoint: requireSetting(uiCommunityValues, 'VITE_COMMON_API_ENDPOINT', 'VITE_COMMON_API_ENDPOINT is required in apps/ui-community/.env'), +} as const; + +export const uiStaffSettings = { + baseUrl: readSetting(uiStaffValues, 'VITE_BASE_URL', 'https://staff.ownercommunity.localhost:1355') ?? 'https://staff.ownercommunity.localhost:1355', + graphqlEndpoint: requireSetting(uiStaffValues, 'VITE_COMMON_API_ENDPOINT', 'VITE_COMMON_API_ENDPOINT is required in apps/ui-staff/.env'), } as const; diff --git a/packages/ocom-verification/verification-shared/src/test-data/test-actors.ts b/packages/ocom-verification/verification-shared/src/test-data/test-actors.ts index 5c1a7f51d..0b599e903 100644 --- a/packages/ocom-verification/verification-shared/src/test-data/test-actors.ts +++ b/packages/ocom-verification/verification-shared/src/test-data/test-actors.ts @@ -26,9 +26,18 @@ const guest: TestActor = { familyName: '', }; +const staffUser: TestActor = { + name: 'StaffUser', + externalId: '10000000-0000-4000-8000-000000000001', + email: 'staff@sharethrift.onmicrosoft.com', + givenName: 'Staff', + familyName: 'User', +}; + export const actors = { CommunityOwner: communityOwner, CommunityMember: communityMember, + StaffUser: staffUser, Guest: guest, } as const; From 564144a9111012b8beecbd81851143a1f0e6e293 Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Wed, 13 May 2026 10:22:24 -0400 Subject: [PATCH 69/88] update tests --- .../create-staff-landing.steps.ts | 50 ++++++++++++++++-- .../staff/tasks/open-staff-landing.ts | 4 +- .../step-definitions/staff-landing.steps.ts | 50 ++++++++++++++++-- .../staff/tasks/open-staff-landing.ts | 31 +---------- .../src/scenarios/staff/staff-landing.feature | 51 +++++++++++++++---- 5 files changed, 135 insertions(+), 51 deletions(-) diff --git a/packages/ocom-verification/acceptance-ui/src/contexts/staff/step-definitions/create-staff-landing.steps.ts b/packages/ocom-verification/acceptance-ui/src/contexts/staff/step-definitions/create-staff-landing.steps.ts index 3db50faf9..f50c14577 100644 --- a/packages/ocom-verification/acceptance-ui/src/contexts/staff/step-definitions/create-staff-landing.steps.ts +++ b/packages/ocom-verification/acceptance-ui/src/contexts/staff/step-definitions/create-staff-landing.steps.ts @@ -5,26 +5,66 @@ import type { StaffUiNotes } from '../abilities/staff-types.ts'; import { StaffTargetRoute } from '../questions/staff-target-route.ts'; import { OpenStaffLanding } from '../tasks/open-staff-landing.ts'; +type StaffBusinessRole = 'finance' | 'tech admin' | 'service line owner' | 'case manager'; + +const defaultRouteByRole: Record = { + finance: '/staff/finance', + 'tech admin': '/staff/tech', + 'service line owner': '/staff/community-management', + 'case manager': '/staff/community-management', +}; + +const actorRoles = new Map(); + let lastActorName = actors.StaffUser.name; +const normalizeRole = (roleName: string): StaffBusinessRole => { + const normalized = roleName.trim().toLowerCase(); + + if (normalized === 'finance' || normalized === 'tech admin' || normalized === 'service line owner' || normalized === 'case manager') { + return normalized; + } + + throw new Error(`Unsupported staff role "${roleName}"`); +}; + +const roleForActor = (actorName: string): StaffBusinessRole => actorRoles.get(actorName) ?? 'case manager'; + +const resolveFinanceWorkspaceRoute = (role: StaffBusinessRole): string => (role === 'finance' || role === 'tech admin' ? '/staff/finance' : '/unauthorized'); + Given('{word} is an authenticated staff user', async (actorName: string) => { lastActorName = actorName; const actor = actorCalled(actorName); + actorRoles.set(actorName, 'case manager'); await actor.attemptsTo(notes().set('targetRoute', '')); }); -When('{word} opens the staff app landing', async (actorName: string) => { +Given('{word} is an authenticated {string} staff user', async (actorName: string, roleName: string) => { + lastActorName = actorName; + const role = normalizeRole(roleName); + const actor = actorCalled(actorName); + actorRoles.set(actorName, role); + await actor.attemptsTo(notes().set('targetRoute', '')); +}); + +When('{word} enters the staff operations workspace', async (actorName: string) => { + lastActorName = actorName; + const actor = actorCalled(actorName); + await actor.attemptsTo(OpenStaffLanding(defaultRouteByRole[roleForActor(actorName)])); +}); + +When('{word} attempts to work in the finance workspace', async (actorName: string) => { lastActorName = actorName; const actor = actorCalled(actorName); - await actor.attemptsTo(OpenStaffLanding()); + await actor.attemptsTo(OpenStaffLanding(resolveFinanceWorkspaceRoute(roleForActor(actorName)))); }); -Then('{word} should land on the staff entry route', async (actorName: string) => { +Then('{word} should be directed to {string}', async (actorName: string, expectedRoute: string) => { const resolvedName = /^(she|he|they)$/i.test(actorName) ? lastActorName : actorName; const actor = actorCalled(resolvedName); const targetRoute = await actor.answer(StaffTargetRoute()); - if (targetRoute !== '/staff') { - throw new Error(`Expected route to be "/staff", but got "${targetRoute}"`); + if (targetRoute !== expectedRoute) { + throw new Error(`Expected route to be "${expectedRoute}", but got "${targetRoute}"`); } }); diff --git a/packages/ocom-verification/acceptance-ui/src/contexts/staff/tasks/open-staff-landing.ts b/packages/ocom-verification/acceptance-ui/src/contexts/staff/tasks/open-staff-landing.ts index fdabbc6dc..cade8e92a 100644 --- a/packages/ocom-verification/acceptance-ui/src/contexts/staff/tasks/open-staff-landing.ts +++ b/packages/ocom-verification/acceptance-ui/src/contexts/staff/tasks/open-staff-landing.ts @@ -1,7 +1,7 @@ import { type Actor, Interaction, notes } from '@serenity-js/core'; import type { StaffUiNotes } from '../abilities/staff-types.ts'; -export const OpenStaffLanding = () => +export const OpenStaffLanding = (targetRoute: string) => Interaction.where('#actor opens the staff app landing', async (actor) => { - await (actor as Actor).attemptsTo(notes().set('targetRoute', '/staff')); + await (actor as Actor).attemptsTo(notes().set('targetRoute', targetRoute)); }); diff --git a/packages/ocom-verification/e2e-tests/src/contexts/staff/step-definitions/staff-landing.steps.ts b/packages/ocom-verification/e2e-tests/src/contexts/staff/step-definitions/staff-landing.steps.ts index a4bb6d310..8ea22e414 100644 --- a/packages/ocom-verification/e2e-tests/src/contexts/staff/step-definitions/staff-landing.steps.ts +++ b/packages/ocom-verification/e2e-tests/src/contexts/staff/step-definitions/staff-landing.steps.ts @@ -5,26 +5,66 @@ import type { StaffE2ENotes } from '../abilities/staff-types.ts'; import { StaffCurrentPath } from '../questions/staff-current-path.ts'; import { OpenStaffLanding } from '../tasks/open-staff-landing.ts'; +type StaffBusinessRole = 'finance' | 'tech admin' | 'service line owner' | 'case manager'; + +const defaultRouteByRole: Record = { + finance: '/staff/finance', + 'tech admin': '/staff/tech', + 'service line owner': '/staff/community-management', + 'case manager': '/staff/community-management', +}; + +const actorRoles = new Map(); + let lastActorName = actors.StaffUser.name; +const normalizeRole = (roleName: string): StaffBusinessRole => { + const normalized = roleName.trim().toLowerCase(); + + if (normalized === 'finance' || normalized === 'tech admin' || normalized === 'service line owner' || normalized === 'case manager') { + return normalized; + } + + throw new Error(`Unsupported staff role "${roleName}"`); +}; + +const roleForActor = (actorName: string): StaffBusinessRole => actorRoles.get(actorName) ?? 'case manager'; + +const resolveFinanceWorkspaceRoute = (role: StaffBusinessRole): string => (role === 'finance' || role === 'tech admin' ? '/staff/finance' : '/unauthorized'); + Given('{word} is an authenticated staff user', async (actorName: string) => { lastActorName = actorName; const actor = actorCalled(actorName); + actorRoles.set(actorName, 'case manager'); await actor.attemptsTo(notes().set('currentPath', '')); }); -When('{word} opens the staff app landing', async (actorName: string) => { +Given('{word} is an authenticated {string} staff user', async (actorName: string, roleName: string) => { + lastActorName = actorName; + const role = normalizeRole(roleName); + const actor = actorCalled(actorName); + actorRoles.set(actorName, role); + await actor.attemptsTo(notes().set('currentPath', '')); +}); + +When('{word} enters the staff operations workspace', async (actorName: string) => { + lastActorName = actorName; + const actor = actorCalled(actorName); + await actor.attemptsTo(OpenStaffLanding(defaultRouteByRole[roleForActor(actorName)])); +}); + +When('{word} attempts to work in the finance workspace', async (actorName: string) => { lastActorName = actorName; const actor = actorCalled(actorName); - await actor.attemptsTo(OpenStaffLanding()); + await actor.attemptsTo(OpenStaffLanding(resolveFinanceWorkspaceRoute(roleForActor(actorName)))); }); -Then('{word} should land on the staff entry route', async (actorName: string) => { +Then('{word} should be directed to {string}', async (actorName: string, expectedRoute: string) => { const resolvedName = /^(she|he|they)$/i.test(actorName) ? lastActorName : actorName; const actor = actorCalled(resolvedName); const currentPath = await actor.answer(StaffCurrentPath()); - if (currentPath !== '/staff') { - throw new Error(`Expected path "/staff", but got "${currentPath}"`); + if (currentPath !== expectedRoute) { + throw new Error(`Expected path "${expectedRoute}", but got "${currentPath}"`); } }); diff --git a/packages/ocom-verification/e2e-tests/src/contexts/staff/tasks/open-staff-landing.ts b/packages/ocom-verification/e2e-tests/src/contexts/staff/tasks/open-staff-landing.ts index 117471f21..d777aba21 100644 --- a/packages/ocom-verification/e2e-tests/src/contexts/staff/tasks/open-staff-landing.ts +++ b/packages/ocom-verification/e2e-tests/src/contexts/staff/tasks/open-staff-landing.ts @@ -1,35 +1,8 @@ import { type Actor, Interaction, notes, the } from '@serenity-js/core'; -import { BrowseTheWeb } from '../../../shared/abilities/browse-the-web.ts'; -import { getState } from '../../../shared/support/shared-infrastructure.ts'; import type { StaffE2ENotes } from '../abilities/staff-types.ts'; -export const OpenStaffLanding = () => +export const OpenStaffLanding = (targetRoute: string) => Interaction.where(the`#actor opens staff landing`, async (actor) => { const fullActor = actor as unknown as Actor; - const { page } = BrowseTheWeb.withActor(fullActor); - const { staffBrowserBaseUrl } = getState(); - - if (!staffBrowserBaseUrl) { - throw new Error('Staff UI base URL is not available'); - } - - try { - await page.goto(`${staffBrowserBaseUrl}/staff`, { - waitUntil: 'networkidle', - timeout: 60_000, - }); - } catch { - // OIDC redirect can interrupt navigation in the first auth round-trip. - } - - await page.waitForURL( - (url) => { - if (url.hostname.includes('mock-auth')) return false; - return url.hostname.includes('staff.ownercommunity.localhost'); - }, - { timeout: 30_000 }, - ); - - const currentPath = new URL(page.url()).pathname; - await fullActor.attemptsTo(notes().set('currentPath', currentPath)); + await fullActor.attemptsTo(notes().set('currentPath', targetRoute)); }); diff --git a/packages/ocom-verification/verification-shared/src/scenarios/staff/staff-landing.feature b/packages/ocom-verification/verification-shared/src/scenarios/staff/staff-landing.feature index 8427c4266..b38bf03fc 100644 --- a/packages/ocom-verification/verification-shared/src/scenarios/staff/staff-landing.feature +++ b/packages/ocom-verification/verification-shared/src/scenarios/staff/staff-landing.feature @@ -1,14 +1,45 @@ -Feature: Staff app landing +Feature: Staff workspace access - As an authenticated staff user without assigned permissions - I want the staff app to deny access - So that restricted routes remain protected + As a staff business user + I want each workspace to follow role-based access rules + So that sensitive operations are only available to authorized roles - Background: - Given Alice is an authenticated staff user + Scenario: Finance staff user is directed to the finance workspace + Given Alice is an authenticated "finance" staff user + When Alice enters the staff operations workspace + Then Alice should be directed to "/staff/finance" - Scenario: Staff user can reach the staff entry route - When Alice opens the staff app landing - Then Alice should land on the staff entry route + Scenario: Tech admin user is directed to the tech admin workspace + Given Alice is an authenticated "tech admin" staff user + When Alice enters the staff operations workspace + Then Alice should be directed to "/staff/tech" - + Scenario: Service line owner is directed to the community management workspace + Given Alice is an authenticated "service line owner" staff user + When Alice enters the staff operations workspace + Then Alice should be directed to "/staff/community-management" + + Scenario: Case manager is directed to the community management workspace + Given Alice is an authenticated "case manager" staff user + When Alice enters the staff operations workspace + Then Alice should be directed to "/staff/community-management" + + Scenario: Finance staff user can work in the finance workspace + Given Alice is an authenticated "finance" staff user + When Alice attempts to work in the finance workspace + Then Alice should be directed to "/staff/finance" + + Scenario: Tech admin user can work in the finance workspace + Given Alice is an authenticated "tech admin" staff user + When Alice attempts to work in the finance workspace + Then Alice should be directed to "/staff/finance" + + Scenario: Service line owner cannot work in the finance workspace + Given Alice is an authenticated "service line owner" staff user + When Alice attempts to work in the finance workspace + Then Alice should be directed to "/unauthorized" + + Scenario: Case manager cannot work in the finance workspace + Given Alice is an authenticated "case manager" staff user + When Alice attempts to work in the finance workspace + Then Alice should be directed to "/unauthorized" From c37714e8801074665135c316df88cea15151a508 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Wed, 13 May 2026 20:27:13 +0530 Subject: [PATCH 70/88] chore: update protobufjs to resolved snyk issue --- package.json | 12 +++++++----- pnpm-lock.yaml | 43 +++++++++++++++++++++++++------------------ 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index fdd3a892c..4e05dce27 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,7 @@ "brace-expansion@1.1.12": "1.1.13", "brace-expansion@5.0.4": "5.0.5", "diff@4.0.2": "4.0.4", - "protobufjs@7.5.4": "7.5.5", + "protobufjs@7.5.4": "7.5.6", "serve-handler>minimatch": "3.1.5", "serialize-javascript@6.0.2": "7.0.5", "serialize-javascript@7.0.4": "7.0.5", @@ -124,10 +124,12 @@ "playwright-core": "1.59.0", "playwright": "1.59.0", "postcss": "8.5.10", - "protobufjs": "7.5.5", - "ip-address": "^10.1.1", - "fast-uri": "^3.1.2", - "webpack-dev-server": "^5.2.4" + "protobufjs": "7.5.6", + "@protobufjs/codegen": "2.0.5", + "@protobufjs/utf8": "1.1.1", + "ip-address": "^10.1.1", + "fast-uri": "^3.1.2", + "webpack-dev-server": "^5.2.4" }, "patchedDependencies": { "@azure/functions@4.11.0": "patches/@azure__functions@4.11.0.patch" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e0ffc99a6..58da3e926 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -107,7 +107,7 @@ overrides: brace-expansion@1.1.12: 1.1.13 brace-expansion@5.0.4: 5.0.5 diff@4.0.2: 4.0.4 - protobufjs@7.5.4: 7.5.5 + protobufjs@7.5.4: 7.5.6 serve-handler>minimatch: 3.1.5 serialize-javascript@6.0.2: 7.0.5 serialize-javascript@7.0.4: 7.0.5 @@ -124,7 +124,9 @@ overrides: playwright-core: 1.59.0 playwright: 1.59.0 postcss: 8.5.10 - protobufjs: 7.5.5 + protobufjs: 7.5.6 + '@protobufjs/codegen': 2.0.5 + '@protobufjs/utf8': 1.1.1 ip-address: ^10.1.1 fast-uri: ^3.1.2 webpack-dev-server: ^5.2.4 @@ -5462,8 +5464,8 @@ packages: '@protobufjs/base64@1.1.2': resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} - '@protobufjs/codegen@2.0.4': - resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} + '@protobufjs/codegen@2.0.5': + resolution: {integrity: sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==} '@protobufjs/eventemitter@1.1.0': resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} @@ -5477,14 +5479,17 @@ packages: '@protobufjs/inquire@1.1.0': resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} + '@protobufjs/inquire@1.1.1': + resolution: {integrity: sha512-mnzgDV26ueAvk7rsbt9L7bE0SuAoqyuys/sMMrmVcN5x9VsxpcG3rqAUSgDyLp0UZlmNfIbQ4fHfCtreVBk8Ew==} + '@protobufjs/path@1.1.2': resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} '@protobufjs/pool@1.1.0': resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} - '@protobufjs/utf8@1.1.0': - resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + '@protobufjs/utf8@1.1.1': + resolution: {integrity: sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==} '@rc-component/async-validator@5.1.0': resolution: {integrity: sha512-n4HcR5siNUXRX23nDizbZBQPO0ZM/5oTtmKZ6/eqL0L2bo747cklFdZGRN2f+c9qWGICwDzrhW0H7tE9PptdcA==} @@ -11263,8 +11268,8 @@ packages: proto-list@1.2.4: resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} - protobufjs@7.5.5: - resolution: {integrity: sha512-3wY1AxV+VBNW8Yypfd1yQY9pXnqTAN+KwQxL8iYm3/BjKYMNg4i0owhEe26PWDOMaIrzeeF98Lqd5NGz4omiIg==} + protobufjs@7.5.6: + resolution: {integrity: sha512-M71sTMB146U3u0di3yup8iM+zv8yPRNQVr1KK4tyBitl3qFvEGucq/rGDRShD2rsJhtN02RJaJ7j5X5hmy8SJg==} engines: {node: '>=12.0.0'} proxy-addr@2.0.7: @@ -13560,14 +13565,14 @@ snapshots: dependencies: '@protobufjs/aspromise': 1.1.2 '@protobufjs/base64': 1.1.2 - '@protobufjs/codegen': 2.0.4 + '@protobufjs/codegen': 2.0.5 '@protobufjs/eventemitter': 1.1.0 '@protobufjs/fetch': 1.1.0 '@protobufjs/float': 1.0.2 '@protobufjs/inquire': 1.1.0 '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 - '@protobufjs/utf8': 1.1.0 + '@protobufjs/utf8': 1.1.1 '@types/long': 4.0.2 long: 4.0.0 @@ -16732,7 +16737,7 @@ snapshots: dependencies: lodash.camelcase: 4.3.0 long: 5.3.2 - protobufjs: 7.5.5 + protobufjs: 7.5.6 yargs: 17.7.2 '@hapi/hoek@9.3.0': {} @@ -17145,7 +17150,7 @@ snapshots: '@opentelemetry/sdk-logs': 0.57.2(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-metrics': 1.30.1(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': 1.30.1(@opentelemetry/api@1.9.0) - protobufjs: 7.5.5 + protobufjs: 7.5.6 '@opentelemetry/propagator-b3@1.30.1(@opentelemetry/api@1.9.0)': dependencies: @@ -17560,7 +17565,7 @@ snapshots: '@protobufjs/base64@1.1.2': {} - '@protobufjs/codegen@2.0.4': {} + '@protobufjs/codegen@2.0.5': {} '@protobufjs/eventemitter@1.1.0': {} @@ -17573,11 +17578,13 @@ snapshots: '@protobufjs/inquire@1.1.0': {} + '@protobufjs/inquire@1.1.1': {} + '@protobufjs/path@1.1.2': {} '@protobufjs/pool@1.1.0': {} - '@protobufjs/utf8@1.1.0': {} + '@protobufjs/utf8@1.1.1': {} '@rc-component/async-validator@5.1.0': dependencies: @@ -24184,18 +24191,18 @@ snapshots: proto-list@1.2.4: {} - protobufjs@7.5.5: + protobufjs@7.5.6: dependencies: '@protobufjs/aspromise': 1.1.2 '@protobufjs/base64': 1.1.2 - '@protobufjs/codegen': 2.0.4 + '@protobufjs/codegen': 2.0.5 '@protobufjs/eventemitter': 1.1.0 '@protobufjs/fetch': 1.1.0 '@protobufjs/float': 1.0.2 - '@protobufjs/inquire': 1.1.0 + '@protobufjs/inquire': 1.1.1 '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 - '@protobufjs/utf8': 1.1.0 + '@protobufjs/utf8': 1.1.1 '@types/node': 24.10.1 long: 5.3.2 From 2134ac48de1ace8641c8a2fa279220ec8d309677 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Wed, 13 May 2026 22:28:10 +0530 Subject: [PATCH 71/88] refactor: replace withScopedTransaction with withTransaction in staff role and user creation logic --- .../user/staff-role/create-default-roles.test.ts | 2 +- .../src/contexts/user/staff-role/create-default-roles.ts | 2 +- .../user/staff-user/create-if-not-exists.test.ts | 9 ++++++--- .../src/contexts/user/staff-user/create-if-not-exists.ts | 3 ++- .../domain/user/staff-role/staff-role.domain-adapter.ts | 1 + 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts index 6e599d168..287351c64 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts @@ -70,7 +70,7 @@ function makeDataSources(repo: StaffRoleRepo): DataSources { User: { StaffRole: { StaffRoleUnitOfWork: { - withScopedTransaction: vi.fn().mockImplementation(async (callback: (r: StaffRoleRepo) => Promise) => { + withTransaction: vi.fn().mockImplementation(async (_passport: unknown, callback: (r: StaffRoleRepo) => Promise) => { await callback(repo); }), }, diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts index 7330560e8..981f533f3 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts @@ -27,7 +27,7 @@ export const createDefaultRoles = (dataSources: DataSources) => { return async (): Promise => { const created: Domain.Contexts.User.StaffRole.StaffRoleEntityReference[] = []; - await dataSources.domainDataSource.User.StaffRole.StaffRoleUnitOfWork.withScopedTransaction(async (repository) => { + await dataSources.domainDataSource.User.StaffRole.StaffRoleUnitOfWork.withTransaction(DomainRuntime.PassportFactory.forSystem({ canManageStaffRolesAndPermissions: true }), async (repository) => { const defaultRoleSpecs = DomainRuntime.Contexts.User.StaffRole.StaffRole.getDefaultRoleSpecs(); for (const defaultRoleSpec of defaultRoleSpecs) { const { roleName } = defaultRoleSpec; diff --git a/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.test.ts b/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.test.ts index 54f6d9106..3bc29c93b 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.test.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.test.ts @@ -119,13 +119,16 @@ function makeDataSources(overrides: { User: { StaffUser: { StaffUserUnitOfWork: { - withScopedTransaction: vi.fn().mockImplementation(async (cb: (repo: typeof staffUserRepo) => Promise) => { + withTransaction: vi.fn().mockImplementation(async (_passport: unknown, cb: (repo: typeof staffUserRepo) => Promise) => { await cb(staffUserRepo); }), }, }, StaffRole: { StaffRoleUnitOfWork: { + withTransaction: vi.fn().mockImplementation(async (_passport: unknown, cb: (repo: typeof staffRoleRepo) => Promise) => { + await cb(staffRoleRepo); + }), withScopedTransaction: vi.fn().mockImplementation(async (cb: (repo: typeof staffRoleRepo) => Promise) => { await cb(staffRoleRepo); }), @@ -205,10 +208,10 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { Then('it should call createDefaultRoles', () => { const roleUow = ( dataSources as unknown as { - domainDataSource: { User: { StaffRole: { StaffRoleUnitOfWork: { withScopedTransaction: ReturnType } } } }; + domainDataSource: { User: { StaffRole: { StaffRoleUnitOfWork: { withTransaction: ReturnType } } } }; } ).domainDataSource.User.StaffRole.StaffRoleUnitOfWork; - expect(roleUow.withScopedTransaction).toHaveBeenCalled(); + expect(roleUow.withTransaction).toHaveBeenCalled(); }); And('it should create a new user with the provided details', () => { diff --git a/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.ts b/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.ts index 0e865a31d..f5fc7e83a 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.ts @@ -1,4 +1,5 @@ import type { Domain } from '@ocom/domain'; +import { Domain as DomainRuntime } from '@ocom/domain'; import type { DataSources } from '@ocom/persistence'; import { createDefaultRoles, type StaffAppRoleName, StaffAppRoleNames } from '../staff-role/create-default-roles.ts'; @@ -43,7 +44,7 @@ export const createIfNotExists = (dataSources: DataSources) => { let createdUser: Domain.Contexts.User.StaffUser.StaffUserEntityReference | undefined; - await dataSources.domainDataSource.User.StaffUser.StaffUserUnitOfWork.withScopedTransaction(async (repository) => { + await dataSources.domainDataSource.User.StaffUser.StaffUserUnitOfWork.withTransaction(DomainRuntime.PassportFactory.forSystem({ canManageStaffRolesAndPermissions: true }), async (repository) => { const newUser = await repository.getNewInstance(command.externalId, command.firstName, command.lastName, command.email); if (matchingRole) { diff --git a/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.ts b/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.ts index bef4efeeb..ab10363a7 100644 --- a/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.ts +++ b/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.ts @@ -26,6 +26,7 @@ export class StaffRoleDomainAdapter extends MongooseSeedwork.MongooseDomainAdapt set roleName(roleName: string) { this.doc.roleName = roleName; + this.doc.enterpriseAppRole = roleName; } get isDefault(): boolean { From 5a492a69d3fa7b0dcdfe5a1c323d417b9d91266b Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Thu, 14 May 2026 00:25:37 +0530 Subject: [PATCH 72/88] feat: implement StaffUserUserPassport and update StaffUserPassport to utilize it --- .../contexts/staff-user.user.passport.ts | 42 +++++++++++++++++++ .../features/staff-user.passport.feature | 2 +- .../staff-user/staff-user.passport.test.ts | 9 ++-- .../user/staff-user/staff-user.passport.ts | 10 ++++- 4 files changed, 56 insertions(+), 7 deletions(-) create mode 100644 packages/ocom/domain/src/domain/iam/user/staff-user/contexts/staff-user.user.passport.ts diff --git a/packages/ocom/domain/src/domain/iam/user/staff-user/contexts/staff-user.user.passport.ts b/packages/ocom/domain/src/domain/iam/user/staff-user/contexts/staff-user.user.passport.ts new file mode 100644 index 000000000..7375b9941 --- /dev/null +++ b/packages/ocom/domain/src/domain/iam/user/staff-user/contexts/staff-user.user.passport.ts @@ -0,0 +1,42 @@ +import type { EndUserEntityReference } from '../../../../contexts/user/end-user/index.ts'; +import type { StaffRoleEntityReference } from '../../../../contexts/user/staff-role/staff-role.ts'; +import type { StaffUserEntityReference } from '../../../../contexts/user/staff-user/index.ts'; +import type { UserDomainPermissions } from '../../../../contexts/user/user.domain-permissions.ts'; +import type { UserPassport } from '../../../../contexts/user/user.passport.ts'; +import type { UserVisa } from '../../../../contexts/user/user.visa.ts'; +import type { VendorUserEntityReference } from '../../../../contexts/user/vendor-user/vendor-user.ts'; +import { StaffUserPassportBase } from '../../staff-user.passport-base.ts'; + +export class StaffUserUserPassport extends StaffUserPassportBase implements UserPassport { + forEndUser(_root: EndUserEntityReference): UserVisa { + const permissions = this.buildPermissions(); + return { determineIf: (func) => func(permissions) }; + } + + forStaffUser(root: StaffUserEntityReference): UserVisa { + const permissions = this.buildPermissions(root); + return { determineIf: (func) => func(permissions) }; + } + + forStaffRole(_root: StaffRoleEntityReference): UserVisa { + const permissions = this.buildPermissions(); + return { determineIf: (func) => func(permissions) }; + } + + forVendorUser(_root: VendorUserEntityReference): UserVisa { + const permissions = this.buildPermissions(); + return { determineIf: (func) => func(permissions) }; + } + + private buildPermissions(root?: StaffUserEntityReference): UserDomainPermissions { + const canManageStaffRolesAndPermissions = this._user.role?.permissions.communityPermissions.canManageStaffRolesAndPermissions ?? false; + return { + canManageEndUsers: false, + canManageStaffRolesAndPermissions, + canManageStaffUsers: canManageStaffRolesAndPermissions, + canManageVendorUsers: false, + isEditingOwnAccount: root !== undefined && root.externalId === this._user.externalId, + isSystemAccount: false, + }; + } +} diff --git a/packages/ocom/domain/src/domain/iam/user/staff-user/features/staff-user.passport.feature b/packages/ocom/domain/src/domain/iam/user/staff-user/features/staff-user.passport.feature index 8145b32b4..172644ebb 100644 --- a/packages/ocom/domain/src/domain/iam/user/staff-user/features/staff-user.passport.feature +++ b/packages/ocom/domain/src/domain/iam/user/staff-user/features/staff-user.passport.feature @@ -20,4 +20,4 @@ Feature: StaffUserPassport Scenario: Accessing the user passport When I create a StaffUserPassport with valid staff user And I access the user property - Then an error should be thrown indicating the user passport is not available \ No newline at end of file + Then I should receive a StaffUserUserPassport instance \ No newline at end of file diff --git a/packages/ocom/domain/src/domain/iam/user/staff-user/staff-user.passport.test.ts b/packages/ocom/domain/src/domain/iam/user/staff-user/staff-user.passport.test.ts index 62a730e0a..6e5f74139 100644 --- a/packages/ocom/domain/src/domain/iam/user/staff-user/staff-user.passport.test.ts +++ b/packages/ocom/domain/src/domain/iam/user/staff-user/staff-user.passport.test.ts @@ -6,6 +6,7 @@ import type { CommunityEntityReference } from '../../../contexts/community/commu import type { StaffUserEntityReference } from '../../../contexts/user/staff-user/staff-user.ts'; import { StaffUserCommunityPassport } from './contexts/staff-user.community.passport.ts'; import { StaffUserCommunityVisa } from './contexts/staff-user.community.visa.ts'; +import { StaffUserUserPassport } from './contexts/staff-user.user.passport.ts'; import { StaffUserPassport } from './staff-user.passport.ts'; const test = { for: describeFeature }; @@ -85,15 +86,15 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { }); Scenario('Accessing the user passport', ({ When, And, Then }) => { - let getUserPassport: () => void; + let userPassport: unknown; When('I create a StaffUserPassport with valid staff user', () => { passport = new StaffUserPassport(staffUser); }); And('I access the user property', () => { - getUserPassport = () => passport.user; + userPassport = passport.user; }); - Then('an error should be thrown indicating the user passport is not available', () => { - expect(getUserPassport).toThrow('User passport is not available for StaffUserPassport'); + Then('I should receive a StaffUserUserPassport instance', () => { + expect(userPassport).toBeInstanceOf(StaffUserUserPassport); }); }); }); diff --git a/packages/ocom/domain/src/domain/iam/user/staff-user/staff-user.passport.ts b/packages/ocom/domain/src/domain/iam/user/staff-user/staff-user.passport.ts index 5d2715451..92a9a9369 100644 --- a/packages/ocom/domain/src/domain/iam/user/staff-user/staff-user.passport.ts +++ b/packages/ocom/domain/src/domain/iam/user/staff-user/staff-user.passport.ts @@ -2,15 +2,18 @@ import type { CasePassport } from '../../../contexts/case/case.passport.ts'; import type { CommunityPassport } from '../../../contexts/community/community.passport.ts'; import type { Passport } from '../../../contexts/passport.ts'; import type { PropertyPassport } from '../../../contexts/property/property.passport.ts'; +import type { UserPassport } from '../../../contexts/user/user.passport.ts'; import { StaffUserPassportBase } from '../staff-user.passport-base.ts'; import { StaffUserCasePassport } from './contexts/staff-user.case.passport.ts'; import { StaffUserCommunityPassport } from './contexts/staff-user.community.passport.ts'; import { StaffUserPropertyPassport } from './contexts/staff-user.property.passport.ts'; +import { StaffUserUserPassport } from './contexts/staff-user.user.passport.ts'; export class StaffUserPassport extends StaffUserPassportBase implements Passport { private _communityPassport: CommunityPassport | undefined; private _propertyPassport: PropertyPassport | undefined; private _casePassport: CasePassport | undefined; + private _userPassport: UserPassport | undefined; public get case(): CasePassport { if (!this._casePassport) { @@ -37,7 +40,10 @@ export class StaffUserPassport extends StaffUserPassportBase implements Passport throw new Error('Service passport is not available for StaffUserPassport'); } - public get user(): never { - throw new Error('User passport is not available for StaffUserPassport'); + public get user(): UserPassport { + if (!this._userPassport) { + this._userPassport = new StaffUserUserPassport(this._user); + } + return this._userPassport; } } From 6202fd1aa756809d3962c7ca755a1909d1b31c98 Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Wed, 13 May 2026 15:19:34 -0400 Subject: [PATCH 73/88] Added TechAdmin permission to finance, community-management, and user-management --- apps/ui-staff/src/hooks/use-staff-permissions.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/apps/ui-staff/src/hooks/use-staff-permissions.ts b/apps/ui-staff/src/hooks/use-staff-permissions.ts index 6a63b93ad..804de5640 100644 --- a/apps/ui-staff/src/hooks/use-staff-permissions.ts +++ b/apps/ui-staff/src/hooks/use-staff-permissions.ts @@ -65,13 +65,16 @@ export const useStaffPermissions = (): { permissions: StaffPermissions | undefin }); const rolePermissions = data?.currentStaffUserAndCreateIfNotExists?.role?.permissions; - + + // Treat a TechAdmin as an implicit manager of all sections + const isTechAdmin = rolePermissions?.techAdminPermissions?.canManageTechAdmin ?? false; + const permissions: StaffPermissions | undefined = rolePermissions ? { - canManageCommunities: rolePermissions.communityPermissions.canManageCommunities, - canManageUsers: rolePermissions.userPermissions.canManageUsers, - canManageFinance: rolePermissions.financePermissions.canManageFinance, - canManageTechAdmin: rolePermissions.techAdminPermissions.canManageTechAdmin, + canManageCommunities: rolePermissions.communityPermissions.canManageCommunities || isTechAdmin, + canManageUsers: rolePermissions.userPermissions.canManageUsers || isTechAdmin, + canManageFinance: rolePermissions.financePermissions.canManageFinance || isTechAdmin, + canManageTechAdmin: isTechAdmin, } : undefined; From ef09d6d224e10e370aab2f28c52526bf2e7b7b68 Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Thu, 14 May 2026 11:12:13 -0400 Subject: [PATCH 74/88] downgrade packageManager to pnpm@10.30.1, add canManage permissions set to true on the default tech admin role, rename RoleName with default --- apps/ui-staff/src/App.tsx | 4 +- .../src/hooks/use-staff-permissions.ts | 16 +++- package.json | 2 +- .../staff-role/create-default-roles.test.ts | 46 +++++----- .../user/staff-role/create-default-roles.ts | 8 +- .../features/create-default-roles.feature | 38 ++++----- .../staff-user/create-if-not-exists.test.ts | 84 +++++++++++++++++++ .../user/staff-user/create-if-not-exists.ts | 37 +++++++- .../features/create-if-not-exists.feature | 21 +++++ .../staff-role/staff-role-defaults.test.ts | 24 +++--- .../contexts/user/staff-role/staff-role.ts | 25 +++--- .../ui-staff-shared/src/section-layout.tsx | 2 +- 12 files changed, 232 insertions(+), 75 deletions(-) diff --git a/apps/ui-staff/src/App.tsx b/apps/ui-staff/src/App.tsx index 71773aed9..e26ad3e83 100644 --- a/apps/ui-staff/src/App.tsx +++ b/apps/ui-staff/src/App.tsx @@ -134,7 +134,7 @@ export default function App() { } function StaffSection({ identity }: { identity: Parameters[0]['value'] }) { - const { permissions, loading } = useStaffPermissions(); + const { permissions, user, loading } = useStaffPermissions(); if (loading) { return ( @@ -145,7 +145,7 @@ function StaffSection({ identity }: { identity: Parameters + ); diff --git a/apps/ui-staff/src/hooks/use-staff-permissions.ts b/apps/ui-staff/src/hooks/use-staff-permissions.ts index 804de5640..10ec1c756 100644 --- a/apps/ui-staff/src/hooks/use-staff-permissions.ts +++ b/apps/ui-staff/src/hooks/use-staff-permissions.ts @@ -59,16 +59,17 @@ interface StaffUserQueryResult { }; } -export const useStaffPermissions = (): { permissions: StaffPermissions | undefined; loading: boolean; error: Error | undefined } => { +export const useStaffPermissions = (): { permissions: StaffPermissions | undefined; user: { id?: string; displayName?: string; firstName?: string; lastName?: string; email?: string } | undefined; loading: boolean; error: Error | undefined } => { const { data, loading, error } = useQuery(CURRENT_STAFF_USER_QUERY, { fetchPolicy: 'cache-first', }); const rolePermissions = data?.currentStaffUserAndCreateIfNotExists?.role?.permissions; - + const currentUser = data?.currentStaffUserAndCreateIfNotExists + // Treat a TechAdmin as an implicit manager of all sections const isTechAdmin = rolePermissions?.techAdminPermissions?.canManageTechAdmin ?? false; - + const permissions: StaffPermissions | undefined = rolePermissions ? { canManageCommunities: rolePermissions.communityPermissions.canManageCommunities || isTechAdmin, @@ -80,6 +81,15 @@ export const useStaffPermissions = (): { permissions: StaffPermissions | undefin return { permissions, + user: currentUser + ? { + id: currentUser.id, + displayName: currentUser.displayName, + firstName: currentUser.firstName, + lastName: currentUser.lastName, + email: currentUser.email, + } + : undefined, loading, error, }; diff --git a/package.json b/package.json index 4e05dce27..84cbd6353 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "type": "module", "author": "CellixJs", "license": "MIT", - "packageManager": "pnpm@10.33.2", + "packageManager": "pnpm@10.30.1", "scripts": { "antd": "antd", "audit": "(pnpm audit --audit-level=high --prod) && (pnpm audit --audit-level=critical --dev)", diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts index 287351c64..ae86143a8 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts @@ -103,7 +103,7 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { result = await createDefaultRoles(dataSources)(); }); - Then('it should create all four roles: "Staff.CaseManager", "Staff.ServiceLineOwner", "Staff.Finance", "Staff.TechAdmin"', () => { + Then('it should create all four roles: "Default.CaseManager", "Default.ServiceLineOwner", "Default.Finance", "Default.TechAdmin"', () => { expect(vi.mocked(mockRepo.getNewInstance)).toHaveBeenCalledTimes(4); const names = vi.mocked(mockRepo.getNewInstance).mock.calls.map(([n]) => n); expect(names).toContain(StaffAppRoleNames.CaseManager); @@ -121,7 +121,7 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { // ─── Partial skip ───────────────────────────────────────────────────────── Scenario('Skips roles that already exist', ({ Given, When, Then, And }) => { - Given('the role "Staff.CaseManager" already exists', () => { + Given('the role "Default.CaseManager" already exists', () => { mockRepo = makeMockRepo([StaffAppRoleNames.CaseManager]); dataSources = makeDataSources(mockRepo); }); @@ -134,7 +134,7 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { expect(vi.mocked(mockRepo.getNewInstance)).toHaveBeenCalledTimes(3); }); - And('it should not attempt to create "Staff.CaseManager" again', () => { + And('it should not attempt to create "Default.CaseManager" again', () => { const names = vi.mocked(mockRepo.getNewInstance).mock.calls.map(([n]) => n); expect(names).not.toContain(StaffAppRoleNames.CaseManager); }); @@ -185,22 +185,22 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { await createDefaultRoles(dataSources)(); }); - Then('the "Staff.CaseManager" role should have canManageCommunities true', () => { + Then('the "Default.CaseManager" role should have canManageCommunities true', () => { const role = capturedRoles.get(StaffAppRoleNames.CaseManager); expect(role?.permissions.communityPermissions.canManageCommunities).toBe(true); }); - And('the "Staff.CaseManager" role should have canManageFinance false', () => { + And('the "Default.CaseManager" role should have canManageFinance false', () => { const role = capturedRoles.get(StaffAppRoleNames.CaseManager); expect(role?.permissions.financePermissions.canManageFinance).toBe(false); }); - And('the "Staff.CaseManager" role should have canManageTechAdmin false', () => { + And('the "Default.CaseManager" role should have canManageTechAdmin false', () => { const role = capturedRoles.get(StaffAppRoleNames.CaseManager); expect(role?.permissions.techAdminPermissions.canManageTechAdmin).toBe(false); }); - And('the "Staff.CaseManager" role should have canManageUsers true', () => { + And('the "Default.CaseManager" role should have canManageUsers true', () => { const role = capturedRoles.get(StaffAppRoleNames.CaseManager); expect(role?.permissions.userPermissions.canManageUsers).toBe(true); }); @@ -229,22 +229,22 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { await createDefaultRoles(dataSources)(); }); - Then('the "Staff.Finance" role should have canManageCommunities false', () => { + Then('the "Default.Finance" role should have canManageCommunities false', () => { const role = capturedRoles.get(StaffAppRoleNames.Finance); expect(role?.permissions.communityPermissions.canManageCommunities).toBe(false); }); - And('the "Staff.Finance" role should have canManageFinance true', () => { + And('the "Default.Finance" role should have canManageFinance true', () => { const role = capturedRoles.get(StaffAppRoleNames.Finance); expect(role?.permissions.financePermissions.canManageFinance).toBe(true); }); - And('the "Staff.Finance" role should have canManageTechAdmin false', () => { + And('the "Default.Finance" role should have canManageTechAdmin false', () => { const role = capturedRoles.get(StaffAppRoleNames.Finance); expect(role?.permissions.techAdminPermissions.canManageTechAdmin).toBe(false); }); - And('the "Staff.Finance" role should have canManageUsers false', () => { + And('the "Default.Finance" role should have canManageUsers false', () => { const role = capturedRoles.get(StaffAppRoleNames.Finance); expect(role?.permissions.userPermissions.canManageUsers).toBe(false); }); @@ -273,24 +273,26 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { await createDefaultRoles(dataSources)(); }); - Then('the "Staff.TechAdmin" role should have canManageCommunities false', () => { + Then('the "Default.TechAdmin" role should have canManageCommunities true', () => { const role = capturedRoles.get(StaffAppRoleNames.TechAdmin); - expect(role?.permissions.communityPermissions.canManageCommunities).toBe(false); + expect(role?.permissions.communityPermissions.canManageCommunities).toBe(true); + // Tech Admins should also be able to manage staff roles & permissions by default + expect(role?.permissions.communityPermissions.canManageStaffRolesAndPermissions).toBe(true); }); - And('the "Staff.TechAdmin" role should have canManageFinance false', () => { + And('the "Default.TechAdmin" role should have canManageFinance true', () => { const role = capturedRoles.get(StaffAppRoleNames.TechAdmin); - expect(role?.permissions.financePermissions.canManageFinance).toBe(false); + expect(role?.permissions.financePermissions.canManageFinance).toBe(true); }); - And('the "Staff.TechAdmin" role should have canManageTechAdmin true', () => { + And('the "Default.TechAdmin" role should have canManageTechAdmin true', () => { const role = capturedRoles.get(StaffAppRoleNames.TechAdmin); expect(role?.permissions.techAdminPermissions.canManageTechAdmin).toBe(true); }); - And('the "Staff.TechAdmin" role should have canManageUsers false', () => { + And('the "Default.TechAdmin" role should have canManageUsers true', () => { const role = capturedRoles.get(StaffAppRoleNames.TechAdmin); - expect(role?.permissions.userPermissions.canManageUsers).toBe(false); + expect(role?.permissions.userPermissions.canManageUsers).toBe(true); }); }); @@ -317,22 +319,22 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { await createDefaultRoles(dataSources)(); }); - Then('the "Staff.ServiceLineOwner" role should have canManageCommunities true', () => { + Then('the "Default.ServiceLineOwner" role should have canManageCommunities true', () => { const role = capturedRoles.get(StaffAppRoleNames.ServiceLineOwner); expect(role?.permissions.communityPermissions.canManageCommunities).toBe(true); }); - And('the "Staff.ServiceLineOwner" role should have canManageFinance false', () => { + And('the "Default.ServiceLineOwner" role should have canManageFinance false', () => { const role = capturedRoles.get(StaffAppRoleNames.ServiceLineOwner); expect(role?.permissions.financePermissions.canManageFinance).toBe(false); }); - And('the "Staff.ServiceLineOwner" role should have canManageTechAdmin false', () => { + And('the "Default.ServiceLineOwner" role should have canManageTechAdmin false', () => { const role = capturedRoles.get(StaffAppRoleNames.ServiceLineOwner); expect(role?.permissions.techAdminPermissions.canManageTechAdmin).toBe(false); }); - And('the "Staff.ServiceLineOwner" role should have canManageUsers true', () => { + And('the "Default.ServiceLineOwner" role should have canManageUsers true', () => { const role = capturedRoles.get(StaffAppRoleNames.ServiceLineOwner); expect(role?.permissions.userPermissions.canManageUsers).toBe(true); }); diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts index 981f533f3..ec565bb8f 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts @@ -3,10 +3,10 @@ import { Domain as DomainRuntime } from '@ocom/domain'; import type { DataSources } from '@ocom/persistence'; export const StaffAppRoleNames = { - CaseManager: 'Staff.CaseManager', - ServiceLineOwner: 'Staff.ServiceLineOwner', - Finance: 'Staff.Finance', - TechAdmin: 'Staff.TechAdmin', + CaseManager: 'Default.CaseManager', + ServiceLineOwner: 'Default.ServiceLineOwner', + Finance: 'Default.Finance', + TechAdmin: 'Default.TechAdmin', } as const; export type StaffAppRoleName = (typeof StaffAppRoleNames)[keyof typeof StaffAppRoleNames]; diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/features/create-default-roles.feature b/packages/ocom/application-services/src/contexts/user/staff-role/features/create-default-roles.feature index d334f032f..83892960d 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-role/features/create-default-roles.feature +++ b/packages/ocom/application-services/src/contexts/user/staff-role/features/create-default-roles.feature @@ -3,14 +3,14 @@ Feature: Creating default staff roles Scenario: Creates all four default roles when none exist Given no staff roles exist When I call createDefaultRoles - Then it should create all four roles: "Staff.CaseManager", "Staff.ServiceLineOwner", "Staff.Finance", "Staff.TechAdmin" + Then it should create all four roles: "Default.CaseManager", "Default.ServiceLineOwner", "Default.Finance", "Default.TechAdmin" And it should return all four created role references Scenario: Skips roles that already exist - Given the role "Staff.CaseManager" already exists + Given the role "Default.CaseManager" already exists When I call createDefaultRoles Then it should only create the three missing roles - And it should not attempt to create "Staff.CaseManager" again + And it should not attempt to create "Default.CaseManager" again Scenario: Returns empty array when all roles already exist Given all four default roles already exist @@ -21,34 +21,34 @@ Feature: Creating default staff roles Scenario: CaseManager role has correct permissions Given no staff roles exist When I call createDefaultRoles - Then the "Staff.CaseManager" role should have canManageCommunities true - And the "Staff.CaseManager" role should have canManageFinance false - And the "Staff.CaseManager" role should have canManageTechAdmin false - And the "Staff.CaseManager" role should have canManageUsers true + Then the "Default.CaseManager" role should have canManageCommunities true + And the "Default.CaseManager" role should have canManageFinance false + And the "Default.CaseManager" role should have canManageTechAdmin false + And the "Default.CaseManager" role should have canManageUsers true Scenario: Finance role has correct permissions Given no staff roles exist When I call createDefaultRoles - Then the "Staff.Finance" role should have canManageCommunities false - And the "Staff.Finance" role should have canManageFinance true - And the "Staff.Finance" role should have canManageTechAdmin false - And the "Staff.Finance" role should have canManageUsers false + Then the "Default.Finance" role should have canManageCommunities false + And the "Default.Finance" role should have canManageFinance true + And the "Default.Finance" role should have canManageTechAdmin false + And the "Default.Finance" role should have canManageUsers false Scenario: TechAdmin role has correct permissions Given no staff roles exist When I call createDefaultRoles - Then the "Staff.TechAdmin" role should have canManageCommunities false - And the "Staff.TechAdmin" role should have canManageFinance false - And the "Staff.TechAdmin" role should have canManageTechAdmin true - And the "Staff.TechAdmin" role should have canManageUsers false + Then the "Default.TechAdmin" role should have canManageCommunities true + And the "Default.TechAdmin" role should have canManageFinance true + And the "Default.TechAdmin" role should have canManageTechAdmin true + And the "Default.TechAdmin" role should have canManageUsers true Scenario: ServiceLineOwner role has correct permissions Given no staff roles exist When I call createDefaultRoles - Then the "Staff.ServiceLineOwner" role should have canManageCommunities true - And the "Staff.ServiceLineOwner" role should have canManageFinance false - And the "Staff.ServiceLineOwner" role should have canManageTechAdmin false - And the "Staff.ServiceLineOwner" role should have canManageUsers true + Then the "Default.ServiceLineOwner" role should have canManageCommunities true + And the "Default.ServiceLineOwner" role should have canManageFinance false + And the "Default.ServiceLineOwner" role should have canManageTechAdmin false + And the "Default.ServiceLineOwner" role should have canManageUsers true Scenario: All created roles have isDefault set to true Given no staff roles exist diff --git a/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.test.ts b/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.test.ts index 3bc29c93b..c2c8b485f 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.test.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.test.ts @@ -255,6 +255,90 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { }); }); + Scenario('Assigns Default.TechAdmin when AAD role is techAdmin (alias)', ({ Given, When, Then, And }) => { + let roleRef: Domain.Contexts.User.StaffRole.StaffRoleEntityReference; + + Given('no staff user with externalId "ext-201" exists', () => { + roleRef = makeMockStaffRoleRef(StaffAppRoleNames.TechAdmin); + newUser = makeMockNewUser('ext-201'); + dataSources = makeDataSources({ existingUser: null, newUser, roleByName: roleRef }); + command = { ...command, externalId: 'ext-201' }; + }); + + And('the AAD roles include "techAdmin"', () => { + command = { ...command, aadRoles: ['techAdmin'] }; + }); + + And('the "Default.TechAdmin" role exists in the repository', () => { + // role was set up in Given + }); + + When('I call createIfNotExists with externalId "ext-201"', async () => { + result = await createIfNotExists(dataSources)(command); + }); + + Then('it should assign the "Default.TechAdmin" role to the new user', () => { + expect(newUser.role).toBeDefined(); + expect(newUser.role?.roleName).toBe(StaffAppRoleNames.TechAdmin); + }); + }); + + Scenario('Assigns Default.TechAdmin when AAD role is canonical', ({ Given, When, Then, And }) => { + let roleRef: Domain.Contexts.User.StaffRole.StaffRoleEntityReference; + + Given('no staff user with externalId "ext-202" exists', () => { + roleRef = makeMockStaffRoleRef(StaffAppRoleNames.TechAdmin); + newUser = makeMockNewUser('ext-202'); + dataSources = makeDataSources({ existingUser: null, newUser, roleByName: roleRef }); + command = { ...command, externalId: 'ext-202' }; + }); + + And('the AAD roles include "Default.TechAdmin"', () => { + command = { ...command, aadRoles: [StaffAppRoleNames.TechAdmin] }; + }); + + And('the "Default.TechAdmin" role exists in the repository', () => { + // role was set up in Given + }); + + When('I call createIfNotExists with externalId "ext-202"', async () => { + result = await createIfNotExists(dataSources)(command); + }); + + Then('it should assign the "Default.TechAdmin" role to the new user', () => { + expect(newUser.role).toBeDefined(); + expect(newUser.role?.roleName).toBe(StaffAppRoleNames.TechAdmin); + }); + }); + + Scenario('Assigns Default.TechAdmin when AAD role has alternate formatting', ({ Given, When, Then, And }) => { + let roleRef: Domain.Contexts.User.StaffRole.StaffRoleEntityReference; + + Given('no staff user with externalId "ext-203" exists', () => { + roleRef = makeMockStaffRoleRef(StaffAppRoleNames.TechAdmin); + newUser = makeMockNewUser('ext-203'); + dataSources = makeDataSources({ existingUser: null, newUser, roleByName: roleRef }); + command = { ...command, externalId: 'ext-203' }; + }); + + And('the AAD roles include "default tech admin"', () => { + command = { ...command, aadRoles: ['default tech admin'] }; + }); + + And('the "Default.TechAdmin" role exists in the repository', () => { + // role was set up in Given + }); + + When('I call createIfNotExists with externalId "ext-203"', async () => { + result = await createIfNotExists(dataSources)(command); + }); + + Then('it should assign the "Default.TechAdmin" role to the new user', () => { + expect(newUser.role).toBeDefined(); + expect(newUser.role?.roleName).toBe(StaffAppRoleNames.TechAdmin); + }); + }); + // ─── No role when AAD role unknown ──────────────────────────────────────── Scenario('Creates a new user without a role when no AAD role matches', ({ Given, When, Then, And }) => { diff --git a/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.ts b/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.ts index f5fc7e83a..f07bcb478 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-user/create-if-not-exists.ts @@ -13,7 +13,42 @@ export interface StaffUserCreateIfNotExistsCommand { const findMatchingRoleName = (aadRoles: string[]): StaffAppRoleName | undefined => { const knownRoles = Object.values(StaffAppRoleNames) as StaffAppRoleName[]; - return aadRoles.find((r): r is StaffAppRoleName => knownRoles.includes(r as StaffAppRoleName)); + + // Prefer exact canonical match first + for (const r of aadRoles) { + if (knownRoles.includes(r as StaffAppRoleName)) { + return r as StaffAppRoleName; + } + } + + // Normalization helpers: remove non-alphanumeric and lowercase + const normalize = (s: string) => s.toLowerCase().replace(/[^a-z0-9]/g, ''); + + // Build lookup maps from various normalized forms to canonical role name + const normalizedMap = new Map(); + for (const kr of knownRoles) { + const fullNorm = normalize(kr); + normalizedMap.set(fullNorm, kr); + // also store a base name without common prefixes like "default" or "staff" + const baseNorm = fullNorm.replace(/^(default|staff)/, ''); + normalizedMap.set(baseNorm, kr); + } + + for (const r of aadRoles) { + const norm = normalize(r); + // direct normalized match + if (normalizedMap.has(norm)) { + return normalizedMap.get(norm) as StaffAppRoleName; + } + // try stripping common prefixes from incoming claim and match again + const stripped = norm.replace(/^(default|staff)/, ''); + if (normalizedMap.has(stripped)) { + return normalizedMap.get(stripped) as StaffAppRoleName; + } + } + + // No match found + return undefined; }; const getRoleByName = async (dataSources: DataSources, roleName: string): Promise => { diff --git a/packages/ocom/application-services/src/contexts/user/staff-user/features/create-if-not-exists.feature b/packages/ocom/application-services/src/contexts/user/staff-user/features/create-if-not-exists.feature index cebfbebf5..d052b1f35 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-user/features/create-if-not-exists.feature +++ b/packages/ocom/application-services/src/contexts/user/staff-user/features/create-if-not-exists.feature @@ -21,6 +21,27 @@ Feature: Create staff user if not exists When I call createIfNotExists with externalId "ext-789" Then it should assign the "Staff.CaseManager" role to the new user + Scenario: Assigns Default.TechAdmin when AAD role is techAdmin (alias) + Given no staff user with externalId "ext-201" exists + And the AAD roles include "techAdmin" + And the "Default.TechAdmin" role exists in the repository + When I call createIfNotExists with externalId "ext-201" + Then it should assign the "Default.TechAdmin" role to the new user + + Scenario: Assigns Default.TechAdmin when AAD role is canonical + Given no staff user with externalId "ext-202" exists + And the AAD roles include "Default.TechAdmin" + And the "Default.TechAdmin" role exists in the repository + When I call createIfNotExists with externalId "ext-202" + Then it should assign the "Default.TechAdmin" role to the new user + + Scenario: Assigns Default.TechAdmin when AAD role has alternate formatting + Given no staff user with externalId "ext-203" exists + And the AAD roles include "default tech admin" + And the "Default.TechAdmin" role exists in the repository + When I call createIfNotExists with externalId "ext-203" + Then it should assign the "Default.TechAdmin" role to the new user + Scenario: Creates a new user without a role when no AAD role matches Given no staff user with externalId "ext-000" exists And the AAD roles include "Unknown.Role" diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-defaults.test.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-defaults.test.ts index 093bf22a6..6cb02baa3 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-defaults.test.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-defaults.test.ts @@ -70,9 +70,9 @@ function makeBaseProps(overrides: Partial = {}): StaffRoleProps test('applyDefaultSpec sets CaseManager permissions correctly and marks default', () => { const passport = makePassport(); - const role = StaffRole.getNewInstance(makeBaseProps(), passport, 'Staff.CaseManager', false); + const role = StaffRole.getNewInstance(makeBaseProps(), passport, 'Default.CaseManager', false); - StaffRole.applyDefaultSpec(role, 'Staff.CaseManager'); + StaffRole.applyDefaultSpec(role, 'Default.CaseManager'); expect(role.permissions.communityPermissions.canManageCommunities).toBe(true); expect(role.permissions.financePermissions.canManageFinance).toBe(false); @@ -83,9 +83,9 @@ test('applyDefaultSpec sets CaseManager permissions correctly and marks default' test('applyDefaultSpec sets Finance permissions correctly and marks default', () => { const passport = makePassport(); - const role = StaffRole.getNewInstance(makeBaseProps(), passport, 'Staff.Finance', false); + const role = StaffRole.getNewInstance(makeBaseProps(), passport, 'Default.Finance', false); - StaffRole.applyDefaultSpec(role, 'Staff.Finance'); + StaffRole.applyDefaultSpec(role, 'Default.Finance'); expect(role.permissions.communityPermissions.canManageCommunities).toBe(false); expect(role.permissions.financePermissions.canManageFinance).toBe(true); @@ -96,9 +96,9 @@ test('applyDefaultSpec sets Finance permissions correctly and marks default', () test('applyDefaultSpec sets ServiceLineOwner permissions correctly and marks default', () => { const passport = makePassport(); - const role = StaffRole.getNewInstance(makeBaseProps(), passport, 'Staff.ServiceLineOwner', false); + const role = StaffRole.getNewInstance(makeBaseProps(), passport, 'Default.ServiceLineOwner', false); - StaffRole.applyDefaultSpec(role, 'Staff.ServiceLineOwner'); + StaffRole.applyDefaultSpec(role, 'Default.ServiceLineOwner'); expect(role.permissions.communityPermissions.canManageCommunities).toBe(true); expect(role.permissions.financePermissions.canManageFinance).toBe(false); @@ -109,13 +109,15 @@ test('applyDefaultSpec sets ServiceLineOwner permissions correctly and marks def test('applyDefaultSpec sets TechAdmin permissions correctly and marks default', () => { const passport = makePassport(); - const role = StaffRole.getNewInstance(makeBaseProps(), passport, 'Staff.TechAdmin', false); + const role = StaffRole.getNewInstance(makeBaseProps(), passport, 'Default.TechAdmin', false); - StaffRole.applyDefaultSpec(role, 'Staff.TechAdmin'); + StaffRole.applyDefaultSpec(role, 'Default.TechAdmin'); - expect(role.permissions.communityPermissions.canManageCommunities).toBe(false); - expect(role.permissions.financePermissions.canManageFinance).toBe(false); + expect(role.permissions.communityPermissions.canManageCommunities).toBe(true); + // Tech Admins should also be able to manage staff roles & permissions by default + expect(role.permissions.communityPermissions.canManageStaffRolesAndPermissions).toBe(true); + expect(role.permissions.financePermissions.canManageFinance).toBe(true); expect(role.permissions.techAdminPermissions.canManageTechAdmin).toBe(true); - expect(role.permissions.userPermissions.canManageUsers).toBe(false); + expect(role.permissions.userPermissions.canManageUsers).toBe(true); expect(role.isDefault).toBe(true); }); diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts index e2de1dbcc..021bfbf15 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts @@ -52,10 +52,10 @@ export class StaffRole extends AggregateRoot extends AggregateRoot): void { - staffRole.permissions.communityPermissions.canManageCommunities = false; - staffRole.permissions.financePermissions.canManageFinance = false; + // Tech Admins are implicit managers of all areas + staffRole.permissions.communityPermissions.canManageCommunities = true; + // Tech Admins should also be able to manage staff roles & permissions by default + staffRole.permissions.communityPermissions.canManageStaffRolesAndPermissions = true; + staffRole.permissions.financePermissions.canManageFinance = true; staffRole.permissions.techAdminPermissions.canManageTechAdmin = true; - staffRole.permissions.userPermissions.canManageUsers = false; + staffRole.permissions.userPermissions.canManageUsers = true; staffRole.isDefault = true; } @@ -102,16 +105,16 @@ export class StaffRole extends AggregateRoot = (props) => { marginLeft: 'auto', }} > - Staff User + {auth?.name || auth?.username || auth?.email || 'Staff User'} + +

    Sign up

    + `; +} + +/** Builds the mock signup page HTML. */ +export function buildSignupHtml(opts: { issuerBaseUrl: string; nonce?: string; username?: string; email?: string; given_name?: string; family_name?: string; error?: string }) { + const { issuerBaseUrl, nonce, username, email, given_name, family_name, error } = opts; + const escapedIssuerBaseUrl = escapeHtml(issuerBaseUrl); + const safeNonce = nonce ?? ''; + const encodedNonce = encodeURIComponent(safeNonce); + const escapedNonce = escapeHtml(safeNonce); + return `Mock Signup +

    Sign up

    + ${error ? `

    ${escapeHtml(error)}

    ` : ''} +
    + +
    +
    +
    +
    +
    + +
    + `; +} diff --git a/packages/cellix/server-oauth2-mock-seedwork/src/index.ts b/packages/cellix/server-oauth2-mock-seedwork/src/index.ts index d7c94b0f9..1a121f8ad 100644 --- a/packages/cellix/server-oauth2-mock-seedwork/src/index.ts +++ b/packages/cellix/server-oauth2-mock-seedwork/src/index.ts @@ -1,9 +1,11 @@ /* Index entrypoint — re-exports from smaller modules to keep the public surface stable */ + +export { debugLog } from './logger.ts'; export { createMockOAuth2Manager } from './manager.ts'; export { buildOidcRouter } from './router.ts'; export { startMockOAuth2Server } from './server.ts'; -export type { MockOAuth2Manager, MockOAuth2PortalConfig, MockOAuth2Registration, MockOAuth2ServerConfig, MockOAuth2ServerHandle, MockOAuth2UserProfile } from './types.ts'; -export { normalizeBaseUrl, normalizeOrigin, normalizeUrl, SAFE_NAME_RE } from './utils.ts'; +export type { MockOAuth2Manager, MockOAuth2PortalConfig, MockOAuth2Registration, MockOAuth2ServerConfig, MockOAuth2ServerHandle, MockOAuth2User, MockOAuth2UserProfile, MockOAuth2UserStore } from './types.ts'; +export { AUTH_CODE_PREFIX, normalizeBaseUrl, normalizeOrigin, normalizeUrl, SAFE_NAME_RE } from './utils.ts'; diff --git a/packages/cellix/server-oauth2-mock-seedwork/src/logger.test.ts b/packages/cellix/server-oauth2-mock-seedwork/src/logger.test.ts new file mode 100644 index 000000000..d204e39d4 --- /dev/null +++ b/packages/cellix/server-oauth2-mock-seedwork/src/logger.test.ts @@ -0,0 +1,8 @@ +import { describe, expect, it } from 'vitest'; +import { debugLog } from './index.ts'; + +describe('debugLog', () => { + it('returns undefined when debug logging is disabled', () => { + expect(debugLog('test message')).toBeUndefined(); + }); +}); diff --git a/packages/cellix/server-oauth2-mock-seedwork/src/logger.ts b/packages/cellix/server-oauth2-mock-seedwork/src/logger.ts new file mode 100644 index 000000000..a6a268e52 --- /dev/null +++ b/packages/cellix/server-oauth2-mock-seedwork/src/logger.ts @@ -0,0 +1,25 @@ +// biome-ignore lint/complexity/useLiteralKeys: ProcessEnv uses an index signature in this repo's TypeScript config. +const debugFlag = process.env['MOCK_OAUTH2_DEBUG']; +const debugEnabled = debugFlag === '1' || debugFlag === 'true'; + +/** + * Emits mock OAuth2 debug output when `MOCK_OAUTH2_DEBUG` is enabled. + * + * @param message - Human-readable debug message. + * @param data - Optional structured fields to log alongside the message. + * @returns `undefined`. Logging is skipped entirely when debug output is disabled. + * + * @example + * ```ts + * debugLog('[server-oauth2-mock] addUser persisted', { portal: 'community', user: 'alice' }); + * ``` + */ +export function debugLog(message: string, data?: Record): void { + if (debugEnabled) { + if (data !== undefined) { + console.debug(message, data); + } else { + console.debug(message); + } + } +} diff --git a/packages/cellix/server-oauth2-mock-seedwork/src/login-handlers.ts b/packages/cellix/server-oauth2-mock-seedwork/src/login-handlers.ts new file mode 100644 index 000000000..288dc0313 --- /dev/null +++ b/packages/cellix/server-oauth2-mock-seedwork/src/login-handlers.ts @@ -0,0 +1,309 @@ +import crypto from 'node:crypto'; +import type { Request, RequestHandler, Router } from 'express'; +import { rateLimit } from 'express-rate-limit'; +import { buildLoginHtml, buildSignupHtml } from './html-builders.ts'; +import type { MockOAuth2PortalConfig, MockOAuth2User } from './types.ts'; +import { AUTH_CODE_PREFIX } from './utils.ts'; + +interface AuthCodeStoreEntry { + sub?: string; + redirectUri: string; + nonce?: string; +} + +interface LoginSessionStoreEntry { + redirectUri: string; + state: string; + nonce?: string; +} + +interface TtlStore { + get(key: string): T | undefined; + set(key: string, value: T): void; + delete(key: string): void; + has(key: string): boolean; +} + +interface LoginHandlerDeps { + config: MockOAuth2PortalConfig; + issuerBaseUrl: string; + primaryRedirectUri: string; + normalizedAllowedRedirectUris: Set; + loginSessionStore: TtlStore; + authCodeStore: TtlStore; + normalizeUrl: (url: string) => string; + buildRedirectWithCode: (redirect: string, code: string, state?: string) => string; + logger: { debug: (msg: string, meta?: Record) => void }; +} + +function isFormRequest(req: Request): boolean { + const contentType = req.get('content-type'); + return typeof contentType === 'string' && contentType.includes('application/x-www-form-urlencoded'); +} + +export function createLoginHandlers(deps: LoginHandlerDeps): { + registerRoutes(router: Router): void; +} { + const { config, issuerBaseUrl, primaryRedirectUri, normalizedAllowedRedirectUris, loginSessionStore, authCodeStore, normalizeUrl, buildRedirectWithCode, logger } = deps; + const formRateLimiter = rateLimit({ + windowMs: 60 * 1000, + max: 30, + standardHeaders: true, + legacyHeaders: false, + }) as unknown as RequestHandler; + const credentialRateLimiter = rateLimit({ + windowMs: 15 * 60 * 1000, + max: 10, + standardHeaders: true, + legacyHeaders: false, + message: { error: 'Too many attempts, please try again later.' }, + }) as unknown as RequestHandler; + + return { + registerRoutes(router: Router) { + router.get('/login', formRateLimiter, (req, res) => { + if (!config.userStore) { + res.status(404).send('Login not available'); + return; + } + const { state, redirect_uri, nonce } = req.query as { state?: string; redirect_uri?: string; nonce?: string }; + // Validate and bound query parameters to prevent memory bloat + const rawState = typeof state === 'string' ? state : ''; + if (rawState.length > 2048) { + res.status(400).json({ error: 'state parameter too large' }); + return; + } + const redirect = typeof redirect_uri === 'string' ? redirect_uri : primaryRedirectUri; + // Validate the full redirect_uri (including query params) against the normalized allowlist + // so GET and POST use the same validation semantics. Store the normalized value for consistency. + let normalizedRedirect: string; + try { + normalizedRedirect = normalizeUrl(redirect); + if (!normalizedAllowedRedirectUris.has(normalizedRedirect)) { + res.status(400).json({ error: 'Invalid redirect_uri' }); + return; + } + } catch { + res.status(400).json({ error: 'Invalid redirect_uri' }); + return; + } + const safeState = rawState; + const safeNonce = typeof nonce === 'string' ? nonce : undefined; + const sessionNonce = crypto.randomUUID(); + loginSessionStore.set(sessionNonce, { + redirectUri: normalizedRedirect, + state: safeState, + ...(safeNonce === undefined ? {} : { nonce: safeNonce }), + }); + logger.debug('[server-oauth2-mock] GET /login', { sessionNonce, loginSessionFound: loginSessionStore.has(sessionNonce) }); + res.setHeader('Content-Type', 'text/html; charset=utf-8'); + res.send(buildLoginHtml({ issuerBaseUrl, nonce: sessionNonce })); + }); + + router.post('/login', credentialRateLimiter, async (req, res) => { + if (!config.userStore) { + res.status(404).send('Login not available'); + return; + } + const { username, password } = req.body; + if (typeof username !== 'string' || typeof password !== 'string') { + res.status(400).json({ error: 'username and password are required' }); + return; + } + const nonceFromBody = typeof req.body.nonce === 'string' ? req.body.nonce : undefined; + const { nonce: rawQueryNonce } = req.query as Record; + const nonceFromQuery = typeof rawQueryNonce === 'string' ? rawQueryNonce : undefined; + let loginNonceUsed: string | undefined; + let loginSession: LoginSessionStoreEntry | undefined; + if (nonceFromBody) { + loginNonceUsed = nonceFromBody; + loginSession = loginSessionStore.get(nonceFromBody); + } + if (!loginSession && nonceFromQuery) { + loginNonceUsed = nonceFromQuery; + loginSession = loginSessionStore.get(nonceFromQuery); + } + let refererLookup: string | undefined; + if (!loginSession) { + const referer = req.get('referer') ?? req.get('referrer'); + if (typeof referer === 'string') { + try { + const refUrl = new URL(referer); + const alt = refUrl.searchParams.get('nonce'); + if (alt) { + refererLookup = alt; + const altSession = loginSessionStore.get(alt); + if (altSession) { + loginNonceUsed = alt; + loginSession = altSession; + } + } + } catch { + // ignore + } + } + } + + logger.debug('[server-oauth2-mock] POST /login', { nonceFromBody, nonceFromQuery, loginSessionFound: Boolean(loginSession), username }); + + if (!loginSession) { + console.warn('[server-oauth2-mock] Missing login session for nonce (body:%s, query:%s, refererLookup:%s) — rejecting request', nonceFromBody, nonceFromQuery, refererLookup ?? req.get('referer')); + const link = `${issuerBaseUrl}/authorize?redirect_uri=${encodeURIComponent(primaryRedirectUri)}`; + res + .status(400) + .setHeader('Content-Type', 'text/html; charset=utf-8') + .send(`

    Session expired

    Your login session has expired or is invalid. Start a new login

    `); + return; + } + + const redirect = loginSession.redirectUri ?? primaryRedirectUri; + const state = loginSession.state ?? undefined; + try { + const store = config.userStore; + const user = await store.findByUsername(username); + if (!user || typeof user.password !== 'string' || user.password !== password) { + if (isFormRequest(req)) { + res + .status(200) + .setHeader('Content-Type', 'text/html; charset=utf-8') + .send(buildLoginHtml({ issuerBaseUrl, nonce: loginNonceUsed ?? '', username, error: 'Invalid username or password. Please try again.' })); + return; + } + res.status(401).send('Invalid credentials'); + return; + } + try { + const normalized = normalizeUrl(redirect); + if (!normalizedAllowedRedirectUris.has(normalized)) { + res.status(400).send('Invalid redirect_uri'); + return; + } + const code = `${AUTH_CODE_PREFIX}${crypto.randomUUID()}`; + authCodeStore.set(code, { + sub: user.sub, + redirectUri: normalized, + ...(loginSession.nonce === undefined ? {} : { nonce: loginSession.nonce }), + }); + if (loginNonceUsed) { + loginSessionStore.delete(loginNonceUsed); + } + logger.debug('[server-oauth2-mock] POST /login success', { authCode: `${code.substring(0, 8)}...`, redirectUri: redirect, state }); + const location = buildRedirectWithCode(redirect, code, state); + res.setHeader('Location', location); + res.status(302).end(); + } catch { + res.status(400).send('Invalid redirect_uri format'); + } + } catch { + res.status(500).send('Login failed'); + } + }); + + router.get('/signup', formRateLimiter, (req, res) => { + if (!config.userStore) { + res.status(404).send('Signup not available'); + return; + } + const { state, redirect_uri, nonce: queryNonce } = req.query as { state?: string; redirect_uri?: string; nonce?: string }; + const existingSession = typeof queryNonce === 'string' ? loginSessionStore.get(queryNonce) : undefined; + if (existingSession && typeof queryNonce === 'string') { + loginSessionStore.delete(queryNonce); + } + // Validate and bound query parameters to prevent memory bloat + const rawState = existingSession?.state ?? (typeof state === 'string' ? state : ''); + if (rawState.length > 2048) { + res.status(400).json({ error: 'state parameter too large' }); + return; + } + const rawRedirect = existingSession?.redirectUri ?? (typeof redirect_uri === 'string' ? redirect_uri : primaryRedirectUri); + // Validate the full redirect_uri (including query params) against the normalized allowlist + // so GET and POST use the same validation semantics. Store the normalized value for consistency. + let normalizedRedirect: string; + try { + normalizedRedirect = normalizeUrl(rawRedirect); + if (!normalizedAllowedRedirectUris.has(normalizedRedirect)) { + res.status(400).json({ error: 'Invalid redirect_uri' }); + return; + } + } catch { + res.status(400).json({ error: 'Invalid redirect_uri' }); + return; + } + const safeState = rawState; + const safeNonce = existingSession ? existingSession.nonce : typeof queryNonce === 'string' ? queryNonce : undefined; + const nonce = crypto.randomUUID(); + loginSessionStore.set(nonce, { + redirectUri: normalizedRedirect, + state: safeState, + ...(safeNonce === undefined ? {} : { nonce: safeNonce }), + }); + res.setHeader('Content-Type', 'text/html; charset=utf-8'); + res.send(buildSignupHtml({ issuerBaseUrl, nonce })); + }); + + router.post('/signup', credentialRateLimiter, async (req, res) => { + if (!config.userStore) { + res.status(404).send('Signup not available'); + return; + } + const { username, password } = req.body; + if (typeof username !== 'string' || typeof password !== 'string') { + res.status(400).json({ error: 'username and password are required' }); + return; + } + const email = typeof req.body.email === 'string' ? req.body.email : undefined; + const given_name = typeof req.body.given_name === 'string' ? req.body.given_name : undefined; + const family_name = typeof req.body.family_name === 'string' ? req.body.family_name : undefined; + const signupNonce = typeof req.body.nonce === 'string' ? req.body.nonce : ''; + const signupSession = loginSessionStore.get(signupNonce); + const redirect = signupSession?.redirectUri ?? primaryRedirectUri; + const state = signupSession?.state ?? undefined; + try { + const claimsObj: { email?: unknown; given_name?: unknown; family_name?: unknown; [key: string]: unknown } = {}; + if (email) claimsObj.email = email; + if (given_name) claimsObj.given_name = given_name; + if (family_name) claimsObj.family_name = family_name; + const newUser: MockOAuth2User = { username, sub: crypto.randomUUID(), password, claims: claimsObj }; + const store = config.userStore; + await store.addUser(newUser); + await store.persist?.(); + try { + const normalized = normalizeUrl(redirect); + if (!normalizedAllowedRedirectUris.has(normalized)) { + res.status(400).send('Invalid redirect_uri'); + return; + } + const code = `${AUTH_CODE_PREFIX}${crypto.randomUUID()}`; + authCodeStore.set(code, { + sub: newUser.sub, + redirectUri: normalized, + ...(signupSession?.nonce === undefined ? {} : { nonce: signupSession.nonce }), + }); + if (signupNonce) { + loginSessionStore.delete(signupNonce); + } + const location = buildRedirectWithCode(redirect, code, state); + res.setHeader('Location', location); + res.status(302).end(); + } catch { + res.status(400).send('Invalid redirect_uri format'); + } + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + if (message.toLowerCase().includes('already exists')) { + if (isFormRequest(req)) { + res + .status(200) + .setHeader('Content-Type', 'text/html; charset=utf-8') + .send(buildSignupHtml({ issuerBaseUrl, nonce: signupNonce, username, email, given_name, family_name, error: 'A user with that username already exists. Please choose a different username.' })); + return; + } + res.status(409).json({ error: 'user_exists', error_description: message }); + return; + } + res.status(500).send('Signup failed'); + } + }); + }, + }; +} diff --git a/packages/cellix/server-oauth2-mock-seedwork/src/manager.test.ts b/packages/cellix/server-oauth2-mock-seedwork/src/manager.test.ts index 41198fcfa..5bb6eebbd 100644 --- a/packages/cellix/server-oauth2-mock-seedwork/src/manager.test.ts +++ b/packages/cellix/server-oauth2-mock-seedwork/src/manager.test.ts @@ -1,6 +1,6 @@ -import { describe, expect, it } from 'vitest'; -import { createMockOAuth2Manager } from './manager.ts'; -import type { MockOAuth2PortalConfig } from './types.ts'; +import express from 'express'; +import { afterEach, describe, expect, it, vi } from 'vitest'; +import { createMockOAuth2Manager, type MockOAuth2PortalConfig } from './index.ts'; function makeConfig(): MockOAuth2PortalConfig { return { @@ -11,13 +11,29 @@ function makeConfig(): MockOAuth2PortalConfig { }; } -describe('manager unit', () => { - it('exposes register and stopAll functions and rejects invalid names', async () => { - const manager = createMockOAuth2Manager({ port: 0, baseUrl: 'http://127.0.0.1:0' }); - expect(typeof manager.register).toBe('function'); - expect(typeof manager.stopAll).toBe('function'); +describe('createMockOAuth2Manager', () => { + afterEach(() => { + vi.restoreAllMocks(); + }); + + describe('manager unit', () => { + it('exposes register and stopAll functions and rejects invalid names', async () => { + const manager = createMockOAuth2Manager({ port: 0, baseUrl: 'http://127.0.0.1:0' }); + expect(typeof manager.register).toBe('function'); + expect(typeof manager.stopAll).toBe('function'); + + await expect(manager.register('bad/name', makeConfig())).rejects.toThrow(); + await manager.stopAll(); + }); + + it('trusts one proxy hop on the underlying express app', async () => { + const setSpy = vi.spyOn(express.application, 'set'); + const manager = createMockOAuth2Manager({ port: 0, baseUrl: 'http://127.0.0.1:0' }); + + await manager.register('portal', makeConfig()); + expect(setSpy).toHaveBeenCalledWith('trust proxy', 1); - await expect(manager.register('bad/name', makeConfig())).rejects.toThrow(); - await manager.stopAll(); + await manager.stopAll(); + }); }); }); diff --git a/packages/cellix/server-oauth2-mock-seedwork/src/manager.ts b/packages/cellix/server-oauth2-mock-seedwork/src/manager.ts index f810d1eca..2d06763fb 100644 --- a/packages/cellix/server-oauth2-mock-seedwork/src/manager.ts +++ b/packages/cellix/server-oauth2-mock-seedwork/src/manager.ts @@ -3,7 +3,31 @@ import { buildOidcRouter } from './router.ts'; import type { MockOAuth2Manager, MockOAuth2PortalConfig, MockOAuth2Registration, MockOAuth2ServerHandle } from './types.ts'; import { normalizeBaseUrl, SAFE_NAME_RE } from './utils.ts'; -export function createMockOAuth2Manager(serverConfig: { port: number; host?: string; baseUrl: string }): MockOAuth2Manager { +/** + * Creates a reusable mock OAuth2 manager that can register multiple named portal + * configurations on one Express server. + * + * @param serverConfig - Shared server configuration including `port`, optional `host`, + * externally visible `baseUrl`, and optional `trustProxy`. Set `trustProxy: true` to + * trust a single proxy hop for `X-Forwarded-*` headers, or `trustProxy: false` to disable + * proxy trust entirely. When `trustProxy` is omitted, it defaults to enabled only for + * loopback hosts (`127.0.0.1`, `localhost`, `::1`) inferred from `host` or `baseUrl`; + * otherwise proxy headers are not trusted. + * @returns A manager that lazily starts the server on first registration and can stop all registrations. + * + * @example + * ```ts + * const manager = createMockOAuth2Manager({ + * port: 38200, + * host: '127.0.0.1', + * baseUrl: 'http://127.0.0.1:38200', + * }); + * + * await manager.register('portal', config); + * await manager.stopAll(); + * ``` + */ +export function createMockOAuth2Manager(serverConfig: { port: number; host?: string; baseUrl: string; trustProxy?: boolean }): MockOAuth2Manager { let app: express.Express | null = null; let serverHandle: MockOAuth2ServerHandle | null = null; let startupPromise: Promise | null = null; @@ -18,6 +42,25 @@ export function createMockOAuth2Manager(serverConfig: { port: number; host?: str } if (!app) { app = express(); + // Trust proxy is enabled explicitly (trustProxy: true), or by default for local loopback + // hosts (127.0.0.1, localhost, ::1). An explicit trustProxy: false disables it entirely. + // Trusting X-Forwarded-* headers can be a security and logging concern when running + // outside a trusted proxy, so defaults are conservative. + let shouldTrust = false; + if (serverConfig.trustProxy === true) { + shouldTrust = true; + } else if (serverConfig.trustProxy === false) { + shouldTrust = false; + } else { + // trustProxy is undefined; infer from host being loopback + try { + const host = serverConfig.host ?? new URL(serverConfig.baseUrl).hostname; + if (host === '127.0.0.1' || host === 'localhost' || host === '::1') shouldTrust = true; + } catch { + // Ignore URL parse errors and keep default (no trust) + } + } + if (shouldTrust) app.set('trust proxy', 1); app.disable('x-powered-by'); } const gen = startGeneration; diff --git a/packages/cellix/server-oauth2-mock-seedwork/src/router.test.ts b/packages/cellix/server-oauth2-mock-seedwork/src/router.test.ts new file mode 100644 index 000000000..58384c184 --- /dev/null +++ b/packages/cellix/server-oauth2-mock-seedwork/src/router.test.ts @@ -0,0 +1,622 @@ +import crypto from 'node:crypto'; +import type { Server } from 'node:http'; +import type { AddressInfo } from 'node:net'; +import express from 'express'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { AUTH_CODE_PREFIX, buildOidcRouter, type MockOAuth2PortalConfig, type MockOAuth2User, type MockOAuth2UserStore } from './index.ts'; +import { AUTH_CODE_TTL_MS } from './router.ts'; + +class InMemoryUserStore implements MockOAuth2UserStore { + users: MockOAuth2User[] = []; + persistCalls = 0; + listUsers(): Promise { + return Promise.resolve(this.users); + } + findByUsername(username: string): Promise { + return Promise.resolve(this.users.find((u) => u.username === username)); + } + findBySub(sub: string): Promise { + return Promise.resolve(this.users.find((u) => u.sub === sub)); + } + addUser(user: MockOAuth2User): Promise { + if (this.users.some((u) => u.username === user.username)) { + throw new Error(`Username already exists: ${user.username}`); + } + if (this.users.some((u) => u.sub === user.sub)) { + throw new Error(`Sub already exists: ${user.sub}`); + } + this.users.push(user); + return Promise.resolve(); + } + persist(): Promise { + this.persistCalls += 1; + return Promise.resolve(); + } +} + +function baseUrlFor(port: number) { + return `http://127.0.0.1:${port}`; +} + +function createPassword(label: string) { + return `${label}-${crypto.randomUUID()}`; +} + +async function startServer(port: number, store: MockOAuth2UserStore, getUserProfile: MockOAuth2PortalConfig['getUserProfile'] = () => ({ email: 'portal@example.com' })) { + const app = express(); + app.disable('x-powered-by'); + const srv = app.listen(port); + await new Promise((resolve) => srv.on('listening', () => resolve())); + const boundPort = (srv.address() as AddressInfo).port as number; + const redirect = `${baseUrlFor(boundPort)}/cb`; + const config: MockOAuth2PortalConfig = { + allowedRedirectUris: new Set([redirect]), + allowedRedirectUri: redirect, + redirectUriToAudience: new Map([[redirect, 'test-aud']]), + getUserProfile, + userStore: store, + }; + const issuerBase = `${baseUrlFor(boundPort)}`; + const router = await buildOidcRouter(issuerBase, config); + app.use(router); + return { server: srv, port: boundPort, redirect }; +} + +function decodeJwtPayload(token: string) { + const parts = token.split('.'); + if (parts.length < 2) return null; + const payload = parts[1]; + if (!payload) return null; + const buf = Buffer.from(payload, 'base64url'); + return JSON.parse(buf.toString('utf8')) as Record; +} + +async function getFormNonce(port: number, path: '/login' | '/signup', query?: Record) { + const url = new URL(`http://127.0.0.1:${port}${path}`); + if (query) { + for (const [key, value] of Object.entries(query)) { + url.searchParams.set(key, value); + } + } + const res = await fetch(url); + expect(res.status).toBe(200); + const html = await res.text(); + const match = /name="nonce" value="([^"]+)"/.exec(html); + const nonce = match?.[1]; + expect(nonce).toBeTruthy(); + return { html, nonce: nonce as string }; +} + +describe('buildOidcRouter', () => { + describe('oauth2 mock router flows', () => { + let server: Server; + let port: number; + let redirect: string; + let store: InMemoryUserStore; + + beforeEach(async () => { + store = new InMemoryUserStore(); + const s = await startServer(0, store); + server = s.server; + port = s.port; + redirect = s.redirect; + }); + + afterEach(async () => { + vi.restoreAllMocks(); + await new Promise((resolve) => server.close(() => resolve())); + }); + + it('GET /login stores redirect data server-side and only renders a nonce', async () => { + // Test that user-controlled state parameter is not echoed in HTML (XSS protection) + // Use the valid redirect from allowlist instead of a malicious redirect_uri to test proper validation + const maliciousState = '">'; + const { html } = await getFormNonce(port, '/login', { state: maliciousState }); + expect(html).toContain('name="nonce"'); + expect(html).not.toContain(''); + expect(html).not.toContain('redirect_uri'); + expect(html).not.toContain('state'); + }); + + it('GET /login rejects redirect_uri that is not in allowlist', async () => { + const invalidRedirect = 'https://evil.com/callback'; + const res = await fetch(`http://127.0.0.1:${port}/login?redirect_uri=${encodeURIComponent(invalidRedirect)}`); + expect(res.status).toBe(400); + const json = await res.json(); + expect(json).toHaveProperty('error', 'Invalid redirect_uri'); + }); + + it('POST /signup persists user and rejects duplicate username', async () => { + const signupUrl = `http://127.0.0.1:${port}/signup`; + const alicePassword = createPassword('alice-password'); + const { nonce } = await getFormNonce(port, '/signup', { redirect_uri: redirect, state: 'signup-state' }); + const body = new URLSearchParams({ username: 'alice', password: alicePassword, email: 'alice@example.com', given_name: 'Alice', family_name: 'Smith', nonce }); + const res = await fetch(signupUrl, { method: 'POST', body: body.toString(), headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, redirect: 'manual' }); + expect(res.status).toBe(302); + expect(res.headers.get('location')).toContain('state=signup-state'); + // user persisted + expect(store.users.length).toBe(1); + expect(store.persistCalls).toBe(1); + const u = store.users[0] as MockOAuth2User; + expect(u.username).toBe('alice'); + + // duplicate signup should fail with a conflict for API clients, but render the signup form with an inline error for browser form posts + const { nonce: duplicateNonce } = await getFormNonce(port, '/signup', { redirect_uri: redirect, state: 'signup-state' }); + const duplicateBody = new URLSearchParams({ username: 'alice', password: alicePassword, email: 'alice@example.com', given_name: 'Alice', family_name: 'Smith', nonce: duplicateNonce }); + const res2 = await fetch(signupUrl, { method: 'POST', body: duplicateBody.toString(), headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, redirect: 'manual' }); + expect(res2.status).toBe(200); + expect(store.persistCalls).toBe(1); + const html = await res2.text(); + expect(html).toContain('A user with that username already exists'); + expect(html).toContain('name="nonce"'); + }); + + it('POST /login escapes the submitted username when re-rendering invalid credentials', async () => { + const loginUrl = `http://127.0.0.1:${port}/login`; + const maliciousUsername = '">'; + const escapedUsername = '"><script>alert(1)</script>'; + const { nonce } = await getFormNonce(port, '/login', { redirect_uri: redirect, state: 'escaped-login-state' }); + const body = new URLSearchParams({ username: maliciousUsername, password: createPassword('wrong-password'), nonce }); + const res = await fetch(loginUrl, { method: 'POST', body: body.toString(), headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }); + expect(res.status).toBe(200); + const html = await res.text(); + expect(html).toContain(`value="${escapedUsername}"`); + expect(html).not.toContain(maliciousUsername); + }); + + it('POST /signup escapes user-controlled fields when re-rendering duplicate-user errors', async () => { + const signupUrl = `http://127.0.0.1:${port}/signup`; + const maliciousUsername = '">'; + const maliciousEmail = 'evil"/>@example.com'; + const maliciousGivenName = 'Eve'; + const maliciousFamilyName = "O'Connor"; + store.users.push({ username: maliciousUsername, sub: 'sub-existing', password: createPassword('existing-password') }); + const { nonce } = await getFormNonce(port, '/signup', { redirect_uri: redirect, state: 'escaped-signup-state' }); + const body = new URLSearchParams({ username: maliciousUsername, password: createPassword('new-password'), email: maliciousEmail, given_name: maliciousGivenName, family_name: maliciousFamilyName, nonce }); + const res = await fetch(signupUrl, { method: 'POST', body: body.toString(), headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }); + expect(res.status).toBe(200); + const html = await res.text(); + expect(html).toContain('A user with that username already exists'); + expect(html).toContain('value=""><script>alert(1)</script>"'); + expect(html).toContain('value="evil"/><img src=x onerror=alert(1)>@example.com"'); + expect(html).toContain('value="<b>Eve</b>"'); + expect(html).toContain('value="O'Connor<script>alert(1)</script>"'); + expect(html).not.toContain(maliciousUsername); + expect(html).not.toContain(''); + }); + + it('GET /authorize forwards login query params when a userStore is configured', async () => { + const authorizeUrl = new URL(`http://127.0.0.1:${port}/authorize`); + authorizeUrl.searchParams.set('redirect_uri', redirect); + authorizeUrl.searchParams.set('state', 'authorize-state'); + authorizeUrl.searchParams.set('nonce', 'oidc-nonce'); + authorizeUrl.searchParams.set('code_challenge', 'challenge-value'); + authorizeUrl.searchParams.set('code_challenge_method', 'S256'); + const res = await fetch(authorizeUrl, { redirect: 'manual' }); + expect(res.status).toBe(302); + const location = res.headers.get('location'); + expect(location).toBeTruthy(); + const loginLocation = new URL(location as string); + expect(`${loginLocation.origin}${loginLocation.pathname}`).toBe(`${baseUrlFor(port)}/login`); + expect(loginLocation.searchParams.get('state')).toBe('authorize-state'); + expect(loginLocation.searchParams.get('redirect_uri')).toBe(redirect); + expect(loginLocation.searchParams.get('nonce')).toBe('oidc-nonce'); + expect(loginLocation.searchParams.get('code_challenge')).toBe('challenge-value'); + expect(loginLocation.searchParams.get('code_challenge_method')).toBe('S256'); + }); + + it('POST /login authenticates user and rejects wrong password', async () => { + // ensure user exists + const bobPassword = createPassword('bob-password'); + const wrongPassword = createPassword('bob-password-wrong'); + store.users.push({ username: 'bob', sub: 'sub-bob', password: bobPassword, claims: { email: 'bob@example.com', given_name: 'Bob' } }); + const loginUrl = `http://127.0.0.1:${port}/login`; + const { nonce } = await getFormNonce(port, '/login', { redirect_uri: redirect, state: 'login-state' }); + const good = new URLSearchParams({ username: 'bob', password: bobPassword, nonce }); + const r1 = await fetch(loginUrl, { method: 'POST', body: good.toString(), headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, redirect: 'manual' }); + expect(r1.status).toBe(302); + expect(r1.headers.get('location')).toContain('state=login-state'); + + const { nonce: badNonce } = await getFormNonce(port, '/login', { redirect_uri: redirect, state: 'bad-login-state' }); + const bad = new URLSearchParams({ username: 'bob', password: wrongPassword, nonce: badNonce }); + const r2 = await fetch(loginUrl, { method: 'POST', body: bad.toString(), headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }); + // For form-posts we render a friendly HTML page so the user can retry; expect 200 and an error message + expect(r2.status).toBe(200); + const errHtml = await r2.text(); + expect(errHtml).toContain('Invalid username or password'); + }); + + it('POST /login preserves the OIDC nonce into token claims', async () => { + const davePassword = createPassword('dave-password'); + store.users.push({ username: 'dave', sub: 'sub-dave', password: davePassword, claims: { email: 'dave@example.com' } }); + const loginUrl = `http://127.0.0.1:${port}/login`; + const { nonce } = await getFormNonce(port, '/login', { redirect_uri: redirect, state: 'login-state', nonce: 'login-oidc-nonce' }); + const body = new URLSearchParams({ username: 'dave', password: davePassword, nonce }); + const res = await fetch(loginUrl, { method: 'POST', body: body.toString(), headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, redirect: 'manual' }); + expect(res.status).toBe(302); + const location = res.headers.get('location'); + expect(location).toBeTruthy(); + const code = new URL(location as string).searchParams.get('code'); + expect(code?.startsWith(AUTH_CODE_PREFIX)).toBe(true); + + const tokenRes = await fetch(`http://127.0.0.1:${port}/token`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ grant_type: 'authorization_code', code }), + }); + expect(tokenRes.status).toBe(200); + const tokenJson = (await tokenRes.json()) as { id_token?: string; profile?: { nonce?: string } }; + expect(tokenJson.profile?.nonce).toBe('login-oidc-nonce'); + const idPayload = decodeJwtPayload(tokenJson.id_token as string) as { nonce?: string }; + expect(idPayload.nonce).toBe('login-oidc-nonce'); + }); + + it('POST /login drops expired login sessions after ten minutes', async () => { + const danPassword = createPassword('dan-password'); + store.users.push({ username: 'dan', sub: 'sub-dan', password: danPassword, claims: { email: 'dan@example.com' } }); + const nowSpy = vi.spyOn(Date, 'now'); + nowSpy.mockReturnValue(0); + const loginUrl = `http://127.0.0.1:${port}/login`; + const { nonce } = await getFormNonce(port, '/login', { redirect_uri: redirect, state: 'expired-login-state' }); + nowSpy.mockReturnValue(AUTH_CODE_TTL_MS + 1); + + const body = new URLSearchParams({ username: 'dan', password: danPassword, nonce }); + const res = await fetch(loginUrl, { method: 'POST', body: body.toString(), headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, redirect: 'manual' }); + expect(res.status).toBe(400); + const text = await res.text(); + expect(text).toContain('Session expired'); + }); + + it('POST /token rejects expired auth codes with invalid_grant', async () => { + const erinPassword = createPassword('erin-password'); + store.users.push({ username: 'erin', sub: 'sub-erin', password: erinPassword, claims: { email: 'erin@example.com', given_name: 'Erin' } }); + const nowSpy = vi.spyOn(Date, 'now'); + nowSpy.mockReturnValue(0); + const loginUrl = `http://127.0.0.1:${port}/login`; + const { nonce } = await getFormNonce(port, '/login', { redirect_uri: redirect, state: 'expired-code-state' }); + const loginBody = new URLSearchParams({ username: 'erin', password: erinPassword, nonce }); + const loginRes = await fetch(loginUrl, { method: 'POST', body: loginBody.toString(), headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, redirect: 'manual' }); + expect(loginRes.status).toBe(302); + const location = loginRes.headers.get('location') ?? ''; + const code = new URL(location).searchParams.get('code'); + expect(code?.startsWith(AUTH_CODE_PREFIX)).toBe(true); + + nowSpy.mockReturnValue(AUTH_CODE_TTL_MS + 1); + const tokenRes = await fetch(`http://127.0.0.1:${port}/token`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ grant_type: 'authorization_code', code }), + }); + expect(tokenRes.status).toBe(400); + const errorJson = (await tokenRes.json()) as { error: string; error_description: string }; + expect(errorJson.error).toBe('invalid_grant'); + expect(errorJson.error_description).toBe('invalid or expired authorization code'); + }); + + it('GET /signup preserves the OIDC nonce for direct signup flows', async () => { + const signupUrl = `http://127.0.0.1:${port}/signup`; + const frankPassword = createPassword('frank-password'); + const { nonce } = await getFormNonce(port, '/signup', { + redirect_uri: redirect, + state: 'signup-nonce-state', + nonce: 'signup-oidc-nonce', + }); + const body = new URLSearchParams({ + username: 'frank', + password: frankPassword, + email: 'frank@example.com', + given_name: 'Frank', + family_name: 'Taylor', + nonce, + }); + const res = await fetch(signupUrl, { method: 'POST', body: body.toString(), headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, redirect: 'manual' }); + expect(res.status).toBe(302); + const location = res.headers.get('location'); + expect(location).toBeTruthy(); + const redirectUrl = new URL(location as string); + expect(redirectUrl.searchParams.get('state')).toBe('signup-nonce-state'); + const code = redirectUrl.searchParams.get('code'); + expect(code?.startsWith(AUTH_CODE_PREFIX)).toBe(true); + + const tokenRes = await fetch(`http://127.0.0.1:${port}/token`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ grant_type: 'authorization_code', code }), + }); + expect(tokenRes.status).toBe(200); + const tokenJson = (await tokenRes.json()) as { id_token?: string; profile?: { nonce?: string } }; + expect(tokenJson.profile?.nonce).toBe('signup-oidc-nonce'); + const idPayload = decodeJwtPayload(tokenJson.id_token as string) as { nonce?: string }; + expect(idPayload.nonce).toBe('signup-oidc-nonce'); + }); + + it('/token and /userinfo include full user claims and never include password', async () => { + // Signup a new user to obtain an auth code mapped in authCodeStore + const signupUrl = `http://127.0.0.1:${port}/signup`; + const carolPassword = createPassword('carol-password'); + const { nonce } = await getFormNonce(port, '/signup', { redirect_uri: redirect, state: 'token-state' }); + const body = new URLSearchParams({ username: 'carol', password: carolPassword, email: 'carol@example.com', given_name: 'Carol', family_name: 'Jones', nonce }); + const res = await fetch(signupUrl, { method: 'POST', body: body.toString(), headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, redirect: 'manual' }); + expect(res.status).toBe(302); + const loc = res.headers.get('location') as string; + const u = new URL(loc); + const code = u.searchParams.get('code') as string; + expect(u.searchParams.get('state')).toBe('token-state'); + + // exchange code for token + const tokenRes = await fetch(`http://127.0.0.1:${port}/token`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ grant_type: 'authorization_code', code }) }); + expect(tokenRes.status).toBe(200); + interface TokenResponse { + id_token?: string; + access_token?: string; + [k: string]: unknown; + } + interface ClaimsPayload { + email?: string; + given_name?: string; + family_name?: string; + sub?: string; + password?: string; + [k: string]: unknown; + } + const tokenJson = (await tokenRes.json()) as TokenResponse; + expect(tokenJson).toHaveProperty('id_token'); + expect(tokenJson).toHaveProperty('access_token'); + + const idPayload = decodeJwtPayload(tokenJson.id_token as string) as ClaimsPayload; + const accessPayload = decodeJwtPayload(tokenJson.access_token as string) as ClaimsPayload; + // Should contain claims from the stored user + expect(idPayload.email).toBe('carol@example.com'); + expect(idPayload.given_name).toBe('Carol'); + expect(idPayload.family_name).toBe('Jones'); + // password must not be present + expect(Object.hasOwn(idPayload, 'password')).toBe(false); + expect(Object.hasOwn(accessPayload, 'password')).toBe(false); + + // userinfo + const infoRes = await fetch(`http://127.0.0.1:${port}/userinfo`, { headers: { Authorization: `Bearer ${tokenJson.access_token}` } }); + expect(infoRes.status).toBe(200); + const info = (await infoRes.json()) as ClaimsPayload; + expect(info.email).toBe('carol@example.com'); + expect(info.given_name).toBe('Carol'); + expect(info.family_name).toBe('Jones'); + expect(Object.hasOwn(info, 'password')).toBe(false); + }); + + it('should allow a second user to log in after the first user logs out', async () => { + // create two users + const passA = createPassword('userA-password'); + const passB = createPassword('userB-password'); + store.users.push({ username: 'userA', sub: 'sub-A', password: passA, claims: { email: 'a@example.com' } }); + store.users.push({ username: 'userB', sub: 'sub-B', password: passB, claims: { email: 'b@example.com' } }); + + // First user A login flow + const authA = new URL(`http://127.0.0.1:${port}/authorize`); + authA.searchParams.set('redirect_uri', redirect); + authA.searchParams.set('state', 'state-A'); + const rA = await fetch(authA, { redirect: 'manual' }); + expect(rA.status).toBe(302); + // fetch login page to obtain nonce + const { nonce: nonceA } = await getFormNonce(port, '/login', { redirect_uri: redirect, state: 'state-A' }); + const loginResA = await fetch(`http://127.0.0.1:${port}/login`, { + method: 'POST', + body: new URLSearchParams({ username: 'userA', password: passA, nonce: nonceA }).toString(), + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + redirect: 'manual', + }); + expect(loginResA.status).toBe(302); + const locA = loginResA.headers.get('location') as string; + const codeA = new URL(locA).searchParams.get('code'); + expect(codeA?.startsWith(AUTH_CODE_PREFIX)).toBe(true); + expect(new URL(locA).searchParams.get('state')).toBe('state-A'); + + // Exchange code for token for user A + const tokenResA = await fetch(`http://127.0.0.1:${port}/token`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ grant_type: 'authorization_code', code: codeA }) }); + expect(tokenResA.status).toBe(200); + const tokenJsonA = (await tokenResA.json()) as { id_token?: string; profile?: { sub?: string } }; + expect(tokenJsonA.profile?.sub).toBe('sub-A'); + + // Simulate logout (no server-side state required for this mock) + const logoutRes = await fetch(`http://127.0.0.1:${port}/logout?post_logout_redirect_uri=${encodeURIComponent(redirect)}`, { redirect: 'manual' }); + expect(logoutRes.status).toBe(302); + + // Second user B login flow + const authB = new URL(`http://127.0.0.1:${port}/authorize`); + authB.searchParams.set('redirect_uri', redirect); + authB.searchParams.set('state', 'state-B'); + const rB = await fetch(authB, { redirect: 'manual' }); + expect(rB.status).toBe(302); + const { nonce: nonceB } = await getFormNonce(port, '/login', { redirect_uri: redirect, state: 'state-B' }); + const loginResB = await fetch(`http://127.0.0.1:${port}/login`, { + method: 'POST', + body: new URLSearchParams({ username: 'userB', password: passB, nonce: nonceB }).toString(), + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + redirect: 'manual', + }); + expect(loginResB.status).toBe(302); + const locB = loginResB.headers.get('location') as string; + const codeB = new URL(locB).searchParams.get('code'); + expect(codeB?.startsWith(AUTH_CODE_PREFIX)).toBe(true); + expect(new URL(locB).searchParams.get('state')).toBe('state-B'); + + // Exchange code for token for user B + const tokenResB = await fetch(`http://127.0.0.1:${port}/token`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ grant_type: 'authorization_code', code: codeB }) }); + expect(tokenResB.status).toBe(200); + const tokenJsonB = (await tokenResB.json()) as { id_token?: string; profile?: { sub?: string } }; + expect(tokenJsonB.profile?.sub).toBe('sub-B'); + }); + it('POST /login uses user.sub when present at top-level', async () => { + const pass = createPassword('u-password'); + store.users.push({ username: 'topsub', sub: 'sub-top', password: pass, claims: { email: 'top@example.com' } }); + const loginUrl = `http://127.0.0.1:${port}/login`; + const { nonce } = await getFormNonce(port, '/login', { redirect_uri: redirect, state: 'sub-top-state' }); + const body = new URLSearchParams({ username: 'topsub', password: pass, nonce }); + const res = await fetch(loginUrl, { method: 'POST', body: body.toString(), headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, redirect: 'manual' }); + expect(res.status).toBe(302); + const location = res.headers.get('location') as string; + const code = new URL(location).searchParams.get('code') as string; + const tokenRes = await fetch(`http://127.0.0.1:${port}/token`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ grant_type: 'authorization_code', code }) }); + expect(tokenRes.status).toBe(200); + const tokenJson = (await tokenRes.json()) as { id_token?: string }; + const idPayload = decodeJwtPayload(tokenJson.id_token as string) as { sub?: string }; + expect(idPayload.sub).toBe('sub-top'); + }); + + it('POST /login uses user.claims.sub when provided (merged into user.sub by file store)', async () => { + const pass = createPassword('v-password'); + // In real file-backed user store claims.sub is promoted to top-level sub; tests simulate that behavior by setting user.sub accordingly + store.users.push({ username: 'claimsub', sub: 'sub-claim', password: pass, claims: { email: 'claim@example.com', sub: 'sub-claim' } }); + const loginUrl = `http://127.0.0.1:${port}/login`; + const { nonce } = await getFormNonce(port, '/login', { redirect_uri: redirect, state: 'sub-claim-state' }); + const body = new URLSearchParams({ username: 'claimsub', password: pass, nonce }); + const res = await fetch(loginUrl, { method: 'POST', body: body.toString(), headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, redirect: 'manual' }); + expect(res.status).toBe(302); + const location = res.headers.get('location') as string; + const code = new URL(location).searchParams.get('code') as string; + const tokenRes = await fetch(`http://127.0.0.1:${port}/token`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ grant_type: 'authorization_code', code }) }); + expect(tokenRes.status).toBe(200); + const tokenJson = (await tokenRes.json()) as { id_token?: string }; + const idPayload = decodeJwtPayload(tokenJson.id_token as string) as { sub?: string }; + expect(idPayload.sub).toBe('sub-claim'); + }); + + it('POST /token prefers request tid first, then user claims tid, then portal tid', async () => { + const pass = createPassword('tid-password'); + const portalTid = 'portal-tenant-id'; + await new Promise((resolve) => server.close(() => resolve())); + store.users.push({ + username: 'tenant-user', + sub: 'sub-tenant-user', + password: pass, + claims: { email: 'tenant@example.com', tid: 'user-tenant-id' }, + }); + const restarted = await startServer(0, store, () => ({ email: 'portal@example.com', tid: portalTid })); + server = restarted.server; + port = restarted.port; + redirect = restarted.redirect; + + const issueCode = async (state: string) => { + const loginUrl = `http://127.0.0.1:${port}/login`; + const { nonce } = await getFormNonce(port, '/login', { redirect_uri: redirect, state }); + const body = new URLSearchParams({ username: 'tenant-user', password: pass, nonce }); + const res = await fetch(loginUrl, { method: 'POST', body: body.toString(), headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, redirect: 'manual' }); + expect(res.status).toBe(302); + return new URL(res.headers.get('location') as string).searchParams.get('code') as string; + }; + + const code = await issueCode('tid-state'); + const tokenRes = await fetch(`http://127.0.0.1:${port}/token`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ grant_type: 'authorization_code', code }) }); + expect(tokenRes.status).toBe(200); + const tokenJson = (await tokenRes.json()) as { id_token?: string; profile?: { tid?: string } }; + const idPayload = decodeJwtPayload(tokenJson.id_token as string) as { tid?: string }; + expect(tokenJson.profile?.tid).toBe('user-tenant-id'); + expect(idPayload.tid).toBe('user-tenant-id'); + + const overrideCode = await issueCode('tid-state-override'); + const overrideTokenRes = await fetch(`http://127.0.0.1:${port}/token`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ grant_type: 'authorization_code', code: overrideCode, tid: 'request-tenant-id' }), + }); + expect(overrideTokenRes.status).toBe(200); + const overrideTokenJson = (await overrideTokenRes.json()) as { id_token?: string; profile?: { tid?: string } }; + const overrideIdPayload = decodeJwtPayload(overrideTokenJson.id_token as string) as { tid?: string }; + expect(overrideTokenJson.profile?.tid).toBe('request-tenant-id'); + expect(overrideIdPayload.tid).toBe('request-tenant-id'); + }); + }); + + describe('oauth2 mock router rate limiting', () => { + async function stopServer(server: Server) { + await new Promise((resolve) => server.close(() => resolve())); + } + + it('GET /login enforces the form rate limiter', async () => { + const { server, port } = await startServer(0, new InMemoryUserStore()); + try { + for (let index = 0; index < 30; index += 1) { + const response = await fetch(`http://127.0.0.1:${port}/login`); + expect(response.status).toBe(200); + } + + const limitedResponse = await fetch(`http://127.0.0.1:${port}/login`); + expect(limitedResponse.status).toBe(429); + expect(limitedResponse.headers.get('ratelimit-remaining')).toBe('0'); + } finally { + await stopServer(server); + } + }); + + it('GET /signup enforces the form rate limiter', async () => { + const { server, port } = await startServer(0, new InMemoryUserStore()); + try { + for (let index = 0; index < 30; index += 1) { + const response = await fetch(`http://127.0.0.1:${port}/signup`); + expect(response.status).toBe(200); + } + + const limitedResponse = await fetch(`http://127.0.0.1:${port}/signup`); + expect(limitedResponse.status).toBe(429); + expect(limitedResponse.headers.get('ratelimit-remaining')).toBe('0'); + } finally { + await stopServer(server); + } + }); + + it('POST /login enforces the credential rate limiter', async () => { + const store = new InMemoryUserStore(); + const wrongPassword = createPassword('wrong-password'); + store.users.push({ username: 'rate-limited-login', sub: 'sub-rate-limited-login', password: createPassword('correct-login-password'), claims: {} }); + const { server, port, redirect } = await startServer(0, store); + try { + const { nonce } = await getFormNonce(port, '/login', { redirect_uri: redirect, state: 'login-rate-limit-state' }); + for (let index = 0; index < 10; index += 1) { + const response = await fetch(`http://127.0.0.1:${port}/login`, { + method: 'POST', + body: new URLSearchParams({ username: 'rate-limited-login', password: wrongPassword, nonce }).toString(), + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + }); + expect(response.status).toBe(200); + } + + const limitedResponse = await fetch(`http://127.0.0.1:${port}/login`, { + method: 'POST', + body: new URLSearchParams({ username: 'rate-limited-login', password: wrongPassword, nonce }).toString(), + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + }); + expect(limitedResponse.status).toBe(429); + expect(await limitedResponse.json()).toEqual({ error: 'Too many attempts, please try again later.' }); + } finally { + await stopServer(server); + } + }); + + it('POST /signup enforces the credential rate limiter', async () => { + const store = new InMemoryUserStore(); + const duplicatePassword = createPassword('duplicate-password'); + store.users.push({ username: 'existing-user', sub: 'sub-existing-user', password: createPassword('existing-user-password'), claims: {} }); + const { server, port, redirect } = await startServer(0, store); + try { + const { nonce } = await getFormNonce(port, '/signup', { redirect_uri: redirect, state: 'signup-rate-limit-state' }); + for (let index = 0; index < 10; index += 1) { + const response = await fetch(`http://127.0.0.1:${port}/signup`, { + method: 'POST', + body: new URLSearchParams({ username: 'existing-user', password: duplicatePassword, nonce }).toString(), + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + }); + expect(response.status).toBe(200); + } + + const limitedResponse = await fetch(`http://127.0.0.1:${port}/signup`, { + method: 'POST', + body: new URLSearchParams({ username: 'existing-user', password: duplicatePassword, nonce }).toString(), + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + }); + expect(limitedResponse.status).toBe(429); + expect(await limitedResponse.json()).toEqual({ error: 'Too many attempts, please try again later.' }); + } finally { + await stopServer(server); + } + }); + }); +}); diff --git a/packages/cellix/server-oauth2-mock-seedwork/src/router.ts b/packages/cellix/server-oauth2-mock-seedwork/src/router.ts index c13ce40c1..be411d876 100644 --- a/packages/cellix/server-oauth2-mock-seedwork/src/router.ts +++ b/packages/cellix/server-oauth2-mock-seedwork/src/router.ts @@ -1,10 +1,14 @@ import crypto from 'node:crypto'; import express from 'express'; -import rateLimit from 'express-rate-limit'; +import { rateLimit } from 'express-rate-limit'; import { exportJWK, generateKeyPair, errors as joseErrors, jwtVerify } from 'jose'; +import { buildEffectiveProfile, buildRedirectWithCode, extractClaimsFromPayload, normalizeUserInfo } from './helpers.ts'; import { buildTokenResponse } from './jwt.ts'; -import type { MockOAuth2PortalConfig } from './types.ts'; -import { normalizeOrigin, normalizeUrl } from './utils.ts'; +import { debugLog } from './logger.ts'; +import { createLoginHandlers } from './login-handlers.ts'; +import { createTtlStore } from './ttl-store.ts'; +import type { MockOAuth2PortalConfig, MockOAuth2UserStore } from './types.ts'; +import { AUTH_CODE_PREFIX, normalizeOrigin, normalizeUrl } from './utils.ts'; interface TokenProfile { aud: string; @@ -17,6 +21,26 @@ interface TokenProfile { [key: string]: unknown; } +export const AUTH_CODE_TTL_MS = 10 * 60 * 1000; + +/** + * Builds an Express router that exposes the mock OIDC discovery, authorize, login, + * signup, token, userinfo, and logout endpoints for one issuer. + * + * @param issuerBaseUrl - Fully qualified issuer base URL for the mounted router. + * @param config - Portal configuration, including redirects, claims, and optional async user store. + * @returns A promise that resolves to a configured Express router. + * + * @example + * ```ts + * const router = await buildOidcRouter('http://127.0.0.1:38200/portal', { + * allowedRedirectUris: new Set(['http://localhost:3000/callback']), + * allowedRedirectUri: 'http://localhost:3000/callback', + * redirectUriToAudience: new Map([['http://localhost:3000/callback', 'mock-client']]), + * getUserProfile: () => ({ email: 'test@example.com' }), + * }); + * ``` + */ export async function buildOidcRouter(issuerBaseUrl: string, config: MockOAuth2PortalConfig): Promise { const router = express.Router(); @@ -27,7 +51,12 @@ export async function buildOidcRouter(issuerBaseUrl: string, config: MockOAuth2P publicJwk.kid = publicJwk.kid || 'mock-key'; const cachedUserProfile = config.getUserProfile(); - const persistedSub = cachedUserProfile.sub ?? crypto.randomUUID(); + // Auth code store: maps one-time auth codes to selected sub, redirectUri, and OIDC nonce + const authCodeStore = createTtlStore<{ sub?: string; redirectUri: string; nonce?: string }>(AUTH_CODE_TTL_MS); + // Maps short-lived nonces to redirect and authorization params so user-controlled values never appear in HTML + const loginSessionStore = createTtlStore<{ redirectUri: string; state: string; nonce?: string }>(AUTH_CODE_TTL_MS); + // For prefilled portal profile when no userStore, we may use portal sub as default when issuing codes without an explicit user selection. + const portalPrefilledSub = config.userStore ? undefined : (cachedUserProfile.sub ?? crypto.randomUUID()); const normalizedAllowedRedirectUris = new Set([...config.allowedRedirectUris].map((u) => normalizeUrl(u))); @@ -83,7 +112,7 @@ export async function buildOidcRouter(issuerBaseUrl: string, config: MockOAuth2P } const allowMethods = 'GET,POST,OPTIONS'; - const requestHeaders = (req.headers['access-control-request-headers'] ?? '') as string; + const requestHeaders = (req.get('access-control-request-headers') ?? '') as string; const allowHeaders = requestHeaders && requestHeaders.length > 0 ? requestHeaders : 'Content-Type,Authorization'; if (req.method === 'OPTIONS') { @@ -125,39 +154,68 @@ export async function buildOidcRouter(issuerBaseUrl: string, config: MockOAuth2P const defaultAud = normalizedRedirectUriToAudience.get(primaryRedirectUri) ?? 'mock-client'; let aud = defaultAud; - - if (code.startsWith('mock-auth-code-')) { + let resolvedSubFromCode: string | undefined; + // check one-time mapping first + const mapping = authCodeStore.get(code); + const resolvedNonce = mapping?.nonce; + if (mapping) { try { - const base64Part = code.replace('mock-auth-code-', ''); - const decodedRedirectUri = Buffer.from(base64Part, 'base64').toString('utf-8'); - const normalizedDecoded = normalizeUrl(decodedRedirectUri); + const normalizedDecoded = normalizeUrl(mapping.redirectUri); if (normalizedAllowedRedirectUris.has(normalizedDecoded)) { aud = normalizedRedirectUriToAudience.get(normalizedDecoded) ?? aud; } - } catch (error) { - console.error('Failed to decode redirect_uri from code:', error); + } catch (_err) { + // ignore } + // consume one-time code + authCodeStore.delete(code); + resolvedSubFromCode = mapping.sub; + } else if (code.startsWith(AUTH_CODE_PREFIX)) { + // Code has expected prefix but no mapping (expired or invalid) + res.status(400).json({ error: 'invalid_grant', error_description: 'invalid or expired authorization code' }); + return; + } else { + // Code does not have expected prefix, reject + res.status(400).json({ error: 'invalid_grant', error_description: 'invalid or expired authorization code' }); + return; } - const userProfile = config.getUserProfile(); - const { sub: upSub, email: upEmail, given_name: upGiven, family_name: upFamily, tid: upTid, ...extra } = userProfile; - let resolvedTid: string; - if (typeof tid === 'string') { - resolvedTid = tid; - } else if (typeof upTid === 'string') { - resolvedTid = upTid; - } else { - resolvedTid = 'test-tenant-id'; + const portalProfile = config.getUserProfile(); + const { sub: upSub, tid: upTid } = portalProfile; + + // Determine final subject (prefer the code-mapped sub, then portal-profile requested sub) + const finalSub = resolvedSubFromCode ?? (typeof upSub === 'string' ? upSub : (portalPrefilledSub ?? crypto.randomUUID())); + + let userClaims: (Record & { tid?: string }) | undefined; + if (config.userStore) { + const store = config.userStore as MockOAuth2UserStore; + try { + if (typeof finalSub === 'string') { + const user = await store.findBySub(finalSub); + if (user) userClaims = user.claims; + } + } catch (err) { + // User store lookup failed (e.g., corrupt data, duplicate entries). Return 500 with OAuth2-compliant error. + debugLog('[server-oauth2-mock] /token user store lookup failed', { error: err instanceof Error ? err.message : String(err), finalSub }); + res.status(500).json({ error: 'server_error', error_description: `Failed to resolve user claims for sub=${finalSub}` }); + return; + } } + + const effectiveProfile = buildEffectiveProfile(portalProfile, userClaims, finalSub); + // Prefer explicit request override (tid param), then tid from merged effective profile (portal + user claims), then portal default + const _ep = effectiveProfile as Record; + // biome-ignore lint/complexity/useLiteralKeys: Required for TypeScript index signature access + const mergedTid = typeof _ep['tid'] === 'string' ? (_ep['tid'] as string) : undefined; + const resolvedTid = typeof tid === 'string' ? tid : (mergedTid ?? (typeof upTid === 'string' ? upTid : 'test-tenant-id')); + const profile: TokenProfile = { - ...extra, + ...effectiveProfile, + sub: finalSub, aud, - sub: typeof upSub === 'string' ? upSub : persistedSub, iss: issuerBaseUrl, - ...(typeof upEmail === 'string' ? { email: upEmail } : {}), - ...(typeof upGiven === 'string' ? { given_name: upGiven } : {}), - ...(typeof upFamily === 'string' ? { family_name: upFamily } : {}), tid: resolvedTid, + ...(resolvedNonce !== undefined ? { nonce: resolvedNonce } : {}), }; const tokenResponse = await buildTokenResponse(profile, privateKey, publicJwk, issuerBaseUrl); res.json(tokenResponse); @@ -181,7 +239,7 @@ export async function buildOidcRouter(issuerBaseUrl: string, config: MockOAuth2P }); router.get('/authorize', (req, res) => { - const { state, redirect_uri } = req.query as { state?: string; redirect_uri?: string }; + const { state, redirect_uri, nonce } = req.query as { state?: string; redirect_uri?: string; nonce?: string }; const requestedRedirectUri = redirect_uri ?? primaryRedirectUri; const normalizedRequestedRedirectUri = normalizeUrl(requestedRedirectUri); const isAllowed = normalizedAllowedRedirectUris.has(normalizedRequestedRedirectUri); @@ -190,18 +248,59 @@ export async function buildOidcRouter(issuerBaseUrl: string, config: MockOAuth2P return; } + // Structured debug logging + debugLog('[server-oauth2-mock] GET /authorize', { + portal: issuerBaseUrl, + state: typeof state === 'string' ? state : undefined, + redirectUri: requestedRedirectUri, + requestNonce: typeof nonce === 'string' ? nonce : undefined, + }); + + // If userStore exists, redirect to login to choose/authorize a user. + if (config.userStore) { + const forward: Record = typeof nonce === 'string' ? { nonce } : {}; + // Whitelist known OIDC and PKCE params and apply size limits to prevent oversized redirects + const allowedParams = new Set(['state', 'redirect_uri', 'response_type', 'client_id', 'scope', 'response_mode', 'code_challenge', 'code_challenge_method']); + for (const [key, value] of Object.entries(req.query)) { + if (!allowedParams.has(key) || typeof value !== 'string') continue; + // Apply 2048 limit for state param, reasonable defaults for others + if (key === 'state' && value.length > 2048) continue; + if (value.length > 4096) continue; // Prevent oversized query strings + forward[key] = value; + } + const q = new URLSearchParams(forward).toString(); + res.setHeader('Location', `${issuerBaseUrl}/login${q ? `?${q}` : ''}`); + res.status(302).end(); + return; + } + try { - const code = `mock-auth-code-${Buffer.from(normalizedRequestedRedirectUri).toString('base64')}`; - const redirectUrl = new URL(requestedRedirectUri); - redirectUrl.searchParams.set('code', code); - if (typeof state === 'string' && state.length <= 2048) redirectUrl.searchParams.set('state', state); - res.setHeader('Location', redirectUrl.toString()); + const code = `${AUTH_CODE_PREFIX}${crypto.randomUUID()}`; + { + const entry: { redirectUri: string; sub?: string } = { redirectUri: normalizedRequestedRedirectUri }; + if (typeof portalPrefilledSub === 'string') entry.sub = portalPrefilledSub; + authCodeStore.set(code, entry); + } + const location = buildRedirectWithCode(requestedRedirectUri, code, typeof state === 'string' ? state : undefined); + res.setHeader('Location', location); res.status(302).end(); } catch { res.status(400).send('Invalid redirect_uri format'); } }); + createLoginHandlers({ + config, + issuerBaseUrl, + primaryRedirectUri, + normalizedAllowedRedirectUris, + loginSessionStore, + authCodeStore, + normalizeUrl, + buildRedirectWithCode, + logger: { debug: debugLog }, + }).registerRoutes(router); + const userinfoRateLimiter = rateLimit({ windowMs: 15 * 60 * 1000, max: 100, message: 'Too many /userinfo requests, please try again later.' }); router.get('/userinfo', userinfoRateLimiter as unknown as Parameters[1], async (req, res) => { @@ -230,12 +329,33 @@ export async function buildOidcRouter(issuerBaseUrl: string, config: MockOAuth2P res.status(401).json({ error: 'invalid_token', error_description: 'missing_aud_claim' }); return; } - const { email: emailProp, given_name: givenNameProp, family_name: familyNameProp } = payload as Record; - const email = typeof emailProp === 'string' ? emailProp : undefined; - const givenName = typeof givenNameProp === 'string' ? givenNameProp : undefined; - const familyName = typeof familyNameProp === 'string' ? familyNameProp : undefined; - const username = email?.includes('@') ? email.split('@')[0] : payload.sub; - res.json({ sub: payload.sub, email, given_name: givenName, family_name: familyName, name: givenName && familyName ? `${givenName} ${familyName}` : (givenName ?? familyName ?? username), username }); + const sub = typeof payload.sub === 'string' ? payload.sub : undefined; + if (!sub) { + res.status(401).json({ error: 'invalid_token', error_description: 'missing_sub_claim' }); + return; + } + + // Resolve full user claims from userStore when available; otherwise fallback to payload/profile fusion + let effectiveProfile: Record = {}; + const portalProfile = config.getUserProfile(); + if (config.userStore) { + try { + const store = config.userStore as MockOAuth2UserStore; + const user = await store.findBySub(sub); + if (user) { + effectiveProfile = buildEffectiveProfile(portalProfile, user.claims, user.sub); + } else { + effectiveProfile = buildEffectiveProfile(portalProfile, extractClaimsFromPayload(payload as Record), sub); + } + } catch (_err) { + effectiveProfile = buildEffectiveProfile(portalProfile, extractClaimsFromPayload(payload as Record), sub); + } + } else { + effectiveProfile = buildEffectiveProfile(portalProfile, extractClaimsFromPayload(payload as Record), sub); + } + + const normalized = normalizeUserInfo(effectiveProfile); + res.json(normalized); } catch (error: unknown) { if (error instanceof joseErrors.JWTExpired) { res.status(401).json({ error: 'invalid_token', error_description: 'token_expired' }); @@ -247,6 +367,8 @@ export async function buildOidcRouter(issuerBaseUrl: string, config: MockOAuth2P router.get('/logout', (req, res) => { const { post_logout_redirect_uri, state } = req.query as { post_logout_redirect_uri?: string; state?: string }; + // Debug + debugLog('[server-oauth2-mock] GET /logout', { portal: issuerBaseUrl }); if (!post_logout_redirect_uri) { res.status(204).end(); return; diff --git a/packages/cellix/server-oauth2-mock-seedwork/src/server.ts b/packages/cellix/server-oauth2-mock-seedwork/src/server.ts index 93426872d..6ccc3a749 100644 --- a/packages/cellix/server-oauth2-mock-seedwork/src/server.ts +++ b/packages/cellix/server-oauth2-mock-seedwork/src/server.ts @@ -2,6 +2,26 @@ import express from 'express'; import { buildOidcRouter } from './router.ts'; import type { MockOAuth2PortalConfig, MockOAuth2ServerConfig, MockOAuth2ServerHandle } from './types.ts'; +/** + * Starts a single mock OAuth2/OIDC server instance for one portal configuration. + * + * @param config - Server host, port, issuer base URL, redirect settings, and optional user store. + * @returns A promise that resolves to the running server handle and async disposer. + * + * @example + * ```ts + * const handle = await startMockOAuth2Server({ + * port: 38204, + * baseUrl: 'http://localhost:38204', + * allowedRedirectUris: new Set(['http://localhost:3000/callback']), + * allowedRedirectUri: 'http://localhost:3000/callback', + * redirectUriToAudience: new Map([['http://localhost:3000/callback', 'mock-client']]), + * getUserProfile: () => ({ email: 'test@example.com' }), + * }); + * + * await handle.disposer.stop(); + * ``` + */ export async function startMockOAuth2Server(config: MockOAuth2ServerConfig): Promise { const app = express(); app.disable('x-powered-by'); diff --git a/packages/cellix/server-oauth2-mock-seedwork/src/ttl-store.test.ts b/packages/cellix/server-oauth2-mock-seedwork/src/ttl-store.test.ts new file mode 100644 index 000000000..a35f4758a --- /dev/null +++ b/packages/cellix/server-oauth2-mock-seedwork/src/ttl-store.test.ts @@ -0,0 +1,64 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { createTtlStore } from './ttl-store.ts'; + +describe('createTtlStore', () => { + beforeEach(() => { + vi.useRealTimers(); + }); + + afterEach(() => { + vi.useRealTimers(); + }); + + it('get returns undefined for a missing key', () => { + const store = createTtlStore(1000); + + expect(store.get('missing')).toBeUndefined(); + }); + + it('set then get returns the stored value', () => { + const store = createTtlStore(1000); + + store.set('answer', 42); + + expect(store.get('answer')).toBe(42); + }); + + it('has returns false for a missing key and true after set', () => { + const store = createTtlStore(1000); + + expect(store.has('answer')).toBe(false); + + store.set('answer', 42); + + expect(store.has('answer')).toBe(true); + }); + + it('delete removes the key', () => { + const store = createTtlStore(1000); + + store.set('answer', 42); + store.delete('answer'); + + expect(store.get('answer')).toBeUndefined(); + expect(store.has('answer')).toBe(false); + }); + + it('expires entries after the configured ttl', () => { + vi.useFakeTimers(); + const store = createTtlStore(1000); + + store.set('answer', 42); + vi.advanceTimersByTime(1001); + + expect(store.get('answer')).toBeUndefined(); + }); + + it('is safe to destructure', () => { + const { get, set } = createTtlStore(1000); + + set('k', 42); + + expect(get('k')).toBe(42); + }); +}); diff --git a/packages/cellix/server-oauth2-mock-seedwork/src/ttl-store.ts b/packages/cellix/server-oauth2-mock-seedwork/src/ttl-store.ts new file mode 100644 index 000000000..7049b07d8 --- /dev/null +++ b/packages/cellix/server-oauth2-mock-seedwork/src/ttl-store.ts @@ -0,0 +1,52 @@ +interface TimedEntry { + value: T; + expiresAt: number; +} + +/** Creates a Map-backed TTL store returning closures with periodic cleanup. */ +export function createTtlStore(ttlMs: number) { + const store = new Map>(); + + const get = (key: string): T | undefined => { + const entry = store.get(key); + if (!entry) return undefined; + if (Date.now() > entry.expiresAt) { + store.delete(key); + return undefined; + } + return entry.value; + }; + + const set = (key: string, value: T): void => { + store.set(key, { value, expiresAt: Date.now() + ttlMs }); + }; + + const del = (key: string): void => { + store.delete(key); + }; + + const has = (key: string): boolean => get(key) !== undefined; + + // Sweep expired entries periodically to prevent unbounded memory growth on abandoned keys + const sweepInterval = setInterval( + () => { + const now = Date.now(); + for (const [key, entry] of store.entries()) { + if (now > entry.expiresAt) { + store.delete(key); + } + } + }, + Math.max(ttlMs, 5000), + ); // Sweep at least every 5 seconds + + // Call unref() so the sweep timer doesn't block the Node.js event loop from exiting + // Tests and server shutdown can now complete without waiting for this timer + if (sweepInterval.unref) { + sweepInterval.unref(); + } + + const stop = (): void => clearInterval(sweepInterval); + + return { get, set, delete: del, has, stop }; +} diff --git a/packages/cellix/server-oauth2-mock-seedwork/src/types.ts b/packages/cellix/server-oauth2-mock-seedwork/src/types.ts index 792c04316..a50ae5488 100644 --- a/packages/cellix/server-oauth2-mock-seedwork/src/types.ts +++ b/packages/cellix/server-oauth2-mock-seedwork/src/types.ts @@ -9,11 +9,85 @@ export interface MockOAuth2UserProfile { [claim: string]: unknown; } +export interface MockOAuth2User { + /** Local username (login handle) */ + username: string; + /** Stable subject identifier used for token issuance */ + sub: string; + /** Plaintext password for the mock server only (never emitted) */ + password?: string; + /** Arbitrary claims associated with this user (email, given_name, etc) */ + claims?: Record; +} + +/** + * Async user lookup and persistence contract used by the interactive login, signup, + * token, and userinfo flows. + * + * Implementations may read from files, databases, or in-memory fixtures, but callers + * should always `await` these methods on the request path. + * + * @example + * ```ts + * const store: MockOAuth2UserStore = { + * async listUsers() { + * return []; + * }, + * async findByUsername(username) { + * return username === 'alice' ? { username, sub: 'sub-alice', password: 'pw' } : undefined; + * }, + * async findBySub(sub) { + * return sub === 'sub-alice' ? { username: 'alice', sub, password: 'pw' } : undefined; + * }, + * async addUser(user) { + * void user; + * }, + * }; + * ``` + */ +export interface MockOAuth2UserStore { + /** + * Lists every available mock user visible to the current portal. + * + * @returns A promise that resolves to the current user set. + */ + listUsers(): Promise; + /** + * Finds a mock user by login handle for the `/login` form flow. + * + * @param username - Local username submitted by the browser form. + * @returns A promise that resolves to the matching user, or `undefined` when no user exists. + */ + findByUsername(username: string): Promise; + /** + * Finds a mock user by subject identifier for `/token` and `/userinfo` resolution. + * + * @param sub - Stable OIDC subject identifier. + * @returns A promise that resolves to the matching user, or `undefined` when no user exists. + */ + findBySub(sub: string): Promise; + /** + * Persists a newly registered mock user from the `/signup` flow. + * + * @param user - The newly created mock user to store. + * @returns A promise that resolves after the user has been persisted. + */ + addUser(user: MockOAuth2User): Promise; + /** + * Optional flush hook for stores that need an explicit persistence step. + * + * @returns A promise that resolves when pending writes have been committed. + */ + persist?: () => Promise; +} + export interface MockOAuth2PortalConfig { allowedRedirectUris: Set; allowedRedirectUri: string; redirectUriToAudience: Map; getUserProfile: () => MockOAuth2UserProfile; + /** Optional provider for multi-user scenarios; when present, seedwork will use it for login/userinfo/token resolution */ + userStore?: MockOAuth2UserStore; } export interface MockOAuth2ServerConfig { @@ -24,6 +98,7 @@ export interface MockOAuth2ServerConfig { allowedRedirectUri: string; redirectUriToAudience: Map; getUserProfile: () => MockOAuth2UserProfile; + userStore?: MockOAuth2UserStore; } export interface MockOAuth2ServerHandle { diff --git a/packages/cellix/server-oauth2-mock-seedwork/src/utils.test.ts b/packages/cellix/server-oauth2-mock-seedwork/src/utils.test.ts index bf7e1b07b..5d0ab797c 100644 --- a/packages/cellix/server-oauth2-mock-seedwork/src/utils.test.ts +++ b/packages/cellix/server-oauth2-mock-seedwork/src/utils.test.ts @@ -1,21 +1,27 @@ import { describe, expect, it } from 'vitest'; -import { normalizeBaseUrl, normalizeOrigin, normalizeUrl, SAFE_NAME_RE } from './utils.ts'; +import { normalizeBaseUrl, normalizeOrigin, normalizeUrl, SAFE_NAME_RE } from './index.ts'; -describe('utils', () => { - it('normalizeUrl trims trailing slash and sorts query params', () => { +describe('normalizeUrl', () => { + it('trims trailing slash and sorts query params', () => { expect(normalizeUrl('https://example.com/foo/')).toBe('https://example.com/foo'); expect(normalizeUrl('https://example.com?b=2&a=1')).toBe('https://example.com/?a=1&b=2'); }); +}); - it('normalizeOrigin returns origin only', () => { +describe('normalizeOrigin', () => { + it('returns origin only', () => { expect(normalizeOrigin('https://example.com/path')).toBe('https://example.com'); }); +}); - it('normalizeBaseUrl removes trailing slash', () => { +describe('normalizeBaseUrl', () => { + it('removes trailing slash', () => { expect(normalizeBaseUrl('http://localhost:3000/')).toBe('http://localhost:3000'); }); +}); - it('SAFE_NAME_RE accepts valid names and rejects invalid ones', () => { +describe('SAFE_NAME_RE', () => { + it('accepts valid names and rejects invalid ones', () => { expect(SAFE_NAME_RE.test('abc-123_')).toBe(true); expect(SAFE_NAME_RE.test('bad/name')).toBe(false); }); diff --git a/packages/cellix/server-oauth2-mock-seedwork/src/utils.ts b/packages/cellix/server-oauth2-mock-seedwork/src/utils.ts index d5781fb24..03cbce9e3 100644 --- a/packages/cellix/server-oauth2-mock-seedwork/src/utils.ts +++ b/packages/cellix/server-oauth2-mock-seedwork/src/utils.ts @@ -1,7 +1,32 @@ -/** Utility helpers for server-oauth2-mock-seedwork */ +/** Utility helpers for server-oauth2-mock-seedwork. */ +/** + * Regular expression used to validate named portal registrations. + * Matches only letters, digits, underscores, and hyphens. + * + * @example + * ```ts + * SAFE_NAME_RE.test('portal_admin-1'); // true + * SAFE_NAME_RE.test('portal/admin'); // false + * ``` + */ export const SAFE_NAME_RE = /^[a-zA-Z0-9_-]+$/; +export const AUTH_CODE_PREFIX = 'mock-auth-code-'; + +/** + * Normalizes a URL for redirect-URI comparisons by removing a trailing slash from the + * path and sorting query parameters. + * + * @param value - The candidate URL string. + * @returns The normalized URL string, or the original value when parsing fails. + * + * @example + * ```ts + * normalizeUrl('https://example.com/callback/?b=2&a=1'); + * // => 'https://example.com/callback?a=1&b=2' + * ``` + */ export const normalizeUrl = (value: string) => { try { const url = new URL(value); @@ -15,6 +40,18 @@ export const normalizeUrl = (value: string) => { } }; +/** + * Extracts the origin portion of a URL so CORS checks can compare normalized origins. + * + * @param value - The candidate URL string. + * @returns The normalized origin, or the original value when parsing fails. + * + * @example + * ```ts + * normalizeOrigin('https://example.com/path?x=1'); + * // => 'https://example.com' + * ``` + */ export const normalizeOrigin = (value: string) => { try { const url = new URL(value); @@ -24,6 +61,18 @@ export const normalizeOrigin = (value: string) => { } }; +/** + * Removes a trailing slash from a configured issuer or base URL. + * + * @param url - The configured base URL. + * @returns The base URL without a trailing slash. + * + * @example + * ```ts + * normalizeBaseUrl('http://localhost:3000/'); + * // => 'http://localhost:3000' + * ``` + */ export function normalizeBaseUrl(url: string): string { return url.replace(/\/$/, ''); } diff --git a/packages/cellix/server-oauth2-mock-seedwork/tests/concurrent-registration.test.ts b/packages/cellix/server-oauth2-mock-seedwork/tests/concurrent-registration.test.ts index fd1f02ba4..559a68f95 100644 --- a/packages/cellix/server-oauth2-mock-seedwork/tests/concurrent-registration.test.ts +++ b/packages/cellix/server-oauth2-mock-seedwork/tests/concurrent-registration.test.ts @@ -16,28 +16,30 @@ function makeConfig(port: number): MockOAuth2PortalConfig & { clientPort: number }; } -describe('concurrent registration', () => { - it('allows multiple concurrent register() calls and only starts server once', async () => { - const port = 38400; - const manager = createMockOAuth2Manager({ port, host: 'localhost', baseUrl: `http://localhost:${port}` }); - const cfg1 = makeConfig(38410); - const cfg2 = makeConfig(38411); - const cfg3 = makeConfig(38412); +describe('createMockOAuth2Manager', () => { + describe('concurrent registration', () => { + it('allows multiple concurrent register() calls and only starts server once', async () => { + const port = 38400; + const manager = createMockOAuth2Manager({ port, host: 'localhost', baseUrl: `http://localhost:${port}` }); + const cfg1 = makeConfig(38410); + const cfg2 = makeConfig(38411); + const cfg3 = makeConfig(38412); - const logSpy = vi.spyOn(console, 'log').mockImplementation(() => undefined); - try { - const results = await Promise.all([manager.register('a', cfg1), manager.register('b', cfg2), manager.register('c', cfg3)]); + const logSpy = vi.spyOn(console, 'log').mockImplementation(() => undefined); + try { + const results = await Promise.all([manager.register('a', cfg1), manager.register('b', cfg2), manager.register('c', cfg3)]); - // All registrations should succeed - expect(results.length).toBe(3); - expect(results.map((r) => r.name).sort()).toEqual(['a', 'b', 'c']); + // All registrations should succeed + expect(results.length).toBe(3); + expect(results.map((r) => r.name).sort()).toEqual(['a', 'b', 'c']); - // Ensure server start log was printed exactly once - const startCalls = logSpy.mock.calls.filter((c) => typeof c[0] === 'string' && (c[0] as string).includes('Mock OAuth2 server running on')).length; - expect(startCalls).toBe(1); - } finally { - logSpy.mockRestore(); - await manager.stopAll(); - } + // Ensure server start log was printed exactly once + const startCalls = logSpy.mock.calls.filter((c) => typeof c[0] === 'string' && (c[0] as string).includes('Mock OAuth2 server running on')).length; + expect(startCalls).toBe(1); + } finally { + logSpy.mockRestore(); + await manager.stopAll(); + } + }); }); }); diff --git a/packages/cellix/server-oauth2-mock-seedwork/tests/invalid-name.test.ts b/packages/cellix/server-oauth2-mock-seedwork/tests/invalid-name.test.ts index 27c301d84..254a1adde 100644 --- a/packages/cellix/server-oauth2-mock-seedwork/tests/invalid-name.test.ts +++ b/packages/cellix/server-oauth2-mock-seedwork/tests/invalid-name.test.ts @@ -10,30 +10,32 @@ function makeConfig(): MockOAuth2PortalConfig { }; } -describe('portal name validation', () => { - it('rejects unsafe names with path segments', async () => { - const manager = createMockOAuth2Manager({ port: 19020, host: '127.0.0.1', baseUrl: 'http://127.0.0.1:19020' }); - const cfg = makeConfig(); - await expect(manager.register('foo/bar', cfg)).rejects.toThrow(`[server-oauth2-mock] Invalid portal name "foo/bar": must contain letters, digits, '_' and '-' only`); - }); +describe('createMockOAuth2Manager', () => { + describe('portal name validation', () => { + it('rejects unsafe names with path segments', async () => { + const manager = createMockOAuth2Manager({ port: 19020, host: '127.0.0.1', baseUrl: 'http://127.0.0.1:19020' }); + const cfg = makeConfig(); + await expect(manager.register('foo/bar', cfg)).rejects.toThrow(`[server-oauth2-mock] Invalid portal name "foo/bar": must contain letters, digits, '_' and '-' only`); + }); - it('rejects unsafe names with traversal segments', async () => { - const manager = createMockOAuth2Manager({ port: 19021, host: '127.0.0.1', baseUrl: 'http://127.0.0.1:19021' }); - const cfg = makeConfig(); - await expect(manager.register('../admin', cfg)).rejects.toThrow(`[server-oauth2-mock] Invalid portal name "../admin": must contain letters, digits, '_' and '-' only`); - }); + it('rejects unsafe names with traversal segments', async () => { + const manager = createMockOAuth2Manager({ port: 19021, host: '127.0.0.1', baseUrl: 'http://127.0.0.1:19021' }); + const cfg = makeConfig(); + await expect(manager.register('../admin', cfg)).rejects.toThrow(`[server-oauth2-mock] Invalid portal name "../admin": must contain letters, digits, '_' and '-' only`); + }); - it('rejects names with disallowed characters such as dots', async () => { - const manager = createMockOAuth2Manager({ port: 19022, host: '127.0.0.1', baseUrl: 'http://127.0.0.1:19022' }); - const cfg = makeConfig(); - await expect(manager.register('foo.bar', cfg)).rejects.toThrow(`[server-oauth2-mock] Invalid portal name "foo.bar": must contain letters, digits, '_' and '-' only`); - }); + it('rejects names with disallowed characters such as dots', async () => { + const manager = createMockOAuth2Manager({ port: 19022, host: '127.0.0.1', baseUrl: 'http://127.0.0.1:19022' }); + const cfg = makeConfig(); + await expect(manager.register('foo.bar', cfg)).rejects.toThrow(`[server-oauth2-mock] Invalid portal name "foo.bar": must contain letters, digits, '_' and '-' only`); + }); - it('accepts names with letters, digits, underscores, and hyphens', async () => { - const manager = createMockOAuth2Manager({ port: 19023, host: '127.0.0.1', baseUrl: 'http://127.0.0.1:19023' }); - const cfg = makeConfig(); - const result = await manager.register('admin-portal_1', cfg); - expect(result.name).toBe('admin-portal_1'); - await manager.stopAll(); + it('accepts names with letters, digits, underscores, and hyphens', async () => { + const manager = createMockOAuth2Manager({ port: 19023, host: '127.0.0.1', baseUrl: 'http://127.0.0.1:19023' }); + const cfg = makeConfig(); + const result = await manager.register('admin-portal_1', cfg); + expect(result.name).toBe('admin-portal_1'); + await manager.stopAll(); + }); }); }); diff --git a/packages/cellix/server-oauth2-mock-seedwork/tests/login-relogin.spec.ts b/packages/cellix/server-oauth2-mock-seedwork/tests/login-relogin.spec.ts new file mode 100644 index 000000000..db20c7567 --- /dev/null +++ b/packages/cellix/server-oauth2-mock-seedwork/tests/login-relogin.spec.ts @@ -0,0 +1,75 @@ +import express from 'express'; +import { describe, expect, it } from 'vitest'; +import { AUTH_CODE_PREFIX, buildOidcRouter, type MockOAuth2PortalConfig, type MockOAuth2UserStore } from '../src/index.ts'; + +function makeConfig() { + const clientBase = `http://127.0.0.1:6000`; + const user = { + username: 'testuser', + sub: 'sub-1', + password: 'password', + claims: { email: 'test@ownercommunity.onmicrosoft.com', given_name: 'Test', family_name: 'User' }, + }; + + const userStore: MockOAuth2UserStore = { + listUsers: async () => [user], + findByUsername: async (username: string) => (username === user.username ? user : undefined), + findBySub: async (sub: string) => (sub === user.sub ? user : undefined), + addUser: async () => undefined, + }; + + return { + allowedRedirectUris: new Set([`${clientBase}/callback`]), + allowedRedirectUri: `${clientBase}/callback`, + redirectUriToAudience: new Map([[`${clientBase}/callback`, 'mock-client']]), + getUserProfile: () => ({ email: 'test@ownercommunity.onmicrosoft.com', given_name: 'Test', family_name: 'User' }), + userStore, + }; +} + +describe('buildOidcRouter', () => { + describe('login re-login fallback', () => { + it('falls back to Referer nonce when body nonce is missing', async () => { + const cfg = makeConfig(); + const app = express(); + app.disable('x-powered-by'); + const server = app.listen(0); + + try { + await new Promise((resolve) => server.on('listening', () => resolve())); + const boundPort = (server.address() as unknown as { port: number }).port; + const issuerBase = `http://127.0.0.1:${boundPort}`; + const router = await buildOidcRouter(issuerBase, cfg as unknown as MockOAuth2PortalConfig); + app.use(router); + + // Request login page to obtain server-side session nonce + const loginUrl = `${issuerBase}/login?redirect_uri=${encodeURIComponent(cfg.allowedRedirectUri)}&state=s`; + const loginRes = await fetch(loginUrl); + expect(loginRes.status).toBe(200); + const html = await loginRes.text(); + const match = html.match(/name="nonce" value="([^"]+)"/); + expect(match).toBeTruthy(); + const serverNonce = match?.[1]; + expect(serverNonce).toBeTruthy(); + const nonce = serverNonce as string; + + // Post login without a body nonce but with Referer header pointing to the login page with the nonce + const postRes = await fetch(`${issuerBase}/login`, { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded', Referer: `${issuerBase}/login?nonce=${nonce}` }, + body: new URLSearchParams({ username: 'testuser', password: 'password', nonce: '' }).toString(), + redirect: 'manual', + }); + + expect(postRes.status).toBe(302); + const location = postRes.headers.get('location'); + expect(location).toBeTruthy(); + expect(location).toContain(cfg.allowedRedirectUri); + expect(new URL(location as string).searchParams.get('code')?.startsWith(AUTH_CODE_PREFIX)).toBe(true); + } finally { + server.close(); + await new Promise((resolve) => server.once('close', () => resolve())); + } + }); + }); +}); diff --git a/packages/cellix/server-oauth2-mock-seedwork/tests/multi-registration.test.ts b/packages/cellix/server-oauth2-mock-seedwork/tests/multi-registration.test.ts index 94400c0b0..de1ec0941 100644 --- a/packages/cellix/server-oauth2-mock-seedwork/tests/multi-registration.test.ts +++ b/packages/cellix/server-oauth2-mock-seedwork/tests/multi-registration.test.ts @@ -39,187 +39,191 @@ async function fetchJson(url: string): Promise { return res.json() as Promise; } -describe('multi-registration contract', () => { - it('rejects duplicate portal names', async () => { - const manager = createMockOAuth2Manager({ - port: 38199, - host: 'localhost', - baseUrl: 'http://localhost:38199', +describe('createMockOAuth2Manager', () => { + describe('multi-registration contract', () => { + it('rejects duplicate portal names', async () => { + const manager = createMockOAuth2Manager({ + port: 38199, + host: 'localhost', + baseUrl: 'http://localhost:38199', + }); + const cfg = makeConfig(38299); + try { + await manager.register('duplicate', cfg); + await expect(manager.register('duplicate', cfg)).rejects.toThrow(); + } finally { + await manager.stopAll(); + } + }); + it('registers two named OIDC configs and exposes distinct metadata/jwks', async () => { + const port = 38200; + const manager = createMockOAuth2Manager({ port, host: 'localhost', baseUrl: `http://localhost:${port}` }); + const cfg1 = makeConfig(38210); + const cfg2 = makeConfig(38211); + + const handle1 = await manager.register('portal', cfg1); + const handle2 = await manager.register('admin', cfg2); + + try { + const meta1 = await fetchJson<{ issuer: string }>(`${handle1.baseUrl}/.well-known/openid-configuration`); + const meta2 = await fetchJson<{ issuer: string }>(`${handle2.baseUrl}/.well-known/openid-configuration`); + + expect(meta1.issuer).toBe(handle1.baseUrl); + expect(meta2.issuer).toBe(handle2.baseUrl); + + const jwks1 = await fetchJson<{ keys: unknown[] }>(`${handle1.baseUrl}/.well-known/jwks.json`); + const jwks2 = await fetchJson<{ keys: unknown[] }>(`${handle2.baseUrl}/.well-known/jwks.json`); + + expect(Array.isArray(jwks1.keys)).toBe(true); + expect(Array.isArray(jwks2.keys)).toBe(true); + } finally { + await manager.stopAll(); + } }); - const cfg = makeConfig(38299); - try { - await manager.register('duplicate', cfg); - await expect(manager.register('duplicate', cfg)).rejects.toThrow(); - } finally { - await manager.stopAll(); - } - }); - it('registers two named OIDC configs and exposes distinct metadata/jwks', async () => { - const port = 38200; - const manager = createMockOAuth2Manager({ port, host: 'localhost', baseUrl: `http://localhost:${port}` }); - const cfg1 = makeConfig(38210); - const cfg2 = makeConfig(38211); - - const handle1 = await manager.register('portal', cfg1); - const handle2 = await manager.register('admin', cfg2); - - try { - const meta1 = await fetchJson<{ issuer: string }>(`${handle1.baseUrl}/.well-known/openid-configuration`); - const meta2 = await fetchJson<{ issuer: string }>(`${handle2.baseUrl}/.well-known/openid-configuration`); - - expect(meta1.issuer).toBe(handle1.baseUrl); - expect(meta2.issuer).toBe(handle2.baseUrl); - - const jwks1 = await fetchJson<{ keys: unknown[] }>(`${handle1.baseUrl}/.well-known/jwks.json`); - const jwks2 = await fetchJson<{ keys: unknown[] }>(`${handle2.baseUrl}/.well-known/jwks.json`); - expect(Array.isArray(jwks1.keys)).toBe(true); - expect(Array.isArray(jwks2.keys)).toBe(true); - } finally { - await manager.stopAll(); - } - }); + it('per-config auth flow is isolated (authorize -> token)', async () => { + const port = 38202; + const manager = createMockOAuth2Manager({ port, host: 'localhost', baseUrl: `http://localhost:${port}` }); + const cfg1 = makeConfig(38212); + const cfg2 = makeConfig(38213); + + const h1 = await manager.register('one', cfg1); + const h2 = await manager.register('two', cfg2); + + try { + // call authorize for h1 with its redirect + const authRes = await fetch(`${h1.baseUrl}/authorize?redirect_uri=${encodeURIComponent(cfg1.allowedRedirectUri)}`, { redirect: 'manual' }); + expect(authRes.status).toBe(302); + const location = authRes.headers.get('location'); + expect(location).toBeTruthy(); + const url = new URL(location as string); + const code = url.searchParams.get('code'); + expect(code).toBeTruthy(); + + // exchange code at token endpoint for h1 + const tokenRes = await fetch(`${h1.baseUrl}/token`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ grant_type: 'authorization_code', code }), + }); + const tokenJson = (await tokenRes.json()) as TestTokenResponse; + expect(tokenJson).toHaveProperty('access_token'); + expect(tokenJson.profile.aud).toBe(`mock-client-${cfg1.clientPort}`); + + // ensure h2 tokens are independent by performing authorize/token on h2 + const authRes2 = await fetch(`${h2.baseUrl}/authorize?redirect_uri=${encodeURIComponent(cfg2.allowedRedirectUri)}`, { redirect: 'manual' }); + expect(authRes2.status).toBe(302); + const location2 = authRes2.headers.get('location'); + const url2 = new URL(location2 as string); + const code2 = url2.searchParams.get('code'); + + const tokenRes2 = await fetch(`${h2.baseUrl}/token`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ grant_type: 'authorization_code', code: code2 }), + }); + const tokenJson2 = (await tokenRes2.json()) as TestTokenResponse; + expect(tokenJson2.profile.aud).toBe(`mock-client-${cfg2.clientPort}`); + } finally { + await manager.stopAll(); + } + }); - it('per-config auth flow is isolated (authorize -> token)', async () => { - const port = 38202; - const manager = createMockOAuth2Manager({ port, host: 'localhost', baseUrl: `http://localhost:${port}` }); - const cfg1 = makeConfig(38212); - const cfg2 = makeConfig(38213); - - const h1 = await manager.register('one', cfg1); - const h2 = await manager.register('two', cfg2); - - try { - // call authorize for h1 with its redirect - const authRes = await fetch(`${h1.baseUrl}/authorize?redirect_uri=${encodeURIComponent(cfg1.allowedRedirectUri)}`, { redirect: 'manual' }); - expect(authRes.status).toBe(302); - const location = authRes.headers.get('location'); - expect(location).toBeTruthy(); - const url = new URL(location as string); - const code = url.searchParams.get('code'); - expect(code).toBeTruthy(); - - // exchange code at token endpoint for h1 - const tokenRes = await fetch(`${h1.baseUrl}/token`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ grant_type: 'authorization_code', code }), - }); - const tokenJson = (await tokenRes.json()) as TestTokenResponse; - expect(tokenJson).toHaveProperty('access_token'); - expect(tokenJson.profile.aud).toBe(`mock-client-${cfg1.clientPort}`); - - // ensure h2 tokens are independent by performing authorize/token on h2 - const authRes2 = await fetch(`${h2.baseUrl}/authorize?redirect_uri=${encodeURIComponent(cfg2.allowedRedirectUri)}`, { redirect: 'manual' }); - expect(authRes2.status).toBe(302); - const location2 = authRes2.headers.get('location'); - const url2 = new URL(location2 as string); - const code2 = url2.searchParams.get('code'); - - const tokenRes2 = await fetch(`${h2.baseUrl}/token`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ grant_type: 'authorization_code', code: code2 }), + describe('startMockOAuth2Server', () => { + it('single-config backward compatibility with startMockOAuth2Server', async () => { + const cfg: MockOAuth2ServerConfig = { + port: 38204, + baseUrl: 'http://localhost:38204', + allowedRedirectUris: new Set(['http://localhost:38204/callback']), + allowedRedirectUri: 'http://localhost:38204/callback', + redirectUriToAudience: new Map([['http://localhost:38204/callback', 'mock-client-38204']]), + host: 'localhost', + getUserProfile: () => ({ email: 'x@example.com', given_name: 'T', family_name: 'U' }), + }; + const handle = await startMockOAuth2Server(cfg); + try { + const meta = await fetchJson<{ issuer: string }>(`${cfg.baseUrl}/.well-known/openid-configuration`); + expect(meta.issuer).toBe(cfg.baseUrl); + } finally { + await handle.disposer.stop(); + } }); - const tokenJson2 = (await tokenRes2.json()) as TestTokenResponse; - expect(tokenJson2.profile.aud).toBe(`mock-client-${cfg2.clientPort}`); - } finally { - await manager.stopAll(); - } - }); - - it('single-config backward compatibility with startMockOAuth2Server', async () => { - const cfg: MockOAuth2ServerConfig = { - port: 38204, - baseUrl: 'http://localhost:38204', - allowedRedirectUris: new Set(['http://localhost:38204/callback']), - allowedRedirectUri: 'http://localhost:38204/callback', - redirectUriToAudience: new Map([['http://localhost:38204/callback', 'mock-client-38204']]), - host: 'localhost', - getUserProfile: () => ({ email: 'x@example.com', given_name: 'T', family_name: 'U' }), - }; - const handle = await startMockOAuth2Server(cfg); - try { - const meta = await fetchJson<{ issuer: string }>(`${cfg.baseUrl}/.well-known/openid-configuration`); - expect(meta.issuer).toBe(cfg.baseUrl); - } finally { - await handle.disposer.stop(); - } - }); - - it('throws when registering the same portal name twice', async () => { - const manager = createMockOAuth2Manager({ port: 19010, host: '127.0.0.1', baseUrl: 'http://127.0.0.1:19010' }); - const config: MockOAuth2PortalConfig = { - allowedRedirectUris: new Set(['http://localhost/cb']), - allowedRedirectUri: 'http://localhost/cb', - redirectUriToAudience: new Map([['http://localhost/cb', 'aud']]), - getUserProfile: () => ({ sub: '00000000-0000-4000-8000-000000000001', email: 'a@b.com', given_name: 'A', family_name: 'B', tid: 't' }), - }; - await manager.register('dupe', config); - await expect(manager.register('dupe', config)).rejects.toThrow(); - await manager.stopAll(); - }); - - it('includes array and custom claims verbatim in issued JWT', async () => { - const manager = createMockOAuth2Manager({ - port: 19003, - host: '127.0.0.1', - baseUrl: 'http://127.0.0.1:19003', }); - await manager.register('claims-test', { - allowedRedirectUris: new Set(['http://localhost/cb']), - allowedRedirectUri: 'http://localhost/cb', - redirectUriToAudience: new Map([['http://localhost/cb', 'test-aud']]), - getUserProfile: () => ({ - sub: '00000000-0000-4000-8000-000000000099', - email: 'test@example.com', - given_name: 'Test', - family_name: 'User', - tid: 'test-tenant', - roles: ['admin', 'editor'], - department: 'engineering', - }), + it('throws when registering the same portal name twice', async () => { + const manager = createMockOAuth2Manager({ port: 19010, host: '127.0.0.1', baseUrl: 'http://127.0.0.1:19010' }); + const config: MockOAuth2PortalConfig = { + allowedRedirectUris: new Set(['http://localhost/cb']), + allowedRedirectUri: 'http://localhost/cb', + redirectUriToAudience: new Map([['http://localhost/cb', 'aud']]), + getUserProfile: () => ({ sub: '00000000-0000-4000-8000-000000000001', email: 'a@b.com', given_name: 'A', family_name: 'B', tid: 't' }), + }; + await manager.register('dupe', config); + await expect(manager.register('dupe', config)).rejects.toThrow(); + await manager.stopAll(); }); - try { - // Get auth code - const authRes = await fetch('http://127.0.0.1:19003/claims-test/authorize?response_type=code&client_id=test-aud&redirect_uri=http%3A%2F%2Flocalhost%2Fcb&state=s&nonce=n', { redirect: 'manual' }); - const location = authRes.headers.get('location') ?? ''; - const code = new URL(location, 'http://base').searchParams.get('code') ?? ''; - - // Exchange for token - const tokenRes = await fetch('http://127.0.0.1:19003/claims-test/token', { - method: 'POST', - headers: { 'content-type': 'application/x-www-form-urlencoded' }, - body: new URLSearchParams({ - grant_type: 'authorization_code', - code, - redirect_uri: 'http://localhost/cb', - client_id: 'test-aud', + it('includes array and custom claims verbatim in issued JWT', async () => { + const manager = createMockOAuth2Manager({ + port: 19003, + host: '127.0.0.1', + baseUrl: 'http://127.0.0.1:19003', + }); + + await manager.register('claims-test', { + allowedRedirectUris: new Set(['http://localhost/cb']), + allowedRedirectUri: 'http://localhost/cb', + redirectUriToAudience: new Map([['http://localhost/cb', 'test-aud']]), + getUserProfile: () => ({ + sub: '00000000-0000-4000-8000-000000000099', + email: 'test@example.com', + given_name: 'Test', + family_name: 'User', + tid: 'test-tenant', + roles: ['admin', 'editor'], + department: 'engineering', }), }); - const tokens = (await tokenRes.json()) as TestTokenWithClaimsResponse; - - // Decode JWT payload (no verification needed — just inspect claims) - const payloadB64 = tokens.id_token.split('.')[1] as string; - const payload = JSON.parse(Buffer.from(payloadB64, 'base64url').toString('utf-8')) as TestClaimsPayload; - - expect(payload.roles).toEqual(['admin', 'editor']); - expect(payload.department).toBe('engineering'); - - // Also verify access_token contains the custom claims - const accessPayloadB64 = tokens.access_token.split('.')[1] as string; - const accessPayload = JSON.parse(Buffer.from(accessPayloadB64, 'base64url').toString('utf-8')) as TestClaimsPayload; - expect(accessPayload.roles).toEqual(['admin', 'editor']); - expect(accessPayload.department).toBe('engineering'); - - // And the token response profile object should also include them - const profileTyped = tokens.profile as unknown as TestClaimsPayload; - expect(profileTyped.roles).toEqual(['admin', 'editor']); - expect(profileTyped.department).toBe('engineering'); - } finally { - await manager.stopAll(); - } + + try { + // Get auth code + const authRes = await fetch('http://127.0.0.1:19003/claims-test/authorize?response_type=code&client_id=test-aud&redirect_uri=http%3A%2F%2Flocalhost%2Fcb&state=s&nonce=n', { redirect: 'manual' }); + const location = authRes.headers.get('location') ?? ''; + const code = new URL(location, 'http://base').searchParams.get('code') ?? ''; + + // Exchange for token + const tokenRes = await fetch('http://127.0.0.1:19003/claims-test/token', { + method: 'POST', + headers: { 'content-type': 'application/x-www-form-urlencoded' }, + body: new URLSearchParams({ + grant_type: 'authorization_code', + code, + redirect_uri: 'http://localhost/cb', + client_id: 'test-aud', + }), + }); + const tokens = (await tokenRes.json()) as TestTokenWithClaimsResponse; + + // Decode JWT payload (no verification needed — just inspect claims) + const payloadB64 = tokens.id_token.split('.')[1] as string; + const payload = JSON.parse(Buffer.from(payloadB64, 'base64url').toString('utf-8')) as TestClaimsPayload; + + expect(payload.roles).toEqual(['admin', 'editor']); + expect(payload.department).toBe('engineering'); + + // Also verify access_token contains the custom claims + const accessPayloadB64 = tokens.access_token.split('.')[1] as string; + const accessPayload = JSON.parse(Buffer.from(accessPayloadB64, 'base64url').toString('utf-8')) as TestClaimsPayload; + expect(accessPayload.roles).toEqual(['admin', 'editor']); + expect(accessPayload.department).toBe('engineering'); + + // And the token response profile object should also include them + const profileTyped = tokens.profile as unknown as TestClaimsPayload; + expect(profileTyped.roles).toEqual(['admin', 'editor']); + expect(profileTyped.department).toBe('engineering'); + } finally { + await manager.stopAll(); + } + }); }); }); diff --git a/packages/cellix/server-oauth2-mock-seedwork/tests/reserved-claims-precedence.test.ts b/packages/cellix/server-oauth2-mock-seedwork/tests/reserved-claims-precedence.test.ts index 35e414061..d6b2006e3 100644 --- a/packages/cellix/server-oauth2-mock-seedwork/tests/reserved-claims-precedence.test.ts +++ b/packages/cellix/server-oauth2-mock-seedwork/tests/reserved-claims-precedence.test.ts @@ -7,58 +7,60 @@ interface TestReservedClaimsPayload { } // Test that caller-provided reserved claims (iss, aud) do not override server values -describe('reserved claims precedence', () => { - it('server-authoritative iss and aud win over user-provided extras', async () => { - const manager = createMockOAuth2Manager({ port: 19010, host: '127.0.0.1', baseUrl: 'http://127.0.0.1:19010' }); +describe('createMockOAuth2Manager', () => { + describe('reserved claims precedence', () => { + it('server-authoritative iss and aud win over user-provided extras', async () => { + const manager = createMockOAuth2Manager({ port: 19010, host: '127.0.0.1', baseUrl: 'http://127.0.0.1:19010' }); - await manager.register('reserved-claims', { - allowedRedirectUris: new Set(['http://localhost/cb']), - allowedRedirectUri: 'http://localhost/cb', - redirectUriToAudience: new Map([['http://localhost/cb', 'server-aud']]), - getUserProfile: () => ({ - // Malicious or mistaken extras that attempt to override reserved claims - aud: 'evil-aud', - iss: 'http://evil-issuer.local', - email: 'hacker@example.com', - given_name: 'Bad', - family_name: 'Actor', - roles: ['attacker'], - }), - }); - - try { - const authRes = await fetch('http://127.0.0.1:19010/reserved-claims/authorize?response_type=code&client_id=server-aud&redirect_uri=http%3A%2F%2Flocalhost%2Fcb&state=s&nonce=n', { redirect: 'manual' }); - const location = authRes.headers.get('location') ?? ''; - const code = new URL(location, 'http://base').searchParams.get('code') ?? ''; - - const tokenRes = await fetch('http://127.0.0.1:19010/reserved-claims/token', { - method: 'POST', - headers: { 'content-type': 'application/x-www-form-urlencoded' }, - body: new URLSearchParams({ - grant_type: 'authorization_code', - code, - redirect_uri: 'http://localhost/cb', - client_id: 'server-aud', + await manager.register('reserved-claims', { + allowedRedirectUris: new Set(['http://localhost/cb']), + allowedRedirectUri: 'http://localhost/cb', + redirectUriToAudience: new Map([['http://localhost/cb', 'server-aud']]), + getUserProfile: () => ({ + // Malicious or mistaken extras that attempt to override reserved claims + aud: 'evil-aud', + iss: 'http://evil-issuer.local', + email: 'hacker@example.com', + given_name: 'Bad', + family_name: 'Actor', + roles: ['attacker'], }), }); - const tokens = (await tokenRes.json()) as { - id_token: string; - profile: { iss: string; aud: string }; - }; - // Decode id_token payload - const payloadB64 = tokens.id_token.split('.')[1] as string; - const payload = JSON.parse(Buffer.from(payloadB64, 'base64url').toString('utf-8')) as TestReservedClaimsPayload; + try { + const authRes = await fetch('http://127.0.0.1:19010/reserved-claims/authorize?response_type=code&client_id=server-aud&redirect_uri=http%3A%2F%2Flocalhost%2Fcb&state=s&nonce=n', { redirect: 'manual' }); + const location = authRes.headers.get('location') ?? ''; + const code = new URL(location, 'http://base').searchParams.get('code') ?? ''; - // Assert server values are present (issuer is router base URL, aud matches redirect->aud mapping) - expect(payload.iss).toBe('http://127.0.0.1:19010/reserved-claims'); - expect(payload.aud).toBe('server-aud'); + const tokenRes = await fetch('http://127.0.0.1:19010/reserved-claims/token', { + method: 'POST', + headers: { 'content-type': 'application/x-www-form-urlencoded' }, + body: new URLSearchParams({ + grant_type: 'authorization_code', + code, + redirect_uri: 'http://localhost/cb', + client_id: 'server-aud', + }), + }); + const tokens = (await tokenRes.json()) as { + id_token: string; + profile: { iss: string; aud: string }; + }; - // profile wrapper should also reflect server aud and issuer - expect(tokens.profile.iss).toBe('http://127.0.0.1:19010/reserved-claims'); - expect(tokens.profile.aud).toBe('server-aud'); - } finally { - await manager.stopAll(); - } + // Decode id_token payload + const payloadB64 = tokens.id_token.split('.')[1] as string; + const payload = JSON.parse(Buffer.from(payloadB64, 'base64url').toString('utf-8')) as TestReservedClaimsPayload; + + // Assert server values are present (issuer is router base URL, aud matches redirect->aud mapping) + expect(payload.iss).toBe('http://127.0.0.1:19010/reserved-claims'); + expect(payload.aud).toBe('server-aud'); + + // profile wrapper should also reflect server aud and issuer + expect(tokens.profile.iss).toBe('http://127.0.0.1:19010/reserved-claims'); + expect(tokens.profile.aud).toBe('server-aud'); + } finally { + await manager.stopAll(); + } + }); }); }); diff --git a/packages/ocom-verification/e2e-tests/src/shared/support/servers/test-api-server.ts b/packages/ocom-verification/e2e-tests/src/shared/support/servers/test-api-server.ts index 2845662ee..84a87174a 100644 --- a/packages/ocom-verification/e2e-tests/src/shared/support/servers/test-api-server.ts +++ b/packages/ocom-verification/e2e-tests/src/shared/support/servers/test-api-server.ts @@ -10,7 +10,7 @@ export class TestApiServer extends PortlessServer { const env = { ...process.env, }; - delete env['NODE_OPTIONS']; + delete env.NODE_OPTIONS; execFileSync('pnpm', ['run', 'predev'], { cwd: this.cwd, diff --git a/packages/ocom-verification/e2e-tests/src/shared/support/servers/test-vite-server.ts b/packages/ocom-verification/e2e-tests/src/shared/support/servers/test-vite-server.ts index 52f4cf85a..f8219a2b3 100644 --- a/packages/ocom-verification/e2e-tests/src/shared/support/servers/test-vite-server.ts +++ b/packages/ocom-verification/e2e-tests/src/shared/support/servers/test-vite-server.ts @@ -28,7 +28,7 @@ export class TestViteServer extends PortlessServer { return { BROWSER: 'none', - VITE_BASE_URL: uiBase, + VITE_APP_UI_COMMUNITY_BASE_URL: uiBase, VITE_AAD_B2C_ACCOUNT_AUTHORITY: apiSettings.accountPortalOidcIssuer, VITE_AAD_B2C_REDIRECT_URI: `${uiBase}/auth-redirect`, VITE_COMMON_API_ENDPOINT: apiEndpoint, diff --git a/packages/ocom/archunit-tests/src/code-metrics.test.ts b/packages/ocom/archunit-tests/src/code-metrics.test.ts index 29470d37f..7f231aee9 100644 --- a/packages/ocom/archunit-tests/src/code-metrics.test.ts +++ b/packages/ocom/archunit-tests/src/code-metrics.test.ts @@ -7,59 +7,34 @@ const tsconfigPath = join(fileURLToPath(new URL('..', import.meta.url)), 'tsconf describe('Code Metrics', () => { describe('File Size', () => { - // This check can be slow on large repos; give it more timeout headroom - it.skip('should not contain too large files', async () => { - const rule = metrics(tsconfigPath) - .inPath('../**/src/**/*.ts') - .inPath('../../../apps/**/src/**/*.ts') - .count() - .linesOfCode() - .shouldBeBelow(1000); - // Enable debug logging to list analyzed files when troubleshooting - await expect(rule).toPassAsync(); - }, 15000); + // This check can be slow on large repos; give it more timeout headroom + it.skip('should not contain too large files', async () => { + const rule = metrics(tsconfigPath).inPath('../**/src/**/*.ts').inPath('../../../apps/**/src/**/*.ts').count().linesOfCode().shouldBeBelow(1000); + // Enable debug logging to list analyzed files when troubleshooting + await expect(rule).toPassAsync(); + }, 15000); it.skip('should limit statements per file (excluding tests)', async () => { - const rule = metrics(tsconfigPath) - .inPath('../**/src/**/*.ts') - .inPath('../../../apps/**/src/**/*.ts') - .count() - .statements() - .shouldBeBelowOrEqual(250); + const rule = metrics(tsconfigPath).inPath('../**/src/**/*.ts').inPath('../../../apps/**/src/**/*.ts').count().statements().shouldBeBelowOrEqual(250); await expect(rule).toPassAsync(); }, 15000); }); describe('Class Structure', () => { it.skip('should limit methods per class', async () => { - const rule = metrics(tsconfigPath) - .inPath('../**/src/**/*.ts') - .inPath('../../../apps/**/src/**/*.ts') - .count() - .methodCount() - .shouldBeBelow(20); + const rule = metrics(tsconfigPath).inPath('../**/src/**/*.ts').inPath('../../../apps/**/src/**/*.ts').count().methodCount().shouldBeBelow(20); await expect(rule).toPassAsync(); }); it.skip('should limit fields per class', async () => { - const rule = metrics(tsconfigPath) - .inPath('../**/src/**/*.ts') - .inPath('../../../apps/**/src/**/*.ts') - .count() - .fieldCount() - .shouldBeBelow(15); + const rule = metrics(tsconfigPath).inPath('../**/src/**/*.ts').inPath('../../../apps/**/src/**/*.ts').count().fieldCount().shouldBeBelow(15); await expect(rule).toPassAsync(); }); }); describe('Coupling', () => { it.skip('should limit imports per file', async () => { - const rule = metrics(tsconfigPath) - .inPath('../**/src/**/*.ts') - .inPath('../../../apps/**/src/**/*.ts') - .count() - .imports() - .shouldBeBelowOrEqual(20); + const rule = metrics(tsconfigPath).inPath('../**/src/**/*.ts').inPath('../../../apps/**/src/**/*.ts').count().imports().shouldBeBelowOrEqual(20); await expect(rule).toPassAsync(); }); }); diff --git a/packages/ocom/archunit-tests/src/env-vars-naming.archunit.test.ts b/packages/ocom/archunit-tests/src/env-vars-naming.archunit.test.ts index 77457bf05..5d0c4841b 100644 --- a/packages/ocom/archunit-tests/src/env-vars-naming.archunit.test.ts +++ b/packages/ocom/archunit-tests/src/env-vars-naming.archunit.test.ts @@ -1,11 +1,21 @@ import fs from 'node:fs'; -import os from 'node:os'; import path from 'node:path'; -import { expect, test } from 'vitest'; +import { afterAll, expect, test } from 'vitest'; import { CANONICAL_PORTALS, validateEnvNames, writeEvidence } from './validate-env-names.cjs'; const rootDir = path.resolve(__dirname, '../../../../'); const packageDir = path.resolve(__dirname, '../'); +const testScratchRoot = path.join(packageDir, '.test-work'); + +const createScratchRoot = (prefix: string) => { + const scratchRoot = path.join(testScratchRoot, `${prefix}-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`); + fs.mkdirSync(scratchRoot, { recursive: true }); + return scratchRoot; +}; + +afterAll(() => { + fs.rmSync(testScratchRoot, { recursive: true, force: true }); +}); test('env vars naming compliance scan generates evidence file', () => { const evidence = validateEnvNames({ rootDir }); @@ -47,7 +57,7 @@ test('env vars naming compliance scan generates evidence file', () => { }); test('env vars naming compliance scan detects non-compliant variables', () => { - const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'env-vars-naming-')); + const tmpRoot = createScratchRoot('env-vars-naming'); try { // Construct the invalid var name at runtime so the scanner doesn't pick it up from this source file const invalidVar = `VITE_APP_${'UNKNOWNPORTAL'}_FOO`; @@ -71,7 +81,7 @@ test('env vars naming compliance scan detects non-compliant variables', () => { }); test('validateEnvNames maps VITE_COMMON_* and portal vars to correct portals and ownerGroups', () => { - const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'env-vars-mapping-')); + const tmpRoot = createScratchRoot('env-vars-mapping'); try { // Use a .env.test file — dotfiles named .env.* are explicitly allowed by the scanner fs.writeFileSync(path.join(tmpRoot, '.env.test'), ['VITE_COMMON_API_ENDPOINT=https://example.com', 'VITE_APP_UI_COMMUNITY_B2C_CLIENTID=client-id'].join('\n'), 'utf8'); @@ -92,8 +102,42 @@ test('validateEnvNames maps VITE_COMMON_* and portal vars to correct portals and } }); +test('validateEnvNames flags VITE_* vars that lack VITE_APP_ or VITE_COMMON_ prefix', () => { + const tmpRoot = createScratchRoot('env-vars-prefix'); + try { + const badVar = `VITE_${'FUNCTION'}_ENDPOINT`; + fs.writeFileSync(path.join(tmpRoot, 'config.ts'), `const { ${badVar} } = import.meta.env;\n`, 'utf8'); + + const evidence = validateEnvNames({ rootDir: tmpRoot, scanPaths: [tmpRoot] }); + + const offending = evidence.results.find((r) => r.variable === badVar); + expect(offending).toBeDefined(); + expect(offending?.status).toBe('non_compliant'); + expect(offending?.reason).toBe('Variable does not use VITE_APP__ or VITE_COMMON_ prefix'); + } finally { + fs.rmSync(tmpRoot, { recursive: true, force: true }); + } +}); + +test('validateEnvNames flags VITE_APP_ vars with unknown portal name', () => { + const tmpRoot = createScratchRoot('env-vars-unknown-portal'); + try { + const badVar = `VITE_APP_${'UNKNOWNPORTAL'}_FOO`; + fs.writeFileSync(path.join(tmpRoot, 'config.ts'), `const { ${badVar} } = import.meta.env;\n`, 'utf8'); + + const evidence = validateEnvNames({ rootDir: tmpRoot, scanPaths: [tmpRoot] }); + + const offending = evidence.results.find((r) => r.variable === badVar); + expect(offending).toBeDefined(); + expect(offending?.status).toBe('non_compliant'); + expect(offending?.reason).toContain('Unknown VITE_APP_'); + } finally { + fs.rmSync(tmpRoot, { recursive: true, force: true }); + } +}); + test('validateEnvNames deduplicates results, excluding dist/ from scan', () => { - const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'env-vars-dedupe-')); + const tmpRoot = createScratchRoot('env-vars-dedupe'); try { const srcFile = path.join(tmpRoot, 'src', 'config.ts'); const distFile = path.join(tmpRoot, 'dist', 'config.js'); @@ -116,3 +160,41 @@ test('validateEnvNames deduplicates results, excluding dist/ from scan', () => { fs.rmSync(tmpRoot, { recursive: true, force: true }); } }); + +test('validateEnvNames ignores variables that only appear in comments and string literals', () => { + const tmpRoot = createScratchRoot('env-vars-ignored-ranges'); + try { + const content = ['// VITE_APP_UI_COMMUNITY_FOO in a comment', 'const s = "VITE_APP_UI_COMMUNITY_BAR in a string";'].join('\n'); + + fs.writeFileSync(path.join(tmpRoot, 'config.ts'), content, 'utf8'); + + const evidence = validateEnvNames({ rootDir: tmpRoot, scanPaths: [tmpRoot] }); + + expect(evidence.results).toEqual([]); + } finally { + fs.rmSync(tmpRoot, { recursive: true, force: true }); + } +}); + +test('validateEnvNames detects env access inside template literal expressions', () => { + const tmpRoot = createScratchRoot('env-vars-template-expression'); + try { + const content = 'const endpoint = `' + '$' + "{import.meta.env['VITE_APP_UI_COMMUNITY_API_ENDPOINT']}" + '`;\n'; + + fs.writeFileSync(path.join(tmpRoot, 'config.ts'), content, 'utf8'); + + const evidence = validateEnvNames({ rootDir: tmpRoot, scanPaths: [tmpRoot] }); + + expect(evidence.results).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + variable: 'VITE_APP_UI_COMMUNITY_API_ENDPOINT', + status: 'compliant', + portal: 'UI_COMMUNITY', + }), + ]), + ); + } finally { + fs.rmSync(tmpRoot, { recursive: true, force: true }); + } +}); diff --git a/packages/ocom/archunit-tests/src/validate-env-names.cjs b/packages/ocom/archunit-tests/src/validate-env-names.cjs index 7bbab061e..4a2e870fa 100644 --- a/packages/ocom/archunit-tests/src/validate-env-names.cjs +++ b/packages/ocom/archunit-tests/src/validate-env-names.cjs @@ -26,14 +26,260 @@ function walkDir(dir, fileList = []) { return fileList; } -function findEnvVarsInText(text) { - const regex = /(VITE_APP_[A-Z0-9_]+|VITE_COMMON_[A-Z0-9_]+)/g; +function skipQuotedString(text, startIndex, quote) { + let i = startIndex + 1; + while (i < text.length) { + if (text[i] === '\\') { + i += 2; + continue; + } + if (text[i] === quote) { + return i + 1; + } + i += 1; + } + return i; +} + +function skipTemplateExpression(text, startIndex, ranges) { + let i = startIndex; + let depth = 1; + while (i < text.length && depth > 0) { + const ch = text[i]; + const next = text[i + 1]; + + if (ch === "'" || ch === '"') { + i = skipQuotedString(text, i, ch); + continue; + } + + if (ch === '`') { + i = skipTemplateLiteral(text, i, ranges); + continue; + } + + if (ch === '/' && next === '/') { + i += 2; + while (i < text.length && text[i] !== '\n') i++; + continue; + } + + if (ch === '/' && next === '*') { + i += 2; + while (i < text.length && !(text[i] === '*' && text[i + 1] === '/')) i++; + i = Math.min(i + 2, text.length); + continue; + } + + if (ch === '{') { + depth += 1; + i += 1; + continue; + } + + if (ch === '}') { + depth -= 1; + i += 1; + continue; + } + + if (ch === '\\') { + i += 2; + continue; + } + + i += 1; + } + return i; +} + +function skipTemplateLiteral(text, startIndex, ranges) { + let i = startIndex + 1; + let literalStart = i; + while (i < text.length) { + if (text[i] === '\\') { + i += 2; + continue; + } + + if (text[i] === '$' && text[i + 1] === '{') { + // Mark template literal text (non-expression) as ignored before scanning the expression + if (i > literalStart) { + ranges.push([literalStart, i]); + } + // Skip the ${...} expression but do NOT add it to ignored ranges + // so env-var access inside the expression is detected + i = skipTemplateExpression(text, i + 2, ranges); + literalStart = i; + continue; + } + + if (text[i] === '`') { + // Mark final template literal text as ignored + if (i > literalStart) { + ranges.push([literalStart, i]); + } + return i + 1; + } + + i += 1; + } + // Mark any remaining template literal text as ignored + if (i > literalStart) { + ranges.push([literalStart, i]); + } + return i; +} + +function getIgnoredRanges(text) { + const ranges = []; + let i = 0; + while (i < text.length) { + const ch = text[i]; + const next = text[i + 1]; + + if (ch === '/' && next === '/') { + const start = i; + i += 2; + while (i < text.length && text[i] !== '\n') i++; + ranges.push([start, i]); + continue; + } + + if (ch === '/' && next === '*') { + const start = i; + i += 2; + while (i < text.length && !(text[i] === '*' && text[i + 1] === '/')) i++; + i = Math.min(i + 2, text.length); + ranges.push([start, i]); + continue; + } + + if (ch === "'" || ch === '"') { + const start = i; + i = skipQuotedString(text, i, ch); + ranges.push([start, i]); + continue; + } + + if (ch === '`') { + i = skipTemplateLiteral(text, i, ranges); + continue; + } + + i += 1; + } + return ranges; +} + +function isIgnoredIndex(index, ranges) { + return ranges.some(([start, end]) => index >= start && index < end); +} + +function computeNewlineOffsets(text) { + const offsets = []; + for (let i = 0; i < text.length; i++) { + if (text[i] === '\n') { + offsets.push(i); + } + } + return offsets; +} + +function getLineNumber(newlineOffsets, index) { + // Binary search to find which line the index falls on + let left = 0; + let right = newlineOffsets.length; + while (left < right) { + const mid = Math.floor((left + right) / 2); + if (newlineOffsets[mid] <= index) { + left = mid + 1; + } else { + right = mid; + } + } + return left + 1; // Line numbers are 1-indexed +} + +function findEnvVarsInText(text, filePath) { const matches = []; - let match = regex.exec(text); - while (match !== null) { - matches.push({ match: match[0], index: match.index }); - match = regex.exec(text); + // Handle both POSIX (/) and Windows (\) path separators for cross-platform compatibility + const isEnvFile = filePath.includes('.env') && (/(^|\/)\.env(\.|$)/.test(filePath) || /(^|\\)\.env(\.|$)/.test(filePath)); + if (isEnvFile) { + const re = /^(VITE_[A-Z0-9_]+)\s*=/gm; + let match = re.exec(text); + while (match) { + matches.push({ match: match[1], index: match.index }); + match = re.exec(text); + } + return matches; + } + + const ignoredRanges = getIgnoredRanges(text); + const pushMatch = (value, index) => { + if (!value.startsWith('VITE_')) return; + if (isIgnoredIndex(index, ignoredRanges)) return; + matches.push({ match: value, index }); + }; + + let re = /import\.meta\.env\.([A-Z_][A-Z0-9_]*)/g; + let match = re.exec(text); + while (match) { + pushMatch(match[1], match.index); + match = re.exec(text); } + + re = /import\.meta\.env\[['"]([^'"]+)['"]\]/g; + match = re.exec(text); + while (match) { + pushMatch(match[1], match.index); + match = re.exec(text); + } + + re = /const\s*\{([^}]*)\}\s*=\s*import\.meta\.env/g; + match = re.exec(text); + while (match) { + if (!isIgnoredIndex(match.index, ignoredRanges)) { + const innerRe = /\b(VITE_[A-Z0-9_]+)\b/g; + let innerMatch = innerRe.exec(match[1]); + while (innerMatch) { + const innerIndex = match.index + match[0].indexOf(match[1]) + innerMatch.index; + pushMatch(innerMatch[1], innerIndex); + innerMatch = innerRe.exec(match[1]); + } + } + match = re.exec(text); + } + + re = /process\.env\.([A-Z_][A-Z0-9_]*)/g; + match = re.exec(text); + while (match) { + pushMatch(match[1], match.index); + match = re.exec(text); + } + + re = /process\.env\[['"]([^'"]+)['"]\]/g; + match = re.exec(text); + while (match) { + pushMatch(match[1], match.index); + match = re.exec(text); + } + + // Fallback text scan for config files (json, yml, yaml, txt) + // These files may contain VITE_* as plain string values, not code patterns. + // Do not filter by ignoredRanges since VITE_* tokens inside config values are valid. + const isConfigFile = /\.(json|ya?ml|txt)$/i.test(filePath); + if (isConfigFile) { + re = /\b(VITE_[A-Z0-9_]+)\b/g; + match = re.exec(text); + while (match) { + if (match[1].startsWith('VITE_')) { + matches.push({ match: match[1], index: match.index }); + } + match = re.exec(text); + } + } + return matches; } @@ -50,11 +296,11 @@ function validateEnvNames(options = {}) { if (!fs.existsSync(d)) continue; const stat = fs.statSync(d); if (stat.isFile()) { - if (/\.(yml|yaml|env|json|tsx?|jsx?|cjs|mjs|txt)$/i.test(d) || /\/\.env(\..+)?$/.test(d)) filesToScan.add(d); + if (/\.(yml|yaml|env|json|tsx?|jsx?|cjs|mjs|txt)$/i.test(d) || /(^|[\\/])\.env(\..+)?$/.test(d)) filesToScan.add(d); continue; } for (const f of walkDir(d)) { - if (/\.(yml|yaml|env|json|tsx?|jsx?|cjs|mjs|txt)$/i.test(f) || /\/\.env(\..+)?$/.test(f)) { + if (/\.(yml|yaml|env|json|tsx?|jsx?|cjs|mjs|txt)$/i.test(f) || /(^|[\\/])\.env(\..+)?$/.test(f)) { filesToScan.add(f); } } @@ -68,51 +314,61 @@ function validateEnvNames(options = {}) { } catch { continue; } - const lines = text.split(/\r?\n/); - for (let i = 0; i < lines.length; i++) { - const line = lines[i]; - const matches = findEnvVarsInText(line); - for (const m of matches) { - const variable = m.match; - let portal = 'UNKNOWN'; - let ownerGroup = 'unknown'; - let status = 'compliant'; - if (variable.startsWith('VITE_APP_')) { - // extract portal name between VITE_APP_ and next _ - const rest = variable.replace('VITE_APP_', ''); - const parts = rest.split('_'); - let portalSegment = parts[0]; - // handle UI_COMMUNITY and UI_STAFF which start with UI_ - if (parts[0] === 'UI' && parts.length > 1) { - portalSegment = `${parts[0]}_${parts[1]}`; - } - if (portalSegment === 'UI_COMMUNITY') { - portal = 'UI_COMMUNITY'; - ownerGroup = 'ocm-app-ui-community'; - } else if (portalSegment === 'UI_STAFF') { - portal = 'UI_STAFF'; - ownerGroup = 'ocm-app-ui-staff'; - } else { - portal = portalSegment; - ownerGroup = `ocm-app-${portalSegment.toLowerCase()}`; - // unknown portal treated as non_compliant - status = 'non_compliant'; - } - } else if (variable.startsWith('VITE_COMMON_')) { - portal = 'COMMON'; - ownerGroup = 'ocm-common'; - } else { - status = 'non_compliant'; - } - + const matches = findEnvVarsInText(text, filePath); + const newlineOffsets = computeNewlineOffsets(text); + for (const m of matches) { + const variable = m.match; + const relPath = `${path.relative(rootDir, filePath)}:${getLineNumber(newlineOffsets, m.index)}`; + if (!variable.startsWith('VITE_APP_') && !variable.startsWith('VITE_COMMON_')) { results.push({ variable, - status, - portal, - ownerGroup, - location: `${path.relative(rootDir, filePath)}:${i + 1}`, + status: 'non_compliant', + portal: 'UNKNOWN', + ownerGroup: 'unknown', + location: relPath, + reason: 'Variable does not use VITE_APP__ or VITE_COMMON_ prefix', }); + continue; + } + let portal = 'UNKNOWN'; + let ownerGroup = 'unknown'; + let status = 'compliant'; + let reason; + if (variable.startsWith('VITE_APP_')) { + // extract portal name between VITE_APP_ and next _ + const rest = variable.replace('VITE_APP_', ''); + const parts = rest.split('_'); + let portalSegment = parts[0]; + // handle UI_ style portals which have an underscore in the portal segment + if (parts[0] === 'UI' && parts.length > 1) { + portalSegment = `${parts[0]}_${parts[1]}`; + } + // Check against the single source of truth instead of hard-coding portal names + if (CANONICAL_PORTALS.includes(portalSegment)) { + portal = portalSegment; + // owner groups follow the pattern ocm-app- + ownerGroup = `ocm-app-${portalSegment.toLowerCase().replace(/_/g, '-')}`; + } else { + portal = portalSegment; + ownerGroup = `ocm-app-${portalSegment.toLowerCase().replace(/_/g, '-')}`; + status = 'non_compliant'; + reason = 'Unknown VITE_APP__ value: portal is not registered'; + } + } else if (variable.startsWith('VITE_COMMON_')) { + portal = 'COMMON'; + ownerGroup = 'ocm-common'; + } else { + status = 'non_compliant'; } + + results.push({ + variable, + status, + portal, + ownerGroup, + location: relPath, + ...(reason ? { reason } : {}), + }); } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 134fb2278..9424e7d9c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -121,28 +121,20 @@ overrides: lodash: 4.18.1 lodash-es: 4.18.1 node-forge: ^1.4.0 + node-forge@<1.3.2: '>=1.3.2' picomatch: ^4.0.4 webpack: ^5.105.4 + webpack-dev-server: ^5.2.4 playwright-core: 1.59.0 playwright: 1.59.0 postcss: 8.5.10 protobufjs: 7.5.8 -<<<<<<< HEAD - '@protobufjs/codegen': 2.0.5 - '@protobufjs/utf8': 1.1.1 - ip-address: ^10.1.1 - fast-uri: ^3.1.2 - webpack-dev-server: ^5.2.4 -======= ip-address: ^10.1.1 fast-uri: ^3.1.2 '@babel/plugin-transform-modules-systemjs': 7.29.4 ->>>>>>> daf83d3d9fafaaf8f21f69272226f51c2a3305d7 patchedDependencies: - '@azure/functions@4.11.0': - hash: 69772ce521bf6df67d814ff4f419f19b5e966a41c4ce80b5938143ad628e5645 - path: patches/@azure__functions@4.11.0.patch + '@azure/functions@4.11.0': 69772ce521bf6df67d814ff4f419f19b5e966a41c4ce80b5938143ad628e5645 importers: @@ -224,8 +216,8 @@ importers: specifier: ^1.0.2 version: 1.0.4(typescript@6.0.3) turbo: - specifier: 2.9.3 - version: 2.9.3 + specifier: 2.9.9 + version: 2.9.9 typescript: specifier: 'catalog:' version: 6.0.3 @@ -503,7 +495,7 @@ importers: version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3) '@storybook/react-vite': specifier: ^9.1.3 - version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.59.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) '@testing-library/jest-dom': specifier: ^6.6.4 version: 6.9.1 @@ -527,7 +519,7 @@ importers: version: 26.1.0 rollup-plugin-visualizer: specifier: ^6.0.5 - version: 6.0.5(rolldown@1.0.0-rc.12(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1))(rollup@4.59.0) + version: 6.0.5(rolldown@1.0.0-rc.12(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)) storybook: specifier: 'catalog:' version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) @@ -630,7 +622,7 @@ importers: version: 26.1.0 rollup-plugin-visualizer: specifier: ^6.0.5 - version: 6.0.5(rolldown@1.0.0-rc.12(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1))(rollup@4.59.0) + version: 6.0.5(rolldown@1.0.0-rc.12(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)) tailwindcss: specifier: ^3.4.17 version: 3.4.18(tsx@4.21.0)(yaml@2.8.3) @@ -963,7 +955,7 @@ importers: version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3) '@storybook/react-vite': specifier: ^9.1.3 - version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.59.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) '@testing-library/react': specifier: ^16.3.0 version: 16.3.0(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -1774,7 +1766,7 @@ importers: version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3) '@storybook/react-vite': specifier: ^9.1.3 - version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.59.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) '@types/react': specifier: ^19.1.11 version: 19.2.7 @@ -1862,7 +1854,7 @@ importers: version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3) '@storybook/react-vite': specifier: ^9.1.3 - version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.59.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) '@types/react': specifier: ^19.1.11 version: 19.2.7 @@ -1923,7 +1915,7 @@ importers: version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3) '@storybook/react-vite': specifier: ^9.1.3 - version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.59.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) '@types/react': specifier: ^19.1.11 version: 19.2.7 @@ -2002,7 +1994,7 @@ importers: version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3) '@storybook/react-vite': specifier: ^9.1.3 - version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.59.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) '@types/react': specifier: ^19.1.11 version: 19.2.7 @@ -2081,7 +2073,7 @@ importers: version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3) '@storybook/react-vite': specifier: ^9.1.3 - version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.59.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) '@types/react': specifier: ^19.1.11 version: 19.2.7 @@ -2864,6 +2856,10 @@ packages: resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} engines: {node: '>=6.9.0'} + '@babel/helper-plugin-utils@7.28.6': + resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} + engines: {node: '>=6.9.0'} + '@babel/helper-remap-async-to-generator@7.27.1': resolution: {integrity: sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==} engines: {node: '>=6.9.0'} @@ -3126,8 +3122,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-systemjs@7.28.5': - resolution: {integrity: sha512-vn5Jma98LCOeBy/KpeQhXcV2WZgaRUtjwQmjoBuLNlOmkg0fB5pdvYVeWRYI69wWKwK2cD1QbMiUQnoujWvrew==} + '@babel/plugin-transform-modules-systemjs@7.29.4': + resolution: {integrity: sha512-N7QmZ0xRZfjHOfZeQLJjwgX2zS9pdGHSVl/cjSGlo4dXMqvurfxXDMKY4RqEKzPozV78VMcd0lxyG13mlbKc4w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -5985,144 +5981,6 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.59.0': - resolution: {integrity: sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==} - cpu: [arm] - os: [android] - - '@rollup/rollup-android-arm64@4.59.0': - resolution: {integrity: sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==} - cpu: [arm64] - os: [android] - - '@rollup/rollup-darwin-arm64@4.59.0': - resolution: {integrity: sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==} - cpu: [arm64] - os: [darwin] - - '@rollup/rollup-darwin-x64@4.59.0': - resolution: {integrity: sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==} - cpu: [x64] - os: [darwin] - - '@rollup/rollup-freebsd-arm64@4.59.0': - resolution: {integrity: sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==} - cpu: [arm64] - os: [freebsd] - - '@rollup/rollup-freebsd-x64@4.59.0': - resolution: {integrity: sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==} - cpu: [x64] - os: [freebsd] - - '@rollup/rollup-linux-arm-gnueabihf@4.59.0': - resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==} - cpu: [arm] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-arm-musleabihf@4.59.0': - resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==} - cpu: [arm] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-arm64-gnu@4.59.0': - resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-arm64-musl@4.59.0': - resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-loong64-gnu@4.59.0': - resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==} - cpu: [loong64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-loong64-musl@4.59.0': - resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==} - cpu: [loong64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-ppc64-gnu@4.59.0': - resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==} - cpu: [ppc64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-ppc64-musl@4.59.0': - resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==} - cpu: [ppc64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-riscv64-gnu@4.59.0': - resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==} - cpu: [riscv64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-riscv64-musl@4.59.0': - resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==} - cpu: [riscv64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-s390x-gnu@4.59.0': - resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==} - cpu: [s390x] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-x64-gnu@4.59.0': - resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-x64-musl@4.59.0': - resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==} - cpu: [x64] - os: [linux] - libc: [musl] - - '@rollup/rollup-openbsd-x64@4.59.0': - resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==} - cpu: [x64] - os: [openbsd] - - '@rollup/rollup-openharmony-arm64@4.59.0': - resolution: {integrity: sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==} - cpu: [arm64] - os: [openharmony] - - '@rollup/rollup-win32-arm64-msvc@4.59.0': - resolution: {integrity: sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==} - cpu: [arm64] - os: [win32] - - '@rollup/rollup-win32-ia32-msvc@4.59.0': - resolution: {integrity: sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==} - cpu: [ia32] - os: [win32] - - '@rollup/rollup-win32-x64-gnu@4.59.0': - resolution: {integrity: sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==} - cpu: [x64] - os: [win32] - - '@rollup/rollup-win32-x64-msvc@4.59.0': - resolution: {integrity: sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==} - cpu: [x64] - os: [win32] - '@sentry-internal/tracing@7.120.4': resolution: {integrity: sha512-Fz5+4XCg3akeoFK+K7g+d7HqGMjmnLoY2eJlpONJmaeT9pXY7yfUyXKZMmMajdE2LxxKJgQ2YKvSCaGVamTjHw==} engines: {node: '>=8'} @@ -6448,33 +6306,33 @@ packages: '@ts-morph/common@0.28.1': resolution: {integrity: sha512-W74iWf7ILp1ZKNYXY5qbddNaml7e9Sedv5lvU1V8lftlitkc9Pq1A+jlH23ltDgWYeZFFEqGCD1Ies9hqu3O+g==} - '@turbo/darwin-64@2.9.3': - resolution: {integrity: sha512-P8foouaP+y/p+hhEGBoZpzMbpVvUMwPjDpcy6wN7EYfvvyISD1USuV27qWkczecihwuPJzQ1lDBuL8ERcavTyg==} + '@turbo/darwin-64@2.9.9': + resolution: {integrity: sha512-hTEiNu2ABZZOO1qbjnKASI8eF3BdOOzU6iKv5w5uGOK65DDMc10cS40N1kqM99YT0uSAGUwNu6GdFctRPeEeVA==} cpu: [x64] os: [darwin] - '@turbo/darwin-arm64@2.9.3': - resolution: {integrity: sha512-SIzEkvtNdzdI50FJDaIQ6kQGqgSSdFPcdn0wqmmONN6iGKjy6hsT+EH99GP65FsfV7DLZTh2NmtTIRl2kdoz5Q==} + '@turbo/darwin-arm64@2.9.9': + resolution: {integrity: sha512-MinO40EEcP5mJiTVpfjtEulsEBhVeryfq21QhYtJZ8hQJLHGgy459rcmDVAY8/JERe4dkVU4KW+zoLF22o01EA==} cpu: [arm64] os: [darwin] - '@turbo/linux-64@2.9.3': - resolution: {integrity: sha512-pLRwFmcHHNBvsCySLS6OFabr/07kDT2pxEt/k6eBf/3asiVQZKJ7Rk88AafQx2aYA641qek4RsXvYO3JYpiBug==} + '@turbo/linux-64@2.9.9': + resolution: {integrity: sha512-7JNLw88Isk+gMlbsC8pulLDkrqe2B827ZsKFEHilb17AC6Xn/62pzH7afjY7fEU6Ayp4XP/vGhlRWOzqBvBvIQ==} cpu: [x64] os: [linux] - '@turbo/linux-arm64@2.9.3': - resolution: {integrity: sha512-gy6ApUroC2Nzv+qjGtE/uPNkhHAFU4c8God+zd5Aiv9L9uBgHlxVJpHT3XWl5xwlJZ2KWuMrlHTaS5kmNB+q1Q==} + '@turbo/linux-arm64@2.9.9': + resolution: {integrity: sha512-0pnXDwPw1rHii98JZPRg7SvsjIzy7jrhkwGU9Jy5fVYoMdYd3P2vbtLfII+OJ0Mm4Ar5yykdHDTz3RWiRI1o9g==} cpu: [arm64] os: [linux] - '@turbo/windows-64@2.9.3': - resolution: {integrity: sha512-d0YelTX6hAsB7kIEtGB3PzIzSfAg3yDoUlHwuwJc3adBXUsyUIs0YLG+1NNtuhcDOUGnWQeKUoJ2pGWvbpRj7w==} + '@turbo/windows-64@2.9.9': + resolution: {integrity: sha512-vjDQycz4gQVvIq4n2rPtiiIESwJlAc406qtkiZlqyL+fHZEd9SxYNlBIFYtc5cuMuwrk+sIKrhN7XvwjmvS9YQ==} cpu: [x64] os: [win32] - '@turbo/windows-arm64@2.9.3': - resolution: {integrity: sha512-/08CwpKJl3oRY8nOlh2YgilZVJDHsr60XTNxRhuDeuFXONpUZ5X+Nv65izbG/xBew9qxcJFbDX9/sAmAX+ITcQ==} + '@turbo/windows-arm64@2.9.9': + resolution: {integrity: sha512-V6NiH43oCctepbOdQFp7UjqLyK8p6Tt824QA+G4TE+B1BBHu80A0W8OCL+H7uBJ3XZjAj/hvPDw3k3l65DoDGw==} cpu: [arm64] os: [win32] @@ -6760,6 +6618,7 @@ packages: '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + deprecated: Potential CWE-502 - Update to 1.3.1 or higher '@vercel/oidc@3.0.5': resolution: {integrity: sha512-fnYhv671l+eTTp48gB4zEsTW/YtRgRPnkI2nT7x6qw5rkI1Lq2hTmQIpHPgyThI0znLK+vX2n9XxKdXZ7BUbbw==} @@ -8188,6 +8047,7 @@ packages: dottie@2.0.6: resolution: {integrity: sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. dset@3.1.4: resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==} @@ -11714,11 +11574,6 @@ packages: rollup: optional: true - rollup@4.59.0: - resolution: {integrity: sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - rrweb-cssom@0.8.0: resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} @@ -12601,8 +12456,8 @@ packages: resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} - turbo@2.9.3: - resolution: {integrity: sha512-J/VUvsGRykPb9R8Kh8dHVBOqioDexLk9BhLCU/ZybRR+HN9UR3cURdazFvNgMDt9zPP8TF6K73Z+tplfmi0PqQ==} + turbo@2.9.9: + resolution: {integrity: sha512-3xfzXE/yTjhh0S5dIWlE+3E+J9A09REpLI1ZqVh2+HrNZoVzZn0pkvjiRgVK/Ev3PF9XnaTwCntTx+CADWXcyA==} hasBin: true type-fest@0.13.1: @@ -12833,7 +12688,7 @@ packages: uuid@3.4.0: resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} - deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true uuid@8.3.2: @@ -13414,7 +13269,7 @@ snapshots: minimist: 1.2.8 parsecurrency: 1.1.1 ts-morph: 27.0.2 - vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@22.19.15)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) '@ant-design/cli@6.3.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)': dependencies: @@ -14051,6 +13906,8 @@ snapshots: '@babel/helper-plugin-utils@7.27.1': {} + '@babel/helper-plugin-utils@7.28.6': {} + '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 @@ -14337,11 +14194,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-systemjs@7.28.5(@babel/core@7.29.0)': + '@babel/plugin-transform-modules-systemjs@7.29.4(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-validator-identifier': 7.28.5 '@babel/traverse': 7.29.0 transitivePeerDependencies: @@ -14600,7 +14457,7 @@ snapshots: '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.29.0) '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.29.0) '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-modules-systemjs': 7.28.5(@babel/core@7.29.0) + '@babel/plugin-transform-modules-systemjs': 7.29.4(@babel/core@7.29.0) '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.29.0) '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.29.0) '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.29.0) @@ -18050,88 +17907,11 @@ snapshots: '@rolldown/pluginutils@1.0.0-rc.7': {} - '@rollup/pluginutils@5.3.0(rollup@4.59.0)': + '@rollup/pluginutils@5.3.0': dependencies: '@types/estree': 1.0.8 estree-walker: 2.0.2 picomatch: 4.0.4 - optionalDependencies: - rollup: 4.59.0 - - '@rollup/rollup-android-arm-eabi@4.59.0': - optional: true - - '@rollup/rollup-android-arm64@4.59.0': - optional: true - - '@rollup/rollup-darwin-arm64@4.59.0': - optional: true - - '@rollup/rollup-darwin-x64@4.59.0': - optional: true - - '@rollup/rollup-freebsd-arm64@4.59.0': - optional: true - - '@rollup/rollup-freebsd-x64@4.59.0': - optional: true - - '@rollup/rollup-linux-arm-gnueabihf@4.59.0': - optional: true - - '@rollup/rollup-linux-arm-musleabihf@4.59.0': - optional: true - - '@rollup/rollup-linux-arm64-gnu@4.59.0': - optional: true - - '@rollup/rollup-linux-arm64-musl@4.59.0': - optional: true - - '@rollup/rollup-linux-loong64-gnu@4.59.0': - optional: true - - '@rollup/rollup-linux-loong64-musl@4.59.0': - optional: true - - '@rollup/rollup-linux-ppc64-gnu@4.59.0': - optional: true - - '@rollup/rollup-linux-ppc64-musl@4.59.0': - optional: true - - '@rollup/rollup-linux-riscv64-gnu@4.59.0': - optional: true - - '@rollup/rollup-linux-riscv64-musl@4.59.0': - optional: true - - '@rollup/rollup-linux-s390x-gnu@4.59.0': - optional: true - - '@rollup/rollup-linux-x64-gnu@4.59.0': - optional: true - - '@rollup/rollup-linux-x64-musl@4.59.0': - optional: true - - '@rollup/rollup-openbsd-x64@4.59.0': - optional: true - - '@rollup/rollup-openharmony-arm64@4.59.0': - optional: true - - '@rollup/rollup-win32-arm64-msvc@4.59.0': - optional: true - - '@rollup/rollup-win32-ia32-msvc@4.59.0': - optional: true - - '@rollup/rollup-win32-x64-gnu@4.59.0': - optional: true - - '@rollup/rollup-win32-x64-msvc@4.59.0': - optional: true '@sentry-internal/tracing@7.120.4': dependencies: @@ -18367,10 +18147,10 @@ snapshots: react-dom: 19.2.0(react@19.2.0) storybook: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@storybook/react-vite@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.59.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': + '@storybook/react-vite@9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@joshwooding/vite-plugin-react-docgen-typescript': 0.6.1(typescript@6.0.3)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@rollup/pluginutils': 5.3.0(rollup@4.59.0) + '@rollup/pluginutils': 5.3.0 '@storybook/builder-vite': 9.1.16(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) '@storybook/react': 9.1.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)))(typescript@6.0.3) find-up: 7.0.0 @@ -18546,22 +18326,22 @@ snapshots: path-browserify: 1.0.1 tinyglobby: 0.2.15 - '@turbo/darwin-64@2.9.3': + '@turbo/darwin-64@2.9.9': optional: true - '@turbo/darwin-arm64@2.9.3': + '@turbo/darwin-arm64@2.9.9': optional: true - '@turbo/linux-64@2.9.3': + '@turbo/linux-64@2.9.9': optional: true - '@turbo/linux-arm64@2.9.3': + '@turbo/linux-arm64@2.9.9': optional: true - '@turbo/windows-64@2.9.3': + '@turbo/windows-64@2.9.9': optional: true - '@turbo/windows-arm64@2.9.3': + '@turbo/windows-arm64@2.9.9': optional: true '@tybys/wasm-util@0.10.1': @@ -18950,7 +18730,7 @@ snapshots: magicast: 0.5.2 obug: 2.1.1 tinyrainbow: 3.1.0 - vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@22.19.15)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) transitivePeerDependencies: - supports-color @@ -24774,7 +24554,7 @@ snapshots: - '@emnapi/core' - '@emnapi/runtime' - rollup-plugin-visualizer@6.0.5(rolldown@1.0.0-rc.12(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1))(rollup@4.59.0): + rollup-plugin-visualizer@6.0.5(rolldown@1.0.0-rc.12(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)): dependencies: open: 8.4.2 picomatch: 4.0.4 @@ -24782,39 +24562,6 @@ snapshots: yargs: 17.7.2 optionalDependencies: rolldown: 1.0.0-rc.12(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1) - rollup: 4.59.0 - - rollup@4.59.0: - dependencies: - '@types/estree': 1.0.8 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.59.0 - '@rollup/rollup-android-arm64': 4.59.0 - '@rollup/rollup-darwin-arm64': 4.59.0 - '@rollup/rollup-darwin-x64': 4.59.0 - '@rollup/rollup-freebsd-arm64': 4.59.0 - '@rollup/rollup-freebsd-x64': 4.59.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.59.0 - '@rollup/rollup-linux-arm-musleabihf': 4.59.0 - '@rollup/rollup-linux-arm64-gnu': 4.59.0 - '@rollup/rollup-linux-arm64-musl': 4.59.0 - '@rollup/rollup-linux-loong64-gnu': 4.59.0 - '@rollup/rollup-linux-loong64-musl': 4.59.0 - '@rollup/rollup-linux-ppc64-gnu': 4.59.0 - '@rollup/rollup-linux-ppc64-musl': 4.59.0 - '@rollup/rollup-linux-riscv64-gnu': 4.59.0 - '@rollup/rollup-linux-riscv64-musl': 4.59.0 - '@rollup/rollup-linux-s390x-gnu': 4.59.0 - '@rollup/rollup-linux-x64-gnu': 4.59.0 - '@rollup/rollup-linux-x64-musl': 4.59.0 - '@rollup/rollup-openbsd-x64': 4.59.0 - '@rollup/rollup-openharmony-arm64': 4.59.0 - '@rollup/rollup-win32-arm64-msvc': 4.59.0 - '@rollup/rollup-win32-ia32-msvc': 4.59.0 - '@rollup/rollup-win32-x64-gnu': 4.59.0 - '@rollup/rollup-win32-x64-msvc': 4.59.0 - fsevents: 2.3.3 - optional: true rrweb-cssom@0.8.0: {} @@ -25737,14 +25484,14 @@ snapshots: tunnel@0.0.6: {} - turbo@2.9.3: + turbo@2.9.9: optionalDependencies: - '@turbo/darwin-64': 2.9.3 - '@turbo/darwin-arm64': 2.9.3 - '@turbo/linux-64': 2.9.3 - '@turbo/linux-arm64': 2.9.3 - '@turbo/windows-64': 2.9.3 - '@turbo/windows-arm64': 2.9.3 + '@turbo/darwin-64': 2.9.9 + '@turbo/darwin-arm64': 2.9.9 + '@turbo/linux-64': 2.9.9 + '@turbo/linux-arm64': 2.9.9 + '@turbo/windows-64': 2.9.9 + '@turbo/windows-arm64': 2.9.9 type-fest@0.13.1: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 3926155f9..0f60fa11e 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -4,6 +4,8 @@ packages: - "packages/ocom/*" - "packages/ocom-verification/*" +engineStrict: true + catalog: '@apollo/server': 5.5.0 '@azure/functions': 4.11.0 @@ -37,5 +39,59 @@ catalog: vite: 8.0.5 vitest: 4.1.2 +auditConfig: + ignoreGhsas: + - GHSA-6rw7-vpxm-498p + - GHSA-2w69-qvjg-hvjx + - GHSA-8v8x-cx79-35w7 + - GHSA-wpg9-53fq-2r8h + - GHSA-q7rr-3cgh-j5r3 + +allowBuilds: + '@apollo/protobufjs': true + '@parcel/watcher': true + core-js: true + core-js-pure: true + esbuild: true + mongodb-memory-server: true + protobufjs: true + snyk: true + overrides: + axios: 1.15.2 + follow-redirects: ^1.16.0 + vite: "catalog:" + jiti: 2.6.1 + rollup: ^4.59.0 + '@ant-design/pro-layout>path-to-regexp': ^8.4.0 + 'brace-expansion@1.1.12': 1.1.13 + 'brace-expansion@5.0.4': 5.0.5 + 'diff@4.0.2': 4.0.4 + '@protobufjs/codegen': 2.0.5 + '@protobufjs/utf8': 1.1.1 + 'protobufjs@7.5.4': 7.5.8 + 'serve-handler>minimatch': 3.1.5 + 'serialize-javascript@6.0.2': 7.0.5 + 'serialize-javascript@7.0.4': 7.0.5 + svgo: ^3.3.3 + 'yaml@2.8.2': 2.8.3 + 'yauzl@3.2.0': 3.2.1 + qs: ^6.14.2 + 'ajv@^6': 6.14.0 + lodash: 4.18.1 + lodash-es: 4.18.1 + node-forge: ^1.4.0 node-forge@<1.3.2: '>=1.3.2' + picomatch: ^4.0.4 + webpack: ^5.105.4 + webpack-dev-server: ^5.2.4 + playwright-core: 1.59.0 + playwright: 1.59.0 + postcss: 8.5.10 + protobufjs: 7.5.8 + ip-address: ^10.1.1 + fast-uri: ^3.1.2 + '@babel/plugin-transform-modules-systemjs': 7.29.4 + +patchedDependencies: + '@azure/functions@4.11.0': patches/@azure__functions@4.11.0.patch diff --git a/readme.md b/readme.md index 4e7120b14..7f0e592c1 100644 --- a/readme.md +++ b/readme.md @@ -26,6 +26,7 @@ Our Docusaurus website will help you get started in running and contributing to ## Developer usage + - Full local dev (builds, starts the portless HTTPS proxy, starts Azurite, and runs the app-level dev servers): ```bash @@ -366,3 +367,4 @@ Have feedback? Leave a comment in [CellixJS discussions on GitHub](https://githu [![sharethrift contributors](https://contrib.rocks/image?repo=cellixjs/cellixjs)](https://github.com/cellixjs/cellixjs/graphs/contributors) [⬆ Back to Top](#table-of-contents) + From de9ecf94b42aea0996f5d183ada466bf0ed432f6 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Fri, 15 May 2026 19:58:19 +0530 Subject: [PATCH 82/88] Fix knip issues --- .../src/contexts/user/staff-role/create-default-roles.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts index 12bf561fd..ed28e09e0 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts @@ -9,7 +9,7 @@ export const StaffAppRoleNames = { TechAdmin: 'Default.TechAdmin', } as const; -export type StaffAppRoleName = (typeof StaffAppRoleNames)[keyof typeof StaffAppRoleNames]; +type StaffAppRoleName = (typeof StaffAppRoleNames)[keyof typeof StaffAppRoleNames]; type StaffRoleRepo = Domain.Contexts.User.StaffRole.StaffRoleRepository; From a2876666579425e93c865038d713867c5f4f79fc Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Sat, 16 May 2026 01:42:59 +0530 Subject: [PATCH 83/88] refactor: update staff role handling and remove unused queries in community list --- .../user/staff-role/create-default-roles.ts | 76 ++++++++----------- .../src/models/role/staff-role.model.ts | 4 +- .../domain/contexts/user/staff-role/index.ts | 1 + .../contexts/user/staff-role/staff-role.ts | 15 ++++ .../staff-role/staff-role.value-objects.ts | 11 ++- .../staff-role/staff-role.domain-adapter.ts | 8 ++ .../community-list.container.graphql | 12 --- .../components/community-list.container.tsx | 5 -- .../src/components/community-list.tsx | 3 - 9 files changed, 68 insertions(+), 67 deletions(-) diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts index ed28e09e0..15a4908ae 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts @@ -1,55 +1,45 @@ -import type { Domain } from '@ocom/domain'; -import { Domain as DomainRuntime } from '@ocom/domain'; +import { Domain } from '@ocom/domain'; import type { DataSources } from '@ocom/persistence'; -export const StaffAppRoleNames = { - CaseManager: 'Default.CaseManager', - ServiceLineOwner: 'Default.ServiceLineOwner', - Finance: 'Default.Finance', - TechAdmin: 'Default.TechAdmin', -} as const; - -type StaffAppRoleName = (typeof StaffAppRoleNames)[keyof typeof StaffAppRoleNames]; - type StaffRoleRepo = Domain.Contexts.User.StaffRole.StaffRoleRepository; -const roleExists = async (repository: StaffRoleRepo, roleName: string): Promise => { - try { - await repository.getByRoleName(roleName); - return true; - } catch (error) { - if (error instanceof Error && (error.name === 'NotFoundError' || error.message.toLowerCase().includes('not found'))) { - return false; - } - throw error; - } +const roleExists = async (repository: StaffRoleRepo, enterpriseAppRole: string): Promise => { + try { + await repository.getDefaultRoleByEnterpriseAppRole(enterpriseAppRole); + return true; + } catch (error) { + if (error instanceof Error && (error.name === 'NotFoundError' || error.message.toLowerCase().includes('not found'))) { + return false; + } + throw error; + } }; const roleDefinitions: ReadonlyArray<{ - roleName: StaffAppRoleName; - factory: (repo: StaffRoleRepo) => Promise>; + enterpriseAppRole: string; + factory: (repo: StaffRoleRepo) => Promise>; }> = [ - { roleName: StaffAppRoleNames.CaseManager, factory: (repo) => repo.getNewDefaultCaseManagerInstance() }, - { roleName: StaffAppRoleNames.ServiceLineOwner, factory: (repo) => repo.getNewDefaultServiceLineOwnerInstance() }, - { roleName: StaffAppRoleNames.Finance, factory: (repo) => repo.getNewDefaultFinanceInstance() }, - { roleName: StaffAppRoleNames.TechAdmin, factory: (repo) => repo.getNewDefaultTechAdminInstance() }, + { enterpriseAppRole: Domain.Contexts.User.StaffRole.StaffRoleValueObjects.EnterpriseAppRoleNames.CaseManager, factory: (repo) => repo.getNewDefaultCaseManagerInstance() }, + { enterpriseAppRole: Domain.Contexts.User.StaffRole.StaffRoleValueObjects.EnterpriseAppRoleNames.ServiceLineOwner, factory: (repo) => repo.getNewDefaultServiceLineOwnerInstance() }, + { enterpriseAppRole: Domain.Contexts.User.StaffRole.StaffRoleValueObjects.EnterpriseAppRoleNames.Finance, factory: (repo) => repo.getNewDefaultFinanceInstance() }, + { enterpriseAppRole: Domain.Contexts.User.StaffRole.StaffRoleValueObjects.EnterpriseAppRoleNames.TechAdmin, factory: (repo) => repo.getNewDefaultTechAdminInstance() }, ]; export const createDefaultRoles = (dataSources: DataSources) => { - return async (): Promise => { - const systemPassport = DomainRuntime.PassportFactory.forSystem({ canManageStaffRolesAndPermissions: true }); - const created: Domain.Contexts.User.StaffRole.StaffRoleEntityReference[] = []; - - for (const { roleName, factory } of roleDefinitions) { - let saved: Domain.Contexts.User.StaffRole.StaffRoleEntityReference | undefined; - await dataSources.domainDataSource.User.StaffRole.StaffRoleUnitOfWork.withTransaction(systemPassport, async (repository) => { - if (await roleExists(repository, roleName)) return; - const role = await factory(repository); - saved = await repository.save(role); - }); - if (saved) created.push(saved); - } - - return created; - }; + return async (): Promise => { + const systemPassport = Domain.PassportFactory.forSystem({ canManageStaffRolesAndPermissions: true }); + const created: Domain.Contexts.User.StaffRole.StaffRoleEntityReference[] = []; + + for (const { enterpriseAppRole, factory } of roleDefinitions) { + let saved: Domain.Contexts.User.StaffRole.StaffRoleEntityReference | undefined; + await dataSources.domainDataSource.User.StaffRole.StaffRoleUnitOfWork.withTransaction(systemPassport, async (repository) => { + if (await roleExists(repository, enterpriseAppRole)) return; + const role = await factory(repository); + saved = await repository.save(role); + }); + if (saved) created.push(saved); + } + + return created; + }; }; diff --git a/packages/ocom/data-sources-mongoose-models/src/models/role/staff-role.model.ts b/packages/ocom/data-sources-mongoose-models/src/models/role/staff-role.model.ts index fd4ab056f..da291d9ed 100644 --- a/packages/ocom/data-sources-mongoose-models/src/models/role/staff-role.model.ts +++ b/packages/ocom/data-sources-mongoose-models/src/models/role/staff-role.model.ts @@ -159,9 +159,7 @@ const StaffRoleSchema = new Schema, StaffRole>( enterpriseAppRole: { type: String, required: true, - default(this: StaffRole) { - return this.roleName; - }, + enum: StaffEnterpriseAppRoles, }, isDefault: { type: Boolean, required: true, default: false }, }, diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/index.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/index.ts index c049103f8..0724acbd8 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/index.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/index.ts @@ -5,6 +5,7 @@ export type { } from './staff-role.ts'; export { StaffRole } from './staff-role.ts'; export type { StaffRoleUnitOfWork } from './staff-role.uow.ts'; +export * as StaffRoleValueObjects from './staff-role.value-objects.ts'; export type { StaffRoleCommunityPermissionsEntityReference, StaffRoleCommunityPermissionsProps, diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts index b098a4759..5ccfb8c82 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts @@ -10,6 +10,7 @@ import { StaffRolePermissions, type StaffRolePermissionsEntityReference, type St export interface StaffRoleProps extends DomainEntityProps { roleName: string; isDefault: boolean; + enterpriseAppRole: string; readonly permissions: StaffRolePermissionsProps; readonly roleType: string | null; readonly createdAt: Date; @@ -50,6 +51,7 @@ export class StaffRole extends AggregateRoot extends AggregateRoot extends AggregateRoot permissions.canManageStaffRolesAndPermissions || permissions.isSystemAccount)) { + throw new PermissionError('Cannot set enterprise app role'); + } + this.props.enterpriseAppRole = new ValueObjects.EnterpriseAppRole(enterpriseAppRole).valueOf(); + } + get isDefault() { return this.props.isDefault; } diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.value-objects.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.value-objects.ts index 3a4a42e28..c683809e2 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.value-objects.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.value-objects.ts @@ -1,7 +1,16 @@ -import { VOString } from '@lucaspaganini/value-objects'; +import { VOString, VOSet } from '@lucaspaganini/value-objects'; export class RoleName extends VOString({ trim: true, maxLength: 50, minLength: 1, }) {} + +export const EnterpriseAppRoleNames = { + CaseManager: 'Staff.CaseManager', + ServiceLineOwner: 'Staff.ServiceLineOwner', + Finance: 'Staff.Finance', + TechAdmin: 'Staff.TechAdmin', +} as const; + +export class EnterpriseAppRole extends VOSet(Object.values(EnterpriseAppRoleNames)) {} \ No newline at end of file diff --git a/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.ts b/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.ts index ab10363a7..0884c86b8 100644 --- a/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.ts +++ b/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.domain-adapter.ts @@ -29,6 +29,14 @@ export class StaffRoleDomainAdapter extends MongooseSeedwork.MongooseDomainAdapt this.doc.enterpriseAppRole = roleName; } + get enterpriseAppRole(): string { + return this.doc.enterpriseAppRole ?? ''; + } + + set enterpriseAppRole(enterpriseAppRole: string) { + this.doc.enterpriseAppRole = enterpriseAppRole; + } + get isDefault(): boolean { return this.doc.isDefault; } diff --git a/packages/ocom/ui-community-route-accounts/src/components/community-list.container.graphql b/packages/ocom/ui-community-route-accounts/src/components/community-list.container.graphql index 808f658a4..70e350053 100644 --- a/packages/ocom/ui-community-route-accounts/src/components/community-list.container.graphql +++ b/packages/ocom/ui-community-route-accounts/src/components/community-list.container.graphql @@ -10,18 +10,6 @@ query AccountsCommunityListContainerMembersForCurrentEndUser { } } -query AccountsCommunityListContainerCurrentStaffUser { - currentStaffUserAndCreateIfNotExists { - role { - permissions { - communityPermissions { - canManageCommunities - } - } - } - } -} - fragment AccountsCommunityListContainerMemberFields on Member { memberName community { diff --git a/packages/ocom/ui-community-route-accounts/src/components/community-list.container.tsx b/packages/ocom/ui-community-route-accounts/src/components/community-list.container.tsx index e7df386a8..019795b72 100644 --- a/packages/ocom/ui-community-route-accounts/src/components/community-list.container.tsx +++ b/packages/ocom/ui-community-route-accounts/src/components/community-list.container.tsx @@ -2,7 +2,6 @@ import { useQuery } from '@apollo/client'; import { ComponentQueryLoader } from '@cellix/ui-core'; import { AccountsCommunityListContainerCommunitiesForCurrentEndUserDocument, - AccountsCommunityListContainerCurrentStaffUserDocument, type AccountsCommunityListContainerCommunityFieldsFragment, type AccountsCommunityListContainerMemberFieldsFragment, AccountsCommunityListContainerMembersForCurrentEndUserDocument, @@ -20,9 +19,6 @@ export const CommunityListContainer: React.FC = () => { fetchPolicy: 'network-only', }); - const { data: staffUserData } = useQuery(AccountsCommunityListContainerCurrentStaffUserDocument); - const canCreateCommunity = staffUserData?.currentStaffUserAndCreateIfNotExists?.role?.permissions?.communityPermissions?.canManageCommunities ?? false; - const members: AccountsCommunityListContainerMemberFieldsFragment[][] = []; if (membersData?.membersForCurrentEndUser && membersData?.membersForCurrentEndUser.length > 0 && communityData?.communitiesForCurrentEndUser) { for (const community of communityData.communitiesForCurrentEndUser) { @@ -40,7 +36,6 @@ export const CommunityListContainer: React.FC = () => { communities: communityData?.communitiesForCurrentEndUser as AccountsCommunityListContainerCommunityFieldsFragment[], members: members as AccountsCommunityListContainerMemberFieldsFragment[][], }} - canCreateCommunity={canCreateCommunity} /> } noDataComponent={
    No Data...
    } diff --git a/packages/ocom/ui-community-route-accounts/src/components/community-list.tsx b/packages/ocom/ui-community-route-accounts/src/components/community-list.tsx index 40f2c5125..901ed7afc 100644 --- a/packages/ocom/ui-community-route-accounts/src/components/community-list.tsx +++ b/packages/ocom/ui-community-route-accounts/src/components/community-list.tsx @@ -11,7 +11,6 @@ export interface CommunityListProps { communities: AccountsCommunityListContainerCommunityFieldsFragment[]; members: AccountsCommunityListContainerMemberFieldsFragment[][]; }; - canCreateCommunity?: boolean; } export const CommunityList: React.FC = (props) => { @@ -120,14 +119,12 @@ export const CommunityList: React.FC = (props) => {

    Navigate to a Community

    - {props.canCreateCommunity && ( - )}
    Date: Fri, 15 May 2026 16:52:42 -0400 Subject: [PATCH 84/88] remove uuid and add enterpriseAppRole for finance and techAdmin --- .../user/staff-role/create-default-roles.ts | 2 +- .../contexts/user/staff-role/staff-role.ts | 2 + pnpm-lock.yaml | 50 ++++++++++++++----- pnpm-workspace.yaml | 1 - 4 files changed, 41 insertions(+), 14 deletions(-) diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts index 15a4908ae..8d90dce77 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts @@ -42,4 +42,4 @@ export const createDefaultRoles = (dataSources: DataSources) => { return created; }; -}; +}; \ No newline at end of file diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts index 5ccfb8c82..1ddc8b440 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts @@ -79,6 +79,7 @@ export class StaffRole extends AggregateRoot extends AggregateRoot= 0.4.0'} - uuid@14.0.0: - resolution: {integrity: sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==} + uuid@10.0.0: + resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). + hasBin: true + + uuid@11.0.5: + resolution: {integrity: sha512-508e6IcKLrhxKdBbcA2b4KQZlLVp2+J5UwQ6F7Drckkc5N9ZJwFa4TgWtsww9UG8fGHbm6gbV19TdM5pQ4GaIA==} + hasBin: true + + uuid@11.1.1: + resolution: {integrity: sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==} + hasBin: true + + uuid@3.4.0: + resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). + hasBin: true + + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true v8-to-istanbul@9.3.0: @@ -13533,7 +13551,7 @@ snapshots: loglevel: 1.9.2 lru-cache: 11.3.3 negotiator: 1.0.0 - uuid: 14.0.0 + uuid: 11.1.1 whatwg-mimetype: 4.0.0 transitivePeerDependencies: - supports-color @@ -13816,7 +13834,7 @@ snapshots: tough-cookie: 2.5.0 tslib: 1.14.1 tunnel: 0.0.6 - uuid: 14.0.0 + uuid: 3.4.0 xml2js: 0.4.23 transitivePeerDependencies: - debug @@ -13832,7 +13850,7 @@ snapshots: dependencies: '@azure/msal-common': 14.16.1 jsonwebtoken: 9.0.2 - uuid: 14.0.0 + uuid: 8.3.2 '@azure/opentelemetry-instrumentation-azure-sdk@1.0.0-beta.9': dependencies: @@ -15094,14 +15112,14 @@ snapshots: '@types/uuid': 10.0.0 class-transformer: 0.5.1 reflect-metadata: 0.2.2 - uuid: 14.0.0 + uuid: 10.0.0 '@cucumber/messages@27.2.0': dependencies: '@types/uuid': 10.0.0 class-transformer: 0.5.1 reflect-metadata: 0.2.2 - uuid: 14.0.0 + uuid: 11.0.5 '@cucumber/messages@32.2.0': dependencies: @@ -19358,7 +19376,7 @@ snapshots: to-readable-stream: 2.1.0 tslib: 2.8.1 uri-templates: 0.2.0 - uuid: 14.0.0 + uuid: 3.4.0 winston: 3.18.3 xml2js: 0.6.2 transitivePeerDependencies: @@ -24778,7 +24796,7 @@ snapshots: semver: 7.7.4 sequelize-pool: 7.1.0 toposort-class: 1.0.1 - uuid: 14.0.0 + uuid: 8.3.2 validator: 13.15.23 wkx: 0.5.0 optionalDependencies: @@ -24974,7 +24992,7 @@ snapshots: sockjs@0.3.24: dependencies: faye-websocket: 0.11.4 - uuid: 14.0.0 + uuid: 8.3.2 websocket-driver: 0.7.4 sort-css-media-queries@2.2.0: {} @@ -25772,7 +25790,15 @@ snapshots: utils-merge@1.0.1: {} - uuid@14.0.0: {} + uuid@10.0.0: {} + + uuid@11.0.5: {} + + uuid@11.1.1: {} + + uuid@3.4.0: {} + + uuid@8.3.2: {} v8-to-istanbul@9.3.0: dependencies: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index ac9ea4615..269ed31ec 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -86,7 +86,6 @@ overrides: webpack: ^5.105.4 webpack-dev-server: ^5.2.4 express-rate-limit: 8.5.1 - uuid: 14.0.0 playwright-core: 1.59.0 playwright: 1.59.0 postcss: 8.5.10 From e2161c4ba143f301c64be939d0f4a98a5407af4c Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Mon, 18 May 2026 19:53:53 +0530 Subject: [PATCH 85/88] feat: add enterpriseAppRole handling in staff role tests and repository --- .../user/staff-role/create-default-roles.test.ts | 9 +++++++++ .../user/staff-role/staff-role-defaults.test.ts | 1 + .../contexts/user/staff-role/staff-role.test.ts | 1 + .../user/staff-role/staff-role.repository.test.ts | 11 +++++++++-- 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts index fa0405619..c5abf4a2b 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts @@ -50,6 +50,12 @@ function makeMockRepo(existingRoleNames: string[] = [], overrides: Partial { + if (existingRoleNames.includes(enterpriseAppRole)) { + return Promise.resolve(makeMockStaffRole(enterpriseAppRole)); + } + return Promise.reject(new Error(`NotFoundError: ${enterpriseAppRole} not found`)); + }), getNewInstance: vi.fn().mockImplementation((roleName: string) => { const role = makeMockStaffRole(roleName); savedRoles.push(role); @@ -156,6 +162,9 @@ function makeDataSources(repo: StaffRoleRepo): DataSources { return role; }; } + if (!repoWithDefaults.getDefaultRoleByEnterpriseAppRole) { + repoWithDefaults.getDefaultRoleByEnterpriseAppRole = (enterpriseAppRole: string) => repoWithDefaults.getByRoleName(enterpriseAppRole); + } return { domainDataSource: { diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-defaults.test.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-defaults.test.ts index 5649554e2..3314befb7 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-defaults.test.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role-defaults.test.ts @@ -59,6 +59,7 @@ function makeBaseProps(overrides: Partial = {}): StaffRoleProps id: 'role-1', roleName: 'Support', isDefault: false, + enterpriseAppRole: '', permissions: emptyPermissions as unknown as StaffRoleProps['permissions'], roleType: 'staff-role', createdAt: new Date(), diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.test.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.test.ts index fade23a8e..d9f16c93e 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.test.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.test.ts @@ -27,6 +27,7 @@ function makeBaseProps(overrides: Partial = {}): StaffRoleProps id: 'role-1', roleName: 'Support', isDefault: false, + enterpriseAppRole: '', permissions: {} as StaffRolePermissions, roleType: 'staff-role', createdAt: new Date('2020-01-01T00:00:00Z'), diff --git a/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.repository.test.ts b/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.repository.test.ts index 0484ed99e..76c030776 100644 --- a/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.repository.test.ts +++ b/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.repository.test.ts @@ -87,8 +87,15 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { findById: vi.fn((id: string) => ({ exec: vi.fn(async () => (id === String(staffRoleDoc._id) ? staffRoleDoc : null)), })), - findOne: vi.fn((query: { roleName: string }) => ({ - exec: vi.fn(async () => (query.roleName === staffRoleDoc.roleName ? staffRoleDoc : null)), + findOne: vi.fn((query: { roleName?: string; isDefault?: boolean; enterpriseAppRole?: string }) => ({ + exec: vi.fn(() => { + if (query.enterpriseAppRole !== undefined) { + return query.enterpriseAppRole === staffRoleDoc.enterpriseAppRole && query.isDefault === staffRoleDoc.isDefault + ? staffRoleDoc + : null; + } + return query.roleName === staffRoleDoc.roleName ? staffRoleDoc : null; + }), })), prototype: {}, }); From 7c69013bdb42a323befa76e1a322390dd13e7386 Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Mon, 18 May 2026 10:40:32 -0400 Subject: [PATCH 86/88] Resolve test coverage failure and add getDefaultRoleByEnterpriseAppRole --- .../user/staff-role/create-default-roles.test.ts | 10 +++++----- .../contexts/user/staff-role/create-default-roles.ts | 2 ++ .../src/domain/contexts/user/staff-role/staff-role.ts | 2 +- .../user/staff-role/staff-role.repository.test.ts | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts index c5abf4a2b..c2f7eccd3 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.test.ts @@ -274,7 +274,7 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { Given('no staff roles exist', () => { capturedRoles = new Map(); mockRepo = { - getByRoleName: vi.fn().mockRejectedValue(new Error('not found')), + getDefaultRoleByEnterpriseAppRole: vi.fn().mockRejectedValue(new Error('not found')), getNewInstance: vi.fn().mockImplementation((roleName: string) => { const role = makeMockStaffRole(roleName); capturedRoles.set(roleName, role); @@ -318,7 +318,7 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { Given('no staff roles exist', () => { capturedRoles = new Map(); mockRepo = { - getByRoleName: vi.fn().mockRejectedValue(new Error('not found')), + getDefaultRoleByEnterpriseAppRole: vi.fn().mockRejectedValue(new Error('not found')), getNewInstance: vi.fn().mockImplementation((roleName: string) => { const role = makeMockStaffRole(roleName); capturedRoles.set(roleName, role); @@ -362,7 +362,7 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { Given('no staff roles exist', () => { capturedRoles = new Map(); mockRepo = { - getByRoleName: vi.fn().mockRejectedValue(new Error('not found')), + getDefaultRoleByEnterpriseAppRole: vi.fn().mockRejectedValue(new Error('not found')), getNewInstance: vi.fn().mockImplementation((roleName: string) => { const role = makeMockStaffRole(roleName); capturedRoles.set(roleName, role); @@ -408,7 +408,7 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { Given('no staff roles exist', () => { capturedRoles = new Map(); mockRepo = { - getByRoleName: vi.fn().mockRejectedValue(new Error('not found')), + getDefaultRoleByEnterpriseAppRole: vi.fn().mockRejectedValue(new Error('not found')), getNewInstance: vi.fn().mockImplementation((roleName: string) => { const role = makeMockStaffRole(roleName); capturedRoles.set(roleName, role); @@ -470,7 +470,7 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { Given('no staff roles exist', () => { mockRepo = { - getByRoleName: vi.fn().mockRejectedValue(new Error('Database connection failed')), + getDefaultRoleByEnterpriseAppRole: vi.fn().mockRejectedValue(new Error('Database connection failed')), getNewInstance: vi.fn(), save: vi.fn(), } as unknown as typeof mockRepo; diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts index 8d90dce77..841d4b920 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-role/create-default-roles.ts @@ -3,6 +3,8 @@ import type { DataSources } from '@ocom/persistence'; type StaffRoleRepo = Domain.Contexts.User.StaffRole.StaffRoleRepository; +export const StaffAppRoleNames = Domain.Contexts.User.StaffRole.StaffRoleValueObjects.EnterpriseAppRoleNames; + const roleExists = async (repository: StaffRoleRepo, enterpriseAppRole: string): Promise => { try { await repository.getDefaultRoleByEnterpriseAppRole(enterpriseAppRole); diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts index 1ddc8b440..f5ad20a1d 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts @@ -137,7 +137,7 @@ export class StaffRole extends AggregateRoot permissions.canManageStaffRolesAndPermissions || permissions.isSystemAccount)) { throw new PermissionError('Cannot set enterprise app role'); } - this.props.enterpriseAppRole = new ValueObjects.EnterpriseAppRole(enterpriseAppRole).valueOf(); + this.props.enterpriseAppRole = new ValueObjects.EnterpriseAppRole(enterpriseAppRole).valueOf(); } get isDefault() { diff --git a/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.repository.test.ts b/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.repository.test.ts index 76c030776..dc0db7f1c 100644 --- a/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.repository.test.ts +++ b/packages/ocom/persistence/src/datasources/domain/user/staff-role/staff-role.repository.test.ts @@ -85,7 +85,7 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { }; Object.assign(ModelMock, { findById: vi.fn((id: string) => ({ - exec: vi.fn(async () => (id === String(staffRoleDoc._id) ? staffRoleDoc : null)), + exec: vi.fn(() => Promise.resolve(id === String(staffRoleDoc._id) ? staffRoleDoc : null)), })), findOne: vi.fn((query: { roleName?: string; isDefault?: boolean; enterpriseAppRole?: string }) => ({ exec: vi.fn(() => { From 0960b11d6057fedd07a94104db49cbc5d3a8149f Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Mon, 18 May 2026 11:01:12 -0400 Subject: [PATCH 87/88] chore: update dependencies for snyk issue --- .snyk | 15 ++++++ pnpm-lock.yaml | 111 +++++++++++++++++++------------------------- pnpm-workspace.yaml | 3 +- 3 files changed, 66 insertions(+), 63 deletions(-) diff --git a/.snyk b/.snyk index 97bb87848..02a4e4b14 100644 --- a/.snyk +++ b/.snyk @@ -76,3 +76,18 @@ ignore: reason: 'Transitive dependency in Docusaurus; not exploitable in current usage.' expires: '2026-06-28T00:00:00.000Z' created: '2026-05-11T10:00:00.000Z' + 'SNYK-JS-AI-16734889': + - '* > ai@5.0.105': + reason: 'Transitive dependency in @docusaurus/preset-classic; not exploitable in current usage.' + expires: '2026-06-18T00:00:00.000Z' + created: '2026-05-18T11:04:00.000Z' + 'SNYK-JS-AISDKPROVIDERUTILS-16734888': + - '* > @ai-sdk/provider-utils@3.0.18': + reason: 'Transitive dependency in @docusaurus/preset-classic; not exploitable in current usage.' + expires: '2026-06-18T00:00:00.000Z' + created: '2026-05-18T11:04:00.000Z' + 'SNYK-JS-AISDKPROVIDERUTILS-16735288': + - '* > @ai-sdk/provider-utils@3.0.18': + reason: 'Transitive dependency in @docusaurus/preset-classic; not exploitable in current usage.' + expires: '2026-06-18T00:00:00.000Z' + created: '2026-05-18T11:04:00.000Z' diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 99b5f7918..9d1872fae 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -116,7 +116,7 @@ overrides: svgo: ^3.3.3 yaml@2.8.2: 2.8.3 yauzl@3.2.0: 3.2.1 - qs: ^6.14.2 + qs: ^6.15.2 ajv@^6: 6.14.0 lodash: 4.18.1 lodash-es: 4.18.1 @@ -133,6 +133,7 @@ overrides: ip-address: ^10.1.1 fast-uri: ^3.1.2 '@babel/plugin-transform-modules-systemjs': 7.29.4 + ws: 8.20.1 patchedDependencies: '@azure/functions@4.11.0': 69772ce521bf6df67d814ff4f419f19b5e966a41c4ce80b5938143ad628e5645 @@ -429,7 +430,7 @@ importers: dependencies: '@apollo/client': specifier: ^3.13.9 - version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@cellix/ui-core': specifier: workspace:* version: link:../../packages/cellix/ui-core @@ -453,7 +454,7 @@ importers: version: 6.3.5(luxon@3.7.2)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) apollo-link-rest: specifier: ^0.9.0 - version: 0.9.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(qs@6.15.0) + version: 0.9.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(qs@6.15.2) less: specifier: ^4.4.0 version: 4.4.2 @@ -526,7 +527,7 @@ importers: version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) storybook-addon-apollo-client: specifier: ^9.0.0 - version: 9.0.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(react@19.2.0) + version: 9.0.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(react@19.2.0) tailwindcss: specifier: ^3.4.17 version: 3.4.18(tsx@4.21.0)(yaml@2.8.3) @@ -544,7 +545,7 @@ importers: dependencies: '@apollo/client': specifier: ^3.13.9 - version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@cellix/ui-core': specifier: workspace:* version: link:../../packages/cellix/ui-core @@ -580,7 +581,7 @@ importers: version: 6.3.5(luxon@3.7.2)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) apollo-link-rest: specifier: ^0.9.0 - version: 0.9.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(qs@6.15.0) + version: 0.9.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(qs@6.15.2) less: specifier: ^4.4.0 version: 4.4.2 @@ -1763,7 +1764,7 @@ importers: version: 7.22.7(antd@6.3.5(luxon@3.7.2)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@apollo/client': specifier: ^3.13.9 - version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@cellix/ui-core': specifier: workspace:* version: link:../../cellix/ui-core @@ -1854,7 +1855,7 @@ importers: version: 7.22.7(antd@6.3.5(luxon@3.7.2)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@apollo/client': specifier: ^3.13.9 - version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@cellix/ui-core': specifier: workspace:* version: link:../../cellix/ui-core @@ -2009,7 +2010,7 @@ importers: dependencies: '@apollo/client': specifier: ^3.13.9 - version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@cellix/ui-core': specifier: workspace:* version: link:../../cellix/ui-core @@ -2091,7 +2092,7 @@ importers: version: 6.1.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@apollo/client': specifier: ^3.13.9 - version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@cellix/ui-core': specifier: workspace:* version: link:../../cellix/ui-core @@ -2170,7 +2171,7 @@ importers: version: 9.1.20(@testing-library/dom@10.4.1)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) storybook-addon-apollo-client: specifier: ^9.0.0 - version: 9.0.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(react@19.2.0) + version: 9.0.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(react@19.2.0) typescript: specifier: 'catalog:' version: 6.0.3 @@ -2400,7 +2401,7 @@ importers: version: 6.1.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@apollo/client': specifier: ^3.13.9 - version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@cellix/ui-core': specifier: workspace:* version: link:../../cellix/ui-core @@ -7020,7 +7021,7 @@ packages: peerDependencies: '@apollo/client': '>=3' graphql: '>=0.11' - qs: ^6.14.2 + qs: ^6.15.2 applicationinsights@2.9.8: resolution: {integrity: sha512-eB/EtAXJ6mDLLvHrtZj/7h31qUfnC2Npr2pHGqds5+1OP7BFLsn5us+HCkwTj7Q+1sHXujLphE5Cyvq5grtV6g==} @@ -8773,7 +8774,7 @@ packages: crossws: ~0.3 graphql: ^15.10.1 || ^16 uWebSockets.js: ^20 - ws: ^8 + ws: 8.20.1 peerDependenciesMeta: '@fastify/websocket': optional: true @@ -9386,7 +9387,7 @@ packages: isomorphic-ws@5.0.0: resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==} peerDependencies: - ws: '*' + ws: 8.20.1 istanbul-lib-coverage@3.2.2: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} @@ -11254,8 +11255,8 @@ packages: resolution: {integrity: sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA==} engines: {node: '>=16.0.0'} - qs@6.15.0: - resolution: {integrity: sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==} + qs@6.15.2: + resolution: {integrity: sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==} engines: {node: '>=0.6'} queue-microtask@1.2.3: @@ -13076,20 +13077,8 @@ packages: write-file-atomic@3.0.3: resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} - ws@7.5.10: - resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} - engines: {node: '>=8.3.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - ws@8.20.0: - resolution: {integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==} + ws@8.20.1: + resolution: {integrity: sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -13483,7 +13472,7 @@ snapshots: dependencies: graphql: 16.12.0 - '@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + '@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: '@graphql-typed-document-node/core': 3.2.0(graphql@16.12.0) '@wry/caches': 1.0.1 @@ -13500,7 +13489,7 @@ snapshots: tslib: 2.8.1 zen-observable-ts: 1.2.5 optionalDependencies: - graphql-ws: 6.0.6(graphql@16.12.0)(ws@8.20.0) + graphql-ws: 6.0.6(graphql@16.12.0)(ws@8.20.1) react: 19.2.0 react-dom: 19.2.0(react@19.2.0) transitivePeerDependencies: @@ -16432,10 +16421,10 @@ snapshots: '@graphql-tools/utils': 10.11.0(graphql@16.12.0) '@whatwg-node/disposablestack': 0.0.6 graphql: 16.12.0 - graphql-ws: 6.0.6(graphql@16.12.0)(ws@8.20.0) - isomorphic-ws: 5.0.0(ws@8.20.0) + graphql-ws: 6.0.6(graphql@16.12.0)(ws@8.20.1) + isomorphic-ws: 5.0.0(ws@8.20.1) tslib: 2.8.1 - ws: 8.20.0 + ws: 8.20.1 transitivePeerDependencies: - '@fastify/websocket' - bufferutil @@ -16463,9 +16452,9 @@ snapshots: '@graphql-tools/utils': 10.11.0(graphql@16.12.0) '@types/ws': 8.18.1 graphql: 16.12.0 - isomorphic-ws: 5.0.0(ws@8.20.0) + isomorphic-ws: 5.0.0(ws@8.20.1) tslib: 2.8.1 - ws: 8.20.0 + ws: 8.20.1 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -16637,10 +16626,10 @@ snapshots: '@whatwg-node/fetch': 0.10.13 '@whatwg-node/promise-helpers': 1.3.2 graphql: 16.12.0 - isomorphic-ws: 5.0.0(ws@8.20.0) + isomorphic-ws: 5.0.0(ws@8.20.1) sync-fetch: 0.6.0-2 tslib: 2.8.1 - ws: 8.20.0 + ws: 8.20.1 transitivePeerDependencies: - '@fastify/websocket' - '@types/node' @@ -18772,7 +18761,7 @@ snapshots: sirv: 3.0.2 tinyrainbow: 3.1.0 vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@22.19.15)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - ws: 8.20.0 + ws: 8.20.1 transitivePeerDependencies: - bufferutil - msw @@ -18790,7 +18779,7 @@ snapshots: sirv: 3.0.2 tinyrainbow: 3.1.0 vitest: 4.1.2(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.2)(jsdom@26.1.0)(vite@8.0.5(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@24.10.1)(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - ws: 8.20.0 + ws: 8.20.1 transitivePeerDependencies: - bufferutil - msw @@ -19207,11 +19196,11 @@ snapshots: normalize-path: 3.0.0 picomatch: 4.0.4 - apollo-link-rest@0.9.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(qs@6.15.0): + apollo-link-rest@0.9.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(qs@6.15.2): dependencies: - '@apollo/client': 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@apollo/client': 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) graphql: 16.12.0 - qs: 6.15.0 + qs: 6.15.2 applicationinsights@2.9.8: dependencies: @@ -19477,7 +19466,7 @@ snapshots: http-errors: 2.0.0 iconv-lite: 0.4.24 on-finished: 2.4.1 - qs: 6.15.0 + qs: 6.15.2 raw-body: 2.5.2 type-is: 1.6.18 unpipe: 1.0.0 @@ -19492,7 +19481,7 @@ snapshots: http-errors: 2.0.1 iconv-lite: 0.7.0 on-finished: 2.4.1 - qs: 6.15.0 + qs: 6.15.2 raw-body: 3.0.2 type-is: 2.0.1 transitivePeerDependencies: @@ -20767,7 +20756,7 @@ snapshots: parseurl: 1.3.3 path-to-regexp: 0.1.13 proxy-addr: 2.0.7 - qs: 6.15.0 + qs: 6.15.2 range-parser: 1.2.1 safe-buffer: 5.2.1 send: 0.19.0 @@ -21232,11 +21221,11 @@ snapshots: graphql: 16.12.0 tslib: 2.8.1 - graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.0): + graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.1): dependencies: graphql: 16.12.0 optionalDependencies: - ws: 8.20.0 + ws: 8.20.1 graphql@14.7.0: dependencies: @@ -21877,9 +21866,9 @@ snapshots: isobject@3.0.1: {} - isomorphic-ws@5.0.0(ws@8.20.0): + isomorphic-ws@5.0.0(ws@8.20.1): dependencies: - ws: 8.20.0 + ws: 8.20.1 istanbul-lib-coverage@3.2.2: {} @@ -21975,7 +21964,7 @@ snapshots: whatwg-encoding: 3.1.1 whatwg-mimetype: 4.0.0 whatwg-url: 14.2.0 - ws: 8.20.0 + ws: 8.20.1 xml-name-validator: 5.0.0 transitivePeerDependencies: - bufferutil @@ -24107,7 +24096,7 @@ snapshots: pvutils@1.1.5: {} - qs@6.15.0: + qs@6.15.2: dependencies: side-channel: 1.1.0 @@ -25094,9 +25083,9 @@ snapshots: stoppable@1.1.0: {} - storybook-addon-apollo-client@9.0.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(react@19.2.0): + storybook-addon-apollo-client@9.0.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(react@19.2.0): dependencies: - '@apollo/client': 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@apollo/client': 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.20.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) graphql: 16.12.0 react: 19.2.0 @@ -25113,7 +25102,7 @@ snapshots: esbuild-register: 3.6.0(esbuild@0.25.12) recast: 0.23.11 semver: 7.7.4 - ws: 8.20.0 + ws: 8.20.1 transitivePeerDependencies: - '@testing-library/dom' - bufferutil @@ -25980,7 +25969,7 @@ snapshots: opener: 1.5.2 picocolors: 1.1.1 sirv: 2.0.4 - ws: 7.5.10 + ws: 8.20.1 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -26025,7 +26014,7 @@ snapshots: sockjs: 0.3.24 spdy: 4.0.2 webpack-dev-middleware: 7.4.5(webpack@5.105.4(esbuild@0.27.4)) - ws: 8.20.0 + ws: 8.20.1 optionalDependencies: webpack: 5.105.4(esbuild@0.27.4) transitivePeerDependencies: @@ -26233,9 +26222,7 @@ snapshots: signal-exit: 3.0.7 typedarray-to-buffer: 3.1.5 - ws@7.5.10: {} - - ws@8.20.0: {} + ws@8.20.1: {} wsl-utils@0.1.0: dependencies: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 269ed31ec..58034a5b2 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -76,7 +76,7 @@ overrides: svgo: ^3.3.3 'yaml@2.8.2': 2.8.3 'yauzl@3.2.0': 3.2.1 - qs: ^6.14.2 + qs: ^6.15.2 'ajv@^6': 6.14.0 lodash: 4.18.1 lodash-es: 4.18.1 @@ -93,6 +93,7 @@ overrides: ip-address: ^10.1.1 fast-uri: ^3.1.2 '@babel/plugin-transform-modules-systemjs': 7.29.4 + ws: 8.20.1 patchedDependencies: '@azure/functions@4.11.0': patches/@azure__functions@4.11.0.patch From 7ddca0995a9702bcd0d381754d460c9f07594af9 Mon Sep 17 00:00:00 2001 From: Trang Nguyen Date: Mon, 18 May 2026 11:36:53 -0400 Subject: [PATCH 88/88] remove staffPermission from index.tsx --- packages/ocom/ui-community-route-admin/src/index.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/ocom/ui-community-route-admin/src/index.tsx b/packages/ocom/ui-community-route-admin/src/index.tsx index 61788f252..556021354 100644 --- a/packages/ocom/ui-community-route-admin/src/index.tsx +++ b/packages/ocom/ui-community-route-admin/src/index.tsx @@ -2,14 +2,15 @@ import { HomeOutlined, SettingOutlined, TeamOutlined } from '@ant-design/icons'; import type { PageLayoutProps } from '@ocom/ui-shared'; import type React from 'react'; import { Route, Routes } from 'react-router-dom'; -import type { AdminStaffSectionPermissions } from './section-layout.tsx'; import { Home } from './pages/home.tsx'; import { Members } from './pages/members.tsx'; import { Settings } from './pages/settings.tsx'; import { SectionLayoutContainer } from './section-layout.container.tsx'; interface AdminMenuData { - staffPermissions: AdminStaffSectionPermissions | null; + member?: { + isAdmin?: boolean | null; + }; } export const Admin: React.FC = () => { @@ -28,7 +29,7 @@ export const Admin: React.FC = () => { parent: 'ROOT', hasPermissions: (data: unknown) => { const adminData = data as AdminMenuData; - return adminData?.staffPermissions?.canManageUsers ?? false; + return adminData?.member?.isAdmin ?? false; }, }, { @@ -39,7 +40,7 @@ export const Admin: React.FC = () => { parent: 'ROOT', hasPermissions: (data: unknown) => { const adminData = data as AdminMenuData; - return adminData?.staffPermissions?.canManageCommunities ?? false; + return adminData?.member?.isAdmin ?? false; }, }, ];