@memoarchitect/architect 0.6.2 → 0.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/assets/ChatPanel-DSjWi7UI.js +3 -0
- package/dist/assets/{ComplianceWizard-Bi9PLmJH.js → ComplianceWizard-CVidRUY4.js} +1 -1
- package/dist/assets/{DSMView-DbC_fUKT.js → DSMView-DdcRG9Te.js} +1 -1
- package/dist/assets/{Dashboard-6Dgma4kY.js → Dashboard-DxOueCqW.js} +1 -1
- package/dist/assets/DhfDashboard-CpDAP41S.js +1 -0
- package/dist/assets/{DhfSettingsPanel-jQ5mh_50.js → DhfSettingsPanel-C2vyewXY.js} +1 -1
- package/dist/assets/{DhfWorkbench-CgFdQIts.js → DhfWorkbench-BGaEk0Qi.js} +3 -3
- package/dist/assets/DiagramCanvas-DybZNdxw.js +1 -0
- package/dist/assets/DiagramEditor-v6VJ5o2f.js +4 -0
- package/dist/assets/ElementDetailView-9EkxZAaF.js +2 -0
- package/dist/assets/{ImportView-HCDzL9Xx.js → ImportView-C8lcbof7.js} +1 -1
- package/dist/assets/{LayerGrid-DSxAFwPk.js → LayerGrid-BB30kAyl.js} +1 -1
- package/dist/assets/{LayerTable-C5VBpm6T.js → LayerTable-BN9IZPbM.js} +1 -1
- package/dist/assets/{MaxGraphCanvas-B7tAFvDf.js → MaxGraphCanvas-CfoIuwsi.js} +3 -3
- package/dist/assets/{ModelDiff-MM5NKKXK.js → ModelDiff-D6IR9kzb.js} +1 -1
- package/dist/assets/OntologyDecompositionDiagram-DjhvdWh5.js +1 -0
- package/dist/assets/{OntologyViewer-C5ik2Kmi.js → OntologyViewer-cI3zi95S.js} +2 -2
- package/dist/assets/{RelationshipOverlay-DSzjs5U7.js → RelationshipOverlay-B9bqt4zl.js} +1 -1
- package/dist/assets/{RelationshipsSection-2CEoiF6o.js → RelationshipsSection-DttMvF2i.js} +1 -1
- package/dist/assets/{ReviewDashboard-DwlsAVBa.js → ReviewDashboard-BTqze9-C.js} +1 -1
- package/dist/assets/ScenarioEditor-BL835I2V.js +3 -0
- package/dist/assets/{StatisticsDashboard-C67W4pb0.js → StatisticsDashboard-BC1JkdTl.js} +1 -1
- package/dist/assets/{SysmlCodeEditor-CGOcUFE7.js → SysmlCodeEditor-Die2RUsz.js} +1 -1
- package/dist/assets/{SysmlGenerator-BwRhtec-.js → SysmlGenerator-B_Me_xGE.js} +1 -1
- package/dist/assets/{TabularView-CTQgMG25.js → TabularView-Bn_WEMpm.js} +1 -1
- package/dist/assets/{TraceabilityMatrix-Bw5ej-So.js → TraceabilityMatrix-BEEPlOQq.js} +1 -1
- package/dist/assets/{WorkflowWizard-BwGWzMkE.js → WorkflowWizard-CFx5KVUH.js} +1 -1
- package/dist/assets/elk-6l8mIQnQ.js +26 -0
- package/dist/assets/index-BMgENwvO.js +3280 -0
- package/dist/assets/index-XtCtnAfF.css +1 -0
- package/dist/assets/layout-providers-Dr743WlP.js +1 -0
- package/dist/assets/layout-selection-ClQts3bC.js +1 -0
- package/dist/assets/{reactflow-CX-HDacK.js → reactflow-CsCqNKB-.js} +1 -1
- package/dist/assets/{zustand-qbFpP9Up.js → zustand-CrhqMOHB.js} +1 -1
- package/dist/index.html +4 -4
- package/lib/bin/memo-architect.js +20 -2
- package/lib/bin/memo-architect.js.map +1 -1
- package/lib/commands/example.d.ts +4 -0
- package/lib/commands/example.d.ts.map +1 -1
- package/lib/commands/example.js +14 -7
- package/lib/commands/example.js.map +1 -1
- package/package.json +7 -5
- package/dist/assets/AskPanel-Dqc6aaqg.js +0 -1
- package/dist/assets/DhfDashboard-BPXIYJnw.js +0 -1
- package/dist/assets/DiagramCanvas-CIfN1ybl.js +0 -1
- package/dist/assets/DiagramEditor-Y4sSx9nO.js +0 -4
- package/dist/assets/ElementDetailView-B946aM3p.js +0 -2
- package/dist/assets/OntologyDecompositionDiagram-CAzu3z_q.js +0 -1
- package/dist/assets/ScenarioEditor-BRWvcD2f.js +0 -3
- package/dist/assets/elk-B75IRfCd.js +0 -1
- package/dist/assets/index-D0i9ua6F.js +0 -3277
- package/dist/assets/index-DPzXL4uF.css +0 -1
- package/dist/assets/layout-providers-BFnfta4Z.js +0 -26
- package/dist/assets/layout-selection-BTId1JyG.js +0 -1
|
@@ -1,3277 +0,0 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/DiagramEditor-Y4sSx9nO.js","assets/reactflow-CX-HDacK.js","assets/zustand-qbFpP9Up.js","assets/DSMView-DbC_fUKT.js","assets/OntologyViewer-C5ik2Kmi.js","assets/TraceabilityMatrix-Bw5ej-So.js","assets/ScenarioEditor-BRWvcD2f.js","assets/ModelDiff-MM5NKKXK.js","assets/ComplianceWizard-Bi9PLmJH.js","assets/StatisticsDashboard-C67W4pb0.js","assets/DhfDashboard-BPXIYJnw.js","assets/DhfWorkbench-CgFdQIts.js","assets/AskPanel-Dqc6aaqg.js","assets/SysmlGenerator-BwRhtec-.js","assets/ElementDetailView-B946aM3p.js","assets/Dashboard-6Dgma4kY.js","assets/ReviewDashboard-DwlsAVBa.js","assets/WorkflowWizard-BwGWzMkE.js","assets/TabularView-CTQgMG25.js","assets/ImportView-HCDzL9Xx.js"])))=>i.map(i=>d[i]);
|
|
2
|
-
import{r as Ir,j as t}from"./reactflow-CX-HDacK.js";import{a as u,c as Kn,W as _r}from"./zustand-qbFpP9Up.js";(function(){const r=document.createElement("link").relList;if(r&&r.supports&&r.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))o(s);new MutationObserver(s=>{for(const i of s)if(i.type==="childList")for(const a of i.addedNodes)a.tagName==="LINK"&&a.rel==="modulepreload"&&o(a)}).observe(document,{childList:!0,subtree:!0});function n(s){const i={};return s.integrity&&(i.integrity=s.integrity),s.referrerPolicy&&(i.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?i.credentials="include":s.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function o(s){if(s.ep)return;s.ep=!0;const i=n(s);fetch(s.href,i)}})();var Je={},Zt;function Nr(){if(Zt)return Je;Zt=1;var e=Ir();return Je.createRoot=e.createRoot,Je.hydrateRoot=e.hydrateRoot,Je}var Mr=Nr();/**
|
|
3
|
-
* react-router v7.13.2
|
|
4
|
-
*
|
|
5
|
-
* Copyright (c) Remix Software Inc.
|
|
6
|
-
*
|
|
7
|
-
* This source code is licensed under the MIT license found in the
|
|
8
|
-
* LICENSE.md file in the root directory of this source tree.
|
|
9
|
-
*
|
|
10
|
-
* @license MIT
|
|
11
|
-
*/var en="popstate";function tn(e){return typeof e=="object"&&e!=null&&"pathname"in e&&"search"in e&&"hash"in e&&"state"in e&&"key"in e}function Or(e={}){function r(o,s){var c;let i=(c=s.state)==null?void 0:c.masked,{pathname:a,search:l,hash:d}=i||o.location;return Tt("",{pathname:a,search:l,hash:d},s.state&&s.state.usr||null,s.state&&s.state.key||"default",i?{pathname:o.location.pathname,search:o.location.search,hash:o.location.hash}:void 0)}function n(o,s){return typeof s=="string"?s:He(s)}return zr(r,n,null,e)}function te(e,r){if(e===!1||e===null||typeof e>"u")throw new Error(r)}function fe(e,r){if(!e){typeof console<"u"&&console.warn(r);try{throw new Error(r)}catch{}}}function Pr(){return Math.random().toString(36).substring(2,10)}function nn(e,r){return{usr:e.state,key:e.key,idx:r,masked:e.unstable_mask?{pathname:e.pathname,search:e.search,hash:e.hash}:void 0}}function Tt(e,r,n=null,o,s){return{pathname:typeof e=="string"?e:e.pathname,search:"",hash:"",...typeof r=="string"?Me(r):r,state:n,key:r&&r.key||o||Pr(),unstable_mask:s}}function He({pathname:e="/",search:r="",hash:n=""}){return r&&r!=="?"&&(e+=r.charAt(0)==="?"?r:"?"+r),n&&n!=="#"&&(e+=n.charAt(0)==="#"?n:"#"+n),e}function Me(e){let r={};if(e){let n=e.indexOf("#");n>=0&&(r.hash=e.substring(n),e=e.substring(0,n));let o=e.indexOf("?");o>=0&&(r.search=e.substring(o),e=e.substring(0,o)),e&&(r.pathname=e)}return r}function zr(e,r,n,o={}){let{window:s=document.defaultView,v5Compat:i=!1}=o,a=s.history,l="POP",d=null,c=p();c==null&&(c=0,a.replaceState({...a.state,idx:c},""));function p(){return(a.state||{idx:null}).idx}function f(){l="POP";let v=p(),w=v==null?null:v-c;c=v,d&&d({action:l,location:x.location,delta:w})}function h(v,w){l="PUSH";let T=tn(v)?v:Tt(x.location,v,w);c=p()+1;let I=nn(T,c),m=x.createHref(T.unstable_mask||T);try{a.pushState(I,"",m)}catch(D){if(D instanceof DOMException&&D.name==="DataCloneError")throw D;s.location.assign(m)}i&&d&&d({action:l,location:x.location,delta:1})}function S(v,w){l="REPLACE";let T=tn(v)?v:Tt(x.location,v,w);c=p();let I=nn(T,c),m=x.createHref(T.unstable_mask||T);a.replaceState(I,"",m),i&&d&&d({action:l,location:x.location,delta:0})}function b(v){return Br(v)}let x={get action(){return l},get location(){return e(s,a)},listen(v){if(d)throw new Error("A history only accepts one active listener");return s.addEventListener(en,f),d=v,()=>{s.removeEventListener(en,f),d=null}},createHref(v){return r(s,v)},createURL:b,encodeLocation(v){let w=b(v);return{pathname:w.pathname,search:w.search,hash:w.hash}},push:h,replace:S,go(v){return a.go(v)}};return x}function Br(e,r=!1){let n="http://localhost";typeof window<"u"&&(n=window.location.origin!=="null"?window.location.origin:window.location.href),te(n,"No window.location.(origin|href) available to create URL");let o=typeof e=="string"?e:He(e);return o=o.replace(/ $/,"%20"),!r&&o.startsWith("//")&&(o=n+o),new URL(o,n)}function Gn(e,r,n="/"){return Lr(e,r,n,!1)}function Lr(e,r,n,o){let s=typeof r=="string"?Me(r):r,i=be(s.pathname||"/",n);if(i==null)return null;let a=Yn(e);qr(a);let l=null;for(let d=0;l==null&&d<a.length;++d){let c=Xr(i);l=Jr(a[d],c,o)}return l}function Yn(e,r=[],n=[],o="",s=!1){let i=(a,l,d=s,c)=>{let p={relativePath:c===void 0?a.path||"":c,caseSensitive:a.caseSensitive===!0,childrenIndex:l,route:a};if(p.relativePath.startsWith("/")){if(!p.relativePath.startsWith(o)&&d)return;te(p.relativePath.startsWith(o),`Absolute route path "${p.relativePath}" nested under path "${o}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),p.relativePath=p.relativePath.slice(o.length)}let f=me([o,p.relativePath]),h=n.concat(p);a.children&&a.children.length>0&&(te(a.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${f}".`),Yn(a.children,r,h,f,d)),!(a.path==null&&!a.index)&&r.push({path:f,score:Gr(f,a.index),routesMeta:h})};return e.forEach((a,l)=>{var d;if(a.path===""||!((d=a.path)!=null&&d.includes("?")))i(a,l);else for(let c of Jn(a.path))i(a,l,!0,c)}),r}function Jn(e){let r=e.split("/");if(r.length===0)return[];let[n,...o]=r,s=n.endsWith("?"),i=n.replace(/\?$/,"");if(o.length===0)return s?[i,""]:[i];let a=Jn(o.join("/")),l=[];return l.push(...a.map(d=>d===""?i:[i,d].join("/"))),s&&l.push(...a),l.map(d=>e.startsWith("/")&&d===""?"/":d)}function qr(e){e.sort((r,n)=>r.score!==n.score?n.score-r.score:Yr(r.routesMeta.map(o=>o.childrenIndex),n.routesMeta.map(o=>o.childrenIndex)))}var Vr=/^:[\w-]+$/,$r=3,Ur=2,Wr=1,Hr=10,Kr=-2,rn=e=>e==="*";function Gr(e,r){let n=e.split("/"),o=n.length;return n.some(rn)&&(o+=Kr),r&&(o+=Ur),n.filter(s=>!rn(s)).reduce((s,i)=>s+(Vr.test(i)?$r:i===""?Wr:Hr),o)}function Yr(e,r){return e.length===r.length&&e.slice(0,-1).every((o,s)=>o===r[s])?e[e.length-1]-r[r.length-1]:0}function Jr(e,r,n=!1){let{routesMeta:o}=e,s={},i="/",a=[];for(let l=0;l<o.length;++l){let d=o[l],c=l===o.length-1,p=i==="/"?r:r.slice(i.length)||"/",f=dt({path:d.relativePath,caseSensitive:d.caseSensitive,end:c},p),h=d.route;if(!f&&c&&n&&!o[o.length-1].route.index&&(f=dt({path:d.relativePath,caseSensitive:d.caseSensitive,end:!1},p)),!f)return null;Object.assign(s,f.params),a.push({params:s,pathname:me([i,f.pathname]),pathnameBase:no(me([i,f.pathnameBase])),route:h}),f.pathnameBase!=="/"&&(i=me([i,f.pathnameBase]))}return a}function dt(e,r){typeof e=="string"&&(e={path:e,caseSensitive:!1,end:!0});let[n,o]=Qr(e.path,e.caseSensitive,e.end),s=r.match(n);if(!s)return null;let i=s[0],a=i.replace(/(.)\/+$/,"$1"),l=s.slice(1);return{params:o.reduce((c,{paramName:p,isOptional:f},h)=>{if(p==="*"){let b=l[h]||"";a=i.slice(0,i.length-b.length).replace(/(.)\/+$/,"$1")}const S=l[h];return f&&!S?c[p]=void 0:c[p]=(S||"").replace(/%2F/g,"/"),c},{}),pathname:i,pathnameBase:a,pattern:e}}function Qr(e,r=!1,n=!0){fe(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 o=[],s="^"+e.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(a,l,d,c,p)=>{if(o.push({paramName:l,isOptional:d!=null}),d){let f=p.charAt(c+a.length);return f&&f!=="/"?"/([^\\/]*)":"(?:/([^\\/]*))?"}return"/([^\\/]+)"}).replace(/\/([\w-]+)\?(\/|$)/g,"(/$1)?$2");return e.endsWith("*")?(o.push({paramName:"*"}),s+=e==="*"||e==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):n?s+="\\/*$":e!==""&&e!=="/"&&(s+="(?:(?=\\/|$))"),[new RegExp(s,r?void 0:"i"),o]}function Xr(e){try{return e.split("/").map(r=>decodeURIComponent(r).replace(/\//g,"%2F")).join("/")}catch(r){return fe(!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 (${r}).`),e}}function be(e,r){if(r==="/")return e;if(!e.toLowerCase().startsWith(r.toLowerCase()))return null;let n=r.endsWith("/")?r.length-1:r.length,o=e.charAt(n);return o&&o!=="/"?null:e.slice(n)||"/"}var Zr=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;function eo(e,r="/"){let{pathname:n,search:o="",hash:s=""}=typeof e=="string"?Me(e):e,i;return n?(n=n.replace(/\/\/+/g,"/"),n.startsWith("/")?i=on(n.substring(1),"/"):i=on(n,r)):i=r,{pathname:i,search:ro(o),hash:oo(s)}}function on(e,r){let n=r.replace(/\/+$/,"").split("/");return e.split("/").forEach(s=>{s===".."?n.length>1&&n.pop():s!=="."&&n.push(s)}),n.length>1?n.join("/"):"/"}function ht(e,r,n,o){return`Cannot include a '${e}' character in a manually specified \`to.${r}\` field [${JSON.stringify(o)}]. Please separate it out to the \`to.${n}\` field. Alternatively you may provide the full path as a string in <Link to="..."> and the router will parse it for you.`}function to(e){return e.filter((r,n)=>n===0||r.route.path&&r.route.path.length>0)}function Qn(e){let r=to(e);return r.map((n,o)=>o===r.length-1?n.pathname:n.pathnameBase)}function Lt(e,r,n,o=!1){let s;typeof e=="string"?s=Me(e):(s={...e},te(!s.pathname||!s.pathname.includes("?"),ht("?","pathname","search",s)),te(!s.pathname||!s.pathname.includes("#"),ht("#","pathname","hash",s)),te(!s.search||!s.search.includes("#"),ht("#","search","hash",s)));let i=e===""||s.pathname==="",a=i?"/":s.pathname,l;if(a==null)l=n;else{let f=r.length-1;if(!o&&a.startsWith("..")){let h=a.split("/");for(;h[0]==="..";)h.shift(),f-=1;s.pathname=h.join("/")}l=f>=0?r[f]:"/"}let d=eo(s,l),c=a&&a!=="/"&&a.endsWith("/"),p=(i||a===".")&&n.endsWith("/");return!d.pathname.endsWith("/")&&(c||p)&&(d.pathname+="/"),d}var me=e=>e.join("/").replace(/\/\/+/g,"/"),no=e=>e.replace(/\/+$/,"").replace(/^\/*/,"/"),ro=e=>!e||e==="?"?"":e.startsWith("?")?e:"?"+e,oo=e=>!e||e==="#"?"":e.startsWith("#")?e:"#"+e,so=class{constructor(e,r,n,o=!1){this.status=e,this.statusText=r||"",this.internal=o,n instanceof Error?(this.data=n.toString(),this.error=n):this.data=n}};function io(e){return e!=null&&typeof e.status=="number"&&typeof e.statusText=="string"&&typeof e.internal=="boolean"&&"data"in e}function ao(e){return e.map(r=>r.route.path).filter(Boolean).join("/").replace(/\/\/*/g,"/")||"/"}var Xn=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function Zn(e,r){let n=e;if(typeof n!="string"||!Zr.test(n))return{absoluteURL:void 0,isExternal:!1,to:n};let o=n,s=!1;if(Xn)try{let i=new URL(window.location.href),a=n.startsWith("//")?new URL(i.protocol+n):new URL(n),l=be(a.pathname,r);a.origin===i.origin&&l!=null?n=l+a.search+a.hash:s=!0}catch{fe(!1,`<Link to="${n}"> contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}return{absoluteURL:o,isExternal:s,to:n}}Object.getOwnPropertyNames(Object.prototype).sort().join("\0");var er=["POST","PUT","PATCH","DELETE"];new Set(er);var lo=["GET",...er];new Set(lo);var Oe=u.createContext(null);Oe.displayName="DataRouter";var ut=u.createContext(null);ut.displayName="DataRouterState";var co=u.createContext(!1),tr=u.createContext({isTransitioning:!1});tr.displayName="ViewTransition";var uo=u.createContext(new Map);uo.displayName="Fetchers";var po=u.createContext(null);po.displayName="Await";var ce=u.createContext(null);ce.displayName="Navigation";var Pe=u.createContext(null);Pe.displayName="Location";var he=u.createContext({outlet:null,matches:[],isDataRoute:!1});he.displayName="Route";var qt=u.createContext(null);qt.displayName="RouteError";var nr="REACT_ROUTER_ERROR",mo="REDIRECT",fo="ROUTE_ERROR_RESPONSE";function ho(e){if(e.startsWith(`${nr}:${mo}:{`))try{let r=JSON.parse(e.slice(28));if(typeof r=="object"&&r&&typeof r.status=="number"&&typeof r.statusText=="string"&&typeof r.location=="string"&&typeof r.reloadDocument=="boolean"&&typeof r.replace=="boolean")return r}catch{}}function go(e){if(e.startsWith(`${nr}:${fo}:{`))try{let r=JSON.parse(e.slice(40));if(typeof r=="object"&&r&&typeof r.status=="number"&&typeof r.statusText=="string")return new so(r.status,r.statusText,r.data)}catch{}}function yo(e,{relative:r}={}){te(Ge(),"useHref() may be used only in the context of a <Router> component.");let{basename:n,navigator:o}=u.useContext(ce),{hash:s,pathname:i,search:a}=Ye(e,{relative:r}),l=i;return n!=="/"&&(l=i==="/"?n:me([n,i])),o.createHref({pathname:l,search:a,hash:s})}function Ge(){return u.useContext(Pe)!=null}function ge(){return te(Ge(),"useLocation() may be used only in the context of a <Router> component."),u.useContext(Pe).location}function xo(){return u.useContext(Pe).navigationType}var rr="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function or(e){u.useContext(ce).static||u.useLayoutEffect(e)}function ve(){let{isDataRoute:e}=u.useContext(he);return e?To():bo()}function bo(){te(Ge(),"useNavigate() may be used only in the context of a <Router> component.");let e=u.useContext(Oe),{basename:r,navigator:n}=u.useContext(ce),{matches:o}=u.useContext(he),{pathname:s}=ge(),i=JSON.stringify(Qn(o)),a=u.useRef(!1);return or(()=>{a.current=!0}),u.useCallback((d,c={})=>{if(fe(a.current,rr),!a.current)return;if(typeof d=="number"){n.go(d);return}let p=Lt(d,JSON.parse(i),s,c.relative==="path");e==null&&r!=="/"&&(p.pathname=p.pathname==="/"?r:me([r,p.pathname])),(c.replace?n.replace:n.push)(p,c.state,c)},[r,n,i,s,e])}u.createContext(null);function Vt(){let{matches:e}=u.useContext(he),r=e[e.length-1];return r?r.params:{}}function Ye(e,{relative:r}={}){let{matches:n}=u.useContext(he),{pathname:o}=ge(),s=JSON.stringify(Qn(n));return u.useMemo(()=>Lt(e,JSON.parse(s),o,r==="path"),[e,s,o,r])}function vo(e,r){return sr(e,r)}function sr(e,r,n){var v;te(Ge(),"useRoutes() may be used only in the context of a <Router> component.");let{navigator:o}=u.useContext(ce),{matches:s}=u.useContext(he),i=s[s.length-1],a=i?i.params:{},l=i?i.pathname:"/",d=i?i.pathnameBase:"/",c=i&&i.route;{let w=c&&c.path||"";ar(l,!c||w.endsWith("*")||w.endsWith("*?"),`You rendered descendant <Routes> (or called \`useRoutes()\`) at "${l}" (under <Route path="${w}">) 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.
|
|
12
|
-
|
|
13
|
-
Please change the parent <Route path="${w}"> to <Route path="${w==="/"?"*":`${w}/*`}">.`)}let p=ge(),f;if(r){let w=typeof r=="string"?Me(r):r;te(d==="/"||((v=w.pathname)==null?void 0:v.startsWith(d)),`When overriding the location using \`<Routes location>\` 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 "${d}" but pathname "${w.pathname}" was given in the \`location\` prop.`),f=w}else f=p;let h=f.pathname||"/",S=h;if(d!=="/"){let w=d.replace(/^\//,"").split("/");S="/"+h.replace(/^\//,"").split("/").slice(w.length).join("/")}let b=Gn(e,{pathname:S});fe(c||b!=null,`No routes matched location "${f.pathname}${f.search}${f.hash}" `),fe(b==null||b[b.length-1].route.element!==void 0||b[b.length-1].route.Component!==void 0||b[b.length-1].route.lazy!==void 0,`Matched leaf route at location "${f.pathname}${f.search}${f.hash}" does not have an element or Component. This means it will render an <Outlet /> with a null value by default resulting in an "empty" page.`);let x=jo(b&&b.map(w=>Object.assign({},w,{params:Object.assign({},a,w.params),pathname:me([d,o.encodeLocation?o.encodeLocation(w.pathname.replace(/%/g,"%25").replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:w.pathname]),pathnameBase:w.pathnameBase==="/"?d:me([d,o.encodeLocation?o.encodeLocation(w.pathnameBase.replace(/%/g,"%25").replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:w.pathnameBase])})),s,n);return r&&x?u.createElement(Pe.Provider,{value:{location:{pathname:"/",search:"",hash:"",state:null,key:"default",unstable_mask:void 0,...f},navigationType:"POP"}},x):x}function wo(){let e=Ro(),r=io(e)?`${e.status} ${e.statusText}`:e instanceof Error?e.message:JSON.stringify(e),n=e instanceof Error?e.stack:null,o="rgba(200,200,200, 0.5)",s={padding:"0.5rem",backgroundColor:o},i={padding:"2px 4px",backgroundColor:o},a=null;return console.error("Error handled by React Router default ErrorBoundary:",e),a=u.createElement(u.Fragment,null,u.createElement("p",null,"💿 Hey developer 👋"),u.createElement("p",null,"You can provide a way better UX than this when your app throws errors by providing your own ",u.createElement("code",{style:i},"ErrorBoundary")," or"," ",u.createElement("code",{style:i},"errorElement")," prop on your route.")),u.createElement(u.Fragment,null,u.createElement("h2",null,"Unexpected Application Error!"),u.createElement("h3",{style:{fontStyle:"italic"}},r),n?u.createElement("pre",{style:s},n):null,a)}var ko=u.createElement(wo,null),ir=class extends u.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,r){return r.location!==e.location||r.revalidation!=="idle"&&e.revalidation==="idle"?{error:e.error,location:e.location,revalidation:e.revalidation}:{error:e.error!==void 0?e.error:r.error,location:r.location,revalidation:e.revalidation||r.revalidation}}componentDidCatch(e,r){this.props.onError?this.props.onError(e,r):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"){const n=go(e.digest);n&&(e=n)}let r=e!==void 0?u.createElement(he.Provider,{value:this.props.routeContext},u.createElement(qt.Provider,{value:e,children:this.props.component})):this.props.children;return this.context?u.createElement(So,{error:e},r):r}};ir.contextType=co;var gt=new WeakMap;function So({children:e,error:r}){let{basename:n}=u.useContext(ce);if(typeof r=="object"&&r&&"digest"in r&&typeof r.digest=="string"){let o=ho(r.digest);if(o){let s=gt.get(r);if(s)throw s;let i=Zn(o.location,n);if(Xn&&!gt.get(r))if(i.isExternal||o.reloadDocument)window.location.href=i.absoluteURL||i.to;else{const a=Promise.resolve().then(()=>window.__reactRouterDataRouter.navigate(i.to,{replace:o.replace}));throw gt.set(r,a),a}return u.createElement("meta",{httpEquiv:"refresh",content:`0;url=${i.absoluteURL||i.to}`})}}return e}function Eo({routeContext:e,match:r,children:n}){let o=u.useContext(Oe);return o&&o.static&&o.staticContext&&(r.route.errorElement||r.route.ErrorBoundary)&&(o.staticContext._deepestRenderedBoundaryId=r.route.id),u.createElement(he.Provider,{value:e},n)}function jo(e,r=[],n){let o=n==null?void 0:n.state;if(e==null){if(!o)return null;if(o.errors)e=o.matches;else if(r.length===0&&!o.initialized&&o.matches.length>0)e=o.matches;else return null}let s=e,i=o==null?void 0:o.errors;if(i!=null){let p=s.findIndex(f=>f.route.id&&(i==null?void 0:i[f.route.id])!==void 0);te(p>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(i).join(",")}`),s=s.slice(0,Math.min(s.length,p+1))}let a=!1,l=-1;if(n&&o){a=o.renderFallback;for(let p=0;p<s.length;p++){let f=s[p];if((f.route.HydrateFallback||f.route.hydrateFallbackElement)&&(l=p),f.route.id){let{loaderData:h,errors:S}=o,b=f.route.loader&&!h.hasOwnProperty(f.route.id)&&(!S||S[f.route.id]===void 0);if(f.route.lazy||b){n.isStatic&&(a=!0),l>=0?s=s.slice(0,l+1):s=[s[0]];break}}}}let d=n==null?void 0:n.onError,c=o&&d?(p,f)=>{var h,S;d(p,{location:o.location,params:((S=(h=o.matches)==null?void 0:h[0])==null?void 0:S.params)??{},unstable_pattern:ao(o.matches),errorInfo:f})}:void 0;return s.reduceRight((p,f,h)=>{let S,b=!1,x=null,v=null;o&&(S=i&&f.route.id?i[f.route.id]:void 0,x=f.route.errorElement||ko,a&&(l<0&&h===0?(ar("route-fallback",!1,"No `HydrateFallback` element provided to render during initial hydration"),b=!0,v=null):l===h&&(b=!0,v=f.route.hydrateFallbackElement||null)));let w=r.concat(s.slice(0,h+1)),T=()=>{let I;return S?I=x:b?I=v:f.route.Component?I=u.createElement(f.route.Component,null):f.route.element?I=f.route.element:I=p,u.createElement(Eo,{match:f,routeContext:{outlet:p,matches:w,isDataRoute:o!=null},children:I})};return o&&(f.route.ErrorBoundary||f.route.errorElement||h===0)?u.createElement(ir,{location:o.location,revalidation:o.revalidation,component:x,error:S,children:T(),routeContext:{outlet:null,matches:w,isDataRoute:!0},onError:c}):T()},null)}function $t(e){return`${e} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function Co(e){let r=u.useContext(Oe);return te(r,$t(e)),r}function Do(e){let r=u.useContext(ut);return te(r,$t(e)),r}function Ao(e){let r=u.useContext(he);return te(r,$t(e)),r}function Ut(e){let r=Ao(e),n=r.matches[r.matches.length-1];return te(n.route.id,`${e} can only be used on routes that contain a unique "id"`),n.route.id}function Fo(){return Ut("useRouteId")}function Ro(){var o;let e=u.useContext(qt),r=Do("useRouteError"),n=Ut("useRouteError");return e!==void 0?e:(o=r.errors)==null?void 0:o[n]}function To(){let{router:e}=Co("useNavigate"),r=Ut("useNavigate"),n=u.useRef(!1);return or(()=>{n.current=!0}),u.useCallback(async(s,i={})=>{fe(n.current,rr),n.current&&(typeof s=="number"?await e.navigate(s):await e.navigate(s,{fromRouteId:r,...i}))},[e,r])}var sn={};function ar(e,r,n){!r&&!sn[e]&&(sn[e]=!0,fe(!1,n))}u.memo(Io);function Io({routes:e,future:r,state:n,isStatic:o,onError:s}){return sr(e,void 0,{state:n,isStatic:o,onError:s})}function pe(e){te(!1,"A <Route> is only ever to be used as the child of <Routes> element, never rendered directly. Please wrap your <Route> in a <Routes>.")}function _o({basename:e="/",children:r=null,location:n,navigationType:o="POP",navigator:s,static:i=!1,unstable_useTransitions:a}){te(!Ge(),"You cannot render a <Router> inside another <Router>. You should never have more than one in your app.");let l=e.replace(/^\/*/,"/"),d=u.useMemo(()=>({basename:l,navigator:s,static:i,unstable_useTransitions:a,future:{}}),[l,s,i,a]);typeof n=="string"&&(n=Me(n));let{pathname:c="/",search:p="",hash:f="",state:h=null,key:S="default",unstable_mask:b}=n,x=u.useMemo(()=>{let v=be(c,l);return v==null?null:{location:{pathname:v,search:p,hash:f,state:h,key:S,unstable_mask:b},navigationType:o}},[l,c,p,f,h,S,o,b]);return fe(x!=null,`<Router basename="${l}"> is not able to match the URL "${c}${p}${f}" because it does not start with the basename, so the <Router> won't render anything.`),x==null?null:u.createElement(ce.Provider,{value:d},u.createElement(Pe.Provider,{children:r,value:x}))}function No({children:e,location:r}){return vo(It(e),r)}function It(e,r=[]){let n=[];return u.Children.forEach(e,(o,s)=>{if(!u.isValidElement(o))return;let i=[...r,s];if(o.type===u.Fragment){n.push.apply(n,It(o.props.children,i));return}te(o.type===pe,`[${typeof o.type=="string"?o.type:o.type.name}] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>`),te(!o.props.index||!o.props.children,"An index route cannot have child routes.");let a={id:o.props.id||i.join("-"),caseSensitive:o.props.caseSensitive,element:o.props.element,Component:o.props.Component,index:o.props.index,path:o.props.path,middleware:o.props.middleware,loader:o.props.loader,action:o.props.action,hydrateFallbackElement:o.props.hydrateFallbackElement,HydrateFallback:o.props.HydrateFallback,errorElement:o.props.errorElement,ErrorBoundary:o.props.ErrorBoundary,hasErrorBoundary:o.props.hasErrorBoundary===!0||o.props.ErrorBoundary!=null||o.props.errorElement!=null,shouldRevalidate:o.props.shouldRevalidate,handle:o.props.handle,lazy:o.props.lazy};o.props.children&&(a.children=It(o.props.children,i)),n.push(a)}),n}var it="get",at="application/x-www-form-urlencoded";function pt(e){return typeof HTMLElement<"u"&&e instanceof HTMLElement}function Mo(e){return pt(e)&&e.tagName.toLowerCase()==="button"}function Oo(e){return pt(e)&&e.tagName.toLowerCase()==="form"}function Po(e){return pt(e)&&e.tagName.toLowerCase()==="input"}function zo(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}function Bo(e,r){return e.button===0&&(!r||r==="_self")&&!zo(e)}var Qe=null;function Lo(){if(Qe===null)try{new FormData(document.createElement("form"),0),Qe=!1}catch{Qe=!0}return Qe}var qo=new Set(["application/x-www-form-urlencoded","multipart/form-data","text/plain"]);function yt(e){return e!=null&&!qo.has(e)?(fe(!1,`"${e}" is not a valid \`encType\` for \`<Form>\`/\`<fetcher.Form>\` and will default to "${at}"`),null):e}function Vo(e,r){let n,o,s,i,a;if(Oo(e)){let l=e.getAttribute("action");o=l?be(l,r):null,n=e.getAttribute("method")||it,s=yt(e.getAttribute("enctype"))||at,i=new FormData(e)}else if(Mo(e)||Po(e)&&(e.type==="submit"||e.type==="image")){let l=e.form;if(l==null)throw new Error('Cannot submit a <button> or <input type="submit"> without a <form>');let d=e.getAttribute("formaction")||l.getAttribute("action");if(o=d?be(d,r):null,n=e.getAttribute("formmethod")||l.getAttribute("method")||it,s=yt(e.getAttribute("formenctype"))||yt(l.getAttribute("enctype"))||at,i=new FormData(l,e),!Lo()){let{name:c,type:p,value:f}=e;if(p==="image"){let h=c?`${c}.`:"";i.append(`${h}x`,"0"),i.append(`${h}y`,"0")}else c&&i.append(c,f)}}else{if(pt(e))throw new Error('Cannot submit element that is not <form>, <button>, or <input type="submit|image">');n=it,o=null,s=at,a=e}return i&&s==="text/plain"&&(a=i,i=void 0),{action:o,method:n.toLowerCase(),encType:s,formData:i,body:a}}Object.getOwnPropertyNames(Object.prototype).sort().join("\0");function Wt(e,r){if(e===!1||e===null||typeof e>"u")throw new Error(r)}function $o(e,r,n,o){let s=typeof e=="string"?new URL(e,typeof window>"u"?"server://singlefetch/":window.location.origin):e;return n?s.pathname.endsWith("/")?s.pathname=`${s.pathname}_.${o}`:s.pathname=`${s.pathname}.${o}`:s.pathname==="/"?s.pathname=`_root.${o}`:r&&be(s.pathname,r)==="/"?s.pathname=`${r.replace(/\/$/,"")}/_root.${o}`:s.pathname=`${s.pathname.replace(/\/$/,"")}.${o}`,s}async function Uo(e,r){if(e.id in r)return r[e.id];try{let n=await import(e.module);return r[e.id]=n,n}catch(n){return console.error(`Error loading route module \`${e.module}\`, reloading page...`),console.error(n),window.__reactRouterContext&&window.__reactRouterContext.isSpaMode,window.location.reload(),new Promise(()=>{})}}function Wo(e){return e==null?!1:e.href==null?e.rel==="preload"&&typeof e.imageSrcSet=="string"&&typeof e.imageSizes=="string":typeof e.rel=="string"&&typeof e.href=="string"}async function Ho(e,r,n){let o=await Promise.all(e.map(async s=>{let i=r.routes[s.route.id];if(i){let a=await Uo(i,n);return a.links?a.links():[]}return[]}));return Jo(o.flat(1).filter(Wo).filter(s=>s.rel==="stylesheet"||s.rel==="preload").map(s=>s.rel==="stylesheet"?{...s,rel:"prefetch",as:"style"}:{...s,rel:"prefetch"}))}function an(e,r,n,o,s,i){let a=(d,c)=>n[c]?d.route.id!==n[c].route.id:!0,l=(d,c)=>{var p;return n[c].pathname!==d.pathname||((p=n[c].route.path)==null?void 0:p.endsWith("*"))&&n[c].params["*"]!==d.params["*"]};return i==="assets"?r.filter((d,c)=>a(d,c)||l(d,c)):i==="data"?r.filter((d,c)=>{var f;let p=o.routes[d.route.id];if(!p||!p.hasLoader)return!1;if(a(d,c)||l(d,c))return!0;if(d.route.shouldRevalidate){let h=d.route.shouldRevalidate({currentUrl:new URL(s.pathname+s.search+s.hash,window.origin),currentParams:((f=n[0])==null?void 0:f.params)||{},nextUrl:new URL(e,window.origin),nextParams:d.params,defaultShouldRevalidate:!0});if(typeof h=="boolean")return h}return!0}):[]}function Ko(e,r,{includeHydrateFallback:n}={}){return Go(e.map(o=>{let s=r.routes[o.route.id];if(!s)return[];let i=[s.module];return s.clientActionModule&&(i=i.concat(s.clientActionModule)),s.clientLoaderModule&&(i=i.concat(s.clientLoaderModule)),n&&s.hydrateFallbackModule&&(i=i.concat(s.hydrateFallbackModule)),s.imports&&(i=i.concat(s.imports)),i}).flat(1))}function Go(e){return[...new Set(e)]}function Yo(e){let r={},n=Object.keys(e).sort();for(let o of n)r[o]=e[o];return r}function Jo(e,r){let n=new Set;return new Set(r),e.reduce((o,s)=>{let i=JSON.stringify(Yo(s));return n.has(i)||(n.add(i),o.push({key:i,link:s})),o},[])}function lr(){let e=u.useContext(Oe);return Wt(e,"You must render this element inside a <DataRouterContext.Provider> element"),e}function Qo(){let e=u.useContext(ut);return Wt(e,"You must render this element inside a <DataRouterStateContext.Provider> element"),e}var Ht=u.createContext(void 0);Ht.displayName="FrameworkContext";function cr(){let e=u.useContext(Ht);return Wt(e,"You must render this element inside a <HydratedRouter> element"),e}function Xo(e,r){let n=u.useContext(Ht),[o,s]=u.useState(!1),[i,a]=u.useState(!1),{onFocus:l,onBlur:d,onMouseEnter:c,onMouseLeave:p,onTouchStart:f}=r,h=u.useRef(null);u.useEffect(()=>{if(e==="render"&&a(!0),e==="viewport"){let x=w=>{w.forEach(T=>{a(T.isIntersecting)})},v=new IntersectionObserver(x,{threshold:.5});return h.current&&v.observe(h.current),()=>{v.disconnect()}}},[e]),u.useEffect(()=>{if(o){let x=setTimeout(()=>{a(!0)},100);return()=>{clearTimeout(x)}}},[o]);let S=()=>{s(!0)},b=()=>{s(!1),a(!1)};return n?e!=="intent"?[i,h,{}]:[i,h,{onFocus:Be(l,S),onBlur:Be(d,b),onMouseEnter:Be(c,S),onMouseLeave:Be(p,b),onTouchStart:Be(f,S)}]:[!1,h,{}]}function Be(e,r){return n=>{e&&e(n),n.defaultPrevented||r(n)}}function Zo({page:e,...r}){let{router:n}=lr(),o=u.useMemo(()=>Gn(n.routes,e,n.basename),[n.routes,e,n.basename]);return o?u.createElement(ts,{page:e,matches:o,...r}):null}function es(e){let{manifest:r,routeModules:n}=cr(),[o,s]=u.useState([]);return u.useEffect(()=>{let i=!1;return Ho(e,r,n).then(a=>{i||s(a)}),()=>{i=!0}},[e,r,n]),o}function ts({page:e,matches:r,...n}){let o=ge(),{future:s,manifest:i,routeModules:a}=cr(),{basename:l}=lr(),{loaderData:d,matches:c}=Qo(),p=u.useMemo(()=>an(e,r,c,i,o,"data"),[e,r,c,i,o]),f=u.useMemo(()=>an(e,r,c,i,o,"assets"),[e,r,c,i,o]),h=u.useMemo(()=>{if(e===o.pathname+o.search+o.hash)return[];let x=new Set,v=!1;if(r.forEach(T=>{var m;let I=i.routes[T.route.id];!I||!I.hasLoader||(!p.some(D=>D.route.id===T.route.id)&&T.route.id in d&&((m=a[T.route.id])!=null&&m.shouldRevalidate)||I.hasClientLoader?v=!0:x.add(T.route.id))}),x.size===0)return[];let w=$o(e,l,s.unstable_trailingSlashAwareDataRequests,"data");return v&&x.size>0&&w.searchParams.set("_routes",r.filter(T=>x.has(T.route.id)).map(T=>T.route.id).join(",")),[w.pathname+w.search]},[l,s.unstable_trailingSlashAwareDataRequests,d,o,i,p,r,e,a]),S=u.useMemo(()=>Ko(f,i),[f,i]),b=es(f);return u.createElement(u.Fragment,null,h.map(x=>u.createElement("link",{key:x,rel:"prefetch",as:"fetch",href:x,...n})),S.map(x=>u.createElement("link",{key:x,rel:"modulepreload",href:x,...n})),b.map(({key:x,link:v})=>u.createElement("link",{key:x,nonce:n.nonce,...v,crossOrigin:v.crossOrigin??n.crossOrigin})))}function ns(...e){return r=>{e.forEach(n=>{typeof n=="function"?n(r):n!=null&&(n.current=r)})}}var rs=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";try{rs&&(window.__reactRouterVersion="7.13.2")}catch{}function os({basename:e,children:r,unstable_useTransitions:n,window:o}){let s=u.useRef();s.current==null&&(s.current=Or({window:o,v5Compat:!0}));let i=s.current,[a,l]=u.useState({action:i.action,location:i.location}),d=u.useCallback(c=>{n===!1?l(c):u.startTransition(()=>l(c))},[n]);return u.useLayoutEffect(()=>i.listen(d),[i,d]),u.createElement(_o,{basename:e,children:r,location:a.location,navigationType:a.action,navigator:i,unstable_useTransitions:n})}var dr=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,ur=u.forwardRef(function({onClick:r,discover:n="render",prefetch:o="none",relative:s,reloadDocument:i,replace:a,unstable_mask:l,state:d,target:c,to:p,preventScrollReset:f,viewTransition:h,unstable_defaultShouldRevalidate:S,...b},x){let{basename:v,navigator:w,unstable_useTransitions:T}=u.useContext(ce),I=typeof p=="string"&&dr.test(p),m=Zn(p,v);p=m.to;let D=yo(p,{relative:s}),F=ge(),E=null;if(l){let H=Lt(l,[],F.unstable_mask?F.unstable_mask.pathname:"/",!0);v!=="/"&&(H.pathname=H.pathname==="/"?v:me([v,H.pathname])),E=w.createHref(H)}let[R,O,C]=Xo(o,b),B=ls(p,{replace:a,unstable_mask:l,state:d,target:c,preventScrollReset:f,relative:s,viewTransition:h,unstable_defaultShouldRevalidate:S,unstable_useTransitions:T});function P(H){r&&r(H),H.defaultPrevented||B(H)}let L=!(m.isExternal||i),K=u.createElement("a",{...b,...C,href:(L?E:void 0)||m.absoluteURL||D,onClick:L?P:r,ref:ns(x,O),target:c,"data-discover":!I&&n==="render"?"true":void 0});return R&&!I?u.createElement(u.Fragment,null,K,u.createElement(Zo,{page:D})):K});ur.displayName="Link";var ss=u.forwardRef(function({"aria-current":r="page",caseSensitive:n=!1,className:o="",end:s=!1,style:i,to:a,viewTransition:l,children:d,...c},p){let f=Ye(a,{relative:c.relative}),h=ge(),S=u.useContext(ut),{navigator:b,basename:x}=u.useContext(ce),v=S!=null&&ms(f)&&l===!0,w=b.encodeLocation?b.encodeLocation(f).pathname:f.pathname,T=h.pathname,I=S&&S.navigation&&S.navigation.location?S.navigation.location.pathname:null;n||(T=T.toLowerCase(),I=I?I.toLowerCase():null,w=w.toLowerCase()),I&&x&&(I=be(I,x)||I);const m=w!=="/"&&w.endsWith("/")?w.length-1:w.length;let D=T===w||!s&&T.startsWith(w)&&T.charAt(m)==="/",F=I!=null&&(I===w||!s&&I.startsWith(w)&&I.charAt(w.length)==="/"),E={isActive:D,isPending:F,isTransitioning:v},R=D?r:void 0,O;typeof o=="function"?O=o(E):O=[o,D?"active":null,F?"pending":null,v?"transitioning":null].filter(Boolean).join(" ");let C=typeof i=="function"?i(E):i;return u.createElement(ur,{...c,"aria-current":R,className:O,ref:p,style:C,to:a,viewTransition:l},typeof d=="function"?d(E):d)});ss.displayName="NavLink";var is=u.forwardRef(({discover:e="render",fetcherKey:r,navigate:n,reloadDocument:o,replace:s,state:i,method:a=it,action:l,onSubmit:d,relative:c,preventScrollReset:p,viewTransition:f,unstable_defaultShouldRevalidate:h,...S},b)=>{let{unstable_useTransitions:x}=u.useContext(ce),v=us(),w=ps(l,{relative:c}),T=a.toLowerCase()==="get"?"get":"post",I=typeof l=="string"&&dr.test(l),m=D=>{if(d&&d(D),D.defaultPrevented)return;D.preventDefault();let F=D.nativeEvent.submitter,E=(F==null?void 0:F.getAttribute("formmethod"))||a,R=()=>v(F||D.currentTarget,{fetcherKey:r,method:E,navigate:n,replace:s,state:i,relative:c,preventScrollReset:p,viewTransition:f,unstable_defaultShouldRevalidate:h});x&&n!==!1?u.startTransition(()=>R()):R()};return u.createElement("form",{ref:b,method:T,action:w,onSubmit:o?d:m,...S,"data-discover":!I&&e==="render"?"true":void 0})});is.displayName="Form";function as(e){return`${e} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function pr(e){let r=u.useContext(Oe);return te(r,as(e)),r}function ls(e,{target:r,replace:n,unstable_mask:o,state:s,preventScrollReset:i,relative:a,viewTransition:l,unstable_defaultShouldRevalidate:d,unstable_useTransitions:c}={}){let p=ve(),f=ge(),h=Ye(e,{relative:a});return u.useCallback(S=>{if(Bo(S,r)){S.preventDefault();let b=n!==void 0?n:He(f)===He(h),x=()=>p(e,{replace:b,unstable_mask:o,state:s,preventScrollReset:i,relative:a,viewTransition:l,unstable_defaultShouldRevalidate:d});c?u.startTransition(()=>x()):x()}},[f,p,h,n,o,s,r,e,i,a,l,d,c])}var cs=0,ds=()=>`__${String(++cs)}__`;function us(){let{router:e}=pr("useSubmit"),{basename:r}=u.useContext(ce),n=Fo(),o=e.fetch,s=e.navigate;return u.useCallback(async(i,a={})=>{let{action:l,method:d,encType:c,formData:p,body:f}=Vo(i,r);if(a.navigate===!1){let h=a.fetcherKey||ds();await o(h,n,a.action||l,{unstable_defaultShouldRevalidate:a.unstable_defaultShouldRevalidate,preventScrollReset:a.preventScrollReset,formData:p,body:f,formMethod:a.method||d,formEncType:a.encType||c,flushSync:a.flushSync})}else await s(a.action||l,{unstable_defaultShouldRevalidate:a.unstable_defaultShouldRevalidate,preventScrollReset:a.preventScrollReset,formData:p,body:f,formMethod:a.method||d,formEncType:a.encType||c,replace:a.replace,state:a.state,fromRouteId:n,flushSync:a.flushSync,viewTransition:a.viewTransition})},[o,s,r,n])}function ps(e,{relative:r}={}){let{basename:n}=u.useContext(ce),o=u.useContext(he);te(o,"useFormAction must be used inside a RouteContext");let[s]=o.matches.slice(-1),i={...Ye(e||".",{relative:r})},a=ge();if(e==null){i.search=a.search;let l=new URLSearchParams(i.search),d=l.getAll("index");if(d.some(p=>p==="")){l.delete("index"),d.filter(f=>f).forEach(f=>l.append("index",f));let p=l.toString();i.search=p?`?${p}`:""}}return(!e||e===".")&&s.route.index&&(i.search=i.search?i.search.replace(/^\?/,"?index&"):"?index"),n!=="/"&&(i.pathname=i.pathname==="/"?n:me([n,i.pathname])),He(i)}function ms(e,{relative:r}={}){let n=u.useContext(tr);te(n!=null,"`useViewTransitionState` must be used within `react-router-dom`'s `RouterProvider`. Did you accidentally import `RouterProvider` from `react-router`?");let{basename:o}=pr("useViewTransitionState"),s=Ye(e,{relative:r});if(!n.isTransitioning)return!1;let i=be(n.currentLocation.pathname,o)||n.currentLocation.pathname,a=be(n.nextLocation.pathname,o)||n.nextLocation.pathname;return dt(s.pathname,a)!=null||dt(s.pathname,i)!=null}const fs="modulepreload",hs=function(e){return"/"+e},ln={},oe=function(r,n,o){let s=Promise.resolve();if(n&&n.length>0){let a=function(c){return Promise.all(c.map(p=>Promise.resolve(p).then(f=>({status:"fulfilled",value:f}),f=>({status:"rejected",reason:f}))))};document.getElementsByTagName("link");const l=document.querySelector("meta[property=csp-nonce]"),d=(l==null?void 0:l.nonce)||(l==null?void 0:l.getAttribute("nonce"));s=a(n.map(c=>{if(c=hs(c),c in ln)return;ln[c]=!0;const p=c.endsWith(".css"),f=p?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${c}"]${f}`))return;const h=document.createElement("link");if(h.rel=p?"stylesheet":fs,p||(h.as="script"),h.crossOrigin="",h.href=c,d&&h.setAttribute("nonce",d),document.head.appendChild(h),p)return new Promise((S,b)=>{h.addEventListener("load",S),h.addEventListener("error",()=>b(new Error(`Unable to preload CSS for ${c}`)))})}))}function i(a){const l=new Event("vite:preloadError",{cancelable:!0});if(l.payload=a,window.dispatchEvent(l),!l.defaultPrevented)throw a}return s.then(a=>{for(const l of a||[])l.status==="rejected"&&i(l.reason);return r().catch(i)})},gs={dependsOn:{}};function ys(e,r){return new Set([e,...(r??gs).dependsOn[e]??[]])}function xs(e,r){const n=r instanceof Set?r:new Set(r);return n.size===0?!1:e.some(o=>n.has(o))}function _t(e){return(e.sourceEnd.type?1:0)+(e.targetEnd.type?1:0)}function mr(e){return _t(e)===0}function fr(e,r){return _t(r)-_t(e)||e.label.localeCompare(r.label)}function mt(e){return new Map(e.map(r=>[r.name,r]))}function hr(e,r){if(e)return r.relationships.find(n=>n.name===e||n.sysmlName===e)}function De(e,r,n){var a;if(!r)return!0;if(!e)return!1;if(e===r)return!0;const o=Array.isArray(n)?mt(n):n;let s=e;const i=new Set;for(;s&&!i.has(s);){if(s===r)return!0;i.add(s),s=(a=o.get(s))==null?void 0:a.superType}return!1}function bs(e,r,n){if(r.isAbstract)return[];const o=mt(n.kinds),s=[];return De(e.kind,r.sourceEnd.type,o)&&s.push("outgoing"),De(e.kind,r.targetEnd.type,o)&&s.push("incoming"),s}function vs(e,r){const n=[];for(const o of r.relationships){const s=bs(e,o,r);s.length>0&&n.push({definition:o,directions:s})}return n.sort((o,s)=>fr(o.definition,s.definition))}function gr(e,r,n){const o=mt(n.kinds),s=[];for(const i of n.relationships)i.isAbstract||(De(e.kind,i.sourceEnd.type,o)&&De(r.kind,i.targetEnd.type,o)&&s.push({definition:i,direction:"outgoing",sourceId:e.id,targetId:r.id}),De(r.kind,i.sourceEnd.type,o)&&De(e.kind,i.targetEnd.type,o)&&s.push({definition:i,direction:"incoming",sourceId:r.id,targetId:e.id}));return s.sort((i,a)=>fr(i.definition,a.definition))}function ws(e,r,n,o,s,i){var f;const a=mt(s.kinds),l=n==="outgoing"?r.targetEnd:r.sourceEnd,d=n==="outgoing"?r.sourceEnd:r.targetEnd;if(!De(e.kind,d.type,a))return[];const c=(f=i==null?void 0:i.query)==null?void 0:f.trim().toLowerCase(),p=[];for(const h of Object.values(o.elements))h.id!==e.id&&De(h.kind,l.type,a)&&(i!=null&&i.kind&&h.kind!==i.kind||i!=null&&i.layer&&h.layer!==i.layer||i!=null&&i.package&&h.package!==i.package||c&&![h.name,h.id,h.shortId,h.kind].filter(Boolean).join(" ").toLowerCase().includes(c)||p.push({element:h,kind:h.kind,layer:h.layer,package:h.package}));return p.sort((h,S)=>h.layer.localeCompare(S.layer)||h.kind.localeCompare(S.kind)||h.element.name.localeCompare(S.element.name)),p}function ks(e){const r=new Map;for(const n of e){const o=`${n.layer}\0${n.kind}`;let s=r.get(o);s||(s={layer:n.layer,kind:n.kind,elements:[]},r.set(o,s)),s.elements.push(n.element)}return Array.from(r.values())}function Ss(e,r,n,o){const s=(r==null?void 0:r.name)??(o==null?void 0:o.sourceId)??"Unknown",i=n?`${n.kind} ${n.name}`:(o==null?void 0:o.targetId)??"Unknown";return`${s} — ${e.label.toLowerCase()} → ${i}`}const Es=["general","interconnection","actionflow","statetransition","sequence","grid","browser","geometry"];new Set(Es);const js={id:"requirements-matrix",name:"Requirements Matrix",description:"Standard requirements spreadsheet with ID, title, description, priority columns. Typical export from DOORS, Jama, or a simple Excel requirements log.",defaultKind:"Requirement",columnMappings:[{sourceColumn:"req id",targetAttribute:"id",transform:"sanitize-id",required:!0},{sourceColumn:"requirement id",targetAttribute:"id",transform:"sanitize-id",required:!0},{sourceColumn:"id",targetAttribute:"id",transform:"sanitize-id",required:!0},{sourceColumn:"req #",targetAttribute:"id",transform:"sanitize-id"},{sourceColumn:"number",targetAttribute:"id",transform:"sanitize-id"},{sourceColumn:"title",targetAttribute:"name",required:!0},{sourceColumn:"requirement title",targetAttribute:"name",required:!0},{sourceColumn:"name",targetAttribute:"name",required:!0},{sourceColumn:"summary",targetAttribute:"name"},{sourceColumn:"description",targetAttribute:"doc"},{sourceColumn:"text",targetAttribute:"doc"},{sourceColumn:"statement",targetAttribute:"doc"},{sourceColumn:"requirement text",targetAttribute:"doc"},{sourceColumn:"kind",targetAttribute:"kind"},{sourceColumn:"type",targetAttribute:"kind"},{sourceColumn:"category",targetAttribute:"category"},{sourceColumn:"priority",targetAttribute:"priority"},{sourceColumn:"rationale",targetAttribute:"rationale"},{sourceColumn:"verification method",targetAttribute:"verificationMethod"},{sourceColumn:"status",targetAttribute:"status"}]},Cs={id:"hazard-log",name:"Hazard Log",description:"ISO 14971 hazard analysis spreadsheet with hazard ID, description, severity, probability and risk level columns.",defaultKind:"Hazard",columnMappings:[{sourceColumn:"hazard id",targetAttribute:"id",transform:"sanitize-id",required:!0},{sourceColumn:"haz id",targetAttribute:"id",transform:"sanitize-id"},{sourceColumn:"id",targetAttribute:"id",transform:"sanitize-id",required:!0},{sourceColumn:"hazard",targetAttribute:"name",required:!0},{sourceColumn:"hazard description",targetAttribute:"name",required:!0},{sourceColumn:"name",targetAttribute:"name",required:!0},{sourceColumn:"description",targetAttribute:"doc"},{sourceColumn:"hazardous situation",targetAttribute:"doc"},{sourceColumn:"kind",targetAttribute:"kind"},{sourceColumn:"severity",targetAttribute:"severity"},{sourceColumn:"probability",targetAttribute:"probability"},{sourceColumn:"risk level",targetAttribute:"riskLevel"},{sourceColumn:"risk",targetAttribute:"riskLevel"},{sourceColumn:"harm",targetAttribute:"harm"},{sourceColumn:"foreseeable misuse",targetAttribute:"foreseeableMisuse"},{sourceColumn:"mitigation",targetAttribute:"mitigation"},{sourceColumn:"residual risk",targetAttribute:"residualRisk"},{sourceColumn:"status",targetAttribute:"status"}]},Ds={id:"fmea-worksheet",name:"FMEA Worksheet",description:"Failure Mode and Effects Analysis spreadsheet. Maps component failure modes to MEMO Failure kind with FMEA attributes (severity, occurrence, detection, RPN).",defaultKind:"Failure",columnMappings:[{sourceColumn:"id",targetAttribute:"id",transform:"sanitize-id",required:!0},{sourceColumn:"fmea id",targetAttribute:"id",transform:"sanitize-id"},{sourceColumn:"failure mode",targetAttribute:"name",required:!0},{sourceColumn:"failure mode description",targetAttribute:"name"},{sourceColumn:"name",targetAttribute:"name",required:!0},{sourceColumn:"description",targetAttribute:"doc"},{sourceColumn:"effect",targetAttribute:"doc"},{sourceColumn:"effect of failure",targetAttribute:"effect"},{sourceColumn:"kind",targetAttribute:"kind"},{sourceColumn:"component",targetAttribute:"component"},{sourceColumn:"function",targetAttribute:"function"},{sourceColumn:"severity",targetAttribute:"severity"},{sourceColumn:"s",targetAttribute:"severity"},{sourceColumn:"occurrence",targetAttribute:"occurrence"},{sourceColumn:"o",targetAttribute:"occurrence"},{sourceColumn:"detection",targetAttribute:"detection"},{sourceColumn:"d",targetAttribute:"detection"},{sourceColumn:"rpn",targetAttribute:"rpn"},{sourceColumn:"risk priority number",targetAttribute:"rpn"},{sourceColumn:"cause",targetAttribute:"cause"},{sourceColumn:"controls",targetAttribute:"controls"},{sourceColumn:"action",targetAttribute:"action"}]},As={id:"verification-table",name:"Verification Table",description:"Verification and validation traceability matrix mapping requirements to test methods and results.",defaultKind:"VerificationTest",columnMappings:[{sourceColumn:"test id",targetAttribute:"id",transform:"sanitize-id",required:!0},{sourceColumn:"verification id",targetAttribute:"id",transform:"sanitize-id"},{sourceColumn:"id",targetAttribute:"id",transform:"sanitize-id",required:!0},{sourceColumn:"test name",targetAttribute:"name",required:!0},{sourceColumn:"name",targetAttribute:"name",required:!0},{sourceColumn:"title",targetAttribute:"name"},{sourceColumn:"description",targetAttribute:"doc"},{sourceColumn:"objective",targetAttribute:"doc"},{sourceColumn:"kind",targetAttribute:"kind"},{sourceColumn:"requirement id",targetAttribute:"requirementId"},{sourceColumn:"req id",targetAttribute:"requirementId"},{sourceColumn:"method",targetAttribute:"method"},{sourceColumn:"test method",targetAttribute:"method"},{sourceColumn:"verification method",targetAttribute:"method"},{sourceColumn:"result",targetAttribute:"result"},{sourceColumn:"pass/fail",targetAttribute:"result"},{sourceColumn:"status",targetAttribute:"status"},{sourceColumn:"evidence",targetAttribute:"evidence"},{sourceColumn:"notes",targetAttribute:"notes"}]},cn=[js,Cs,Ds,As];function Fs(e,r){return e.map(n=>{const o=n.trim().toLowerCase();if(r){const a=r.columnMappings.find(l=>l.sourceColumn.toLowerCase()===o);if(a)return{...a,sourceColumn:n}}const s=Rs.find(a=>a.sourceColumn.toLowerCase()===o);if(s)return{...s,sourceColumn:n};const i=Ns(n);return{sourceColumn:n,targetAttribute:i}})}const Rs=[{sourceColumn:"id",targetAttribute:"id",transform:"sanitize-id"},{sourceColumn:"identifier",targetAttribute:"id",transform:"sanitize-id"},{sourceColumn:"uid",targetAttribute:"id",transform:"sanitize-id"},{sourceColumn:"name",targetAttribute:"name"},{sourceColumn:"title",targetAttribute:"name"},{sourceColumn:"label",targetAttribute:"name"},{sourceColumn:"description",targetAttribute:"doc"},{sourceColumn:"text",targetAttribute:"doc"},{sourceColumn:"notes",targetAttribute:"doc"},{sourceColumn:"kind",targetAttribute:"kind"},{sourceColumn:"type",targetAttribute:"kind"},{sourceColumn:"category",targetAttribute:"kind"},{sourceColumn:"construct",targetAttribute:"construct"}];function Ts(e,r,n,o){const s=[],i=[],a=new Set,l=[];for(const x of r){if(!x.targetAttribute){i.push(x.sourceColumn);continue}a.has(x.targetAttribute)||(a.add(x.targetAttribute),l.push(x))}const d=a.has("id"),c=a.has("name"),p=a.has("kind");d||s.push("No column mapped to 'id' — id will be auto-generated from row number"),c||s.push("No column mapped to 'name'"),!p&&!o&&s.push("No column mapped to 'kind' and no defaultKind set");const f=["id","name","kind","construct","doc"],h=Array.from(a).filter(x=>!f.includes(x)),S=[...f.filter(x=>a.has(x)),...h];for(const x of["id","name","kind"])S.includes(x)||S.unshift(x);const b=[S.map(dn).join(",")];return e.forEach((x,v)=>{const w={};for(const m of l){const D=x[m.sourceColumn]??"";w[m.targetAttribute]=Is(D,m.transform)}(!w.id||w.id.trim()==="")&&(w.id=`row_${v+1}`),(!w.kind||w.kind.trim()==="")&&o&&(w.kind=o);const T=w.kind;T&&n.kinds&&!n.kinds[T]&&s.push(`Row ${v+2}: unknown kind '${T}' (not in config)`);const I=S.map(m=>dn(w[m]??""));b.push(I.join(","))}),{csv:b.join(`
|
|
14
|
-
`)+`
|
|
15
|
-
`,skippedColumns:i,warnings:s}}function Is(e,r){if(!r)return e;switch(r){case"sanitize-id":return _s(e);case"upper":return e.toUpperCase();case"lower":return e.toLowerCase();default:return e}}function _s(e){let r=e.trim().replace(/[\s\-]+/g,"_").replace(/[^a-zA-Z0-9_]/g,"").toLowerCase();return/^\d/.test(r)&&(r="e_"+r),r}function Ns(e){return e.trim().replace(/[^a-zA-Z0-9 _-]/g,"").split(/[\s_-]+/).map((r,n)=>n===0?r.toLowerCase():r.charAt(0).toUpperCase()+r.slice(1).toLowerCase()).join("")}function dn(e){return e.includes(",")||e.includes('"')||e.includes(`
|
|
16
|
-
`)?`"${e.replace(/"/g,'""')}"`:e}let z=null,Xe=null,xt=0;const Ms=1e4;let Ee=!1,lt=null;const Ne=new Map;function Os(e){const r=Ne.get(e.requestId);r&&(clearTimeout(r.timer),Ne.delete(e.requestId),e.success||e.conflict?r.resolve(e):r.reject(new Error(e.error||`Could not ${e.operation} diagram source.`)))}function Ps(e){for(const r of Ne.values())clearTimeout(r.timer),r.reject(new Error(e));Ne.clear()}const Kt=new Map,Gt=new Map;function un(e,r){const n=r.get(e.requestId);n&&(clearTimeout(n.timer),r.delete(e.requestId),n.resolve(e))}function zs(e){for(const r of[Kt,Gt]){for(const n of r.values())clearTimeout(n.timer),n.reject(new Error(e));r.clear()}}function yr(e,r,n){if(!z||z.readyState!==WebSocket.OPEN)return Promise.reject(new Error("The development server is not connected."));const o=`${e}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`;return new Promise((s,i)=>{const a=setTimeout(()=>{n.delete(o),i(new Error("The server did not answer the relationship request."))},15e3);n.set(o,{resolve:s,reject:i,timer:a}),z.send(JSON.stringify({type:e,payload:{...r,requestId:o}}))})}function Bs(){const e=window.__MEMO_DATA__;if(!e)return!1;const r=k.getState();return r.setConnected(!0),e.model&&r.setModel(e.model),e.validation&&r.setValidation(e.validation),e.completeness&&r.setCompleteness(e.completeness),!0}function xr(e){if(window.__MEMO_DATA__)return;Vs();const r=`ws://${window.location.host}`;if(z&&(z.readyState===WebSocket.OPEN||z.readyState===WebSocket.CONNECTING))return;z=new WebSocket(r);const n=k.getState();z.onopen=()=>{n.setConnected(!0),xt=0,lt=null,Ee=!1,n.setRestartRequired(null),Xe&&(clearTimeout(Xe),Xe=null)},z.onmessage=o=>{try{const s=JSON.parse(o.data);Ls(s)}catch{}},z.onclose=()=>{n.setConnected(!1),Ps("The development server disconnected."),zs("The development server disconnected."),z=null,xt++;const o=Math.min(2e3*Math.pow(2,xt-1),Ms);Xe=setTimeout(()=>xr(),o)},z.onerror=()=>{}}function Ls(e){const r=k.getState();switch(e.type){case"app:restart-required":Ee=!0,r.setRestartRequired(e);return;case"model:update":if(Ee)return;r.setModel(e.payload);break;case"source:changed":if(Ee)return;r.applySourceChange(e.payload);break;case"validation:update":if(Ee)return;r.setValidation(e.payload);break;case"completeness:update":if(Ee)return;r.setCompleteness(e.payload);break;case"methodology:update":if(Ee)return;r.setMethodology(e.payload);break;case"error":console.error("[MEMO] Server error:",e.payload.message);break;case"diagram:parse:result":r.applyDiagramParseResult(e.payload.diagramId,e.payload.elementIds,e.payload.errors);break;case"diagram:source:result":Os(e.payload);break;case"relationship:create:result":un(e.payload,Kt);break;case"relationship:delete:result":un(e.payload,Gt);break;case"ontology:packages":{const n=e.payload.ontologyHash;if(n){if(lt===null)lt=n;else if(lt!==n){Ee=!0,r.setRestartRequired({type:"app:restart-required",reason:"ontology-source-changed",changedFile:"(server restarted with different ontology)",instruction:"Reload the page to connect to the new server."});return}}r.setAvailableOntologies(e.payload.packages);break}case"ontology:install:result":r.setOntologyInstallStatus({installing:!1,lastInstalled:e.payload.success?e.payload.packageName:void 0,error:e.payload.error});break;case"ontology:remove:result":r.setOntologyInstallStatus({installing:!1});break;case"diagram:layout":r.mergeDiagramLayouts(e.payload.layouts);break;case"import:result":r.setImportResult(e.payload);break;case"llm:status":r.setLlmStatus(e.payload.available,e.payload.provider,e.payload.model);break;case"llm:ask:result":e.payload.error?r.rejectLlmRequest(e.payload.requestId,e.payload.error):r.resolveLlmRequest(e.payload.requestId,e.payload.answer);break;case"llm:generate:result":e.payload.error?r.rejectLlmRequest(e.payload.requestId,e.payload.error):r.resolveLlmRequest(e.payload.requestId,{sysml:e.payload.sysml,explanation:e.payload.explanation,suggestedFile:e.payload.suggestedFile});break;case"llm:draft:result":e.payload.error?r.rejectLlmRequest(e.payload.requestId,e.payload.error):r.resolveLlmRequest(e.payload.requestId,{markdown:e.payload.markdown,summary:e.payload.summary});break;case"llm:suggest:result":e.payload.error?r.rejectLlmRequest(e.payload.requestId,e.payload.error):r.resolveLlmRequest(e.payload.requestId,e.payload.suggestions);break;case"dhf:docs":pn(()=>r.setDhfDocuments(e.payload.docs));break;case"dhf:settings":pn(()=>r.hydrateDhfSettings(e.payload.settings));break;case"dhf:templates:result":r.resolveLlmRequest(e.payload.requestId,e.payload.templates);break;case"dhf:template:content":e.payload.error?r.rejectLlmRequest(e.payload.requestId,e.payload.error):r.resolveLlmRequest(e.payload.requestId,e.payload.content);break}}let Nt=!1;const br=600,We=new Map;let Ze=null;function pn(e){Nt=!0;try{e()}finally{Nt=!1}}function Ke(e){z&&z.readyState===WebSocket.OPEN&&z.send(JSON.stringify(e))}function qs(e){const r=We.get(e.id);r&&clearTimeout(r),We.set(e.id,setTimeout(()=>{We.delete(e.id);const n=k.getState().dhfDocuments.find(o=>o.id===e.id);n&&Ke({type:"dhf:doc:save",payload:{doc:n}})},br))}let mn=!1;function Vs(){mn||(mn=!0,k.subscribe((e,r)=>{if(!Nt){if(e.dhfDocuments!==r.dhfDocuments){const n=new Map(r.dhfDocuments.map(o=>[o.id,o]));for(const o of e.dhfDocuments)n.get(o.id)!==o&&qs(o),n.delete(o.id);for(const o of n.keys()){const s=We.get(o);s&&(clearTimeout(s),We.delete(o)),Ke({type:"dhf:doc:delete",payload:{docId:o}})}}e.dhfSettings!==r.dhfSettings&&(Ze&&clearTimeout(Ze),Ze=setTimeout(()=>{Ze=null,Ke({type:"dhf:settings:save",payload:{settings:k.getState().dhfSettings}})},br))}}))}function $s(e){Ke({type:"dhf:templates:list",payload:{requestId:e}})}function Us(e,r){Ke({type:"dhf:template:read",payload:{requestId:e,path:r}})}function Re(e){z&&z.readyState===WebSocket.OPEN&&z.send(JSON.stringify({type:"element:update",payload:e}))}function fn(e){z&&z.readyState===WebSocket.OPEN&&z.send(JSON.stringify({type:"element:create",payload:e}))}function Ws(e){return yr("relationship:create",e,Kt)}function Hs(e){return yr("relationship:delete",e,Gt)}function Ks(e){z&&z.readyState===WebSocket.OPEN&&z.send(JSON.stringify({type:"diagram:create",payload:e}))}function hn(e){z&&z.readyState===WebSocket.OPEN&&z.send(JSON.stringify({type:"diagram:update",payload:e}))}function Gs(e){if(z&&z.readyState===WebSocket.OPEN){const r={id:e};z.send(JSON.stringify({type:"diagram:delete",payload:r}))}}function ec(e,r){if(z&&z.readyState===WebSocket.OPEN){const n={diagramId:e,text:r};z.send(JSON.stringify({type:"diagram:parse",payload:n}))}}function vr(e,r,n){if(!z||z.readyState!==WebSocket.OPEN)return Promise.reject(new Error("The development server is not connected."));const o=`diagram-source-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`;return new Promise((s,i)=>{const a=setTimeout(()=>{Ne.delete(o),i(new Error(`Timed out while trying to ${e} the SysML source.`))},1e4);Ne.set(o,{resolve:s,reject:i,timer:a}),z.send(JSON.stringify({type:e==="load"?"diagram:source:request":"diagram:source:save",payload:{requestId:o,diagramId:r,...e==="save"?n:{}}}))})}function tc(e){return vr("load",e)}function nc(e,r,n){return vr("save",e,{text:r,baseRevision:n})}function Ys(e){z&&z.readyState===WebSocket.OPEN&&z.send(JSON.stringify({type:"element:remap-kinds",payload:{mappings:e}}))}function bt(e){z&&z.readyState===WebSocket.OPEN&&z.send(JSON.stringify({type:"ontology:save-selection",payload:{selected:e}}))}function rc(e){z&&z.readyState===WebSocket.OPEN&&z.send(JSON.stringify({type:"ontology:install",payload:{source:e}}))}function oc(e){z&&z.readyState===WebSocket.OPEN&&z.send(JSON.stringify({type:"open-file",payload:{path:e}}))}function sc(e){z&&z.readyState===WebSocket.OPEN&&z.send(JSON.stringify({type:"ontology:remove",payload:{packageName:e}}))}function ic(e,r){z&&z.readyState===WebSocket.OPEN&&z.send(JSON.stringify({type:"diagram:layout:update",payload:{diagramId:e,layout:r}}))}function Js(e){z&&z.readyState===WebSocket.OPEN&&z.send(JSON.stringify({type:"csv:import",payload:e}))}function ac(e,r){z&&z.readyState===WebSocket.OPEN&&z.send(JSON.stringify({type:"llm:ask",payload:{requestId:e,question:r}}))}function lc(e,r){z&&z.readyState===WebSocket.OPEN&&z.send(JSON.stringify({type:"llm:generate",payload:{requestId:e,description:r}}))}function cc(e,r,n){z&&z.readyState===WebSocket.OPEN&&z.send(JSON.stringify({type:"llm:draft",payload:{requestId:e,documentTypeId:r,targetSections:n}}))}const gn="memo:userViewpoints",Mt="memo:activeView";function Qs(){try{const e=JSON.parse(sessionStorage.getItem(Mt)??"null");if((e==null?void 0:e.type)==="diagram"&&typeof e.diagramId=="string")return e}catch{}return{type:"welcome"}}function yn(e){try{e.type==="diagram"?sessionStorage.setItem(Mt,JSON.stringify(e)):sessionStorage.removeItem(Mt)}catch{}}function Xs(){try{const e=localStorage.getItem(gn);if(e){const r=JSON.parse(e);return localStorage.removeItem(gn),r.length>0&&console.warn(`[MEMO] Migrated ${r.length} user viewpoint(s) from localStorage. Save them to memo.viewpoints.yaml to persist across sessions.`),r}}catch{}return[]}const je="_folder",et=Qs(),k=Kn((e,r)=>({model:null,validation:null,completeness:null,connected:!1,restartRequired:null,methodology:null,lastSourceChange:null,activeMode:et.type==="diagram"?"diagram":"catalog",activeView:et,explorerTab:"model",selectedElementId:null,selectedRelationshipId:null,selectedElementIds:new Set,recentlyVisited:[],selectedViewpointId:null,selectedDiagramId:et.type==="diagram"?et.diagramId:null,searchTerm:"",sidebarCollapsed:!1,propertiesPanelCollapsed:!0,hiddenLayers:new Set,ontologyGroupBy:"layer",collapsedGroups:new Set,availableOntologies:[],selectedOntologies:new Set,focusedOntologyId:null,selectedOntologyKind:null,ontologyViewMode:"visual",showOntologyRelationships:!1,highlightedRelationshipType:null,hiddenEdgeTypes:new Set(["extends"]),ontologyInstallStatus:{installing:!1},gapBarExpanded:!1,gapBarHeight:160,catalogGroupBy:"semantic",catalogCollapsed:new Set,contextMenu:null,attributeFilter:null,labelFilter:null,tagFilters:[],userViewpoints:Xs(),diagramLayouts:{},mergeDiagramLayouts:n=>e(o=>({diagramLayouts:{...o.diagramLayouts,...n}})),setNodeLayout:(n,o,s)=>e(i=>{const a=i.diagramLayouts[n]??{nodes:{},edges:{}};return{diagramLayouts:{...i.diagramLayouts,[n]:{...a,nodes:{...a.nodes,[o]:{...a.nodes[o]??{},...s}}}}}}),diagramParseErrors:{},dhfDocuments:[],dhfSettings:{company:"",product:"",deviceType:"",version:"0.1",phase:"",logoUrl:"",compactLogoUrl:"",primaryColor:"#1B3A4B",compactMode:!1,headerTemplate:"**{{project.product}}** | {{id}} | Rev {{project.version}}",footerTemplate:"Confidential — {{project.company}} | Page {{page}}",documentNumberingPrefix:"DOC"},bulkImportOpen:!1,importResult:null,llmAvailable:!1,llmProvider:void 0,llmModel:void 0,llmPending:new Map,setLlmStatus:(n,o,s)=>e({llmAvailable:n,llmProvider:o,llmModel:s}),registerLlmRequest:(n,o,s)=>e(i=>{const a=new Map(i.llmPending);return a.set(n,{resolve:o,reject:s}),{llmPending:a}}),resolveLlmRequest:(n,o)=>e(s=>{const i=s.llmPending.get(n);if(i){i.resolve(o);const a=new Map(s.llmPending);return a.delete(n),{llmPending:a}}return{}}),rejectLlmRequest:(n,o)=>e(s=>{const i=s.llmPending.get(n);if(i){i.reject(new Error(o));const a=new Map(s.llmPending);return a.delete(n),{llmPending:a}}return{}}),analysisIssues:[],editingElementId:null,pendingEdits:new Map,pendingRelationships:[],createRelationship:async n=>{const o=`pending-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`,s=ei(r().model,n.type);e(a=>({pendingRelationships:[...a.pendingRelationships,{pendingId:o,type:n.type,label:(s==null?void 0:s.label)??n.type,sourceId:n.sourceId,targetId:n.targetId,direction:n.direction,status:"saving"}]}));const i=(a,l)=>(e(d=>({pendingRelationships:d.pendingRelationships.map(c=>c.pendingId===o?{...c,status:"failed",error:a}:c)})),{success:!1,error:a,diagnostics:l});try{const a=await Ws(n);return a.success?(e(l=>({pendingRelationships:l.pendingRelationships.filter(d=>d.pendingId!==o)})),{success:!0,relationshipId:a.relationshipId,sourceFile:a.sourceFile,diagnostics:a.diagnostics}):i(a.error??"The relationship could not be created.",a.diagnostics)}catch(a){return i(a instanceof Error?a.message:String(a))}},deleteRelationship:async n=>{try{const o=await Hs({relationshipId:n});return o.success?(e(s=>s.model?{model:{...s.model,relationships:s.model.relationships.filter(i=>i.id!==n)},selectedRelationshipId:s.selectedRelationshipId===n?null:s.selectedRelationshipId}:{}),{success:!0,sourceFile:o.sourceFile}):{success:!1,error:o.error??"The relationship could not be deleted."}}catch(o){return{success:!1,error:o instanceof Error?o.message:String(o)}}},dismissPendingRelationship:n=>e(o=>({pendingRelationships:o.pendingRelationships.filter(s=>s.pendingId!==n)})),setRestartRequired:n=>e({restartRequired:n}),applySourceChange:n=>e(o=>{var s;return{lastSourceChange:{...n,seq:(((s=o.lastSourceChange)==null?void 0:s.seq)??0)+1}}}),setMethodology:n=>e({methodology:n}),setModel:n=>e(o=>{var l,d,c,p;let s=o.activeView,i=o.selectedDiagramId,a=o.selectedViewpointId;if(s.type==="diagram"){const f=s.diagramId,h=(l=n.diagrams)==null?void 0:l.find(x=>x.id===f),S=(c=(d=o.model)==null?void 0:d.diagrams)==null?void 0:c.find(x=>x.id===f),b=h??(S!=null&&S.sourceFile?(p=n.diagrams)==null?void 0:p.find(x=>x.sourceFile===S.sourceFile):void 0);b&&(b.id!==f&&(s={type:"diagram",diagramId:b.id},yn(s)),i=b.id,a=b.viewpointId==="__model"?null:b.viewpointId)}else(s.type==="welcome"||s.type==="dashboard")&&Object.keys(n.elements).length>0&&(s={type:"dashboard"});return{model:n,activeView:s,selectedDiagramId:i,selectedViewpointId:a}}),setValidation:n=>e({validation:n}),setCompleteness:n=>e({completeness:n}),setConnected:n=>e({connected:n}),setAnalysisIssues:n=>e({analysisIssues:n}),setActiveMode:n=>e({activeMode:n}),setActiveView:n=>{yn(n),e({activeView:n})},setExplorerTab:n=>e({explorerTab:n}),selectElement:n=>{e(n?o=>{const s=[n,...o.recentlyVisited.filter(i=>i!==n)].slice(0,20);return{selectedElementId:n,activeView:{type:"element-detail",elementId:n},recentlyVisited:s}}:{selectedElementId:n})},inspectElement:n=>e(o=>({selectedElementId:n,selectedRelationshipId:null,propertiesPanelCollapsed:n?!1:o.propertiesPanelCollapsed,recentlyVisited:n?[n,...o.recentlyVisited.filter(s=>s!==n)].slice(0,20):o.recentlyVisited})),inspectRelationship:n=>e({selectedRelationshipId:n,selectedElementId:null,propertiesPanelCollapsed:n?!1:r().propertiesPanelCollapsed}),toggleElementSelection:n=>e(o=>{const s=new Set(o.selectedElementIds);return s.has(n)?s.delete(n):s.add(n),{selectedElementIds:s}}),selectAllElements:n=>e({selectedElementIds:new Set(n)}),clearElementSelection:()=>e({selectedElementIds:new Set}),updateElementKind:(n,o)=>{const{model:s}=r();if(!s)return;const i=s.elements[n];if(!i)return;const a={...i,kind:o};e(l=>({model:l.model?{...l.model,elements:{...l.model.elements,[n]:a}}:null})),Re(a)},bulkUpdateAttributes:(n,o)=>{const{model:s}=r();if(!s)return;const i={...s.elements};for(const a of n){const l=i[a];if(!l)continue;const d={...l,attributes:{...l.attributes,...o}};i[a]=d,Re(d)}e(a=>({model:a.model?{...a.model,elements:i}:null}))},selectViewpoint:n=>e({selectedViewpointId:n,selectedDiagramId:null}),selectDiagram:n=>{var i;if(!n){e({selectedDiagramId:null});return}const{model:o}=r(),s=(i=o==null?void 0:o.diagrams)==null?void 0:i.find(a=>a.id===n);e(s?{selectedDiagramId:n,selectedViewpointId:s.viewpointId==="__model"?null:s.viewpointId}:{selectedDiagramId:n})},setSearchTerm:n=>e({searchTerm:n}),toggleSidebar:()=>e(n=>({sidebarCollapsed:!n.sidebarCollapsed})),togglePropertiesPanel:()=>e(n=>({propertiesPanelCollapsed:!n.propertiesPanelCollapsed})),toggleLayerVisibility:n=>e(o=>{const s=new Set(o.hiddenLayers);return s.has(n)?s.delete(n):s.add(n),{hiddenLayers:s}}),setOntologyGroupBy:n=>e({ontologyGroupBy:n,collapsedGroups:new Set}),toggleGroupCollapsed:n=>e(o=>{const s=new Set(o.collapsedGroups);return s.has(n)?s.delete(n):s.add(n),{collapsedGroups:s}}),setAvailableOntologies:n=>e(o=>{let s=new Set(n.filter(l=>l.selected).map(l=>l.name));const i=["@memoarchitect/ontology"];for(const l of n)i.includes(l.name)&&s.add(l.name);s.size===0&&n.length>0&&(s=new Set(n.map(l=>l.name)));const a=o.focusedOntologyId??(s.size>0?[...s][0]:null);return{availableOntologies:n,selectedOntologies:s,focusedOntologyId:a}}),toggleOntologySelection:n=>e(o=>{const s=new Set(o.selectedOntologies);return s.has(n)?s.delete(n):s.add(n),{selectedOntologies:s}}),setFocusedOntology:n=>e({focusedOntologyId:n}),setSelectedOntologyKind:n=>e({selectedOntologyKind:n}),setOntologyViewMode:n=>e({ontologyViewMode:n}),toggleOntologyRelationships:()=>e(n=>({showOntologyRelationships:!n.showOntologyRelationships})),setHighlightedRelationshipType:n=>e(o=>({highlightedRelationshipType:o.highlightedRelationshipType===n?null:n})),toggleHiddenEdgeType:n=>e(o=>{const s=new Set(o.hiddenEdgeTypes);return s.has(n)?s.delete(n):s.add(n),{hiddenEdgeTypes:s}}),saveOntologySelection:()=>{const{model:n,availableOntologies:o,selectedOntologies:s}=r();if(!n)return{success:!0};const i=o.filter(d=>!s.has(d.name)),a=new Set;for(const d of i)for(const c of d.layers)for(const p of c.kinds)a.add(p.name);const l=[];if(a.size>0){for(const d of Object.values(n.elements))if(a.has(d.kind)){const c=i.find(p=>p.layers.some(f=>f.kinds.some(h=>h.name===d.kind)));l.push({elementId:d.id,elementName:d.name,kind:d.kind,fromOntology:(c==null?void 0:c.name)??"unknown"})}}return{success:!0,orphanedElements:l}},setOntologyInstallStatus:n=>e({ontologyInstallStatus:n}),toggleGapBar:()=>e(n=>({gapBarExpanded:!n.gapBarExpanded})),setGapBarHeight:n=>e({gapBarHeight:Math.max(80,Math.min(400,n))}),setCatalogGroupBy:n=>e({catalogGroupBy:n,catalogCollapsed:new Set}),toggleCatalogCollapsed:n=>e(o=>{const s=new Set(o.catalogCollapsed);return s.has(n)?s.delete(n):s.add(n),{catalogCollapsed:s}}),setCatalogCollapsedAll:n=>e(o=>n?{catalogCollapsed:new Set(["__ALL__"])}:{catalogCollapsed:new Set}),setContextMenu:n=>e({contextMenu:n}),setAttributeFilter:n=>e({attributeFilter:n}),setLabelFilter:n=>e({labelFilter:n}),toggleTagFilter:n=>e(o=>({tagFilters:o.tagFilters.includes(n)?o.tagFilters.filter(i=>i!==n):[...o.tagFilters,n]})),clearTagFilters:()=>e({tagFilters:[]}),setEditingElement:n=>e({editingElementId:n}),updateElementField:(n,o,s)=>e(i=>{const a=new Map(i.pendingEdits),l=a.get(n)||{};return a.set(n,{...l,[o]:s}),{pendingEdits:a}}),updateElementAttribute:(n,o,s)=>e(i=>{const a=new Map(i.pendingEdits),l=a.get(n)||{},d={...l.attributes||{},[o]:s};return a.set(n,{...l,attributes:d}),{pendingEdits:a}}),updateElementFolder:(n,o)=>{var a;const s=(a=r().model)==null?void 0:a.elements[n];if(!s)return;const i={...s,attributes:{...s.attributes,[je]:o}};e(l=>({model:l.model?{...l.model,elements:{...l.model.elements,[n]:i}}:null})),Re(i)},moveFolder:(n,o,s)=>{const i=r();if(!i.model)return;const a={...i.model.elements},l=[];for(const[d,c]of Object.entries(a))if(c.kind===n){const p=c.attributes[je]||"";if(p===o||p.startsWith(o+"/")){const f=p.slice(o.length),h=(s+f).replace("//","/"),S={...c,attributes:{...c.attributes,[je]:h}};a[d]=S,l.push(d)}}if(l.length!==0){e(d=>({model:d.model?{...d.model,elements:a}:null}));for(const d of l)Re(a[d])}},addElement:(n,o,s)=>{const i=r();if(!i.model)return;const a=`${n.toLowerCase().replace(/\s+/g,"_")}_${Math.random().toString(36).substr(2,5)}`,l=Object.values(i.model.elements).find(c=>c.kind===n),d={id:a,name:o,kind:n,construct:(l==null?void 0:l.construct)||"part",layer:(l==null?void 0:l.layer)||"Other",doc:"",attributes:{[je]:s},file:(l==null?void 0:l.file)||"model/generated.sysml"};e(c=>({model:c.model?{...c.model,elements:{...c.model.elements,[a]:d}}:null,selectedElementId:a,activeView:{type:"element-detail",elementId:a}})),fn(d)},deleteFolder:(n,o)=>{const s=r();if(!s.model)return;const i={...s.model.elements},a=o.includes("/")?o.split("/").slice(0,-1).join("/"):"",l=[];for(const[d,c]of Object.entries(i))if(c.kind===n){const p=c.attributes[je]||"";if(p===o||p.startsWith(o+"/")){const f=p.replace(o,a).replace("//","/"),h={...c,attributes:{...c.attributes,[je]:f}};i[d]=h,l.push(d)}}if(l.length!==0){e(d=>({model:d.model?{...d.model,elements:i}:null}));for(const d of l)Re(i[d])}},addUserViewpoint:n=>e(o=>({userViewpoints:[...o.userViewpoints,n]})),updateUserViewpoint:n=>e(o=>({userViewpoints:o.userViewpoints.map(s=>s.id===n.id?n:s)})),deleteUserViewpoint:n=>e(o=>({userViewpoints:o.userViewpoints.filter(s=>s.id!==n),selectedViewpointId:o.selectedViewpointId===n?null:o.selectedViewpointId})),createDiagram:({name:n,diagramType:o,viewpointId:s})=>{const i=`diag_${Math.random().toString(36).substr(2,9)}`,a={id:i,name:n,diagramType:o,viewpointId:s,auto:!1,elementIds:[]};e(l=>({model:l.model?{...l.model,diagrams:[...l.model.diagrams??[],a]}:null,selectedDiagramId:i,activeView:{type:"diagram",diagramId:i}})),Ks({id:i,name:n,diagramType:o,viewpointId:s,elementIds:[]})},addElementToDiagram:(n,o)=>{var l;const{model:s}=r(),i=(l=s==null?void 0:s.diagrams)==null?void 0:l.find(d=>d.id===n);if(!i)return;const a=i.elementIds??[];a.includes(o)||r().updateDiagramElementIds(n,[...a,o])},updateDiagramElementIds:(n,o)=>{const{model:s}=r();if(!(s!=null&&s.diagrams))return;const i=s.diagrams.findIndex(d=>d.id===n);if(i<0)return;const a={...s.diagrams[i],elementIds:o},l=[...s.diagrams];l[i]=a,e(d=>({model:d.model?{...d.model,diagrams:l}:null})),hn({id:n,elementIds:o})},deleteDiagram:n=>{e(o=>({model:o.model?{...o.model,diagrams:(o.model.diagrams??[]).filter(s=>s.id!==n)}:null,selectedDiagramId:o.selectedDiagramId===n?null:o.selectedDiagramId,activeView:o.activeView.type==="diagram"&&o.activeView.diagramId===n?{type:"welcome"}:o.activeView})),Gs(n)},applyDiagramParseResult:(n,o,s)=>{const{model:i}=r();if(!(i!=null&&i.diagrams))return;const a=i.diagrams.findIndex(l=>l.id===n);if(a>=0){const l={...i.diagrams[a],elementIds:o},d=[...i.diagrams];d[a]=l,e(c=>({model:c.model?{...c.model,diagrams:d}:null,diagramParseErrors:{...c.diagramParseErrors,[n]:s}})),hn({id:n,elementIds:o})}else e(l=>({diagramParseErrors:{...l.diagramParseErrors,[n]:s}}))},addDhfDocument:n=>e(o=>({dhfDocuments:[...o.dhfDocuments,n]})),setDhfDocuments:n=>e({dhfDocuments:n}),hydrateDhfSettings:n=>e(o=>({dhfSettings:{...o.dhfSettings,...n}})),updateDhfSettings:n=>e(o=>({dhfSettings:{...o.dhfSettings,...n}})),updateDhfDocumentMeta:(n,o)=>e(s=>({dhfDocuments:s.dhfDocuments.map(i=>i.id===n?{...i,...o}:i)})),updateDhfDocumentContent:(n,o)=>e(s=>({dhfDocuments:s.dhfDocuments.map(i=>i.id===n?{...i,content:o}:i)})),removeDhfDocument:n=>e(o=>({dhfDocuments:o.dhfDocuments.filter(s=>s.id!==n),activeView:o.activeView.type==="dhf-document"&&o.activeView.docId===n?{type:"dhf-dashboard"}:o.activeView})),setBulkImportOpen:n=>e({bulkImportOpen:n}),setImportResult:n=>e({importResult:n}),clearImportResult:()=>e({importResult:null}),cancelEdit:n=>e(o=>{const s=new Map(o.pendingEdits);return s.delete(n),{pendingEdits:s}}),applyEdit:async n=>{const{pendingEdits:o,model:s}=r(),i=o.get(n);if(!i||!s)return;const a=s.elements[n];if(!a)return;const l={...a};i.doc!==void 0&&(l.doc=i.doc),i.attributes&&(l.attributes={...a.attributes,...i.attributes}),n.startsWith("new_")?fn(l):Re(l);const d={...s,elements:{...s.elements,[n]:l}},c=new Map(o);c.delete(n),e({model:d,pendingEdits:c})}})),Zs={relationships:[],kinds:[]};function wr(e){return(e==null?void 0:e.registries)??Zs}function ei(e,r){return hr(r,wr(e))}function dc(e){const r=new Map;if(!e)return r;for(const n of Object.values(e.elements))r.has(n.layer)||r.set(n.layer,[]),r.get(n.layer).push(n);return r}function ti(e,r){return e?e.relationships.filter(n=>n.sourceId===r||n.targetId===r):[]}function ft(e,r){return!e||!r||!e.diagrams?null:e.diagrams.find(n=>n.id===r)??null}function uc(e,r){const n=ft(e,r);return n?n.sourceFiles&&n.sourceFiles.length>0?n.sourceFiles:n.sourceFile?[n.sourceFile]:[]:[]}function ni(e,r){var o;const n=r?(o=e==null?void 0:e.elements[r])==null?void 0:o.file:void 0;return n?[...ys(n,e==null?void 0:e.sourceGraph)]:[]}function ri(e,r){return e?xs(e.files,r):!1}function xn(e,r){return e!=null&&e.diagrams?e.diagrams.filter(n=>n.viewpointId===r):[]}const Yt={dashboard:"/",dsm:"/dsm",ontology:"/ontology",traceability:"/traceability","scenario-editor":"/scenarios","model-diff":"/diff","compliance-wizard":"/compliance",statistics:"/statistics","dhf-dashboard":"/dhf","dhf-dashboard-legacy":"/dhf/legacy",ask:"/ask","sysml-generator":"/generate","review-dashboard":"/review","workflow-wizard":"/workflow",import:"/import"},kr={"/dashboard":"dashboard"},oi={...Object.fromEntries(Object.entries(Yt).map(([e,r])=>[r,e])),...kr};function bn(e){return e.toLowerCase().replace(/\s+/g,"-")}function si(e){switch(e.type){case"welcome":return"/";case"ontology-detail":return e.layerId?`/ontology/${encodeURIComponent(e.packageName)}/${encodeURIComponent(e.layerId)}`:`/ontology/${encodeURIComponent(e.packageName)}`;case"dhf-document":return`/dhf/${encodeURIComponent(e.docId)}`;case"tabular":{const r=new URLSearchParams;e.viewpointId&&r.set("viewpoint",e.viewpointId),e.diagramId&&r.set("diagram",e.diagramId);const n=r.toString();return n?`/table?${n}`:"/table"}case"element-detail":case"diagram":return null;default:return Yt[e.type]??null}}function ii(e,r=""){const n=e.length>1?e.replace(/\/+$/,""):e,o=oi[n];if(o)return{type:o};if(n==="/table"){const i=new URLSearchParams(r);return{type:"tabular",viewpointId:i.get("viewpoint")??void 0,diagramId:i.get("diagram")??void 0}}const s=n.split("/").filter(Boolean);return s[0]==="dhf"&&s.length===2?{type:"dhf-document",docId:decodeURIComponent(s[1])}:s[0]==="ontology"&&s.length>=2?{type:"ontology-detail",packageName:decodeURIComponent(s[1]),layerId:s[2]?decodeURIComponent(s[2]):void 0}:null}function ai(e){const r=e.split("/").filter(Boolean);return r[0]==="catalog"&&r.length===3||r[0]==="diagrams"&&r.length===3}function li(){return[...Object.values(Yt),...Object.keys(kr)].filter(e=>e!=="/")}const ci=new Set(["catalog","diagram","dhf"]);function tt(){k(d=>d.model);const e=k(d=>d.setActiveView),r=k(d=>d.setActiveMode),n=k(d=>d.sidebarCollapsed),o=k(d=>d.toggleSidebar),s=k(d=>d.activeMode),i=ve(),a=ci.has(s);function l(){r("catalog"),e({type:"welcome"}),i("/")}return t.jsxs("div",{className:"flex items-center gap-3 px-4 py-2",style:{background:"#0B1E2D",borderBottom:"1px solid rgba(255,255,255,0.06)",position:"relative",zIndex:10},children:[t.jsx("button",{onClick:a?o:void 0,title:n?"Show explorer":"Hide explorer",style:{width:"28px",height:"28px",borderRadius:"6px",background:"none",border:"none",cursor:a?"pointer":"default",color:a?n?"rgba(255,255,255,0.35)":"#2DD4A8":"rgba(255,255,255,0.12)",display:"flex",alignItems:"center",justifyContent:"center",fontSize:"16px",flexShrink:0,transition:"color 150ms"},onMouseEnter:d=>{a&&(d.currentTarget.style.color="#2DD4A8")},onMouseLeave:d=>{a&&(d.currentTarget.style.color=n?"rgba(255,255,255,0.35)":"#2DD4A8")},children:"☰"}),t.jsx("button",{onClick:l,className:"text-sm font-bold transition-opacity",style:{color:"#2DD4A8",letterSpacing:"0.04em",background:"none",border:"none",cursor:"pointer",padding:0},onMouseEnter:d=>d.currentTarget.style.opacity="0.75",onMouseLeave:d=>d.currentTarget.style.opacity="1",title:"Go to home",children:"MEMO Architect"}),t.jsx("div",{className:"flex-1"}),t.jsx("img",{src:"/logo.png",alt:"MEMO",style:{height:40,opacity:.9,cursor:"pointer"},onClick:l,title:"Go to home"})]})}const Sr="memo-working-sets",Er="memo-quick-slots";function di(){return`ws-${Date.now()}-${Math.random().toString(36).slice(2,8)}`}function nt(e){try{localStorage.setItem(Sr,JSON.stringify(e))}catch{}}function ui(){try{const e=localStorage.getItem(Sr);return e?JSON.parse(e):[]}catch{return[]}}function vn(){try{const e=localStorage.getItem(Er);return e?JSON.parse(e):[null,null,null,null]}catch{return[null,null,null,null]}}function wn(e){try{localStorage.setItem(Er,JSON.stringify(e))}catch{}}const vt=Kn((e,r)=>({workingSets:[],activeWorkingSetId:null,quickSlots:vn(),loadFromStorage:()=>{const n=ui(),o=vn();e({workingSets:n,quickSlots:o})},saveWorkingSet:(n,o)=>{const s=di(),i=Date.now(),a={id:s,name:n,createdAt:i,updatedAt:i,state:o},l=[...r().workingSets,a];return e({workingSets:l,activeWorkingSetId:s}),nt(l),s},updateWorkingSet:(n,o)=>{const s=r().workingSets.map(i=>i.id===n?{...i,state:o,updatedAt:Date.now()}:i);e({workingSets:s}),nt(s)},renameWorkingSet:(n,o)=>{const s=r().workingSets.map(i=>i.id===n?{...i,name:o,updatedAt:Date.now()}:i);e({workingSets:s}),nt(s)},deleteWorkingSet:n=>{const o=r().workingSets.filter(i=>i.id!==n),s=r().activeWorkingSetId===n?null:r().activeWorkingSetId;e({workingSets:o,activeWorkingSetId:s}),nt(o)},setActiveWorkingSet:n=>e({activeWorkingSetId:n}),saveQuickSlot:(n,o,s)=>{const i=["Last Session","Slot 1","Slot 2","Slot 3"],a=[...r().quickSlots];for(;a.length<4;)a.push(null);a[n]={name:s??i[n],state:o,savedAt:Date.now()},wn(a),e({quickSlots:a})},clearQuickSlot:n=>{const o=[...r().quickSlots];o[n]=null,wn(o),e({quickSlots:o})}})),j={badge:"12px",xs:"12px",sm:"13px",md:"14px",lg:"15px",explorer:{group:"13px",kind:"12px",item:"13px",element:"13px",count:"12px",search:"13px"}},y={primary:"#1a1a1a",secondary:"#4B5563",muted:"#6B7280",faint:"#9CA3AF",surface:"#FFFFFF",surfaceAlt:"#F7F7F5",border:"#E5E5E0",borderLight:"#EDEDEA",accent:"#2DD4A8",accentDark:"#1B3A4B"},pc={sm:"0 1px 3px rgba(0,0,0,0.08)",md:"0 2px 8px rgba(0,0,0,0.1)",selected:"0 0 0 2px #2DD4A8, 0 4px 12px rgba(45, 212, 168, 0.3)"},mc={md:"10px"},fc={defaultWidth:2,flowWidth:2.5,arrowSize:16,labelBgPadding:[6,4],labelBgRadius:6,labelBgStyle:{fill:"#FFFFFF",fillOpacity:.92,stroke:"#E5E5E0",strokeWidth:.5}};function wt(){const e=k.getState();return{activeView:e.activeView,explorerTab:e.explorerTab,selectedElementId:e.selectedElementId,selectedViewpointId:e.selectedViewpointId,selectedDiagramId:e.selectedDiagramId,sidebarCollapsed:e.sidebarCollapsed,propertiesPanelCollapsed:e.propertiesPanelCollapsed,hiddenLayers:Array.from(e.hiddenLayers)}}function kt(e){const r=k.getState();r.setActiveView(e.activeView),r.setExplorerTab(e.explorerTab),r.selectElement(e.selectedElementId),e.selectedDiagramId&&r.selectDiagram(e.selectedDiagramId),e.selectedViewpointId&&r.selectViewpoint(e.selectedViewpointId)}function pi(){const[e,r]=u.useState(!1),n=u.useRef(null),o=vt(l=>l.quickSlots),s=vt(l=>l.saveQuickSlot),i=vt(l=>l.clearQuickSlot);u.useEffect(()=>{if(!e)return;const l=d=>{n.current&&!n.current.contains(d.target)&&r(!1)};return document.addEventListener("mousedown",l),()=>document.removeEventListener("mousedown",l)},[e]),u.useEffect(()=>{const l=()=>{s(0,wt(),"Last Session")};return window.addEventListener("beforeunload",l),()=>window.removeEventListener("beforeunload",l)},[s]),u.useEffect(()=>{const l=d=>{if(!(d.ctrlKey||d.metaKey))return;const c=d.key==="1"?1:d.key==="2"?2:d.key==="3"?3:null;if(c)if(d.preventDefault(),d.shiftKey)s(c,wt());else{const p=o[c];p&&kt(p.state)}};return window.addEventListener("keydown",l),()=>window.removeEventListener("keydown",l)},[o,s]);const a=["Last Session","Slot 1","Slot 2","Slot 3"];return t.jsxs("div",{ref:n,style:{position:"relative"},children:[t.jsxs("button",{onClick:()=>r(l=>!l),className:"flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-md transition-all",style:e?{background:"rgba(45,212,168,0.15)",color:"#2DD4A8"}:{background:"transparent",color:"rgba(255,255,255,0.5)"},title:"Workspaces (Ctrl+1/2/3 to restore, Ctrl+Shift+1/2/3 to save)",children:[t.jsx("span",{children:"⊟"}),t.jsx("span",{style:{fontSize:"10px",marginLeft:"2px",opacity:.7},children:"▾"})]}),e&&t.jsxs("div",{style:{position:"absolute",top:"calc(100% + 6px)",right:0,zIndex:100,background:"#132D3E",border:"1px solid rgba(45,212,168,0.2)",borderRadius:"8px",minWidth:"240px",boxShadow:"0 8px 24px rgba(0,0,0,0.4)",overflow:"hidden"},children:[t.jsx("div",{className:"px-3 py-2",style:{borderBottom:"1px solid rgba(255,255,255,0.08)",fontSize:j.xs,color:"rgba(255,255,255,0.4)",fontWeight:600},children:"WORKSPACES"}),t.jsxs("div",{className:"px-3 py-2",style:{borderBottom:"1px solid rgba(255,255,255,0.06)"},children:[t.jsxs("div",{className:"flex items-center justify-between gap-2",children:[t.jsx("span",{style:{fontSize:j.xs,color:"rgba(255,255,255,0.5)",fontWeight:600},children:"Last Session"}),o[0]?t.jsx("button",{onClick:()=>{kt(o[0].state),r(!1)},className:"px-2 py-0.5 rounded text-xs",style:{background:"rgba(45,212,168,0.15)",color:"#2DD4A8",border:"none",cursor:"pointer"},children:"Restore"}):t.jsx("span",{style:{fontSize:"10px",color:"rgba(255,255,255,0.25)"},children:"— none saved —"})]}),o[0]&&t.jsx("div",{style:{fontSize:"10px",color:"rgba(255,255,255,0.3)",marginTop:2},children:new Date(o[0].savedAt).toLocaleString()})]}),[1,2,3].map(l=>{const d=o[l];return t.jsxs("div",{className:"flex items-center gap-2 px-3 py-2",style:{borderBottom:"1px solid rgba(255,255,255,0.04)"},children:[t.jsxs("span",{style:{fontSize:"10px",fontWeight:700,color:"rgba(255,255,255,0.3)",minWidth:"16px"},children:["⌃",l]}),t.jsx("div",{className:"flex-1 min-w-0",children:d?t.jsxs(t.Fragment,{children:[t.jsx("div",{style:{fontSize:j.xs,color:"rgba(255,255,255,0.7)",fontWeight:500},children:d.name}),t.jsx("div",{style:{fontSize:"10px",color:"rgba(255,255,255,0.3)"},children:new Date(d.savedAt).toLocaleTimeString()})]}):t.jsx("span",{style:{fontSize:j.xs,color:"rgba(255,255,255,0.25)",fontStyle:"italic"},children:"empty"})}),t.jsxs("div",{className:"flex gap-1",children:[d&&t.jsx("button",{onClick:()=>{kt(d.state),r(!1)},style:{fontSize:"10px",padding:"2px 6px",borderRadius:3,background:"rgba(45,212,168,0.15)",color:"#2DD4A8",border:"none",cursor:"pointer"},children:"Restore"}),t.jsx("button",{onClick:()=>s(l,wt(),a[l]),style:{fontSize:"10px",padding:"2px 6px",borderRadius:3,background:"rgba(255,255,255,0.1)",color:"rgba(255,255,255,0.6)",border:"none",cursor:"pointer"},title:`Save current view to Slot ${l} (⌃⇧${l})`,children:"Save"}),d&&t.jsx("button",{onClick:()=>i(l),style:{fontSize:"10px",padding:"2px 4px",borderRadius:3,background:"transparent",color:"rgba(255,255,255,0.3)",border:"none",cursor:"pointer"},title:"Clear slot",children:"✕"})]})]},l)})]})]})}const mi="/help/",fi=[{id:"dashboard",label:"Dashboard",icon:"⌂"},{id:"catalog",label:"Model Explorer",icon:"☰"},{id:"diagram",label:"Diagrams",icon:"⊟"},{id:"dhf",label:"DHF",icon:"⊞"},{id:"scenario",label:"Scenarios",icon:"▶"},{id:"ontology",label:"Ontology",icon:"◉"},{id:"import",label:"Import",icon:"↓"}],hi=new Set(["dsm","traceability","statistics","compliance-wizard","model-diff","review-dashboard","workflow-wizard"]),kn=[{id:"dsm",label:"Design Structure Matrix",icon:"▤",view:{type:"dsm"}},{id:"traceability",label:"Traceability Matrix",icon:"☷",view:{type:"traceability"}},{id:"statistics",label:"Statistics Dashboard",icon:"⊠",view:{type:"statistics"}},{id:"compliance-wizard",label:"Compliance Wizard",icon:"☑",view:{type:"compliance-wizard"}},{id:"model-diff",label:"Model Diff",icon:"↔",view:{type:"model-diff"}},{id:"review-dashboard",label:"Design Review Dashboard",icon:"📋",view:{type:"review-dashboard"}},{id:"workflow-wizard",label:"Workflow Wizard",icon:"🧙",view:{type:"workflow-wizard"}}];function gi({activeViewType:e}){const r=k(l=>l.setActiveView);k(l=>l.setActiveMode);const[n,o]=u.useState(!1),s=u.useRef(null),a=kn.map(l=>l.id).includes(e);return u.useEffect(()=>{function l(d){s.current&&!s.current.contains(d.target)&&o(!1)}return n&&document.addEventListener("mousedown",l),()=>document.removeEventListener("mousedown",l)},[n]),t.jsxs("div",{ref:s,style:{position:"relative"},children:[t.jsxs("button",{onClick:()=>o(l=>!l),className:"flex items-center gap-1 px-4 py-1.5 text-sm font-medium rounded-md transition-all",style:a||n?{background:"rgba(45, 212, 168, 0.15)",color:"#2DD4A8"}:{background:"transparent",color:"rgba(255,255,255,0.5)"},children:[t.jsx("span",{className:"mr-0.5",children:"⚙"}),"Tools",t.jsx("span",{style:{fontSize:"10px",marginLeft:"2px",opacity:.7},children:"▾"})]}),n&&t.jsx("div",{style:{position:"absolute",top:"calc(100% + 6px)",left:0,zIndex:100,background:"#132D3E",border:"1px solid rgba(45,212,168,0.2)",borderRadius:"8px",minWidth:"220px",boxShadow:"0 8px 24px rgba(0,0,0,0.4)",overflow:"hidden"},children:kn.map((l,d)=>{const c=e===l.view.type;return t.jsxs("button",{onClick:()=>{r(c?{type:"welcome"}:l.view),o(!1)},className:"w-full flex items-center gap-3 px-4 py-2.5 text-left transition-colors",style:{fontSize:"13px",color:c?"#2DD4A8":"rgba(255,255,255,0.75)",background:c?"rgba(45,212,168,0.1)":"transparent",borderTop:d>0?"1px solid rgba(255,255,255,0.05)":"none"},onMouseEnter:p=>{c||(p.currentTarget.style.background="rgba(255,255,255,0.06)")},onMouseLeave:p=>{c||(p.currentTarget.style.background="transparent")},children:[t.jsx("span",{style:{width:"18px",textAlign:"center",opacity:.7},children:l.icon}),l.label]},l.id)})})]})}function yi(){const e=k(f=>f.activeMode),r=k(f=>f.setActiveMode),n=k(f=>f.activeView),o=k(f=>f.setActiveView),s=k(f=>f.setExplorerTab),i=k(f=>f.sidebarCollapsed),a=k(f=>f.toggleSidebar),l=ve(),d=["catalog","diagram","dhf"],c=hi.has(n.type)?"":e==="dhf"||n.type==="dhf-dashboard"?"dhf":n.type==="scenario-editor"?"scenario":n.type==="ontology"||n.type==="ontology-detail"?"ontology":n.type==="import"?"import":n.type==="diagram"||e==="diagram"?"diagram":e==="catalog"?"catalog":n.type==="dashboard"?"dashboard":e;function p(f){if(f===c&&d.includes(f)){a();return}switch(d.includes(f)&&i&&a(),r(f),f){case"dashboard":o({type:"dashboard"});break;case"catalog":o({type:"welcome"}),l("/catalog");break;case"diagram":s("views"),o({type:"welcome"}),l("/diagrams");break;case"dhf":o({type:"dhf-dashboard"});break;case"scenario":o({type:"scenario-editor"});break;case"ontology":o({type:"ontology"});break;case"import":o({type:"import"});break}}return t.jsxs("div",{className:"flex items-center gap-1 px-5 py-3",style:{background:"#1B3A4B",borderBottom:"1px solid rgba(255,255,255,0.08)",overflow:"visible",position:"relative",zIndex:10},children:[fi.map(f=>t.jsxs("button",{onClick:()=>p(f.id),className:"px-4 py-1.5 text-sm font-medium rounded-md transition-all",style:c===f.id?{background:"rgba(45, 212, 168, 0.15)",color:"#2DD4A8"}:{background:"transparent",color:"rgba(255,255,255,0.5)"},children:[t.jsx("span",{className:"mr-1.5",children:f.icon}),f.label]},f.id)),t.jsx("div",{style:{width:"1px",height:"20px",background:"rgba(255,255,255,0.12)",margin:"0 4px"}}),t.jsx(gi,{activeViewType:n.type}),t.jsx("div",{className:"flex-1"}),t.jsx(pi,{}),t.jsx("a",{href:mi,target:"_blank",rel:"noopener noreferrer",className:"px-4 py-1.5 text-sm font-medium rounded-md transition-all",style:{color:"rgba(255,255,255,0.4)",textDecoration:"none"},onMouseEnter:f=>f.currentTarget.style.color="rgba(255,255,255,0.75)",onMouseLeave:f=>f.currentTarget.style.color="rgba(255,255,255,0.4)",children:"? Help"}),t.jsx("img",{src:"/memo-top.png",alt:"MEMO",className:"ml-3",style:{height:56,marginTop:-4,marginBottom:-10}})]})}const re={operational:"#0F766E",business:"#8E44AD",requirements:"#4A90D9",risk:"#E74C3C",functional:"#E67E22",behavior:"#FF6B6B",logical:"#7B68EE",physical:"#95A5A6",software:"#F39C12",interfaces:"#1ABC9C",verification:"#2ECC71",ui:"#3498DB"},Ot={operational:"Operational Analysis",business:"Business Analysis",requirements:"Requirements",risk:"Risk Management",functional:"Functional Analysis",behavior:"Behavior",logical:"Logical Architecture",physical:"Physical Architecture",software:"Software Architecture",interfaces:"Interfaces & Ports",verification:"Verification",ui:"UI Wireframe"},rt=["operational","business","requirements","risk","functional","behavior","logical","physical","software","interfaces","verification","ui"],hc={mitigates:"#E74C3C",causes:"#C0392B",leadsTo:"#E74C3C",identifies:"#D35400",traceTo:"#4A90D9",satisfy:"#2ECC71",verify:"#27AE60",allocateTo:"#E67E22",aggregation:"#7B68EE",composedOf:"#8E44AD",decomposedBy:"#D35400",flow:"#3498DB",succession:"#95A5A6"},xi={general:{label:"GEN",fullName:"General View",color:"#7B68EE"},interconnection:{label:"INT",fullName:"Interconnection View",color:"#1ABC9C"},actionflow:{label:"ACT",fullName:"Action Flow View",color:"#F39C12"},statetransition:{label:"STM",fullName:"State Transition View",color:"#FF6B6B"},sequence:{label:"SEQ",fullName:"Sequence View",color:"#3498DB"},grid:{label:"GRID",fullName:"Grid View",color:"#2ECC71"},browser:{label:"BRW",fullName:"Browser View",color:"#95A5A6"},geometry:{label:"GEO",fullName:"Geometry View",color:"#8E44AD"}},Fe={bdd:{code:"BDD",label:"BDD",fullName:"Block Definition Diagram",color:"#7B68EE",viewKind:"general"},ibd:{code:"IBD",label:"IBD",fullName:"Internal Block Diagram",color:"#1ABC9C",viewKind:"interconnection"},req:{code:"REQ",label:"REQ",fullName:"Requirements Diagram",color:"#4A90D9",viewKind:"general"},ucd:{code:"UCD",label:"UCD",fullName:"Use Case Diagram",color:"#E67E22",viewKind:"general"},context:{code:"CTX",label:"CTX",fullName:"System Context Diagram",color:"#5DADE2",viewKind:"general"},act:{code:"ACT",label:"ACT",fullName:"Activity Diagram",color:"#F39C12",viewKind:"actionflow"},afd:{code:"AFD",label:"AFD",fullName:"Action Flow Diagram",color:"#FF6B6B",viewKind:"actionflow"},ofd:{code:"OFD",label:"OFD",fullName:"Operational Flow Diagram",color:"#F39C12",viewKind:"actionflow"},ffd:{code:"FFD",label:"FFD",fullName:"Functional Flow Diagram",color:"#F39C12",viewKind:"actionflow"},pkg:{code:"PKG",label:"PKG",fullName:"Package Diagram",color:"#95A5A6",viewKind:"general"},par:{code:"PAR",label:"PAR",fullName:"Parametric Diagram",color:"#2ECC71",viewKind:"interconnection"},risk:{code:"RISK",label:"RISK",fullName:"Risk Diagram",color:"#E74C3C",viewKind:"general"},stm:{code:"STM",label:"STM",fullName:"State Transition Diagram",color:"#FF6B6B",viewKind:"statetransition"},seq:{code:"SEQ",label:"SEQ",fullName:"Sequence Diagram",color:"#3498DB",viewKind:"sequence"},fmea:{code:"FMEA",label:"FMEA",fullName:"FMEA Matrix",color:"#E74C3C",viewKind:"grid"},alloc:{code:"ALLOC",label:"ALLOC",fullName:"Allocation Matrix",color:"#E67E22",viewKind:"grid"},"threat-model":{code:"THREAT",label:"THREAT",fullName:"Threat Model Diagram",color:"#C0392B",viewKind:"general"}};function bi(e){const r=e.diagramType.trim().toLowerCase();return r==="ofd"||r==="ffd"?r:"afd"}const gc=["#FFFFFF","#f8fafc","#f0f9ff","#fdf2f8","#f0fdf4"];function Se({label:e,onClick:r,icon:n}){return t.jsxs("button",{className:"w-full flex items-center gap-2 px-3 py-1.5 text-left text-xs",style:{color:"#374151",background:"transparent",border:"none",cursor:"pointer",whiteSpace:"nowrap"},onMouseEnter:o=>o.currentTarget.style.background="#F0F0ED",onMouseLeave:o=>o.currentTarget.style.background="transparent",onClick:o=>{o.stopPropagation(),r()},children:[n&&t.jsx("span",{style:{fontSize:"12px",width:"14px",flexShrink:0},children:n}),e]})}function vi(){return t.jsx("div",{style:{height:"1px",background:"#E5E5E0",margin:"3px 0"}})}function wi({x:e,y:r,target:n,onViewVisual:o,onViewTable:s,onToggleSelection:i,onViewProperties:a,onClose:l}){const d=u.useRef(null);u.useEffect(()=>{if(!d.current)return;const p=d.current,{innerWidth:f,innerHeight:h}=window,S=p.getBoundingClientRect();S.right>f&&(p.style.left=`${e-S.width}px`),S.bottom>h&&(p.style.top=`${r-S.height}px`)},[e,r]);const c={position:"fixed",top:r,left:e,background:"#FFFFFF",border:"1px solid #E5E5E0",borderRadius:"6px",boxShadow:"0 4px 12px rgba(0,0,0,0.12)",zIndex:9999,minWidth:"180px",padding:"4px 0"};return n.type==="package"?t.jsxs("div",{ref:d,style:c,onMouseDown:p=>p.stopPropagation(),children:[t.jsx(Se,{icon:"⬜",label:"View Visual Layout",onClick:()=>{o(n.pkgName),l()}}),t.jsx(Se,{icon:"☰",label:"View as Table",onClick:()=>{s(n.pkgName),l()}}),t.jsx(vi,{}),t.jsx(Se,{icon:n.isSelected?"☑":"☐",label:n.isSelected?"Deselect for Project":"Select for Project",onClick:()=>i(n.pkgName)})]}):n.type==="layer"?t.jsxs("div",{ref:d,style:c,onMouseDown:p=>p.stopPropagation(),children:[t.jsx(Se,{icon:"⬜",label:"View Visual Layout",onClick:()=>{o(n.pkgName),l()}}),t.jsx(Se,{icon:"☰",label:"View as Table",onClick:()=>s(n.pkgName,n.layerId)})]}):t.jsxs("div",{ref:d,style:c,onMouseDown:p=>p.stopPropagation(),children:[t.jsx(Se,{icon:"🔍",label:"View Properties",onClick:()=>a(n.kindName,n.pkgName)}),t.jsx(Se,{icon:"☰",label:"View as Table",onClick:()=>s(n.pkgName,n.layerId)}),t.jsx(Se,{icon:"⬜",label:"Show in Visual Layout",onClick:()=>{o(n.pkgName),l()}})]})}function ki({kindsToRemap:e,onConfirm:r,onCancel:n}){const o=k(p=>p.availableOntologies),s=k(p=>p.selectedOntologies),i=o.filter(p=>s.has(p.name)).flatMap(p=>p.layers.flatMap(f=>f.kinds.map(h=>h.name))).filter((p,f,h)=>h.indexOf(p)===f).sort(),[a,l]=u.useState(Object.fromEntries(e.map(p=>[p,""])));function d(p,f){l(h=>({...h,[p]:f}))}const c=e.every(p=>a[p]);return t.jsx("div",{className:"fixed inset-0 flex items-center justify-center z-50",style:{background:"rgba(0,0,0,0.4)"},children:t.jsxs("div",{className:"rounded-xl shadow-2xl max-w-lg w-full mx-4 overflow-hidden",style:{background:"#FFFFFF",border:"1px solid #E5E5E0"},children:[t.jsxs("div",{className:"px-6 py-4",style:{borderBottom:"1px solid #E5E5E0"},children:[t.jsx("h2",{className:"text-sm font-semibold",style:{color:"#1a1a1a"},children:"Remap Orphaned Kinds"}),t.jsx("p",{className:"text-xs mt-1",style:{color:"#6B7280"},children:"Map each orphaned kind to a kind in the selected ontologies. Model elements will be updated to use the new kind."})]}),t.jsx("div",{className:"px-6 py-4 space-y-3 max-h-64 overflow-y-auto",children:e.map(p=>t.jsxs("div",{className:"flex items-center gap-3",children:[t.jsx("div",{className:"flex-1 px-2 py-1 rounded text-xs font-medium",style:{background:"#FEF2F2",color:"#EF4444",border:"1px solid #FCA5A5"},children:p}),t.jsx("span",{style:{color:"#9CA3AF"},children:"→"}),t.jsxs("select",{value:a[p],onChange:f=>d(p,f.target.value),className:"flex-1 text-xs rounded-md px-2 py-1 focus:outline-none",style:{border:"1px solid #E5E5E0",color:"#1a1a1a",background:"#FFFFFF"},children:[t.jsx("option",{value:"",children:"Select target kind…"}),i.map(f=>t.jsx("option",{value:f,children:f},f))]})]},p))}),t.jsxs("div",{className:"px-6 py-4 flex gap-2 justify-end",style:{borderTop:"1px solid #E5E5E0"},children:[t.jsx("button",{onClick:n,className:"px-3 py-1.5 text-xs rounded-md",style:{background:"#F0F0ED",color:"#374151"},children:"Back"}),t.jsx("button",{onClick:()=>r(a),disabled:!c,className:"px-3 py-1.5 text-xs rounded-md font-medium",style:{background:c?"#1B3A4B":"#E5E5E0",color:c?"#FFFFFF":"#9CA3AF",cursor:c?"pointer":"not-allowed"},children:"Apply Remapping"})]})]})})}function Si({orphans:e,onKeep:r,onRemap:n,onCancel:o}){const[s,i]=u.useState(!1),a=new Map;for(const l of e)a.has(l.kind)||a.set(l.kind,[]),a.get(l.kind).push(l);return s?t.jsx(ki,{kindsToRemap:[...a.keys()],onConfirm:n,onCancel:()=>i(!1)}):t.jsx("div",{className:"fixed inset-0 flex items-center justify-center z-50",style:{background:"rgba(0,0,0,0.4)"},onClick:l=>{l.target===l.currentTarget&&o()},children:t.jsxs("div",{className:"rounded-xl shadow-2xl max-w-md w-full mx-4 overflow-hidden",style:{background:"#FFFFFF",border:"1px solid #E5E5E0"},children:[t.jsxs("div",{className:"px-6 py-4",style:{borderBottom:"1px solid #E5E5E0",background:"#FEF2F2"},children:[t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx("span",{className:"text-red-500 text-lg",children:"⚠"}),t.jsx("h2",{className:"text-sm font-semibold",style:{color:"#1a1a1a"},children:"Orphaned Elements"})]}),t.jsxs("p",{className:"text-xs mt-1",style:{color:"#6B7280"},children:[e.length," element",e.length!==1?"s":""," use kinds from the deselected ontology."]})]}),t.jsx("div",{className:"px-6 py-4 max-h-48 overflow-y-auto",children:[...a.entries()].map(([l,d])=>t.jsxs("div",{className:"mb-3",children:[t.jsxs("div",{className:"text-xs font-semibold mb-1",style:{color:"#374151"},children:[l,t.jsxs("span",{className:"ml-1 font-normal",style:{color:"#9CA3AF"},children:["(",d.length," element",d.length!==1?"s":"",")"]})]}),t.jsxs("div",{className:"flex flex-wrap gap-1",children:[d.slice(0,5).map(c=>t.jsx("span",{className:"px-1.5 py-0.5 text-xs rounded",style:{background:"#FEF2F2",color:"#EF4444",border:"1px solid #FCA5A5"},children:c.elementName},c.elementId)),d.length>5&&t.jsxs("span",{className:"text-xs",style:{color:"#9CA3AF"},children:["+",d.length-5," more"]})]})]},l))}),t.jsxs("div",{className:"px-6 py-4 flex gap-2 justify-end",style:{borderTop:"1px solid #E5E5E0"},children:[t.jsx("button",{onClick:o,className:"px-3 py-1.5 text-xs rounded-md",style:{background:"#F0F0ED",color:"#374151"},children:"Cancel"}),t.jsx("button",{onClick:r,className:"px-3 py-1.5 text-xs rounded-md",style:{background:"#FEF2F2",color:"#EF4444",border:"1px solid #FCA5A5"},children:"Keep (mark orphaned)"}),t.jsx("button",{onClick:()=>i(!0),className:"px-3 py-1.5 text-xs rounded-md font-medium",style:{background:"#1B3A4B",color:"#FFFFFF"},children:"Remap kinds →"})]})]})})}const Sn={ontology:"📦",profile:"🔧",extension:"🧩"};function Ei(e){const r=new Map(e.map(l=>[l.name,l])),n=new Map;function o(l){if(n.has(l))return n.get(l);const d=r.get(l);if(!d||!d.derivesFrom||!r.has(d.derivesFrom))return n.set(l,0),0;const c=o(d.derivesFrom)+1;return n.set(l,c),c}for(const l of e)o(l.name);const s=new Map;for(const l of e){const d=n.get(l.name)??0,c=s.get(d)??[];c.push(l),s.set(d,c)}const i=Math.max(...s.keys()),a=[];for(let l=0;l<=i;l++){const d=s.get(l)??[];a.push(...d.sort((c,p)=>c.name.localeCompare(p.name)))}return a}function ji(e){const r=new Map(e.map(l=>[l.name,l])),n=new Map;function o(l){if(n.has(l))return n.get(l);const d=r.get(l);if(!d||!d.extends||!r.has(d.extends))return n.set(l,0),0;const c=o(d.extends)+1;return n.set(l,c),c}for(const l of e)o(l.name);const s=new Map;for(const l of e){const d=n.get(l.name)??0,c=s.get(d)??[];c.push(l),s.set(d,c)}const i=s.size>0?Math.max(...s.keys()):0,a=[];for(let l=0;l<=i;l++){const d=s.get(l)??[];a.push(...d.sort((c,p)=>c.name.localeCompare(p.name)))}return a}function Ci({pkgName:e,onCancel:r,onConfirm:n}){const o=e.replace(/^@memo(?:architect)?\//,"");return t.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center",style:{background:"rgba(0,0,0,0.45)"},onMouseDown:s=>{s.target===s.currentTarget&&r()},children:t.jsxs("div",{className:"rounded-xl p-5 shadow-2xl",style:{background:"#FFFFFF",maxWidth:"340px",width:"90vw"},children:[t.jsx("div",{className:"font-semibold mb-1.5",style:{fontSize:j.sm,color:y.primary},children:"Remove ontology?"}),t.jsxs("div",{className:"mb-4",style:{fontSize:j.xs,color:y.secondary,lineHeight:1.5},children:["Removing ",t.jsx("strong",{children:o})," will affect all model elements that depend on its kinds. Those elements will become orphaned until you add a compatible ontology."]}),t.jsxs("div",{className:"flex gap-2 justify-end",children:[t.jsx("button",{onClick:r,className:"px-3 py-1.5 rounded-md font-medium",style:{fontSize:j.xs,background:y.surfaceAlt,color:y.secondary,border:`1px solid ${y.border}`,cursor:"pointer"},children:"Cancel"}),t.jsx("button",{onClick:n,className:"px-3 py-1.5 rounded-md font-medium",style:{fontSize:j.xs,background:"#DC2626",color:"#FFFFFF",border:"none",cursor:"pointer"},children:"Remove"})]})]})})}function Di(){const e=k(g=>g.availableOntologies),r=k(g=>g.selectedOntologies),n=k(g=>g.toggleOntologySelection),o=k(g=>g.saveOntologySelection),s=k(g=>g.selectedOntologyKind),i=k(g=>g.setSelectedOntologyKind),a=k(g=>g.setActiveView),l=k(g=>g.setOntologyViewMode),d=k(g=>g.activeView),[c,p]=u.useState(""),[f,h]=u.useState(()=>new Set(e.filter(g=>g.selected).map(g=>g.name))),[S,b]=u.useState(new Set),[x,v]=u.useState(()=>new Set(e.filter(g=>g.selected).map(g=>g.name))),w=u.useMemo(()=>{if(r.size!==x.size)return!0;for(const g of r)if(!x.has(g))return!0;return!1},[r,x]),[T,I]=u.useState(null),[m,D]=u.useState(null),[F,E]=u.useState(null),R=u.useRef(new Map),O=u.useMemo(()=>{const g=c.trim()?e.map(_=>({..._,layers:_.layers.map(q=>({...q,kinds:q.kinds.filter(ee=>ee.name.toLowerCase().includes(c.toLowerCase())||ee.label.toLowerCase().includes(c.toLowerCase())||ee.layer.toLowerCase().includes(c.toLowerCase()))})).filter(q=>q.kinds.length>0)})).filter(_=>_.layers.length>0||_.name.toLowerCase().includes(c.toLowerCase())):e;return ji(g)},[e,c]);u.useEffect(()=>{c.trim()&&(h(new Set(O.map(g=>g.name))),b(new Set(O.flatMap(g=>g.layers.map(_=>`${g.name}:${_.id}`)))))},[c,O]),u.useEffect(()=>{if(s&&R.current.has(s)){for(const g of e)for(const _ of g.layers)if(_.kinds.find(q=>q.name===s)){h(q=>new Set([...q,g.name])),b(q=>new Set([...q,`${g.name}:${_.id}`]));break}setTimeout(()=>{var g;(g=R.current.get(s))==null||g.scrollIntoView({behavior:"smooth",block:"nearest"})},80)}},[s,e]);function C(g){a({type:"ontology-detail",packageName:g})}function B(g,_){a({type:"ontology-detail",packageName:g,layerId:_})}function P(g,_){i(s===g?null:g),a({type:"ontology-detail",packageName:_})}function L(g){h(_=>{const q=new Set(_);return q.has(g)?q.delete(g):q.add(g),q})}function K(g){b(_=>{const q=new Set(_);return q.has(g)?q.delete(g):q.add(g),q})}function H(g,_,q){g.stopPropagation(),q?D(_):n(_)}function N(){const g=o();g.orphanedElements&&g.orphanedElements.length>0?I(g.orphanedElements):(bt([...r]),v(new Set(r)))}function W(){bt([...r]),v(new Set(r)),I(null)}function X(g){Ys(g),bt([...r]),v(new Set(r)),I(null)}function U(g,_){g.preventDefault(),g.stopPropagation(),E({x:g.clientX,y:g.clientY,target:_})}function M(g,_){l("table"),a({type:"ontology-detail",packageName:g,layerId:_}),E(null)}function A(g){l("visual"),a({type:"ontology-detail",packageName:g}),E(null)}function V(g){r.has(g)?D(g):n(g),E(null)}function Y(g,_){i(g),a({type:"ontology-detail",packageName:_}),E(null)}if(u.useEffect(()=>{function g(_){_.key==="Escape"&&(i(null),E(null),D(null))}return document.addEventListener("keydown",g),()=>document.removeEventListener("keydown",g)},[i]),u.useEffect(()=>{if(!F)return;function g(){E(null)}return document.addEventListener("mousedown",g),()=>document.removeEventListener("mousedown",g)},[F]),e.length===0)return t.jsx("div",{className:"flex-1 flex items-center justify-center p-4",children:t.jsxs("div",{className:"text-center",style:{color:y.faint},children:[t.jsx("div",{className:"text-xl mb-2",children:"◉"}),t.jsx("div",{style:{fontSize:j.xs},children:"No ontology packages"}),t.jsx("div",{style:{fontSize:j.xs,opacity:.7,marginTop:"4px"},children:"Start memo-architect dev to load"})]})});const J=d.type==="ontology-detail"?d.packageName:null;return t.jsxs("div",{className:"flex flex-col flex-1 overflow-hidden",style:{fontSize:j.explorer.item},children:[t.jsx("div",{className:"px-3 py-2 sticky top-0 z-10",style:{background:y.surface,borderBottom:`1px solid ${y.border}`},children:t.jsx("input",{type:"text",placeholder:"Search kinds...",value:c,onChange:g=>p(g.target.value),className:"w-full px-2.5 py-1.5 rounded-lg focus:outline-none",style:{fontSize:j.explorer.search,border:`1px solid ${y.border}`,background:y.surfaceAlt,color:y.primary},onFocus:g=>g.currentTarget.style.borderColor="#2563EB",onBlur:g=>g.currentTarget.style.borderColor=y.border})}),t.jsx("div",{className:"flex-1 overflow-y-auto py-1",children:O.map(g=>{const _=r.has(g.name),q=J===g.name,ee=f.has(g.name),ne=g.name.replace(/^@memo(?:architect)?\//,""),se=Sn[g.type]??Sn.ontology;return t.jsxs("div",{children:[t.jsxs("div",{className:"flex items-center gap-1.5 px-2 py-1.5 cursor-pointer",style:{borderRadius:"6px",margin:"0 4px",background:q?`${y.accent}18`:"transparent",borderLeft:q?`3px solid ${y.accentDark}`:"3px solid transparent",opacity:_?1:.55},onMouseEnter:$=>{q||($.currentTarget.style.background="#F0F0ED")},onMouseLeave:$=>{$.currentTarget.style.background=q?`${y.accent}18`:"transparent"},onClick:$=>{$.stopPropagation(),L(g.name)},onDoubleClick:()=>C(g.name),onContextMenu:$=>U($,{type:"package",pkgName:g.name,isSelected:_}),children:[t.jsx("input",{type:"checkbox",checked:_,onChange:$=>H($,g.name,_),onClick:$=>$.stopPropagation(),style:{cursor:"pointer",accentColor:"#2563EB",flexShrink:0},title:_?"Deselect for project":"Select for project"}),t.jsx("span",{style:{color:y.muted,fontSize:"10px"},children:ee?"▾":"▸"}),t.jsx("span",{children:se}),t.jsx("span",{className:"font-semibold truncate flex-1",style:{color:y.primary,fontSize:j.explorer.group},children:ne}),t.jsx("span",{style:{color:y.faint},children:g.kindCount})]}),ee&&g.layers.map($=>{const ie=re[$.id]??$.color??y.muted,ye=`${g.name}:${$.id}`,de=S.has(ye),G=Ei($.kinds);return t.jsxs("div",{children:[t.jsxs("div",{className:"flex items-center gap-2 px-3 py-1 cursor-pointer",style:{borderRadius:"4px",margin:"0 4px 0 20px"},onMouseEnter:Q=>Q.currentTarget.style.background="#F0F0ED",onMouseLeave:Q=>Q.currentTarget.style.background="transparent",onClick:Q=>{Q.stopPropagation(),K(ye)},onDoubleClick:()=>B(g.name,$.id),onContextMenu:Q=>U(Q,{type:"layer",pkgName:g.name,layerId:$.id,layerLabel:$.label}),children:[t.jsx("span",{style:{color:y.faint,fontSize:"9px"},children:de?"▾":"▸"}),t.jsx("span",{className:"w-2 h-2 rounded flex-shrink-0",style:{backgroundColor:ie}}),t.jsx("span",{className:"flex-1 truncate capitalize",style:{color:y.muted,fontSize:j.explorer.kind},children:$.label}),t.jsx("span",{style:{color:y.faint},children:$.kindCount})]}),de&&(()=>{const Q=new Map;for(const Z of G){const le=Z.derivesFrom?Q.get(Z.derivesFrom)??0:0;Q.set(Z.name,Z.derivesFrom?le+1:0)}const ue=Z=>{const le=s===Z.name,Qt=Q.get(Z.name)??0,Xt=Qt===0,Tr=36+Qt*12;return t.jsxs("div",{ref:ke=>{ke&&R.current.set(Z.name,ke)},className:"flex items-center gap-1.5 px-3 py-0.5 cursor-pointer",style:{borderRadius:"4px",margin:`0 4px 0 ${Tr}px`,background:le?`${y.accent}18`:"transparent",borderLeft:le?`2px solid ${ie}`:"2px solid transparent",transition:"background 150ms ease"},onMouseEnter:ke=>{le||(ke.currentTarget.style.background="#F0F0ED")},onMouseLeave:ke=>{ke.currentTarget.style.background=le?`${y.accent}18`:"transparent"},onClick:()=>P(Z.name,g.name),onContextMenu:ke=>U(ke,{type:"kind",kindName:Z.name,pkgName:g.name,layerId:$.id}),children:[!Xt&&t.jsx("span",{style:{color:y.faint,fontSize:"9px",flexShrink:0},children:"↳"}),t.jsx("span",{className:"truncate",style:{color:le?y.accentDark:y.primary,fontWeight:Xt?500:400,fontSize:j.explorer.item},children:Z.name}),Z.instanceCount>0&&t.jsxs("span",{style:{color:y.faint,fontSize:"10px"},children:["·",Z.instanceCount]})]},Z.name)},we=[],ze=new Map;for(const Z of G){const le=Z.group??"";ze.has(le)||(ze.set(le,[]),we.push(le)),ze.get(le).push(Z)}return we.filter(Z=>Z!=="").length<=1?G.map(ue):we.map(Z=>t.jsxs("div",{children:[Z&&t.jsxs("div",{className:"px-3 py-0.5 flex items-center gap-1.5",style:{margin:"0 4px 0 30px"},children:[t.jsx("span",{className:"capitalize truncate",style:{color:y.faint,fontSize:j.explorer.kind,letterSpacing:"0.02em"},children:Z.replace(/_/g," ")}),t.jsx("span",{style:{color:y.faint,fontSize:"10px"},children:ze.get(Z).length})]}),ze.get(Z).map(ue)]},`grp:${ye}:${Z||"_root"}`))})()]},ye)})]},g.name)})}),w&&t.jsx("div",{className:"px-3 py-2 flex-shrink-0",style:{borderTop:`1px solid ${y.border}`,background:y.surfaceAlt},children:t.jsx("button",{onClick:N,className:"w-full py-1.5 rounded-md font-medium",style:{fontSize:j.xs,background:"#2563EB",color:"#FFFFFF",border:"none",cursor:"pointer"},children:"Save Selection"})}),m&&t.jsx(Ci,{pkgName:m,onCancel:()=>D(null),onConfirm:()=>{n(m),D(null)}}),T&&t.jsx(Si,{orphans:T,onKeep:W,onRemap:X,onCancel:()=>I(null)}),F&&t.jsx(wi,{x:F.x,y:F.y,target:F.target,onViewVisual:A,onViewTable:M,onToggleSelection:V,onViewProperties:Y,onClose:()=>E(null)})]})}function Ai(){const e=k(d=>d.model),r=k(d=>d.recentlyVisited),n=k(d=>d.selectElement),o=u.useMemo(()=>e?r.map(d=>e.elements[d]).filter(Boolean):[],[r,e]),s=u.useMemo(()=>{if(!e||o.length>0)return[];const d=new Map;for(const c of Object.values(e.elements))if(d.has(c.kind)||d.set(c.kind,c),d.size>=12)break;return Array.from(d.values())},[e,o.length]),i=o.length>0?o:s,a=o.length>0?"Recently visited":"Sample elements",l=o.length>0?`${o.length} item${o.length===1?"":"s"} this session`:"Click any to start exploring";return t.jsxs("div",{className:"flex flex-col flex-1 overflow-hidden",children:[t.jsxs("div",{className:"px-3 py-3",style:{borderBottom:`1px solid ${y.border}`},children:[t.jsx("div",{style:{fontSize:"10px",fontWeight:700,textTransform:"uppercase",letterSpacing:"0.08em",color:y.muted,marginBottom:"2px"},children:a}),t.jsx("div",{style:{fontSize:"11px",color:y.muted,opacity:.8},children:l})]}),t.jsx("div",{className:"flex-1 overflow-y-auto",style:{padding:"4px 0"},children:i.length===0?t.jsx("div",{style:{padding:"24px 16px",textAlign:"center",fontSize:"12px",color:y.muted,lineHeight:"1.6"},children:"No elements in this model yet."}):i.map(d=>{const c=re[d.layer]||y.muted;return t.jsx("button",{onClick:()=>n(d.id),style:{display:"flex",alignItems:"flex-start",gap:"8px",width:"100%",padding:"8px 12px",background:"transparent",border:"none",borderLeft:`3px solid ${c}`,cursor:"pointer",textAlign:"left",transition:"background 0.1s"},onMouseEnter:p=>p.currentTarget.style.background=y.surfaceAlt,onMouseLeave:p=>p.currentTarget.style.background="transparent",children:t.jsxs("div",{style:{flex:1,minWidth:0},children:[t.jsx("div",{style:{fontSize:j.explorer.item,fontWeight:500,color:y.primary,whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"},children:d.name}),t.jsxs("div",{style:{fontSize:"10px",color:y.muted,marginTop:"2px",whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"},children:[t.jsx("span",{style:{color:c,fontWeight:600},children:d.kind}),d.shortId&&t.jsx("span",{style:{marginLeft:"6px",fontFamily:"monospace",opacity:.7},children:d.shortId})]})]})},d.id)})})]})}const Fi=`---
|
|
17
|
-
id: change-record
|
|
18
|
-
title: Design Change Record
|
|
19
|
-
standard: 21 CFR Part 820
|
|
20
|
-
clauses: ["820.30(i)"]
|
|
21
|
-
required_for: ["FDA_510k", "FDA_PMA"]
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
25
|
-
|
|
26
|
-
---
|
|
27
|
-
|
|
28
|
-
## 1. Purpose
|
|
29
|
-
|
|
30
|
-
Documents design changes for **{{project.product}}** per 21 CFR 820.30(i). All changes must be evaluated for safety impact and approved before implementation.
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
## 2. Change Log
|
|
35
|
-
|
|
36
|
-
Record each change with its identifier, description, affected items, and verification status:
|
|
37
|
-
|
|
38
|
-
| Change # | Date | Description | Reason | Impact Assessment | Approved By |
|
|
39
|
-
| --- | --- | --- | --- | --- | --- |
|
|
40
|
-
| CHG-001 | | | | | |
|
|
41
|
-
|
|
42
|
-
---
|
|
43
|
-
|
|
44
|
-
## 3. Substantial Equivalence Assessment
|
|
45
|
-
|
|
46
|
-
Assess substantial equivalence to the predicate device, comparing intended use and technological characteristics.
|
|
47
|
-
|
|
48
|
-
_[TODO: For FDA-cleared devices, assess whether any changes affect substantial equivalence]_
|
|
49
|
-
|
|
50
|
-
---
|
|
51
|
-
|
|
52
|
-
## 4. Risk Assessment for Changes
|
|
53
|
-
|
|
54
|
-
Assess the risk impact of each change per ISO 14971, including effects on existing risk controls.
|
|
55
|
-
|
|
56
|
-
_[TODO: Document risk management activity triggered by each significant change]_
|
|
57
|
-
|
|
58
|
-
---
|
|
59
|
-
|
|
60
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
61
|
-
`,Ri=`---
|
|
62
|
-
id: design-input
|
|
63
|
-
title: Design Input Plan
|
|
64
|
-
standard: 21 CFR Part 820
|
|
65
|
-
clauses: ["820.30(c)"]
|
|
66
|
-
required_for: ["FDA_510k", "FDA_PMA"]
|
|
67
|
-
---
|
|
68
|
-
|
|
69
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
70
|
-
|
|
71
|
-
{{toc}}
|
|
72
|
-
|
|
73
|
-
---
|
|
74
|
-
|
|
75
|
-
## 1. Purpose
|
|
76
|
-
|
|
77
|
-
Defines design inputs for **{{project.product}}** per 21 CFR 820.30(c). Design inputs are the physical and performance requirements to which the device design must conform.
|
|
78
|
-
|
|
79
|
-
---
|
|
80
|
-
|
|
81
|
-
## 2. Design Input Requirements
|
|
82
|
-
|
|
83
|
-
### 2.1 Performance Requirements
|
|
84
|
-
|
|
85
|
-
\`\`\`memo-query
|
|
86
|
-
kind: Requirement
|
|
87
|
-
display: table
|
|
88
|
-
columns: name, layer, doc
|
|
89
|
-
sort: name
|
|
90
|
-
empty: "No system requirements defined."
|
|
91
|
-
\`\`\`
|
|
92
|
-
|
|
93
|
-
### 2.2 Design Inputs from User Needs
|
|
94
|
-
|
|
95
|
-
\`\`\`memo-query
|
|
96
|
-
kind: [DesignInput, Need]
|
|
97
|
-
display: table
|
|
98
|
-
columns: name, layer, doc
|
|
99
|
-
sort: name
|
|
100
|
-
empty: "No design inputs defined. Add DesignInput elements."
|
|
101
|
-
\`\`\`
|
|
102
|
-
|
|
103
|
-
---
|
|
104
|
-
|
|
105
|
-
## 3. Regulatory and Standards Requirements
|
|
106
|
-
|
|
107
|
-
Complete the table below for **{{project.product}}**:
|
|
108
|
-
|
|
109
|
-
| Standard | Requirement | Input Reference |
|
|
110
|
-
| --- | --- | --- |
|
|
111
|
-
| 21 CFR 820.30 | Design controls | |
|
|
112
|
-
| ISO 14971 | Risk management requirements | |
|
|
113
|
-
| IEC 62304 | Software development | |
|
|
114
|
-
|
|
115
|
-
---
|
|
116
|
-
|
|
117
|
-
## 4. Design Input Review
|
|
118
|
-
|
|
119
|
-
Record the review of design inputs for completeness, unambiguity, and absence of conflicts per 21 CFR 820.30(c).
|
|
120
|
-
|
|
121
|
-
_[TODO: Document the design input review process and sign-off]_
|
|
122
|
-
|
|
123
|
-
---
|
|
124
|
-
|
|
125
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
126
|
-
|
|
127
|
-
{{include:shared/snippets/approval-block.md}}
|
|
128
|
-
`,Ti=`---
|
|
129
|
-
id: design-output
|
|
130
|
-
title: Design Output Plan
|
|
131
|
-
standard: 21 CFR Part 820
|
|
132
|
-
clauses: ["820.30(d)"]
|
|
133
|
-
required_for: ["FDA_510k", "FDA_PMA"]
|
|
134
|
-
---
|
|
135
|
-
|
|
136
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
137
|
-
|
|
138
|
-
{{toc}}
|
|
139
|
-
|
|
140
|
-
---
|
|
141
|
-
|
|
142
|
-
## 1. Purpose
|
|
143
|
-
|
|
144
|
-
Defines design outputs for **{{project.product}}** per 21 CFR 820.30(d). Design outputs are the results of the design process, forming the basis for manufacturing.
|
|
145
|
-
|
|
146
|
-
---
|
|
147
|
-
|
|
148
|
-
## 2. Design Outputs
|
|
149
|
-
|
|
150
|
-
### 2.1 Hardware Design Outputs
|
|
151
|
-
|
|
152
|
-
\`\`\`memo-query
|
|
153
|
-
kind: [Component, Subsystem, DesignOutput]
|
|
154
|
-
where: layer == "physical"
|
|
155
|
-
display: table
|
|
156
|
-
columns: name, kind, layer, doc
|
|
157
|
-
sort: name
|
|
158
|
-
empty: "No hardware design outputs defined."
|
|
159
|
-
\`\`\`
|
|
160
|
-
|
|
161
|
-
### 2.2 Software Design Outputs
|
|
162
|
-
|
|
163
|
-
\`\`\`memo-query
|
|
164
|
-
kind: [SoftwareItem, SoftwareUnit, DesignOutput]
|
|
165
|
-
where: layer == "software"
|
|
166
|
-
display: table
|
|
167
|
-
columns: name, kind, layer, doc
|
|
168
|
-
sort: name
|
|
169
|
-
empty: "No software design outputs defined."
|
|
170
|
-
\`\`\`
|
|
171
|
-
|
|
172
|
-
### 2.3 All Design Outputs
|
|
173
|
-
|
|
174
|
-
\`\`\`memo-query
|
|
175
|
-
kind: DesignOutput
|
|
176
|
-
display: table
|
|
177
|
-
columns: name, layer, doc
|
|
178
|
-
sort: name
|
|
179
|
-
empty: "No DesignOutput elements defined. Add DesignOutput elements."
|
|
180
|
-
\`\`\`
|
|
181
|
-
|
|
182
|
-
---
|
|
183
|
-
|
|
184
|
-
## 3. Design Output → Input Traceability
|
|
185
|
-
|
|
186
|
-
Traceability from design outputs back to design inputs, generated live from the model:
|
|
187
|
-
|
|
188
|
-
_[TODO: Demonstrate that each design output meets a design input requirement]_
|
|
189
|
-
|
|
190
|
-
---
|
|
191
|
-
|
|
192
|
-
## 4. Essential Design Output Documents
|
|
193
|
-
|
|
194
|
-
List the documents constituting the essential design outputs for the DHF.
|
|
195
|
-
|
|
196
|
-
| Document | Description | Status |
|
|
197
|
-
| --- | --- | --- |
|
|
198
|
-
| Engineering drawings | Physical design specifications | |
|
|
199
|
-
| Software architecture | Software design specifications | |
|
|
200
|
-
| Manufacturing specs | Production procedures | |
|
|
201
|
-
| Labeling | Device labels and IFU | |
|
|
202
|
-
|
|
203
|
-
---
|
|
204
|
-
|
|
205
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
206
|
-
|
|
207
|
-
{{include:shared/snippets/approval-block.md}}
|
|
208
|
-
`,Ii=`---
|
|
209
|
-
id: design-review
|
|
210
|
-
title: Design Review Record
|
|
211
|
-
standard: 21 CFR Part 820
|
|
212
|
-
clauses: ["820.30(e)"]
|
|
213
|
-
required_for: ["FDA_510k", "FDA_PMA"]
|
|
214
|
-
---
|
|
215
|
-
|
|
216
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
217
|
-
|
|
218
|
-
---
|
|
219
|
-
|
|
220
|
-
## 1. Purpose
|
|
221
|
-
|
|
222
|
-
Documents formal design reviews for **{{project.product}}** per 21 CFR 820.30(e).
|
|
223
|
-
|
|
224
|
-
---
|
|
225
|
-
|
|
226
|
-
## 2. Design Review Log
|
|
227
|
-
|
|
228
|
-
Record of formal design reviews with dates, participants, and outcomes:
|
|
229
|
-
|
|
230
|
-
| Review | Date | Stage | Attendees | Outcome | Actions |
|
|
231
|
-
| --- | --- | --- | --- | --- | --- |
|
|
232
|
-
| DR-001 | | Preliminary Design | | | |
|
|
233
|
-
| DR-002 | | Critical Design | | | |
|
|
234
|
-
| DR-003 | | Final Design | | | |
|
|
235
|
-
|
|
236
|
-
---
|
|
237
|
-
|
|
238
|
-
## 3. Open Action Items
|
|
239
|
-
|
|
240
|
-
Action items raised during review, their owners, and due dates:
|
|
241
|
-
|
|
242
|
-
_[TODO: Track all open action items from design reviews]_
|
|
243
|
-
|
|
244
|
-
---
|
|
245
|
-
|
|
246
|
-
## 4. Design Status at Review
|
|
247
|
-
|
|
248
|
-
Snapshot of the design state at the time of review, computed from the model:
|
|
249
|
-
|
|
250
|
-
\`\`\`memo-query
|
|
251
|
-
kind: [Requirement, Requirement, DesignInput, DesignOutput]
|
|
252
|
-
display: count
|
|
253
|
-
label: Total design elements at last review
|
|
254
|
-
\`\`\`
|
|
255
|
-
|
|
256
|
-
---
|
|
257
|
-
|
|
258
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
259
|
-
`,_i=`---
|
|
260
|
-
id: design-validation
|
|
261
|
-
title: Design Validation Records
|
|
262
|
-
standard: 21 CFR Part 820
|
|
263
|
-
clauses: ["820.30(g)"]
|
|
264
|
-
required_for: ["FDA_510k", "FDA_PMA"]
|
|
265
|
-
---
|
|
266
|
-
|
|
267
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
268
|
-
|
|
269
|
-
---
|
|
270
|
-
|
|
271
|
-
## 1. Purpose
|
|
272
|
-
|
|
273
|
-
Documents design validation confirming the device meets user needs and intended use for **{{project.product}}** per 21 CFR 820.30(g).
|
|
274
|
-
|
|
275
|
-
---
|
|
276
|
-
|
|
277
|
-
## 2. Validation Plan Reference
|
|
278
|
-
|
|
279
|
-
Reference the validation plan governing these activities and note any deviations from it.
|
|
280
|
-
|
|
281
|
-
_[TODO: Reference V&V Plan]_
|
|
282
|
-
|
|
283
|
-
---
|
|
284
|
-
|
|
285
|
-
## 3. Clinical/Bench Validation
|
|
286
|
-
|
|
287
|
-
Describe clinical or bench validation activities demonstrating conformity with user needs under actual or simulated use conditions.
|
|
288
|
-
|
|
289
|
-
\`\`\`memo-query
|
|
290
|
-
kind: ValidationActivity
|
|
291
|
-
display: table
|
|
292
|
-
columns: name, layer, doc
|
|
293
|
-
sort: name
|
|
294
|
-
empty: "No validation activities defined."
|
|
295
|
-
\`\`\`
|
|
296
|
-
|
|
297
|
-
---
|
|
298
|
-
|
|
299
|
-
## 4. User Need Coverage
|
|
300
|
-
|
|
301
|
-
Coverage of user needs by validation activities, computed live from the model:
|
|
302
|
-
|
|
303
|
-
\`\`\`memo-query
|
|
304
|
-
kind: [Need, Requirement]
|
|
305
|
-
display: table
|
|
306
|
-
columns: name, layer, doc
|
|
307
|
-
empty: "No user needs defined."
|
|
308
|
-
\`\`\`
|
|
309
|
-
|
|
310
|
-
---
|
|
311
|
-
|
|
312
|
-
## 5. Conclusion
|
|
313
|
-
|
|
314
|
-
Summarize the outcome and state the overall conclusion, including any conditions or follow-up actions.
|
|
315
|
-
|
|
316
|
-
_[TODO: State validation conclusion — device meets intended use for intended users]_
|
|
317
|
-
|
|
318
|
-
---
|
|
319
|
-
|
|
320
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
321
|
-
|
|
322
|
-
{{include:shared/snippets/approval-block.md}}
|
|
323
|
-
`,Ni=`---
|
|
324
|
-
id: design-verification
|
|
325
|
-
title: Design Verification Records
|
|
326
|
-
standard: 21 CFR Part 820
|
|
327
|
-
clauses: ["820.30(f)"]
|
|
328
|
-
required_for: ["FDA_510k", "FDA_PMA"]
|
|
329
|
-
---
|
|
330
|
-
|
|
331
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
332
|
-
|
|
333
|
-
---
|
|
334
|
-
|
|
335
|
-
## 1. Purpose
|
|
336
|
-
|
|
337
|
-
Documents design verification that design outputs meet design inputs for **{{project.product}}** per 21 CFR 820.30(f).
|
|
338
|
-
|
|
339
|
-
---
|
|
340
|
-
|
|
341
|
-
## 2. Verification Matrix
|
|
342
|
-
|
|
343
|
-
The verification traceability below is generated live from the model — every requirement should be covered by at least one verification activity:
|
|
344
|
-
|
|
345
|
-
\`\`\`memo-query
|
|
346
|
-
kind: VerificationActivity
|
|
347
|
-
display: table
|
|
348
|
-
columns: name, layer, doc
|
|
349
|
-
sort: name
|
|
350
|
-
empty: "No verification activities defined."
|
|
351
|
-
\`\`\`
|
|
352
|
-
|
|
353
|
-
---
|
|
354
|
-
|
|
355
|
-
## 3. Test Results
|
|
356
|
-
|
|
357
|
-
Test executions and their outcomes are summarized below from the model:
|
|
358
|
-
|
|
359
|
-
\`\`\`memo-query
|
|
360
|
-
kind: TestCase
|
|
361
|
-
display: table
|
|
362
|
-
columns: name, layer, doc
|
|
363
|
-
sort: name
|
|
364
|
-
empty: "No test cases defined."
|
|
365
|
-
\`\`\`
|
|
366
|
-
|
|
367
|
-
---
|
|
368
|
-
|
|
369
|
-
## 4. Design Input Coverage
|
|
370
|
-
|
|
371
|
-
Coverage of design inputs by verification activities, computed live from the model:
|
|
372
|
-
|
|
373
|
-
_[TODO: Demonstrate that all design inputs are verified by at least one test]_
|
|
374
|
-
|
|
375
|
-
---
|
|
376
|
-
|
|
377
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
378
|
-
|
|
379
|
-
{{include:shared/snippets/approval-block.md}}
|
|
380
|
-
`,Mi=`---
|
|
381
|
-
id: dhf-index
|
|
382
|
-
title: Design History File Index
|
|
383
|
-
standard: 21 CFR Part 820
|
|
384
|
-
clauses: ["820.30(j)", "ISO 13485:2016 §4.2.4"]
|
|
385
|
-
required_for: ["FDA_510k", "FDA_PMA", "CE", "MDR"]
|
|
386
|
-
---
|
|
387
|
-
|
|
388
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
389
|
-
|
|
390
|
-
{{toc}}
|
|
391
|
-
|
|
392
|
-
---
|
|
393
|
-
|
|
394
|
-
## 1. Purpose
|
|
395
|
-
|
|
396
|
-
This Design History File (DHF) Index serves as the master index for all design and development records for **{{project.product}}** per 21 CFR 820.30(j).
|
|
397
|
-
|
|
398
|
-
---
|
|
399
|
-
|
|
400
|
-
## 2. Device Summary
|
|
401
|
-
|
|
402
|
-
Key characteristics of **{{project.product}}**, drawn from the model:
|
|
403
|
-
|
|
404
|
-
| Field | Value |
|
|
405
|
-
| --- | --- |
|
|
406
|
-
| Device Name | {{project.product}} |
|
|
407
|
-
| Company | {{project.company}} |
|
|
408
|
-
| Device Type | {{project.device_type}} |
|
|
409
|
-
| Development Phase | {{project.phase}} |
|
|
410
|
-
| Version | {{project.version}} |
|
|
411
|
-
|
|
412
|
-
---
|
|
413
|
-
|
|
414
|
-
## 3. DHF Documents
|
|
415
|
-
|
|
416
|
-
### Risk Management
|
|
417
|
-
|
|
418
|
-
| Document | Standard | Status |
|
|
419
|
-
| --- | --- | --- |
|
|
420
|
-
| Risk Management Plan | ISO 14971:2019 §4.4 | |
|
|
421
|
-
| Hazard Analysis Report | ISO 14971:2019 §5-7 | |
|
|
422
|
-
| FMEA | IEC 60812:2018 | |
|
|
423
|
-
| Risk Management Report | ISO 14971:2019 §9 | |
|
|
424
|
-
|
|
425
|
-
### Design Controls
|
|
426
|
-
|
|
427
|
-
| Document | Standard | Status |
|
|
428
|
-
| --- | --- | --- |
|
|
429
|
-
| User Needs | 21 CFR 820.30(c) | |
|
|
430
|
-
| Design Input Plan | 21 CFR 820.30(c) | |
|
|
431
|
-
| Design Output Plan | 21 CFR 820.30(d) | |
|
|
432
|
-
| V&V Plan | 21 CFR 820.30(f-g) | |
|
|
433
|
-
| V&V Report | 21 CFR 820.30(f-g) | |
|
|
434
|
-
| Design Transfer Plan | 21 CFR 820.30(h) | |
|
|
435
|
-
|
|
436
|
-
### Software Documentation
|
|
437
|
-
|
|
438
|
-
| Document | Standard | Status |
|
|
439
|
-
| --- | --- | --- |
|
|
440
|
-
| Software Development Plan | IEC 62304 §5.1 | |
|
|
441
|
-
| Software Requirements Specification | IEC 62304 §5.2 | |
|
|
442
|
-
| Software Architecture Description | IEC 62304 §5.3 | |
|
|
443
|
-
| SOUP List | IEC 62304 §8.1.2 | |
|
|
444
|
-
| Software Traceability Matrix | IEC 62304 §5.7.5 | |
|
|
445
|
-
|
|
446
|
-
### Usability Engineering
|
|
447
|
-
|
|
448
|
-
| Document | Standard | Status |
|
|
449
|
-
| --- | --- | --- |
|
|
450
|
-
| Usability Engineering Plan | IEC 62366-1 §4 | |
|
|
451
|
-
| Use-Related Risk Analysis | IEC 62366-1 §5 | |
|
|
452
|
-
| Summative Evaluation Report | IEC 62366-1 §5.9 | |
|
|
453
|
-
|
|
454
|
-
---
|
|
455
|
-
|
|
456
|
-
## 4. Model Summary
|
|
457
|
-
|
|
458
|
-
Summary statistics of the system model at the time this document was generated:
|
|
459
|
-
|
|
460
|
-
\`\`\`memo-query
|
|
461
|
-
kind: [Requirement, Requirement]
|
|
462
|
-
display: count
|
|
463
|
-
label: Total requirements
|
|
464
|
-
\`\`\`
|
|
465
|
-
|
|
466
|
-
\`\`\`memo-query
|
|
467
|
-
kind: Hazard
|
|
468
|
-
display: count
|
|
469
|
-
label: Total hazards
|
|
470
|
-
\`\`\`
|
|
471
|
-
|
|
472
|
-
\`\`\`memo-query
|
|
473
|
-
kind: [TestCase, VerificationActivity]
|
|
474
|
-
display: count
|
|
475
|
-
label: Total test cases
|
|
476
|
-
\`\`\`
|
|
477
|
-
|
|
478
|
-
---
|
|
479
|
-
|
|
480
|
-
## 5. All Model Elements
|
|
481
|
-
|
|
482
|
-
{{glossary}}
|
|
483
|
-
|
|
484
|
-
---
|
|
485
|
-
|
|
486
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
487
|
-
|
|
488
|
-
{{include:shared/snippets/approval-block.md}}
|
|
489
|
-
|
|
490
|
-
{{include:shared/snippets/references-section.md}}
|
|
491
|
-
`,Oi=`---
|
|
492
|
-
id: transfer-plan
|
|
493
|
-
title: Design Transfer Plan
|
|
494
|
-
standard: 21 CFR Part 820
|
|
495
|
-
clauses: ["820.30(h)"]
|
|
496
|
-
required_for: ["FDA_510k", "FDA_PMA"]
|
|
497
|
-
---
|
|
498
|
-
|
|
499
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
500
|
-
|
|
501
|
-
---
|
|
502
|
-
|
|
503
|
-
## 1. Purpose
|
|
504
|
-
|
|
505
|
-
Defines design transfer activities for **{{project.product}}** per 21 CFR 820.30(h), ensuring device design is correctly translated to production specifications.
|
|
506
|
-
|
|
507
|
-
---
|
|
508
|
-
|
|
509
|
-
## 2. Transfer Checklist
|
|
510
|
-
|
|
511
|
-
Checklist of items required before design transfer to production is complete:
|
|
512
|
-
|
|
513
|
-
| Activity | Responsible | Completion Date | Status |
|
|
514
|
-
| --- | --- | --- | --- |
|
|
515
|
-
| Engineering drawings released to production | | | |
|
|
516
|
-
| Software build process documented | | | |
|
|
517
|
-
| Production procedures validated | | | |
|
|
518
|
-
| Test equipment calibrated | | | |
|
|
519
|
-
| Production personnel trained | | | |
|
|
520
|
-
| First article inspection completed | | | |
|
|
521
|
-
|
|
522
|
-
---
|
|
523
|
-
|
|
524
|
-
## 3. Production Specifications
|
|
525
|
-
|
|
526
|
-
Production specifications derived from the design outputs:
|
|
527
|
-
|
|
528
|
-
\`\`\`memo-query
|
|
529
|
-
kind: DesignOutput
|
|
530
|
-
display: table
|
|
531
|
-
columns: name, layer, doc
|
|
532
|
-
sort: name
|
|
533
|
-
empty: "No design outputs defined."
|
|
534
|
-
\`\`\`
|
|
535
|
-
|
|
536
|
-
---
|
|
537
|
-
|
|
538
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
539
|
-
|
|
540
|
-
{{include:shared/snippets/approval-block.md}}
|
|
541
|
-
`,Pi=`---
|
|
542
|
-
id: user-needs
|
|
543
|
-
title: User Needs Document
|
|
544
|
-
standard: 21 CFR Part 820
|
|
545
|
-
clauses: ["820.30(c)"]
|
|
546
|
-
required_for: ["FDA_510k", "FDA_PMA"]
|
|
547
|
-
---
|
|
548
|
-
|
|
549
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
550
|
-
|
|
551
|
-
{{toc}}
|
|
552
|
-
|
|
553
|
-
---
|
|
554
|
-
|
|
555
|
-
## 1. Purpose
|
|
556
|
-
|
|
557
|
-
This document captures user needs for **{{project.product}}** per 21 CFR 820.30(c) Design Input requirements. User needs represent the intended purpose of the device as stated by customers and intended users.
|
|
558
|
-
|
|
559
|
-
---
|
|
560
|
-
|
|
561
|
-
## 2. Intended Users
|
|
562
|
-
|
|
563
|
-
Identify every intended user group of **{{project.product}}**, including their roles, training assumptions, and use environments.
|
|
564
|
-
|
|
565
|
-
_[TODO: Describe all intended user groups with their roles, training levels, and environments]_
|
|
566
|
-
|
|
567
|
-
---
|
|
568
|
-
|
|
569
|
-
## 3. User Needs
|
|
570
|
-
|
|
571
|
-
User needs captured for **{{project.product}}** are listed below from the model. Each user need should trace forward to at least one design input:
|
|
572
|
-
|
|
573
|
-
\`\`\`memo-query
|
|
574
|
-
kind: [Need, Requirement]
|
|
575
|
-
display: table
|
|
576
|
-
columns: name, layer, doc
|
|
577
|
-
sort: name
|
|
578
|
-
empty: "No user need elements defined. Add Need or Requirement elements."
|
|
579
|
-
\`\`\`
|
|
580
|
-
|
|
581
|
-
---
|
|
582
|
-
|
|
583
|
-
## 4. Use Cases
|
|
584
|
-
|
|
585
|
-
Use cases describing how intended users interact with **{{project.product}}**, drawn from the model:
|
|
586
|
-
|
|
587
|
-
\`\`\`memo-query
|
|
588
|
-
kind: UseCase
|
|
589
|
-
display: table
|
|
590
|
-
columns: name, layer, doc
|
|
591
|
-
sort: name
|
|
592
|
-
empty: "No use cases defined."
|
|
593
|
-
\`\`\`
|
|
594
|
-
|
|
595
|
-
---
|
|
596
|
-
|
|
597
|
-
## 5. Customer Requirements
|
|
598
|
-
|
|
599
|
-
List customer-stated requirements that serve as input to the design process.
|
|
600
|
-
|
|
601
|
-
_[TODO: List customer-stated requirements as input to the design process]_
|
|
602
|
-
|
|
603
|
-
---
|
|
604
|
-
|
|
605
|
-
## 6. Regulatory Requirements
|
|
606
|
-
|
|
607
|
-
Regulatory and standards requirements applicable to **{{project.product}}**:
|
|
608
|
-
|
|
609
|
-
| Standard | Applicability | Notes |
|
|
610
|
-
| --- | --- | --- |
|
|
611
|
-
| 21 CFR Part 820 | Quality System Regulation | |
|
|
612
|
-
| IEC 62304 | Software lifecycle | If Class B/C SW |
|
|
613
|
-
| ISO 14971 | Risk management | |
|
|
614
|
-
|
|
615
|
-
---
|
|
616
|
-
|
|
617
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
618
|
-
|
|
619
|
-
{{include:shared/snippets/approval-block.md}}
|
|
620
|
-
|
|
621
|
-
{{include:shared/snippets/references-section.md}}
|
|
622
|
-
`,zi=`---
|
|
623
|
-
id: vv-plan
|
|
624
|
-
title: Verification and Validation Plan
|
|
625
|
-
standard: 21 CFR Part 820
|
|
626
|
-
clauses: ["820.30(f)", "820.30(g)"]
|
|
627
|
-
required_for: ["FDA_510k", "FDA_PMA", "CE"]
|
|
628
|
-
---
|
|
629
|
-
|
|
630
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
631
|
-
|
|
632
|
-
{{toc}}
|
|
633
|
-
|
|
634
|
-
---
|
|
635
|
-
|
|
636
|
-
## 1. Purpose
|
|
637
|
-
|
|
638
|
-
This V&V Plan defines verification and validation activities for **{{project.product}}** per 21 CFR 820.30(f)-(g) and ISO 13485:2016 §7.3.6-7.3.7.
|
|
639
|
-
|
|
640
|
-
---
|
|
641
|
-
|
|
642
|
-
## 2. Scope
|
|
643
|
-
|
|
644
|
-
This plan covers:
|
|
645
|
-
- Software verification (per IEC 62304 §5.6-5.7)
|
|
646
|
-
- Hardware verification
|
|
647
|
-
- System-level validation
|
|
648
|
-
- Usability validation (per IEC 62366-1)
|
|
649
|
-
|
|
650
|
-
---
|
|
651
|
-
|
|
652
|
-
## 3. Verification Activities
|
|
653
|
-
|
|
654
|
-
### 3.1 Requirements to Verify
|
|
655
|
-
|
|
656
|
-
\`\`\`memo-query
|
|
657
|
-
kind: [Requirement, Requirement]
|
|
658
|
-
display: table
|
|
659
|
-
columns: name, layer, doc
|
|
660
|
-
sort: name
|
|
661
|
-
empty: "No requirements defined."
|
|
662
|
-
\`\`\`
|
|
663
|
-
|
|
664
|
-
### 3.2 Verification Test Cases
|
|
665
|
-
|
|
666
|
-
\`\`\`memo-query
|
|
667
|
-
kind: [TestCase, VerificationActivity]
|
|
668
|
-
display: table
|
|
669
|
-
columns: name, kind, layer, doc
|
|
670
|
-
sort: name
|
|
671
|
-
empty: "No verification test cases defined."
|
|
672
|
-
\`\`\`
|
|
673
|
-
|
|
674
|
-
---
|
|
675
|
-
|
|
676
|
-
## 4. Validation Activities
|
|
677
|
-
|
|
678
|
-
Validation activities demonstrating that **{{project.product}}** meets user needs and intended uses:
|
|
679
|
-
|
|
680
|
-
\`\`\`memo-query
|
|
681
|
-
kind: ValidationActivity
|
|
682
|
-
display: table
|
|
683
|
-
columns: name, layer, doc
|
|
684
|
-
sort: name
|
|
685
|
-
empty: "No validation activities defined."
|
|
686
|
-
\`\`\`
|
|
687
|
-
|
|
688
|
-
---
|
|
689
|
-
|
|
690
|
-
## 5. Acceptance Criteria
|
|
691
|
-
|
|
692
|
-
State the objective criteria that must be met for the validation to be considered successful.
|
|
693
|
-
|
|
694
|
-
_[TODO: Define objective acceptance criteria for all V&V activities]_
|
|
695
|
-
|
|
696
|
-
---
|
|
697
|
-
|
|
698
|
-
## 6. Test Environment
|
|
699
|
-
|
|
700
|
-
Describe the hardware, software, tools, and configuration of the test environment in sufficient detail to reproduce the test setup.
|
|
701
|
-
|
|
702
|
-
_[TODO: Describe hardware, software, and clinical test environments]_
|
|
703
|
-
|
|
704
|
-
---
|
|
705
|
-
|
|
706
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
707
|
-
|
|
708
|
-
{{include:shared/snippets/approval-block.md}}
|
|
709
|
-
|
|
710
|
-
{{include:shared/snippets/references-section.md}}
|
|
711
|
-
`,Bi=`---
|
|
712
|
-
id: vv-report
|
|
713
|
-
title: Verification and Validation Report
|
|
714
|
-
standard: 21 CFR Part 820
|
|
715
|
-
clauses: ["820.30(f)", "820.30(g)"]
|
|
716
|
-
required_for: ["FDA_510k", "FDA_PMA", "CE"]
|
|
717
|
-
---
|
|
718
|
-
|
|
719
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
720
|
-
|
|
721
|
-
{{toc}}
|
|
722
|
-
|
|
723
|
-
---
|
|
724
|
-
|
|
725
|
-
## 1. Purpose
|
|
726
|
-
|
|
727
|
-
This V&V Report documents the results of all verification and validation activities for **{{project.product}}**.
|
|
728
|
-
|
|
729
|
-
---
|
|
730
|
-
|
|
731
|
-
## 2. Summary
|
|
732
|
-
|
|
733
|
-
Summary metrics computed live from the model:
|
|
734
|
-
|
|
735
|
-
\`\`\`memo-query
|
|
736
|
-
kind: TestCase
|
|
737
|
-
display: count
|
|
738
|
-
label: Total test cases
|
|
739
|
-
\`\`\`
|
|
740
|
-
|
|
741
|
-
\`\`\`memo-query
|
|
742
|
-
kind: [VerificationActivity, ValidationActivity]
|
|
743
|
-
display: count
|
|
744
|
-
label: V&V activities
|
|
745
|
-
\`\`\`
|
|
746
|
-
|
|
747
|
-
---
|
|
748
|
-
|
|
749
|
-
## 3. Verification Results
|
|
750
|
-
|
|
751
|
-
### 3.1 Test Results by Requirement
|
|
752
|
-
|
|
753
|
-
\`\`\`memo-query
|
|
754
|
-
kind: [TestCase, VerificationActivity]
|
|
755
|
-
display: table
|
|
756
|
-
columns: name, kind, layer, doc
|
|
757
|
-
sort: name
|
|
758
|
-
empty: "No verification activities defined."
|
|
759
|
-
\`\`\`
|
|
760
|
-
|
|
761
|
-
---
|
|
762
|
-
|
|
763
|
-
## 4. Validation Results
|
|
764
|
-
|
|
765
|
-
Results of the validation activities are summarized below:
|
|
766
|
-
|
|
767
|
-
\`\`\`memo-query
|
|
768
|
-
kind: ValidationActivity
|
|
769
|
-
display: table
|
|
770
|
-
columns: name, layer, doc
|
|
771
|
-
sort: name
|
|
772
|
-
empty: "No validation activities defined."
|
|
773
|
-
\`\`\`
|
|
774
|
-
|
|
775
|
-
---
|
|
776
|
-
|
|
777
|
-
## 5. Known Anomalies and Deviations
|
|
778
|
-
|
|
779
|
-
Record any anomalies, deviations from plan, and their disposition, including rationale for acceptance of unresolved anomalies.
|
|
780
|
-
|
|
781
|
-
_[TODO: List any unresolved anomalies and provide justification for acceptance]_
|
|
782
|
-
|
|
783
|
-
---
|
|
784
|
-
|
|
785
|
-
## 6. V&V Conclusion
|
|
786
|
-
|
|
787
|
-
State the overall verification and validation conclusion for **{{project.product}}**, including any conditions, limitations, or required follow-up actions.
|
|
788
|
-
|
|
789
|
-
_[TODO: State whether the device meets all design inputs and is fit for intended use]_
|
|
790
|
-
|
|
791
|
-
---
|
|
792
|
-
|
|
793
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
794
|
-
|
|
795
|
-
{{include:shared/snippets/approval-block.md}}
|
|
796
|
-
`,Li=`---
|
|
797
|
-
id: incident-response
|
|
798
|
-
title: Cybersecurity Incident Response Plan
|
|
799
|
-
standard: FDA Cybersecurity Guidance 2023
|
|
800
|
-
clauses: ["5.2"]
|
|
801
|
-
required_for: ["FDA_510k", "FDA_PMA"]
|
|
802
|
-
---
|
|
803
|
-
|
|
804
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
805
|
-
|
|
806
|
-
---
|
|
807
|
-
|
|
808
|
-
## 1. Purpose
|
|
809
|
-
|
|
810
|
-
Defines the incident response process for cybersecurity events affecting **{{project.product}}**.
|
|
811
|
-
|
|
812
|
-
---
|
|
813
|
-
|
|
814
|
-
## 2. Incident Classification
|
|
815
|
-
|
|
816
|
-
Define the severity classes for security incidents and the criteria for assigning them.
|
|
817
|
-
|
|
818
|
-
| Class | Description | Response Time | FDA Reporting |
|
|
819
|
-
| --- | --- | --- | --- |
|
|
820
|
-
| Class 1 | Exploited vulnerability affecting device safety | 24 hours | Required within 30 days |
|
|
821
|
-
| Class 2 | Unpatched but known vulnerability | 72 hours | Likely required |
|
|
822
|
-
| Class 3 | Suspected security event | 5 days | Assess case-by-case |
|
|
823
|
-
|
|
824
|
-
---
|
|
825
|
-
|
|
826
|
-
## 3. Response Team
|
|
827
|
-
|
|
828
|
-
Identify the incident response team members, their roles, and contact paths.
|
|
829
|
-
|
|
830
|
-
| Role | Responsible Party | Contact |
|
|
831
|
-
| --- | --- | --- |
|
|
832
|
-
| Incident Commander | | |
|
|
833
|
-
| Security Lead | | |
|
|
834
|
-
| Regulatory Affairs | | |
|
|
835
|
-
| Clinical Safety | | |
|
|
836
|
-
| Legal/Compliance | | |
|
|
837
|
-
|
|
838
|
-
---
|
|
839
|
-
|
|
840
|
-
## 4. Response Procedure
|
|
841
|
-
|
|
842
|
-
1. Detection and initial assessment
|
|
843
|
-
2. Containment of affected devices
|
|
844
|
-
3. Impact analysis (patient safety, data)
|
|
845
|
-
4. Develop and test patch
|
|
846
|
-
5. Deploy and verify patch
|
|
847
|
-
6. FDA notification (if required)
|
|
848
|
-
7. Customer notification
|
|
849
|
-
8. Post-incident review
|
|
850
|
-
|
|
851
|
-
---
|
|
852
|
-
|
|
853
|
-
## 5. Coordinated Vulnerability Disclosure
|
|
854
|
-
|
|
855
|
-
Describe the process by which external researchers can report vulnerabilities and how reports are triaged and disclosed.
|
|
856
|
-
|
|
857
|
-
_[TODO: Describe the coordinated disclosure policy for external researchers]_
|
|
858
|
-
|
|
859
|
-
---
|
|
860
|
-
|
|
861
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
862
|
-
`,qi=`---
|
|
863
|
-
id: postmarket-surveillance
|
|
864
|
-
title: Post-Market Cybersecurity Surveillance Plan
|
|
865
|
-
standard: FDA Cybersecurity Guidance 2023
|
|
866
|
-
clauses: ["5"]
|
|
867
|
-
required_for: ["FDA_510k", "FDA_PMA"]
|
|
868
|
-
---
|
|
869
|
-
|
|
870
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
871
|
-
|
|
872
|
-
---
|
|
873
|
-
|
|
874
|
-
## 1. Purpose
|
|
875
|
-
|
|
876
|
-
Defines ongoing cybersecurity surveillance for **{{project.product}}** in the post-market phase per FDA's 2023 guidance.
|
|
877
|
-
|
|
878
|
-
---
|
|
879
|
-
|
|
880
|
-
## 2. Surveillance Sources
|
|
881
|
-
|
|
882
|
-
- NVD / CVE database monitoring for SOUP vulnerabilities
|
|
883
|
-
- ICS-CERT / FDA MedSun cybersecurity alerts
|
|
884
|
-
- Vulnerability reports from customers and researchers
|
|
885
|
-
- Threat intelligence feeds
|
|
886
|
-
|
|
887
|
-
---
|
|
888
|
-
|
|
889
|
-
## 3. SOUP Monitoring
|
|
890
|
-
|
|
891
|
-
Describe the process for ongoing monitoring of SOUP components for newly published vulnerabilities.
|
|
892
|
-
|
|
893
|
-
\`\`\`memo-query
|
|
894
|
-
kind: SOUPComponent
|
|
895
|
-
display: table
|
|
896
|
-
columns: name, doc
|
|
897
|
-
sort: name
|
|
898
|
-
empty: "No SOUP components to monitor."
|
|
899
|
-
\`\`\`
|
|
900
|
-
|
|
901
|
-
---
|
|
902
|
-
|
|
903
|
-
## 4. Response Timelines
|
|
904
|
-
|
|
905
|
-
Define target timelines for triage, containment, remediation, and notification per incident class.
|
|
906
|
-
|
|
907
|
-
| Severity | CVSS Score | Response Target |
|
|
908
|
-
| --- | --- | --- |
|
|
909
|
-
| Critical | 9.0–10.0 | 30 days |
|
|
910
|
-
| High | 7.0–8.9 | 60 days |
|
|
911
|
-
| Medium | 4.0–6.9 | 90 days |
|
|
912
|
-
| Low | < 4.0 | Next release |
|
|
913
|
-
|
|
914
|
-
---
|
|
915
|
-
|
|
916
|
-
## 5. Patch and Update Process
|
|
917
|
-
|
|
918
|
-
Describe how security patches are developed, verified, approved, and deployed to fielded devices.
|
|
919
|
-
|
|
920
|
-
_[TODO: Describe how security patches are tested, validated, and released]_
|
|
921
|
-
|
|
922
|
-
---
|
|
923
|
-
|
|
924
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
925
|
-
`,Vi=`---
|
|
926
|
-
id: security-arch
|
|
927
|
-
title: Cybersecurity Architecture Description
|
|
928
|
-
standard: FDA Cybersecurity Guidance 2023
|
|
929
|
-
clauses: ["3.3"]
|
|
930
|
-
required_for: ["FDA_510k", "FDA_PMA"]
|
|
931
|
-
---
|
|
932
|
-
|
|
933
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
934
|
-
|
|
935
|
-
{{toc}}
|
|
936
|
-
|
|
937
|
-
---
|
|
938
|
-
|
|
939
|
-
## 1. Purpose
|
|
940
|
-
|
|
941
|
-
Describes the cybersecurity architecture for **{{project.product}}** per FDA's 2023 guidance and IEC 81001-5-1:2021.
|
|
942
|
-
|
|
943
|
-
---
|
|
944
|
-
|
|
945
|
-
## 2. Security Architecture
|
|
946
|
-
|
|
947
|
-
This section describes the security architecture of **{{project.product}}**. The security-relevant elements below are drawn from the model:
|
|
948
|
-
|
|
949
|
-
{{diagram:security-architecture}}
|
|
950
|
-
|
|
951
|
-
---
|
|
952
|
-
|
|
953
|
-
## 3. Trusted Zones and Communication Paths
|
|
954
|
-
|
|
955
|
-
Define the trusted zones, the communication paths crossing zone boundaries, and the protection applied at each crossing.
|
|
956
|
-
|
|
957
|
-
\`\`\`memo-query
|
|
958
|
-
kind: Interface
|
|
959
|
-
display: table
|
|
960
|
-
columns: name, layer, doc
|
|
961
|
-
sort: name
|
|
962
|
-
empty: "No interfaces defined."
|
|
963
|
-
\`\`\`
|
|
964
|
-
|
|
965
|
-
---
|
|
966
|
-
|
|
967
|
-
## 4. Security Controls
|
|
968
|
-
|
|
969
|
-
Security controls implemented in **{{project.product}}** are listed below from the model. Each control should trace to at least one identified threat:
|
|
970
|
-
|
|
971
|
-
\`\`\`memo-query
|
|
972
|
-
kind: SecurityControl
|
|
973
|
-
display: table
|
|
974
|
-
columns: name, layer, doc
|
|
975
|
-
sort: name
|
|
976
|
-
empty: "No security controls defined."
|
|
977
|
-
\`\`\`
|
|
978
|
-
|
|
979
|
-
---
|
|
980
|
-
|
|
981
|
-
## 5. Cybersecurity Design Principles Applied
|
|
982
|
-
|
|
983
|
-
Describe how core security principles (least privilege, defense in depth, secure defaults, fail secure) are applied in the design.
|
|
984
|
-
|
|
985
|
-
_[TODO: Document which NIST CSF or IEC 81001-5-1 principles are applied]_
|
|
986
|
-
|
|
987
|
-
| Principle | Implementation | Reference |
|
|
988
|
-
| --- | --- | --- |
|
|
989
|
-
| Least privilege | | |
|
|
990
|
-
| Defense in depth | | |
|
|
991
|
-
| Fail secure | | |
|
|
992
|
-
| Cryptographic controls | | |
|
|
993
|
-
| Secure boot | | |
|
|
994
|
-
|
|
995
|
-
---
|
|
996
|
-
|
|
997
|
-
## 6. Security Testing
|
|
998
|
-
|
|
999
|
-
Describe the security testing performed (e.g. static analysis, fuzzing, penetration testing) and reference the detailed results.
|
|
1000
|
-
|
|
1001
|
-
_[TODO: Describe penetration testing, vulnerability scanning, and security code review]_
|
|
1002
|
-
|
|
1003
|
-
---
|
|
1004
|
-
|
|
1005
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
1006
|
-
|
|
1007
|
-
{{include:shared/snippets/approval-block.md}}
|
|
1008
|
-
`,$i=`---
|
|
1009
|
-
id: threat-model
|
|
1010
|
-
title: Cybersecurity Threat Model
|
|
1011
|
-
standard: FDA Cybersecurity Guidance 2023
|
|
1012
|
-
clauses: ["3.2"]
|
|
1013
|
-
required_for: ["FDA_510k", "FDA_PMA"]
|
|
1014
|
-
---
|
|
1015
|
-
|
|
1016
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
1017
|
-
|
|
1018
|
-
{{toc}}
|
|
1019
|
-
|
|
1020
|
-
---
|
|
1021
|
-
|
|
1022
|
-
## 1. Purpose
|
|
1023
|
-
|
|
1024
|
-
This threat model documents cybersecurity threats for **{{project.product}}** per FDA's 2023 Cybersecurity in Medical Devices guidance and IEC 81001-5-1:2021.
|
|
1025
|
-
|
|
1026
|
-
---
|
|
1027
|
-
|
|
1028
|
-
## 2. System Assets
|
|
1029
|
-
|
|
1030
|
-
Assets requiring protection (data, functions, interfaces), drawn from the model:
|
|
1031
|
-
|
|
1032
|
-
\`\`\`memo-query
|
|
1033
|
-
kind: [SoftwareSystem, Interface, SOUPComponent]
|
|
1034
|
-
display: table
|
|
1035
|
-
columns: name, kind, layer, doc
|
|
1036
|
-
sort: name
|
|
1037
|
-
empty: "No system assets defined."
|
|
1038
|
-
\`\`\`
|
|
1039
|
-
|
|
1040
|
-
---
|
|
1041
|
-
|
|
1042
|
-
## 3. Entry Points and Attack Surface
|
|
1043
|
-
|
|
1044
|
-
Entry points and externally reachable interfaces constituting the attack surface, drawn from the model:
|
|
1045
|
-
|
|
1046
|
-
\`\`\`memo-query
|
|
1047
|
-
kind: Interface
|
|
1048
|
-
display: table
|
|
1049
|
-
columns: name, layer, doc
|
|
1050
|
-
sort: name
|
|
1051
|
-
empty: "No interfaces defined."
|
|
1052
|
-
\`\`\`
|
|
1053
|
-
|
|
1054
|
-
---
|
|
1055
|
-
|
|
1056
|
-
## 4. Threat Catalog
|
|
1057
|
-
|
|
1058
|
-
The threat catalog below is generated from the model. Each threat should be assessed for likelihood and impact and trace to mitigating security controls:
|
|
1059
|
-
|
|
1060
|
-
\`\`\`memo-query
|
|
1061
|
-
kind: ThreatModel
|
|
1062
|
-
display: table
|
|
1063
|
-
columns: name, layer, doc
|
|
1064
|
-
sort: name
|
|
1065
|
-
empty: "No threat model elements defined. Add ThreatModel elements."
|
|
1066
|
-
\`\`\`
|
|
1067
|
-
|
|
1068
|
-
### 4.1 STRIDE Analysis
|
|
1069
|
-
|
|
1070
|
-
| Threat Category | Description | Affected Assets | Likelihood | Impact |
|
|
1071
|
-
| --- | --- | --- | --- | --- |
|
|
1072
|
-
| Spoofing | | | | |
|
|
1073
|
-
| Tampering | | | | |
|
|
1074
|
-
| Repudiation | | | | |
|
|
1075
|
-
| Information Disclosure | | | | |
|
|
1076
|
-
| Denial of Service | | | | |
|
|
1077
|
-
| Elevation of Privilege | | | | |
|
|
1078
|
-
|
|
1079
|
-
---
|
|
1080
|
-
|
|
1081
|
-
## 5. Security Controls
|
|
1082
|
-
|
|
1083
|
-
Security controls implemented in **{{project.product}}** are listed below from the model. Each control should trace to at least one identified threat:
|
|
1084
|
-
|
|
1085
|
-
\`\`\`memo-query
|
|
1086
|
-
kind: SecurityControl
|
|
1087
|
-
display: table
|
|
1088
|
-
columns: name, layer, doc
|
|
1089
|
-
sort: name
|
|
1090
|
-
empty: "No security controls defined."
|
|
1091
|
-
\`\`\`
|
|
1092
|
-
|
|
1093
|
-
---
|
|
1094
|
-
|
|
1095
|
-
## 6. Unmitigated Threats
|
|
1096
|
-
|
|
1097
|
-
Threats without a mitigating security control are surfaced below by a live model query — this list should be empty before release:
|
|
1098
|
-
|
|
1099
|
-
_[TODO: List any threats without security controls and provide residual risk justification]_
|
|
1100
|
-
|
|
1101
|
-
---
|
|
1102
|
-
|
|
1103
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
1104
|
-
|
|
1105
|
-
{{include:shared/snippets/approval-block.md}}
|
|
1106
|
-
|
|
1107
|
-
{{include:shared/snippets/references-section.md}}
|
|
1108
|
-
`,Ui=`---
|
|
1109
|
-
id: vuln-assessment
|
|
1110
|
-
title: Vulnerability Assessment and Penetration Testing Report
|
|
1111
|
-
standard: FDA Cybersecurity Guidance 2023
|
|
1112
|
-
clauses: ["3.4"]
|
|
1113
|
-
required_for: ["FDA_510k", "FDA_PMA"]
|
|
1114
|
-
---
|
|
1115
|
-
|
|
1116
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
1117
|
-
|
|
1118
|
-
{{toc}}
|
|
1119
|
-
|
|
1120
|
-
---
|
|
1121
|
-
|
|
1122
|
-
## 1. Purpose
|
|
1123
|
-
|
|
1124
|
-
Documents cybersecurity vulnerability assessment and testing for **{{project.product}}** per FDA's 2023 cybersecurity guidance.
|
|
1125
|
-
|
|
1126
|
-
---
|
|
1127
|
-
|
|
1128
|
-
## 2. Scope of Assessment
|
|
1129
|
-
|
|
1130
|
-
Define the boundaries of this assessment: components, interfaces, and threat classes in and out of scope.
|
|
1131
|
-
|
|
1132
|
-
\`\`\`memo-query
|
|
1133
|
-
kind: [SoftwareSystem, SoftwareItem, Interface]
|
|
1134
|
-
display: table
|
|
1135
|
-
columns: name, kind, layer
|
|
1136
|
-
sort: name
|
|
1137
|
-
empty: "No software assets defined."
|
|
1138
|
-
\`\`\`
|
|
1139
|
-
|
|
1140
|
-
---
|
|
1141
|
-
|
|
1142
|
-
## 3. SOUP/Third-Party Component Vulnerabilities
|
|
1143
|
-
|
|
1144
|
-
Known vulnerabilities in SOUP and third-party components (e.g. from CVE/NVD monitoring) and their disposition:
|
|
1145
|
-
|
|
1146
|
-
\`\`\`memo-query
|
|
1147
|
-
kind: SOUPComponent
|
|
1148
|
-
display: table
|
|
1149
|
-
columns: name, doc
|
|
1150
|
-
sort: name
|
|
1151
|
-
empty: "No SOUP components defined."
|
|
1152
|
-
\`\`\`
|
|
1153
|
-
|
|
1154
|
-
---
|
|
1155
|
-
|
|
1156
|
-
## 4. Vulnerability Findings
|
|
1157
|
-
|
|
1158
|
-
Identified vulnerabilities and their assessment are listed below:
|
|
1159
|
-
|
|
1160
|
-
| CVE / Finding | Component | Severity (CVSS) | Status | Mitigation |
|
|
1161
|
-
| --- | --- | --- | --- | --- |
|
|
1162
|
-
| | | | | |
|
|
1163
|
-
|
|
1164
|
-
---
|
|
1165
|
-
|
|
1166
|
-
## 5. Penetration Test Results
|
|
1167
|
-
|
|
1168
|
-
Summarize the scope, methodology, and findings of penetration testing.
|
|
1169
|
-
|
|
1170
|
-
_[TODO: Summarize penetration testing scope, methodology, and findings]_
|
|
1171
|
-
|
|
1172
|
-
---
|
|
1173
|
-
|
|
1174
|
-
## 6. Residual Vulnerabilities
|
|
1175
|
-
|
|
1176
|
-
Vulnerabilities remaining after mitigation, with the rationale for their acceptability:
|
|
1177
|
-
|
|
1178
|
-
_[TODO: Document any accepted residual vulnerabilities with justification]_
|
|
1179
|
-
|
|
1180
|
-
---
|
|
1181
|
-
|
|
1182
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
1183
|
-
|
|
1184
|
-
{{include:shared/snippets/approval-block.md}}
|
|
1185
|
-
`,Wi=`---
|
|
1186
|
-
id: change-control
|
|
1187
|
-
title: Software Change Control Log
|
|
1188
|
-
standard: IEC 62304:2006+AMD1:2015
|
|
1189
|
-
clauses: ["6"]
|
|
1190
|
-
required_for: ["CE", "FDA_510k", "MDR"]
|
|
1191
|
-
---
|
|
1192
|
-
|
|
1193
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
1194
|
-
|
|
1195
|
-
---
|
|
1196
|
-
|
|
1197
|
-
## 1. Purpose
|
|
1198
|
-
|
|
1199
|
-
This log documents all changes to **{{project.product}}** software, including the change description, impact assessment, and approval per IEC 62304:2006 §6.
|
|
1200
|
-
|
|
1201
|
-
---
|
|
1202
|
-
|
|
1203
|
-
## 2. Change Log
|
|
1204
|
-
|
|
1205
|
-
Record each change with its identifier, description, affected items, and verification status:
|
|
1206
|
-
|
|
1207
|
-
| Change ID | Date | Version | Description | Impact Assessment | Approved By |
|
|
1208
|
-
| --- | --- | --- | --- | --- | --- |
|
|
1209
|
-
| CHG-001 | | 1.0.0 | Initial release | N/A | |
|
|
1210
|
-
|
|
1211
|
-
---
|
|
1212
|
-
|
|
1213
|
-
## 3. Change Procedure
|
|
1214
|
-
|
|
1215
|
-
All changes must:
|
|
1216
|
-
1. Be requested via the change request process
|
|
1217
|
-
2. Have an impact assessment (safety, requirements, design, test)
|
|
1218
|
-
3. Be approved prior to implementation
|
|
1219
|
-
4. Be verified and validated after implementation
|
|
1220
|
-
5. Be documented in this log
|
|
1221
|
-
|
|
1222
|
-
---
|
|
1223
|
-
|
|
1224
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
1225
|
-
`,Hi=`---
|
|
1226
|
-
id: detailed-design
|
|
1227
|
-
title: Software Detailed Design
|
|
1228
|
-
standard: IEC 62304:2006+AMD1:2015
|
|
1229
|
-
clauses: ["5.4"]
|
|
1230
|
-
required_for: ["CE", "FDA_510k"]
|
|
1231
|
-
---
|
|
1232
|
-
|
|
1233
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
1234
|
-
|
|
1235
|
-
{{toc}}
|
|
1236
|
-
|
|
1237
|
-
---
|
|
1238
|
-
|
|
1239
|
-
## 1. Purpose
|
|
1240
|
-
|
|
1241
|
-
This document provides detailed design specifications for **{{project.product}}** software per IEC 62304:2006 §5.4, sufficient to implement and test each software unit.
|
|
1242
|
-
|
|
1243
|
-
---
|
|
1244
|
-
|
|
1245
|
-
## 2. Software Units
|
|
1246
|
-
|
|
1247
|
-
The software units — the lowest level of decomposition per IEC 62304 — are listed below from the model:
|
|
1248
|
-
|
|
1249
|
-
\`\`\`memo-query
|
|
1250
|
-
kind: SoftwareUnit
|
|
1251
|
-
display: table
|
|
1252
|
-
columns: name, layer, doc
|
|
1253
|
-
sort: name
|
|
1254
|
-
empty: "No SoftwareUnit elements defined."
|
|
1255
|
-
\`\`\`
|
|
1256
|
-
|
|
1257
|
-
---
|
|
1258
|
-
|
|
1259
|
-
## 3. Unit Specifications
|
|
1260
|
-
|
|
1261
|
-
### 3.1 Algorithms and Data Structures
|
|
1262
|
-
|
|
1263
|
-
_[TODO: Describe key algorithms, data structures, and design patterns]_
|
|
1264
|
-
|
|
1265
|
-
### 3.2 State Machines
|
|
1266
|
-
|
|
1267
|
-
{{diagram:state-machine}}
|
|
1268
|
-
|
|
1269
|
-
_[TODO: Document state machine diagrams for stateful components]_
|
|
1270
|
-
|
|
1271
|
-
### 3.3 Interface Specifications
|
|
1272
|
-
|
|
1273
|
-
\`\`\`memo-query
|
|
1274
|
-
kind: Interface
|
|
1275
|
-
display: table
|
|
1276
|
-
columns: name, layer, doc
|
|
1277
|
-
sort: name
|
|
1278
|
-
empty: "No Interface elements defined."
|
|
1279
|
-
\`\`\`
|
|
1280
|
-
|
|
1281
|
-
---
|
|
1282
|
-
|
|
1283
|
-
## 4. Design Verification Criteria
|
|
1284
|
-
|
|
1285
|
-
The criteria used to verify that design outputs meet design inputs:
|
|
1286
|
-
|
|
1287
|
-
_[TODO: List criteria that verify this design meets software requirements]_
|
|
1288
|
-
|
|
1289
|
-
---
|
|
1290
|
-
|
|
1291
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
1292
|
-
|
|
1293
|
-
{{include:shared/snippets/approval-block.md}}
|
|
1294
|
-
`,Ki=`---
|
|
1295
|
-
id: integration-test
|
|
1296
|
-
title: Software Integration Test Plan
|
|
1297
|
-
standard: IEC 62304:2006+AMD1:2015
|
|
1298
|
-
clauses: ["5.6"]
|
|
1299
|
-
required_for: ["CE", "FDA_510k", "MDR"]
|
|
1300
|
-
---
|
|
1301
|
-
|
|
1302
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
1303
|
-
|
|
1304
|
-
{{toc}}
|
|
1305
|
-
|
|
1306
|
-
---
|
|
1307
|
-
|
|
1308
|
-
## 1. Purpose
|
|
1309
|
-
|
|
1310
|
-
This Integration Test Plan defines the approach for integration testing of **{{project.product}}** software per IEC 62304:2006 §5.6.
|
|
1311
|
-
|
|
1312
|
-
---
|
|
1313
|
-
|
|
1314
|
-
## 2. Software Items Under Test
|
|
1315
|
-
|
|
1316
|
-
The software items in scope for this test plan, drawn from the model:
|
|
1317
|
-
|
|
1318
|
-
\`\`\`memo-query
|
|
1319
|
-
kind: [SoftwareItem, SoftwareUnit]
|
|
1320
|
-
display: table
|
|
1321
|
-
columns: name, kind, layer, doc
|
|
1322
|
-
sort: name
|
|
1323
|
-
empty: "No software items defined."
|
|
1324
|
-
\`\`\`
|
|
1325
|
-
|
|
1326
|
-
---
|
|
1327
|
-
|
|
1328
|
-
## 3. Integration Test Cases
|
|
1329
|
-
|
|
1330
|
-
Integration test cases are listed below from the model:
|
|
1331
|
-
|
|
1332
|
-
\`\`\`memo-query
|
|
1333
|
-
kind: TestCase
|
|
1334
|
-
where: layer == "verification"
|
|
1335
|
-
display: table
|
|
1336
|
-
columns: name, layer, doc
|
|
1337
|
-
sort: name
|
|
1338
|
-
empty: "No integration test cases defined. Add TestCase elements."
|
|
1339
|
-
\`\`\`
|
|
1340
|
-
|
|
1341
|
-
---
|
|
1342
|
-
|
|
1343
|
-
## 4. Integration Sequence
|
|
1344
|
-
|
|
1345
|
-
Describe the order in which software items are integrated and tested, and the rationale for that order.
|
|
1346
|
-
|
|
1347
|
-
_[TODO: Define the order in which software items are integrated and tested]_
|
|
1348
|
-
|
|
1349
|
-
---
|
|
1350
|
-
|
|
1351
|
-
## 5. Pass/Fail Criteria
|
|
1352
|
-
|
|
1353
|
-
State the objective criteria used to judge each test as passed or failed.
|
|
1354
|
-
|
|
1355
|
-
_[TODO: Define objective pass/fail criteria for integration tests]_
|
|
1356
|
-
|
|
1357
|
-
---
|
|
1358
|
-
|
|
1359
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
1360
|
-
|
|
1361
|
-
{{include:shared/snippets/approval-block.md}}
|
|
1362
|
-
`,Gi=`---
|
|
1363
|
-
id: sad
|
|
1364
|
-
title: Software Architecture Description
|
|
1365
|
-
standard: IEC 62304:2006+AMD1:2015
|
|
1366
|
-
clauses: ["5.3"]
|
|
1367
|
-
required_for: ["CE", "FDA_510k", "MDR"]
|
|
1368
|
-
---
|
|
1369
|
-
|
|
1370
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
1371
|
-
|
|
1372
|
-
{{toc}}
|
|
1373
|
-
|
|
1374
|
-
---
|
|
1375
|
-
|
|
1376
|
-
## 1. Purpose
|
|
1377
|
-
|
|
1378
|
-
This Software Architecture Description (SAD) defines the architecture of **{{project.product}}** software per IEC 62304:2006 §5.3 and ISO/IEC/IEEE 42010:2022.
|
|
1379
|
-
|
|
1380
|
-
---
|
|
1381
|
-
|
|
1382
|
-
## 2. System Overview
|
|
1383
|
-
|
|
1384
|
-
This section gives a high-level overview of the **{{project.product}}** software system. The composition below is drawn live from the architecture model:
|
|
1385
|
-
|
|
1386
|
-
\`\`\`memo-query
|
|
1387
|
-
kind: SoftwareSystem
|
|
1388
|
-
display: table
|
|
1389
|
-
columns: name, layer, doc
|
|
1390
|
-
sort: name
|
|
1391
|
-
empty: "No SoftwareSystem defined."
|
|
1392
|
-
\`\`\`
|
|
1393
|
-
|
|
1394
|
-
**Total elements:**
|
|
1395
|
-
|
|
1396
|
-
\`\`\`memo-query
|
|
1397
|
-
kind: [SoftwareSystem, SoftwareItem, SoftwareUnit, SOUPComponent]
|
|
1398
|
-
display: count
|
|
1399
|
-
label: Total software elements
|
|
1400
|
-
\`\`\`
|
|
1401
|
-
|
|
1402
|
-
---
|
|
1403
|
-
|
|
1404
|
-
## 3. Software Architecture
|
|
1405
|
-
|
|
1406
|
-
This section describes the decomposition of the software into software items per IEC 62304 §5.3.1. The architecture view and the element tables that follow are generated from the model:
|
|
1407
|
-
|
|
1408
|
-
{{diagram:software-architecture}}
|
|
1409
|
-
|
|
1410
|
-
### 3.1 Software Items
|
|
1411
|
-
|
|
1412
|
-
\`\`\`memo-query
|
|
1413
|
-
kind: SoftwareItem
|
|
1414
|
-
display: table
|
|
1415
|
-
columns: name, layer, doc
|
|
1416
|
-
sort: name
|
|
1417
|
-
empty: "No SoftwareItem elements defined."
|
|
1418
|
-
\`\`\`
|
|
1419
|
-
|
|
1420
|
-
### 3.2 Software Units
|
|
1421
|
-
|
|
1422
|
-
\`\`\`memo-query
|
|
1423
|
-
kind: SoftwareUnit
|
|
1424
|
-
display: table
|
|
1425
|
-
columns: name, layer, doc
|
|
1426
|
-
sort: name
|
|
1427
|
-
empty: "No SoftwareUnit elements defined."
|
|
1428
|
-
\`\`\`
|
|
1429
|
-
|
|
1430
|
-
### 3.3 Interfaces
|
|
1431
|
-
|
|
1432
|
-
\`\`\`memo-query
|
|
1433
|
-
kind: Interface
|
|
1434
|
-
display: table
|
|
1435
|
-
columns: name, layer, doc
|
|
1436
|
-
sort: name
|
|
1437
|
-
empty: "No Interface elements defined."
|
|
1438
|
-
\`\`\`
|
|
1439
|
-
|
|
1440
|
-
---
|
|
1441
|
-
|
|
1442
|
-
## 4. SOUP Components
|
|
1443
|
-
|
|
1444
|
-
Software of Unknown Provenance (SOUP) used by **{{project.product}}** is listed below per IEC 62304 §5.3.3–5.3.4. For each SOUP item, functional/performance requirements and required hardware/software must be specified:
|
|
1445
|
-
|
|
1446
|
-
\`\`\`memo-query
|
|
1447
|
-
kind: SOUPComponent
|
|
1448
|
-
display: table
|
|
1449
|
-
columns: name, doc, layer
|
|
1450
|
-
sort: name
|
|
1451
|
-
empty: "No SOUP components identified."
|
|
1452
|
-
\`\`\`
|
|
1453
|
-
|
|
1454
|
-
---
|
|
1455
|
-
|
|
1456
|
-
## 5. Architecture Decisions
|
|
1457
|
-
|
|
1458
|
-
Record the significant architecture decisions, the alternatives considered, and the rationale — including decisions driven by risk control measures (ISO 14971) or cybersecurity considerations.
|
|
1459
|
-
|
|
1460
|
-
_[TODO: Document key architecture decisions and their rationale]_
|
|
1461
|
-
|
|
1462
|
-
---
|
|
1463
|
-
|
|
1464
|
-
## 6. Software Item Segregation
|
|
1465
|
-
|
|
1466
|
-
Describe the segregation between software items that is necessary for risk control per IEC 62304 §5.3.5, and the rationale for the integrity of each segregation boundary.
|
|
1467
|
-
|
|
1468
|
-
_[TODO: Describe how safety-critical software items are segregated from non-safety-critical items]_
|
|
1469
|
-
|
|
1470
|
-
---
|
|
1471
|
-
|
|
1472
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
1473
|
-
|
|
1474
|
-
{{include:shared/snippets/approval-block.md}}
|
|
1475
|
-
|
|
1476
|
-
{{include:shared/snippets/references-section.md}}
|
|
1477
|
-
`,Yi=`---
|
|
1478
|
-
id: sbom
|
|
1479
|
-
title: Software Bill of Materials (SBOM)
|
|
1480
|
-
standard: IEC 62304:2006+AMD1:2015
|
|
1481
|
-
clauses: ["8.1.2"]
|
|
1482
|
-
required_for: ["FDA_510k", "FDA_PMA", "CE"]
|
|
1483
|
-
---
|
|
1484
|
-
|
|
1485
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
1486
|
-
|
|
1487
|
-
{{toc}}
|
|
1488
|
-
|
|
1489
|
-
---
|
|
1490
|
-
|
|
1491
|
-
## 1. Purpose
|
|
1492
|
-
|
|
1493
|
-
This Software Bill of Materials (SBOM) provides a complete inventory of software components in **{{project.product}}**, including first-party code, SOUP, and open-source dependencies. Required for FDA cybersecurity submissions and EU MDR.
|
|
1494
|
-
|
|
1495
|
-
---
|
|
1496
|
-
|
|
1497
|
-
## 2. First-Party Software
|
|
1498
|
-
|
|
1499
|
-
Software developed in-house for this system is listed below from the model:
|
|
1500
|
-
|
|
1501
|
-
\`\`\`memo-query
|
|
1502
|
-
kind: [SoftwareSystem, SoftwareItem, SoftwareUnit]
|
|
1503
|
-
display: table
|
|
1504
|
-
columns: name, kind, layer, doc
|
|
1505
|
-
sort: name
|
|
1506
|
-
empty: "No first-party software items defined."
|
|
1507
|
-
\`\`\`
|
|
1508
|
-
|
|
1509
|
-
---
|
|
1510
|
-
|
|
1511
|
-
## 3. SOUP and Third-Party Components
|
|
1512
|
-
|
|
1513
|
-
All third-party and SOUP components with their versions and origins, generated from the model:
|
|
1514
|
-
|
|
1515
|
-
\`\`\`memo-query
|
|
1516
|
-
kind: SOUPComponent
|
|
1517
|
-
display: table
|
|
1518
|
-
columns: name, doc, layer
|
|
1519
|
-
sort: name
|
|
1520
|
-
empty: "No SOUP components defined."
|
|
1521
|
-
\`\`\`
|
|
1522
|
-
|
|
1523
|
-
---
|
|
1524
|
-
|
|
1525
|
-
## 4. Dependency Versions
|
|
1526
|
-
|
|
1527
|
-
Exact component versions currently recorded in the model — keep these synchronized with the build system:
|
|
1528
|
-
|
|
1529
|
-
_[TODO: Attach machine-readable SBOM (CycloneDX or SPDX format)]_
|
|
1530
|
-
|
|
1531
|
-
---
|
|
1532
|
-
|
|
1533
|
-
## 5. Vulnerability Assessment
|
|
1534
|
-
|
|
1535
|
-
Assessment of component vulnerabilities and their disposition:
|
|
1536
|
-
|
|
1537
|
-
_[TODO: Reference FDA cybersecurity submission or security assessment]_
|
|
1538
|
-
|
|
1539
|
-
---
|
|
1540
|
-
|
|
1541
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
1542
|
-
|
|
1543
|
-
{{include:shared/snippets/approval-block.md}}
|
|
1544
|
-
`,Ji=`---
|
|
1545
|
-
id: sdp
|
|
1546
|
-
title: Software Development Plan
|
|
1547
|
-
standard: IEC 62304:2006+AMD1:2015
|
|
1548
|
-
clauses: ["5.1"]
|
|
1549
|
-
required_for: ["CE", "FDA_510k", "MDR"]
|
|
1550
|
-
---
|
|
1551
|
-
|
|
1552
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
1553
|
-
|
|
1554
|
-
{{toc}}
|
|
1555
|
-
|
|
1556
|
-
---
|
|
1557
|
-
|
|
1558
|
-
## 1. Purpose and Scope
|
|
1559
|
-
|
|
1560
|
-
This Software Development Plan (SDP) defines the processes, activities, and tasks for the development of software for **{{project.product}}**. This plan is maintained per IEC 62304:2006 §5.1.
|
|
1561
|
-
|
|
1562
|
-
---
|
|
1563
|
-
|
|
1564
|
-
## 2. Software Classification
|
|
1565
|
-
|
|
1566
|
-
<!-- [GUIDANCE] Classify software per IEC 62304 §4.3: Class A (no injury), Class B (non-serious injury), Class C (death or serious injury). -->
|
|
1567
|
-
|
|
1568
|
-
| Software Item | Classification | Justification |
|
|
1569
|
-
| --- | --- | --- |
|
|
1570
|
-
| {{project.product}} Software System | Class B | |
|
|
1571
|
-
|
|
1572
|
-
\`\`\`memo-query
|
|
1573
|
-
kind: [SoftwareSystem, SoftwareItem]
|
|
1574
|
-
display: table
|
|
1575
|
-
columns: name, kind, layer, doc
|
|
1576
|
-
sort: name
|
|
1577
|
-
empty: "No software items defined. Add SoftwareSystem or SoftwareItem elements."
|
|
1578
|
-
\`\`\`
|
|
1579
|
-
|
|
1580
|
-
---
|
|
1581
|
-
|
|
1582
|
-
## 3. Development Standards and Procedures
|
|
1583
|
-
|
|
1584
|
-
Identify the coding standards, review procedures, and quality gates applied during development.
|
|
1585
|
-
|
|
1586
|
-
| Activity | Standard | Reference Procedure |
|
|
1587
|
-
| --- | --- | --- |
|
|
1588
|
-
| Requirements | IEC 62304 §5.2 | SRS |
|
|
1589
|
-
| Architecture | IEC 62304 §5.3 | SAD |
|
|
1590
|
-
| Detailed Design | IEC 62304 §5.4 | SDS |
|
|
1591
|
-
| Implementation | IEC 62304 §5.5 | Coding standard |
|
|
1592
|
-
| Integration | IEC 62304 §5.6 | Integration Test Plan |
|
|
1593
|
-
| System Testing | IEC 62304 §5.7 | System Test Plan |
|
|
1594
|
-
| Release | IEC 62304 §5.8 | Release procedure |
|
|
1595
|
-
|
|
1596
|
-
---
|
|
1597
|
-
|
|
1598
|
-
## 4. Software Safety Activities
|
|
1599
|
-
|
|
1600
|
-
### 4.1 Software Items of Unknown Provenance (SOUP)
|
|
1601
|
-
|
|
1602
|
-
\`\`\`memo-query
|
|
1603
|
-
kind: SOUPComponent
|
|
1604
|
-
display: table
|
|
1605
|
-
columns: name, doc, layer
|
|
1606
|
-
sort: name
|
|
1607
|
-
empty: "No SOUP components defined."
|
|
1608
|
-
\`\`\`
|
|
1609
|
-
|
|
1610
|
-
### 4.2 Software-Related Hazards
|
|
1611
|
-
|
|
1612
|
-
\`\`\`memo-query
|
|
1613
|
-
kind: Hazard
|
|
1614
|
-
where: layer == "software"
|
|
1615
|
-
display: table
|
|
1616
|
-
columns: name, doc, layer
|
|
1617
|
-
sort: name
|
|
1618
|
-
empty: "No software-related hazards defined."
|
|
1619
|
-
\`\`\`
|
|
1620
|
-
|
|
1621
|
-
---
|
|
1622
|
-
|
|
1623
|
-
## 5. Configuration Management
|
|
1624
|
-
|
|
1625
|
-
Describe how configuration items are identified, versioned, and controlled per IEC 62304 §8.
|
|
1626
|
-
|
|
1627
|
-
_[TODO: Describe version control, branching strategy, and release process]_
|
|
1628
|
-
|
|
1629
|
-
---
|
|
1630
|
-
|
|
1631
|
-
## 6. Problem Resolution
|
|
1632
|
-
|
|
1633
|
-
Describe the problem resolution process per IEC 62304 §9, including how problems are reported, investigated, and tracked to closure.
|
|
1634
|
-
|
|
1635
|
-
_[TODO: Describe defect tracking and resolution process]_
|
|
1636
|
-
|
|
1637
|
-
---
|
|
1638
|
-
|
|
1639
|
-
## 7. Development Environment
|
|
1640
|
-
|
|
1641
|
-
Describe the toolchain, languages, build system, and environments used for development.
|
|
1642
|
-
|
|
1643
|
-
_[TODO: List development tools, compilers, IDEs, and their versions]_
|
|
1644
|
-
|
|
1645
|
-
---
|
|
1646
|
-
|
|
1647
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
1648
|
-
|
|
1649
|
-
{{include:shared/snippets/approval-block.md}}
|
|
1650
|
-
|
|
1651
|
-
{{include:shared/snippets/references-section.md}}
|
|
1652
|
-
`,Qi=`---
|
|
1653
|
-
id: soup
|
|
1654
|
-
title: SOUP List (Software of Unknown Provenance)
|
|
1655
|
-
standard: IEC 62304:2006+AMD1:2015
|
|
1656
|
-
clauses: ["8.1.2"]
|
|
1657
|
-
required_for: ["CE", "FDA_510k", "MDR"]
|
|
1658
|
-
---
|
|
1659
|
-
|
|
1660
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
1661
|
-
|
|
1662
|
-
{{toc}}
|
|
1663
|
-
|
|
1664
|
-
---
|
|
1665
|
-
|
|
1666
|
-
## 1. Purpose
|
|
1667
|
-
|
|
1668
|
-
This document lists all Software of Unknown Provenance (SOUP) components used in **{{project.product}}** per IEC 62304:2006 §8.1.2. SOUP includes off-the-shelf software, open-source libraries, and third-party components that were not developed under a quality management system.
|
|
1669
|
-
|
|
1670
|
-
---
|
|
1671
|
-
|
|
1672
|
-
## 2. SOUP Inventory
|
|
1673
|
-
|
|
1674
|
-
The complete inventory of SOUP and third-party components in **{{project.product}}**, generated from the model:
|
|
1675
|
-
|
|
1676
|
-
\`\`\`memo-query
|
|
1677
|
-
kind: SOUPComponent
|
|
1678
|
-
display: table
|
|
1679
|
-
columns: name, layer, doc
|
|
1680
|
-
sort: name
|
|
1681
|
-
empty: "No SOUP components defined. Add SOUPComponent elements to the model."
|
|
1682
|
-
\`\`\`
|
|
1683
|
-
|
|
1684
|
-
---
|
|
1685
|
-
|
|
1686
|
-
## 3. SOUP Risk Assessment
|
|
1687
|
-
|
|
1688
|
-
For each SOUP component, the potential impact on device safety must be evaluated.
|
|
1689
|
-
|
|
1690
|
-
\`\`\`memo-query
|
|
1691
|
-
kind: SOUPComponent
|
|
1692
|
-
display: table
|
|
1693
|
-
columns: name, doc
|
|
1694
|
-
sort: name
|
|
1695
|
-
empty: "No SOUP components to evaluate."
|
|
1696
|
-
\`\`\`
|
|
1697
|
-
|
|
1698
|
-
### 3.1 Known Anomalies
|
|
1699
|
-
|
|
1700
|
-
_[TODO: For each SOUP component, list known anomalies and assess impact on safety]_
|
|
1701
|
-
|
|
1702
|
-
---
|
|
1703
|
-
|
|
1704
|
-
## 4. SOUP Maintenance
|
|
1705
|
-
|
|
1706
|
-
### 4.1 Update Monitoring
|
|
1707
|
-
|
|
1708
|
-
_[TODO: Describe the process for monitoring SOUP components for security patches and updates]_
|
|
1709
|
-
|
|
1710
|
-
### 4.2 Version Pinning
|
|
1711
|
-
|
|
1712
|
-
_[TODO: Describe how SOUP versions are pinned in configuration management]_
|
|
1713
|
-
|
|
1714
|
-
---
|
|
1715
|
-
|
|
1716
|
-
## 5. SBOM Integration
|
|
1717
|
-
|
|
1718
|
-
Describe how this document relates to the machine-readable SBOM (e.g. SPDX/CycloneDX) produced by the build pipeline.
|
|
1719
|
-
|
|
1720
|
-
_[TODO: Reference Software Bill of Materials (SBOM) for FDA cybersecurity requirements]_
|
|
1721
|
-
|
|
1722
|
-
---
|
|
1723
|
-
|
|
1724
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
1725
|
-
|
|
1726
|
-
{{include:shared/snippets/approval-block.md}}
|
|
1727
|
-
|
|
1728
|
-
{{include:shared/snippets/references-section.md}}
|
|
1729
|
-
`,Xi=`---
|
|
1730
|
-
id: srs
|
|
1731
|
-
title: Software Requirements Specification
|
|
1732
|
-
standard: IEC 62304:2006+AMD1:2015
|
|
1733
|
-
clauses: ["5.2"]
|
|
1734
|
-
required_for: ["CE", "FDA_510k", "MDR"]
|
|
1735
|
-
---
|
|
1736
|
-
|
|
1737
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
1738
|
-
|
|
1739
|
-
{{toc}}
|
|
1740
|
-
|
|
1741
|
-
---
|
|
1742
|
-
|
|
1743
|
-
## 1. Purpose
|
|
1744
|
-
|
|
1745
|
-
This Software Requirements Specification (SRS) defines the software requirements for **{{project.product}}** in accordance with IEC 62304:2006 §5.2.
|
|
1746
|
-
|
|
1747
|
-
---
|
|
1748
|
-
|
|
1749
|
-
## 2. Requirements Summary
|
|
1750
|
-
|
|
1751
|
-
Summary metrics for the requirements captured in the model:
|
|
1752
|
-
|
|
1753
|
-
\`\`\`memo-query
|
|
1754
|
-
kind: Requirement
|
|
1755
|
-
display: count
|
|
1756
|
-
label: Total software requirements
|
|
1757
|
-
\`\`\`
|
|
1758
|
-
|
|
1759
|
-
\`\`\`memo-query
|
|
1760
|
-
kind: Requirement
|
|
1761
|
-
display: count
|
|
1762
|
-
label: System requirements
|
|
1763
|
-
\`\`\`
|
|
1764
|
-
|
|
1765
|
-
---
|
|
1766
|
-
|
|
1767
|
-
## 3. Functional Requirements
|
|
1768
|
-
|
|
1769
|
-
Functional requirements are listed below from the model:
|
|
1770
|
-
|
|
1771
|
-
\`\`\`memo-query
|
|
1772
|
-
kind: Requirement
|
|
1773
|
-
where: doc contains "shall"
|
|
1774
|
-
display: table
|
|
1775
|
-
columns: name, layer, doc
|
|
1776
|
-
sort: name
|
|
1777
|
-
empty: "No functional software requirements defined."
|
|
1778
|
-
\`\`\`
|
|
1779
|
-
|
|
1780
|
-
### All Software Requirements
|
|
1781
|
-
|
|
1782
|
-
\`\`\`memo-query
|
|
1783
|
-
kind: Requirement
|
|
1784
|
-
display: table
|
|
1785
|
-
columns: name, kind, layer, doc
|
|
1786
|
-
sort: name
|
|
1787
|
-
empty: "No software requirements defined. Add Requirement elements to model/requirements/*.sysml."
|
|
1788
|
-
\`\`\`
|
|
1789
|
-
|
|
1790
|
-
---
|
|
1791
|
-
|
|
1792
|
-
## 4. System Requirements (Allocated to Software)
|
|
1793
|
-
|
|
1794
|
-
System requirements allocated to software per IEC 62304 §5.2, drawn from the model:
|
|
1795
|
-
|
|
1796
|
-
\`\`\`memo-query
|
|
1797
|
-
kind: Requirement
|
|
1798
|
-
display: table
|
|
1799
|
-
columns: name, layer, doc
|
|
1800
|
-
sort: name
|
|
1801
|
-
empty: "No system requirements defined."
|
|
1802
|
-
\`\`\`
|
|
1803
|
-
|
|
1804
|
-
---
|
|
1805
|
-
|
|
1806
|
-
## 5. Non-Functional Requirements
|
|
1807
|
-
|
|
1808
|
-
### 5.1 Performance Requirements
|
|
1809
|
-
|
|
1810
|
-
_[TODO: Define performance requirements (response time, throughput, memory)]_
|
|
1811
|
-
|
|
1812
|
-
### 5.2 Safety Requirements
|
|
1813
|
-
|
|
1814
|
-
\`\`\`memo-query
|
|
1815
|
-
kind: Hazard
|
|
1816
|
-
where: layer == "software"
|
|
1817
|
-
display: table
|
|
1818
|
-
columns: name, doc
|
|
1819
|
-
sort: name
|
|
1820
|
-
empty: "No software safety requirements derived from hazard analysis."
|
|
1821
|
-
\`\`\`
|
|
1822
|
-
|
|
1823
|
-
### 5.3 Security Requirements
|
|
1824
|
-
|
|
1825
|
-
\`\`\`memo-query
|
|
1826
|
-
kind: [SecurityControl, ThreatModel]
|
|
1827
|
-
display: table
|
|
1828
|
-
columns: name, layer, doc
|
|
1829
|
-
empty: "No security requirements defined."
|
|
1830
|
-
\`\`\`
|
|
1831
|
-
|
|
1832
|
-
---
|
|
1833
|
-
|
|
1834
|
-
## 6. SOUP Requirements
|
|
1835
|
-
|
|
1836
|
-
This section is generated from the system model. The table below lists the **SOUP Requirements** elements currently defined:
|
|
1837
|
-
|
|
1838
|
-
\`\`\`memo-query
|
|
1839
|
-
kind: SOUPComponent
|
|
1840
|
-
display: table
|
|
1841
|
-
columns: name, doc
|
|
1842
|
-
sort: name
|
|
1843
|
-
empty: "No SOUP components identified."
|
|
1844
|
-
\`\`\`
|
|
1845
|
-
|
|
1846
|
-
---
|
|
1847
|
-
|
|
1848
|
-
## 7. Requirements Traceability
|
|
1849
|
-
|
|
1850
|
-
This section is generated from the system model. The table below lists the **Requirements Traceability** elements currently defined:
|
|
1851
|
-
|
|
1852
|
-
\`\`\`memo-query
|
|
1853
|
-
kind: Requirement
|
|
1854
|
-
display: table
|
|
1855
|
-
columns: name, layer
|
|
1856
|
-
sort: name
|
|
1857
|
-
empty: "No software requirements to trace."
|
|
1858
|
-
\`\`\`
|
|
1859
|
-
|
|
1860
|
-
---
|
|
1861
|
-
|
|
1862
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
1863
|
-
|
|
1864
|
-
{{include:shared/snippets/approval-block.md}}
|
|
1865
|
-
|
|
1866
|
-
{{include:shared/snippets/references-section.md}}
|
|
1867
|
-
`,Zi=`---
|
|
1868
|
-
id: sw-traceability
|
|
1869
|
-
title: Software Traceability Matrix
|
|
1870
|
-
standard: IEC 62304:2006+AMD1:2015
|
|
1871
|
-
clauses: ["5.1.1", "5.7.5"]
|
|
1872
|
-
required_for: ["CE", "FDA_510k", "MDR"]
|
|
1873
|
-
---
|
|
1874
|
-
|
|
1875
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
1876
|
-
|
|
1877
|
-
{{toc}}
|
|
1878
|
-
|
|
1879
|
-
---
|
|
1880
|
-
|
|
1881
|
-
## 1. Purpose
|
|
1882
|
-
|
|
1883
|
-
This Software Traceability Matrix demonstrates bidirectional traceability from system requirements through software requirements, design, implementation, and test for **{{project.product}}**.
|
|
1884
|
-
|
|
1885
|
-
---
|
|
1886
|
-
|
|
1887
|
-
## 2. Traceability Summary
|
|
1888
|
-
|
|
1889
|
-
The following metric is computed live from the model:
|
|
1890
|
-
|
|
1891
|
-
\`\`\`memo-query
|
|
1892
|
-
kind: Requirement
|
|
1893
|
-
display: count
|
|
1894
|
-
label: System requirements
|
|
1895
|
-
\`\`\`
|
|
1896
|
-
|
|
1897
|
-
\`\`\`memo-query
|
|
1898
|
-
kind: Requirement
|
|
1899
|
-
display: count
|
|
1900
|
-
label: Software requirements
|
|
1901
|
-
\`\`\`
|
|
1902
|
-
|
|
1903
|
-
\`\`\`memo-query
|
|
1904
|
-
kind: TestCase
|
|
1905
|
-
display: count
|
|
1906
|
-
label: Test cases
|
|
1907
|
-
\`\`\`
|
|
1908
|
-
|
|
1909
|
-
---
|
|
1910
|
-
|
|
1911
|
-
## 3. System → Software Requirements
|
|
1912
|
-
|
|
1913
|
-
This section is generated from the system model. The table below lists the **System → Software Requirements** elements currently defined:
|
|
1914
|
-
|
|
1915
|
-
\`\`\`memo-query
|
|
1916
|
-
kind: Requirement
|
|
1917
|
-
display: table
|
|
1918
|
-
columns: name, layer, doc
|
|
1919
|
-
sort: name
|
|
1920
|
-
empty: "No system requirements defined."
|
|
1921
|
-
\`\`\`
|
|
1922
|
-
|
|
1923
|
-
---
|
|
1924
|
-
|
|
1925
|
-
## 4. Software Requirements
|
|
1926
|
-
|
|
1927
|
-
This section is generated from the system model. The table below lists the **Software Requirements** elements currently defined:
|
|
1928
|
-
|
|
1929
|
-
\`\`\`memo-query
|
|
1930
|
-
kind: Requirement
|
|
1931
|
-
display: table
|
|
1932
|
-
columns: name, layer, doc
|
|
1933
|
-
sort: name
|
|
1934
|
-
empty: "No software requirements defined."
|
|
1935
|
-
\`\`\`
|
|
1936
|
-
|
|
1937
|
-
---
|
|
1938
|
-
|
|
1939
|
-
## 5. Software Requirements → Design Elements
|
|
1940
|
-
|
|
1941
|
-
This section is generated from the system model. The table below lists the **Software Requirements → Design Elements** elements currently defined:
|
|
1942
|
-
|
|
1943
|
-
\`\`\`memo-query
|
|
1944
|
-
kind: [SoftwareItem, SoftwareUnit]
|
|
1945
|
-
display: table
|
|
1946
|
-
columns: name, kind, layer, doc
|
|
1947
|
-
sort: name
|
|
1948
|
-
empty: "No software design elements defined."
|
|
1949
|
-
\`\`\`
|
|
1950
|
-
|
|
1951
|
-
---
|
|
1952
|
-
|
|
1953
|
-
## 6. Test Cases
|
|
1954
|
-
|
|
1955
|
-
This section is generated from the system model. The table below lists the **Test Cases** elements currently defined:
|
|
1956
|
-
|
|
1957
|
-
\`\`\`memo-query
|
|
1958
|
-
kind: TestCase
|
|
1959
|
-
display: table
|
|
1960
|
-
columns: name, layer, doc
|
|
1961
|
-
sort: name
|
|
1962
|
-
empty: "No test cases defined. Add TestCase elements."
|
|
1963
|
-
\`\`\`
|
|
1964
|
-
|
|
1965
|
-
---
|
|
1966
|
-
|
|
1967
|
-
## 7. Untraced Requirements
|
|
1968
|
-
|
|
1969
|
-
Complete this section for **{{project.product}}** using the guidance below.
|
|
1970
|
-
|
|
1971
|
-
_[TODO: List any software requirements without corresponding test cases]_
|
|
1972
|
-
|
|
1973
|
-
---
|
|
1974
|
-
|
|
1975
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
1976
|
-
|
|
1977
|
-
{{include:shared/snippets/approval-block.md}}
|
|
1978
|
-
`,ea=`---
|
|
1979
|
-
id: system-test
|
|
1980
|
-
title: Software System Test Plan
|
|
1981
|
-
standard: IEC 62304:2006+AMD1:2015
|
|
1982
|
-
clauses: ["5.7"]
|
|
1983
|
-
required_for: ["CE", "FDA_510k", "MDR"]
|
|
1984
|
-
---
|
|
1985
|
-
|
|
1986
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
1987
|
-
|
|
1988
|
-
{{toc}}
|
|
1989
|
-
|
|
1990
|
-
---
|
|
1991
|
-
|
|
1992
|
-
## 1. Purpose
|
|
1993
|
-
|
|
1994
|
-
This System Test Plan defines the approach for system-level testing of **{{project.product}}** per IEC 62304:2006 §5.7.
|
|
1995
|
-
|
|
1996
|
-
---
|
|
1997
|
-
|
|
1998
|
-
## 2. System Requirements Under Test
|
|
1999
|
-
|
|
2000
|
-
This section is generated from the system model. The table below lists the **System Requirements Under Test** elements currently defined:
|
|
2001
|
-
|
|
2002
|
-
\`\`\`memo-query
|
|
2003
|
-
kind: Requirement
|
|
2004
|
-
display: table
|
|
2005
|
-
columns: name, layer, doc
|
|
2006
|
-
sort: name
|
|
2007
|
-
empty: "No system requirements defined."
|
|
2008
|
-
\`\`\`
|
|
2009
|
-
|
|
2010
|
-
---
|
|
2011
|
-
|
|
2012
|
-
## 3. System Test Cases
|
|
2013
|
-
|
|
2014
|
-
This section is generated from the system model. The table below lists the **System Test Cases** elements currently defined:
|
|
2015
|
-
|
|
2016
|
-
\`\`\`memo-query
|
|
2017
|
-
kind: [TestCase, ValidationActivity]
|
|
2018
|
-
display: table
|
|
2019
|
-
columns: name, kind, layer, doc
|
|
2020
|
-
sort: name
|
|
2021
|
-
empty: "No system test cases defined."
|
|
2022
|
-
\`\`\`
|
|
2023
|
-
|
|
2024
|
-
---
|
|
2025
|
-
|
|
2026
|
-
## 4. Test Environment
|
|
2027
|
-
|
|
2028
|
-
Describe the hardware, software, tools, and configuration of the test environment in sufficient detail to reproduce the test setup.
|
|
2029
|
-
|
|
2030
|
-
_[TODO: Describe the test environment, tools, and hardware configuration]_
|
|
2031
|
-
|
|
2032
|
-
---
|
|
2033
|
-
|
|
2034
|
-
## 5. Anomaly Reporting
|
|
2035
|
-
|
|
2036
|
-
Complete this section for **{{project.product}}** using the guidance below.
|
|
2037
|
-
|
|
2038
|
-
_[TODO: Describe how test failures and anomalies are documented and tracked]_
|
|
2039
|
-
|
|
2040
|
-
---
|
|
2041
|
-
|
|
2042
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
2043
|
-
|
|
2044
|
-
{{include:shared/snippets/approval-block.md}}
|
|
2045
|
-
`,ta=`---
|
|
2046
|
-
id: formative-eval
|
|
2047
|
-
title: Formative Usability Evaluation Report
|
|
2048
|
-
standard: IEC 62366-1:2015+AMD1:2020
|
|
2049
|
-
clauses: ["5.7"]
|
|
2050
|
-
required_for: ["CE", "MDR"]
|
|
2051
|
-
---
|
|
2052
|
-
|
|
2053
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
2054
|
-
|
|
2055
|
-
---
|
|
2056
|
-
|
|
2057
|
-
## 1. Purpose
|
|
2058
|
-
|
|
2059
|
-
Documents formative (iterative) usability evaluation activities for **{{project.product}}** during design development.
|
|
2060
|
-
|
|
2061
|
-
---
|
|
2062
|
-
|
|
2063
|
-
## 2. Evaluation Methods Used
|
|
2064
|
-
|
|
2065
|
-
Complete this section for **{{project.product}}** using the guidance below.
|
|
2066
|
-
|
|
2067
|
-
_[TODO: Describe methods used — expert review, cognitive walkthrough, prototype testing, etc.]_
|
|
2068
|
-
|
|
2069
|
-
---
|
|
2070
|
-
|
|
2071
|
-
## 3. Issues Identified and Resolved
|
|
2072
|
-
|
|
2073
|
-
Complete the table below for **{{project.product}}**:
|
|
2074
|
-
|
|
2075
|
-
| Issue | Severity | Resolution | Status |
|
|
2076
|
-
| --- | --- | --- | --- |
|
|
2077
|
-
| | | | |
|
|
2078
|
-
|
|
2079
|
-
---
|
|
2080
|
-
|
|
2081
|
-
## 4. Design Changes Made
|
|
2082
|
-
|
|
2083
|
-
Complete this section for **{{project.product}}** using the guidance below.
|
|
2084
|
-
|
|
2085
|
-
_[TODO: Summarize user interface design changes made as a result of formative evaluations]_
|
|
2086
|
-
|
|
2087
|
-
---
|
|
2088
|
-
|
|
2089
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
2090
|
-
|
|
2091
|
-
{{include:shared/snippets/approval-block.md}}
|
|
2092
|
-
`,na=`---
|
|
2093
|
-
id: summative-eval
|
|
2094
|
-
title: Summative Usability Evaluation Report
|
|
2095
|
-
standard: IEC 62366-1:2015+AMD1:2020
|
|
2096
|
-
clauses: ["5.9"]
|
|
2097
|
-
required_for: ["CE", "FDA_510k", "MDR"]
|
|
2098
|
-
---
|
|
2099
|
-
|
|
2100
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
2101
|
-
|
|
2102
|
-
{{toc}}
|
|
2103
|
-
|
|
2104
|
-
---
|
|
2105
|
-
|
|
2106
|
-
## 1. Purpose
|
|
2107
|
-
|
|
2108
|
-
This report documents the results of summative (validation) usability testing for **{{project.product}}** per IEC 62366-1:2015 §5.9.
|
|
2109
|
-
|
|
2110
|
-
---
|
|
2111
|
-
|
|
2112
|
-
## 2. Test Participants
|
|
2113
|
-
|
|
2114
|
-
Complete this section for **{{project.product}}** using the guidance below.
|
|
2115
|
-
|
|
2116
|
-
_[TODO: Describe participant demographics, number, and selection criteria]_
|
|
2117
|
-
|
|
2118
|
-
---
|
|
2119
|
-
|
|
2120
|
-
## 3. Test Scenarios
|
|
2121
|
-
|
|
2122
|
-
This section is generated from the system model. The table below lists the **Test Scenarios** elements currently defined:
|
|
2123
|
-
|
|
2124
|
-
\`\`\`memo-query
|
|
2125
|
-
kind: [UseCase, ValidationActivity]
|
|
2126
|
-
display: table
|
|
2127
|
-
columns: name, layer, doc
|
|
2128
|
-
sort: name
|
|
2129
|
-
empty: "No validation scenarios defined."
|
|
2130
|
-
\`\`\`
|
|
2131
|
-
|
|
2132
|
-
---
|
|
2133
|
-
|
|
2134
|
-
## 4. Results
|
|
2135
|
-
|
|
2136
|
-
### 4.1 Task Completion Rates
|
|
2137
|
-
|
|
2138
|
-
_[TODO: Report task completion rates and time-on-task for each critical task]_
|
|
2139
|
-
|
|
2140
|
-
### 4.2 Use Errors Observed
|
|
2141
|
-
|
|
2142
|
-
_[TODO: List all use errors observed during testing]_
|
|
2143
|
-
|
|
2144
|
-
### 4.3 Pass/Fail Assessment
|
|
2145
|
-
|
|
2146
|
-
_[TODO: State whether each test scenario passed or failed per pre-defined criteria]_
|
|
2147
|
-
|
|
2148
|
-
---
|
|
2149
|
-
|
|
2150
|
-
## 5. Conclusions
|
|
2151
|
-
|
|
2152
|
-
Complete this section for **{{project.product}}** using the guidance below.
|
|
2153
|
-
|
|
2154
|
-
_[TODO: State whether the device passed summative usability evaluation]_
|
|
2155
|
-
|
|
2156
|
-
---
|
|
2157
|
-
|
|
2158
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
2159
|
-
|
|
2160
|
-
{{include:shared/snippets/approval-block.md}}
|
|
2161
|
-
`,ra=`---
|
|
2162
|
-
id: task-analysis
|
|
2163
|
-
title: Task Analysis
|
|
2164
|
-
standard: IEC 62366-1:2015+AMD1:2020
|
|
2165
|
-
clauses: ["5.4"]
|
|
2166
|
-
required_for: ["CE", "MDR"]
|
|
2167
|
-
---
|
|
2168
|
-
|
|
2169
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
2170
|
-
|
|
2171
|
-
{{toc}}
|
|
2172
|
-
|
|
2173
|
-
---
|
|
2174
|
-
|
|
2175
|
-
## 1. Purpose
|
|
2176
|
-
|
|
2177
|
-
Documents task analysis for **{{project.product}}** per IEC 62366-1:2015 §5.4, identifying tasks that could cause hazardous situations if performed incorrectly.
|
|
2178
|
-
|
|
2179
|
-
---
|
|
2180
|
-
|
|
2181
|
-
## 2. User Tasks
|
|
2182
|
-
|
|
2183
|
-
This section is generated from the system model. The table below lists the **User Tasks** elements currently defined:
|
|
2184
|
-
|
|
2185
|
-
\`\`\`memo-query
|
|
2186
|
-
kind: UserActivity
|
|
2187
|
-
display: table
|
|
2188
|
-
columns: name, layer, doc
|
|
2189
|
-
sort: name
|
|
2190
|
-
empty: "No UserActivity elements defined."
|
|
2191
|
-
\`\`\`
|
|
2192
|
-
|
|
2193
|
-
---
|
|
2194
|
-
|
|
2195
|
-
## 3. Critical Tasks
|
|
2196
|
-
|
|
2197
|
-
Complete this section for **{{project.product}}** using the guidance below.
|
|
2198
|
-
|
|
2199
|
-
_[TODO: Identify which tasks are critical (could lead to hazardous situation if performed incorrectly)]_
|
|
2200
|
-
|
|
2201
|
-
| Task | Critical | Hazardous Situation if Error | Mitigation |
|
|
2202
|
-
| --- | --- | --- | --- |
|
|
2203
|
-
| | | | |
|
|
2204
|
-
|
|
2205
|
-
---
|
|
2206
|
-
|
|
2207
|
-
## 4. Task Flow Analysis
|
|
2208
|
-
|
|
2209
|
-
The diagram below is rendered from the corresponding model view and reflects the current state of the model:
|
|
2210
|
-
|
|
2211
|
-
{{diagram:task-flow}}
|
|
2212
|
-
|
|
2213
|
-
_[TODO: Document sequential and parallel task flows with decision points]_
|
|
2214
|
-
|
|
2215
|
-
---
|
|
2216
|
-
|
|
2217
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
2218
|
-
`,oa=`---
|
|
2219
|
-
id: ue-plan
|
|
2220
|
-
title: Usability Engineering Plan
|
|
2221
|
-
standard: IEC 62366-1:2015+AMD1:2020
|
|
2222
|
-
clauses: ["4"]
|
|
2223
|
-
required_for: ["CE", "FDA_510k", "MDR"]
|
|
2224
|
-
---
|
|
2225
|
-
|
|
2226
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
2227
|
-
|
|
2228
|
-
{{toc}}
|
|
2229
|
-
|
|
2230
|
-
---
|
|
2231
|
-
|
|
2232
|
-
## 1. Purpose
|
|
2233
|
-
|
|
2234
|
-
This Usability Engineering Plan (UE Plan) defines the usability engineering activities for **{{project.product}}** per IEC 62366-1:2015.
|
|
2235
|
-
|
|
2236
|
-
---
|
|
2237
|
-
|
|
2238
|
-
## 2. Intended Users
|
|
2239
|
-
|
|
2240
|
-
Identify every intended user group of **{{project.product}}**, including their roles, training assumptions, and use environments.
|
|
2241
|
-
|
|
2242
|
-
_[TODO: Define all intended user groups (clinicians, patients, technicians, lay users)]_
|
|
2243
|
-
|
|
2244
|
-
---
|
|
2245
|
-
|
|
2246
|
-
## 3. Intended Use Environment
|
|
2247
|
-
|
|
2248
|
-
Complete this section for **{{project.product}}** using the guidance below.
|
|
2249
|
-
|
|
2250
|
-
_[TODO: Describe all use environments: clinical, home, ambulatory, etc.]_
|
|
2251
|
-
|
|
2252
|
-
---
|
|
2253
|
-
|
|
2254
|
-
## 4. Use-Related Hazards
|
|
2255
|
-
|
|
2256
|
-
This section is generated from the system model. The table below lists the **Use-Related Hazards** elements currently defined:
|
|
2257
|
-
|
|
2258
|
-
\`\`\`memo-query
|
|
2259
|
-
kind: [UseCase, UserActivity]
|
|
2260
|
-
display: table
|
|
2261
|
-
columns: name, layer, doc
|
|
2262
|
-
sort: name
|
|
2263
|
-
empty: "No use cases or user activities defined."
|
|
2264
|
-
\`\`\`
|
|
2265
|
-
|
|
2266
|
-
---
|
|
2267
|
-
|
|
2268
|
-
## 5. Usability Testing Plan
|
|
2269
|
-
|
|
2270
|
-
### 5.1 Formative Evaluation
|
|
2271
|
-
|
|
2272
|
-
_[TODO: Describe formative evaluation approach: cognitive walkthrough, expert review, prototype testing]_
|
|
2273
|
-
|
|
2274
|
-
### 5.2 Summative Evaluation
|
|
2275
|
-
|
|
2276
|
-
_[TODO: Describe summative usability testing: participants, scenarios, pass/fail criteria]_
|
|
2277
|
-
|
|
2278
|
-
---
|
|
2279
|
-
|
|
2280
|
-
## 6. User Interface Elements
|
|
2281
|
-
|
|
2282
|
-
This section is generated from the system model. The table below lists the **User Interface Elements** elements currently defined:
|
|
2283
|
-
|
|
2284
|
-
\`\`\`memo-query
|
|
2285
|
-
kind: UserInterface
|
|
2286
|
-
display: table
|
|
2287
|
-
columns: name, layer, doc
|
|
2288
|
-
sort: name
|
|
2289
|
-
empty: "No UserInterface elements defined."
|
|
2290
|
-
\`\`\`
|
|
2291
|
-
|
|
2292
|
-
---
|
|
2293
|
-
|
|
2294
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
2295
|
-
|
|
2296
|
-
{{include:shared/snippets/approval-block.md}}
|
|
2297
|
-
|
|
2298
|
-
{{include:shared/snippets/references-section.md}}
|
|
2299
|
-
`,sa=`---
|
|
2300
|
-
id: ui-spec
|
|
2301
|
-
title: User Interface Specification
|
|
2302
|
-
standard: IEC 62366-1:2015+AMD1:2020
|
|
2303
|
-
clauses: ["5.6"]
|
|
2304
|
-
required_for: ["CE", "MDR"]
|
|
2305
|
-
---
|
|
2306
|
-
|
|
2307
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
2308
|
-
|
|
2309
|
-
{{toc}}
|
|
2310
|
-
|
|
2311
|
-
---
|
|
2312
|
-
|
|
2313
|
-
## 1. Purpose
|
|
2314
|
-
|
|
2315
|
-
Specifies the user interface design for **{{project.product}}** per IEC 62366-1:2015 §5.6.
|
|
2316
|
-
|
|
2317
|
-
---
|
|
2318
|
-
|
|
2319
|
-
## 2. User Interface Elements
|
|
2320
|
-
|
|
2321
|
-
This section is generated from the system model. The table below lists the **User Interface Elements** elements currently defined:
|
|
2322
|
-
|
|
2323
|
-
\`\`\`memo-query
|
|
2324
|
-
kind: UserInterface
|
|
2325
|
-
display: table
|
|
2326
|
-
columns: name, layer, doc
|
|
2327
|
-
sort: name
|
|
2328
|
-
empty: "No UserInterface elements defined."
|
|
2329
|
-
\`\`\`
|
|
2330
|
-
|
|
2331
|
-
---
|
|
2332
|
-
|
|
2333
|
-
## 3. Screen/Mode Specifications
|
|
2334
|
-
|
|
2335
|
-
Complete this section for **{{project.product}}** using the guidance below.
|
|
2336
|
-
|
|
2337
|
-
_[TODO: Document each screen, mode, and key interaction with screenshots or wireframes]_
|
|
2338
|
-
|
|
2339
|
-
---
|
|
2340
|
-
|
|
2341
|
-
## 4. Alerts and Alarms
|
|
2342
|
-
|
|
2343
|
-
Complete this section for **{{project.product}}** using the guidance below.
|
|
2344
|
-
|
|
2345
|
-
_[TODO: Document all alarms, alerts, and status indicators with their visual/auditory characteristics]_
|
|
2346
|
-
|
|
2347
|
-
---
|
|
2348
|
-
|
|
2349
|
-
## 5. Labeling on Device
|
|
2350
|
-
|
|
2351
|
-
Complete this section for **{{project.product}}** using the guidance below.
|
|
2352
|
-
|
|
2353
|
-
_[TODO: Document all labels, symbols, and icons used on the physical device]_
|
|
2354
|
-
|
|
2355
|
-
---
|
|
2356
|
-
|
|
2357
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
2358
|
-
|
|
2359
|
-
{{include:shared/snippets/approval-block.md}}
|
|
2360
|
-
`,ia=`---
|
|
2361
|
-
id: urra
|
|
2362
|
-
title: Use-Related Risk Analysis
|
|
2363
|
-
standard: IEC 62366-1:2015+AMD1:2020
|
|
2364
|
-
clauses: ["5"]
|
|
2365
|
-
required_for: ["CE", "FDA_510k", "MDR"]
|
|
2366
|
-
---
|
|
2367
|
-
|
|
2368
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
2369
|
-
|
|
2370
|
-
{{toc}}
|
|
2371
|
-
|
|
2372
|
-
---
|
|
2373
|
-
|
|
2374
|
-
## 1. Purpose
|
|
2375
|
-
|
|
2376
|
-
This Use-Related Risk Analysis (URRA) identifies use errors and use-related hazardous situations for **{{project.product}}** per IEC 62366-1:2015 §5.
|
|
2377
|
-
|
|
2378
|
-
---
|
|
2379
|
-
|
|
2380
|
-
## 2. Use Scenarios
|
|
2381
|
-
|
|
2382
|
-
This section is generated from the system model. The table below lists the **Use Scenarios** elements currently defined:
|
|
2383
|
-
|
|
2384
|
-
\`\`\`memo-query
|
|
2385
|
-
kind: [UseCase, UserActivity]
|
|
2386
|
-
display: table
|
|
2387
|
-
columns: name, layer, doc
|
|
2388
|
-
sort: name
|
|
2389
|
-
empty: "No use scenarios defined. Add UseCase or UserActivity elements."
|
|
2390
|
-
\`\`\`
|
|
2391
|
-
|
|
2392
|
-
---
|
|
2393
|
-
|
|
2394
|
-
## 3. Use Errors and Abnormal Use
|
|
2395
|
-
|
|
2396
|
-
This section is generated from the system model. The table below lists the **Use Errors and Abnormal Use** elements currently defined:
|
|
2397
|
-
|
|
2398
|
-
\`\`\`memo-query
|
|
2399
|
-
kind: [Hazard, HazardousSituation]
|
|
2400
|
-
where: layer == "ui"
|
|
2401
|
-
display: table
|
|
2402
|
-
columns: name, doc, layer
|
|
2403
|
-
sort: name
|
|
2404
|
-
empty: "No use-related hazards defined."
|
|
2405
|
-
\`\`\`
|
|
2406
|
-
|
|
2407
|
-
---
|
|
2408
|
-
|
|
2409
|
-
## 4. Critical Tasks
|
|
2410
|
-
|
|
2411
|
-
Complete this section for **{{project.product}}** using the guidance below.
|
|
2412
|
-
|
|
2413
|
-
_[TODO: Identify the critical tasks whose failure could cause a hazardous situation]_
|
|
2414
|
-
|
|
2415
|
-
---
|
|
2416
|
-
|
|
2417
|
-
## 5. Mitigation Measures
|
|
2418
|
-
|
|
2419
|
-
This section is generated from the system model. The table below lists the **Mitigation Measures** elements currently defined:
|
|
2420
|
-
|
|
2421
|
-
\`\`\`memo-query
|
|
2422
|
-
kind: [RiskControlMeasure, UsabilityRequirement]
|
|
2423
|
-
display: table
|
|
2424
|
-
columns: name, layer, doc
|
|
2425
|
-
sort: name
|
|
2426
|
-
empty: "No usability-related risk controls defined."
|
|
2427
|
-
\`\`\`
|
|
2428
|
-
|
|
2429
|
-
---
|
|
2430
|
-
|
|
2431
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
2432
|
-
|
|
2433
|
-
{{include:shared/snippets/approval-block.md}}
|
|
2434
|
-
`,aa=`---
|
|
2435
|
-
id: use-spec
|
|
2436
|
-
title: Intended Use and Indications for Use Specification
|
|
2437
|
-
standard: IEC 62366-1:2015+AMD1:2020
|
|
2438
|
-
clauses: ["5.1"]
|
|
2439
|
-
required_for: ["CE", "FDA_510k", "MDR"]
|
|
2440
|
-
---
|
|
2441
|
-
|
|
2442
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
2443
|
-
|
|
2444
|
-
---
|
|
2445
|
-
|
|
2446
|
-
## 1. Intended Use
|
|
2447
|
-
|
|
2448
|
-
Complete this section for **{{project.product}}** using the guidance below.
|
|
2449
|
-
|
|
2450
|
-
_[TODO: Provide the FDA-required Indications for Use statement and intended use statement]_
|
|
2451
|
-
|
|
2452
|
-
---
|
|
2453
|
-
|
|
2454
|
-
## 2. Intended User Profile
|
|
2455
|
-
|
|
2456
|
-
Complete this section for **{{project.product}}** using the guidance below.
|
|
2457
|
-
|
|
2458
|
-
_[TODO: Describe user knowledge, training level, and physical/cognitive capabilities]_
|
|
2459
|
-
|
|
2460
|
-
---
|
|
2461
|
-
|
|
2462
|
-
## 3. Use Environment
|
|
2463
|
-
|
|
2464
|
-
Complete this section for **{{project.product}}** using the guidance below.
|
|
2465
|
-
|
|
2466
|
-
_[TODO: Describe physical, social, technical environments where the device will be used]_
|
|
2467
|
-
|
|
2468
|
-
---
|
|
2469
|
-
|
|
2470
|
-
## 4. Use Cases
|
|
2471
|
-
|
|
2472
|
-
Use cases describing how intended users interact with **{{project.product}}**, drawn from the model:
|
|
2473
|
-
|
|
2474
|
-
\`\`\`memo-query
|
|
2475
|
-
kind: UseCase
|
|
2476
|
-
display: table
|
|
2477
|
-
columns: name, layer, doc
|
|
2478
|
-
sort: name
|
|
2479
|
-
empty: "No UseCase elements defined."
|
|
2480
|
-
\`\`\`
|
|
2481
|
-
|
|
2482
|
-
---
|
|
2483
|
-
|
|
2484
|
-
## 5. Known Use-Related Constraints
|
|
2485
|
-
|
|
2486
|
-
Complete this section for **{{project.product}}** using the guidance below.
|
|
2487
|
-
|
|
2488
|
-
_[TODO: Describe contraindications, limitations, and warnings that constrain use]_
|
|
2489
|
-
|
|
2490
|
-
---
|
|
2491
|
-
|
|
2492
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
2493
|
-
|
|
2494
|
-
{{include:shared/snippets/approval-block.md}}
|
|
2495
|
-
`,la=`---
|
|
2496
|
-
id: fmea
|
|
2497
|
-
title: Failure Mode and Effects Analysis
|
|
2498
|
-
standard: IEC 60812:2018
|
|
2499
|
-
clauses: ["5", "6", "7"]
|
|
2500
|
-
required_for: ["CE", "FDA_510k", "FDA_PMA"]
|
|
2501
|
-
---
|
|
2502
|
-
|
|
2503
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
2504
|
-
|
|
2505
|
-
{{toc}}
|
|
2506
|
-
|
|
2507
|
-
---
|
|
2508
|
-
|
|
2509
|
-
## 1. Purpose and Scope
|
|
2510
|
-
|
|
2511
|
-
This FMEA documents failure modes for **{{project.product}}** components, their effects, severity, and mitigations. Combines hardware, software, and system-level failure analysis.
|
|
2512
|
-
|
|
2513
|
-
---
|
|
2514
|
-
|
|
2515
|
-
## 2. Component Inventory
|
|
2516
|
-
|
|
2517
|
-
This section is generated from the system model. The table below lists the **Component Inventory** elements currently defined:
|
|
2518
|
-
|
|
2519
|
-
\`\`\`memo-query
|
|
2520
|
-
kind: [Component, Subsystem, SoftwareItem]
|
|
2521
|
-
display: table
|
|
2522
|
-
columns: name, kind, layer, doc
|
|
2523
|
-
sort: name
|
|
2524
|
-
empty: "No components defined. Add Component, Subsystem, or SoftwareItem elements."
|
|
2525
|
-
\`\`\`
|
|
2526
|
-
|
|
2527
|
-
---
|
|
2528
|
-
|
|
2529
|
-
## 3. FMEA Worksheet
|
|
2530
|
-
|
|
2531
|
-
### 3.1 Hardware Failures
|
|
2532
|
-
|
|
2533
|
-
\`\`\`memo-query
|
|
2534
|
-
kind: Component
|
|
2535
|
-
display: table
|
|
2536
|
-
columns: name, layer, doc
|
|
2537
|
-
sort: name
|
|
2538
|
-
empty: "No hardware components defined."
|
|
2539
|
-
\`\`\`
|
|
2540
|
-
|
|
2541
|
-
### 3.2 Software Failures
|
|
2542
|
-
|
|
2543
|
-
\`\`\`memo-query
|
|
2544
|
-
kind: [SoftwareItem, SoftwareUnit]
|
|
2545
|
-
display: table
|
|
2546
|
-
columns: name, kind, layer, doc
|
|
2547
|
-
sort: name
|
|
2548
|
-
empty: "No software items defined."
|
|
2549
|
-
\`\`\`
|
|
2550
|
-
|
|
2551
|
-
### 3.3 Interface Failures
|
|
2552
|
-
|
|
2553
|
-
\`\`\`memo-query
|
|
2554
|
-
kind: Interface
|
|
2555
|
-
display: table
|
|
2556
|
-
columns: name, layer, doc
|
|
2557
|
-
sort: name
|
|
2558
|
-
empty: "No interfaces defined."
|
|
2559
|
-
\`\`\`
|
|
2560
|
-
|
|
2561
|
-
---
|
|
2562
|
-
|
|
2563
|
-
## 4. Risk Controls for FMEA Items
|
|
2564
|
-
|
|
2565
|
-
This section is generated from the system model. The table below lists the **Risk Controls for FMEA Items** elements currently defined:
|
|
2566
|
-
|
|
2567
|
-
\`\`\`memo-query
|
|
2568
|
-
kind: RiskControlMeasure
|
|
2569
|
-
display: table
|
|
2570
|
-
columns: name, layer, doc
|
|
2571
|
-
sort: name
|
|
2572
|
-
empty: "No risk controls defined."
|
|
2573
|
-
\`\`\`
|
|
2574
|
-
|
|
2575
|
-
---
|
|
2576
|
-
|
|
2577
|
-
## 5. Unmitigated Failures
|
|
2578
|
-
|
|
2579
|
-
Complete this section for **{{project.product}}** using the guidance below.
|
|
2580
|
-
|
|
2581
|
-
_[TODO: List any failure modes without risk controls and justify residual risk]_
|
|
2582
|
-
|
|
2583
|
-
---
|
|
2584
|
-
|
|
2585
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
2586
|
-
|
|
2587
|
-
{{include:shared/snippets/approval-block.md}}
|
|
2588
|
-
`,ca=`---
|
|
2589
|
-
id: fta
|
|
2590
|
-
title: Fault Tree Analysis
|
|
2591
|
-
standard: ISO 14971:2019
|
|
2592
|
-
clauses: ["5", "6"]
|
|
2593
|
-
required_for: ["CE"]
|
|
2594
|
-
---
|
|
2595
|
-
|
|
2596
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
2597
|
-
|
|
2598
|
-
{{toc}}
|
|
2599
|
-
|
|
2600
|
-
---
|
|
2601
|
-
|
|
2602
|
-
## 1. Purpose
|
|
2603
|
-
|
|
2604
|
-
This Fault Tree Analysis (FTA) complements the FMEA by providing a top-down analysis of failure modes that could lead to identified harms for **{{project.product}}**.
|
|
2605
|
-
|
|
2606
|
-
---
|
|
2607
|
-
|
|
2608
|
-
## 2. Top Events (Harms)
|
|
2609
|
-
|
|
2610
|
-
This section is generated from the system model. The table below lists the **Top Events (Harms)** elements currently defined:
|
|
2611
|
-
|
|
2612
|
-
\`\`\`memo-query
|
|
2613
|
-
kind: Harm
|
|
2614
|
-
display: table
|
|
2615
|
-
columns: name, doc, layer
|
|
2616
|
-
sort: name
|
|
2617
|
-
empty: "No harm elements defined. Add Harm elements to the model."
|
|
2618
|
-
\`\`\`
|
|
2619
|
-
|
|
2620
|
-
---
|
|
2621
|
-
|
|
2622
|
-
## 3. Contributing Failure Modes
|
|
2623
|
-
|
|
2624
|
-
This section is generated from the system model. The table below lists the **Contributing Failure Modes** elements currently defined:
|
|
2625
|
-
|
|
2626
|
-
\`\`\`memo-query
|
|
2627
|
-
kind: [Hazard, HazardousSituation]
|
|
2628
|
-
display: grouped
|
|
2629
|
-
group_by: layer
|
|
2630
|
-
columns: name, kind, doc
|
|
2631
|
-
sort: name
|
|
2632
|
-
empty: "No hazards or hazardous situations defined."
|
|
2633
|
-
\`\`\`
|
|
2634
|
-
|
|
2635
|
-
---
|
|
2636
|
-
|
|
2637
|
-
## 4. Fault Tree Diagrams
|
|
2638
|
-
|
|
2639
|
-
The diagram below is rendered from the corresponding model view and reflects the current state of the model:
|
|
2640
|
-
|
|
2641
|
-
{{diagram:fta-diagram}}
|
|
2642
|
-
|
|
2643
|
-
_[TODO: Attach or reference FTA diagram files]_
|
|
2644
|
-
|
|
2645
|
-
---
|
|
2646
|
-
|
|
2647
|
-
## 5. Cut Sets and Recommendations
|
|
2648
|
-
|
|
2649
|
-
Complete this section for **{{project.product}}** using the guidance below.
|
|
2650
|
-
|
|
2651
|
-
_[TODO: List minimal cut sets and associated risk reduction recommendations]_
|
|
2652
|
-
|
|
2653
|
-
---
|
|
2654
|
-
|
|
2655
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
2656
|
-
|
|
2657
|
-
{{include:shared/snippets/approval-block.md}}
|
|
2658
|
-
`,da=`---
|
|
2659
|
-
id: har
|
|
2660
|
-
title: Hazard Analysis Report
|
|
2661
|
-
standard: ISO 14971:2019
|
|
2662
|
-
clauses: ["5", "6", "7"]
|
|
2663
|
-
required_for: ["CE", "FDA_510k", "FDA_PMA", "MDR"]
|
|
2664
|
-
---
|
|
2665
|
-
|
|
2666
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
2667
|
-
|
|
2668
|
-
{{toc}}
|
|
2669
|
-
|
|
2670
|
-
---
|
|
2671
|
-
|
|
2672
|
-
## 1. Purpose
|
|
2673
|
-
|
|
2674
|
-
This Hazard Analysis Report documents the systematic identification of hazards, hazardous situations, and harms associated with **{{project.product}}**, along with the associated risk estimation and risk control measures.
|
|
2675
|
-
|
|
2676
|
-
---
|
|
2677
|
-
|
|
2678
|
-
## 2. Hazard Summary
|
|
2679
|
-
|
|
2680
|
-
The following metric is computed live from the model:
|
|
2681
|
-
|
|
2682
|
-
\`\`\`memo-query
|
|
2683
|
-
kind: Hazard
|
|
2684
|
-
display: count
|
|
2685
|
-
label: Total hazards identified
|
|
2686
|
-
\`\`\`
|
|
2687
|
-
|
|
2688
|
-
\`\`\`memo-query
|
|
2689
|
-
kind: HazardousSituation
|
|
2690
|
-
display: count
|
|
2691
|
-
label: Hazardous situations
|
|
2692
|
-
\`\`\`
|
|
2693
|
-
|
|
2694
|
-
\`\`\`memo-query
|
|
2695
|
-
kind: RiskControlMeasure
|
|
2696
|
-
display: count
|
|
2697
|
-
label: Risk control measures
|
|
2698
|
-
\`\`\`
|
|
2699
|
-
|
|
2700
|
-
---
|
|
2701
|
-
|
|
2702
|
-
## 3. Hazard Identification
|
|
2703
|
-
|
|
2704
|
-
All foreseeable hazards arising from the device, its intended use, and reasonably foreseeable misuse are listed below.
|
|
2705
|
-
|
|
2706
|
-
### 3.1 Energy Hazards
|
|
2707
|
-
|
|
2708
|
-
\`\`\`memo-query
|
|
2709
|
-
kind: Hazard
|
|
2710
|
-
where: doc contains "energy"
|
|
2711
|
-
display: table
|
|
2712
|
-
columns: name, doc, layer
|
|
2713
|
-
sort: name
|
|
2714
|
-
empty: "No energy hazards identified."
|
|
2715
|
-
\`\`\`
|
|
2716
|
-
|
|
2717
|
-
### 3.2 Biological and Chemical Hazards
|
|
2718
|
-
|
|
2719
|
-
\`\`\`memo-query
|
|
2720
|
-
kind: Hazard
|
|
2721
|
-
where: doc contains "biolog"
|
|
2722
|
-
display: table
|
|
2723
|
-
columns: name, doc, layer
|
|
2724
|
-
empty: "No biological/chemical hazards identified."
|
|
2725
|
-
\`\`\`
|
|
2726
|
-
|
|
2727
|
-
### 3.3 Operational Hazards
|
|
2728
|
-
|
|
2729
|
-
\`\`\`memo-query
|
|
2730
|
-
kind: Hazard
|
|
2731
|
-
display: grouped
|
|
2732
|
-
group_by: layer
|
|
2733
|
-
columns: name, doc
|
|
2734
|
-
sort: name
|
|
2735
|
-
empty: "No hazards defined. Add Hazard elements to model/risk/*.sysml."
|
|
2736
|
-
\`\`\`
|
|
2737
|
-
|
|
2738
|
-
---
|
|
2739
|
-
|
|
2740
|
-
## 4. Hazardous Situations
|
|
2741
|
-
|
|
2742
|
-
This section is generated from the system model. The table below lists the **Hazardous Situations** elements currently defined:
|
|
2743
|
-
|
|
2744
|
-
\`\`\`memo-query
|
|
2745
|
-
kind: HazardousSituation
|
|
2746
|
-
display: table
|
|
2747
|
-
columns: name, doc, layer
|
|
2748
|
-
sort: name
|
|
2749
|
-
empty: "No hazardous situations defined. Add HazardousSituation elements."
|
|
2750
|
-
\`\`\`
|
|
2751
|
-
|
|
2752
|
-
---
|
|
2753
|
-
|
|
2754
|
-
## 5. Risk Estimation
|
|
2755
|
-
|
|
2756
|
-
<!-- [GUIDANCE] For each hazardous situation, estimate probability of occurrence and severity of harm per ISO 14971:2019 §5. -->
|
|
2757
|
-
|
|
2758
|
-
\`\`\`memo-query
|
|
2759
|
-
kind: Harm
|
|
2760
|
-
display: table
|
|
2761
|
-
columns: name, doc, layer
|
|
2762
|
-
sort: name
|
|
2763
|
-
empty: "No harm elements defined. Add Harm elements linked to HazardousSituation."
|
|
2764
|
-
\`\`\`
|
|
2765
|
-
|
|
2766
|
-
---
|
|
2767
|
-
|
|
2768
|
-
## 6. Risk Control Measures
|
|
2769
|
-
|
|
2770
|
-
### 6.1 Inherent Safety by Design
|
|
2771
|
-
|
|
2772
|
-
\`\`\`memo-query
|
|
2773
|
-
kind: RiskControlMeasure
|
|
2774
|
-
where: doc contains "design"
|
|
2775
|
-
display: table
|
|
2776
|
-
columns: name, doc, layer
|
|
2777
|
-
empty: "No inherent safety controls."
|
|
2778
|
-
\`\`\`
|
|
2779
|
-
|
|
2780
|
-
### 6.2 Protective Measures
|
|
2781
|
-
|
|
2782
|
-
\`\`\`memo-query
|
|
2783
|
-
kind: RiskControlMeasure
|
|
2784
|
-
display: table
|
|
2785
|
-
columns: name, doc, layer
|
|
2786
|
-
sort: name
|
|
2787
|
-
empty: "No risk controls defined. Add RiskControlMeasure elements."
|
|
2788
|
-
\`\`\`
|
|
2789
|
-
|
|
2790
|
-
### 6.3 Information for Safety
|
|
2791
|
-
|
|
2792
|
-
_[TODO: List all warnings, cautions, and contraindications in labeling]_
|
|
2793
|
-
|
|
2794
|
-
---
|
|
2795
|
-
|
|
2796
|
-
## 7. Residual Risk Evaluation
|
|
2797
|
-
|
|
2798
|
-
This section is generated from the system model. The table below lists the **Residual Risk Evaluation** elements currently defined:
|
|
2799
|
-
|
|
2800
|
-
\`\`\`memo-query
|
|
2801
|
-
kind: Hazard
|
|
2802
|
-
display: table
|
|
2803
|
-
columns: name, layer, doc
|
|
2804
|
-
sort: name
|
|
2805
|
-
empty: "All hazards have been evaluated."
|
|
2806
|
-
\`\`\`
|
|
2807
|
-
|
|
2808
|
-
---
|
|
2809
|
-
|
|
2810
|
-
## 8. Benefit-Risk Analysis
|
|
2811
|
-
|
|
2812
|
-
<!-- [GUIDANCE] Per ISO 14971:2019 §8, if residual risks remain after all control measures, the overall residual risk must be judged acceptable relative to medical benefits. -->
|
|
2813
|
-
|
|
2814
|
-
_[TODO: Document benefit-risk justification if any residual risks remain]_
|
|
2815
|
-
|
|
2816
|
-
---
|
|
2817
|
-
|
|
2818
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
2819
|
-
|
|
2820
|
-
{{include:shared/snippets/approval-block.md}}
|
|
2821
|
-
|
|
2822
|
-
{{include:shared/snippets/references-section.md}}
|
|
2823
|
-
`,ua=`---
|
|
2824
|
-
id: risk-benefit
|
|
2825
|
-
title: Risk-Benefit Analysis
|
|
2826
|
-
standard: ISO 14971:2019
|
|
2827
|
-
clauses: ["8"]
|
|
2828
|
-
required_for: ["CE", "MDR"]
|
|
2829
|
-
---
|
|
2830
|
-
|
|
2831
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
2832
|
-
|
|
2833
|
-
---
|
|
2834
|
-
|
|
2835
|
-
## 1. Purpose
|
|
2836
|
-
|
|
2837
|
-
This document provides the benefit-risk analysis for **{{project.product}}** as required by ISO 14971:2019 §8. It is prepared when residual risks cannot be further reduced and a judgment of acceptability must be made.
|
|
2838
|
-
|
|
2839
|
-
---
|
|
2840
|
-
|
|
2841
|
-
## 2. Medical Benefits
|
|
2842
|
-
|
|
2843
|
-
Complete this section for **{{project.product}}** using the guidance below.
|
|
2844
|
-
|
|
2845
|
-
_[TODO: Describe the medical benefits of the device for its intended patient population]_
|
|
2846
|
-
|
|
2847
|
-
---
|
|
2848
|
-
|
|
2849
|
-
## 3. Residual Risks Summary
|
|
2850
|
-
|
|
2851
|
-
This section is generated from the system model. The table below lists the **Residual Risks Summary** elements currently defined:
|
|
2852
|
-
|
|
2853
|
-
\`\`\`memo-query
|
|
2854
|
-
kind: Hazard
|
|
2855
|
-
display: table
|
|
2856
|
-
columns: name, doc, layer
|
|
2857
|
-
sort: name
|
|
2858
|
-
empty: "No residual risks identified — standard risk controls are sufficient."
|
|
2859
|
-
\`\`\`
|
|
2860
|
-
|
|
2861
|
-
---
|
|
2862
|
-
|
|
2863
|
-
## 4. Benefit-Risk Conclusion
|
|
2864
|
-
|
|
2865
|
-
Complete this section for **{{project.product}}** using the guidance below.
|
|
2866
|
-
|
|
2867
|
-
_[TODO: State the conclusion: the medical benefits of the intended use outweigh the residual risks]_
|
|
2868
|
-
|
|
2869
|
-
---
|
|
2870
|
-
|
|
2871
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
2872
|
-
|
|
2873
|
-
{{include:shared/snippets/approval-block.md}}
|
|
2874
|
-
`,pa=`---
|
|
2875
|
-
id: risk-matrix
|
|
2876
|
-
title: Risk Matrix
|
|
2877
|
-
standard: ISO 14971:2019
|
|
2878
|
-
clauses: ["5", "6"]
|
|
2879
|
-
required_for: ["CE", "MDR"]
|
|
2880
|
-
---
|
|
2881
|
-
|
|
2882
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
2883
|
-
|
|
2884
|
-
---
|
|
2885
|
-
|
|
2886
|
-
## Risk Matrix
|
|
2887
|
-
|
|
2888
|
-
This matrix shows the distribution of identified hazards across severity and probability levels.
|
|
2889
|
-
|
|
2890
|
-
\`\`\`memo-query
|
|
2891
|
-
kind: Hazard
|
|
2892
|
-
display: matrix
|
|
2893
|
-
row_kind: kind
|
|
2894
|
-
col_kind: layer
|
|
2895
|
-
empty: "No hazards defined."
|
|
2896
|
-
\`\`\`
|
|
2897
|
-
|
|
2898
|
-
### Hazard Coverage by Layer
|
|
2899
|
-
|
|
2900
|
-
\`\`\`memo-query
|
|
2901
|
-
kind: [Hazard, HazardousSituation, Harm]
|
|
2902
|
-
display: grouped
|
|
2903
|
-
group_by: layer
|
|
2904
|
-
columns: name, kind, doc
|
|
2905
|
-
empty: "No risk elements defined."
|
|
2906
|
-
\`\`\`
|
|
2907
|
-
|
|
2908
|
-
---
|
|
2909
|
-
|
|
2910
|
-
## Risk Control Coverage
|
|
2911
|
-
|
|
2912
|
-
This section is generated from the system model. The table below lists the **Risk Control Coverage** elements currently defined:
|
|
2913
|
-
|
|
2914
|
-
\`\`\`memo-query
|
|
2915
|
-
kind: RiskControlMeasure
|
|
2916
|
-
display: table
|
|
2917
|
-
columns: name, layer, doc
|
|
2918
|
-
sort: name
|
|
2919
|
-
empty: "No risk controls defined."
|
|
2920
|
-
\`\`\`
|
|
2921
|
-
|
|
2922
|
-
---
|
|
2923
|
-
|
|
2924
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
2925
|
-
`,ma=`---
|
|
2926
|
-
id: rmp
|
|
2927
|
-
title: Risk Management Plan
|
|
2928
|
-
standard: ISO 14971:2019
|
|
2929
|
-
clauses: ["4.4"]
|
|
2930
|
-
required_for: ["CE", "FDA_510k", "FDA_PMA", "MDR"]
|
|
2931
|
-
---
|
|
2932
|
-
|
|
2933
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
2934
|
-
|
|
2935
|
-
{{toc}}
|
|
2936
|
-
|
|
2937
|
-
---
|
|
2938
|
-
|
|
2939
|
-
## 1. Purpose and Scope
|
|
2940
|
-
|
|
2941
|
-
This Risk Management Plan (RMP) defines the risk management activities for **{{project.product}}** developed by **{{project.company}}**. This plan is maintained throughout the product lifecycle in accordance with ISO 14971:2019.
|
|
2942
|
-
|
|
2943
|
-
### 1.1 Intended Use
|
|
2944
|
-
|
|
2945
|
-
<!-- [GUIDANCE] Describe the intended use of the device, intended users, and intended use environment. -->
|
|
2946
|
-
|
|
2947
|
-
_[TODO: Describe intended use, intended users, and intended use environment]_
|
|
2948
|
-
|
|
2949
|
-
### 1.2 Scope of Risk Management
|
|
2950
|
-
|
|
2951
|
-
This plan applies to all phases of the product lifecycle: design, development, manufacture, post-market surveillance, and eventual decommission.
|
|
2952
|
-
|
|
2953
|
-
---
|
|
2954
|
-
|
|
2955
|
-
## 2. Regulatory Context
|
|
2956
|
-
|
|
2957
|
-
Complete the table below for **{{project.product}}**:
|
|
2958
|
-
|
|
2959
|
-
| Requirement | Reference |
|
|
2960
|
-
| --- | --- |
|
|
2961
|
-
| Risk Management Process | ISO 14971:2019 §4.1 |
|
|
2962
|
-
| Risk Management Plan | ISO 14971:2019 §4.4 |
|
|
2963
|
-
| Risk Estimation | ISO 14971:2019 §5 |
|
|
2964
|
-
| Risk Evaluation | ISO 14971:2019 §6 |
|
|
2965
|
-
| Risk Control | ISO 14971:2019 §7 |
|
|
2966
|
-
| Overall Residual Risk | ISO 14971:2019 §8 |
|
|
2967
|
-
| Risk Management Review | ISO 14971:2019 §9 |
|
|
2968
|
-
| Post-production | ISO 14971:2019 §10 |
|
|
2969
|
-
|
|
2970
|
-
---
|
|
2971
|
-
|
|
2972
|
-
## 3. Risk Management Team
|
|
2973
|
-
|
|
2974
|
-
<!-- [GUIDANCE] List all personnel involved in risk management activities. -->
|
|
2975
|
-
|
|
2976
|
-
| Role | Name | Responsibilities |
|
|
2977
|
-
| --- | --- | --- |
|
|
2978
|
-
| Risk Management Lead | | Overall RM coordination |
|
|
2979
|
-
| Clinical Representative | | Clinical risk input |
|
|
2980
|
-
| Software Engineer | | Software FMEA and SOUP risk |
|
|
2981
|
-
| Regulatory Affairs | | Standards compliance |
|
|
2982
|
-
| Quality Engineer | | Process compliance |
|
|
2983
|
-
|
|
2984
|
-
---
|
|
2985
|
-
|
|
2986
|
-
## 4. Risk Acceptability Criteria
|
|
2987
|
-
|
|
2988
|
-
### 4.1 Severity Levels
|
|
2989
|
-
|
|
2990
|
-
\`\`\`memo-query
|
|
2991
|
-
kind: RiskAcceptabilityCriteria
|
|
2992
|
-
display: table
|
|
2993
|
-
columns: name, doc, layer
|
|
2994
|
-
empty: "No risk acceptability criteria defined. Add RiskAcceptabilityCriteria elements to the model."
|
|
2995
|
-
\`\`\`
|
|
2996
|
-
|
|
2997
|
-
### 4.2 Risk Policy
|
|
2998
|
-
|
|
2999
|
-
<!-- [GUIDANCE] Define the risk policy: ALARP, broadly acceptable, or unacceptable regions. -->
|
|
3000
|
-
|
|
3001
|
-
_[TODO: Define risk acceptability matrix — probability vs. severity]_
|
|
3002
|
-
|
|
3003
|
-
Residual risk is acceptable when:
|
|
3004
|
-
- All individual risks are reduced to ALARP or broadly acceptable level
|
|
3005
|
-
- Overall residual risk is acceptable per §8 of ISO 14971:2019
|
|
3006
|
-
- Unmitigated hazards:
|
|
3007
|
-
|
|
3008
|
-
\`\`\`memo-query
|
|
3009
|
-
kind: Hazard
|
|
3010
|
-
where: layer == "risk"
|
|
3011
|
-
display: count
|
|
3012
|
-
label: Total hazards in model
|
|
3013
|
-
\`\`\`
|
|
3014
|
-
|
|
3015
|
-
---
|
|
3016
|
-
|
|
3017
|
-
## 5. Risk Management Activities
|
|
3018
|
-
|
|
3019
|
-
### 5.1 Hazard Identification
|
|
3020
|
-
|
|
3021
|
-
All hazard identification activities are documented in the Hazard Analysis Report (HAR).
|
|
3022
|
-
|
|
3023
|
-
\`\`\`memo-query
|
|
3024
|
-
kind: Hazard
|
|
3025
|
-
display: table
|
|
3026
|
-
columns: name, layer, doc
|
|
3027
|
-
sort: name
|
|
3028
|
-
empty: "No hazards defined. Add Hazard elements to model/risk/*.sysml."
|
|
3029
|
-
\`\`\`
|
|
3030
|
-
|
|
3031
|
-
### 5.2 Risk Estimation and Evaluation
|
|
3032
|
-
|
|
3033
|
-
Risk estimation is performed for each hazardous situation per ISO 14971:2019 §5–6.
|
|
3034
|
-
|
|
3035
|
-
\`\`\`memo-query
|
|
3036
|
-
kind: HazardousSituation
|
|
3037
|
-
display: table
|
|
3038
|
-
columns: name, layer, doc
|
|
3039
|
-
sort: name
|
|
3040
|
-
empty: "No hazardous situations defined."
|
|
3041
|
-
\`\`\`
|
|
3042
|
-
|
|
3043
|
-
### 5.3 Risk Control Measures
|
|
3044
|
-
|
|
3045
|
-
\`\`\`memo-query
|
|
3046
|
-
kind: RiskControlMeasure
|
|
3047
|
-
display: table
|
|
3048
|
-
columns: name, layer, doc
|
|
3049
|
-
sort: name
|
|
3050
|
-
empty: "No risk controls defined."
|
|
3051
|
-
\`\`\`
|
|
3052
|
-
|
|
3053
|
-
### 5.4 Residual Risk Evaluation
|
|
3054
|
-
|
|
3055
|
-
Unmitigated hazards (hazards without associated risk controls):
|
|
3056
|
-
|
|
3057
|
-
\`\`\`memo-query
|
|
3058
|
-
kind: Hazard
|
|
3059
|
-
display: table
|
|
3060
|
-
columns: name, doc
|
|
3061
|
-
empty: "All hazards have associated risk controls."
|
|
3062
|
-
\`\`\`
|
|
3063
|
-
|
|
3064
|
-
---
|
|
3065
|
-
|
|
3066
|
-
## 6. Risk Management Documentation
|
|
3067
|
-
|
|
3068
|
-
Complete the table below for **{{project.product}}**:
|
|
3069
|
-
|
|
3070
|
-
| Document | Purpose | Reference |
|
|
3071
|
-
| --- | --- | --- |
|
|
3072
|
-
| Hazard Analysis Report (HAR) | Hazard identification and estimation | HAR |
|
|
3073
|
-
| FMEA | Failure mode analysis | FMEA |
|
|
3074
|
-
| Risk Benefit Analysis | Benefit-risk justification | N/A |
|
|
3075
|
-
| Risk Management Report | Overall residual risk summary | N/A |
|
|
3076
|
-
|
|
3077
|
-
---
|
|
3078
|
-
|
|
3079
|
-
## 7. Plan Maintenance
|
|
3080
|
-
|
|
3081
|
-
This plan shall be reviewed:
|
|
3082
|
-
- At each major design change
|
|
3083
|
-
- Following post-market surveillance findings
|
|
3084
|
-
- Prior to each design review gate
|
|
3085
|
-
- At least annually during active development
|
|
3086
|
-
|
|
3087
|
-
---
|
|
3088
|
-
|
|
3089
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
3090
|
-
|
|
3091
|
-
{{include:shared/snippets/approval-block.md}}
|
|
3092
|
-
|
|
3093
|
-
{{include:shared/snippets/references-section.md}}
|
|
3094
|
-
`,fa=`---
|
|
3095
|
-
id: rmr
|
|
3096
|
-
title: Risk Management Report
|
|
3097
|
-
standard: ISO 14971:2019
|
|
3098
|
-
clauses: ["9"]
|
|
3099
|
-
required_for: ["CE", "FDA_510k", "FDA_PMA", "MDR"]
|
|
3100
|
-
---
|
|
3101
|
-
|
|
3102
|
-
{{include:shared/snippets/document-control-header.md}}
|
|
3103
|
-
|
|
3104
|
-
{{toc}}
|
|
3105
|
-
|
|
3106
|
-
---
|
|
3107
|
-
|
|
3108
|
-
## 1. Purpose
|
|
3109
|
-
|
|
3110
|
-
This Risk Management Report (RMR) summarizes the results of all risk management activities performed for **{{project.product}}** in accordance with ISO 14971:2019 §9.
|
|
3111
|
-
|
|
3112
|
-
---
|
|
3113
|
-
|
|
3114
|
-
## 2. Summary Statistics
|
|
3115
|
-
|
|
3116
|
-
The following metric is computed live from the model:
|
|
3117
|
-
|
|
3118
|
-
\`\`\`memo-query
|
|
3119
|
-
kind: Hazard
|
|
3120
|
-
display: count
|
|
3121
|
-
label: Total hazards identified
|
|
3122
|
-
\`\`\`
|
|
3123
|
-
|
|
3124
|
-
\`\`\`memo-query
|
|
3125
|
-
kind: RiskControlMeasure
|
|
3126
|
-
display: count
|
|
3127
|
-
label: Risk controls implemented
|
|
3128
|
-
\`\`\`
|
|
3129
|
-
|
|
3130
|
-
\`\`\`memo-query
|
|
3131
|
-
kind: HazardousSituation
|
|
3132
|
-
display: count
|
|
3133
|
-
label: Hazardous situations analyzed
|
|
3134
|
-
\`\`\`
|
|
3135
|
-
|
|
3136
|
-
---
|
|
3137
|
-
|
|
3138
|
-
## 3. Risk Management Plan Compliance
|
|
3139
|
-
|
|
3140
|
-
<!-- [GUIDANCE] Confirm that the risk management plan was executed as documented. -->
|
|
3141
|
-
|
|
3142
|
-
_[TODO: Confirm that all activities in the Risk Management Plan were completed]_
|
|
3143
|
-
|
|
3144
|
-
| Activity | Status | Reference |
|
|
3145
|
-
| --- | --- | --- |
|
|
3146
|
-
| Hazard identification | | HAR |
|
|
3147
|
-
| Risk estimation | | HAR |
|
|
3148
|
-
| Risk evaluation | | HAR |
|
|
3149
|
-
| Risk control implementation | | Design records |
|
|
3150
|
-
| Residual risk evaluation | | HAR |
|
|
3151
|
-
| Overall residual risk | | This document |
|
|
3152
|
-
| Post-production monitoring | | Post-Market Surveillance Plan |
|
|
3153
|
-
|
|
3154
|
-
---
|
|
3155
|
-
|
|
3156
|
-
## 4. Overall Residual Risk Evaluation
|
|
3157
|
-
|
|
3158
|
-
### 4.1 Remaining Hazards
|
|
3159
|
-
|
|
3160
|
-
\`\`\`memo-query
|
|
3161
|
-
kind: Hazard
|
|
3162
|
-
display: table
|
|
3163
|
-
columns: name, layer, doc
|
|
3164
|
-
sort: name
|
|
3165
|
-
empty: "All identified hazards have been evaluated."
|
|
3166
|
-
\`\`\`
|
|
3167
|
-
|
|
3168
|
-
### 4.2 Overall Residual Risk Conclusion
|
|
3169
|
-
|
|
3170
|
-
<!-- [GUIDANCE] Conclude whether the overall residual risk is acceptable relative to the medical benefits of the device. -->
|
|
3171
|
-
|
|
3172
|
-
_[TODO: State the overall residual risk conclusion with justification]_
|
|
3173
|
-
|
|
3174
|
-
---
|
|
3175
|
-
|
|
3176
|
-
## 5. Benefit-Risk Statement
|
|
3177
|
-
|
|
3178
|
-
Complete this section for **{{project.product}}** using the guidance below.
|
|
3179
|
-
|
|
3180
|
-
_[TODO: State clearly that the benefits of the device outweigh the residual risks for the intended use]_
|
|
3181
|
-
|
|
3182
|
-
---
|
|
3183
|
-
|
|
3184
|
-
## 6. Post-Production Information Collection
|
|
3185
|
-
|
|
3186
|
-
Post-production information collection activities are documented in the Post-Market Surveillance Plan.
|
|
3187
|
-
|
|
3188
|
-
---
|
|
3189
|
-
|
|
3190
|
-
{{include:shared/snippets/revision-history-table.md}}
|
|
3191
|
-
|
|
3192
|
-
{{include:shared/snippets/approval-block.md}}
|
|
3193
|
-
|
|
3194
|
-
{{include:shared/snippets/references-section.md}}
|
|
3195
|
-
`,ha=`---
|
|
3196
|
-
id: approval-block
|
|
3197
|
-
title: Approval Block
|
|
3198
|
-
---
|
|
3199
|
-
|
|
3200
|
-
## Approvals
|
|
3201
|
-
|
|
3202
|
-
This document has been reviewed and approved by the following personnel:
|
|
3203
|
-
|
|
3204
|
-
| Name | Role | Signature | Date |
|
|
3205
|
-
| --- | --- | --- | --- |
|
|
3206
|
-
| | Quality Assurance | | |
|
|
3207
|
-
| | Regulatory Affairs | | |
|
|
3208
|
-
| | Engineering Lead | | |
|
|
3209
|
-
| | Clinical Affairs | | |
|
|
3210
|
-
|
|
3211
|
-
`,ga=`---
|
|
3212
|
-
id: document-control-header
|
|
3213
|
-
title: Document Control Header
|
|
3214
|
-
---
|
|
3215
|
-
|
|
3216
|
-
| Field | Value |
|
|
3217
|
-
| --- | --- |
|
|
3218
|
-
| **Product** | {{project.product}} |
|
|
3219
|
-
| **Company** | {{project.company}} |
|
|
3220
|
-
| **Device Type** | {{project.device_type}} |
|
|
3221
|
-
| **Document Version** | {{project.version}} |
|
|
3222
|
-
| **Development Phase** | {{project.phase}} |
|
|
3223
|
-
| **Date** | — |
|
|
3224
|
-
| **Confidentiality** | Confidential — {{project.company}} |
|
|
3225
|
-
|
|
3226
|
-
`,ya=`---
|
|
3227
|
-
id: references-section
|
|
3228
|
-
title: References
|
|
3229
|
-
---
|
|
3230
|
-
|
|
3231
|
-
## References
|
|
3232
|
-
|
|
3233
|
-
| Standard | Title |
|
|
3234
|
-
| --- | --- |
|
|
3235
|
-
| ISO 14971:2019 | Medical devices — Application of risk management to medical devices |
|
|
3236
|
-
| IEC 62304:2006+AMD1:2015 | Medical device software — Software life cycle processes |
|
|
3237
|
-
| IEC 62366-1:2015+AMD1:2020 | Medical devices — Usability engineering |
|
|
3238
|
-
| ISO 13485:2016 | Medical devices — Quality management systems |
|
|
3239
|
-
| 21 CFR Part 820 | Quality System Regulation |
|
|
3240
|
-
| IEC 81001-5-1:2021 | Health software and health IT systems safety, effectiveness and security |
|
|
3241
|
-
|
|
3242
|
-
`,xa=`---
|
|
3243
|
-
id: revision-history-table
|
|
3244
|
-
title: Revision History Table
|
|
3245
|
-
---
|
|
3246
|
-
|
|
3247
|
-
## Revision History
|
|
3248
|
-
|
|
3249
|
-
| Version | Date | Author | Description of Change |
|
|
3250
|
-
| --- | --- | --- | --- |
|
|
3251
|
-
| 1.0 | {{project.version}} | {{project.authors}} | Initial release |
|
|
3252
|
-
|
|
3253
|
-
`,ba=Object.assign({"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/21cfr820/change-record.md":Fi,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/21cfr820/design-input.md":Ri,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/21cfr820/design-output.md":Ti,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/21cfr820/design-review.md":Ii,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/21cfr820/design-validation.md":_i,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/21cfr820/design-verification.md":Ni,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/21cfr820/dhf-index.md":Mi,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/21cfr820/transfer-plan.md":Oi,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/21cfr820/user-needs.md":Pi,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/21cfr820/vv-plan.md":zi,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/21cfr820/vv-report.md":Bi,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/fda-cybersecurity/incident-response.md":Li,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/fda-cybersecurity/postmarket-surveillance.md":qi,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/fda-cybersecurity/security-arch.md":Vi,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/fda-cybersecurity/threat-model.md":$i,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/fda-cybersecurity/vuln-assessment.md":Ui,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/iec-62304/change-control.md":Wi,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/iec-62304/detailed-design.md":Hi,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/iec-62304/integration-test.md":Ki,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/iec-62304/sad.md":Gi,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/iec-62304/sbom.md":Yi,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/iec-62304/sdp.md":Ji,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/iec-62304/soup.md":Qi,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/iec-62304/srs.md":Xi,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/iec-62304/sw-traceability.md":Zi,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/iec-62304/system-test.md":ea,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/iec-62366/formative-eval.md":ta,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/iec-62366/summative-eval.md":na,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/iec-62366/task-analysis.md":ra,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/iec-62366/ue-plan.md":oa,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/iec-62366/ui-spec.md":sa,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/iec-62366/urra.md":ia,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/iec-62366/use-spec.md":aa,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/iso-14971/fmea.md":la,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/iso-14971/fta.md":ca,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/iso-14971/har.md":da,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/iso-14971/risk-benefit.md":ua,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/iso-14971/risk-matrix.md":pa,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/iso-14971/rmp.md":ma,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/iso-14971/rmr.md":fa,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/shared/snippets/approval-block.md":ha,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/shared/snippets/document-control-header.md":ga,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/shared/snippets/references-section.md":ya,"../../../../node_modules/@memoarchitect/ontology/src/compliance/dhf-templates/shared/snippets/revision-history-table.md":xa}),Jt={};for(const[e,r]of Object.entries(ba)){const n=e.match(/dhf-templates\/(.+)\.md$/);n&&(Jt[n[1]]=r)}function va(e){return e.replace(/^---[\s\S]*?---\n?/,"")}function jr(e){return e.replace(/\{\{include:([^}]+)\}\}/g,(r,n)=>{const o=n.replace(/\.md$/,""),s=Jt[o];return s?jr(va(s)):`<!-- [include: ${n} — not found] -->`})}function wa(e){const r=Jt[e];return r?jr(r):null}const Ce=[{id:"risk",label:"Risk Management",color:"#dc2626",templates:[{id:"iso-14971/rmp",title:"Risk Management Plan",prefix:"RMP"},{id:"iso-14971/har",title:"Hazard Analysis Report",prefix:"HAR"},{id:"iso-14971/fmea",title:"FMEA",prefix:"FMEA"},{id:"iso-14971/fta",title:"Fault Tree Analysis",prefix:"FTA"},{id:"iso-14971/risk-benefit",title:"Risk-Benefit Analysis",prefix:"RBA"},{id:"iso-14971/rmr",title:"Risk Management Report",prefix:"RMR"}]},{id:"software",label:"Software",color:"#2563eb",templates:[{id:"iec-62304/sdp",title:"Software Development Plan",prefix:"SDP"},{id:"iec-62304/srs",title:"Software Requirements Spec",prefix:"SRS"},{id:"iec-62304/sad",title:"Software Architecture Description",prefix:"SAD"},{id:"iec-62304/detailed-design",title:"Software Detailed Design",prefix:"DDS"},{id:"iec-62304/integration-test",title:"Integration Test Plan",prefix:"ITP"},{id:"iec-62304/system-test",title:"System Test Plan",prefix:"STP"},{id:"iec-62304/soup",title:"SOUP List",prefix:"SOUP"},{id:"iec-62304/sbom",title:"Software Bill of Materials",prefix:"SBOM"},{id:"iec-62304/sw-traceability",title:"SW Traceability Matrix",prefix:"STM"},{id:"iec-62304/change-control",title:"Change Control Log",prefix:"CCL"}]},{id:"usability",label:"Usability",color:"#7c3aed",templates:[{id:"iec-62366/ue-plan",title:"Usability Engineering Plan",prefix:"UEP"},{id:"iec-62366/use-spec",title:"Intended Use Specification",prefix:"USE"},{id:"iec-62366/ui-spec",title:"User Interface Specification",prefix:"UIS"},{id:"iec-62366/task-analysis",title:"Task Analysis",prefix:"TA"},{id:"iec-62366/urra",title:"Use-Related Risk Analysis",prefix:"URRA"},{id:"iec-62366/formative-eval",title:"Formative Evaluation",prefix:"FE"},{id:"iec-62366/summative-eval",title:"Summative Evaluation",prefix:"SE"}]},{id:"requirements",label:"Requirements",color:"#0891b2",templates:[{id:"21cfr820/user-needs",title:"User Needs",prefix:"UN"},{id:"21cfr820/design-input",title:"Design Input Specification",prefix:"DIS"},{id:"21cfr820/design-output",title:"Design Output Specification",prefix:"DOS"}]},{id:"vv",label:"Verification & Validation",color:"#0d9488",templates:[{id:"21cfr820/vv-plan",title:"V&V Plan",prefix:"VVP"},{id:"21cfr820/vv-report",title:"V&V Report",prefix:"VVR"},{id:"21cfr820/design-verification",title:"Design Verification Report",prefix:"DVR"},{id:"21cfr820/design-validation",title:"Design Validation Report",prefix:"DVAR"},{id:"21cfr820/design-review",title:"Design Review Record",prefix:"DRR"}]},{id:"release",label:"Release & Change",color:"#4f46e5",templates:[{id:"21cfr820/transfer-plan",title:"Design Transfer Plan",prefix:"DTP"},{id:"21cfr820/change-record",title:"Design Change Record",prefix:"DCR"},{id:"21cfr820/dhf-index",title:"DHF Index",prefix:"DHF"}]},{id:"system",label:"System",color:"#059669",templates:[{id:"system/srs",title:"System Requirements Specification",prefix:"SRS"},{id:"system/sad",title:"System Architecture Description",prefix:"SyAD"},{id:"system/sds",title:"System Design Specification",prefix:"SDS"},{id:"system/icd",title:"Interface Control Document",prefix:"ICD"},{id:"system/svvp",title:"System V&V Plan",prefix:"SVVP"},{id:"system/svvr",title:"System V&V Report",prefix:"SVVR"}]},{id:"hardware",label:"Hardware",color:"#b45309",templates:[{id:"hardware/hdp",title:"Hardware Development Plan",prefix:"HDP"},{id:"hardware/hds",title:"Hardware Design Specification",prefix:"HDS"},{id:"hardware/hvp",title:"Hardware Verification Plan",prefix:"HVP"},{id:"hardware/hvr",title:"Hardware Verification Report",prefix:"HVR"},{id:"hardware/hbom",title:"Hardware Bill of Materials",prefix:"HBOM"},{id:"hardware/haz",title:"Hardware Hazard Analysis",prefix:"HHA"}]},{id:"cybersecurity",label:"Cybersecurity",color:"#d97706",templates:[{id:"fda-cybersecurity/threat-model",title:"Threat Model",prefix:"TM"},{id:"fda-cybersecurity/security-arch",title:"Security Architecture",prefix:"SA"},{id:"fda-cybersecurity/vuln-assessment",title:"Vulnerability Assessment",prefix:"VA"},{id:"fda-cybersecurity/postmarket-surveillance",title:"Post-Market Surveillance",prefix:"PMS"},{id:"fda-cybersecurity/incident-response",title:"Incident Response Plan",prefix:"IRP"}]}],Pt="#6B7280";function ka(e){var r;return((r=Ce.find(n=>n.label===e))==null?void 0:r.color)??Pt}function St(e){const r=e.split(/[^a-zA-Z0-9]+/).filter(Boolean);return r.length>=2?r.slice(0,4).map(n=>n[0].toUpperCase()).join(""):r.length===1?r[0].slice(0,3).toUpperCase():"DOC"}const Sa={position:"fixed",inset:0,zIndex:9999,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(0,0,0,0.4)"},Ea={background:"#fff",borderRadius:"12px",padding:"20px",width:"460px",maxHeight:"560px",display:"flex",flexDirection:"column",boxShadow:"0 20px 60px rgba(0,0,0,0.2)"},En=["Category","Template","Confirm"];function jn(e,r=1e4){const{registerLlmRequest:n}=k.getState(),o=`dhf-${Date.now()}-${Math.random().toString(36).slice(2)}`;return new Promise((s,i)=>{n(o,s,i),e(o),setTimeout(()=>i(new Error("Request timed out.")),r)})}function ja({initialGroupId:e,existingDocs:r,numberingPrefix:n,onCreate:o,onClose:s}){const i=k(A=>A.connected),a=Ce.find(A=>A.id===e)??null,[l,d]=u.useState(a?1:0),[c,p]=u.useState(a),[f,h]=u.useState(""),[S,b]=u.useState({builtIn:new Set,repo:new Set,blank:!1}),[x,v]=u.useState("Untitled Document"),[w,T]=u.useState(null),[I,m]=u.useState(null),[D,F]=u.useState({}),[E,R]=u.useState(!1),[O,C]=u.useState(null),P=c===null&&l>0?f.trim()||"Other":(c==null?void 0:c.label)??"",L=(c==null?void 0:c.color)??Pt,K=u.useMemo(()=>new Set(r.map(A=>A.templateId)),[r]);u.useEffect(()=>{l!==1||w!==null||!i||jn(A=>$s(A)).then(T).catch(A=>m((A==null?void 0:A.message)??"Could not list repository files."))},[l,w,i]);const H=u.useMemo(()=>{const A=[];for(const V of(c==null?void 0:c.templates)??[])S.builtIn.has(V.id)&&A.push({key:V.id,defaultTitle:V.title,prefix:V.prefix,templateId:V.id});for(const V of S.repo){const Y=w==null?void 0:w.find(g=>g.path===V),J=(Y==null?void 0:Y.title)??V.split("/").pop().replace(/\.md$/,"");A.push({key:`repo:${V}`,defaultTitle:J,prefix:St(J),templateId:`repo:${V}`})}return S.blank&&A.push({key:"blank",defaultTitle:x.trim()||"Untitled Document",prefix:St(x),templateId:"blank"}),A},[S,c,w,x]),N=A=>D[A.key]??A.defaultTitle,W=A=>A.templateId==="blank"||A.templateId.startsWith("repo:")?St(N(A)):A.prefix,X=u.useMemo(()=>{const A=new Map;return H.map(V=>{const Y=`${n}-${W(V)}-`,J=r.filter(_=>_.id.startsWith(Y)).length,g=A.get(Y)??0;return A.set(Y,g+1),`${Y}${String(J+g+1).padStart(3,"0")}`})},[H,D,r,n]);async function U(){R(!0),C(null);try{const A=[];for(const V of H){let Y=null;V.templateId.startsWith("repo:")?Y=await jn(J=>Us(J,V.templateId.slice(5))):V.templateId==="blank"&&(Y=`# ${N(V)}
|
|
3254
|
-
|
|
3255
|
-
_[TODO: Add content]_
|
|
3256
|
-
`),A.push({title:N(V),prefix:W(V),templateId:V.templateId,groupLabel:P,content:Y})}o(A)}catch(A){C((A==null?void 0:A.message)??"Could not read template."),R(!1)}}const M=l===0?!0:l===1?H.length>0:H.length>0&&!E;return t.jsx("div",{style:Sa,onClick:A=>{A.target===A.currentTarget&&s()},children:t.jsxs("div",{style:Ea,children:[t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"8px",marginBottom:"4px"},children:[t.jsx("span",{style:{fontSize:"14px",fontWeight:700,color:"#1B3A4B",flex:1},children:"New Document"}),t.jsx("button",{onClick:s,style:{background:"none",border:"none",cursor:"pointer",color:"#9CA3AF",fontSize:"18px",lineHeight:1},children:"×"})]}),t.jsx("div",{style:{display:"flex",gap:"6px",marginBottom:"14px"},children:En.map((A,V)=>t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"5px",fontSize:"11px",fontWeight:V===l?700:500,color:V===l?"#1B3A4B":V<l?"#059669":"#9CA3AF"},children:[t.jsx("span",{style:{width:"16px",height:"16px",borderRadius:"50%",display:"inline-flex",alignItems:"center",justifyContent:"center",fontSize:"9px",fontWeight:700,color:"#fff",background:V===l?"#1B3A4B":V<l?"#059669":"#D1D5DB"},children:V<l?"✓":V+1}),A,V<En.length-1&&t.jsx("span",{style:{color:"#D1D5DB"},children:"—"})]},A))}),l===0&&t.jsxs("div",{style:{flex:1,overflowY:"auto",display:"flex",flexDirection:"column",gap:"4px"},children:[Ce.map(A=>t.jsx(Cn,{label:A.label,color:A.color,detail:`${A.templates.length} meMO templates`,selected:(c==null?void 0:c.id)===A.id,onClick:()=>{p(A),b({builtIn:new Set,repo:new Set,blank:!1})}},A.id)),t.jsx(Cn,{label:"Other",color:Pt,detail:"Custom category — blank or repository template",selected:c===null&&f!=="",onClick:()=>{p(null),h(f||"Other"),b({builtIn:new Set,repo:new Set,blank:!1})}}),c===null&&f!==""&&t.jsx("input",{value:f,onChange:A=>h(A.target.value),placeholder:"Category name, e.g. Clinical",autoFocus:!0,style:{margin:"2px 0 0 26px",padding:"6px 8px",border:"1px solid #D1D5DB",borderRadius:"5px",fontSize:"12px",color:"#1B3A4B",outline:"none"}})]}),l===1&&t.jsxs("div",{style:{flex:1,overflowY:"auto",display:"flex",flexDirection:"column",gap:"10px"},children:[t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"6px",fontSize:"12px",color:"#6B7280"},children:[t.jsx("span",{style:{width:"9px",height:"9px",borderRadius:"50%",background:L,display:"inline-block"}}),t.jsx("strong",{style:{color:"#1B3A4B"},children:P}),t.jsx("span",{children:"— pick one or more sources"})]}),c&&c.templates.length>0&&t.jsx(Et,{title:"meMO templates",hint:"Prefilled sections and model queries",children:c.templates.map(A=>t.jsx(jt,{label:A.title,sub:A.id,color:L,checked:S.builtIn.has(A.id),disabled:K.has(A.id),disabledNote:"exists",onToggle:()=>b(V=>{const Y=new Set(V.builtIn);return Y.has(A.id)?Y.delete(A.id):Y.add(A.id),{...V,builtIn:Y}})},A.id))}),t.jsx(Et,{title:"Blank document",hint:"Start from an empty page",children:t.jsx(jt,{label:S.blank?"":"Blank document",color:L,checked:S.blank,onToggle:()=>b(A=>({...A,blank:!A.blank})),children:S.blank&&t.jsx("input",{value:x,onChange:A=>v(A.target.value),onClick:A=>A.stopPropagation(),style:{flex:1,padding:"4px 8px",border:"1px solid #D1D5DB",borderRadius:"5px",fontSize:"12px",color:"#1B3A4B",outline:"none"}})})}),t.jsxs(Et,{title:"From repository",hint:"Any markdown file in this project",children:[!i&&t.jsx(Le,{text:"Dev server not connected — repository templates unavailable."}),i&&I&&t.jsx(Le,{text:I,error:!0}),i&&!I&&w===null&&t.jsx(Le,{text:"Loading repository files…"}),i&&(w==null?void 0:w.length)===0&&t.jsx(Le,{text:"No markdown files found in this project."}),i&&(w==null?void 0:w.map(A=>t.jsx(jt,{label:A.title,sub:A.path,color:L,checked:S.repo.has(A.path),onToggle:()=>b(V=>{const Y=new Set(V.repo);return Y.has(A.path)?Y.delete(A.path):Y.add(A.path),{...V,repo:Y}})},A.path)))]})]}),l===2&&t.jsxs("div",{style:{flex:1,overflowY:"auto",display:"flex",flexDirection:"column",gap:"6px"},children:[t.jsxs("div",{style:{fontSize:"12px",color:"#6B7280",marginBottom:"4px"},children:[H.length," document",H.length===1?"":"s"," will be created in",t.jsxs("strong",{style:{color:"#1B3A4B"},children:[" ",P]})," and saved to ",t.jsx("code",{style:{background:"#F3F4F6",padding:"0 4px",borderRadius:"3px",fontSize:"11px"},children:"dhf/documents/"}),":"]}),H.map((A,V)=>t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"8px",padding:"7px 10px",border:"1px solid #E5E7EB",borderRadius:"6px"},children:[t.jsx("span",{style:{fontSize:"11px",fontFamily:"monospace",fontWeight:700,color:L,whiteSpace:"nowrap"},children:X[V]}),t.jsx("input",{value:N(A),onChange:Y=>F(J=>({...J,[A.key]:Y.target.value})),style:{flex:1,padding:"4px 8px",border:"1px solid #E5E7EB",borderRadius:"5px",fontSize:"12px",color:"#1B3A4B",outline:"none"}}),t.jsx("span",{style:{fontSize:"10px",color:"#9CA3AF",whiteSpace:"nowrap"},children:A.templateId==="blank"?"blank":A.templateId.startsWith("repo:")?"repo":"meMO"})]},A.key)),O&&t.jsx(Le,{text:O,error:!0})]}),t.jsxs("div",{style:{display:"flex",gap:"8px",justifyContent:"flex-end",marginTop:"16px"},children:[l>0&&t.jsx("button",{onClick:()=>d(A=>A-1),disabled:E,style:{padding:"7px 14px",borderRadius:"6px",border:"1px solid #E5E7EB",background:"#fff",fontSize:"13px",cursor:"pointer",color:"#374151",marginRight:"auto"},children:"← Back"}),t.jsx("button",{onClick:s,style:{padding:"7px 14px",borderRadius:"6px",border:"1px solid #E5E7EB",background:"#fff",fontSize:"13px",cursor:"pointer",color:"#374151"},children:"Cancel"}),l<2?t.jsx("button",{onClick:()=>d(A=>A+1),disabled:!M,style:{padding:"7px 16px",borderRadius:"6px",border:"none",background:M?"#1B3A4B":"#E5E7EB",color:M?"#fff":"#9CA3AF",fontSize:"13px",fontWeight:600,cursor:M?"pointer":"default"},children:"Next →"}):t.jsx("button",{onClick:U,disabled:!M,style:{padding:"7px 16px",borderRadius:"6px",border:"none",background:M?L:"#E5E7EB",color:M?"#fff":"#9CA3AF",fontSize:"13px",fontWeight:600,cursor:M?"pointer":"default"},children:E?"Creating…":`Create ${H.length>0?`(${H.length})`:""}`})]})]})})}function Cn({label:e,color:r,detail:n,selected:o,onClick:s}){return t.jsxs("button",{onClick:s,style:{display:"flex",alignItems:"center",gap:"10px",padding:"9px 10px",borderRadius:"6px",border:`1px solid ${o?r:"#E5E7EB"}`,background:o?`${r}10`:"#fff",cursor:"pointer",textAlign:"left"},children:[t.jsx("span",{style:{width:"10px",height:"10px",borderRadius:"50%",background:r,flexShrink:0}}),t.jsx("span",{style:{flex:1,fontSize:"13px",fontWeight:600,color:"#1B3A4B"},children:e}),t.jsx("span",{style:{fontSize:"11px",color:"#9CA3AF"},children:n})]})}function Et({title:e,hint:r,children:n}){return t.jsxs("div",{children:[t.jsxs("div",{style:{fontSize:"10px",fontWeight:700,color:"#6B7280",textTransform:"uppercase",letterSpacing:"0.05em",marginBottom:"2px"},children:[e," ",t.jsxs("span",{style:{fontWeight:400,textTransform:"none",letterSpacing:0,color:"#9CA3AF"},children:["— ",r]})]}),t.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"2px"},children:n})]})}function jt({label:e,sub:r,color:n,checked:o,disabled:s,disabledNote:i,onToggle:a,children:l}){return t.jsxs("label",{style:{display:"flex",alignItems:"center",gap:"10px",padding:"6px 8px",borderRadius:"6px",cursor:s?"not-allowed":"pointer",background:o?`${n}10`:"transparent",opacity:s?.45:1},children:[t.jsx("input",{type:"checkbox",checked:o,disabled:s,onChange:()=>!s&&a(),style:{accentColor:n}}),e&&t.jsx("span",{style:{fontSize:"13px",color:"#1B3A4B"},children:e}),l,r&&t.jsx("span",{style:{marginLeft:"auto",fontSize:"10px",fontFamily:"monospace",color:"#9CA3AF",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",maxWidth:"180px"},children:r}),s&&i&&t.jsx("span",{style:{fontSize:"10px",color:"#9CA3AF"},children:i})]})}function Le({text:e,error:r}){return t.jsx("div",{style:{fontSize:"11px",color:r?"#DC2626":"#9CA3AF",fontStyle:"italic",padding:"4px 8px"},children:e})}function xe({expanded:e,size:r=14,color:n=y.muted}){return t.jsx("svg",{width:r,height:r,viewBox:"0 0 16 16",fill:"none",style:{transition:"transform 150ms ease",transform:e?"rotate(90deg)":"rotate(0deg)",flexShrink:0},children:t.jsx("path",{d:"M6 4L10 8L6 12",stroke:n,strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}function Ae({open:e,color:r=y.muted}){return e?t.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",style:{flexShrink:0},children:[t.jsx("path",{d:"M1.5 3.5h4.8l1.2 1.5H14.5v8H1.5z",fill:r,opacity:"0.15",stroke:r,strokeWidth:"1",strokeLinejoin:"round"}),t.jsx("path",{d:"M1.5 5h13v8H1.5z",fill:r,opacity:"0.08"})]}):t.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",style:{flexShrink:0},children:t.jsx("path",{d:"M1.5 3.5h4.8l1.2 1.5H14.5v8H1.5z",fill:r,opacity:"0.15",stroke:r,strokeWidth:"1",strokeLinejoin:"round"})})}function zt({color:e=y.muted}){return t.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"none",style:{flexShrink:0},children:[t.jsx("rect",{x:"2",y:"1.5",width:"12",height:"13",rx:"1.5",fill:e,opacity:"0.1",stroke:e,strokeWidth:"1"}),t.jsx("line",{x1:"5",y1:"5.5",x2:"11",y2:"5.5",stroke:e,strokeWidth:"0.8",opacity:"0.5"}),t.jsx("line",{x1:"5",y1:"8",x2:"11",y2:"8",stroke:e,strokeWidth:"0.8",opacity:"0.5"}),t.jsx("line",{x1:"5",y1:"10.5",x2:"9",y2:"10.5",stroke:e,strokeWidth:"0.8",opacity:"0.5"})]})}function Ca({elementId:e,currentKind:r,onClose:n}){const o=k(c=>c.updateElementKind),s=k(c=>c.model),[i,a]=u.useState(r),l=u.useRef(null),d=u.useMemo(()=>{var c;return(((c=s==null?void 0:s.registries)==null?void 0:c.kinds)??[]).filter(p=>!p.isAbstract).map(p=>p.name).sort((p,f)=>p.localeCompare(f))},[s]);return u.useEffect(()=>{const c=p=>{l.current&&!l.current.contains(p.target)&&n()};return document.addEventListener("mousedown",c),()=>document.removeEventListener("mousedown",c)},[n]),t.jsxs("div",{ref:l,className:"fixed z-50 rounded-lg overflow-hidden py-3 px-4",style:{top:"50%",left:"50%",transform:"translate(-50%, -50%)",background:"#FFFFFF",border:"1px solid #E5E7EB",boxShadow:"0 8px 32px rgba(0,0,0,0.16)",minWidth:"320px"},children:[t.jsx("div",{className:"font-semibold mb-3",style:{color:"#1B3A4B",fontSize:"13px"},children:"Change Element Type"}),t.jsxs("div",{className:"text-xs mb-1",style:{color:"#6B7280"},children:["Current: ",t.jsx("span",{style:{color:"#DC2626",fontWeight:600},children:r})," (not in ontology)"]}),t.jsx("select",{value:i,onChange:c=>a(c.target.value),className:"w-full px-3 py-2 rounded-lg mb-3 focus:outline-none",style:{background:"#F9F9F8",border:"1px solid #E5E7EB",color:"#1B3A4B",fontSize:"13px"},children:d.map(c=>t.jsx("option",{value:c,children:c},c))}),t.jsxs("div",{className:"flex gap-2 justify-end",children:[t.jsx("button",{onClick:n,className:"px-3 py-1.5 rounded",style:{fontSize:"12px",color:"#6B7280",background:"#F0F0ED"},children:"Cancel"}),t.jsx("button",{onClick:()=>{o(e,i),n()},className:"px-3 py-1.5 rounded font-medium",style:{fontSize:"12px",color:"#FFFFFF",background:"#2DD4A8"},children:"Apply"})]})]})}function Da({menu:e,onClose:r}){var S;const n=k(b=>b.model),o=k(b=>b.selectElement),s=k(b=>b.addElement),i=k(b=>b.updateElementFolder),a=k(b=>b.moveFolder),l=k(b=>b.deleteFolder),[d,c]=u.useState(null),p=u.useRef(null);if(u.useEffect(()=>{const b=x=>{p.current&&!p.current.contains(x.target)&&r()};return document.addEventListener("mousedown",b),()=>document.removeEventListener("mousedown",b)},[r]),!n)return null;let f="",h=[];if(e.type==="element"&&e.elementId){const b=n.elements[e.elementId];if(!b)return null;f=b.name;const x=!(((S=n.registries)==null?void 0:S.kinds)??[]).some(v=>v.name===b.kind);h=[{label:"View details",action:()=>o(b.id)},{label:"Move to folder...",action:()=>{const v=window.prompt("Enter new folder path (e.g., Manufacturers/Hardware):",b.attributes[je]||"");v!==null&&i(b.id,v)}},{label:"Copy ID",action:()=>{var v;return(v=navigator.clipboard)==null?void 0:v.writeText(b.id)}},...x?[{label:"⚠ Change Type…",action:()=>c({elementId:b.id,currentKind:b.kind})}]:[]]}else e.type==="folder"&&e.folderId&&e.kind?(f=`Folder: ${e.folderId.split("/").pop()}`,h=[{label:"Add Element here",action:()=>{const b=window.prompt("Enter element name:");b&&s(e.kind,b,e.folderId)}},{label:"Add Sub-group",action:()=>{const b=window.prompt("Enter group name:");if(b){const x=e.folderId?`${e.folderId}/${b}`:b;s(e.kind,`(new ${b} element)`,x)}}},{label:"Move Folder...",action:()=>{const b=window.prompt("Enter new folder path:",e.folderId);b&&b!==e.folderId&&a(e.kind,e.folderId,b)}},{label:"Delete Folder (Move items up)",danger:!0,action:()=>{window.confirm(`Move all elements in "${e.folderId}" to its parent group?`)&&l(e.kind,e.folderId)}}]):e.type==="kind"&&e.kind&&(f=`Category: ${e.kind}`,h=[{label:"Add Element",action:()=>{const b=window.prompt("Enter element name:");b&&s(e.kind,b,"")}},{label:"New Group",action:()=>{const b=window.prompt("Enter group name:");b&&s(e.kind,`(new ${b} element)`,b)}}]);return h.length?t.jsxs(t.Fragment,{children:[t.jsxs("div",{ref:p,className:"fixed z-50 rounded-lg overflow-hidden py-1",style:{left:e.x,top:e.y,background:y.surface,border:`1px solid ${y.border}`,boxShadow:"0 4px 16px rgba(0,0,0,0.12)",minWidth:"220px"},children:[t.jsx("div",{className:"px-3 py-1.5 font-bold truncate bg-slate-50",style:{color:y.primary,fontSize:j.xs,borderBottom:`1px solid ${y.border}`},children:f.toUpperCase()}),h.map((b,x)=>t.jsx("div",{className:"px-3 py-2 cursor-pointer transition-colors",style:{color:b.danger?"#DC2626":y.secondary,fontSize:j.explorer.item},onMouseEnter:v=>v.currentTarget.style.background="#F0F0ED",onMouseLeave:v=>v.currentTarget.style.background="transparent",onClick:()=>{b.action(),d||r()},children:b.label},x))]}),d&&t.jsx(Ca,{elementId:d.elementId,currentKind:d.currentKind,onClose:()=>{c(null),r()}})]}):null}function Aa(e){const r=[],n=[...e].sort((s,i)=>s.name.localeCompare(i.name));for(const s of n){const a=(s.attributes[je]||"").split("/").filter(Boolean);let l=r,d="";for(const c of a){d=d?`${d}/${c}`:c;const p=`f:${d}`;let f=l.find(h=>h.id===p);f||(f={id:p,name:c,type:"folder",children:[]},l.push(f)),l=f.children}l.push({id:s.id,name:s.name,type:"element",children:[],element:s})}const o=s=>{s.sort((i,a)=>i.type!==a.type?i.type==="folder"?-1:1:i.name.localeCompare(a.name));for(const i of s)i.children.length>0&&o(i.children)};return o(r),r}function Cr({nodes:e,level:r,expanded:n,toggleExpand:o,selectedElementId:s,selectElement:i,selectedElementIds:a,toggleElementSelection:l,violationCounts:d,baseColor:c,onContextMenu:p,onDragStart:f,onDrop:h,isUndefined:S}){return t.jsx(t.Fragment,{children:e.map(b=>{if(b.type==="folder"){const x=n.has(b.id);return t.jsxs("div",{style:{marginLeft:r>0?"16px":"0"},draggable:!0,onDragStart:v=>f(v,b),onDragOver:v=>v.preventDefault(),onDrop:v=>h(v,b.id.replace("f:","")),children:[t.jsxs("div",{className:"flex items-center gap-1.5 px-2 py-1 cursor-pointer select-none",style:{borderRadius:"4px",margin:"0 4px"},onMouseEnter:v=>v.currentTarget.style.background="#F0F0ED",onMouseLeave:v=>v.currentTarget.style.background="transparent",onClick:()=>o(b.id),onContextMenu:v=>p(v,"folder",b.id),children:[t.jsx(xe,{expanded:x,size:12,color:y.muted}),t.jsx(Ae,{open:x,color:c}),t.jsx("span",{className:"font-medium flex-1 truncate",style:{color:y.secondary,fontSize:j.explorer.kind},children:b.name})]}),x&&t.jsx(Cr,{nodes:b.children,level:r+1,expanded:n,toggleExpand:o,selectedElementId:s,selectElement:i,selectedElementIds:a,toggleElementSelection:l,violationCounts:d,baseColor:c,onContextMenu:p,onDragStart:f,onDrop:h,isUndefined:S})]},b.id)}else{const x=b.element,v=s===x.id,w=a.has(x.id),T=d.get(x.id)||0,I=re[x.layer]||c;return t.jsxs("div",{className:"group flex items-center gap-1.5 px-2 py-1 cursor-pointer",style:{borderRadius:"4px",margin:"0 4px",marginLeft:(r>0?16:0)+20+"px",background:w?"#FFF3CD":v?y.accent+"18":"transparent",fontWeight:v||w?500:400},draggable:!0,onDragStart:m=>f(m,{type:"element",element:x,id:x.id,name:x.name,children:[]}),onMouseEnter:m=>{!v&&!w&&(m.currentTarget.style.background="#F0F0ED")},onMouseLeave:m=>{m.currentTarget.style.background=w?"#FFF3CD":v?y.accent+"18":"transparent"},onClick:m=>{m.metaKey||m.ctrlKey||m.shiftKey?(m.preventDefault(),l(x.id)):i(x.id)},onContextMenu:m=>p(m,"element",x.id),children:[t.jsx("input",{type:"checkbox",checked:w,onChange:m=>{m.stopPropagation(),l(x.id)},onClick:m=>m.stopPropagation(),className:"flex-shrink-0",style:{width:"12px",height:"12px",cursor:"pointer",opacity:w?1:0,transition:"opacity 120ms",accentColor:"#2DD4A8"},onMouseEnter:m=>{m.currentTarget.style.opacity="1"},onMouseLeave:m=>{m.currentTarget.style.opacity=w?"1":"0"}}),t.jsx(zt,{color:S?"#F59E0B":I}),t.jsxs("span",{className:"truncate flex-1",style:{color:v?y.accentDark:y.primary,fontSize:j.explorer.item},children:[x.shortId&&t.jsxs("span",{style:{color:y.muted,fontWeight:500,marginRight:"4px"},children:["[",x.shortId,"]"]}),x.name]}),S&&t.jsx("span",{title:`Kind "${x.kind}" is not defined in the ontology`,style:{color:"#F59E0B",fontSize:"12px",flexShrink:0},children:"⚠"}),T>0&&t.jsx("span",{className:"px-1 py-0.5 rounded-full",style:{background:"#FEF2F2",color:"#DC2626",fontSize:j.explorer.count,fontWeight:600,minWidth:"16px",textAlign:"center"},children:T})]},x.id)}})})}function Fa(e,r,n){return e.endsWith("View")||r==="viewpoints"||r==="views"||n==="viewpoints"||n==="views"}function Dn(e,r,n){return Fa(e,r,n)||e==="ForkNode"||e==="JoinNode"||e==="ActionDefinition"||e==="ActionUsage"||e==="ItemDefinition"}function Ra(e,r){var s;const n=new Map,o=new Map;for(const i of r)for(const a of i.layers)o.has(a.id)||o.set(a.id,a);for(const i of e){const a=((s=i.namespace)==null?void 0:s[0])??i.layer;if(!a||a==="unknown")continue;let l=n.get(a);if(!l){const d=o.get(a);l={id:a,label:(d==null?void 0:d.label)??Dr(a),color:(d==null?void 0:d.color)??re[a]??"#6B7280",kinds:[]},n.set(a,l)}l.kinds.includes(i.name)||l.kinds.push(i.name)}return[...n.values()]}function Ta(e){var n;const r={};for(const o of e)r[o.name]=((n=o.namespace)==null?void 0:n[0])??o.layer;return r}function Ia(e){var n;const r={};for(const o of e)r[o.name]=(n=o.namespace)==null?void 0:n[1];return r}function _a(e){const r={},n=new Set;for(const o of e)o.isAbstract&&n.add(o.name),r[o.name]=o.superType;for(const[o,s]of Object.entries(r))s&&n.has(s)&&(r[o]=void 0);return r}function Dr(e){return e.split(/[_-]/).map(r=>r.charAt(0).toUpperCase()+r.slice(1)).join(" ")}function Na(e,r){const n={StateMachine:"State Machine",ModeState:"Mode State",BehaviorProperty:"Behavioral Constraint",AssumeProperty:"Assumption",GuaranteeProperty:"Guarantee"};if(n[e])return r===1?n[e]:n[e]+"s";const o=e.replace(/([a-z0-9])([A-Z])/g,"$1 $2");return r===1||/(?:ss|Data|Status)$/i.test(o)||o.endsWith("s")?o:o+"s"}function Ma(e,r,n,o){const s=r.toLowerCase(),i=new Set(["views","viewpoints","manifest"]),a=Ta(n),l=Ia(n),d=_a(n),c=Ra(n,o).filter(b=>!i.has(b.id)),p=new Set(c.map(b=>b.id)),f=(b,x)=>{const v=new Map;for(const[w,T]of b.entries()){const I=l[w]??"",m=d[w]??w;v.has(I)||v.set(I,new Map);const D=v.get(I),F=D.get(m)??[];D.set(m,[...F,...Aa(T)])}return[...v.entries()].sort(([w],[T])=>w.localeCompare(T)).map(([w,T])=>({id:w,label:w?Dr(w):"",color:w?re[w]??x:x,kinds:T}))},h=[];for(const b of c){const x=new Map;for(const v of e){const w=a[v.kind]??v.layer,T=l[v.kind];if(Dn(v.kind,w,T))continue;const I=a[v.kind];I&&I===b.id&&(s&&!v.name.toLowerCase().includes(s)&&!v.kind.toLowerCase().includes(s)||(x.has(v.kind)||x.set(v.kind,[]),x.get(v.kind).push(v)))}x.size>0&&h.push({group:b,subGroups:f(x,b.color)})}const S=new Map;for(const b of e){const x=a[b.kind]??b.layer,v=l[b.kind];if(Dn(b.kind,x,v))continue;const w=a[b.kind];w&&p.has(w)||w&&i.has(w)||s&&!b.name.toLowerCase().includes(s)&&!b.kind.toLowerCase().includes(s)||(S.has(b.kind)||S.set(b.kind,[]),S.get(b.kind).push(b))}if(S.size>0){const b="#F59E0B";h.push({group:{id:"undefined",label:"Undefined — Not in Ontology",color:b,kinds:[]},subGroups:f(S,b)})}return h}function An({searchTerm:e}){const r=k(N=>N.model),n=k(N=>N.selectedElementId),o=k(N=>N.selectElement),s=k(N=>N.setActiveView),i=k(N=>N.selectedElementIds),a=k(N=>N.toggleElementSelection),l=k(N=>N.selectAllElements),d=k(N=>N.clearElementSelection),c=k(N=>N.updateElementFolder),p=k(N=>N.moveFolder),f=k(N=>N.validation),h=k(N=>N.availableOntologies),S=k(N=>N.setExplorerTab),b=k(N=>N.setActiveMode),x=k(N=>N.setSelectedOntologyKind),v=u.useCallback(N=>{o(N),s({type:"element-detail",elementId:N})},[o,s]),[w,T]=u.useState(new Set),[I,m]=u.useState(null),[D,F]=u.useState(null),E=u.useCallback((N,W)=>{W==null||W.stopPropagation(),T(X=>{const U=new Set(X);return U.has(N)?U.delete(N):U.add(N),U})},[]),R=u.useCallback((N,W,X,U)=>{N.preventDefault(),m({x:N.clientX,y:N.clientY,type:W,elementId:W==="element"?X:void 0,folderId:W==="folder"?X.replace("f:",""):void 0,kind:U||(W==="kind"?X.replace("k:","").split(":").pop():void 0)})},[]),O=u.useMemo(()=>{var N;return r?Ma(Object.values(r.elements),e,((N=r.registries)==null?void 0:N.kinds)??[],h):[]},[r,e,h]),C=u.useCallback((N,W,X)=>{var U;F({id:W.id,kind:X}),N.dataTransfer.setData("application/memo-node",JSON.stringify({id:W.id,type:W.type,kind:X,name:W.name,elementId:(U=W.element)==null?void 0:U.id,folderPath:W.type==="folder"?W.id.replace("f:",""):void 0})),N.dataTransfer.effectAllowed="move"},[]),B=u.useCallback((N,W)=>{(D==null?void 0:D.kind)===W&&(N.preventDefault(),N.dataTransfer.dropEffect="move")},[D]),P=u.useCallback((N,W,X)=>{N.preventDefault(),F(null);try{const U=JSON.parse(N.dataTransfer.getData("application/memo-node"));if(U.kind!==X)return;if(U.type==="element")c(U.elementId,W);else if(U.type==="folder"){if(W===U.folderPath||W.startsWith(U.folderPath+"/"))return;const M=U.folderPath.includes("/")?U.folderPath.slice(U.folderPath.lastIndexOf("/")+1):U.folderPath,A=W?W+"/"+M:M;p(U.kind,U.folderPath,A)}}catch(U){console.error("Drop error:",U)}},[c,p]),L=u.useMemo(()=>{const N=new Map;if(f)for(const W of f.violations)N.set(W.elementId,(N.get(W.elementId)||0)+1);return N},[f]),K=u.useMemo(()=>{const N=[],W=X=>{for(const U of X)U.type==="element"&&U.element?N.push(U.element.id):W(U.children)};for(const{subGroups:X}of O)for(const U of X)for(const M of U.kinds.values())W(M);return N},[O]),H=i.size;return t.jsxs("div",{className:"flex-1 flex flex-col overflow-hidden",children:[H>0&&t.jsxs("div",{className:"flex items-center gap-2 px-3 py-1.5 flex-shrink-0",style:{background:"#FFFBEB",borderBottom:"1px solid #FDE68A",fontSize:"12px"},children:[t.jsxs("span",{style:{color:"#92400E",fontWeight:600},children:[H," selected"]}),t.jsx("span",{style:{color:"#B45309"},children:"— Cmd/Ctrl+click to multi-select"}),t.jsx("button",{onClick:d,className:"ml-auto px-2 py-0.5 rounded",style:{color:"#92400E",background:"#FDE68A",fontSize:"12px",fontWeight:500},children:"Clear"})]}),e&&K.length>0&&t.jsxs("div",{className:"flex items-center gap-2 px-3 py-1",style:{background:"#F0F9FF",borderBottom:"1px solid #BAE6FD",fontSize:"12px"},children:[t.jsxs("span",{style:{color:"#0369A1"},children:[K.length," matching"]}),t.jsx("button",{onClick:()=>l(K),className:"ml-auto px-2 py-0.5 rounded",style:{color:"#0369A1",background:"#BAE6FD",fontSize:"12px",fontWeight:500},children:"Select All"})]}),t.jsxs("div",{className:"flex-1 overflow-y-auto py-1",style:{fontSize:j.explorer.item},children:[O.map(({group:N,subGroups:W})=>{const X=`g:${N.id}`,U=w.has(X),M=N.id==="undefined",A=J=>J.reduce((g,_)=>g+(_.type==="element"?1:A(_.children)),0),V=J=>Array.from(J.kinds.values()).reduce((g,_)=>g+A(_),0),Y=W.reduce((J,g)=>J+V(g),0);return t.jsxs("div",{className:"mb-0.5",children:[t.jsxs("div",{className:"flex items-center gap-1.5 px-2 py-1.5 cursor-pointer select-none",style:{margin:"0 4px",borderRadius:"4px",...M?{background:"#FFF3CD"}:{}},onMouseEnter:J=>J.currentTarget.style.background=M?"#FDE68A":"#F0F0ED",onMouseLeave:J=>J.currentTarget.style.background=M?"#FFF3CD":"transparent",onClick:()=>E(X),onContextMenu:J=>R(J,"group",X),children:[t.jsx(xe,{expanded:U,size:14,color:N.color}),M?t.jsx("span",{style:{fontSize:"14px",lineHeight:1,flexShrink:0},children:"⚠"}):t.jsx(Ae,{open:U,color:N.color}),t.jsx("span",{className:"font-semibold flex-1 truncate",style:{color:M?"#92400E":y.primary,fontSize:j.explorer.group},children:N.label}),t.jsx("span",{className:"px-1.5 py-0.5 rounded-full",style:{background:N.color+"25",color:N.color,fontSize:j.explorer.count,fontWeight:600,minWidth:"20px",textAlign:"center"},children:Y})]}),(()=>{const J=(g,_,q)=>{const ee=`k:${N.id}:${q?q+":":""}${g}`,ne=w.has(ee),se=G=>{var Q;for(const ue of G){if(ue.type==="element")return(Q=ue.element)==null?void 0:Q.layer;const we=se(ue.children);if(we)return we}},$=se(_),ie=M?"#F59E0B":$&&re[$]||N.color,ye=G=>G.flatMap(Q=>Q.type==="element"&&Q.element?[Q.element.id]:ye(Q.children)),de=ye(_);return t.jsxs("div",{style:{marginLeft:"16px"},onDragOver:G=>B(G,g),onDrop:G=>P(G,"",g),children:[t.jsxs("div",{className:"flex items-center gap-1.5 px-2 py-1 cursor-pointer select-none",style:{borderRadius:"4px",margin:"0 4px"},onMouseEnter:G=>G.currentTarget.style.background="#F0F0ED",onMouseLeave:G=>G.currentTarget.style.background="transparent",onClick:()=>E(ee),onContextMenu:G=>R(G,"kind",ee,g),children:[t.jsx(xe,{expanded:ne,size:12,color:y.muted}),t.jsx(Ae,{open:ne,color:ie}),t.jsxs("span",{className:"font-medium flex-1 truncate",style:{color:M?"#B45309":y.secondary,fontSize:j.explorer.kind},children:[Na(g,de.length),M&&t.jsx("span",{style:{color:"#F59E0B",marginLeft:"4px"},children:"·"})]}),t.jsx("button",{onClick:G=>{G.stopPropagation(),l(de)},title:"Select all in this category",className:"px-1 rounded",style:{color:y.faint,fontSize:"10px",opacity:.6},onMouseEnter:G=>G.currentTarget.style.opacity="1",onMouseLeave:G=>G.currentTarget.style.opacity="0.6",children:"☑"}),!M&&t.jsx("button",{onClick:G=>{G.stopPropagation();for(const Q of h)for(const ue of Q.layers)if(ue.kinds.some(we=>we.name===g)){x(g),S("ontologies"),b("ontology"),s({type:"ontology-detail",packageName:Q.name,layerId:ue.id});return}},title:"View kind in Ontology",className:"px-1 rounded",style:{color:y.faint,fontSize:"10px",opacity:.6},onMouseEnter:G=>G.currentTarget.style.opacity="1",onMouseLeave:G=>G.currentTarget.style.opacity="0.6",children:"⬡"})]}),ne&&t.jsx(Cr,{nodes:_,level:0,expanded:w,toggleExpand:E,selectedElementId:n,selectElement:v,selectedElementIds:i,toggleElementSelection:a,violationCounts:L,baseColor:ie,onContextMenu:(G,Q,ue)=>R(G,Q,ue,g),onDragStart:(G,Q)=>C(G,Q,g),onDrop:(G,Q)=>P(G,Q,g),isUndefined:M})]},g)};return U?W.map(g=>{if(!g.id)return t.jsx("div",{children:Array.from(g.kinds.entries()).map(([ne,se])=>J(ne,se,""))},"__root");const _=`sg:${N.id}:${g.id}`,q=w.has(_),ee=V(g);return t.jsxs("div",{style:{marginLeft:"16px"},children:[t.jsxs("div",{className:"flex items-center gap-1.5 px-2 py-1 cursor-pointer select-none",style:{borderRadius:"4px",margin:"0 4px"},onMouseEnter:ne=>ne.currentTarget.style.background="#F0F0ED",onMouseLeave:ne=>ne.currentTarget.style.background="transparent",onClick:()=>E(_),children:[t.jsx(xe,{expanded:q,size:13,color:g.color}),t.jsx(Ae,{open:q,color:g.color}),t.jsx("span",{className:"font-semibold flex-1 truncate",style:{color:y.primary,fontSize:j.explorer.kind},children:g.label}),t.jsx("span",{className:"px-1.5 py-0.5 rounded-full",style:{background:g.color+"25",color:g.color,fontSize:j.explorer.count,fontWeight:600,minWidth:"20px",textAlign:"center"},children:ee})]}),q&&Array.from(g.kinds.entries()).map(([ne,se])=>J(ne,se,g.id))]},g.id)}):null})()]},N.id)}),I&&t.jsx(Da,{menu:I,onClose:()=>m(null)})]})]})}function Oa({diagram:e}){const r=["afd","ofd","ffd"].includes(e.diagramType.toLowerCase())?bi(e):e.diagramType,n=Fe[r];return n?t.jsx("span",{className:"px-1.5 py-0.5 rounded font-semibold",style:{background:n.color+"20",color:n.color,fontSize:j.badge},title:n.fullName,children:n.code}):null}function Pa({viewpointId:e,onClose:r}){const n=k(c=>c.createDiagram),[o,s]=u.useState("Untitled"),[i,a]=u.useState("bdd"),l=u.useRef(null);u.useEffect(()=>{const c=p=>{l.current&&!l.current.contains(p.target)&&r()};return document.addEventListener("mousedown",c),()=>document.removeEventListener("mousedown",c)},[r]);const d=()=>{o.trim()&&(n({name:o.trim(),diagramType:i,viewpointId:e}),r())};return t.jsxs("div",{ref:l,className:"fixed z-50 rounded-lg overflow-hidden py-3 px-4",style:{top:"50%",left:"50%",transform:"translate(-50%, -50%)",background:"#FFFFFF",border:"1px solid #E5E7EB",boxShadow:"0 8px 32px rgba(0,0,0,0.16)",minWidth:"300px"},children:[t.jsx("div",{className:"font-semibold mb-3",style:{color:y.primary,fontSize:"13px"},children:"New Diagram"}),t.jsx("label",{className:"block mb-1",style:{fontSize:j.xs,color:y.secondary},children:"Name"}),t.jsx("input",{autoFocus:!0,value:o,onChange:c=>s(c.target.value),onKeyDown:c=>{c.key==="Enter"&&d(),c.key==="Escape"&&r()},className:"w-full px-3 py-2 rounded-lg mb-3 focus:outline-none",style:{background:"#F9F9F8",border:"1px solid #E5E7EB",color:y.primary,fontSize:"13px"}}),t.jsx("label",{className:"block mb-1",style:{fontSize:j.xs,color:y.secondary},children:"Type"}),t.jsx("select",{value:i,onChange:c=>a(c.target.value),className:"w-full px-3 py-2 rounded-lg mb-4 focus:outline-none",style:{background:"#F9F9F8",border:"1px solid #E5E7EB",color:y.primary,fontSize:"13px"},children:Object.entries(Fe).map(([c,p])=>t.jsxs("option",{value:c,children:[p.fullName," (",p.code,")"]},c))}),t.jsxs("div",{className:"flex gap-2 justify-end",children:[t.jsx("button",{onClick:r,className:"px-3 py-1.5 rounded",style:{fontSize:"12px",color:y.secondary,background:"#F0F0ED"},children:"Cancel"}),t.jsx("button",{onClick:d,className:"px-3 py-1.5 rounded font-medium",style:{fontSize:"12px",color:"#FFFFFF",background:y.accent},children:"Create"})]})]})}function za({searchTerm:e}){const r=k(m=>m.model),n=k(m=>m.methodology),o=k(m=>m.activeView),s=k(m=>m.setActiveView),i=k(m=>m.selectViewpoint),a=k(m=>m.deleteDiagram),[l,d]=u.useState(new Set(["__model"])),[c,p]=u.useState(null),f=m=>{d(D=>{const F=new Set(D);return F.has(m)?F.delete(m):F.add(m),F})},h=u.useMemo(()=>(r==null?void 0:r.viewpoints)??[],[r==null?void 0:r.viewpoints]),S=u.useMemo(()=>{if(!n)return[];const m=[];for(const D of n.folders){const F=D.parts.Viewpoint??[];for(const E of F){const R=E.attributes.id,O=E.attributes.name,C=E.attributes.title,B=E.attributes.shortDescription??E.attributes.longDescription;m.push({id:typeof R=="string"?R:E.partName,name:typeof O=="string"?O:E.partName,title:typeof C=="string"?C:typeof O=="string"?O:E.partName,description:typeof B=="string"?B:"",folder:D.name})}}return m},[n]),b=m=>{if(!e)return m;const D=e.toLowerCase();return m.filter(F=>F.name.toLowerCase().includes(D)||F.diagramType.toLowerCase().includes(D))},x=o.type==="diagram"?o.diagramId:null,v=xn(r,"__model"),w=b(v.filter(m=>!m.id.startsWith("diag-layer-"))),T=u.useMemo(()=>{const m=new Map;for(const D of w){const E=[...(D.elementIds??[]).map(R=>{var O;return(O=r==null?void 0:r.elements[R])==null?void 0:O.layer}).filter(R=>!!R)].sort((R,O)=>{const C=rt.indexOf(R),B=rt.indexOf(O);return(C<0?Number.MAX_SAFE_INTEGER:C)-(B<0?Number.MAX_SAFE_INTEGER:B)})[0]??"other";m.set(E,[...m.get(E)??[],D])}return[...m.entries()].sort(([D],[F])=>{const E=rt.indexOf(D),R=rt.indexOf(F);return(E<0?Number.MAX_SAFE_INTEGER:E)-(R<0?Number.MAX_SAFE_INTEGER:R)})},[w,r==null?void 0:r.elements]),I=(m,D)=>m.map(F=>t.jsx(Ba,{diag:F,isSelected:x===F.id,onSelect:()=>{s({type:"diagram",diagramId:F.id}),i(D==="__model"?null:D)},onDelete:F.auto?void 0:()=>a(F.id)},F.id));return t.jsxs("div",{className:"flex-1 overflow-y-auto py-1",style:{fontSize:j.explorer.item},children:[S.length>0&&t.jsxs("div",{style:{marginBottom:"6px",borderBottom:`1px solid ${y.border}`,paddingBottom:"6px"},children:[t.jsx("div",{className:"px-3 py-1",style:{fontSize:"10px",fontWeight:700,textTransform:"uppercase",letterSpacing:"0.08em",color:y.muted},children:"Methodology Viewpoints"}),S.map(m=>{const D=l.has(`mvp::${m.id}`);return t.jsxs("div",{className:"mb-0.5",children:[t.jsxs("div",{className:"flex items-center gap-1.5 px-2 py-1.5 cursor-pointer select-none",style:{borderRadius:"4px",margin:"0 4px"},onMouseEnter:F=>F.currentTarget.style.background="#F0F0ED",onMouseLeave:F=>F.currentTarget.style.background="transparent",onClick:()=>f(`mvp::${m.id}`),title:m.description,children:[t.jsx(xe,{expanded:D,size:14,color:y.accent}),t.jsx(Ae,{open:D,color:y.accent}),t.jsx("span",{className:"font-semibold flex-1 truncate",style:{color:y.primary,fontSize:j.explorer.group},children:m.title}),t.jsx("span",{style:{color:y.faint,fontSize:j.badge,fontFamily:"monospace"},children:m.id})]}),D&&t.jsxs("div",{style:{marginLeft:"24px",padding:"4px 0",fontSize:j.xs,color:y.muted,lineHeight:1.5},children:[m.description||t.jsx("em",{children:"No description."}),t.jsxs("div",{style:{marginTop:"4px",fontSize:"10px",color:y.faint},children:["from ",t.jsx("code",{style:{fontFamily:"monospace"},children:m.folder})," · views & diagrams pending (Phase D2 stub)"]})]})]},`mvp::${m.id}`)})]}),t.jsxs("div",{className:"mb-0.5",children:[t.jsxs("div",{className:"flex items-center gap-1.5 px-2 py-1.5 cursor-pointer select-none",style:{borderRadius:"4px",margin:"0 4px"},onMouseEnter:m=>m.currentTarget.style.background="#F0F0ED",onMouseLeave:m=>m.currentTarget.style.background="transparent",onClick:()=>{i(null),f("__model")},children:[t.jsx(xe,{expanded:l.has("__model"),size:14,color:y.accent}),t.jsx(Ae,{open:l.has("__model"),color:y.accent}),t.jsx("span",{className:"font-semibold flex-1",style:{color:y.primary,fontSize:j.explorer.group},children:"Model Viewpoint"}),t.jsx("span",{style:{color:y.faint,fontSize:j.explorer.count},children:v.length})]}),l.has("__model")&&t.jsxs("div",{style:{marginLeft:"16px"},children:[T.map(([m,D])=>t.jsxs("div",{style:{margin:"5px 4px 2px"},children:[t.jsx("div",{className:"px-2 py-1 font-semibold",style:{color:re[m]??y.muted,fontSize:j.xs,borderLeft:`3px solid ${re[m]??y.border}`},children:Ot[m]??`${m.charAt(0).toUpperCase()}${m.slice(1)}`}),t.jsx("div",{style:{marginLeft:"8px"},children:I(D,"__model")})]},m)),t.jsxs("button",{className:"flex items-center gap-1 px-2 py-1 w-full text-left",style:{borderRadius:"4px",margin:"2px 4px",color:y.accent,fontSize:j.xs,background:"transparent"},onMouseEnter:m=>m.currentTarget.style.background=y.accent+"12",onMouseLeave:m=>m.currentTarget.style.background="transparent",onClick:()=>p("__model"),children:[t.jsx("span",{style:{fontSize:"14px",lineHeight:1},children:"+"})," New Diagram"]})]})]}),h.map(m=>{var O;const D=l.has(m.id),F=(O=m.visibleLayers)!=null&&O[0]&&re[m.visibleLayers[0]]||y.muted,E=xn(r,m.id),R=b(E.filter(C=>!C.id.startsWith("diag-layer-")));return t.jsxs("div",{className:"mb-0.5",children:[t.jsxs("div",{className:"flex items-center gap-1.5 px-2 py-1.5 cursor-pointer select-none",style:{borderRadius:"4px",margin:"0 4px"},onMouseEnter:C=>C.currentTarget.style.background="#F0F0ED",onMouseLeave:C=>C.currentTarget.style.background="transparent",onClick:()=>{i(m.id),f(m.id)},children:[t.jsx(xe,{expanded:D,size:14,color:F}),t.jsx(Ae,{open:D,color:F}),t.jsx("span",{className:"font-semibold flex-1 truncate",style:{color:y.primary,fontSize:j.explorer.group},children:m.label}),t.jsx("span",{style:{color:y.faint,fontSize:j.explorer.count},children:E.length})]}),D&&t.jsxs("div",{style:{marginLeft:"16px"},children:[I(R,m.id),t.jsxs("button",{className:"flex items-center gap-1 px-2 py-1 w-full text-left",style:{borderRadius:"4px",margin:"2px 4px",color:y.accent,fontSize:j.xs,background:"transparent"},onMouseEnter:C=>C.currentTarget.style.background=y.accent+"12",onMouseLeave:C=>C.currentTarget.style.background="transparent",onClick:()=>p(m.id),children:[t.jsx("span",{style:{fontSize:"14px",lineHeight:1},children:"+"})," New Diagram"]})]})]},m.id)}),c!==null&&t.jsx(Pa,{viewpointId:c,onClose:()=>p(null)})]})}function Ba({diag:e,isSelected:r,onSelect:n,onDelete:o}){var d;const[s,i]=u.useState(!1),a=Fe[e.diagramType],l=((d=e.elementIds)==null?void 0:d.length)??0;return t.jsxs("div",{className:"flex items-center gap-2 px-2 py-1 cursor-pointer group",style:{borderRadius:"4px",margin:"0 4px",background:r?y.accent+"18":s?"#F0F0ED":"transparent",fontSize:j.explorer.item},onMouseEnter:()=>i(!0),onMouseLeave:()=>i(!1),onClick:n,title:[a==null?void 0:a.fullName,e.description].filter(Boolean).join(" — "),children:[t.jsx(Oa,{diagram:e}),e.auto&&!e.sourceFile&&t.jsx("span",{className:"px-1 py-0.5 rounded",style:{background:"#F0F0ED",color:y.faint,fontSize:j.badge,fontWeight:600},children:"AUTO"}),t.jsx("span",{className:"truncate flex-1",style:{color:r?y.accentDark:y.primary},children:e.name}),l>0&&t.jsx("span",{className:"px-1.5 py-0.5 rounded-full",style:{background:"#F0F0ED",color:y.muted,fontSize:j.explorer.count,fontWeight:600,minWidth:"18px",textAlign:"center"},children:l}),o&&s&&t.jsx("button",{onClick:c=>{c.stopPropagation(),o()},title:"Delete diagram",style:{background:"none",border:"none",cursor:"pointer",color:"#DC2626",fontSize:"12px",padding:"0 2px",lineHeight:1},children:"×"})]})}function La(){const e=k(m=>m.setActiveView),r=k(m=>m.activeView),n=k(m=>m.dhfDocuments),o=k(m=>m.addDhfDocument),s=k(m=>m.removeDhfDocument),i=k(m=>m.dhfSettings),a=k(m=>m.methodology),l=u.useMemo(()=>{if(!a)return[];const m=[];for(const D of a.folders){const F=D.parts.DhfDocumentBinding??[];for(const E of F){const R=E.attributes,O=R.id,C=R.documentTitle,B=R.groupLabel,P=R.templateId,L=R.viewKind,K=R.regulatoryReference,H=R.required;m.push({id:typeof O=="string"?O:E.partName,partName:E.partName,documentTitle:typeof C=="string"?C:E.partName,groupLabel:typeof B=="string"?B:"",templateId:typeof P=="string"?P:"",viewKind:typeof L=="string"?L:"",regulatoryReference:typeof K=="string"?K:"",required:typeof H=="boolean"?H:!1,folder:D.name})}}return m},[a]),[d,c]=u.useState(new Set(Ce.map(m=>m.id))),[p,f]=u.useState(null),[h,S]=u.useState(null),b=r.type==="dhf-document"?r.docId:null,x=u.useMemo(()=>{const m=new Set(Ce.map(D=>D.label));return[...new Set(n.map(D=>D.group))].filter(D=>D&&!m.has(D)).sort()},[n]);function v(m){c(D=>{const F=new Set(D);return F.has(m)?F.delete(m):F.add(m),F})}function w(m,D){m.preventDefault(),m.stopPropagation(),S({x:m.clientX,y:m.clientY,groupId:D})}function T(m){const D=i.documentNumberingPrefix||"DOC",F=[];for(const E of m){const R=`${D}-${E.prefix}-`,O=[...n,...F].filter(H=>H.id.startsWith(R)),C=`${R}${String(O.length+1).padStart(3,"0")}`,B=H=>H.replace(/^---[\s\S]*?---\n?/,""),P=E.content!==null?B(E.content):(()=>{const H=wa(E.templateId);return H?B(H):`# ${E.title}
|
|
3257
|
-
|
|
3258
|
-
_[TODO: Add content]_
|
|
3259
|
-
`})(),L=`---
|
|
3260
|
-
id: ${C}
|
|
3261
|
-
title: ${E.title}
|
|
3262
|
-
template: ${E.templateId}
|
|
3263
|
-
---
|
|
3264
|
-
|
|
3265
|
-
${P}`,K={id:C,title:E.title,group:E.groupLabel,templateId:E.templateId,content:L,createdAt:Date.now(),authors:"",approvers:""};o(K),F.push(K),F.length===1&&e({type:"dhf-document",docId:K.id})}f(null)}u.useEffect(()=>{if(!h)return;function m(){S(null)}return window.addEventListener("click",m),()=>window.removeEventListener("click",m)},[h]);function I(m){const D=n.find(R=>R.templateId===m.templateId);if(D){e({type:"dhf-document",docId:D.id});return}const F=Ce.find(R=>R.templates.some(O=>O.id===m.templateId)),E=F==null?void 0:F.templates.find(R=>R.id===m.templateId);F&&E&&T([{title:E.title,prefix:E.prefix,templateId:E.id,groupLabel:F.label,content:null}])}return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"flex-1 overflow-y-auto py-1",children:[t.jsx("div",{style:{padding:"4px 10px 8px"},children:t.jsxs("button",{onClick:()=>f({}),style:{width:"100%",padding:"7px 10px",borderRadius:"6px",border:"none",background:y.accentDark,fontSize:j.explorer.item,fontWeight:600,color:"#fff",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",gap:"6px"},onMouseEnter:m=>{m.currentTarget.style.background="#254B60"},onMouseLeave:m=>{m.currentTarget.style.background=y.accentDark},children:[t.jsx("span",{style:{fontSize:"14px",lineHeight:1},children:"+"})," New Document"]})}),l.length>0&&t.jsxs("div",{style:{marginBottom:"6px",borderBottom:`1px solid ${y.border}`,paddingBottom:"6px"},children:[t.jsx("div",{className:"px-3 py-1",style:{fontSize:"10px",fontWeight:700,textTransform:"uppercase",letterSpacing:"0.08em",color:y.muted},children:"Methodology DHF"}),l.map(m=>{const D=n.find(R=>R.templateId===m.templateId),F=D!=null&&b===D.id,E=Ce.some(R=>R.templates.some(O=>O.id===m.templateId));return t.jsxs("div",{onClick:()=>I(m),style:{display:"flex",alignItems:"center",gap:"6px",padding:"5px 12px",cursor:E?"pointer":"default",background:F?"#EEF2FF":"transparent",borderLeft:F?"2px solid #6366F1":"2px solid transparent"},title:`${m.regulatoryReference||""} · template: ${m.templateId}${E?"":" (unknown — no built-in template)"}`,onMouseEnter:R=>{!F&&E&&(R.currentTarget.style.background=y.surfaceAlt)},onMouseLeave:R=>{R.currentTarget.style.background=F?"#EEF2FF":"transparent"},children:[t.jsx("span",{style:{fontSize:"9px",fontFamily:"monospace",color:m.required?"#DC2626":y.faint,fontWeight:700},children:m.id}),t.jsx("span",{style:{flex:1,fontSize:j.explorer.element,color:y.primary,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:m.documentTitle}),D?t.jsx("span",{style:{fontSize:"9px",color:"#059669",fontWeight:700},children:"✓"}):t.jsx("span",{style:{fontSize:"9px",color:y.faint},children:"+"})]},`mdhf::${m.id}`)})]}),Ce.filter(m=>n.some(D=>D.group===m.label)).map(m=>{const D=d.has(m.id),F=n.filter(E=>E.group===m.label);return t.jsxs("div",{children:[t.jsxs("button",{onClick:()=>v(m.id),onContextMenu:E=>w(E,m.id),className:"w-full flex items-center gap-2 px-3 py-2 text-left",style:{fontSize:j.xs,fontWeight:600,color:y.secondary,borderRadius:"4px"},onMouseEnter:E=>E.currentTarget.style.background=y.surfaceAlt,onMouseLeave:E=>E.currentTarget.style.background="transparent",title:"Right-click to add documents",children:[t.jsx("span",{style:{display:"inline-block",width:"7px",height:"7px",borderRadius:"50%",background:m.color,flexShrink:0}}),t.jsx("span",{className:"flex-1 uppercase tracking-wide",style:{fontSize:"10px"},children:m.label}),F.length>0&&t.jsx("span",{style:{fontSize:"10px",color:m.color,fontWeight:700},children:F.length}),t.jsx(xe,{expanded:D,size:11})]}),D&&F.map(E=>{const R=b===E.id;return t.jsxs("div",{style:{display:"flex",alignItems:"center",paddingLeft:"28px",paddingRight:"4px",background:R?`${m.color}18`:"transparent",borderLeft:R?`2px solid ${m.color}`:"2px solid transparent",cursor:"pointer"},onMouseEnter:O=>{R||(O.currentTarget.style.background=y.surfaceAlt)},onMouseLeave:O=>{O.currentTarget.style.background=R?`${m.color}18`:"transparent"},children:[t.jsxs("button",{onClick:()=>e({type:"dhf-document",docId:E.id}),style:{flex:1,display:"flex",alignItems:"center",gap:"6px",background:"none",border:"none",padding:"5px 0",fontSize:j.explorer.element,color:R?m.color:y.primary,fontWeight:R?600:400,cursor:"pointer",textAlign:"left"},children:[t.jsx(zt,{color:m.color}),t.jsx("span",{style:{flex:1,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:E.id})]}),t.jsx("button",{onClick:O=>{O.stopPropagation(),s(E.id)},title:"Remove document",style:{background:"none",border:"none",cursor:"pointer",color:"#9CA3AF",padding:"2px 4px",borderRadius:"3px",fontSize:"12px",opacity:0,transition:"opacity 0.1s"},onMouseEnter:O=>{O.currentTarget.style.opacity="1",O.currentTarget.style.color="#ef4444"},onMouseLeave:O=>{O.currentTarget.style.opacity="0",O.currentTarget.style.color="#9CA3AF"},children:"×"})]},E.id)})]},m.id)}),x.map(m=>{const D=`custom:${m}`,F=d.has(D),E=ka(m),R=n.filter(O=>O.group===m);return t.jsxs("div",{children:[t.jsxs("button",{onClick:()=>v(D),className:"w-full flex items-center gap-2 px-3 py-2 text-left",style:{fontSize:j.xs,fontWeight:600,color:y.secondary,borderRadius:"4px"},onMouseEnter:O=>O.currentTarget.style.background=y.surfaceAlt,onMouseLeave:O=>O.currentTarget.style.background="transparent",children:[t.jsx("span",{style:{display:"inline-block",width:"7px",height:"7px",borderRadius:"50%",background:E,flexShrink:0}}),t.jsx("span",{className:"flex-1 uppercase tracking-wide",style:{fontSize:"10px"},children:m}),t.jsx("span",{style:{fontSize:"10px",color:E,fontWeight:700},children:R.length}),t.jsx(xe,{expanded:F,size:11})]}),F&&R.map(O=>{const C=b===O.id;return t.jsxs("div",{style:{display:"flex",alignItems:"center",paddingLeft:"28px",paddingRight:"4px",background:C?`${E}18`:"transparent",borderLeft:C?`2px solid ${E}`:"2px solid transparent",cursor:"pointer"},onMouseEnter:B=>{C||(B.currentTarget.style.background=y.surfaceAlt)},onMouseLeave:B=>{B.currentTarget.style.background=C?`${E}18`:"transparent"},children:[t.jsxs("button",{onClick:()=>e({type:"dhf-document",docId:O.id}),style:{flex:1,display:"flex",alignItems:"center",gap:"6px",background:"none",border:"none",padding:"5px 0",fontSize:j.explorer.element,color:C?E:y.primary,fontWeight:C?600:400,cursor:"pointer",textAlign:"left"},children:[t.jsx(zt,{color:E}),t.jsx("span",{style:{flex:1,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:O.id})]}),t.jsx("button",{onClick:B=>{B.stopPropagation(),s(O.id)},title:"Remove document",style:{background:"none",border:"none",cursor:"pointer",color:"#9CA3AF",padding:"2px 4px",borderRadius:"3px",fontSize:"12px",opacity:0,transition:"opacity 0.1s"},onMouseEnter:B=>{B.currentTarget.style.opacity="1",B.currentTarget.style.color="#ef4444"},onMouseLeave:B=>{B.currentTarget.style.opacity="0",B.currentTarget.style.color="#9CA3AF"},children:"×"})]},O.id)})]},D)}),n.length===0&&t.jsxs("div",{style:{padding:"16px 14px",fontSize:"11px",color:"#9CA3AF",lineHeight:"1.6"},children:["No documents yet. Use ",t.jsx("strong",{children:"+ New Document"})," to create one from a meMO template, a blank page, or a markdown file in this repository."]}),t.jsxs("div",{style:{margin:"8px 10px 6px",padding:"8px",background:"#F0FDF9",borderRadius:"8px",border:"1px solid #A7F3D0"},children:[t.jsxs("div",{style:{fontSize:"10px",fontWeight:700,color:"#065F46",textTransform:"uppercase",letterSpacing:"0.06em",marginBottom:"6px",display:"flex",alignItems:"center",gap:"4px"},children:[t.jsx("span",{children:"✦"})," AI Tools"]}),t.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"3px"},children:[t.jsx(Fn,{label:"Model Q&A",description:"Ask questions about your model",active:r.type==="ask",onClick:()=>e({type:"ask"})}),t.jsx(Fn,{label:"SysML Generator",description:"Natural language → SysML v2",active:r.type==="sysml-generator",onClick:()=>e({type:"sysml-generator"})})]})]})]}),h&&t.jsx("div",{style:{position:"fixed",zIndex:9998,left:h.x,top:h.y,background:"#fff",borderRadius:"8px",border:"1px solid #E5E7EB",boxShadow:"0 8px 24px rgba(0,0,0,0.12)",padding:"4px 0",minWidth:"160px"},onClick:m=>m.stopPropagation(),children:t.jsx("button",{onClick:()=>{f({initialGroupId:h.groupId}),S(null)},style:{display:"block",width:"100%",padding:"8px 14px",background:"none",border:"none",textAlign:"left",fontSize:"13px",color:"#1B3A4B",cursor:"pointer"},onMouseEnter:m=>m.currentTarget.style.background="#F3F4F6",onMouseLeave:m=>m.currentTarget.style.background="none",children:"Add document…"})}),p&&t.jsx(ja,{initialGroupId:p.initialGroupId,existingDocs:n,numberingPrefix:i.documentNumberingPrefix||"DOC",onCreate:T,onClose:()=>f(null)})]})}function Fn({label:e,description:r,active:n,onClick:o}){return t.jsxs("button",{onClick:o,style:{display:"flex",flexDirection:"column",width:"100%",padding:"5px 8px",borderRadius:"5px",border:"none",textAlign:"left",cursor:"pointer",background:n?"#D1FAE5":"rgba(255,255,255,0.7)",transition:"background 0.1s"},onMouseEnter:s=>{n||(s.currentTarget.style.background="rgba(255,255,255,0.95)")},onMouseLeave:s=>{n||(s.currentTarget.style.background="rgba(255,255,255,0.7)")},children:[t.jsx("span",{style:{fontSize:"12px",fontWeight:600,color:"#065F46"},children:e}),t.jsx("span",{style:{fontSize:"10px",color:"#6B7280",marginTop:"1px"},children:r})]})}function qa(){const e=k(a=>a.sidebarCollapsed);k(a=>a.explorerTab);const r=k(a=>a.setExplorerTab),n=k(a=>a.searchTerm),o=k(a=>a.setSearchTerm);k(a=>a.model);const s=k(a=>a.activeMode),i=k(a=>a.activeView);return u.useEffect(()=>{(i.type==="ontology"||i.type==="ontology-detail")&&r("ontologies")},[i.type]),e?null:t.jsx("div",{className:"flex flex-col overflow-hidden flex-shrink-0",style:{width:"300px",background:y.surface,borderRight:`1px solid ${y.border}`},children:s==="dashboard"?t.jsx(Ai,{}):s==="dhf"?t.jsx(La,{}):s==="diagram"?t.jsxs(t.Fragment,{children:[t.jsx("div",{className:"px-3 py-2",style:{borderBottom:`1px solid ${y.border}`},children:t.jsx("input",{type:"text",placeholder:"Search diagrams...",value:n,onChange:a=>o(a.target.value),className:"w-full px-3 py-2 rounded-lg focus:outline-none",style:{background:y.surfaceAlt,border:`1px solid ${y.border}`,color:y.primary,fontSize:j.explorer.search}})}),t.jsx(za,{searchTerm:n})]}):s==="ontology"?t.jsx(Di,{}):s==="scenario"?t.jsxs(t.Fragment,{children:[t.jsx("div",{className:"px-3 py-2",style:{borderBottom:`1px solid ${y.border}`},children:t.jsx("input",{type:"text",placeholder:"Search elements...",value:n,onChange:a=>o(a.target.value),className:"w-full px-3 py-2 rounded-lg focus:outline-none",style:{background:y.surfaceAlt,border:`1px solid ${y.border}`,color:y.primary,fontSize:j.explorer.search}})}),t.jsx(An,{searchTerm:n})]}):t.jsxs(t.Fragment,{children:[t.jsx("div",{className:"px-3 py-2",style:{borderBottom:`1px solid ${y.border}`},children:t.jsx("input",{type:"text",placeholder:"Search elements...",value:n,onChange:a=>o(a.target.value),className:"w-full px-3 py-2 rounded-lg focus:outline-none",style:{background:y.surfaceAlt,border:`1px solid ${y.border}`,color:y.primary,fontSize:j.explorer.search}})}),t.jsx(An,{searchTerm:n})]})})}const Va="#FFFFFF",_e="#E5E5E0",Ar="#2DD4A8";function $a({element:e,model:r,registries:n,onCancel:o,onConfirm:s}){const[i,a]=u.useState("relationship-first"),[l,d]=u.useState(null),[c,p]=u.useState(null),[f,h]=u.useState(null),[S,b]=u.useState(""),[x,v]=u.useState(""),[w,T]=u.useState(""),[I,m]=u.useState("");u.useEffect(()=>{const M=A=>{A.key==="Escape"&&o()};return document.addEventListener("keydown",M),()=>document.removeEventListener("keydown",M)},[o]);const D=u.useMemo(()=>vs(e,n),[e,n]),F=u.useMemo(()=>l?D.filter(M=>M.directions.includes(l)).map(M=>M.definition):[],[D,l]),E=u.useMemo(()=>{const M=new Set;for(const A of D)for(const V of A.directions)M.add(V);return Array.from(M)},[D]),R=u.useMemo(()=>F.find(M=>M.name===c)??n.relationships.find(M=>M.name===c),[F,n,c]),O=u.useMemo(()=>!R||!l?[]:ws(e,R,l,r,n,{query:S,kind:x||void 0,layer:w||void 0,package:I||void 0}),[R,l,e,r,n,S,x,w,I]),C=u.useMemo(()=>ks(O),[O]),B=u.useMemo(()=>{const M=S.trim().toLowerCase();return Object.values(r.elements).filter(A=>A.id!==e.id).filter(A=>!x||A.kind===x).filter(A=>!w||A.layer===w).filter(A=>!I||A.package===I).filter(A=>!M||[A.name,A.id,A.shortId,A.kind].filter(Boolean).join(" ").toLowerCase().includes(M)).sort((A,V)=>A.name.localeCompare(V.name)).slice(0,200)},[r,e.id,S,x,w,I]),P=f?r.elements[f]:void 0,L=u.useMemo(()=>P?gr(e,P,n):[],[e,P,n]);u.useEffect(()=>{i!=="target-first"||!P||(L.length===1?(p(L[0].definition.name),d(L[0].direction)):(p(null),d(null)))},[i,P,L]);const K=u.useMemo(()=>!R||!l||!f?null:l==="outgoing"?{type:R.name,sourceId:e.id,targetId:f,direction:l}:{type:R.name,sourceId:f,targetId:e.id,direction:l},[R,l,f,e.id]),H=u.useMemo(()=>!K||!R?null:Ss(R,r.elements[K.sourceId],r.elements[K.targetId],{sourceId:K.sourceId,targetId:K.targetId}),[K,R,r]),N=u.useCallback(M=>{a(M),d(null),p(null),h(null),b("")},[]),W=u.useMemo(()=>Array.from(new Set(Object.values(r.elements).map(M=>M.kind))).sort(),[r]),X=u.useMemo(()=>Array.from(new Set(Object.values(r.elements).map(M=>M.layer))).sort(),[r]),U=u.useMemo(()=>Array.from(new Set(Object.values(r.elements).map(M=>M.package).filter(M=>!!M))).sort(),[r]);return t.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center",style:{background:"rgba(15,23,42,0.35)"},onClick:o,role:"dialog","aria-modal":"true","aria-label":"Add relationship",children:t.jsxs("div",{className:"flex flex-col rounded-xl overflow-hidden",style:{width:560,maxHeight:"80vh",background:Va,border:`1px solid ${_e}`,boxShadow:"0 16px 48px rgba(0,0,0,0.22)"},onClick:M=>M.stopPropagation(),children:[t.jsxs("div",{className:"px-4 py-3",style:{borderBottom:`1px solid ${_e}`},children:[t.jsx("div",{className:"text-sm font-semibold",style:{color:"#1a1a1a"},children:"Add Relationship"}),t.jsxs("div",{className:"text-xs mt-0.5",style:{color:"#6B7280"},children:["from ",t.jsx("span",{style:{fontWeight:500,color:"#374151"},children:e.name})," ",t.jsxs("span",{style:{color:"#9CA3AF"},children:["(",e.kind,")"]})]}),t.jsxs("div",{className:"flex gap-1 mt-2",children:[t.jsx(Rn,{active:i==="relationship-first",label:"Choose relationship",onClick:()=>N("relationship-first")}),t.jsx(Rn,{active:i==="target-first",label:"Choose element",onClick:()=>N("target-first")})]})]}),t.jsx("div",{className:"flex-1 overflow-y-auto px-4 py-3",children:i==="relationship-first"?t.jsxs(t.Fragment,{children:[t.jsx(qe,{children:"Direction"}),E.length===0?t.jsxs(Ve,{children:["The ontology defines no relationship that a ",e.kind," can take part in."]}):t.jsxs("div",{className:"flex gap-2 mb-3",children:[E.includes("outgoing")&&t.jsx(Tn,{active:l==="outgoing",onClick:()=>{d("outgoing"),p(null),h(null)},title:"Outgoing",subtitle:`${e.name} → other`}),E.includes("incoming")&&t.jsx(Tn,{active:l==="incoming",onClick:()=>{d("incoming"),p(null),h(null)},title:"Incoming",subtitle:`other → ${e.name}`})]}),l&&t.jsxs(t.Fragment,{children:[t.jsx(qe,{children:"Relationship type"}),F.length===0?t.jsxs(Ve,{children:["No relationship type allows a ",e.kind," on that end."]}):t.jsx("div",{className:"mb-3",style:{maxHeight:160,overflowY:"auto"},children:F.map(M=>t.jsx(In,{definition:M,direction:l,selected:c===M.name,onClick:()=>{p(M.name),h(null)}},M.name))})]}),R&&l&&t.jsxs(t.Fragment,{children:[t.jsx(qe,{children:l==="outgoing"?`${R.targetEnd.name} element`:`${R.sourceEnd.name} element`}),t.jsx(Nn,{query:S,setQuery:b,kinds:W,kindFilter:x,setKindFilter:v,layers:X,layerFilter:w,setLayerFilter:T,packages:U,packageFilter:I,setPackageFilter:m}),O.length===0?t.jsx(Ve,{children:"No element in the model can occupy that end."}):t.jsx("div",{style:{maxHeight:220,overflowY:"auto"},children:C.map(M=>t.jsxs("div",{children:[t.jsx(Ua,{layer:M.layer,kind:M.kind,count:M.elements.length}),M.elements.map(A=>t.jsx(_n,{element:A,selected:f===A.id,onClick:()=>h(A.id)},A.id))]},`${M.layer}-${M.kind}`))})]})]}):t.jsxs(t.Fragment,{children:[t.jsx(qe,{children:"Element to link"}),t.jsx(Nn,{query:S,setQuery:b,kinds:W,kindFilter:x,setKindFilter:v,layers:X,layerFilter:w,setLayerFilter:T,packages:U,packageFilter:I,setPackageFilter:m}),t.jsxs("div",{style:{maxHeight:200,overflowY:"auto"},children:[B.map(M=>t.jsx(_n,{element:M,selected:f===M.id,onClick:()=>h(M.id)},M.id)),B.length===0&&t.jsx(Ve,{children:"No element matches that search."})]}),P&&t.jsxs(t.Fragment,{children:[t.jsx(qe,{children:"Legal relationships"}),L.length===0?t.jsxs(Ve,{children:["The ontology defines no relationship between a ",e.kind," and a ",P.kind,"."]}):t.jsx("div",{style:{maxHeight:160,overflowY:"auto"},children:L.map(M=>t.jsx(In,{definition:M.definition,direction:M.direction,selected:c===M.definition.name&&l===M.direction,onClick:()=>{p(M.definition.name),d(M.direction)}},`${M.definition.name}-${M.direction}`))})]})]})}),t.jsxs("div",{className:"px-4 py-3",style:{borderTop:`1px solid ${_e}`,background:"#FAFAF8"},children:[H?t.jsx("div",{className:"text-xs mb-2 px-2 py-1.5 rounded",style:{background:"#F0FDF9",color:"#0F766E",border:"1px solid #99F6E4"},children:H}):t.jsx("div",{className:"text-xs mb-2",style:{color:"#9CA3AF"},children:"Choose a relationship type and an element to see the preview."}),t.jsxs("div",{className:"flex justify-end gap-2",children:[t.jsx("button",{onClick:o,className:"px-3 py-1.5 rounded text-xs font-medium",style:{background:"#F0F0ED",color:"#374151",border:"none",cursor:"pointer"},children:"Cancel"}),t.jsx("button",{onClick:()=>K&&s(K),disabled:!K,className:"px-3 py-1.5 rounded text-xs font-medium",style:{background:K?Ar:"#E5E5E0",color:K?"#FFFFFF":"#9CA3AF",border:"none",cursor:K?"pointer":"not-allowed"},children:"Create relationship"})]})]})]})})}function Rn({active:e,label:r,onClick:n}){return t.jsx("button",{onClick:n,className:"px-2 py-1 rounded",style:{fontSize:j.xs,fontWeight:e?600:400,background:e?"#2DD4A818":"transparent",color:e?"#0F766E":"#6B7280",border:"none",cursor:"pointer"},children:r})}function qe({children:e}){return t.jsx("div",{className:"mb-1.5",style:{fontSize:"10px",fontWeight:600,color:"#6B7280",textTransform:"uppercase",letterSpacing:"0.04em"},children:e})}function Ve({children:e}){return t.jsx("div",{className:"text-xs py-2 mb-2",style:{color:"#9CA3AF"},children:e})}function Tn({active:e,onClick:r,title:n,subtitle:o}){return t.jsxs("button",{onClick:r,className:"flex-1 px-2 py-1.5 rounded text-left",style:{background:e?"#2DD4A818":"#F7F7F5",border:`1px solid ${e?Ar:_e}`,cursor:"pointer"},children:[t.jsx("div",{style:{fontSize:j.xs,fontWeight:500,color:"#1a1a1a"},children:n}),t.jsx("div",{style:{fontSize:"10px",color:"#9CA3AF"},children:o})]})}function In({definition:e,direction:r,selected:n,onClick:o}){const s=r==="outgoing"?e.targetEnd:e.sourceEnd,i=mr(e);return t.jsxs("button",{onClick:o,className:"w-full text-left px-2 py-1.5 rounded",style:{background:n?"#2DD4A818":"transparent",border:"none",cursor:"pointer",display:"block"},onMouseEnter:a=>{n||(a.currentTarget.style.background="#F7F7F5")},onMouseLeave:a=>{n||(a.currentTarget.style.background="transparent")},children:[t.jsxs("div",{className:"flex items-center gap-1.5",children:[t.jsx("span",{style:{fontSize:j.xs,fontWeight:500,color:"#1a1a1a"},children:e.label}),t.jsx("span",{style:{fontSize:"9px",color:"#9CA3AF"},children:r==="outgoing"?"→":"←"}),t.jsx("span",{style:{fontSize:"10px",color:"#6B7280"},children:s.type??"any element"}),i&&t.jsx("span",{className:"px-1 rounded",style:{fontSize:"9px",background:"#FEF3C7",color:"#92400E"},title:"Joins any two elements. Prefer a relation that carries the meaning.",children:"fallback"})]}),e.description&&t.jsx("div",{style:{fontSize:"10px",color:"#9CA3AF"},className:"truncate",children:e.description})]})}function Ua({layer:e,kind:r,count:n}){const o=re[e]||"#666";return t.jsxs("div",{className:"flex items-center gap-1.5 px-1 pt-2 pb-1",children:[t.jsx("span",{className:"w-2 h-2 flex-shrink-0",style:{background:o,borderRadius:"2px"}}),t.jsx("span",{style:{fontSize:"10px",fontWeight:600,color:"#6B7280"},children:r}),t.jsxs("span",{style:{fontSize:"10px",color:"#9CA3AF"},children:["· ",e]}),t.jsx("span",{className:"ml-auto",style:{fontSize:"10px",color:"#D1D5DB"},children:n})]})}function _n({element:e,selected:r,onClick:n}){const o=re[e.layer]||"#666";return t.jsxs("button",{onClick:n,className:"w-full flex items-center gap-1.5 px-2 py-1 rounded text-left",style:{background:r?"#2DD4A818":"transparent",border:"none",cursor:"pointer"},onMouseEnter:s=>{r||(s.currentTarget.style.background="#F7F7F5")},onMouseLeave:s=>{r||(s.currentTarget.style.background="transparent")},children:[t.jsx("span",{className:"truncate",style:{fontSize:j.xs,color:"#1a1a1a"},children:e.name}),t.jsx("span",{className:"ml-auto flex-shrink-0 px-1 rounded",style:{background:o+"15",color:o,fontSize:j.badge},children:e.kind})]})}function Nn({query:e,setQuery:r,kinds:n,kindFilter:o,setKindFilter:s,layers:i,layerFilter:a,setLayerFilter:l,packages:d,packageFilter:c,setPackageFilter:p}){const f={fontSize:"10px",background:"#F7F7F5",border:`1px solid ${_e}`,color:"#374151",borderRadius:4,padding:"2px 4px",flex:1,minWidth:0};return t.jsxs("div",{className:"mb-2",children:[t.jsx("input",{value:e,onChange:h=>r(h.target.value),placeholder:"Search by name, ID or kind…","aria-label":"Search elements",className:"w-full px-2 py-1 rounded focus:outline-none mb-1.5",style:{fontSize:j.xs,background:"#F7F7F5",border:`1px solid ${_e}`,color:"#374151"}}),t.jsxs("div",{className:"flex gap-1",children:[t.jsxs("select",{"aria-label":"Filter by kind",value:o,onChange:h=>s(h.target.value),style:f,children:[t.jsx("option",{value:"",children:"All kinds"}),n.map(h=>t.jsx("option",{value:h,children:h},h))]}),t.jsxs("select",{"aria-label":"Filter by layer",value:a,onChange:h=>l(h.target.value),style:f,children:[t.jsx("option",{value:"",children:"All layers"}),i.map(h=>t.jsx("option",{value:h,children:h},h))]}),t.jsxs("select",{"aria-label":"Filter by package",value:c,onChange:h=>p(h.target.value),style:f,children:[t.jsx("option",{value:"",children:"All packages"}),d.map(h=>t.jsx("option",{value:h,children:h},h))]})]})]})}const Mn="#E5E5E0",On="#2DD4A8",Bt=40;function Pn(e,r){var i;const n=e.id.toLowerCase(),o=((i=e.shortId)==null?void 0:i.toLowerCase())??"",s=e.name.toLowerCase();return n===r||o===r?0:n.startsWith(r)||o.startsWith(r)?1:s.startsWith(r)?2:n.includes(r)||s.includes(r)?3:4}function Wa(e,r){const n=r.query.trim().toLowerCase();return n?Object.values(e).filter(o=>o.id!==r.excludeId).filter(o=>[o.id,o.shortId,o.name,o.kind].filter(Boolean).join(" ").toLowerCase().includes(n)).sort((o,s)=>Pn(o,n)-Pn(s,n)||o.name.localeCompare(s.name)).slice(0,r.limit??Bt):[]}function Ha(e){const r=new Map;for(const n of e){let o=r.get(n.kind);o||(o={kind:n.kind,layer:n.layer,elements:[]},r.set(n.kind,o)),o.elements.push(n)}return[...r.values()]}function Ka({element:e,model:r,registries:n,enabled:o,onCreate:s,onOpenFullDialog:i}){var B;const[a,l]=u.useState(""),[d,c]=u.useState(!1),[p,f]=u.useState(0),[h,S]=u.useState(null),[b,x]=u.useState(null),v=u.useRef(null),w=u.useRef(null);u.useEffect(()=>{l(""),S(null),x(null),c(!1),f(0)},[e.id]);const T=u.useMemo(()=>Wa(r.elements,{query:a,excludeId:e.id}),[r.elements,e.id,a]),I=u.useMemo(()=>Ha(T),[T]),m=u.useMemo(()=>I.flatMap(P=>P.elements),[I]);u.useEffect(()=>{f(0)},[a]),u.useEffect(()=>{var P,L;d&&((L=(P=w.current)==null?void 0:P.querySelector('[data-active="true"]'))==null||L.scrollIntoView({block:"nearest"}))},[p,d]);const D=u.useCallback(P=>{S(P),l(P.name||P.id),c(!1),x(null)},[]),F=u.useCallback(()=>{l(""),S(null),x(null),c(!1)},[]),E=u.useMemo(()=>h?gr(e,h,n):[],[e,h,n]);u.useEffect(()=>{x(E.length===1?E[0]:null)},[E]);const R=u.useMemo(()=>!b||!h?null:{type:b.definition.name,sourceId:b.sourceId,targetId:b.targetId,direction:b.direction},[b,h]),O=u.useCallback(P=>{if(P.key==="Escape"){if(d){c(!1);return}F();return}if(!d||m.length===0){P.key==="ArrowDown"&&m.length>0&&(P.preventDefault(),c(!0));return}if(P.key==="ArrowDown")P.preventDefault(),f(L=>(L+1)%m.length);else if(P.key==="ArrowUp")P.preventDefault(),f(L=>(L-1+m.length)%m.length);else if(P.key==="Enter"){P.preventDefault();const L=m[p];L&&D(L)}},[d,m,p,D,F]),C=(B=m[p])==null?void 0:B.id;return t.jsxs("div",{className:"mt-1.5",style:{opacity:o?1:.6},children:[t.jsxs("div",{className:"relative",children:[t.jsx("input",{ref:v,value:a,disabled:!o,onChange:P=>{l(P.target.value),S(null),x(null),c(!0)},onFocus:()=>{a.trim()&&!h&&c(!0)},onBlur:()=>{window.setTimeout(()=>c(!1),120)},onKeyDown:O,placeholder:o?"Link to… type an element ID or name":"Connect to the dev server to author relationships","aria-label":"Link this element to another","aria-expanded":d,"aria-controls":"memo-quick-add-matches","aria-activedescendant":d&&C?`memo-quick-add-${C}`:void 0,role:"combobox",autoComplete:"off",className:"w-full px-2 py-1 rounded focus:outline-none",style:{fontSize:j.xs,background:"#FFFFFF",border:`1px solid ${h?On:Mn}`,color:"#374151"}}),d&&a.trim()&&t.jsxs("div",{id:"memo-quick-add-matches",ref:w,role:"listbox",className:"absolute left-0 right-0 z-20 mt-1 rounded overflow-y-auto",style:{maxHeight:240,background:"#FFFFFF",border:`1px solid ${Mn}`,boxShadow:"0 8px 24px rgba(15,23,42,0.14)"},children:[m.length===0?t.jsxs("div",{className:"px-2 py-2",style:{fontSize:j.xs,color:"#9CA3AF"},children:["No element matches “",a.trim(),"”."]}):I.map(P=>t.jsxs("div",{children:[t.jsx(Ya,{kind:P.kind,layer:P.layer,count:P.elements.length}),P.elements.map(L=>t.jsx(Ja,{element:L,active:L.id===C,onSelect:()=>D(L)},L.id))]},P.kind)),T.length===Bt&&t.jsxs("div",{className:"px-2 py-1",style:{fontSize:"10px",color:"#9CA3AF"},children:["Showing the first ",Bt," matches — keep typing to narrow, or"," ",t.jsx("button",{onMouseDown:P=>{P.preventDefault(),i()},style:{background:"none",border:"none",padding:0,color:"#2563EB",cursor:"pointer",fontSize:"10px"},children:"filter in the full dialog"}),"."]})]})]}),h&&t.jsx(Ga,{element:e,target:h,options:E,selected:b,registries:n,onSelect:x}),h&&t.jsxs("div",{className:"flex items-center gap-1.5 mt-1.5",children:[t.jsx("button",{onClick:()=>{R&&(s(R),F())},disabled:!R||!o,className:"px-2 py-0.5 rounded",style:{fontSize:j.xs,fontWeight:600,border:"none",background:R&&o?On:"#E5E5E0",color:R&&o?"#FFFFFF":"#9CA3AF",cursor:R&&o?"pointer":"not-allowed"},children:"Create link"}),t.jsx("button",{onClick:F,className:"px-2 py-0.5 rounded",style:{fontSize:j.xs,background:"#F0F0ED",color:"#374151",border:"none",cursor:"pointer"},children:"Cancel"})]})]})}function Ga({element:e,target:r,options:n,selected:o,registries:s,onSelect:i}){const a=s.relationships.filter(l=>!l.isAbstract&&!n.some(d=>d.definition.name===l.name)).length;return n.length===0?t.jsx("div",{className:"mt-1.5 px-2 py-1.5 rounded",style:{background:"#FFFBEB",border:"1px solid #FDE68A"},children:t.jsxs("div",{style:{fontSize:j.xs,color:"#92400E"},children:["The ontology defines no relationship between a ",e.kind," and a ",r.kind,"."]})}):t.jsxs("div",{className:"mt-1.5",children:[t.jsx("div",{className:"mb-1",style:{fontSize:"10px",fontWeight:600,color:"#6B7280",textTransform:"uppercase",letterSpacing:"0.04em"},children:"Relationship"}),t.jsx("div",{style:{maxHeight:160,overflowY:"auto"},children:n.map(l=>{const d=(o==null?void 0:o.definition.name)===l.definition.name&&(o==null?void 0:o.direction)===l.direction,c=mr(l.definition);return t.jsxs("button",{onClick:()=>i(l),className:"w-full text-left px-2 py-1 rounded",style:{background:d?"#2DD4A818":"transparent",border:"none",cursor:"pointer",display:"block"},onMouseEnter:p=>{d||(p.currentTarget.style.background="#F7F7F5")},onMouseLeave:p=>{d||(p.currentTarget.style.background="transparent")},children:[t.jsxs("div",{className:"flex items-center gap-1.5",children:[t.jsx("span",{style:{fontSize:j.xs,fontWeight:500,color:"#1a1a1a"},children:l.definition.label}),c&&t.jsx("span",{className:"px-1 rounded",style:{fontSize:"9px",background:"#FEF3C7",color:"#92400E"},title:"Joins any two elements. Prefer a relation that carries the meaning.",children:"fallback"})]}),t.jsx("div",{className:"truncate",style:{fontSize:"10px",color:"#9CA3AF"},children:l.direction==="outgoing"?`${e.name} → ${r.name}`:`${r.name} → ${e.name}`})]},`${l.definition.name}-${l.direction}`)})}),a>0&&t.jsxs("div",{className:"mt-0.5",style:{fontSize:"10px",color:"#9CA3AF"},children:[a," other relationship type",a>1?"s are":" is"," defined but cannot join a ",e.kind," and a ",r.kind,"."]})]})}function Ya({kind:e,layer:r,count:n}){const o=re[r]||"#666";return t.jsxs("div",{className:"flex items-center gap-1.5 px-2 py-1",style:{background:"#FAFAF8",borderBottom:"1px solid #F0F0ED",position:"sticky",top:0},children:[t.jsx("span",{className:"w-2 h-2 flex-shrink-0",style:{background:o,borderRadius:2}}),t.jsx("span",{style:{fontSize:"10px",fontWeight:600,color:"#6B7280"},children:e}),t.jsx("span",{className:"ml-auto",style:{fontSize:"10px",color:"#D1D5DB"},children:n})]})}function Ja({element:e,active:r,onSelect:n}){return t.jsxs("div",{id:`memo-quick-add-${e.id}`,role:"option","aria-selected":r,"data-active":r,onMouseDown:o=>{o.preventDefault(),n()},className:"flex items-center gap-1.5 px-2 py-1 cursor-pointer",style:{background:r?"#2DD4A818":"transparent"},children:[t.jsx("span",{className:"truncate",style:{fontSize:j.xs,color:"#1a1a1a"},children:e.name||e.id}),t.jsx("span",{className:"ml-auto flex-shrink-0 font-mono truncate",style:{fontSize:"10px",color:"#9CA3AF",maxWidth:110},title:e.id,children:e.shortId??e.id})]})}function zn({value:e,onSave:r,multiline:n,forceEdit:o}){const[s,i]=u.useState(!1),[a,l]=u.useState(e);u.useEffect(()=>{l(e)},[e]);const d=u.useCallback(()=>{i(!1),a!==e&&r(a)},[a,e,r]),c=u.useCallback(p=>{p.key==="Enter"&&!n&&d(),p.key==="Escape"&&(l(e),i(!1))},[d,n,e]);return!s&&!o?t.jsx("span",{className:"cursor-pointer rounded px-1 py-0.5 transition-colors",style:{color:"#1a1a1a"},onMouseEnter:p=>p.currentTarget.style.background="#F0F0ED",onMouseLeave:p=>p.currentTarget.style.background="transparent",onClick:()=>{l(e),i(!0)},title:"Click to edit",children:e||t.jsx("span",{style:{color:"#D1D5DB",fontStyle:"italic"},children:"empty"})}):n?t.jsx("textarea",{value:a,onChange:p=>l(p.target.value),onBlur:d,onKeyDown:c,autoFocus:!0,className:"w-full px-2 py-1 text-xs rounded focus:outline-none",style:{border:"1px solid #2DD4A8",background:"#FAFAF8",color:"#1a1a1a",resize:"vertical",minHeight:"48px"}}):t.jsx("input",{value:a,onChange:p=>l(p.target.value),onBlur:d,onKeyDown:c,autoFocus:!0,className:"w-full px-2 py-1 text-xs rounded focus:outline-none",style:{border:"1px solid #2DD4A8",background:"#FAFAF8",color:"#1a1a1a"}})}function ae({title:e,count:r,defaultOpen:n=!0,actions:o,children:s}){const[i,a]=u.useState(n);return t.jsxs("div",{style:{borderBottom:"1px solid #EDEDEA"},children:[t.jsxs("div",{className:"flex items-center gap-2 px-3 py-1.5 cursor-pointer transition-colors",style:{borderRadius:"6px",margin:"2px 4px"},onMouseEnter:l=>l.currentTarget.style.background="#F0F0ED",onMouseLeave:l=>l.currentTarget.style.background="transparent",onClick:()=>a(l=>!l),children:[t.jsx("span",{className:"font-medium flex-1 text-xs",style:{color:"#374151"},children:e}),o&&t.jsx("span",{onClick:l=>l.stopPropagation(),children:o}),typeof r=="number"&&t.jsx("span",{className:"text-xs",style:{color:"#9CA3AF"},children:r}),t.jsx("span",{style:{color:"#D1D5DB"},children:i?"▾":"▸"})]}),i&&t.jsx("div",{className:"px-4 pb-3",children:s})]})}function Qa({label:e,kind:r,kindColor:n,onClick:o,arrow:s,typeBadge:i,typeColor:a,selected:l}){return t.jsxs("div",{className:"flex items-center gap-1.5 cursor-pointer transition-colors ml-2",style:{borderRadius:"6px",padding:"4px 8px",background:l?"#2DD4A818":"transparent",color:l?"#1B3A4B":"#374151",fontWeight:l?500:400,fontSize:j.xs},onMouseEnter:d=>{l||(d.currentTarget.style.background="#F0F0ED")},onMouseLeave:d=>{l||(d.currentTarget.style.background="transparent")},onClick:o,children:[s&&t.jsx("span",{style:{color:"#9CA3AF"},children:s}),i&&t.jsx("span",{className:"px-1 py-0.5 rounded",style:{background:(a||"#2563EB")+"18",color:a||"#2563EB",fontSize:j.xs},children:i}),t.jsx("span",{className:"truncate",children:e}),r&&t.jsx("span",{className:"ml-auto flex-shrink-0 px-1 py-0.5 rounded",style:{background:(n||"#666")+"15",color:n||"#666",fontSize:j.badge},children:r})]})}function Xa(){const e=k(a=>a.model),r=k(a=>a.activeView),n=r.type==="diagram"?r.diagramId:null,o=ft(e,n);if(!o)return null;const s=Fe[o.diagramType],i={borderBottom:"1px solid #EDEDEA"};return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"p-4",style:{...i,borderLeft:`3px solid ${(s==null?void 0:s.color)||"#6B7280"}`},children:[t.jsx("div",{className:"text-sm font-semibold truncate",style:{color:"#1a1a1a"},children:o.name}),t.jsxs("div",{className:"flex items-center gap-2 text-xs mt-1.5",children:[s&&t.jsx("span",{className:"px-2 py-0.5 rounded-md font-medium",style:{background:s.color+"18",color:s.color},children:s.code}),t.jsx("span",{style:{color:"#6B7280"},children:(s==null?void 0:s.fullName)||o.diagramType})]}),o.auto&&t.jsx("div",{className:"text-xs mt-1",style:{color:"#6B7280"},children:"Auto-generated"})]}),t.jsxs("div",{className:"flex-1 overflow-y-auto",children:[o.description&&t.jsx(ae,{title:"Description",defaultOpen:!0,children:t.jsx("div",{className:"text-xs leading-relaxed",style:{color:"#374151"},children:o.description})}),t.jsx(ae,{title:"Details",defaultOpen:!0,children:t.jsxs("div",{className:"space-y-1.5",children:[t.jsxs("div",{className:"flex text-xs",children:[t.jsx("span",{className:"min-w-[80px]",style:{color:"#6B7280"},children:"ID"}),t.jsx("span",{className:"truncate font-mono",style:{color:"#1a1a1a",fontSize:j.xs},children:o.id})]}),t.jsxs("div",{className:"flex text-xs",children:[t.jsx("span",{className:"min-w-[80px]",style:{color:"#6B7280"},children:"Viewpoint"}),t.jsx("span",{style:{color:"#1a1a1a"},children:o.viewpointId})]}),t.jsxs("div",{className:"flex text-xs",children:[t.jsx("span",{className:"min-w-[80px]",style:{color:"#6B7280"},children:"Type"}),t.jsx("span",{style:{color:"#1a1a1a"},children:o.diagramType})]})]})}),o.properties&&Object.keys(o.properties).length>0&&t.jsx(ae,{title:"Properties",count:Object.keys(o.properties).length,children:t.jsx("div",{className:"space-y-1.5",children:Object.entries(o.properties).map(([a,l])=>t.jsxs("div",{className:"flex text-xs",children:[t.jsx("span",{className:"min-w-[80px]",style:{color:"#6B7280"},children:a}),t.jsx("span",{className:"truncate",style:{color:"#1a1a1a"},children:l})]},a))})}),o.elementIds&&o.elementIds.length>0&&t.jsx(ae,{title:"Scoped Elements",count:o.elementIds.length,defaultOpen:!1,children:t.jsx("div",{className:"text-xs",style:{color:"#6B7280"},children:o.elementIds.join(", ")})}),o.relationshipTypes&&o.relationshipTypes.length>0&&t.jsx(ae,{title:"Relationship Types",count:o.relationshipTypes.length,children:t.jsx("div",{className:"flex flex-wrap gap-1",children:o.relationshipTypes.map(a=>t.jsx("span",{className:"px-1.5 py-0.5 rounded text-xs",style:{background:"#EFF6FF",color:"#2563EB",fontSize:j.xs},children:a},a))})})]})]})}function Za({element:e,outgoing:r,incoming:n}){const o=k(E=>E.model),s=k(E=>E.connected),i=k(E=>E.selectElement),a=k(E=>E.selectedDiagramId),l=k(E=>E.pendingRelationships),d=k(E=>E.createRelationship),c=k(E=>E.deleteRelationship),p=k(E=>E.dismissPendingRelationship),f=k(E=>E.addElementToDiagram),[h,S]=u.useState(!1),[b,x]=u.useState(null),[v,w]=u.useState(null),T=u.useMemo(()=>wr(o),[o]);u.useEffect(()=>{x(null),w(null),S(!1)},[e.id]);const I=l.filter(E=>E.sourceId===e.id||E.targetId===e.id),m=r.length+n.length,D=u.useCallback(async E=>{var L;S(!1),x(null);const R=await d({...E,selectedElementId:e.id,diagramId:a??void 0});if(!R.success){x({kind:"error",message:R.error??"The relationship could not be created."});return}const O=E.sourceId===e.id?E.targetId:E.sourceId,C=ft(o,a),B=(L=R.diagnostics)==null?void 0:L.find(K=>K.code==="REL-005"),P=!!C&&!!C.elementIds&&C.elementIds.length>0&&!C.elementIds.includes(O);x({kind:"success",message:`Relationship created in ${R.sourceFile??"the model"}.`,profileMessage:B==null?void 0:B.message,offerAddToView:P&&!B&&a?{elementId:O,diagramId:a}:void 0})},[d,e.id,a,o]),F=u.useCallback(async E=>{w(null);const R=await c(E);x(R.success?{kind:"success",message:`Relationship removed from ${R.sourceFile??"the model"}.`}:{kind:"error",message:R.error??"The relationship could not be deleted."})},[c]);return o?t.jsxs(t.Fragment,{children:[t.jsxs(ae,{title:"Relationships",count:m,defaultOpen:!0,actions:t.jsx("button",{onClick:()=>{x(null),S(!0)},disabled:!s,className:"px-2 py-0.5 rounded text-xs font-medium",style:{background:s?"#F0F0ED":"#F7F7F5",color:s?"#374151":"#D1D5DB",border:"none",cursor:s?"pointer":"not-allowed"},title:s?"Browse every relationship type and filter candidate elements":"Connect to the dev server to author relationships",children:"Browse…"}),children:[m===0&&I.length===0&&t.jsx("div",{className:"text-xs py-1",style:{color:"#9CA3AF"},children:"No relationships yet."}),r.map(E=>t.jsx(Bn,{relationship:E,direction:"outgoing",model:o,registries:T,confirming:v===E.id,onNavigate:()=>i(E.targetId),onRequestDelete:()=>w(E.id),onCancelDelete:()=>w(null),onConfirmDelete:()=>F(E.id),deletable:s},E.id)),n.map(E=>t.jsx(Bn,{relationship:E,direction:"incoming",model:o,registries:T,confirming:v===E.id,onNavigate:()=>i(E.sourceId),onRequestDelete:()=>w(E.id),onCancelDelete:()=>w(null),onConfirmDelete:()=>F(E.id),deletable:s},E.id)),I.map(E=>t.jsx(tl,{pending:E,model:o,onDismiss:()=>p(E.pendingId)},E.pendingId)),t.jsx(Ka,{element:e,model:o,registries:T,enabled:s,onCreate:D,onOpenFullDialog:()=>{x(null),S(!0)}}),b&&t.jsx(el,{status:b,onAddToView:()=>{b.offerAddToView&&(f(b.offerAddToView.diagramId,b.offerAddToView.elementId),x({kind:"success",message:"Element added to this view."}))},onDismiss:()=>x(null),model:o})]}),h&&t.jsx($a,{element:e,model:o,registries:T,diagramId:a??void 0,onCancel:()=>S(!1),onConfirm:D})]}):null}function el({status:e,onAddToView:r,onDismiss:n,model:o}){var a;const s=e.kind==="success",i=e.offerAddToView?((a=o.elements[e.offerAddToView.elementId])==null?void 0:a.name)??e.offerAddToView.elementId:null;return t.jsxs("div",{className:"text-xs p-2 rounded-lg mt-2",style:{background:s?"#F0FDF4":"#FEF2F2",border:`1px solid ${s?"#BBF7D0":"#FECACA"}`,color:s?"#166534":"#DC2626"},children:[t.jsxs("div",{className:"flex items-start gap-1.5",children:[t.jsx("span",{className:"flex-1",children:e.message}),t.jsx("button",{onClick:n,style:{background:"none",border:"none",cursor:"pointer",color:"inherit",lineHeight:1},"aria-label":"Dismiss",children:"×"})]}),e.profileMessage&&t.jsx("div",{className:"mt-1",style:{color:"#92400E"},children:"Relationship created in the model, but this view profile does not display this relationship type."}),e.offerAddToView&&t.jsxs("button",{onClick:r,className:"mt-1.5 px-2 py-0.5 rounded",style:{background:"#FFFFFF",border:"1px solid #BBF7D0",color:"#166534",cursor:"pointer",fontSize:j.xs},children:["Relationship created. Add ",i," to this view?"]})]})}function Bn({relationship:e,direction:r,model:n,registries:o,deletable:s,confirming:i,onNavigate:a,onRequestDelete:l,onCancelDelete:d,onConfirmDelete:c}){const p=r==="outgoing"?e.targetId:e.sourceId,f=n.elements[p],h=f&&re[f.layer]||"#666",S=hr(e.type,o),[b,x]=u.useState(!1),v=s&&e.named===!0;return t.jsxs("div",{style:{borderBottom:"1px solid #F7F7F5"},children:[t.jsxs("div",{className:"flex items-center gap-1.5 ml-2",style:{padding:"4px 8px",fontSize:j.xs},children:[t.jsx("span",{style:{color:"#9CA3AF"},children:r==="outgoing"?"→":"←"}),t.jsx("span",{className:"px-1 py-0.5 rounded flex-shrink-0",style:{background:(r==="outgoing"?"#2563EB":"#10B981")+"18",color:r==="outgoing"?"#2563EB":"#10B981",fontSize:j.xs},children:(S==null?void 0:S.label)??e.type}),t.jsx("button",{onClick:a,className:"truncate text-left",style:{background:"none",border:"none",cursor:"pointer",color:"#374151",flex:1,minWidth:0},title:`Go to ${(f==null?void 0:f.name)??p}`,children:(f==null?void 0:f.name)??p}),t.jsx("button",{onClick:()=>x(w=>!w),style:{background:"none",border:"none",cursor:"pointer",color:"#D1D5DB"},"aria-label":b?"Hide relationship details":"Show relationship details",children:b?"▾":"▸"})]}),b&&t.jsxs("div",{className:"ml-4 pb-2 space-y-1",style:{fontSize:"10px",color:"#6B7280"},children:[t.jsx(ot,{label:"Kind",value:(f==null?void 0:f.kind)??"—",valueColor:h}),t.jsx(ot,{label:"Roles",value:`${e.sourceEnd||(S==null?void 0:S.sourceEnd.name)||"source"} → ${e.targetEnd||(S==null?void 0:S.targetEnd.name)||"target"}`}),t.jsx(ot,{label:"ID",value:e.id,mono:!0}),t.jsx(ot,{label:"Source",value:e.file||"—",mono:!0}),!e.named&&t.jsx("div",{style:{color:"#D97706"},children:"Anonymous connection — name it in SysML to allow deletion from here."}),v&&!i&&t.jsx("button",{onClick:l,className:"px-1.5 py-0.5 rounded",style:{background:"#FEF2F2",color:"#DC2626",border:"1px solid #FECACA",cursor:"pointer",fontSize:"10px"},children:"Remove relationship"}),i&&t.jsxs("div",{className:"p-1.5 rounded",style:{background:"#FEF2F2",border:"1px solid #FECACA"},children:[t.jsxs("div",{style:{color:"#DC2626"},children:["Remove ",(S==null?void 0:S.label)??e.type," to ",(f==null?void 0:f.name)??p,"? Both elements are kept."]}),t.jsxs("div",{className:"flex gap-1 mt-1",children:[t.jsx("button",{onClick:c,className:"px-1.5 py-0.5 rounded",style:{background:"#DC2626",color:"#FFFFFF",border:"none",cursor:"pointer",fontSize:"10px"},children:"Remove"}),t.jsx("button",{onClick:d,className:"px-1.5 py-0.5 rounded",style:{background:"#FFFFFF",color:"#374151",border:"1px solid #E5E5E0",cursor:"pointer",fontSize:"10px"},children:"Cancel"})]})]})]})]})}function ot({label:e,value:r,mono:n,valueColor:o}){return t.jsxs("div",{className:"flex gap-1.5",children:[t.jsx("span",{style:{minWidth:48,color:"#9CA3AF"},children:e}),t.jsx("span",{className:`truncate ${n?"font-mono":""}`,style:{color:o??"#374151"},title:r,children:r})]})}function tl({pending:e,model:r,onDismiss:n}){const o=e.direction==="outgoing"?e.targetId:e.sourceId,s=r.elements[o],i=e.status==="failed";return t.jsxs("div",{className:"flex items-center gap-1.5 ml-2 rounded",style:{padding:"4px 8px",fontSize:j.xs,background:i?"#FEF2F2":"#F9FAFB",color:i?"#DC2626":"#6B7280",fontStyle:i?"normal":"italic"},children:[t.jsx("span",{children:e.direction==="outgoing"?"→":"←"}),t.jsx("span",{className:"px-1 py-0.5 rounded flex-shrink-0",style:{background:"#E5E7EB",color:"#6B7280",fontSize:j.xs},children:e.label}),t.jsx("span",{className:"truncate flex-1",children:(s==null?void 0:s.name)??o}),i?t.jsxs(t.Fragment,{children:[t.jsx("span",{className:"truncate",style:{fontSize:"10px",maxWidth:90},title:e.error,children:e.error}),t.jsx("button",{onClick:n,style:{background:"none",border:"none",cursor:"pointer",color:"inherit"},"aria-label":"Dismiss failed relationship",children:"×"})]}):t.jsx("span",{style:{fontSize:"10px"},children:"saving…"})]})}const nl=4e3;function rl({elementId:e}){const r=k(a=>a.model),n=k(a=>a.lastSourceChange),[o,s]=u.useState(null),i=u.useMemo(()=>ni(r,e),[r,e]);return u.useEffect(()=>{if(!ri(n,i))return;s(n.at);const a=setTimeout(()=>s(null),nl);return()=>clearTimeout(a)},[n==null?void 0:n.seq]),u.useEffect(()=>{s(null)},[e]),o?t.jsx("span",{title:"A source file this element depends on changed; the model was rebuilt",className:"px-1.5 rounded",style:{fontSize:j.badge,background:"#ECFDF5",color:"#047857",border:"1px solid #A7F3D0"},children:"↻ Updated"}):null}function ol(){var T,I;const e=k(m=>m.model),r=k(m=>m.selectedElementId),n=k(m=>m.validation),o=k(m=>m.selectElement),s=k(m=>m.updateElementField),i=k(m=>m.updateElementAttribute),a=k(m=>m.applyEdit),[l,d]=u.useState(!1);u.useEffect(()=>{d(!1)},[r]),u.useEffect(()=>{if(!r)return;const m=D=>{(D.metaKey||D.ctrlKey)&&D.key==="s"&&(D.preventDefault(),a(r),d(!1))};return window.addEventListener("keydown",m),()=>window.removeEventListener("keydown",m)},[r,a]);const c=u.useMemo(()=>r&&e?ti(e,r):[],[e,r]);if(!r||!e)return null;const p=e.elements[r];if(!p)return null;const f=c.filter(m=>m.sourceId===r),h=c.filter(m=>m.targetId===r),S=re[p.layer]||"#666",b=(n==null?void 0:n.violations.filter(m=>m.elementId===r))||[],x=Object.entries(p.attributes).filter(([m])=>m!=="name"),v=m=>{s(r,"doc",m),a(r)},w=(m,D)=>{i(r,m,D),a(r)};return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"p-4",style:{borderBottom:"1px solid #EDEDEA",borderLeft:`3px solid ${S}`},children:[t.jsxs("div",{className:"flex items-center gap-2 mb-1.5",children:[t.jsx("span",{className:"w-2.5 h-2.5 flex-shrink-0",style:{background:S,borderRadius:"3px"}}),t.jsx("span",{className:"text-sm font-semibold truncate",style:{color:"#1a1a1a"},children:p.name})]}),t.jsxs("div",{className:"flex items-center gap-2 text-xs",children:[t.jsx("span",{className:"px-2 py-0.5 rounded-md font-medium",style:{background:S+"18",color:S},children:p.kind}),t.jsx("span",{style:{color:"#6B7280"},children:p.construct})]}),t.jsxs("div",{className:"text-xs mt-1.5 capitalize",style:{color:"#6B7280"},children:[p.layer," layer"]})]}),t.jsxs("div",{className:"flex-1 overflow-y-auto",children:[t.jsx(ae,{title:"Description",defaultOpen:!0,children:t.jsx("div",{className:"text-xs leading-relaxed",children:t.jsx(zn,{value:p.doc||"",onSave:v,multiline:!0})})}),p.parameters&&p.parameters.length>0&&t.jsx(ae,{title:"Parameters",count:p.parameters.length,children:t.jsx("div",{className:"space-y-1.5",children:p.parameters.map(m=>t.jsxs("div",{className:"flex items-center gap-2 text-xs",children:[t.jsx("span",{className:"px-1.5 py-0.5 rounded font-mono",style:{fontSize:"10px",background:m.direction==="in"?"#EFF6FF":m.direction==="out"?"#FFF7ED":"#F0FDF4",color:m.direction==="in"?"#2563EB":m.direction==="out"?"#EA580C":"#16A34A"},children:m.direction}),t.jsx("span",{style:{color:"#374151",fontWeight:500},children:m.name}),t.jsx("span",{style:{color:"#6B7280"},children:":"}),t.jsx("span",{style:{color:"#6B7280"},children:m.type})]},m.name))})}),p.allocatedTo&&t.jsx(ae,{title:"Allocated To",defaultOpen:!0,children:t.jsx(Qa,{label:((T=e.elements[p.allocatedTo])==null?void 0:T.name)||p.allocatedTo,kind:(I=e.elements[p.allocatedTo])==null?void 0:I.kind,kindColor:"#E67E22",arrow:"→",onClick:()=>o(p.allocatedTo)})}),x.length>0&&t.jsx(ae,{title:"Attributes",count:x.length,defaultOpen:!0,actions:t.jsx("button",{onClick:()=>{l&&r&&a(r),d(m=>!m)},className:"px-2 py-0.5 rounded text-xs font-medium",style:{background:l?"#2DD4A8":"#F0F0ED",color:l?"#FFFFFF":"#6B7280",border:"none",cursor:"pointer"},title:l?"Save (Ctrl+S)":"Edit attributes",children:l?"✓ Save":"✏ Edit"}),children:t.jsx("div",{className:"space-y-1.5",children:x.map(([m,D])=>t.jsxs("div",{className:"flex text-xs items-start",children:[t.jsx("span",{className:"min-w-[80px] pt-0.5",style:{color:"#6B7280"},children:m}),t.jsx(zn,{value:D,onSave:F=>w(m,F),forceEdit:l})]},m))})}),t.jsx(Za,{element:p,outgoing:f,incoming:h}),b.length>0&&t.jsx(ae,{title:"Guidance",count:b.length,defaultOpen:!0,children:t.jsx("div",{className:"space-y-2",children:b.map((m,D)=>t.jsxs("div",{className:"text-xs p-2.5 rounded-lg",style:{background:m.severity==="error"?"#FEF2F2":m.severity==="warning"?"#FFFBEB":"#EFF6FF",border:`1px solid ${m.severity==="error"?"#FECACA":m.severity==="warning"?"#FDE68A":"#BFDBFE"}`},children:[t.jsx("div",{style:{color:m.severity==="error"?"#DC2626":m.severity==="warning"?"#D97706":"#2563EB"},children:m.description}),t.jsxs("div",{className:"mt-0.5",style:{color:"#6B7280"},children:["[",m.ruleId,"]"]})]},`${m.ruleId}-${D}`))})}),b.length===0&&t.jsx("div",{className:"p-4",children:t.jsxs("div",{className:"text-xs flex items-center gap-1",style:{color:"#10B981"},children:[t.jsx("span",{children:"✓"})," All rules satisfied"]})}),p.file&&t.jsx(ae,{title:"Source",defaultOpen:!1,actions:t.jsx(rl,{elementId:r}),children:t.jsxs("button",{className:"flex items-center gap-1.5 text-xs w-full text-left rounded px-1 py-0.5 transition-colors",style:{color:"#2563EB",background:"transparent",border:"none",cursor:"pointer",wordBreak:"break-all"},onMouseEnter:m=>{m.currentTarget.style.background="#EFF6FF"},onMouseLeave:m=>{m.currentTarget.style.background="transparent"},onClick:()=>{navigator.clipboard.writeText(p.file).catch(()=>{})},title:"Click to copy path",children:[t.jsx("span",{style:{flexShrink:0},children:"⟨/⟩"}),t.jsx("span",{className:"font-mono truncate",children:p.file}),t.jsx("span",{style:{flexShrink:0,color:"#9CA3AF",fontSize:"9px"},children:"copy"})]})})]})]})}function sl(){const e=k(c=>c.model),r=k(c=>c.selectedRelationshipId);if(!e||!r)return null;const n=e.relationships.find(c=>c.id===r);if(!n)return null;const o=e.elements[n.sourceId],s=e.elements[n.targetId],i=n.type==="flow",a=n.flowItem,l=a&&/energy|power|voltage|current/i.test(a)?"Energy":a&&/material|fluid|gas|batch/i.test(a)?"Material":i?"Data":"Control",d=l==="Energy"?"#D97706":l==="Material"?"#16A34A":l==="Data"?"#3498DB":"#4B5563";return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"p-4",style:{borderBottom:"1px solid #EDEDEA",borderLeft:`3px solid ${d}`},children:[t.jsx("div",{className:"text-sm font-semibold",style:{color:"#1a1a1a"},children:"Connection"}),t.jsxs("div",{className:"mt-1 text-xs",style:{color:"#6B7280"},children:[(o==null?void 0:o.name)??n.sourceId," → ",(s==null?void 0:s.name)??n.targetId]}),t.jsxs("div",{className:"mt-2 flex gap-2",children:[t.jsxs("span",{className:"px-2 py-0.5 rounded-md text-xs font-medium",style:{background:d+"18",color:d},children:[l," flow"]}),t.jsx("span",{className:"px-2 py-0.5 rounded-md text-xs font-medium",style:{background:"#F3F4F6",color:"#374151"},children:n.type})]})]}),t.jsxs("div",{className:"flex-1 overflow-y-auto",children:[t.jsx(ae,{title:"Involved item",defaultOpen:!0,children:t.jsx("div",{className:"text-xs",style:{color:"#374151"},children:a??"No transported item is modeled for this connection."})}),t.jsx(ae,{title:"Endpoints",defaultOpen:!0,children:t.jsxs("div",{className:"space-y-2 text-xs",children:[t.jsxs("div",{children:[t.jsx("span",{style:{color:"#6B7280"},children:"Source"}),t.jsx("div",{style:{color:"#1a1a1a",fontWeight:500},children:(o==null?void 0:o.name)??n.sourceId})]}),t.jsxs("div",{children:[t.jsx("span",{style:{color:"#6B7280"},children:"Target"}),t.jsx("div",{style:{color:"#1a1a1a",fontWeight:500},children:(s==null?void 0:s.name)??n.targetId})]})]})}),t.jsx(ae,{title:"Traceability",defaultOpen:!1,children:t.jsx("div",{className:"text-xs",style:{color:"#6B7280"},children:n.file||"Model relationship"})})]})]})}function il(){const e=k(l=>l.selectedElementId),r=k(l=>l.activeView),n=k(l=>l.selectedRelationshipId),o=k(l=>l.propertiesPanelCollapsed),s=k(l=>l.togglePropertiesPanel);if(o)return t.jsxs("div",{className:"flex flex-col items-center flex-shrink-0 cursor-pointer",style:{width:"40px",background:"#FAFAF8",borderLeft:"1px solid #E5E5E0"},onClick:s,title:"Expand properties",children:[t.jsx("div",{className:"flex items-center justify-center mt-2",style:{color:"#6B7280",fontSize:"20px",width:"32px",height:"32px",borderRadius:"6px"},children:"◂"}),t.jsx("div",{style:{writingMode:"vertical-rl",textOrientation:"mixed",color:"#6B7280",fontSize:"12px",fontWeight:600,letterSpacing:"0.1em"},children:"Properties"})]});const i=r.type==="diagram"&&!e&&!n,a=!!e;return t.jsxs("div",{className:"flex flex-col overflow-hidden flex-shrink-0",style:{width:"300px",background:"#FAFAF8",borderLeft:"1px solid #E5E5E0"},children:[t.jsxs("div",{className:"flex items-center justify-between px-3 py-1.5",style:{borderBottom:"1px solid #EDEDEA"},children:[t.jsx("span",{className:"text-xs font-medium",style:{color:"#6B7280"},children:"Properties"}),t.jsx("button",{onClick:s,className:"flex items-center justify-center",style:{color:"#6B7280",fontSize:"20px",lineHeight:1,width:"32px",height:"32px",borderRadius:"6px"},onMouseEnter:l=>l.currentTarget.style.color="#374151",onMouseLeave:l=>l.currentTarget.style.color="#6B7280",title:"Collapse properties","aria-label":"Collapse properties",children:"▸"})]}),n?t.jsx(sl,{}):a?t.jsx(ol,{}):i?t.jsx(Xa,{}):t.jsx("div",{className:"flex-1 flex items-center justify-center p-4",children:t.jsx("span",{className:"text-xs text-center",style:{color:"#6B7280"},children:"Select an element or diagram to view properties"})})]})}function Ct(e=y.border){return{borderTop:`1px solid ${e}`}}function al({placeholder:e,value:r,onChange:n}){return t.jsx("input",{type:"text",value:r,placeholder:e,onChange:o=>n(o.target.value),className:"flex-1 px-2 py-1 rounded focus:outline-none",style:{background:"#F7F7F5",border:"1px solid #E5E5E0",color:y.primary,fontSize:j.xs,minWidth:0}})}function ll({values:e}){const r=[...new Set(e.filter(Boolean))];return r.length===0?t.jsx("span",{style:{color:y.faint,fontSize:"12px"},children:"—"}):r.length===1?t.jsx("span",{style:{color:y.muted,fontSize:"12px"},children:r[0]}):t.jsxs("span",{style:{color:"#F59E0B",fontSize:"12px"},children:[r.length," different values"]})}function cl(){const e=k(x=>x.model),r=k(x=>x.selectedElementIds),n=k(x=>x.clearElementSelection),o=k(x=>x.bulkUpdateAttributes),s=u.useMemo(()=>[...r],[r]),i=u.useMemo(()=>s.map(x=>e==null?void 0:e.elements[x]).filter(Boolean),[s,e]),a=u.useMemo(()=>{if(i.length===0)return[];const x="_",v=i.map(T=>new Set(Object.keys(T.attributes).filter(I=>!I.startsWith(x))));return[...v[0]].filter(T=>v.every(I=>I.has(T))).sort()},[i]),l=u.useMemo(()=>{const x={};for(const v of a)x[v]=i.map(w=>w.attributes[v]??"");return x},[i,a]),d=u.useMemo(()=>[...new Set(i.map(x=>x.kind))].sort(),[i]),[c,p]=u.useState({}),f=u.useCallback((x,v)=>{p(w=>({...w,[x]:v}))},[]),h=Object.values(c).some(x=>x!==""),S=u.useCallback(()=>{const x=Object.fromEntries(Object.entries(c).filter(([,v])=>v!==""));Object.keys(x).length!==0&&(o(s,x),p({}))},[c,s,o]),b=u.useCallback(()=>{p({})},[]);return i.length<2?null:t.jsxs("div",{className:"flex flex-col overflow-hidden",style:{width:"280px",background:y.surface,borderLeft:`1px solid ${y.border}`,fontSize:j.xs},children:[t.jsxs("div",{className:"flex items-center justify-between px-4 py-3 flex-shrink-0",style:{borderBottom:`1px solid ${y.border}`},children:[t.jsxs("div",{children:[t.jsx("div",{className:"font-semibold",style:{color:y.primary,fontSize:j.sm},children:"Bulk Edit"}),t.jsxs("div",{style:{color:y.muted,fontSize:"12px",marginTop:"2px"},children:[s.length," elements selected"]})]}),t.jsx("button",{onClick:n,className:"px-2 py-1 rounded",style:{color:y.muted,background:"#F0F0ED",fontSize:"12px"},title:"Clear selection",children:"✕ Clear"})]}),t.jsxs("div",{className:"px-4 py-3 flex-shrink-0",style:Ct(),children:[t.jsx("div",{style:{color:y.muted,fontSize:"12px",fontWeight:600,marginBottom:"6px",textTransform:"uppercase",letterSpacing:"0.5px"},children:"Selection"}),t.jsx("div",{className:"flex flex-wrap gap-1",children:d.map(x=>t.jsx("span",{className:"px-2 py-0.5 rounded-full",style:{background:"#EEF2FF",color:"#4F46E5",fontSize:"12px",fontWeight:500},children:x},x))}),t.jsxs("div",{style:{color:y.faint,fontSize:"12px",marginTop:"6px"},children:[i.map(x=>x.name).slice(0,5).join(", "),i.length>5&&` +${i.length-5} more`]})]}),t.jsxs("div",{className:"flex-1 overflow-y-auto px-4 py-3",style:Ct(),children:[t.jsxs("div",{style:{color:y.muted,fontSize:"12px",fontWeight:600,marginBottom:"8px",textTransform:"uppercase",letterSpacing:"0.5px"},children:["Common Attributes",a.length>0&&t.jsxs("span",{style:{color:y.faint,fontWeight:400,marginLeft:"4px"},children:["(",a.length,")"]})]}),a.length===0?t.jsx("div",{style:{color:y.faint,fontSize:"12px"},children:"No common attributes across selected elements."}):t.jsx("div",{className:"space-y-3",children:a.map(x=>t.jsxs("div",{children:[t.jsxs("div",{className:"flex items-center justify-between mb-1",children:[t.jsx("span",{style:{color:y.secondary,fontSize:"12px",fontWeight:500},children:x}),t.jsx(ll,{values:l[x]})]}),t.jsx(al,{placeholder:`Set for all ${s.length} elements…`,value:c[x]??"",onChange:v=>f(x,v)})]},x))})]}),a.length>0&&t.jsxs("div",{className:"flex items-center gap-2 px-4 py-3 flex-shrink-0",style:Ct(),children:[t.jsx("button",{onClick:b,disabled:!h,className:"flex-1 py-1.5 rounded",style:{fontSize:j.xs,fontWeight:500,color:h?y.secondary:y.faint,background:h?"#F0F0ED":"#F7F7F5",cursor:h?"pointer":"default"},children:"Reset"}),t.jsxs("button",{onClick:S,disabled:!h,className:"flex-1 py-1.5 rounded font-semibold",style:{fontSize:j.xs,color:"#FFFFFF",background:h?"#2DD4A8":"#A7F3D0",cursor:h?"pointer":"default"},children:["Apply to ",s.length]})]})]})}const Ln="memo-gapbar-pulse";if(typeof document<"u"&&!document.getElementById(Ln)){const e=document.createElement("style");e.id=Ln,e.textContent=`
|
|
3266
|
-
@keyframes memo-pulse-red {
|
|
3267
|
-
0%, 100% { opacity: 1; }
|
|
3268
|
-
50% { opacity: 0.35; }
|
|
3269
|
-
}
|
|
3270
|
-
`,document.head.appendChild(e)}const st={error:{color:"#DC2626",bg:"#FEF2F2",icon:"✖"},warning:{color:"#D97706",bg:"#FFFBEB",icon:"⚠"},info:{color:"#2563EB",bg:"#EFF6FF",icon:"ℹ"}};function dl(){const e=k(C=>C.validation),r=k(C=>C.analysisIssues),n=k(C=>C.selectElement),o=k(C=>C.model),s=k(C=>C.completeness),i=k(C=>C.gapBarExpanded),a=k(C=>C.toggleGapBar),l=k(C=>C.gapBarHeight),d=k(C=>C.setGapBarHeight),[c,p]=u.useState("problems"),f=u.useRef(!1),h=u.useRef(0),S=u.useRef(0),b=o==null?void 0:o.metadata,x=o?Object.keys(o.elements).length:0,v=b!=null&&b.gitUser?t.jsxs(t.Fragment,{children:["@",b.gitUser,b.gitBranch&&t.jsxs(t.Fragment,{children:[" · ",b.gitBranch]}),b.gitCommitShort&&t.jsx("span",{style:{marginLeft:"4px",fontFamily:"monospace",fontSize:j.badge},children:b.gitCommitShort})]}):null,w=(e==null?void 0:e.violations.filter(C=>C.severity==="error"))??[],T=(e==null?void 0:e.violations.filter(C=>C.severity==="warning"))??[],I=(e==null?void 0:e.violations.length)??0,m=r.filter(C=>C.severity==="warning").length,D=I>0||r.length>0,F=!!s,E=D&&F,R=(s==null?void 0:s.layers.filter(C=>C.totalElements>0))??[],O=u.useCallback(C=>{C.preventDefault(),f.current=!0,h.current=C.clientY,S.current=l;const B=L=>{if(!f.current)return;const K=h.current-L.clientY;d(S.current+K)},P=()=>{f.current=!1,document.removeEventListener("mousemove",B),document.removeEventListener("mouseup",P)};document.addEventListener("mousemove",B),document.addEventListener("mouseup",P)},[l,d]);return t.jsxs("div",{style:{background:y.surface,borderTop:`1px solid ${y.border}`,flexShrink:0},children:[i&&t.jsx("div",{style:{height:"4px",cursor:"row-resize",background:"transparent",flexShrink:0},onMouseDown:O,onMouseEnter:C=>{C.currentTarget.style.background=y.accent+"40"},onMouseLeave:C=>{C.currentTarget.style.background="transparent"}}),t.jsxs("div",{className:"flex items-center px-4 gap-3 cursor-pointer select-none",style:{height:"32px",fontSize:j.sm},onClick:a,children:[t.jsx("span",{style:{color:y.faint,fontSize:"10px",transition:"transform 150ms ease",transform:i?"rotate(0deg)":"rotate(-90deg)",display:"inline-block"},children:"▼"}),t.jsx("span",{style:{color:y.secondary,fontWeight:600,fontSize:j.xs},children:"Problems"}),w.length>0&&t.jsxs("span",{className:"flex items-center gap-1",style:{color:"#DC2626",fontSize:j.xs},children:[t.jsx("span",{style:{fontSize:"10px"},children:"✖"})," ",w.length]}),T.length>0&&t.jsxs("span",{className:"flex items-center gap-1",style:{color:"#D97706",fontSize:j.xs},children:[t.jsx("span",{style:{fontSize:"10px"},children:"⚠"})," ",T.length]}),m>0&&t.jsxs("span",{className:"flex items-center gap-1",style:{color:"#D97706",fontSize:j.xs},children:[t.jsx("span",{style:{fontSize:"9px",opacity:.7},children:"DSM"}),t.jsx("span",{style:{fontSize:"10px"},children:"⚠"})," ",m]}),!D&&e&&t.jsx("span",{style:{color:"#10B981",fontSize:j.xs},children:"✓ No problems"}),!e&&t.jsx("span",{style:{color:y.faint,fontSize:j.xs},children:"Waiting for validation…"}),F&&t.jsxs(t.Fragment,{children:[t.jsx("div",{style:{width:"1px",height:"14px",background:y.border,flexShrink:0}}),t.jsx("span",{style:{color:y.secondary,fontWeight:600,fontSize:j.xs},children:"Completeness"}),t.jsxs("span",{style:{color:s.overall>=80?"#10B981":s.overall>=50?"#D97706":"#DC2626",fontSize:j.xs,fontWeight:600},children:[s.overall,"%"]}),t.jsx("div",{className:"flex items-center gap-0.5",children:R.map(C=>{const B=C.percentage<40;return t.jsx("div",{title:`${Ot[C.layerId]||C.layerLabel}: ${C.percentage}%`,style:{width:8,height:8,borderRadius:"2px",background:C.layerColor,opacity:Math.max(C.percentage/100,.12),flexShrink:0,animation:B?"memo-pulse-red 1.4s ease-in-out infinite":"none",cursor:"default"}},C.layerId)})})]}),t.jsxs("span",{className:"ml-auto flex items-center gap-1",style:{fontSize:j.xs},children:[e&&t.jsxs("span",{style:{color:y.faint},children:[e.rulesEvaluated," rules | ",e.rulesPassed," passed |"," "]}),t.jsxs("strong",{style:{color:y.secondary,fontWeight:700},children:[x," elements"]}),o&&t.jsxs(t.Fragment,{children:[t.jsx("span",{style:{color:y.faint},children:" · "}),t.jsxs("strong",{style:{color:y.secondary,fontWeight:700},children:[o.relationships.length," rels"]})]}),v&&t.jsxs("span",{style:{color:y.faint},children:[" | ",v]})]})]}),i&&t.jsxs("div",{style:{borderTop:`1px solid ${y.borderLight}`},children:[E&&t.jsx("div",{className:"flex",style:{borderBottom:`1px solid ${y.border}`,background:"#FAFAF8"},children:["problems","completeness"].map(C=>t.jsx("button",{onClick:B=>{B.stopPropagation(),p(C)},className:"px-4 py-1.5 font-medium transition-colors",style:{fontSize:j.xs,borderBottom:c===C?`2px solid ${y.accent}`:"2px solid transparent",color:c===C?y.accentDark:y.faint,background:"transparent"},children:C==="problems"?`Problems (${I+r.length})`:`Completeness ${s.overall}%`},C))}),(c==="problems"||!E)&&t.jsx("div",{className:"overflow-y-auto",style:{maxHeight:`${l}px`},children:D?t.jsxs(t.Fragment,{children:[I>0&&(e==null?void 0:e.violations.map((C,B)=>{const P=st[C.severity]||st.info;return t.jsxs("div",{className:"flex items-center gap-2 px-4 py-1.5 cursor-pointer transition-colors",style:{color:P.color,fontSize:j.xs},onMouseEnter:L=>L.currentTarget.style.background=P.bg,onMouseLeave:L=>L.currentTarget.style.background="transparent",onClick:()=>n(C.elementId),children:[t.jsx("span",{children:P.icon}),t.jsxs("span",{style:{color:y.faint},children:["[",C.ruleId,"]"]}),t.jsxs("span",{className:"font-medium",children:[C.elementKind,"/",C.elementName]}),t.jsx("span",{className:"truncate flex-1",style:{color:y.muted},children:C.description})]},`${C.ruleId}-${C.elementId}-${B}`)})),r.length>0&&t.jsxs(t.Fragment,{children:[I>0&&t.jsx("div",{style:{padding:"4px 16px",fontSize:"10px",fontWeight:600,color:y.faint,background:y.surfaceAlt,borderTop:`1px solid ${y.border}`,textTransform:"uppercase",letterSpacing:"0.06em"},children:"DSM Analysis"}),r.map(C=>{const B=st[C.severity]||st.info;return t.jsxs("div",{className:"flex items-center gap-2 px-4 py-1.5 cursor-pointer transition-colors",style:{color:B.color,fontSize:j.xs},onMouseEnter:P=>P.currentTarget.style.background=B.bg,onMouseLeave:P=>P.currentTarget.style.background="transparent",onClick:()=>n(C.elementId),children:[t.jsx("span",{children:B.icon}),t.jsxs("span",{style:{color:y.faint},children:["[",C.source,"]"]}),t.jsx("span",{className:"font-medium",children:C.elementName}),t.jsx("span",{className:"truncate flex-1",style:{color:y.muted},children:C.message}),C.tag&&t.jsx("span",{style:{flexShrink:0,fontSize:"9px",padding:"1px 5px",borderRadius:"4px",background:"#E5E7EB",color:"#374151"},children:C.tag})]},C.id)})]})]}):t.jsx("div",{className:"px-4 py-3",style:{color:y.faint,fontSize:j.xs},children:e?"✓ No problems found":"Waiting for validation…"})}),(c==="completeness"||!E)&&F&&t.jsxs("div",{className:"overflow-y-auto",style:{maxHeight:`${l}px`},children:[t.jsxs("div",{className:"px-4 py-2 flex items-center gap-3",style:{borderBottom:`1px solid ${y.borderLight}`},children:[t.jsxs("span",{style:{fontWeight:700,fontSize:"18px",color:s.overall>=80?"#10B981":s.overall>=50?"#D97706":"#DC2626"},children:[s.overall,"%"]}),t.jsx("div",{className:"flex-1 flex items-center gap-0.5",style:{height:"8px"},children:R.map(C=>{const B=Math.max(C.totalElements/s.totalElements*100,2);return t.jsx("div",{style:{width:`${B}%`,height:"100%",background:C.layerColor+"30",borderRadius:"4px",overflow:"hidden"},children:t.jsx("div",{style:{width:`${C.percentage}%`,height:"100%",background:C.layerColor,borderRadius:"4px"}})},C.layerId)})}),t.jsxs("span",{style:{color:y.faint,fontSize:j.xs},children:[s.completeElements,"/",s.totalElements]})]}),t.jsx("div",{className:"px-4 py-2 grid gap-1.5",style:{gridTemplateColumns:"repeat(auto-fill, minmax(220px, 1fr))"},children:R.map(C=>t.jsxs("div",{className:"flex items-center gap-2",style:{fontSize:j.xs},children:[t.jsx("span",{className:"w-2.5 h-2.5 rounded flex-shrink-0",style:{backgroundColor:C.layerColor}}),t.jsx("span",{className:"flex-1 truncate",style:{color:"#374151"},children:Ot[C.layerId]||C.layerLabel}),t.jsxs("span",{style:{color:"#6B7280"},children:[C.percentage,"%"]}),t.jsxs("span",{style:{color:"#9CA3AF"},children:["(",C.completeElements,"/",C.totalElements,")"]})]},C.layerId))})]})]})]})}function ul(){const[e,r]=u.useState(!1),[n,o]=u.useState(""),[s,i]=u.useState(0),a=u.useRef(null),l=k(v=>v.model),d=k(v=>v.selectElement),c=k(v=>v.setActiveView),p=k(v=>v.selectViewpoint),f=k(v=>v.setExplorerTab);u.useEffect(()=>{const v=w=>{(w.metaKey||w.ctrlKey)&&w.key==="k"&&(w.preventDefault(),r(T=>!T),o(""),i(0)),w.key==="Escape"&&e&&r(!1)};return window.addEventListener("keydown",v),()=>window.removeEventListener("keydown",v)},[e]),u.useEffect(()=>{e&&setTimeout(()=>{var v;return(v=a.current)==null?void 0:v.focus()},50)},[e]);const h=u.useMemo(()=>{const v=[];if(v.push({id:"tool:dsm",label:"DSM",sublabel:"Design Structure Matrix",kind:"tool",action:()=>c({type:"dsm"})},{id:"tool:traceability",label:"Traceability Matrix",sublabel:"N×N trace matrix with presets",kind:"tool",action:()=>c({type:"traceability"})},{id:"tool:ontology",label:"Ontology",sublabel:"Ontology Viewer",kind:"tool",action:()=>c({type:"ontology"})}),!l)return v;for(const w of l.diagrams??[]){const T=Fe[w.diagramType];v.push({id:`diag:${w.id}`,label:w.name,sublabel:(T==null?void 0:T.fullName)||w.diagramType,kind:"diagram",color:T==null?void 0:T.color,action:()=>{c({type:"diagram",diagramId:w.id}),p(w.viewpointId==="__model"?null:w.viewpointId),f("views")}})}for(const w of l.viewpoints??[])v.push({id:`vp:${w.id}`,label:w.label,sublabel:"Viewpoint",kind:"viewpoint",action:()=>{p(w.id),f("views")}});for(const w of Object.values(l.elements))v.push({id:`el:${w.id}`,label:w.name,sublabel:`${w.kind} · ${w.layer}`,kind:"element",color:re[w.layer],action:()=>{d(w.id),f("model")}});return v},[l,c,d,p,f]),S=u.useMemo(()=>{if(!n)return h.slice(0,20);const v=n.toLowerCase();return h.filter(w=>{var T;return w.label.toLowerCase().includes(v)||((T=w.sublabel)==null?void 0:T.toLowerCase().includes(v))}).slice(0,20)},[h,n]);u.useEffect(()=>{i(0)},[S]);const b=u.useCallback(v=>{v.key==="ArrowDown"&&(v.preventDefault(),i(w=>Math.min(w+1,S.length-1))),v.key==="ArrowUp"&&(v.preventDefault(),i(w=>Math.max(w-1,0))),v.key==="Enter"&&S[s]&&(S[s].action(),r(!1))},[S,s]);if(!e)return null;const x={element:"○",diagram:"▦",tool:"⚙",viewpoint:"◉"};return t.jsx("div",{className:"fixed inset-0 z-50 flex items-start justify-center pt-24",style:{background:"rgba(0,0,0,0.4)"},onClick:()=>r(!1),children:t.jsxs("div",{className:"rounded-xl overflow-hidden",style:{width:"520px",maxHeight:"400px",background:"#FFFFFF",boxShadow:"0 16px 48px rgba(0,0,0,0.2)"},onClick:v=>v.stopPropagation(),children:[t.jsxs("div",{className:"flex items-center gap-2 px-4 py-3",style:{borderBottom:"1px solid #E5E5E0"},children:[t.jsx("span",{style:{color:"#9CA3AF",fontSize:"14px"},children:"⌕"}),t.jsx("input",{ref:a,type:"text",placeholder:"Search elements, diagrams, tools...",value:n,onChange:v=>o(v.target.value),onKeyDown:b,className:"flex-1 text-sm focus:outline-none",style:{color:"#1a1a1a",background:"transparent"}}),t.jsx("kbd",{className:"px-1.5 py-0.5 rounded text-xs",style:{background:"#F0F0ED",color:"#9CA3AF",fontSize:"10px"},children:"ESC"})]}),t.jsxs("div",{className:"overflow-y-auto",style:{maxHeight:"340px"},children:[S.length===0&&t.jsx("div",{className:"px-4 py-6 text-center text-xs",style:{color:"#9CA3AF"},children:"No results found"}),S.map((v,w)=>t.jsxs("div",{className:"flex items-center gap-2 px-4 py-2 cursor-pointer",style:{background:w===s?"#F0F0ED":"transparent"},onMouseEnter:()=>i(w),onClick:()=>{v.action(),r(!1)},children:[t.jsx("span",{style:{color:v.color||"#9CA3AF",fontSize:"12px"},children:x[v.kind]||"○"}),t.jsx("span",{className:"text-sm truncate",style:{color:"#1a1a1a"},children:v.label}),v.sublabel&&t.jsx("span",{className:"text-xs truncate ml-auto",style:{color:"#9CA3AF"},children:v.sublabel})]},v.id))]}),t.jsx("div",{className:"px-4 py-2 flex items-center gap-3",style:{borderTop:"1px solid #E5E5E0",background:"#FAFAF8"},children:t.jsxs("span",{className:"text-xs",style:{color:"#9CA3AF"},children:["↑↓"," navigate · ","↵"," select · esc close"]})})]})})}function pl(e){const r=e.trim().split(/\r?\n/).filter(Boolean);if(r.length<2)return{headers:[],rows:[]};const o=r[0].includes(" ")?" ":",",s=l=>l.split(o).map(d=>d.replace(/^"(.*)"$/,"$1").replace(/""/g,'"').trim()),i=s(r[0]),a=r.slice(1).map(l=>{const d=s(l),c={};return i.forEach((p,f)=>{c[p]=d[f]??""}),c});return{headers:i,rows:a}}const qn=["id","name","kind","construct","doc","— skip —"];function ml(){const e=k(g=>g.bulkImportOpen),r=k(g=>g.setBulkImportOpen),n=k(g=>g.importResult),o=k(g=>g.clearImportResult),s=k(g=>g.model),i=u.useRef(null),[a,l]=u.useState("input"),[d,c]=u.useState(""),[p,f]=u.useState(null),[h,S]=u.useState("bulk_import"),[b,x]=u.useState(""),[v,w]=u.useState([]),[T,I]=u.useState([]),[m,D]=u.useState([]),[F,E]=u.useState([]),[R,O]=u.useState([]),[C,B]=u.useState([]),[P,L]=u.useState(""),[K,H]=u.useState(!1);_r.useMemo(()=>s?Array.from(new Set(Object.values(s.elements).map(g=>g.kind))).sort():[],[s]),u.useEffect(()=>{e||(l("input"),c(""),f(null),S("bulk_import"),x(""),w([]),I([]),D([]),E([]),O([]),B([]),L(""),H(!1),o())},[e,o]),u.useEffect(()=>{n&&H(!1)},[n]);const N=u.useCallback(()=>{r(!1)},[r]),W=u.useCallback(g=>{var ee;const _=(ee=g.target.files)==null?void 0:ee[0];if(!_)return;const q=new FileReader;q.onload=ne=>{var ie;const se=(ie=ne.target)==null?void 0:ie.result;c(se),x("");const $=_.name.replace(/\.[^.]+$/,"").replace(/[^a-zA-Z0-9_]/g,"_");$&&S($)},q.readAsText(_)},[]),X=u.useCallback(()=>{if(!d.trim()){x("Paste CSV data or upload a file first.");return}const{headers:g,rows:_}=pl(d);if(g.length===0){x("Could not parse headers. Make sure the first row contains column names.");return}if(_.length===0){x("No data rows found after the header row.");return}w(g),I(_),D(Fs(g,p??void 0)),x(""),l("mapping")},[d,p]),U=u.useCallback(()=>{const g=p==null?void 0:p.defaultKind,_=Ts(T,m,{},g);L(_.csv),B(_.warnings);const q=_.csv.trim().split(`
|
|
3271
|
-
`);if(q.length<2){O(["No rows to preview after applying mappings."]),E([]),l("preview");return}const ee=q[0].split(",").map($=>$.replace(/^"|"$/g,"").trim()),ne=[],se=[];q.slice(1,21).forEach(($,ie)=>{const ye=$.split(",").map(G=>G.replace(/^"|"$/g,"").trim()),de={rowIndex:ie+1,id:"",name:"",kind:"",doc:""};ee.forEach((G,Q)=>{de[G]=ye[Q]??""}),de.id||se.push(`Row ${ie+2}: missing id`),de.name||se.push(`Row ${ie+2}: missing name`),de.kind||se.push(`Row ${ie+2}: missing kind`),ne.push(de)}),E(ne),O(se),l("preview")},[T,m,p]),M=u.useCallback(()=>{P&&(H(!0),o(),Js({elementsCsv:P,packageName:h||"bulk_import"}))},[P,h,o]),A=u.useCallback((g,_)=>{D(q=>q.map((ee,ne)=>ne===g?{...ee,targetAttribute:_}:ee))},[]);if(!e)return null;const V={input:"1 · Input",mapping:"2 · Map columns",preview:"3 · Preview & Import"},Y=["input","mapping","preview"],J=Y.indexOf(a);return t.jsx("div",{ref:i,className:"fixed inset-0 z-50 flex items-center justify-center",style:{background:"rgba(0,0,0,0.35)"},onMouseDown:g=>{g.target===i.current&&N()},children:t.jsxs("div",{className:"flex flex-col rounded-2xl overflow-hidden",style:{width:680,maxHeight:"90vh",background:"#FFFFFF",boxShadow:"0 24px 64px rgba(0,0,0,0.18)",border:"1px solid #E5E5E0"},children:[t.jsxs("div",{className:"flex items-center justify-between px-6 py-4",style:{background:"linear-gradient(135deg, #1B3A4B, #2D6A7A)",flexShrink:0},children:[t.jsxs("div",{children:[t.jsx("h2",{style:{fontSize:"15px",fontWeight:700,color:"#2DD4A8",margin:0},children:"Bulk Import Elements"}),t.jsx("p",{style:{fontSize:"12px",color:"rgba(255,255,255,0.6)",margin:"2px 0 0"},children:"Import from CSV, Excel paste, or requirements spreadsheet"})]}),t.jsx("button",{onClick:N,style:fl,children:"✕"})]}),t.jsx("div",{className:"flex",style:{borderBottom:"1px solid #F0F0EC",background:"#FAFAF8",flexShrink:0},children:Y.map((g,_)=>t.jsx("div",{className:"flex-1 flex items-center justify-center py-2.5",style:{fontSize:j.xs,fontWeight:_===J?700:400,color:_===J?"#1B3A4B":_<J?"#2D6A7A":"#9CA3AF",borderBottom:_===J?"2px solid #2D6A7A":"2px solid transparent"},children:V[g]},g))}),t.jsxs("div",{className:"flex-1 overflow-y-auto px-6 py-5",style:{minHeight:0},children:[a==="input"&&t.jsxs("div",{className:"flex flex-col gap-4",children:[t.jsxs("div",{children:[t.jsx("label",{style:Dt,children:"Artifact type (recipe preset)"}),t.jsxs("select",{value:(p==null?void 0:p.id)??"",onChange:g=>{const _=cn.find(q=>q.id===g.target.value)??null;f(_)},style:At,children:[t.jsx("option",{value:"",children:"— Custom / no preset —"}),cn.map(g=>t.jsx("option",{value:g.id,children:g.name},g.id))]}),p&&t.jsx("p",{style:{fontSize:j.xs,color:"#6B7280",marginTop:4},children:p.description})]}),t.jsxs("div",{children:[t.jsxs("label",{style:Dt,children:["Package name ",t.jsx("span",{style:{color:"#9CA3AF",fontWeight:400},children:"(for the generated .sysml file)"})]}),t.jsx("input",{type:"text",value:h,onChange:g=>S(g.target.value.replace(/[^a-zA-Z0-9_]/g,"_")),style:At,placeholder:"bulk_import"})]}),t.jsxs("div",{children:[t.jsxs("label",{style:Dt,children:["CSV data ",t.jsx("span",{style:{color:"#E74C3C"},children:"*"})]}),t.jsx("textarea",{value:d,onChange:g=>{c(g.target.value),x("")},placeholder:`Paste CSV or tab-separated data here.
|
|
3272
|
-
First row must be the header.
|
|
3273
|
-
|
|
3274
|
-
Example:
|
|
3275
|
-
id,name,kind,doc
|
|
3276
|
-
req_001,System shall be safe,Requirement,Safety requirement`,rows:10,style:{...At,resize:"vertical",fontFamily:"monospace",fontSize:"12px",lineHeight:"1.5"}}),b&&t.jsx("p",{style:{fontSize:j.xs,color:"#E74C3C",marginTop:4},children:b})]}),t.jsxs("div",{className:"flex items-center gap-3",children:[t.jsx("span",{style:{fontSize:j.xs,color:"#6B7280"},children:"or upload a file:"}),t.jsxs("label",{style:{cursor:"pointer",padding:"4px 12px",borderRadius:6,background:"#F3F4F6",border:"1px solid #E5E5E0",fontSize:j.xs,color:"#374151"},children:["Browse…",t.jsx("input",{type:"file",accept:".csv,.tsv,.txt",style:{display:"none"},onChange:W})]}),d&&t.jsxs("span",{style:{fontSize:j.xs,color:"#6B7280"},children:[d.split(`
|
|
3277
|
-
`).length," line(s) loaded"]})]})]}),a==="mapping"&&t.jsxs("div",{className:"flex flex-col gap-3",children:[t.jsxs("p",{style:{fontSize:j.xs,color:"#6B7280",margin:0},children:["Map each source column to a MEMO attribute. ",t.jsx("strong",{children:"id"}),", ",t.jsx("strong",{children:"name"}),", and ",t.jsx("strong",{children:"kind"})," are required. Unrecognised columns are passed through as dynamic attributes."]}),t.jsxs("div",{style:{border:"1px solid #E5E5E0",borderRadius:8,overflow:"hidden"},children:[t.jsxs("div",{className:"flex",style:{background:"#F8F8F5",padding:"8px 12px",borderBottom:"1px solid #E5E5E0"},children:[t.jsx("span",{style:{flex:1,fontSize:j.xs,fontWeight:600,color:"#374151"},children:"Source column"}),t.jsx("span",{style:{flex:1,fontSize:j.xs,fontWeight:600,color:"#374151"},children:"Maps to"}),t.jsx("span",{style:{width:80,fontSize:j.xs,fontWeight:600,color:"#374151"},children:"Transform"})]}),m.map((g,_)=>{const q=["id","name","kind"].includes(g.targetAttribute),ee=!g.targetAttribute,ne=m.filter(($,ie)=>ie!==_&&["id","name","kind","doc","construct"].includes($.targetAttribute)).map($=>$.targetAttribute),se=qn.filter($=>$==="— skip —"||!ne.includes($)||$===g.targetAttribute);return t.jsxs("div",{className:"flex items-center",style:{padding:"6px 12px",borderBottom:_<m.length-1?"1px solid #F0F0EC":"none",background:q?"#F0FDF4":"transparent"},children:[t.jsx("div",{style:{flex:1,fontSize:j.xs,color:"#374151",fontFamily:"monospace"},children:g.sourceColumn}),t.jsx("div",{style:{flex:1,paddingRight:8},children:t.jsxs("select",{value:g.targetAttribute||"",onChange:$=>A(_,$.target.value==="— skip —"?"":$.target.value),style:{width:"100%",fontSize:j.xs,padding:"3px 6px",borderRadius:5,border:`1px solid ${ee?"#E5E5E0":q?"#22C55E":"#E5E5E0"}`,background:ee?"#F9FAFB":"#FFFFFF",color:ee?"#9CA3AF":"#1a1a1a"},children:[se.map($=>t.jsx("option",{value:$,children:$},$)),g.targetAttribute&&!qn.includes(g.targetAttribute)&&t.jsx("option",{value:g.targetAttribute,children:g.targetAttribute})]})}),t.jsx("div",{style:{width:80,fontSize:"10px",color:"#9CA3AF"},children:g.transform??"—"})]},_)})]}),T.length>0&&t.jsxs("details",{children:[t.jsxs("summary",{style:{fontSize:j.xs,color:"#6B7280",cursor:"pointer",marginTop:4},children:["Show raw data sample (",Math.min(T.length,3)," of ",T.length," rows)"]}),t.jsx("div",{style:{marginTop:6,overflowX:"auto"},children:t.jsxs("table",{style:{fontSize:"10px",borderCollapse:"collapse",width:"100%"},children:[t.jsx("thead",{children:t.jsx("tr",{children:v.map(g=>t.jsx("th",{style:Te,children:g},g))})}),t.jsx("tbody",{children:T.slice(0,3).map((g,_)=>t.jsx("tr",{children:v.map(q=>t.jsx("td",{style:Ue,children:g[q]??""},q))},_))})]})})]})]}),a==="preview"&&t.jsxs("div",{className:"flex flex-col gap-4",children:[R.length>0&&t.jsxs("div",{style:{background:"#FEF2F2",border:"1px solid #FECACA",borderRadius:8,padding:"10px 14px"},children:[t.jsxs("p",{style:{fontSize:j.xs,fontWeight:700,color:"#DC2626",margin:"0 0 4px"},children:[R.length," validation error(s) — rows with missing required fields will be skipped"]}),R.slice(0,5).map((g,_)=>t.jsx("p",{style:{fontSize:"11px",color:"#DC2626",margin:"1px 0"},children:g},_)),R.length>5&&t.jsxs("p",{style:{fontSize:"11px",color:"#DC2626",margin:"2px 0 0"},children:["+",R.length-5," more…"]})]}),C.length>0&&t.jsxs("div",{style:{background:"#FFFBEB",border:"1px solid #FDE68A",borderRadius:8,padding:"10px 14px"},children:[t.jsxs("p",{style:{fontSize:j.xs,fontWeight:700,color:"#D97706",margin:"0 0 4px"},children:[C.length," warning(s)"]}),C.slice(0,3).map((g,_)=>t.jsx("p",{style:{fontSize:"11px",color:"#D97706",margin:"1px 0"},children:g},_))]}),n&&t.jsxs("div",{style:{background:n.success?"#F0FDF4":"#FEF2F2",border:`1px solid ${n.success?"#86EFAC":"#FECACA"}`,borderRadius:8,padding:"12px 14px"},children:[t.jsx("p",{style:{fontSize:j.xs,fontWeight:700,margin:"0 0 4px",color:n.success?"#16A34A":"#DC2626"},children:n.success?`Import complete — ${n.elementsImported} element(s) written to ${n.generatedFile??"model"}`:"Import failed"}),n.errors.map((g,_)=>t.jsx("p",{style:{fontSize:"11px",color:"#DC2626",margin:"1px 0"},children:g},_)),n.warnings.slice(0,3).map((g,_)=>t.jsx("p",{style:{fontSize:"11px",color:"#D97706",margin:"1px 0"},children:g},_))]}),F.length>0&&t.jsxs(t.Fragment,{children:[t.jsxs("p",{style:{fontSize:j.xs,color:"#6B7280",margin:0},children:["Showing first ",F.length," of ",T.length," row(s)",T.length>F.length&&` (+${T.length-F.length} more will be imported)`]}),t.jsx("div",{style:{overflowX:"auto",borderRadius:8,border:"1px solid #E5E5E0"},children:t.jsxs("table",{style:{fontSize:"11px",borderCollapse:"collapse",width:"100%"},children:[t.jsx("thead",{children:t.jsxs("tr",{style:{background:"#F8F8F5"},children:[t.jsx("th",{style:Te,children:"#"}),t.jsx("th",{style:Te,children:"id"}),t.jsx("th",{style:Te,children:"name"}),t.jsx("th",{style:Te,children:"kind"}),t.jsx("th",{style:Te,children:"doc"})]})}),t.jsx("tbody",{children:F.map(g=>{const _=!g.id||!g.name||!g.kind;return t.jsxs("tr",{style:{background:_?"#FEF9F9":"transparent"},children:[t.jsx("td",{style:$n,children:g.rowIndex}),t.jsx("td",{style:{...$n,color:g.id?"#1a1a1a":"#DC2626"},children:g.id||"⚠ missing"}),t.jsx("td",{style:{...Ue,maxWidth:160,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:String(g.name||"—")}),t.jsx("td",{style:{...Ue,color:g.kind?"#1B3A4B":"#DC2626"},children:g.kind||"⚠ missing"}),t.jsx("td",{style:{...Ue,maxWidth:180,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",color:"#6B7280"},children:String(g.doc||"—")})]},g.rowIndex)})})]})})]}),F.length===0&&R.length===0&&t.jsx("p",{style:{fontSize:j.xs,color:"#9CA3AF",textAlign:"center",padding:"24px 0"},children:"No rows to preview."})]})]}),t.jsxs("div",{className:"flex items-center justify-between px-6 py-4",style:{borderTop:"1px solid #F0F0EC",background:"#FAFAF8",flexShrink:0},children:[t.jsx("div",{className:"flex gap-2",children:a!=="input"&&!n&&t.jsx("button",{onClick:()=>l(Y[J-1]),style:Vn,children:"← Back"})}),t.jsxs("div",{className:"flex gap-2 items-center",children:[t.jsx("button",{onClick:N,style:Vn,children:n!=null&&n.success?"Done":"Cancel"}),!n&&t.jsxs(t.Fragment,{children:[a==="input"&&t.jsx("button",{onClick:X,style:Ft,children:"Next →"}),a==="mapping"&&t.jsx("button",{onClick:U,style:Ft,children:"Preview →"}),a==="preview"&&t.jsx("button",{onClick:M,disabled:K||F.length===0,style:{...Ft,opacity:K||F.length===0?.5:1,cursor:K||F.length===0?"not-allowed":"pointer"},children:K?"Importing…":`Import ${T.length} element(s)`})]})]})]})]})})}const Dt={display:"block",fontSize:j.xs,fontWeight:600,color:"#374151",marginBottom:6},At={width:"100%",padding:"7px 10px",borderRadius:8,border:"1px solid #E5E5E0",fontSize:j.sm,color:"#1a1a1a",background:"#FAFAF8",boxSizing:"border-box"},fl={background:"rgba(255,255,255,0.12)",border:"none",borderRadius:8,color:"rgba(255,255,255,0.8)",cursor:"pointer",padding:"6px 10px",fontSize:"14px"},Ft={padding:"7px 18px",borderRadius:8,background:"#1B3A4B",border:"none",color:"#FFFFFF",fontSize:j.xs,fontWeight:600,cursor:"pointer"},Vn={padding:"7px 14px",borderRadius:8,background:"transparent",border:"1px solid #E5E5E0",color:"#374151",fontSize:j.xs,cursor:"pointer"},Te={padding:"5px 8px",textAlign:"left",fontWeight:600,fontSize:"10px",color:"#6B7280",borderBottom:"1px solid #E5E5E0",whiteSpace:"nowrap"},Ue={padding:"4px 8px",fontSize:"11px",color:"#1a1a1a",borderBottom:"1px solid #F5F5F2"},$n={...Ue,fontFamily:"monospace",fontSize:"10px",color:"#6B7280"};function hl(){var l,d;const e=k(c=>c.activeView),r=k(c=>c.model),n=k(c=>c.selectedElementId),o=k(c=>c.selectElement),s=k(c=>c.setActiveView),i=ve(),a=[];switch(e.type){case"diagram":{const c=ft(r,e.diagramId);if(c){const p=c.viewpointId==="__model"?"Model Viewpoint":((d=(l=r==null?void 0:r.viewpoints)==null?void 0:l.find(b=>b.id===c.viewpointId))==null?void 0:d.label)||c.viewpointId;a.push({label:p});const f=c.viewKind?xi[c.viewKind]:void 0,h=Fe[c.diagramType],S=(f==null?void 0:f.label)??(h==null?void 0:h.code)??c.diagramType;a.push({label:`${S}: ${c.name}`})}break}case"element-detail":{const c=e.elementId,p=r==null?void 0:r.elements[c];if(p){const f=p.shortId??p.id,h=f.split("-")[0];a.push({label:"Catalog",onClick:()=>i("/catalog")}),a.push({label:h,onClick:()=>i(`/catalog/${h}`)}),a.push({label:`${f} ${p.name}`})}break}case"dsm":a.push({label:"Tools"}),a.push({label:"DSM"});break;case"traceability":a.push({label:"Tools"}),a.push({label:"Traceability Matrix"});break;case"ontology":a.push({label:"Tools"}),a.push({label:"Ontology"});break}if(n&&r&&e.type!=="element-detail"){const c=r.elements[n];c&&a.push({label:c.name,onClick:()=>o(c.id)})}return a.length===0?null:t.jsxs("div",{className:"flex items-center gap-1 px-4 py-1.5",style:{background:"#FAFAF8",borderBottom:"1px solid #E5E5E0"},children:[t.jsx("button",{className:"text-xs px-1 py-0.5 rounded transition-colors",style:{color:"#9CA3AF"},onMouseEnter:c=>{c.currentTarget.style.color="#374151",c.currentTarget.style.background="#F0F0ED"},onMouseLeave:c=>{c.currentTarget.style.color="#9CA3AF",c.currentTarget.style.background="transparent"},onClick:()=>s({type:"welcome"}),title:"Home",children:"⌂"}),a.map((c,p)=>t.jsxs("span",{className:"flex items-center gap-1",children:[t.jsx("span",{className:"text-xs",style:{color:"#D1D5DB"},children:"/"}),c.onClick?t.jsx("button",{className:"text-xs px-1 py-0.5 rounded transition-colors",style:{color:"#374151"},onMouseEnter:f=>f.currentTarget.style.background="#F0F0ED",onMouseLeave:f=>f.currentTarget.style.background="transparent",onClick:c.onClick,children:c.label}):t.jsx("span",{className:"text-xs",style:{color:p===a.length-1?"#374151":"#9CA3AF"},children:c.label})]},p)),t.jsx("div",{className:"flex-1"}),t.jsxs("kbd",{className:"px-1.5 py-0.5 rounded text-xs",style:{background:"#F0F0ED",color:"#9CA3AF",fontSize:"9px"},children:["⌘","K"]})]})}const Un="memo-onboarding-completed",$e=[{title:"Welcome to MEMO Architect",description:"MEMO is a model-based systems engineering tool for medical devices. You'll land on the Dashboard — it shows your model health and suggests the next action. Let's take a quick tour.",target:"center",position:"center"},{title:"Model Explorer",description:"Browse your model elements organized by architecture layer. Switch to Views tab to see diagrams grouped by viewpoint.",target:"left panel",position:"left"},{title:"Unified Canvas",description:"The center area renders your selected view — diagrams, action flows, DSM matrices, and more.",target:"center canvas",position:"center"},{title:"Properties Panel",description:"View and edit element properties, relationships, and attributes. Select any element to see its details.",target:"right panel",position:"right"},{title:"Tools Menu",description:"Access analysis tools from the toolbar: DSM, Trace Matrix, Action Flow, Ontology, Scenarios, Diff, Compliance, and Stats.",target:"toolbar",position:"center"},{title:"Command Palette",description:"Press Cmd+K (or Ctrl+K) to quickly search elements, diagrams, viewpoints, and tools.",target:"keyboard shortcut",position:"center"},{title:"Working Sets",description:"Save and restore your workspace layout using the Sets tab in the Explorer panel. Great for switching between review contexts.",target:"explorer sets tab",position:"left"},{title:"You're all set!",description:"Start from the Dashboard — it shows your model status and suggests the next step. Use the Workflow Wizard (Tools menu) for a guided path through requirements, risk, and verification.",target:"center",position:"center"}];function gl(){const[e,r]=u.useState(!1),[n,o]=u.useState(0);u.useEffect(()=>{try{if(!localStorage.getItem(Un)){const h=setTimeout(()=>r(!0),800);return()=>clearTimeout(h)}}catch{}},[]);const s=u.useCallback(()=>{r(!1);try{localStorage.setItem(Un,"true")}catch{}},[]),i=u.useCallback(()=>{n>=$e.length-1?s():o(n+1)},[n,s]),a=u.useCallback(()=>{n>0&&o(n-1)},[n]);if(!e)return null;const l=$e[n],d=n===$e.length-1,c=n===0,p=()=>{switch(l.position){case"left":return{left:"300px",top:"50%",transform:"translateY(-50%)"};case"right":return{right:"300px",top:"50%",transform:"translateY(-50%)"};case"bottom":return{left:"50%",bottom:"80px",transform:"translateX(-50%)"};case"center":default:return{left:"50%",top:"50%",transform:"translate(-50%, -50%)"}}};return t.jsxs(t.Fragment,{children:[t.jsx("div",{className:"fixed inset-0 z-50",style:{background:"rgba(0,0,0,0.4)",backdropFilter:"blur(2px)"},onClick:s}),t.jsxs("div",{className:"fixed z-50 rounded-xl p-5 max-w-sm",style:{...p(),background:"#FFFFFF",boxShadow:"0 8px 32px rgba(0,0,0,0.2)",border:"1px solid #E5E5E0"},onClick:f=>f.stopPropagation(),children:[t.jsx("div",{className:"flex items-center gap-1 mb-3",children:$e.map((f,h)=>t.jsx("div",{className:"h-1 rounded-full transition-all",style:{width:h===n?"20px":"8px",background:h===n?"#2DD4A8":h<n?"#2DD4A880":"#E5E5E0"}},h))}),t.jsx("h3",{className:"text-sm font-semibold mb-1.5",style:{color:"#1B3A4B"},children:l.title}),t.jsx("p",{className:"text-xs leading-relaxed mb-4",style:{color:"#6B7280"},children:l.description}),t.jsxs("div",{className:"flex items-center gap-2",children:[!c&&t.jsx("button",{onClick:a,className:"px-3 py-1.5 text-xs rounded-lg",style:{background:"#F3F4F6",color:"#6B7280"},children:"Back"}),t.jsx("div",{className:"flex-1"}),t.jsx("button",{onClick:s,className:"px-3 py-1.5 text-xs rounded-lg",style:{color:"#9CA3AF"},children:"Skip tour"}),t.jsx("button",{onClick:i,className:"px-4 py-1.5 text-xs font-medium rounded-lg",style:{background:"#2DD4A8",color:"#FFFFFF"},children:d?"Get started":"Next"})]}),t.jsxs("div",{className:"text-center mt-2",style:{color:"#D1D5DB",fontSize:"10px"},children:[n+1," of ",$e.length]})]})]})}function yl(){const e=k(n=>n.restartRequired);if(!e)return null;const r=e.reason==="ontology-selection-changed"?"Ontology selection changed":"Ontology source changed";return t.jsx("div",{style:{position:"fixed",inset:0,zIndex:9999,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(15, 23, 42, 0.85)",backdropFilter:"blur(4px)"},children:t.jsxs("div",{style:{background:"#1E293B",border:"1px solid #F59E0B",borderRadius:"12px",padding:"32px 40px",maxWidth:"480px",width:"90%",textAlign:"center",color:"#F8FAFC",boxShadow:"0 25px 50px rgba(0,0,0,0.5)"},children:[t.jsx("div",{style:{fontSize:"2rem",marginBottom:"12px"},children:"⚠️"}),t.jsx("div",{style:{fontSize:"1.1rem",fontWeight:600,marginBottom:"8px",color:"#F59E0B"},children:"Restart Required"}),t.jsx("div",{style:{fontSize:"0.875rem",color:"#CBD5E1",marginBottom:"4px"},children:r}),t.jsx("div",{style:{fontSize:"0.75rem",color:"#94A3B8",marginBottom:"24px",fontFamily:"monospace"},children:e.changedFile}),t.jsx("div",{style:{fontSize:"0.875rem",color:"#E2E8F0",marginBottom:"24px",lineHeight:1.6},children:e.instruction}),t.jsx("div",{style:{display:"flex",gap:"12px",justifyContent:"center"},children:t.jsx("button",{onClick:()=>window.location.reload(),style:{background:"#F59E0B",color:"#0F172A",border:"none",borderRadius:"6px",padding:"8px 20px",fontWeight:600,fontSize:"0.875rem",cursor:"pointer"},children:"Reload page"})})]})})}const Wn={Hazard:"HZD",HazardousEvent:"HZD-EVT",HazardousSituation:"HZD-SIT",Risk:"RISK",RiskControlMeasure:"RISK-CTL",MitigationMeasure:"MIT",ResidualRisk:"RRISK",StakeholderRequirement:"STK-REQ",Requirement:"REQ",SoftwareSpecification:"SW-SPEC",InterfaceRequirement:"REQ",PerformanceRequirement:"PERF-REQ",SafetyRequirement:"SAF-REQ",RegulatoryRequirement:"REG-REQ",FunctionalRequirement:"REQ",NonFunctionalRequirement:"NFR",SystemComponent:"SYS-COMP",SoftwareComponent:"SW-COMP",HardwareComponent:"HW-COMP",Subsystem:"SUBSYS",Module:"MOD",Interface:"IF",Port:"PORT",Action:"ACT",ActionDefinition:"ACT-DEF",UseCase:"UC",Stakeholder:"STK",OperationalScenario:"OPS",Mission:"MSNS",Capability:"CAP",DesignInput:"DI",DesignOutput:"DO",VerificationActivity:"VER",ValidationActivity:"VAL",TestCase:"TC",Item:"ITM",Part:"PART"};function xl(e){return e.length<=3?e.toUpperCase():(e[0]+e.slice(1).replace(/[aeiouAEIOU]/g,"")).slice(0,3).toUpperCase()}function bl(e){if(Wn[e])return Wn[e];const r=e.replace(/([A-Z])/g," $1").trim().split(" ").filter(Boolean);return r.length===0?"EL":r.map(xl).join("-")}function vl(e){return e.split("-")[0]}function wl(e){return`/catalog/${e.split("-")[0]}/${e}`}function kl(e){return`/catalog/${e}`}function Sl(e,r){const n=e.toLowerCase().replace(/\s+/g,"-"),o=r.toLowerCase().replace(/\s+/g,"-");return`/diagrams/${n}/${o}`}function El(){const e=k(s=>s.model),r=ve(),n=u.useMemo(()=>{if(!e)return[];const s={};for(const i of Object.values(e.elements)){const a=bl(i.kind),l=vl(a);s[l]||(s[l]={count:0,kinds:new Set,layer:i.layer}),s[l].count++,s[l].kinds.add(i.kind)}return Object.entries(s).sort((i,a)=>a[1].count-i[1].count)},[e]);if(!e)return t.jsx("div",{style:{flex:1,display:"flex",alignItems:"center",justifyContent:"center",background:"#F7F7F5"},children:t.jsx("p",{style:{color:y.muted,fontSize:j.sm},children:"Loading…"})});const o=Object.keys(e.elements).length;return t.jsxs("div",{style:{flex:1,overflow:"auto",background:"#F7F7F5",padding:"32px 40px"},children:[t.jsx("h1",{style:{fontSize:"20px",fontWeight:700,color:y.primary,marginBottom:"4px",marginTop:0},children:"Catalog"}),t.jsxs("p",{style:{color:y.muted,fontSize:j.sm,marginTop:0,marginBottom:"24px"},children:[o," elements across ",n.length," families"]}),t.jsx("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fill, minmax(200px, 1fr))",gap:"12px"},children:n.map(([s,i])=>{const a=re[i.layer]??"#9CA3AF";return t.jsx(jl,{family:s,count:i.count,kinds:i.kinds,color:a,onClick:()=>r(kl(s))},s)})})]})}function jl({family:e,count:r,kinds:n,color:o,onClick:s}){return t.jsxs("div",{onClick:s,style:{background:y.surface,border:`1px solid ${y.border}`,borderRadius:"10px",padding:"16px",cursor:"pointer",transition:"box-shadow 0.15s, border-color 0.15s",borderTop:`3px solid ${o}`},onMouseEnter:i=>{i.currentTarget.style.boxShadow="0 4px 12px rgba(0,0,0,0.08)",i.currentTarget.style.borderTopColor=o},onMouseLeave:i=>{i.currentTarget.style.boxShadow="none"},children:[t.jsx("div",{style:{fontWeight:700,fontSize:"15px",color:y.primary,marginBottom:"4px"},children:e}),t.jsx("div",{style:{fontSize:"22px",fontWeight:800,color:o,lineHeight:1,marginBottom:"6px"},children:r}),t.jsxs("div",{style:{fontSize:"11px",color:y.muted,lineHeight:"1.5"},children:[Array.from(n).slice(0,3).join(", "),n.size>3&&` +${n.size-3} more`]})]})}function Cl(){var s;const e=k(i=>i.model),r=ve(),n=u.useMemo(()=>{const i=(e==null?void 0:e.diagrams)??[],a=new Map;for(const l of i){const d=l.viewpointId==="__model"?"Model":l.viewpointId,c=a.get(d);c?c.push(l):a.set(d,[l])}return[...a.entries()].map(([l,d])=>({viewpoint:l,items:[...d].sort((c,p)=>c.name.localeCompare(p.name))})).sort((l,d)=>d.items.length-l.items.length||l.viewpoint.localeCompare(d.viewpoint))},[e]);if(!e)return t.jsx("div",{style:{flex:1,display:"flex",alignItems:"center",justifyContent:"center",background:"#F7F7F5"},children:t.jsx("p",{style:{color:y.muted,fontSize:j.sm},children:"Loading…"})});const o=((s=e.diagrams)==null?void 0:s.length)??0;return t.jsxs("div",{style:{flex:1,overflow:"auto",background:"#F7F7F5",padding:"32px 40px"},children:[t.jsx("h1",{style:{fontSize:"20px",fontWeight:700,color:y.primary,marginBottom:"4px",marginTop:0},children:"Diagrams"}),t.jsxs("p",{style:{color:y.muted,fontSize:j.sm,marginTop:0,marginBottom:"24px"},children:[o," ",o===1?"diagram":"diagrams"," across ",n.length," ",n.length===1?"viewpoint":"viewpoints"]}),o===0&&t.jsx("p",{style:{color:y.muted,fontSize:j.sm},children:"This model defines no diagrams yet."}),n.map(i=>t.jsxs("section",{style:{marginBottom:"28px"},children:[t.jsxs("h2",{style:{fontSize:"11px",fontWeight:700,color:y.muted,textTransform:"uppercase",letterSpacing:"0.06em",margin:"0 0 10px 0"},children:[i.viewpoint,t.jsx("span",{style:{marginLeft:8,fontWeight:400},children:i.items.length})]}),t.jsx("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fill, minmax(220px, 1fr))",gap:"12px"},children:i.items.map(a=>t.jsx(Dl,{diagram:a,onClick:()=>r(Sl(a.diagramType,a.id))},a.id))})]},i.viewpoint))]})}function Dl({diagram:e,onClick:r}){var i;const n=Fe[e.diagramType],o=(n==null?void 0:n.color)??"#6B7280",s=((i=e.elementIds)==null?void 0:i.length)??0;return t.jsxs("div",{onClick:r,role:"button",tabIndex:0,onKeyDown:a=>{(a.key==="Enter"||a.key===" ")&&(a.preventDefault(),r())},style:{background:y.surface,border:`1px solid ${y.border}`,borderRadius:"10px",padding:"14px 16px",cursor:"pointer",transition:"box-shadow 0.15s",borderTop:`3px solid ${o}`},onMouseEnter:a=>{a.currentTarget.style.boxShadow="0 4px 12px rgba(0,0,0,0.08)"},onMouseLeave:a=>{a.currentTarget.style.boxShadow="none"},children:[t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6,marginBottom:6},children:[n&&t.jsx("span",{style:{background:o+"18",color:o,borderRadius:4,padding:"1px 5px",fontSize:"10px",fontWeight:700},children:n.code}),e.auto&&t.jsx("span",{style:{fontSize:"10px",color:y.muted},children:"auto"})]}),t.jsx("div",{style:{fontWeight:600,fontSize:"14px",color:y.primary,marginBottom:4},children:e.name}),t.jsxs("div",{style:{fontSize:"11px",color:y.muted,lineHeight:1.5},children:[(n==null?void 0:n.fullName)??e.diagramType,s>0&&` · ${s} element${s===1?"":"s"}`]})]})}function Al({family:e}){const r=k(d=>d.model),n=ve(),[o,s]=u.useState(""),i=u.useMemo(()=>r?Object.values(r.elements).filter(d=>{const c=d.shortId??"";return c.startsWith(e+"-")||c.startsWith(e+" ")}):[],[r,e]),a=u.useMemo(()=>{if(!o.trim())return i;const d=o.toLowerCase();return i.filter(c=>c.name.toLowerCase().includes(d)||(c.shortId??"").toLowerCase().includes(d)||c.kind.toLowerCase().includes(d))},[i,o]),l=u.useMemo(()=>{const d={};for(const c of i)d[c.kind]=(d[c.kind]??0)+1;return d},[i]);return r?i.length===0?t.jsx(Rt,{family:e,children:t.jsxs("p",{style:{color:y.muted,fontSize:j.sm},children:["No elements found with family prefix ",t.jsx("code",{children:e}),"."]})}):t.jsxs(Rt,{family:e,children:[t.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:"6px",marginBottom:"16px"},children:Object.entries(l).map(([d,c])=>{const p=re[d]??"#9CA3AF";return t.jsxs("span",{style:{fontSize:j.xs,padding:"2px 8px",borderRadius:"12px",background:p+"20",color:p,border:`1px solid ${p}40`,fontWeight:500},children:[d," · ",c]},d)})}),t.jsx("input",{type:"search",placeholder:`Search ${i.length} elements…`,value:o,onChange:d=>s(d.target.value),style:{width:"100%",boxSizing:"border-box",padding:"7px 12px",fontSize:j.sm,border:`1px solid ${y.border}`,borderRadius:"6px",background:y.surface,color:y.primary,outline:"none",marginBottom:"12px"}}),t.jsxs("div",{style:{background:y.surface,border:`1px solid ${y.border}`,borderRadius:"8px",overflow:"hidden"},children:[t.jsxs("div",{style:{display:"grid",gridTemplateColumns:"140px 1fr 120px 120px",padding:"8px 16px",background:y.surfaceAlt,borderBottom:`1px solid ${y.border}`,fontSize:j.xs,fontWeight:600,color:y.muted,gap:"12px"},children:[t.jsx("span",{children:"ID"}),t.jsx("span",{children:"Name"}),t.jsx("span",{children:"Kind"}),t.jsx("span",{children:"Layer"})]}),a.length===0?t.jsxs("div",{style:{padding:"24px 16px",color:y.muted,fontSize:j.sm,textAlign:"center"},children:['No results for "',o,'"']}):a.map((d,c)=>t.jsx(Fl,{element:d,zebra:c%2===1,onClick:()=>n(wl(d.shortId??d.id))},d.id))]}),t.jsxs("p",{style:{color:y.faint,fontSize:"11px",marginTop:"8px"},children:[a.length," of ",i.length," elements shown"]})]}):t.jsx(Rt,{family:e,children:t.jsx("p",{style:{color:y.muted,fontSize:j.sm},children:"Loading model…"})})}function Fl({element:e,zebra:r,onClick:n}){const o=re[e.layer]??"#9CA3AF";return t.jsxs("div",{onClick:n,style:{display:"grid",gridTemplateColumns:"140px 1fr 120px 120px",padding:"10px 16px",gap:"12px",background:r?"#FAFAF8":y.surface,cursor:"pointer",borderBottom:`1px solid ${y.borderLight}`,alignItems:"center",transition:"background 0.1s"},onMouseEnter:s=>s.currentTarget.style.background="#F0FDF4",onMouseLeave:s=>s.currentTarget.style.background=r?"#FAFAF8":y.surface,children:[t.jsx("code",{style:{fontSize:"11px",color:"#2DD4A8",fontWeight:600,fontFamily:"monospace"},children:e.shortId??e.id}),t.jsx("span",{style:{fontSize:j.sm,color:y.primary,fontWeight:500,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:e.name}),t.jsx("span",{style:{fontSize:j.xs,color:y.secondary},children:e.kind}),t.jsx("span",{style:{fontSize:"11px",color:o,fontWeight:500,background:o+"15",padding:"2px 6px",borderRadius:"4px",width:"fit-content"},children:e.layer})]})}function Rt({family:e,children:r}){const n=ve();return t.jsxs("div",{style:{flex:1,overflow:"auto",background:"#F7F7F5",padding:"32px 40px"},children:[t.jsxs("nav",{style:{fontSize:j.xs,color:y.muted,marginBottom:"20px"},children:[t.jsx("button",{onClick:()=>n("/catalog"),style:{background:"none",border:"none",color:"#2DD4A8",cursor:"pointer",padding:0,fontSize:j.xs},children:"Catalog"})," / ",t.jsx("span",{style:{color:y.primary,fontWeight:600},children:e})]}),t.jsx("h1",{style:{fontSize:"20px",fontWeight:700,color:y.primary,marginBottom:"6px",marginTop:0},children:e}),r]})}const Rl=u.lazy(()=>oe(()=>import("./DiagramEditor-Y4sSx9nO.js"),__vite__mapDeps([0,1,2])).then(e=>({default:e.DiagramEditor}))),Tl=u.lazy(()=>oe(()=>import("./DSMView-DbC_fUKT.js"),__vite__mapDeps([3,1,2])).then(e=>({default:e.DSMView}))),Il=u.lazy(()=>oe(()=>import("./OntologyViewer-C5ik2Kmi.js"),__vite__mapDeps([4,1,2])).then(e=>({default:e.OntologyViewer}))),_l=u.lazy(()=>oe(()=>import("./TraceabilityMatrix-Bw5ej-So.js"),__vite__mapDeps([5,1,2])).then(e=>({default:e.TraceabilityMatrix}))),Nl=u.lazy(()=>oe(()=>import("./ScenarioEditor-BRWvcD2f.js"),__vite__mapDeps([6,1,2])).then(e=>({default:e.ScenarioEditor}))),Ml=u.lazy(()=>oe(()=>import("./ModelDiff-MM5NKKXK.js"),__vite__mapDeps([7,1,2])).then(e=>({default:e.ModelDiff}))),Ol=u.lazy(()=>oe(()=>import("./ComplianceWizard-Bi9PLmJH.js"),__vite__mapDeps([8,1,2])).then(e=>({default:e.ComplianceWizard}))),Pl=u.lazy(()=>oe(()=>import("./StatisticsDashboard-C67W4pb0.js"),__vite__mapDeps([9,1,2])).then(e=>({default:e.StatisticsDashboard}))),zl=u.lazy(()=>oe(()=>import("./DhfDashboard-BPXIYJnw.js"),__vite__mapDeps([10,1,2])).then(e=>({default:e.DhfDashboard}))),Bl=u.lazy(()=>oe(()=>import("./DhfWorkbench-CgFdQIts.js"),__vite__mapDeps([11,1,2])).then(e=>({default:e.DhfWorkbench}))),Ll=u.lazy(()=>oe(()=>import("./AskPanel-Dqc6aaqg.js"),__vite__mapDeps([12,1,2])).then(e=>({default:e.AskPanel}))),ql=u.lazy(()=>oe(()=>import("./SysmlGenerator-BwRhtec-.js"),__vite__mapDeps([13,1,2])).then(e=>({default:e.SysmlGenerator}))),Fr=u.lazy(()=>oe(()=>import("./ElementDetailView-B946aM3p.js"),__vite__mapDeps([14,1,2])).then(e=>({default:e.ElementDetailView}))),Vl=u.lazy(()=>oe(()=>import("./Dashboard-6Dgma4kY.js"),__vite__mapDeps([15,1,2])).then(e=>({default:e.Dashboard}))),$l=u.lazy(()=>oe(()=>import("./ReviewDashboard-DwlsAVBa.js"),__vite__mapDeps([16,1,2])).then(e=>({default:e.ReviewDashboard}))),Ul=u.lazy(()=>oe(()=>import("./WorkflowWizard-BwGWzMkE.js"),__vite__mapDeps([17,1,2])).then(e=>({default:e.WorkflowWizard}))),Wl=u.lazy(()=>oe(()=>import("./TabularView-CTQgMG25.js"),__vite__mapDeps([18,1,2])).then(e=>({default:e.TabularView}))),Hl=u.lazy(()=>oe(()=>import("./ImportView-HCDzL9Xx.js"),__vite__mapDeps([19,1,2])).then(e=>({default:e.ImportView})));function Ie(){const e=k(s=>s.activeView);k(s=>s.selectedViewpointId);const r=k(s=>s.selectedDiagramId),n=k(s=>s.selectDiagram);u.useEffect(()=>{e.type==="diagram"&&r!==e.diagramId&&n(e.diagramId)},[e,r,n]);const o=()=>{switch(e.type){case"diagram":return t.jsx(Rl,{diagramId:e.diagramId});case"dsm":return t.jsx(Tl,{});case"traceability":return t.jsx(_l,{});case"tabular":return t.jsx(Wl,{});case"ontology":case"ontology-detail":return t.jsx(Il,{});case"scenario-editor":return t.jsx(Nl,{});case"model-diff":return t.jsx(Ml,{});case"compliance-wizard":return t.jsx(Ol,{});case"statistics":return t.jsx(Pl,{});case"dhf-dashboard":case"dhf-document":return t.jsx(Bl,{});case"dhf-dashboard-legacy":return t.jsx(zl,{});case"ask":return t.jsx(Ll,{});case"sysml-generator":return t.jsx(ql,{});case"element-detail":return t.jsx(Fr,{});case"dashboard":return t.jsx(Vl,{});case"review-dashboard":return t.jsx($l,{});case"workflow-wizard":return t.jsx(Ul,{});case"import":return t.jsx(Hl,{});case"welcome":default:return t.jsx(Hn,{})}};return(e.type==="welcome"||e.type==="dashboard")&&e.type==="welcome"?t.jsx(Hn,{}):t.jsx(u.Suspense,{fallback:t.jsx(Rr,{}),children:o()})}function Rr(){return t.jsx("div",{className:"flex-1 flex items-center justify-center",style:{background:"#F7F7F5"},children:t.jsxs("div",{className:"text-center",style:{color:"#9CA3AF"},children:[t.jsx("img",{src:"/logo.png",alt:"MEMO Logo",style:{width:"180px",marginBottom:"24px",opacity:.4,filter:"grayscale(1)"},className:"animate-pulse"}),t.jsx("div",{className:"text-xs mt-2",children:"Loading view..."})]})})}const ct="linear-gradient(135deg, #EEF7F3 0%, #EAF2F8 55%, #F2EEF8 100%)";function Hn(){var d;const e=k(c=>c.model),r=k(c=>c.setActiveView),n=k(c=>c.selectElement),o=k(c=>c.setExplorerTab),s=((d=e==null?void 0:e.diagrams)==null?void 0:d.length)??0,i=e?Object.keys(e.elements).length:0,a=u.useMemo(()=>{if(!e)return[];const c=new Map;for(const p of Object.values(e.elements))c.has(p.kind)||c.set(p.kind,p);return Array.from(c.values()).slice(0,8)},[e]);function l(c){n(c),r({type:"element-detail",elementId:c})}return t.jsxs("div",{className:"flex-1 flex flex-col items-center justify-center overflow-auto",style:{background:ct,padding:"48px 40px"},children:[t.jsx("img",{src:"/logo.png",alt:"MEMO Logo",style:{width:"520px",maxWidth:"80vw",maxHeight:"40vh",objectFit:"contain",marginBottom:"-36px",opacity:.97}}),t.jsx("h2",{style:{fontSize:"18px",fontWeight:700,color:"#1B3A4B",marginBottom:"6px",marginTop:0},children:"MEMO Architect"}),t.jsx("p",{style:{fontSize:"14px",color:"#4B6E80",marginTop:0,marginBottom:"24px",maxWidth:"480px",textAlign:"center",lineHeight:"1.6"},children:"SysML-based medical device architecture tool, aligned with ISO 14971 and IEC 62304."}),i>0&&t.jsxs("div",{className:"flex items-center gap-4 mb-6",style:{fontSize:"13px",color:"#4B6E80"},children:[t.jsxs("span",{children:[t.jsx("strong",{style:{color:"#1B3A4B"},children:i})," elements"]}),t.jsx("span",{style:{color:"#CBD5DB"},children:"·"}),t.jsxs("span",{children:[t.jsx("strong",{style:{color:"#1B3A4B"},children:s})," diagrams"]}),(e==null?void 0:e.relationships)&&t.jsxs(t.Fragment,{children:[t.jsx("span",{style:{color:"#CBD5DB"},children:"·"}),t.jsxs("span",{children:[t.jsx("strong",{style:{color:"#1B3A4B"},children:e.relationships.length})," relationships"]})]})]}),t.jsxs("div",{className:"flex gap-3 mb-8",children:[t.jsx("button",{onClick:()=>o("model"),className:"px-5 py-2.5 text-sm font-semibold rounded-lg transition-all",style:{background:"#1B3A4B",color:"#FFFFFF",border:"none",cursor:"pointer"},onMouseEnter:c=>c.currentTarget.style.background="#244D63",onMouseLeave:c=>c.currentTarget.style.background="#1B3A4B",children:"Browse Model"}),s>0&&t.jsxs("button",{onClick:()=>o("views"),className:"px-5 py-2.5 text-sm font-semibold rounded-lg transition-all",style:{background:"#2DD4A815",color:"#1B3A4B",border:"1px solid #2DD4A840",cursor:"pointer"},onMouseEnter:c=>c.currentTarget.style.background="#2DD4A830",onMouseLeave:c=>c.currentTarget.style.background="#2DD4A815",children:["View Diagrams (",s,")"]})]}),a.length>0&&t.jsxs("div",{style:{width:"100%",maxWidth:"680px"},children:[t.jsx("div",{style:{fontSize:"11px",fontWeight:600,color:"#7A9BAA",textTransform:"uppercase",letterSpacing:"0.08em",marginBottom:"10px"},children:"Quick Browse"}),t.jsx("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fill, minmax(180px, 1fr))",gap:"8px"},children:a.map(c=>t.jsxs("button",{onClick:()=>l(c.id),style:{textAlign:"left",background:"rgba(255,255,255,0.7)",border:"1px solid rgba(255,255,255,0.9)",borderRadius:"8px",padding:"10px 12px",cursor:"pointer",transition:"all 0.15s",backdropFilter:"blur(4px)"},onMouseEnter:p=>{p.currentTarget.style.background="rgba(255,255,255,0.95)",p.currentTarget.style.boxShadow="0 2px 8px rgba(0,0,0,0.08)",p.currentTarget.style.transform="translateY(-1px)"},onMouseLeave:p=>{p.currentTarget.style.background="rgba(255,255,255,0.7)",p.currentTarget.style.boxShadow="none",p.currentTarget.style.transform="none"},children:[t.jsx("div",{style:{fontSize:"10px",color:"#7A9BAA",fontWeight:600,textTransform:"uppercase",letterSpacing:"0.05em",marginBottom:"3px"},children:c.kind}),t.jsx("div",{style:{fontSize:"13px",color:"#1B3A4B",fontWeight:500,whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"},children:c.name}),c.shortId&&t.jsx("div",{style:{fontSize:"10px",color:"#9CB8C5",marginTop:"2px",fontFamily:"monospace"},children:c.shortId})]},c.id))})]})]})}function Kl(){const e=k(h=>h.connected),r=k(h=>h.model),n=k(h=>h.activeView),o=k(h=>h.selectedElementIds),{pathname:s}=ge(),i=s.startsWith("/catalog"),a=k(h=>h.activeMode),l=k(h=>h.sidebarCollapsed),d=k(h=>h.toggleSidebar),c=k(h=>h.toggleGapBar);u.useEffect(()=>{const h=S=>{(S.metaKey||S.ctrlKey)&&S.shiftKey&&S.key==="P"&&(S.preventDefault(),c())};return window.addEventListener("keydown",h),()=>window.removeEventListener("keydown",h)},[c]);const p=n.type!=="scenario-editor"&&n.type!=="dsm";u.useEffect(()=>{p&&l&&d()},[n.type]),u.useEffect(()=>{Bs()||xr()},[]);const f=r?Object.keys(r.elements).length:0;return e?r?f===0?t.jsxs("div",{className:"flex flex-col h-screen",style:{background:ct,color:"#1a1a1a"},children:[t.jsx(tt,{}),t.jsx("div",{className:"flex-1 flex items-center justify-center",children:t.jsxs("div",{className:"text-center max-w-lg",style:{lineHeight:"1.7"},children:[t.jsx("img",{src:"/logo.png",alt:"MEMO Logo",style:{width:"380px",maxWidth:"80vw",display:"block",margin:"0 auto -20px auto",opacity:.35,filter:"grayscale(1)"}}),t.jsx("h2",{style:{fontSize:"20px",fontWeight:700,color:"#1B3A4B",marginBottom:"8px"},children:"Your model is empty"}),t.jsxs("p",{style:{fontSize:"14px",color:"#4B6E80",marginBottom:"20px"},children:["Connected successfully — but no ",t.jsx("code",{children:".sysml"})," elements found yet."]}),t.jsxs("div",{style:{textAlign:"left",background:"rgba(255,255,255,0.65)",borderRadius:"10px",padding:"16px 20px",fontSize:"13px",border:"1px solid rgba(255,255,255,0.9)"},children:[t.jsx("p",{style:{fontWeight:600,marginBottom:"8px",color:"#1B3A4B"},children:"Get started:"}),t.jsxs("ol",{style:{paddingLeft:"18px",margin:0,color:"#4B6E80"},children:[t.jsxs("li",{style:{marginBottom:"6px"},children:["Create a ",t.jsx("code",{children:".sysml"})," file in your ",t.jsx("code",{children:"model/"})," directory"]}),t.jsxs("li",{style:{marginBottom:"6px"},children:["Import from CSV: ",t.jsx("code",{children:"pnpm memo import template elements"})]}),t.jsxs("li",{children:["Scaffold a new project: ",t.jsx("code",{children:"pnpm memo init my-device"})]})]})]})]})})]}):t.jsxs("div",{className:"flex flex-col h-screen",style:{background:"#F7F7F5",color:"#1a1a1a"},children:[t.jsx(Ql,{}),t.jsx(tt,{}),t.jsx(yi,{}),t.jsx(hl,{}),t.jsxs("div",{className:"flex flex-1 overflow-hidden",children:[p&&t.jsx(qa,{}),t.jsx("div",{className:"flex-1 flex flex-col",style:{minWidth:0},children:t.jsxs(No,{children:[t.jsx(pe,{path:"/catalog",element:t.jsx(El,{})}),t.jsx(pe,{path:"/catalog/:family",element:t.jsx(Gl,{})}),t.jsx(pe,{path:"/catalog/:family/:shortId",element:t.jsx(Yl,{})}),t.jsx(pe,{path:"/diagrams",element:t.jsx(Cl,{})}),t.jsx(pe,{path:"/diagrams/:diagramType/:diagramId",element:t.jsx(Jl,{})}),li().map(h=>t.jsx(pe,{path:h,element:t.jsx(Ie,{})},h)),t.jsx(pe,{path:"/ontology/:packageName",element:t.jsx(Ie,{})}),t.jsx(pe,{path:"/ontology/:packageName/:layerId",element:t.jsx(Ie,{})}),t.jsx(pe,{path:"/dhf/:docId",element:t.jsx(Ie,{})}),t.jsx(pe,{path:"*",element:t.jsx(Ie,{})})]})}),n.type!=="element-detail"&&n.type!=="scenario-editor"&&n.type!=="ontology"&&n.type!=="ontology-detail"&&n.type!=="ask"&&n.type!=="sysml-generator"&&!i&&a!=="dhf"&&a!=="ontology"&&(o.size>=2?t.jsx(cl,{}):t.jsx(il,{}))]}),t.jsx(dl,{}),t.jsx(ul,{}),t.jsx(ml,{}),t.jsx(gl,{}),t.jsx(yl,{})]}):t.jsxs("div",{className:"flex flex-col h-screen",style:{background:ct,color:"#1a1a1a"},children:[t.jsx(tt,{}),t.jsx("div",{className:"flex-1 flex items-center justify-center",children:t.jsxs("div",{className:"text-center",children:[t.jsx("img",{src:"/logo.png",alt:"MEMO Logo",style:{width:"360px",maxWidth:"80vw",display:"block",margin:"0 auto -20px auto",opacity:.45,filter:"grayscale(1)"},className:"animate-pulse"}),t.jsx("h2",{style:{fontSize:"18px",fontWeight:700,color:"#1B3A4B",marginBottom:"6px"},children:"MEMO Architect"}),t.jsx("p",{style:{color:"#6B7280",fontSize:"14px"},children:"Loading model data…"})]})})]}):t.jsxs("div",{className:"flex flex-col h-screen",style:{background:ct,color:"#1a1a1a"},children:[t.jsx(tt,{}),t.jsx("div",{className:"flex-1 flex items-center justify-center",children:t.jsxs("div",{className:"text-center max-w-md",children:[t.jsx("img",{src:"/logo.png",alt:"MEMO Logo",style:{width:"360px",maxWidth:"80vw",display:"block",margin:"0 auto -20px auto",opacity:.45,filter:"grayscale(1)"},className:"animate-pulse"}),t.jsx("h2",{style:{fontSize:"18px",fontWeight:700,color:"#1B3A4B",marginBottom:"8px"},children:"MEMO Architect"}),t.jsx("p",{style:{color:"#6B7280",fontSize:"14px",marginBottom:"20px"},children:"Connecting to dev server…"}),t.jsxs("div",{style:{color:"#6B7280",fontSize:"13px",lineHeight:"1.6",textAlign:"left",background:"rgba(255,255,255,0.6)",borderRadius:"10px",padding:"16px 20px",border:"1px solid rgba(255,255,255,0.9)"},children:[t.jsx("p",{style:{fontWeight:600,color:"#374151",marginBottom:"8px"},children:"Start the MEMO dev server:"}),t.jsx("code",{style:{display:"block",margin:"0 0 12px",padding:"8px 14px",background:"#1B3A4B",color:"#2DD4A8",borderRadius:"6px",fontFamily:"monospace",fontSize:"13px"},children:"pnpm architect -- dev --port 3000"}),t.jsx("p",{style:{color:"#9CA3AF",marginBottom:"8px"},children:"Or try the example project:"}),t.jsx("code",{style:{display:"block",padding:"8px 14px",background:"#1B3A4B",color:"#2DD4A8",borderRadius:"6px",fontFamily:"monospace",fontSize:"13px"},children:"pnpm example:dev"})]})]})})]})}function Gl(){const{family:e=""}=Vt();return t.jsx(Al,{family:e.toUpperCase()})}function Yl(){const{shortId:e=""}=Vt(),r=k(s=>s.model),n=k(s=>s.setActiveView),o=k(s=>s.selectElement);return u.useEffect(()=>{if(!r)return;const s=Object.values(r.elements).find(i=>(i.shortId??i.id)===e);s&&(o(s.id),n({type:"element-detail",elementId:s.id}))},[e,r,n,o]),t.jsx(u.Suspense,{fallback:t.jsx(Rr,{}),children:t.jsx(Fr,{})})}function Jl(){const{diagramId:e=""}=Vt(),r=k(s=>s.model),n=k(s=>s.selectDiagram),o=k(s=>s.setActiveView);return u.useEffect(()=>{var i;if(!r)return;const s=(i=r.diagrams)==null?void 0:i.find(a=>a.id===e||a.id.toLowerCase().replace(/\s+/g,"-")===e);s&&(n(s.id),o({type:"diagram",diagramId:s.id}))},[e,r,n,o]),t.jsx(Ie,{})}function Ql(){const e=k(d=>d.activeView),r=k(d=>d.model),n=k(d=>d.setActiveView),o=ve(),s=ge(),i=xo(),a=u.useRef(!1),l=u.useRef(!1);return u.useEffect(()=>{const d=!a.current;if(a.current=!0,!d&&i!=="POP")return;const c=ii(s.pathname,s.search);c&&JSON.stringify(c)!==JSON.stringify(e)&&(l.current=!0,n(c))},[s.pathname,s.search,i]),u.useEffect(()=>{var c;if(!a.current)return;if(l.current){l.current=!1;return}if(e.type==="welcome"&&s.pathname!=="/"||ai(s.pathname)&&!(e.type==="diagram"||e.type==="element-detail"))return;let d=null;if(e.type==="element-detail"&&r){const p=r.elements[e.elementId];if(p){const f=p.shortId??p.id;d=`/catalog/${f.split("-")[0]}/${f}`}}else if(e.type==="diagram"&&r){const p=(c=r.diagrams)==null?void 0:c.find(f=>f.id===e.diagramId);p&&(d=`/diagrams/${bn(p.diagramType)}/${bn(p.id)}`)}else d=si(e);d&&s.pathname+s.search!==d&&o(d,{replace:!1})},[e,r]),null}Mr.createRoot(document.getElementById("root")).render(t.jsx(u.StrictMode,{children:t.jsx(os,{children:t.jsx(Kl,{})})}));export{y as C,Fe as D,fc as E,j as F,rt as L,hc as R,pc as S,xi as V,oe as _,uc as a,nc as b,ec as c,dc as d,Ot as e,re as f,ft as g,ti as h,Re as i,cc as j,ac as k,tc as l,lc as m,mc as n,wr as o,ic as p,fn as q,bi as r,ri as s,gc as t,k as u,gr as v,rc as w,sc as x,oc as y};
|