diff --git a/.github/scripts/process_issue.py b/.github/scripts/process_issue.py new file mode 100644 index 0000000..0328e04 --- /dev/null +++ b/.github/scripts/process_issue.py @@ -0,0 +1,113 @@ +""" +Processes a GitHub issue and updates reproinventory_data.yaml and +frontend/public/data/reproinventory_data.json accordingly. + +Reads: + /tmp/issue_body.txt - full issue body + /tmp/issue_title.txt - issue title + +Environment variables: + ISSUE_LABEL - one of: new-material, edit-material, delete-material + ISSUE_NUMBER - issue number (for logging) +""" + +import os +import re +import json +import yaml + +YAML_PATH = "model/reproinventory_data.yaml" +JSON_PATH = "frontend/public/data/reproinventory_data.json" + +ARRAY_FIELDS = [ + "tag_team", "level", "platform", "keywords", "instruction_medium", + "delivery", "language", "programming_language", "neuroimaging_software", + "imaging_modality", "quadrants", "source", "prerequisite", +] + +def normalize_entry(entry): + """Ensure all array fields are lists, not scalars.""" + for field in ARRAY_FIELDS: + val = entry.get(field) + if val is not None and not isinstance(val, list): + entry[field] = [val] + return entry + +label = os.environ["ISSUE_LABEL"] +issue_number = os.environ["ISSUE_NUMBER"] + +with open("/tmp/issue_body.txt", "r", encoding="utf-8") as f: + issue_body = f.read() + +with open("/tmp/issue_title.txt", "r", encoding="utf-8") as f: + issue_title = f.read().strip() + +# Load current data +with open(YAML_PATH, "r", encoding="utf-8") as f: + data = [normalize_entry(e) for e in (yaml.safe_load(f) or [])] + + +def extract_yaml_block(body): + """Extract the first ```yaml ... ``` block from the issue body.""" + match = re.search(r"```yaml\s*\n(.*?)\n```", body, re.DOTALL) + if not match: + raise ValueError("No YAML block found in issue body.") + return yaml.safe_load(match.group(1)) + + +if label == "new-material": + entry = normalize_entry(extract_yaml_block(issue_body)) + + # Assign a new numeric ID + numeric_ids = [e["id"] for e in data if isinstance(e.get("id"), int)] + entry["id"] = max(numeric_ids, default=0) + 1 + + data.append(entry) + print(f"Added new entry with ID {entry['id']}: {entry.get('course_name')}") + +elif label == "edit-material": + entry = normalize_entry(extract_yaml_block(issue_body)) + entry_id = entry.get("id") + + replaced = False + for i, e in enumerate(data): + if str(e.get("id")) == str(entry_id): + data[i] = entry + replaced = True + break + + if not replaced: + raise ValueError(f"Entry with ID '{entry_id}' not found in data.") + print(f"Updated entry ID {entry_id}: {entry.get('course_name')}") + +elif label == "delete-material": + # Extract ID from issue title: "Delete material: Name (ID: 123)" + match = re.search(r"ID:\s*(\S+?)\)", issue_title) + if not match: + raise ValueError(f"Could not extract ID from issue title: {issue_title!r}") + + raw_id = match.group(1) + try: + entry_id = int(raw_id) + except ValueError: + entry_id = raw_id + + original_len = len(data) + data = [e for e in data if str(e.get("id")) != str(entry_id)] + + if len(data) == original_len: + raise ValueError(f"Entry with ID '{entry_id}' not found in data.") + print(f"Deleted entry with ID {entry_id}") + +else: + raise ValueError(f"Unknown label: {label!r}") + +# Write updated YAML +with open(YAML_PATH, "w", encoding="utf-8") as f: + yaml.dump(data, f, sort_keys=False, default_flow_style=False, allow_unicode=True) + +# Write updated JSON +with open(JSON_PATH, "w", encoding="utf-8") as f: + json.dump(data, f, indent=2, ensure_ascii=False) + +print(f"Successfully processed '{label}' for issue #{issue_number}.") diff --git a/.github/workflows/create-pr-from-issue.yml b/.github/workflows/create-pr-from-issue.yml new file mode 100644 index 0000000..a2e7451 --- /dev/null +++ b/.github/workflows/create-pr-from-issue.yml @@ -0,0 +1,65 @@ +name: Create PR from Issue + +on: + issues: + types: [labeled] + +jobs: + create-pr: + runs-on: ubuntu-latest + if: contains(fromJSON('["new-material", "edit-material", "delete-material"]'), github.event.label.name) + + permissions: + contents: write + pull-requests: write + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install dependencies + run: pip install pyyaml + + - name: Write issue data to files + env: + ISSUE_BODY: ${{ github.event.issue.body }} + ISSUE_TITLE: ${{ github.event.issue.title }} + run: | + printf '%s' "$ISSUE_BODY" > /tmp/issue_body.txt + printf '%s' "$ISSUE_TITLE" > /tmp/issue_title.txt + + - name: Process issue and update files + env: + ISSUE_LABEL: ${{ github.event.label.name }} + ISSUE_NUMBER: ${{ github.event.issue.number }} + run: python .github/scripts/process_issue.py + + - name: Create branch and open PR + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + ISSUE_NUMBER: ${{ github.event.issue.number }} + ISSUE_LABEL: ${{ github.event.label.name }} + ISSUE_TITLE: ${{ github.event.issue.title }} + run: | + BRANCH="auto/${ISSUE_LABEL}-issue-${ISSUE_NUMBER}" + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git checkout -b "$BRANCH" + git add model/reproinventory_data.yaml frontend/public/data/reproinventory_data.json + if git diff --cached --quiet; then + echo "No changes detected — nothing to commit." + exit 1 + fi + git commit -m "${ISSUE_TITLE}" + git push origin "$BRANCH" + PR_BODY=$(printf "Closes #%s\n\nAutomatically generated from issue #%s." "${ISSUE_NUMBER}" "${ISSUE_NUMBER}") + gh pr create \ + --title "${ISSUE_TITLE}" \ + --body "${PR_BODY}" \ + --base main \ + --head "${BRANCH}" diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..b729136 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,82 @@ +# ReproInventory - Claude Instructions + +## Project Overview + +ReproInventory is a web application for browsing neuroimaging and reproducibility training materials. It is part of the ReproNim project. Users can search and filter a catalog of training resources by level, platform, format, programming language, neuroimaging software, and more. + +## Tech Stack + +- **Frontend:** React 19 + TypeScript + Vite +- **Styling:** Tailwind CSS v4 +- **UI Components:** shadcn/ui (built on Radix UI primitives) +- **Icons:** lucide-react +- **Data:** Static JSON file served from `frontend/public/data/reproinventory_data.json` +- **Model/Schema:** YAML-based schema in `model/`, with Python scripts to generate JSON +- **Deploy:** GitHub Pages via GitHub Actions (pushes to `main` auto-deploy) + +## Directory Structure + +``` +frontend/ # Main React app + src/ + components/ # Custom components (e.g. Footer, EditMaterialDialog, AddMaterialDialog) + components/ui/ # shadcn/ui primitives (accordion, badge, button, card, etc.) + types/ # TypeScript types generated from the YAML schema + training-materials-browser.tsx # Main browser/filter UI + App.tsx # Root component + public/ + data/ + reproinventory_data.json # The training materials dataset + +model/ # Schema and data source of truth + model.yaml # LinkML schema definition + reproinventory_data.yaml # Raw training data + reproinventory_schema.yaml # Schema + generate_reproinventory_data.py # Generates JSON from YAML + convert_yaml_to_json.py + +SimpleViewer/ # Legacy Python/Flask viewer (archived, do not modify) +``` + +## Development Commands + +All commands run from the `frontend/` directory: + +```bash +npm run dev # Start local dev server +npm run build # TypeScript check + Vite build +npm run lint # ESLint +npm run preview # Preview production build locally +``` + +## Data Model + +The data schema is defined in `model/model.yaml` (LinkML). TypeScript types in `frontend/src/types/reproinventory.ts` are generated from this schema. Key fields on `ReproInventoryEntry`: + +- `id`, `course_name`, `url`, `review`, `notes`, `keywords` +- `level`, `platform`, `course_length`, `instruction_medium`, `delivery` +- `language`, `programming_language`, `neuroimaging_software`, `imaging_modality` +- `open_dataset`, `assessment`, `quadrants`, `tag_team` + +Enum values are strict — always use values that match the schema. + +## Code Conventions + +- Use the types from `frontend/src/types/reproinventory.ts` for all data model types; do not redefine them locally (note: `AddMaterialDialog.tsx` currently duplicates types — prefer importing from the shared types file in new code). +- Use `@/` path alias for imports (e.g. `@/components/ui/button`). +- UI primitives live in `frontend/src/components/ui/` — use these rather than raw HTML elements. +- Custom components go in `frontend/src/components/`. +- The dataset is fetched at runtime from `/ReproInventory/data/reproinventory_data.json` (the GitHub Pages base path). + +## Deployment + +- Pushing to `main` triggers GitHub Actions which builds the frontend and deploys to GitHub Pages. +- The Vite base path is set for GitHub Pages — keep this in mind when referencing public assets. +- Do not push broken builds to `main`. + +## What to Avoid + +- Do not modify files in `SimpleViewer/` — it is a legacy viewer and not actively used. +- Do not change enum values without also updating `model/model.yaml` and regenerating types. +- Do not hardcode data that belongs in `reproinventory_data.json` or the YAML source. +- Do not add dependencies without good reason — the stack is intentionally minimal. diff --git a/frontend/dist/assets/index-BN5M8IzP.js b/frontend/dist/assets/index-BN5M8IzP.js new file mode 100644 index 0000000..e2a81e2 --- /dev/null +++ b/frontend/dist/assets/index-BN5M8IzP.js @@ -0,0 +1,199 @@ +function f0(a,r){for(var s=0;sc[f]})}}}return Object.freeze(Object.defineProperty(a,Symbol.toStringTag,{value:"Module"}))}(function(){const r=document.createElement("link").relList;if(r&&r.supports&&r.supports("modulepreload"))return;for(const f of document.querySelectorAll('link[rel="modulepreload"]'))c(f);new MutationObserver(f=>{for(const d of f)if(d.type==="childList")for(const v of d.addedNodes)v.tagName==="LINK"&&v.rel==="modulepreload"&&c(v)}).observe(document,{childList:!0,subtree:!0});function s(f){const d={};return f.integrity&&(d.integrity=f.integrity),f.referrerPolicy&&(d.referrerPolicy=f.referrerPolicy),f.crossOrigin==="use-credentials"?d.credentials="include":f.crossOrigin==="anonymous"?d.credentials="omit":d.credentials="same-origin",d}function c(f){if(f.ep)return;f.ep=!0;const d=s(f);fetch(f.href,d)}})();function cv(a){return a&&a.__esModule&&Object.prototype.hasOwnProperty.call(a,"default")?a.default:a}var mu={exports:{}},Yi={};/** + * @license React + * react-jsx-runtime.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var pg;function d0(){if(pg)return Yi;pg=1;var a=Symbol.for("react.transitional.element"),r=Symbol.for("react.fragment");function s(c,f,d){var v=null;if(d!==void 0&&(v=""+d),f.key!==void 0&&(v=""+f.key),"key"in f){d={};for(var p in f)p!=="key"&&(d[p]=f[p])}else d=f;return f=d.ref,{$$typeof:a,type:c,key:v,ref:f!==void 0?f:null,props:d}}return Yi.Fragment=r,Yi.jsx=s,Yi.jsxs=s,Yi}var yg;function m0(){return yg||(yg=1,mu.exports=d0()),mu.exports}var u=m0(),hu={exports:{}},Se={};/** + * @license React + * react.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var xg;function h0(){if(xg)return Se;xg=1;var a=Symbol.for("react.transitional.element"),r=Symbol.for("react.portal"),s=Symbol.for("react.fragment"),c=Symbol.for("react.strict_mode"),f=Symbol.for("react.profiler"),d=Symbol.for("react.consumer"),v=Symbol.for("react.context"),p=Symbol.for("react.forward_ref"),x=Symbol.for("react.suspense"),m=Symbol.for("react.memo"),g=Symbol.for("react.lazy"),b=Symbol.iterator;function w(A){return A===null||typeof A!="object"?null:(A=b&&A[b]||A["@@iterator"],typeof A=="function"?A:null)}var _={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},M=Object.assign,N={};function T(A,Y,W){this.props=A,this.context=Y,this.refs=N,this.updater=W||_}T.prototype.isReactComponent={},T.prototype.setState=function(A,Y){if(typeof A!="object"&&typeof A!="function"&&A!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,A,Y,"setState")},T.prototype.forceUpdate=function(A){this.updater.enqueueForceUpdate(this,A,"forceUpdate")};function z(){}z.prototype=T.prototype;function j(A,Y,W){this.props=A,this.context=Y,this.refs=N,this.updater=W||_}var U=j.prototype=new z;U.constructor=j,M(U,T.prototype),U.isPureReactComponent=!0;var q=Array.isArray,G={H:null,A:null,T:null,S:null,V:null},J=Object.prototype.hasOwnProperty;function F(A,Y,W,P,I,ye){return W=ye.ref,{$$typeof:a,type:A,key:Y,ref:W!==void 0?W:null,props:ye}}function X(A,Y){return F(A.type,Y,void 0,void 0,void 0,A.props)}function ie(A){return typeof A=="object"&&A!==null&&A.$$typeof===a}function me(A){var Y={"=":"=0",":":"=2"};return"$"+A.replace(/[=:]/g,function(W){return Y[W]})}var xe=/\/+/g;function ue(A,Y){return typeof A=="object"&&A!==null&&A.key!=null?me(""+A.key):Y.toString(36)}function be(){}function ve(A){switch(A.status){case"fulfilled":return A.value;case"rejected":throw A.reason;default:switch(typeof A.status=="string"?A.then(be,be):(A.status="pending",A.then(function(Y){A.status==="pending"&&(A.status="fulfilled",A.value=Y)},function(Y){A.status==="pending"&&(A.status="rejected",A.reason=Y)})),A.status){case"fulfilled":return A.value;case"rejected":throw A.reason}}throw A}function de(A,Y,W,P,I){var ye=typeof A;(ye==="undefined"||ye==="boolean")&&(A=null);var ce=!1;if(A===null)ce=!0;else switch(ye){case"bigint":case"string":case"number":ce=!0;break;case"object":switch(A.$$typeof){case a:case r:ce=!0;break;case g:return ce=A._init,de(ce(A._payload),Y,W,P,I)}}if(ce)return I=I(A),ce=P===""?"."+ue(A,0):P,q(I)?(W="",ce!=null&&(W=ce.replace(xe,"$&/")+"/"),de(I,Y,W,"",function(De){return De})):I!=null&&(ie(I)&&(I=X(I,W+(I.key==null||A&&A.key===I.key?"":(""+I.key).replace(xe,"$&/")+"/")+ce)),Y.push(I)),1;ce=0;var ee=P===""?".":P+":";if(q(A))for(var oe=0;oe>>1,A=R[re];if(0>>1;ref(P,B))If(ye,P)?(R[re]=ye,R[I]=B,re=I):(R[re]=P,R[W]=B,re=W);else if(If(ye,B))R[re]=ye,R[I]=B,re=I;else break e}}return K}function f(R,K){var B=R.sortIndex-K.sortIndex;return B!==0?B:R.id-K.id}if(a.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var d=performance;a.unstable_now=function(){return d.now()}}else{var v=Date,p=v.now();a.unstable_now=function(){return v.now()-p}}var x=[],m=[],g=1,b=null,w=3,_=!1,M=!1,N=!1,T=!1,z=typeof setTimeout=="function"?setTimeout:null,j=typeof clearTimeout=="function"?clearTimeout:null,U=typeof setImmediate<"u"?setImmediate:null;function q(R){for(var K=s(m);K!==null;){if(K.callback===null)c(m);else if(K.startTime<=R)c(m),K.sortIndex=K.expirationTime,r(x,K);else break;K=s(m)}}function G(R){if(N=!1,q(R),!M)if(s(x)!==null)M=!0,J||(J=!0,ue());else{var K=s(m);K!==null&&de(G,K.startTime-R)}}var J=!1,F=-1,X=5,ie=-1;function me(){return T?!0:!(a.unstable_now()-ieR&&me());){var re=b.callback;if(typeof re=="function"){b.callback=null,w=b.priorityLevel;var A=re(b.expirationTime<=R);if(R=a.unstable_now(),typeof A=="function"){b.callback=A,q(R),K=!0;break t}b===s(x)&&c(x),q(R)}else c(x);b=s(x)}if(b!==null)K=!0;else{var Y=s(m);Y!==null&&de(G,Y.startTime-R),K=!1}}break e}finally{b=null,w=B,_=!1}K=void 0}}finally{K?ue():J=!1}}}var ue;if(typeof U=="function")ue=function(){U(xe)};else if(typeof MessageChannel<"u"){var be=new MessageChannel,ve=be.port2;be.port1.onmessage=xe,ue=function(){ve.postMessage(null)}}else ue=function(){z(xe,0)};function de(R,K){F=z(function(){R(a.unstable_now())},K)}a.unstable_IdlePriority=5,a.unstable_ImmediatePriority=1,a.unstable_LowPriority=4,a.unstable_NormalPriority=3,a.unstable_Profiling=null,a.unstable_UserBlockingPriority=2,a.unstable_cancelCallback=function(R){R.callback=null},a.unstable_forceFrameRate=function(R){0>R||125re?(R.sortIndex=B,r(m,R),s(x)===null&&R===s(m)&&(N?(j(F),F=-1):N=!0,de(G,B-re))):(R.sortIndex=A,r(x,R),M||_||(M=!0,J||(J=!0,ue()))),R},a.unstable_shouldYield=me,a.unstable_wrapCallback=function(R){var K=w;return function(){var B=w;w=K;try{return R.apply(this,arguments)}finally{w=B}}}}(pu)),pu}var wg;function v0(){return wg||(wg=1,vu.exports=g0()),vu.exports}var yu={exports:{}},Nt={};/** + * @license React + * react-dom.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Ng;function p0(){if(Ng)return Nt;Ng=1;var a=Ju();function r(x){var m="https://react.dev/errors/"+x;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(a)}catch(r){console.error(r)}}return a(),yu.exports=p0(),yu.exports}/** + * @license React + * react-dom-client.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Ag;function y0(){if(Ag)return Xi;Ag=1;var a=v0(),r=Ju(),s=ov();function c(e){var t="https://react.dev/errors/"+e;if(1A||(e.current=re[A],re[A]=null,A--)}function P(e,t){A++,re[A]=e.current,e.current=t}var I=Y(null),ye=Y(null),ce=Y(null),ee=Y(null);function oe(e,t){switch(P(ce,t),P(ye,e),P(I,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Qh(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Qh(t),e=Zh(t,e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}W(I),P(I,e)}function De(){W(I),W(ye),W(ce)}function je(e){e.memoizedState!==null&&P(ee,e);var t=I.current,n=Zh(t,e.type);t!==n&&(P(ye,e),P(I,n))}function Ne(e){ye.current===e&&(W(I),W(ye)),ee.current===e&&(W(ee),Li._currentValue=B)}var Ee=Object.prototype.hasOwnProperty,lt=a.unstable_scheduleCallback,xt=a.unstable_cancelCallback,En=a.unstable_shouldYield,Pt=a.unstable_requestPaint,at=a.unstable_now,Za=a.unstable_getCurrentPriorityLevel,Q=a.unstable_ImmediatePriority,fe=a.unstable_UserBlockingPriority,Ot=a.unstable_NormalPriority,un=a.unstable_LowPriority,fn=a.unstable_IdlePriority,wl=a.log,ht=a.unstable_setDisableYieldValue,dn=null,ot=null;function It(e){if(typeof wl=="function"&&ht(e),ot&&typeof ot.setStrictMode=="function")try{ot.setStrictMode(dn,e)}catch{}}var bt=Math.clz32?Math.clz32:Iy,lr=Math.log,it=Math.LN2;function Iy(e){return e>>>=0,e===0?32:31-(lr(e)/it|0)|0}var ar=256,ir=4194304;function Nl(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return e&4194048;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function rr(e,t,n){var l=e.pendingLanes;if(l===0)return 0;var i=0,o=e.suspendedLanes,h=e.pingedLanes;e=e.warmLanes;var y=l&134217727;return y!==0?(l=y&~o,l!==0?i=Nl(l):(h&=y,h!==0?i=Nl(h):n||(n=y&~e,n!==0&&(i=Nl(n))))):(y=l&~o,y!==0?i=Nl(y):h!==0?i=Nl(h):n||(n=l&~e,n!==0&&(i=Nl(n)))),i===0?0:t!==0&&t!==i&&(t&o)===0&&(o=i&-i,n=t&-t,o>=n||o===32&&(n&4194048)!==0)?t:i}function Ka(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function Jy(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function _f(){var e=ar;return ar<<=1,(ar&4194048)===0&&(ar=256),e}function jf(){var e=ir;return ir<<=1,(ir&62914560)===0&&(ir=4194304),e}function ts(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function $a(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function Wy(e,t,n,l,i,o){var h=e.pendingLanes;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=n,e.entangledLanes&=n,e.errorRecoveryDisabledLanes&=n,e.shellSuspendCounter=0;var y=e.entanglements,E=e.expirationTimes,k=e.hiddenUpdates;for(n=h&~n;0)":-1i||E[l]!==k[i]){var V=` +`+E[l].replace(" at new "," at ");return e.displayName&&V.includes("")&&(V=V.replace("",e.displayName)),V}while(1<=l&&0<=i);break}}}finally{cs=!1,Error.prepareStackTrace=n}return(n=e?e.displayName||e.name:"")?Jl(n):""}function ix(e){switch(e.tag){case 26:case 27:case 5:return Jl(e.type);case 16:return Jl("Lazy");case 13:return Jl("Suspense");case 19:return Jl("SuspenseList");case 0:case 15:return ss(e.type,!1);case 11:return ss(e.type.render,!1);case 1:return ss(e.type,!0);case 31:return Jl("Activity");default:return""}}function Bf(e){try{var t="";do t+=ix(e),e=e.return;while(e);return t}catch(n){return` +Error generating stack: `+n.message+` +`+n.stack}}function qt(e){switch(typeof e){case"bigint":case"boolean":case"number":case"string":case"undefined":return e;case"object":return e;default:return""}}function Gf(e){var t=e.type;return(e=e.nodeName)&&e.toLowerCase()==="input"&&(t==="checkbox"||t==="radio")}function rx(e){var t=Gf(e)?"checked":"value",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),l=""+e[t];if(!e.hasOwnProperty(t)&&typeof n<"u"&&typeof n.get=="function"&&typeof n.set=="function"){var i=n.get,o=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return i.call(this)},set:function(h){l=""+h,o.call(this,h)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return l},setValue:function(h){l=""+h},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}function or(e){e._valueTracker||(e._valueTracker=rx(e))}function qf(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),l="";return e&&(l=Gf(e)?e.checked?"true":"false":e.value),e=l,e!==n?(t.setValue(e),!0):!1}function ur(e){if(e=e||(typeof document<"u"?document:void 0),typeof e>"u")return null;try{return e.activeElement||e.body}catch{return e.body}}var cx=/[\n"\\]/g;function Vt(e){return e.replace(cx,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function os(e,t,n,l,i,o,h,y){e.name="",h!=null&&typeof h!="function"&&typeof h!="symbol"&&typeof h!="boolean"?e.type=h:e.removeAttribute("type"),t!=null?h==="number"?(t===0&&e.value===""||e.value!=t)&&(e.value=""+qt(t)):e.value!==""+qt(t)&&(e.value=""+qt(t)):h!=="submit"&&h!=="reset"||e.removeAttribute("value"),t!=null?us(e,h,qt(t)):n!=null?us(e,h,qt(n)):l!=null&&e.removeAttribute("value"),i==null&&o!=null&&(e.defaultChecked=!!o),i!=null&&(e.checked=i&&typeof i!="function"&&typeof i!="symbol"),y!=null&&typeof y!="function"&&typeof y!="symbol"&&typeof y!="boolean"?e.name=""+qt(y):e.removeAttribute("name")}function Vf(e,t,n,l,i,o,h,y){if(o!=null&&typeof o!="function"&&typeof o!="symbol"&&typeof o!="boolean"&&(e.type=o),t!=null||n!=null){if(!(o!=="submit"&&o!=="reset"||t!=null))return;n=n!=null?""+qt(n):"",t=t!=null?""+qt(t):n,y||t===e.value||(e.value=t),e.defaultValue=t}l=l??i,l=typeof l!="function"&&typeof l!="symbol"&&!!l,e.checked=y?e.checked:!!l,e.defaultChecked=!!l,h!=null&&typeof h!="function"&&typeof h!="symbol"&&typeof h!="boolean"&&(e.name=h)}function us(e,t,n){t==="number"&&ur(e.ownerDocument)===e||e.defaultValue===""+n||(e.defaultValue=""+n)}function Wl(e,t,n,l){if(e=e.options,t){t={};for(var i=0;i"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),gs=!1;if(Cn)try{var Ja={};Object.defineProperty(Ja,"passive",{get:function(){gs=!0}}),window.addEventListener("test",Ja,Ja),window.removeEventListener("test",Ja,Ja)}catch{gs=!1}var Zn=null,vs=null,dr=null;function Ff(){if(dr)return dr;var e,t=vs,n=t.length,l,i="value"in Zn?Zn.value:Zn.textContent,o=i.length;for(e=0;e=ti),td=" ",nd=!1;function ld(e,t){switch(e){case"keyup":return kx.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function ad(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var la=!1;function Hx(e,t){switch(e){case"compositionend":return ad(t);case"keypress":return t.which!==32?null:(nd=!0,td);case"textInput":return e=t.data,e===td&&nd?null:e;default:return null}}function Lx(e,t){if(la)return e==="compositionend"||!Ss&&ld(e,t)?(e=Ff(),dr=vs=Zn=null,la=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=l}e:{for(;n;){if(n.nextSibling){n=n.nextSibling;break e}n=n.parentNode}n=void 0}n=dd(n)}}function hd(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?hd(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function gd(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=ur(e.document);t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href=="string"}catch{n=!1}if(n)e=t.contentWindow;else break;t=ur(e.document)}return t}function Es(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}var Zx=Cn&&"documentMode"in document&&11>=document.documentMode,aa=null,As=null,ii=null,Cs=!1;function vd(e,t,n){var l=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;Cs||aa==null||aa!==ur(l)||(l=aa,"selectionStart"in l&&Es(l)?l={start:l.selectionStart,end:l.selectionEnd}:(l=(l.ownerDocument&&l.ownerDocument.defaultView||window).getSelection(),l={anchorNode:l.anchorNode,anchorOffset:l.anchorOffset,focusNode:l.focusNode,focusOffset:l.focusOffset}),ii&&ai(ii,l)||(ii=l,l=nc(As,"onSelect"),0>=h,i-=h,_n=1<<32-bt(t)+i|n<o?o:8;var h=R.T,y={};R.T=y,fo(e,!1,t,n);try{var E=i(),k=R.S;if(k!==null&&k(y,E),E!==null&&typeof E=="object"&&typeof E.then=="function"){var V=tb(E,l);bi(e,t,V,Ht(e))}else bi(e,t,l,Ht(e))}catch($){bi(e,t,{then:function(){},status:"rejected",reason:$},Ht())}finally{K.p=o,R.T=h}}function rb(){}function oo(e,t,n,l){if(e.tag!==5)throw Error(c(476));var i=pm(e).queue;vm(e,i,t,B,n===null?rb:function(){return ym(e),n(l)})}function pm(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:B,baseState:B,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Mn,lastRenderedState:B},next:null};var n={};return t.next={memoizedState:n,baseState:n,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Mn,lastRenderedState:n},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function ym(e){var t=pm(e).next.queue;bi(e,t,{},Ht())}function uo(){return wt(Li)}function xm(){return et().memoizedState}function bm(){return et().memoizedState}function cb(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var n=Ht();e=Fn(n);var l=Pn(t,e,n);l!==null&&(Lt(l,t,n),hi(l,t,n)),t={cache:Gs()},e.payload=t;return}t=t.return}}function sb(e,t,n){var l=Ht();n={lane:l,revertLane:0,action:n,hasEagerState:!1,eagerState:null,next:null},Ur(e)?wm(t,n):(n=Rs(e,t,n,l),n!==null&&(Lt(n,e,l),Nm(n,t,l)))}function Sm(e,t,n){var l=Ht();bi(e,t,n,l)}function bi(e,t,n,l){var i={lane:l,revertLane:0,action:n,hasEagerState:!1,eagerState:null,next:null};if(Ur(e))wm(t,i);else{var o=e.alternate;if(e.lanes===0&&(o===null||o.lanes===0)&&(o=t.lastRenderedReducer,o!==null))try{var h=t.lastRenderedState,y=o(h,n);if(i.hasEagerState=!0,i.eagerState=y,Mt(y,h))return xr(e,t,i,0),Xe===null&&yr(),!1}catch{}finally{}if(n=Rs(e,t,i,l),n!==null)return Lt(n,e,l),Nm(n,t,l),!0}return!1}function fo(e,t,n,l){if(l={lane:2,revertLane:Xo(),action:l,hasEagerState:!1,eagerState:null,next:null},Ur(e)){if(t)throw Error(c(479))}else t=Rs(e,n,l,2),t!==null&&Lt(t,e,2)}function Ur(e){var t=e.alternate;return e===Ae||t!==null&&t===Ae}function wm(e,t){ha=Rr=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function Nm(e,t,n){if((n&4194048)!==0){var l=t.lanes;l&=e.pendingLanes,n|=l,t.lanes=n,Of(e,n)}}var Hr={readContext:wt,use:Mr,useCallback:Pe,useContext:Pe,useEffect:Pe,useImperativeHandle:Pe,useLayoutEffect:Pe,useInsertionEffect:Pe,useMemo:Pe,useReducer:Pe,useRef:Pe,useState:Pe,useDebugValue:Pe,useDeferredValue:Pe,useTransition:Pe,useSyncExternalStore:Pe,useId:Pe,useHostTransitionStatus:Pe,useFormState:Pe,useActionState:Pe,useOptimistic:Pe,useMemoCache:Pe,useCacheRefresh:Pe},Em={readContext:wt,use:Mr,useCallback:function(e,t){return Tt().memoizedState=[e,t===void 0?null:t],e},useContext:wt,useEffect:cm,useImperativeHandle:function(e,t,n){n=n!=null?n.concat([e]):null,kr(4194308,4,fm.bind(null,t,e),n)},useLayoutEffect:function(e,t){return kr(4194308,4,e,t)},useInsertionEffect:function(e,t){kr(4,2,e,t)},useMemo:function(e,t){var n=Tt();t=t===void 0?null:t;var l=e();if(Ul){It(!0);try{e()}finally{It(!1)}}return n.memoizedState=[l,t],l},useReducer:function(e,t,n){var l=Tt();if(n!==void 0){var i=n(t);if(Ul){It(!0);try{n(t)}finally{It(!1)}}}else i=t;return l.memoizedState=l.baseState=i,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:i},l.queue=e,e=e.dispatch=sb.bind(null,Ae,e),[l.memoizedState,e]},useRef:function(e){var t=Tt();return e={current:e},t.memoizedState=e},useState:function(e){e=io(e);var t=e.queue,n=Sm.bind(null,Ae,t);return t.dispatch=n,[e.memoizedState,n]},useDebugValue:co,useDeferredValue:function(e,t){var n=Tt();return so(n,e,t)},useTransition:function(){var e=io(!1);return e=vm.bind(null,Ae,e.queue,!0,!1),Tt().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,n){var l=Ae,i=Tt();if(ke){if(n===void 0)throw Error(c(407));n=n()}else{if(n=t(),Xe===null)throw Error(c(349));(Me&124)!==0||Qd(l,t,n)}i.memoizedState=n;var o={value:n,getSnapshot:t};return i.queue=o,cm(Kd.bind(null,l,o,e),[e]),l.flags|=2048,va(9,zr(),Zd.bind(null,l,o,n,t),null),n},useId:function(){var e=Tt(),t=Xe.identifierPrefix;if(ke){var n=jn,l=_n;n=(l&~(1<<32-bt(l)-1)).toString(32)+n,t="«"+t+"R"+n,n=Or++,0ge?(mt=se,se=null):mt=se.sibling;var ze=H(O,se,D[ge],Z);if(ze===null){se===null&&(se=mt);break}e&&se&&ze.alternate===null&&t(O,se),C=o(ze,C,ge),Te===null?ne=ze:Te.sibling=ze,Te=ze,se=mt}if(ge===D.length)return n(O,se),ke&&Rl(O,ge),ne;if(se===null){for(;gege?(mt=se,se=null):mt=se.sibling;var ml=H(O,se,ze.value,Z);if(ml===null){se===null&&(se=mt);break}e&&se&&ml.alternate===null&&t(O,se),C=o(ml,C,ge),Te===null?ne=ml:Te.sibling=ml,Te=ml,se=mt}if(ze.done)return n(O,se),ke&&Rl(O,ge),ne;if(se===null){for(;!ze.done;ge++,ze=D.next())ze=$(O,ze.value,Z),ze!==null&&(C=o(ze,C,ge),Te===null?ne=ze:Te.sibling=ze,Te=ze);return ke&&Rl(O,ge),ne}for(se=l(se);!ze.done;ge++,ze=D.next())ze=L(se,O,ge,ze.value,Z),ze!==null&&(e&&ze.alternate!==null&&se.delete(ze.key===null?ge:ze.key),C=o(ze,C,ge),Te===null?ne=ze:Te.sibling=ze,Te=ze);return e&&se.forEach(function(u0){return t(O,u0)}),ke&&Rl(O,ge),ne}function qe(O,C,D,Z){if(typeof D=="object"&&D!==null&&D.type===M&&D.key===null&&(D=D.props.children),typeof D=="object"&&D!==null){switch(D.$$typeof){case w:e:{for(var ne=D.key;C!==null;){if(C.key===ne){if(ne=D.type,ne===M){if(C.tag===7){n(O,C.sibling),Z=i(C,D.props.children),Z.return=O,O=Z;break e}}else if(C.elementType===ne||typeof ne=="object"&&ne!==null&&ne.$$typeof===X&&Cm(ne)===C.type){n(O,C.sibling),Z=i(C,D.props),wi(Z,D),Z.return=O,O=Z;break e}n(O,C);break}else t(O,C);C=C.sibling}D.type===M?(Z=_l(D.props.children,O.mode,Z,D.key),Z.return=O,O=Z):(Z=Sr(D.type,D.key,D.props,null,O.mode,Z),wi(Z,D),Z.return=O,O=Z)}return h(O);case _:e:{for(ne=D.key;C!==null;){if(C.key===ne)if(C.tag===4&&C.stateNode.containerInfo===D.containerInfo&&C.stateNode.implementation===D.implementation){n(O,C.sibling),Z=i(C,D.children||[]),Z.return=O,O=Z;break e}else{n(O,C);break}else t(O,C);C=C.sibling}Z=Ds(D,O.mode,Z),Z.return=O,O=Z}return h(O);case X:return ne=D._init,D=ne(D._payload),qe(O,C,D,Z)}if(de(D))return pe(O,C,D,Z);if(ue(D)){if(ne=ue(D),typeof ne!="function")throw Error(c(150));return D=ne.call(D),he(O,C,D,Z)}if(typeof D.then=="function")return qe(O,C,Lr(D),Z);if(D.$$typeof===U)return qe(O,C,Ar(O,D),Z);Br(O,D)}return typeof D=="string"&&D!==""||typeof D=="number"||typeof D=="bigint"?(D=""+D,C!==null&&C.tag===6?(n(O,C.sibling),Z=i(C,D),Z.return=O,O=Z):(n(O,C),Z=Ms(D,O.mode,Z),Z.return=O,O=Z),h(O)):n(O,C)}return function(O,C,D,Z){try{Si=0;var ne=qe(O,C,D,Z);return pa=null,ne}catch(se){if(se===di||se===Tr)throw se;var Te=Dt(29,se,null,O.mode);return Te.lanes=Z,Te.return=O,Te}finally{}}}var ya=Tm(!0),_m=Tm(!1),Kt=Y(null),hn=null;function Jn(e){var t=e.alternate;P(ct,ct.current&1),P(Kt,e),hn===null&&(t===null||ma.current!==null||t.memoizedState!==null)&&(hn=e)}function jm(e){if(e.tag===22){if(P(ct,ct.current),P(Kt,e),hn===null){var t=e.alternate;t!==null&&t.memoizedState!==null&&(hn=e)}}else Wn()}function Wn(){P(ct,ct.current),P(Kt,Kt.current)}function Dn(e){W(Kt),hn===e&&(hn=null),W(ct)}var ct=Y(0);function Gr(e){for(var t=e;t!==null;){if(t.tag===13){var n=t.memoizedState;if(n!==null&&(n=n.dehydrated,n===null||n.data==="$?"||nu(n)))return t}else if(t.tag===19&&t.memoizedProps.revealOrder!==void 0){if((t.flags&128)!==0)return t}else if(t.child!==null){t.child.return=t,t=t.child;continue}if(t===e)break;for(;t.sibling===null;){if(t.return===null||t.return===e)return null;t=t.return}t.sibling.return=t.return,t=t.sibling}return null}function mo(e,t,n,l){t=e.memoizedState,n=n(l,t),n=n==null?t:g({},t,n),e.memoizedState=n,e.lanes===0&&(e.updateQueue.baseState=n)}var ho={enqueueSetState:function(e,t,n){e=e._reactInternals;var l=Ht(),i=Fn(l);i.payload=t,n!=null&&(i.callback=n),t=Pn(e,i,l),t!==null&&(Lt(t,e,l),hi(t,e,l))},enqueueReplaceState:function(e,t,n){e=e._reactInternals;var l=Ht(),i=Fn(l);i.tag=1,i.payload=t,n!=null&&(i.callback=n),t=Pn(e,i,l),t!==null&&(Lt(t,e,l),hi(t,e,l))},enqueueForceUpdate:function(e,t){e=e._reactInternals;var n=Ht(),l=Fn(n);l.tag=2,t!=null&&(l.callback=t),t=Pn(e,l,n),t!==null&&(Lt(t,e,n),hi(t,e,n))}};function Rm(e,t,n,l,i,o,h){return e=e.stateNode,typeof e.shouldComponentUpdate=="function"?e.shouldComponentUpdate(l,o,h):t.prototype&&t.prototype.isPureReactComponent?!ai(n,l)||!ai(i,o):!0}function Om(e,t,n,l){e=t.state,typeof t.componentWillReceiveProps=="function"&&t.componentWillReceiveProps(n,l),typeof t.UNSAFE_componentWillReceiveProps=="function"&&t.UNSAFE_componentWillReceiveProps(n,l),t.state!==e&&ho.enqueueReplaceState(t,t.state,null)}function Hl(e,t){var n=t;if("ref"in t){n={};for(var l in t)l!=="ref"&&(n[l]=t[l])}if(e=e.defaultProps){n===t&&(n=g({},n));for(var i in e)n[i]===void 0&&(n[i]=e[i])}return n}var qr=typeof reportError=="function"?reportError:function(e){if(typeof window=="object"&&typeof window.ErrorEvent=="function"){var t=new window.ErrorEvent("error",{bubbles:!0,cancelable:!0,message:typeof e=="object"&&e!==null&&typeof e.message=="string"?String(e.message):String(e),error:e});if(!window.dispatchEvent(t))return}else if(typeof process=="object"&&typeof process.emit=="function"){process.emit("uncaughtException",e);return}console.error(e)};function Mm(e){qr(e)}function Dm(e){console.error(e)}function zm(e){qr(e)}function Vr(e,t){try{var n=e.onUncaughtError;n(t.value,{componentStack:t.stack})}catch(l){setTimeout(function(){throw l})}}function km(e,t,n){try{var l=e.onCaughtError;l(n.value,{componentStack:n.stack,errorBoundary:t.tag===1?t.stateNode:null})}catch(i){setTimeout(function(){throw i})}}function go(e,t,n){return n=Fn(n),n.tag=3,n.payload={element:null},n.callback=function(){Vr(e,t)},n}function Um(e){return e=Fn(e),e.tag=3,e}function Hm(e,t,n,l){var i=n.type.getDerivedStateFromError;if(typeof i=="function"){var o=l.value;e.payload=function(){return i(o)},e.callback=function(){km(t,n,l)}}var h=n.stateNode;h!==null&&typeof h.componentDidCatch=="function"&&(e.callback=function(){km(t,n,l),typeof i!="function"&&(il===null?il=new Set([this]):il.add(this));var y=l.stack;this.componentDidCatch(l.value,{componentStack:y!==null?y:""})})}function ub(e,t,n,l,i){if(n.flags|=32768,l!==null&&typeof l=="object"&&typeof l.then=="function"){if(t=n.alternate,t!==null&&oi(t,n,i,!0),n=Kt.current,n!==null){switch(n.tag){case 13:return hn===null?Bo():n.alternate===null&&Fe===0&&(Fe=3),n.flags&=-257,n.flags|=65536,n.lanes=i,l===Ys?n.flags|=16384:(t=n.updateQueue,t===null?n.updateQueue=new Set([l]):t.add(l),qo(e,l,i)),!1;case 22:return n.flags|=65536,l===Ys?n.flags|=16384:(t=n.updateQueue,t===null?(t={transitions:null,markerInstances:null,retryQueue:new Set([l])},n.updateQueue=t):(n=t.retryQueue,n===null?t.retryQueue=new Set([l]):n.add(l)),qo(e,l,i)),!1}throw Error(c(435,n.tag))}return qo(e,l,i),Bo(),!1}if(ke)return t=Kt.current,t!==null?((t.flags&65536)===0&&(t.flags|=256),t.flags|=65536,t.lanes=i,l!==Us&&(e=Error(c(422),{cause:l}),si(Yt(e,n)))):(l!==Us&&(t=Error(c(423),{cause:l}),si(Yt(t,n))),e=e.current.alternate,e.flags|=65536,i&=-i,e.lanes|=i,l=Yt(l,n),i=go(e.stateNode,l,i),Zs(e,i),Fe!==4&&(Fe=2)),!1;var o=Error(c(520),{cause:l});if(o=Yt(o,n),ji===null?ji=[o]:ji.push(o),Fe!==4&&(Fe=2),t===null)return!0;l=Yt(l,n),n=t;do{switch(n.tag){case 3:return n.flags|=65536,e=i&-i,n.lanes|=e,e=go(n.stateNode,l,e),Zs(n,e),!1;case 1:if(t=n.type,o=n.stateNode,(n.flags&128)===0&&(typeof t.getDerivedStateFromError=="function"||o!==null&&typeof o.componentDidCatch=="function"&&(il===null||!il.has(o))))return n.flags|=65536,i&=-i,n.lanes|=i,i=Um(i),Hm(i,e,n,l),Zs(n,i),!1}n=n.return}while(n!==null);return!1}var Lm=Error(c(461)),ft=!1;function gt(e,t,n,l){t.child=e===null?_m(t,null,n,l):ya(t,e.child,n,l)}function Bm(e,t,n,l,i){n=n.render;var o=t.ref;if("ref"in l){var h={};for(var y in l)y!=="ref"&&(h[y]=l[y])}else h=l;return zl(t),l=Is(e,t,n,h,o,i),y=Js(),e!==null&&!ft?(Ws(e,t,i),zn(e,t,i)):(ke&&y&&zs(t),t.flags|=1,gt(e,t,l,i),t.child)}function Gm(e,t,n,l,i){if(e===null){var o=n.type;return typeof o=="function"&&!Os(o)&&o.defaultProps===void 0&&n.compare===null?(t.tag=15,t.type=o,qm(e,t,o,l,i)):(e=Sr(n.type,null,l,t,t.mode,i),e.ref=t.ref,e.return=t,t.child=e)}if(o=e.child,!No(e,i)){var h=o.memoizedProps;if(n=n.compare,n=n!==null?n:ai,n(h,l)&&e.ref===t.ref)return zn(e,t,i)}return t.flags|=1,e=Tn(o,l),e.ref=t.ref,e.return=t,t.child=e}function qm(e,t,n,l,i){if(e!==null){var o=e.memoizedProps;if(ai(o,l)&&e.ref===t.ref)if(ft=!1,t.pendingProps=l=o,No(e,i))(e.flags&131072)!==0&&(ft=!0);else return t.lanes=e.lanes,zn(e,t,i)}return vo(e,t,n,l,i)}function Vm(e,t,n){var l=t.pendingProps,i=l.children,o=e!==null?e.memoizedState:null;if(l.mode==="hidden"){if((t.flags&128)!==0){if(l=o!==null?o.baseLanes|n:n,e!==null){for(i=t.child=e.child,o=0;i!==null;)o=o|i.lanes|i.childLanes,i=i.sibling;t.childLanes=o&~l}else t.childLanes=0,t.child=null;return Ym(e,t,l,n)}if((n&536870912)!==0)t.memoizedState={baseLanes:0,cachePool:null},e!==null&&Cr(t,o!==null?o.cachePool:null),o!==null?qd(t,o):$s(),jm(t);else return t.lanes=t.childLanes=536870912,Ym(e,t,o!==null?o.baseLanes|n:n,n)}else o!==null?(Cr(t,o.cachePool),qd(t,o),Wn(),t.memoizedState=null):(e!==null&&Cr(t,null),$s(),Wn());return gt(e,t,i,n),t.child}function Ym(e,t,n,l){var i=Vs();return i=i===null?null:{parent:rt._currentValue,pool:i},t.memoizedState={baseLanes:n,cachePool:i},e!==null&&Cr(t,null),$s(),jm(t),e!==null&&oi(e,t,l,!0),null}function Yr(e,t){var n=t.ref;if(n===null)e!==null&&e.ref!==null&&(t.flags|=4194816);else{if(typeof n!="function"&&typeof n!="object")throw Error(c(284));(e===null||e.ref!==n)&&(t.flags|=4194816)}}function vo(e,t,n,l,i){return zl(t),n=Is(e,t,n,l,void 0,i),l=Js(),e!==null&&!ft?(Ws(e,t,i),zn(e,t,i)):(ke&&l&&zs(t),t.flags|=1,gt(e,t,n,i),t.child)}function Xm(e,t,n,l,i,o){return zl(t),t.updateQueue=null,n=Yd(t,l,n,i),Vd(e),l=Js(),e!==null&&!ft?(Ws(e,t,o),zn(e,t,o)):(ke&&l&&zs(t),t.flags|=1,gt(e,t,n,o),t.child)}function Qm(e,t,n,l,i){if(zl(t),t.stateNode===null){var o=sa,h=n.contextType;typeof h=="object"&&h!==null&&(o=wt(h)),o=new n(l,o),t.memoizedState=o.state!==null&&o.state!==void 0?o.state:null,o.updater=ho,t.stateNode=o,o._reactInternals=t,o=t.stateNode,o.props=l,o.state=t.memoizedState,o.refs={},Xs(t),h=n.contextType,o.context=typeof h=="object"&&h!==null?wt(h):sa,o.state=t.memoizedState,h=n.getDerivedStateFromProps,typeof h=="function"&&(mo(t,n,h,l),o.state=t.memoizedState),typeof n.getDerivedStateFromProps=="function"||typeof o.getSnapshotBeforeUpdate=="function"||typeof o.UNSAFE_componentWillMount!="function"&&typeof o.componentWillMount!="function"||(h=o.state,typeof o.componentWillMount=="function"&&o.componentWillMount(),typeof o.UNSAFE_componentWillMount=="function"&&o.UNSAFE_componentWillMount(),h!==o.state&&ho.enqueueReplaceState(o,o.state,null),vi(t,l,o,i),gi(),o.state=t.memoizedState),typeof o.componentDidMount=="function"&&(t.flags|=4194308),l=!0}else if(e===null){o=t.stateNode;var y=t.memoizedProps,E=Hl(n,y);o.props=E;var k=o.context,V=n.contextType;h=sa,typeof V=="object"&&V!==null&&(h=wt(V));var $=n.getDerivedStateFromProps;V=typeof $=="function"||typeof o.getSnapshotBeforeUpdate=="function",y=t.pendingProps!==y,V||typeof o.UNSAFE_componentWillReceiveProps!="function"&&typeof o.componentWillReceiveProps!="function"||(y||k!==h)&&Om(t,o,l,h),$n=!1;var H=t.memoizedState;o.state=H,vi(t,l,o,i),gi(),k=t.memoizedState,y||H!==k||$n?(typeof $=="function"&&(mo(t,n,$,l),k=t.memoizedState),(E=$n||Rm(t,n,E,l,H,k,h))?(V||typeof o.UNSAFE_componentWillMount!="function"&&typeof o.componentWillMount!="function"||(typeof o.componentWillMount=="function"&&o.componentWillMount(),typeof o.UNSAFE_componentWillMount=="function"&&o.UNSAFE_componentWillMount()),typeof o.componentDidMount=="function"&&(t.flags|=4194308)):(typeof o.componentDidMount=="function"&&(t.flags|=4194308),t.memoizedProps=l,t.memoizedState=k),o.props=l,o.state=k,o.context=h,l=E):(typeof o.componentDidMount=="function"&&(t.flags|=4194308),l=!1)}else{o=t.stateNode,Qs(e,t),h=t.memoizedProps,V=Hl(n,h),o.props=V,$=t.pendingProps,H=o.context,k=n.contextType,E=sa,typeof k=="object"&&k!==null&&(E=wt(k)),y=n.getDerivedStateFromProps,(k=typeof y=="function"||typeof o.getSnapshotBeforeUpdate=="function")||typeof o.UNSAFE_componentWillReceiveProps!="function"&&typeof o.componentWillReceiveProps!="function"||(h!==$||H!==E)&&Om(t,o,l,E),$n=!1,H=t.memoizedState,o.state=H,vi(t,l,o,i),gi();var L=t.memoizedState;h!==$||H!==L||$n||e!==null&&e.dependencies!==null&&Er(e.dependencies)?(typeof y=="function"&&(mo(t,n,y,l),L=t.memoizedState),(V=$n||Rm(t,n,V,l,H,L,E)||e!==null&&e.dependencies!==null&&Er(e.dependencies))?(k||typeof o.UNSAFE_componentWillUpdate!="function"&&typeof o.componentWillUpdate!="function"||(typeof o.componentWillUpdate=="function"&&o.componentWillUpdate(l,L,E),typeof o.UNSAFE_componentWillUpdate=="function"&&o.UNSAFE_componentWillUpdate(l,L,E)),typeof o.componentDidUpdate=="function"&&(t.flags|=4),typeof o.getSnapshotBeforeUpdate=="function"&&(t.flags|=1024)):(typeof o.componentDidUpdate!="function"||h===e.memoizedProps&&H===e.memoizedState||(t.flags|=4),typeof o.getSnapshotBeforeUpdate!="function"||h===e.memoizedProps&&H===e.memoizedState||(t.flags|=1024),t.memoizedProps=l,t.memoizedState=L),o.props=l,o.state=L,o.context=E,l=V):(typeof o.componentDidUpdate!="function"||h===e.memoizedProps&&H===e.memoizedState||(t.flags|=4),typeof o.getSnapshotBeforeUpdate!="function"||h===e.memoizedProps&&H===e.memoizedState||(t.flags|=1024),l=!1)}return o=l,Yr(e,t),l=(t.flags&128)!==0,o||l?(o=t.stateNode,n=l&&typeof n.getDerivedStateFromError!="function"?null:o.render(),t.flags|=1,e!==null&&l?(t.child=ya(t,e.child,null,i),t.child=ya(t,null,n,i)):gt(e,t,n,i),t.memoizedState=o.state,e=t.child):e=zn(e,t,i),e}function Zm(e,t,n,l){return ci(),t.flags|=256,gt(e,t,n,l),t.child}var po={dehydrated:null,treeContext:null,retryLane:0,hydrationErrors:null};function yo(e){return{baseLanes:e,cachePool:Dd()}}function xo(e,t,n){return e=e!==null?e.childLanes&~n:0,t&&(e|=$t),e}function Km(e,t,n){var l=t.pendingProps,i=!1,o=(t.flags&128)!==0,h;if((h=o)||(h=e!==null&&e.memoizedState===null?!1:(ct.current&2)!==0),h&&(i=!0,t.flags&=-129),h=(t.flags&32)!==0,t.flags&=-33,e===null){if(ke){if(i?Jn(t):Wn(),ke){var y=$e,E;if(E=y){e:{for(E=y,y=mn;E.nodeType!==8;){if(!y){y=null;break e}if(E=en(E.nextSibling),E===null){y=null;break e}}y=E}y!==null?(t.memoizedState={dehydrated:y,treeContext:jl!==null?{id:_n,overflow:jn}:null,retryLane:536870912,hydrationErrors:null},E=Dt(18,null,null,0),E.stateNode=y,E.return=t,t.child=E,Et=t,$e=null,E=!0):E=!1}E||Ml(t)}if(y=t.memoizedState,y!==null&&(y=y.dehydrated,y!==null))return nu(y)?t.lanes=32:t.lanes=536870912,null;Dn(t)}return y=l.children,l=l.fallback,i?(Wn(),i=t.mode,y=Xr({mode:"hidden",children:y},i),l=_l(l,i,n,null),y.return=t,l.return=t,y.sibling=l,t.child=y,i=t.child,i.memoizedState=yo(n),i.childLanes=xo(e,h,n),t.memoizedState=po,l):(Jn(t),bo(t,y))}if(E=e.memoizedState,E!==null&&(y=E.dehydrated,y!==null)){if(o)t.flags&256?(Jn(t),t.flags&=-257,t=So(e,t,n)):t.memoizedState!==null?(Wn(),t.child=e.child,t.flags|=128,t=null):(Wn(),i=l.fallback,y=t.mode,l=Xr({mode:"visible",children:l.children},y),i=_l(i,y,n,null),i.flags|=2,l.return=t,i.return=t,l.sibling=i,t.child=l,ya(t,e.child,null,n),l=t.child,l.memoizedState=yo(n),l.childLanes=xo(e,h,n),t.memoizedState=po,t=i);else if(Jn(t),nu(y)){if(h=y.nextSibling&&y.nextSibling.dataset,h)var k=h.dgst;h=k,l=Error(c(419)),l.stack="",l.digest=h,si({value:l,source:null,stack:null}),t=So(e,t,n)}else if(ft||oi(e,t,n,!1),h=(n&e.childLanes)!==0,ft||h){if(h=Xe,h!==null&&(l=n&-n,l=(l&42)!==0?1:ns(l),l=(l&(h.suspendedLanes|n))!==0?0:l,l!==0&&l!==E.retryLane))throw E.retryLane=l,ca(e,l),Lt(h,e,l),Lm;y.data==="$?"||Bo(),t=So(e,t,n)}else y.data==="$?"?(t.flags|=192,t.child=e.child,t=null):(e=E.treeContext,$e=en(y.nextSibling),Et=t,ke=!0,Ol=null,mn=!1,e!==null&&(Qt[Zt++]=_n,Qt[Zt++]=jn,Qt[Zt++]=jl,_n=e.id,jn=e.overflow,jl=t),t=bo(t,l.children),t.flags|=4096);return t}return i?(Wn(),i=l.fallback,y=t.mode,E=e.child,k=E.sibling,l=Tn(E,{mode:"hidden",children:l.children}),l.subtreeFlags=E.subtreeFlags&65011712,k!==null?i=Tn(k,i):(i=_l(i,y,n,null),i.flags|=2),i.return=t,l.return=t,l.sibling=i,t.child=l,l=i,i=t.child,y=e.child.memoizedState,y===null?y=yo(n):(E=y.cachePool,E!==null?(k=rt._currentValue,E=E.parent!==k?{parent:k,pool:k}:E):E=Dd(),y={baseLanes:y.baseLanes|n,cachePool:E}),i.memoizedState=y,i.childLanes=xo(e,h,n),t.memoizedState=po,l):(Jn(t),n=e.child,e=n.sibling,n=Tn(n,{mode:"visible",children:l.children}),n.return=t,n.sibling=null,e!==null&&(h=t.deletions,h===null?(t.deletions=[e],t.flags|=16):h.push(e)),t.child=n,t.memoizedState=null,n)}function bo(e,t){return t=Xr({mode:"visible",children:t},e.mode),t.return=e,e.child=t}function Xr(e,t){return e=Dt(22,e,null,t),e.lanes=0,e.stateNode={_visibility:1,_pendingMarkers:null,_retryCache:null,_transitions:null},e}function So(e,t,n){return ya(t,e.child,null,n),e=bo(t,t.pendingProps.children),e.flags|=2,t.memoizedState=null,e}function $m(e,t,n){e.lanes|=t;var l=e.alternate;l!==null&&(l.lanes|=t),Ls(e.return,t,n)}function wo(e,t,n,l,i){var o=e.memoizedState;o===null?e.memoizedState={isBackwards:t,rendering:null,renderingStartTime:0,last:l,tail:n,tailMode:i}:(o.isBackwards=t,o.rendering=null,o.renderingStartTime=0,o.last=l,o.tail=n,o.tailMode=i)}function Fm(e,t,n){var l=t.pendingProps,i=l.revealOrder,o=l.tail;if(gt(e,t,l.children,n),l=ct.current,(l&2)!==0)l=l&1|2,t.flags|=128;else{if(e!==null&&(e.flags&128)!==0)e:for(e=t.child;e!==null;){if(e.tag===13)e.memoizedState!==null&&$m(e,n,t);else if(e.tag===19)$m(e,n,t);else if(e.child!==null){e.child.return=e,e=e.child;continue}if(e===t)break e;for(;e.sibling===null;){if(e.return===null||e.return===t)break e;e=e.return}e.sibling.return=e.return,e=e.sibling}l&=1}switch(P(ct,l),i){case"forwards":for(n=t.child,i=null;n!==null;)e=n.alternate,e!==null&&Gr(e)===null&&(i=n),n=n.sibling;n=i,n===null?(i=t.child,t.child=null):(i=n.sibling,n.sibling=null),wo(t,!1,i,n,o);break;case"backwards":for(n=null,i=t.child,t.child=null;i!==null;){if(e=i.alternate,e!==null&&Gr(e)===null){t.child=i;break}e=i.sibling,i.sibling=n,n=i,i=e}wo(t,!0,n,null,o);break;case"together":wo(t,!1,null,null,void 0);break;default:t.memoizedState=null}return t.child}function zn(e,t,n){if(e!==null&&(t.dependencies=e.dependencies),al|=t.lanes,(n&t.childLanes)===0)if(e!==null){if(oi(e,t,n,!1),(n&t.childLanes)===0)return null}else return null;if(e!==null&&t.child!==e.child)throw Error(c(153));if(t.child!==null){for(e=t.child,n=Tn(e,e.pendingProps),t.child=n,n.return=t;e.sibling!==null;)e=e.sibling,n=n.sibling=Tn(e,e.pendingProps),n.return=t;n.sibling=null}return t.child}function No(e,t){return(e.lanes&t)!==0?!0:(e=e.dependencies,!!(e!==null&&Er(e)))}function fb(e,t,n){switch(t.tag){case 3:oe(t,t.stateNode.containerInfo),Kn(t,rt,e.memoizedState.cache),ci();break;case 27:case 5:je(t);break;case 4:oe(t,t.stateNode.containerInfo);break;case 10:Kn(t,t.type,t.memoizedProps.value);break;case 13:var l=t.memoizedState;if(l!==null)return l.dehydrated!==null?(Jn(t),t.flags|=128,null):(n&t.child.childLanes)!==0?Km(e,t,n):(Jn(t),e=zn(e,t,n),e!==null?e.sibling:null);Jn(t);break;case 19:var i=(e.flags&128)!==0;if(l=(n&t.childLanes)!==0,l||(oi(e,t,n,!1),l=(n&t.childLanes)!==0),i){if(l)return Fm(e,t,n);t.flags|=128}if(i=t.memoizedState,i!==null&&(i.rendering=null,i.tail=null,i.lastEffect=null),P(ct,ct.current),l)break;return null;case 22:case 23:return t.lanes=0,Vm(e,t,n);case 24:Kn(t,rt,e.memoizedState.cache)}return zn(e,t,n)}function Pm(e,t,n){if(e!==null)if(e.memoizedProps!==t.pendingProps)ft=!0;else{if(!No(e,n)&&(t.flags&128)===0)return ft=!1,fb(e,t,n);ft=(e.flags&131072)!==0}else ft=!1,ke&&(t.flags&1048576)!==0&&Cd(t,Nr,t.index);switch(t.lanes=0,t.tag){case 16:e:{e=t.pendingProps;var l=t.elementType,i=l._init;if(l=i(l._payload),t.type=l,typeof l=="function")Os(l)?(e=Hl(l,e),t.tag=1,t=Qm(null,t,l,e,n)):(t.tag=0,t=vo(null,t,l,e,n));else{if(l!=null){if(i=l.$$typeof,i===q){t.tag=11,t=Bm(null,t,l,e,n);break e}else if(i===F){t.tag=14,t=Gm(null,t,l,e,n);break e}}throw t=ve(l)||l,Error(c(306,t,""))}}return t;case 0:return vo(e,t,t.type,t.pendingProps,n);case 1:return l=t.type,i=Hl(l,t.pendingProps),Qm(e,t,l,i,n);case 3:e:{if(oe(t,t.stateNode.containerInfo),e===null)throw Error(c(387));l=t.pendingProps;var o=t.memoizedState;i=o.element,Qs(e,t),vi(t,l,null,n);var h=t.memoizedState;if(l=h.cache,Kn(t,rt,l),l!==o.cache&&Bs(t,[rt],n,!0),gi(),l=h.element,o.isDehydrated)if(o={element:l,isDehydrated:!1,cache:h.cache},t.updateQueue.baseState=o,t.memoizedState=o,t.flags&256){t=Zm(e,t,l,n);break e}else if(l!==i){i=Yt(Error(c(424)),t),si(i),t=Zm(e,t,l,n);break e}else{switch(e=t.stateNode.containerInfo,e.nodeType){case 9:e=e.body;break;default:e=e.nodeName==="HTML"?e.ownerDocument.body:e}for($e=en(e.firstChild),Et=t,ke=!0,Ol=null,mn=!0,n=_m(t,null,l,n),t.child=n;n;)n.flags=n.flags&-3|4096,n=n.sibling}else{if(ci(),l===i){t=zn(e,t,n);break e}gt(e,t,l,n)}t=t.child}return t;case 26:return Yr(e,t),e===null?(n=eg(t.type,null,t.pendingProps,null))?t.memoizedState=n:ke||(n=t.type,e=t.pendingProps,l=ac(ce.current).createElement(n),l[St]=t,l[At]=e,pt(l,n,e),ut(l),t.stateNode=l):t.memoizedState=eg(t.type,e.memoizedProps,t.pendingProps,e.memoizedState),null;case 27:return je(t),e===null&&ke&&(l=t.stateNode=Ih(t.type,t.pendingProps,ce.current),Et=t,mn=!0,i=$e,sl(t.type)?(lu=i,$e=en(l.firstChild)):$e=i),gt(e,t,t.pendingProps.children,n),Yr(e,t),e===null&&(t.flags|=4194304),t.child;case 5:return e===null&&ke&&((i=l=$e)&&(l=Bb(l,t.type,t.pendingProps,mn),l!==null?(t.stateNode=l,Et=t,$e=en(l.firstChild),mn=!1,i=!0):i=!1),i||Ml(t)),je(t),i=t.type,o=t.pendingProps,h=e!==null?e.memoizedProps:null,l=o.children,Wo(i,o)?l=null:h!==null&&Wo(i,h)&&(t.flags|=32),t.memoizedState!==null&&(i=Is(e,t,lb,null,null,n),Li._currentValue=i),Yr(e,t),gt(e,t,l,n),t.child;case 6:return e===null&&ke&&((e=n=$e)&&(n=Gb(n,t.pendingProps,mn),n!==null?(t.stateNode=n,Et=t,$e=null,e=!0):e=!1),e||Ml(t)),null;case 13:return Km(e,t,n);case 4:return oe(t,t.stateNode.containerInfo),l=t.pendingProps,e===null?t.child=ya(t,null,l,n):gt(e,t,l,n),t.child;case 11:return Bm(e,t,t.type,t.pendingProps,n);case 7:return gt(e,t,t.pendingProps,n),t.child;case 8:return gt(e,t,t.pendingProps.children,n),t.child;case 12:return gt(e,t,t.pendingProps.children,n),t.child;case 10:return l=t.pendingProps,Kn(t,t.type,l.value),gt(e,t,l.children,n),t.child;case 9:return i=t.type._context,l=t.pendingProps.children,zl(t),i=wt(i),l=l(i),t.flags|=1,gt(e,t,l,n),t.child;case 14:return Gm(e,t,t.type,t.pendingProps,n);case 15:return qm(e,t,t.type,t.pendingProps,n);case 19:return Fm(e,t,n);case 31:return l=t.pendingProps,n=t.mode,l={mode:l.mode,children:l.children},e===null?(n=Xr(l,n),n.ref=t.ref,t.child=n,n.return=t,t=n):(n=Tn(e.child,l),n.ref=t.ref,t.child=n,n.return=t,t=n),t;case 22:return Vm(e,t,n);case 24:return zl(t),l=wt(rt),e===null?(i=Vs(),i===null&&(i=Xe,o=Gs(),i.pooledCache=o,o.refCount++,o!==null&&(i.pooledCacheLanes|=n),i=o),t.memoizedState={parent:l,cache:i},Xs(t),Kn(t,rt,i)):((e.lanes&n)!==0&&(Qs(e,t),vi(t,null,null,n),gi()),i=e.memoizedState,o=t.memoizedState,i.parent!==l?(i={parent:l,cache:l},t.memoizedState=i,t.lanes===0&&(t.memoizedState=t.updateQueue.baseState=i),Kn(t,rt,l)):(l=o.cache,Kn(t,rt,l),l!==i.cache&&Bs(t,[rt],n,!0))),gt(e,t,t.pendingProps.children,n),t.child;case 29:throw t.pendingProps}throw Error(c(156,t.tag))}function kn(e){e.flags|=4}function Im(e,t){if(t.type!=="stylesheet"||(t.state.loading&4)!==0)e.flags&=-16777217;else if(e.flags|=16777216,!ig(t)){if(t=Kt.current,t!==null&&((Me&4194048)===Me?hn!==null:(Me&62914560)!==Me&&(Me&536870912)===0||t!==hn))throw mi=Ys,zd;e.flags|=8192}}function Qr(e,t){t!==null&&(e.flags|=4),e.flags&16384&&(t=e.tag!==22?jf():536870912,e.lanes|=t,wa|=t)}function Ni(e,t){if(!ke)switch(e.tailMode){case"hidden":t=e.tail;for(var n=null;t!==null;)t.alternate!==null&&(n=t),t=t.sibling;n===null?e.tail=null:n.sibling=null;break;case"collapsed":n=e.tail;for(var l=null;n!==null;)n.alternate!==null&&(l=n),n=n.sibling;l===null?t||e.tail===null?e.tail=null:e.tail.sibling=null:l.sibling=null}}function Ke(e){var t=e.alternate!==null&&e.alternate.child===e.child,n=0,l=0;if(t)for(var i=e.child;i!==null;)n|=i.lanes|i.childLanes,l|=i.subtreeFlags&65011712,l|=i.flags&65011712,i.return=e,i=i.sibling;else for(i=e.child;i!==null;)n|=i.lanes|i.childLanes,l|=i.subtreeFlags,l|=i.flags,i.return=e,i=i.sibling;return e.subtreeFlags|=l,e.childLanes=n,t}function db(e,t,n){var l=t.pendingProps;switch(ks(t),t.tag){case 31:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return Ke(t),null;case 1:return Ke(t),null;case 3:return n=t.stateNode,l=null,e!==null&&(l=e.memoizedState.cache),t.memoizedState.cache!==l&&(t.flags|=2048),On(rt),De(),n.pendingContext&&(n.context=n.pendingContext,n.pendingContext=null),(e===null||e.child===null)&&(ri(t)?kn(t):e===null||e.memoizedState.isDehydrated&&(t.flags&256)===0||(t.flags|=1024,jd())),Ke(t),null;case 26:return n=t.memoizedState,e===null?(kn(t),n!==null?(Ke(t),Im(t,n)):(Ke(t),t.flags&=-16777217)):n?n!==e.memoizedState?(kn(t),Ke(t),Im(t,n)):(Ke(t),t.flags&=-16777217):(e.memoizedProps!==l&&kn(t),Ke(t),t.flags&=-16777217),null;case 27:Ne(t),n=ce.current;var i=t.type;if(e!==null&&t.stateNode!=null)e.memoizedProps!==l&&kn(t);else{if(!l){if(t.stateNode===null)throw Error(c(166));return Ke(t),null}e=I.current,ri(t)?Td(t):(e=Ih(i,l,n),t.stateNode=e,kn(t))}return Ke(t),null;case 5:if(Ne(t),n=t.type,e!==null&&t.stateNode!=null)e.memoizedProps!==l&&kn(t);else{if(!l){if(t.stateNode===null)throw Error(c(166));return Ke(t),null}if(e=I.current,ri(t))Td(t);else{switch(i=ac(ce.current),e){case 1:e=i.createElementNS("http://www.w3.org/2000/svg",n);break;case 2:e=i.createElementNS("http://www.w3.org/1998/Math/MathML",n);break;default:switch(n){case"svg":e=i.createElementNS("http://www.w3.org/2000/svg",n);break;case"math":e=i.createElementNS("http://www.w3.org/1998/Math/MathML",n);break;case"script":e=i.createElement("div"),e.innerHTML=" + + + +
+ + diff --git a/frontend/public/data/reproinventory_data.json b/frontend/public/data/reproinventory_data.json index 6c171e7..1653e65 100644 --- a/frontend/public/data/reproinventory_data.json +++ b/frontend/public/data/reproinventory_data.json @@ -1502,7 +1502,7 @@ "SS", "JB" ], - "course_name": "The Princeton Handbook for Reproducible Neuroimaging\u00b6", + "course_name": "The Princeton Handbook for Reproducible Neuroimaging¶", "url": "https://brainhack-princeton.github.io/handbook/", "level": [ "Beginner" @@ -1982,16 +1982,9 @@ "programming_language": null, "neuroimaging_software": null, "imaging_modality": null, + "open_dataset": "NA", - "last_updated": null, - "functionality": null, - "assessment": null, - "prerequisite": null, - "source": null, - "review": null, - "alias_links": null, - "notes": null, - "quadrants": null + "last_updated": 2026 }, { "id": 59, @@ -2028,9 +2021,14 @@ ], "course_name": "ABCD Repronim ML course", "url": "https://www.abcd-repronim.org/ml.html", - "level": null, + "level": [ + "Intermediate" + ], "platform": null, - "keywords": null, + "keywords": [ + "Machine Learning" + ], + "course_length": "NA", "course_length": [ "1+ weeks" ], @@ -2041,12 +2039,12 @@ "neuroimaging_software": null, "imaging_modality": null, "open_dataset": "NA", - "last_updated": null, + "last_updated": 2025, "functionality": null, "assessment": true, "prerequisite": null, "source": null, - "review": null, + "review": "3 week machone learning course", "alias_links": null, "notes": null, "quadrants": null @@ -2063,22 +2061,28 @@ "Intermediate" ], "platform": null, - "keywords": null, - "course_length": [ + "keywords": [ + "Reproducible Pipelines", + "Best Practices", + "Data Visualization" + ], + "course_length": [ "1-4 hrs" ], "instruction_medium": [ "lecture" ], "delivery": null, - "language": "English", + "language": [ + "English" + ], "programming_language": [ "Python" ], "neuroimaging_software": null, "imaging_modality": null, "open_dataset": "NA", - "last_updated": null, + "last_updated": 2025, "functionality": null, "assessment": null, "prerequisite": null, @@ -2087,5 +2091,21 @@ "alias_links": null, "notes": null, "quadrants": null + }, + { + "id": 62, + "course_name": "test course", + "platform": [ + "Mac" + ], + "instruction_medium": [ + "blog post" + ], + "delivery": [ + "instructor" + ], + "imaging_modality": [ + "Behavioral" + ] } ] \ No newline at end of file diff --git a/frontend/src/components/AddMaterialDialog.tsx b/frontend/src/components/AddMaterialDialog.tsx new file mode 100644 index 0000000..1e252ff --- /dev/null +++ b/frontend/src/components/AddMaterialDialog.tsx @@ -0,0 +1,424 @@ +import React, { useState } from "react"; +import { DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/ui/dialog"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { Checkbox } from "@/components/ui/checkbox"; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; +import { Plus, Minus } from "lucide-react"; +import type { + ReproInventoryEntry, + LevelEnum, + PlatformEnum, + CourseLengthEnum, + ContentFormatEnum, + DeliveryEnum, + LanguageEnum, + ProgrammingLanguageEnum, + NeuroimagingSoftwareEnum, + ImagingModalityEnum, + OpenDatasetEnum, + QuadrantsEnum, +} from "@/types/reproinventory"; + +const GITHUB_REPO = "https://github.com/ReproNim/ReproInventory"; + +const levelOptions: LevelEnum[] = ["Beginner", "Intermediate", "Advanced", "NA"]; +const platformOptions: PlatformEnum[] = ["Mac", "Windows", "Linux", "Docker", "Jupyter", "NA"]; +const courseLengthOptions: CourseLengthEnum[] = ["<1 hr", "1-4 hrs", "1 day", "1-3 days", "1 week", "1+ weeks", "NA"]; +const instructionMediumOptions: ContentFormatEnum[] = ["Hands-on tutorial / notebooks", "lecture", "video", "notes", "blog post", "reference", "slides", "website", "outline", "meta-resource", "NA"]; +const deliveryOptions: DeliveryEnum[] = ["self-paced", "instructor", "Hybrid", "Discussion needed"]; +const languageOptions: LanguageEnum[] = ["English", "French", "Spanish", "Chinese", "German", "English, French", "English, German", "Other", "NA"]; +const programmingLanguageOptions: ProgrammingLanguageEnum[] = ["Python", "R", "shell scripting", "Matlab", "Git", "NA"]; +const neuroimagingSoftwareOptions: NeuroimagingSoftwareEnum[] = ["AFNI", "SPM", "FSL", "Freesurfer", "Python", "Multiple", "NA"]; +const imagingModalityOptions: ImagingModalityEnum[] = ["DWI", "Structural", "Functional", "Task-based", "Resting-State", "EEG", "Behavioral", "MEG", "MRI", "NA"]; +const openDatasetOptions: OpenDatasetEnum[] = ["True", "False", "NA"]; +const quadrantsOptions: QuadrantsEnum[] = ["information-oriented (reference)", "understanding-oriented (explanation)", "learning-oriented (tutorials)", "problem-oriented (how to guides)", "NA"]; + +function formatAsYaml(material: ReproInventoryEntry): string { + const lines: string[] = []; + + const addScalar = (key: string, value: string | number | boolean | undefined | null) => { + if (value !== undefined && value !== null && value !== "") { + lines.push(`${key}: ${value}`); + } + }; + + const addList = (key: string, values: string[] | undefined | null) => { + if (values && values.length > 0) { + lines.push(`${key}:`); + values.forEach((v) => lines.push(` - ${v}`)); + } + }; + + lines.push("id: TBD"); + addScalar("course_name", material.course_name); + addScalar("url", material.url); + addList("level", material.level); + addList("platform", material.platform); + addList("keywords", material.keywords); + addScalar("course_length", material.course_length); + addList("instruction_medium", material.instruction_medium); + addList("delivery", material.delivery); + addList("language", material.language); + addList("programming_language", material.programming_language); + addList("neuroimaging_software", material.neuroimaging_software); + addList("imaging_modality", material.imaging_modality); + addScalar("open_dataset", material.open_dataset); + addScalar("review", material.review); + addScalar("notes", material.notes); + addList("quadrants", material.quadrants); + + return lines.join("\n"); +} + +function openGitHubIssue(material: ReproInventoryEntry) { + const yaml = formatAsYaml(material); + const title = `Add material: ${material.course_name || "New training material"}`; + const body = + `## New Training Material Submission\n\n` + + `Please review the following training material for addition to ReproInventory.\n\n` + + `\`\`\`yaml\n${yaml}\n\`\`\``; + const url = `${GITHUB_REPO}/issues/new?labels=new-material&title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}`; + window.open(url, "_blank"); +} + +interface AddMaterialDialogProps { + onClose: () => void; +} + +const AddMaterialDialog: React.FC = ({ onClose }) => { + const [material, setMaterial] = useState({ + id: "", + course_name: "", + url: "", + level: [], + platform: [], + keywords: [], + course_length: undefined, + instruction_medium: [], + delivery: [], + language: [], + programming_language: [], + neuroimaging_software: [], + imaging_modality: [], + open_dataset: undefined, + review: "", + notes: "", + quadrants: [], + }); + + const handleChange = (field: keyof ReproInventoryEntry, value: any) => { + setMaterial((prev) => ({ ...prev, [field]: value })); + }; + + const handleMultiSelectChange = (field: keyof ReproInventoryEntry, option: string, checked: boolean) => { + const current = (material[field] || []) as string[]; + handleChange(field, checked ? [...current, option] : current.filter((v) => v !== option)); + }; + + const handleArrayItemChange = (field: keyof ReproInventoryEntry, index: number, value: string) => { + const arr = [...((material[field] || []) as string[])]; + arr[index] = value; + handleChange(field, arr); + }; + + const handleAddArrayItem = (field: keyof ReproInventoryEntry) => { + handleChange(field, [...((material[field] || []) as string[]), ""]); + }; + + const handleRemoveArrayItem = (field: keyof ReproInventoryEntry, index: number) => { + handleChange(field, ((material[field] || []) as string[]).filter((_, i) => i !== index)); + }; + + const handleSubmit = () => { + if (!material.course_name?.trim()) { + alert("Please provide a course name."); + return; + } + openGitHubIssue(material); + onClose(); + }; + + return ( + + + Add New Training Material + + Fill in the details below. Submitting will open a pre-filled GitHub issue for maintainer review. + Only course name is required. + + + +
+ {/* Essential fields */} +
+ + handleChange("course_name", e.target.value)} + className="col-span-3" + placeholder="Enter course name" + /> +
+ +
+ + handleChange("url", e.target.value)} + className="col-span-3" + placeholder="https://example.com" + /> +
+ +
+ + handleChange("review", e.target.value)} + className="col-span-3" + placeholder="Brief description of the material" + /> +
+ + {/* Keywords */} +
+ +
+ {(material.keywords || []).map((keyword, index) => ( +
+ handleArrayItemChange("keywords", index, e.target.value)} + className="flex-grow" + placeholder="Enter keyword" + /> + +
+ ))} + +
+
+ + {/* Course Length */} +
+ + +
+ + {/* Multi-select grid */} +
+ {/* Level */} +
+ +
+ {levelOptions.map((option) => ( +
+ handleMultiSelectChange("level", option, checked as boolean)} + /> + +
+ ))} +
+
+ + {/* Platform */} +
+ +
+ {platformOptions.map((option) => ( +
+ handleMultiSelectChange("platform", option, checked as boolean)} + /> + +
+ ))} +
+
+ + {/* Instruction Medium */} +
+ +
+ {instructionMediumOptions.map((option) => ( +
+ handleMultiSelectChange("instruction_medium", option, checked as boolean)} + /> + +
+ ))} +
+
+ + {/* Delivery */} +
+ +
+ {deliveryOptions.map((option) => ( +
+ handleMultiSelectChange("delivery", option, checked as boolean)} + /> + +
+ ))} +
+
+ + {/* Language */} +
+ +
+ {languageOptions.map((option) => ( +
+ handleMultiSelectChange("language", option, checked as boolean)} + /> + +
+ ))} +
+
+ + {/* Programming Language */} +
+ +
+ {programmingLanguageOptions.map((option) => ( +
+ handleMultiSelectChange("programming_language", option, checked as boolean)} + /> + +
+ ))} +
+
+ + {/* Neuroimaging Software */} +
+ +
+ {neuroimagingSoftwareOptions.map((option) => ( +
+ handleMultiSelectChange("neuroimaging_software", option, checked as boolean)} + /> + +
+ ))} +
+
+ + {/* Imaging Modality */} +
+ +
+ {imagingModalityOptions.map((option) => ( +
+ handleMultiSelectChange("imaging_modality", option, checked as boolean)} + /> + +
+ ))} +
+
+
+ + {/* Open Dataset */} +
+ + +
+ + {/* Quadrants */} +
+ +
+ {quadrantsOptions.map((option) => ( +
+ handleMultiSelectChange("quadrants", option, checked as boolean)} + /> + +
+ ))} +
+
+ + {/* Notes */} +
+ + handleChange("notes", e.target.value)} + className="col-span-3" + placeholder="Additional notes" + /> +
+
+ +
+ + +
+
+ ); +}; + +export default AddMaterialDialog; diff --git a/frontend/src/components/EditMaterialDialog.tsx b/frontend/src/components/EditMaterialDialog.tsx index 3428921..c0a5f54 100644 --- a/frontend/src/components/EditMaterialDialog.tsx +++ b/frontend/src/components/EditMaterialDialog.tsx @@ -21,9 +21,66 @@ import type { QuadrantsEnum, } from "@/types/reproinventory"; +const GITHUB_REPO = "https://github.com/ReproNim/ReproInventory"; + +function formatAsYaml(material: ReproInventoryEntry): string { + const lines: string[] = []; + + const addScalar = (key: string, value: string | number | boolean | undefined | null) => { + if (value !== undefined && value !== null && value !== "") { + lines.push(`${key}: ${value}`); + } + }; + + const addList = (key: string, values: string[] | undefined | null) => { + if (values && values.length > 0) { + lines.push(`${key}:`); + values.forEach((v) => lines.push(` - ${v}`)); + } + }; + + addScalar("id", material.id); + addList("tag_team", material.tag_team); + addScalar("course_name", material.course_name); + addScalar("url", material.url); + addList("level", material.level); + addList("platform", material.platform); + addList("keywords", material.keywords); + addScalar("course_length", material.course_length); + addList("instruction_medium", material.instruction_medium); + addList("delivery", material.delivery); + addList("language", material.language); + addList("programming_language", material.programming_language); + addList("neuroimaging_software", material.neuroimaging_software); + addList("imaging_modality", material.imaging_modality); + addScalar("open_dataset", material.open_dataset); + addScalar("last_updated", material.last_updated); + addScalar("functionality", material.functionality); + addScalar("assessment", material.assessment); + addList("prerequisite", material.prerequisite); + addList("source", material.source); + addScalar("review", material.review); + addScalar("exclude_from_repro_inventory", material.exclude_from_repro_inventory); + addScalar("alias_links", material.alias_links); + addScalar("notes", material.notes); + addList("quadrants", material.quadrants); + + return lines.join("\n"); +} + +function openGitHubIssue(material: ReproInventoryEntry) { + const yaml = formatAsYaml(material); + const title = `Edit material: ${material.course_name || "Unknown"} (ID: ${material.id})`; + const body = + `## Edit Training Material Request\n\n` + + `Please update entry **ID: ${material.id}** in \`model/reproinventory_data.yaml\` with the following:\n\n` + + `\`\`\`yaml\n${yaml}\n\`\`\``; + const url = `${GITHUB_REPO}/issues/new?labels=edit-material&title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}`; + window.open(url, "_blank"); +} + interface EditMaterialDialogProps { material: ReproInventoryEntry; - onSave: (updatedMaterial: ReproInventoryEntry) => void; onClose: () => void; } @@ -39,11 +96,28 @@ const imagingModalityOptions: ImagingModalityEnum[] = ["DWI", "Structural", "Fun const openDatasetOptions: OpenDatasetEnum[] = ["True", "False", "NA"]; const quadrantsOptions: QuadrantsEnum[] = ["information-oriented (reference)", "understanding-oriented (explanation)", "learning-oriented (tutorials)", "problem-oriented (how to guides)", "NA"]; -const EditMaterialDialog: React.FC = ({ material, onSave, onClose }) => { - const [editedMaterial, setEditedMaterial] = useState(material); +const ARRAY_FIELDS: (keyof ReproInventoryEntry)[] = [ + "tag_team", "level", "platform", "keywords", "instruction_medium", + "delivery", "language", "programming_language", "neuroimaging_software", + "imaging_modality", "quadrants", "source", "prerequisite", +]; + +function normalizeMaterial(m: ReproInventoryEntry): ReproInventoryEntry { + const normalized = { ...m }; + for (const field of ARRAY_FIELDS) { + const val = normalized[field]; + if (val !== null && val !== undefined && !Array.isArray(val)) { + (normalized as any)[field] = [val]; + } + } + return normalized; +} + +const EditMaterialDialog: React.FC = ({ material, onClose }) => { + const [editedMaterial, setEditedMaterial] = useState(() => normalizeMaterial(material)); useEffect(() => { - setEditedMaterial(material); + setEditedMaterial(normalizeMaterial(material)); }, [material]); const handleChange = (field: keyof ReproInventoryEntry, value: any) => { @@ -77,7 +151,7 @@ const EditMaterialDialog: React.FC = ({ material, onSav }; const handleSave = () => { - onSave(editedMaterial); + openGitHubIssue(editedMaterial); onClose(); }; @@ -439,7 +513,7 @@ const EditMaterialDialog: React.FC = ({ material, onSav
- +
); diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index bef5202..360a3c3 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -8,3 +8,4 @@ createRoot(document.getElementById('root')!).render( , ) + diff --git a/frontend/src/training-materials-browser.tsx b/frontend/src/training-materials-browser.tsx index ec23847..fba7826 100644 --- a/frontend/src/training-materials-browser.tsx +++ b/frontend/src/training-materials-browser.tsx @@ -13,6 +13,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion" import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/ui/dialog" // Adjusted import import EditMaterialDialog from "@/components/EditMaterialDialog"; // Import the new component +import AddMaterialDialog from "@/components/AddMaterialDialog"; import { type ReproInventoryEntry, type LevelEnum, @@ -34,6 +35,7 @@ export default function TrainingMaterialsBrowser() { const [error, setError] = useState(null) const [selectedRawMaterial, setSelectedRawMaterial] = useState(null) const [editingMaterial, setEditingMaterial] = useState(null) + const [showAddMaterial, setShowAddMaterial] = useState(false) useEffect(() => { const fetchData = async () => { @@ -590,23 +592,29 @@ export default function TrainingMaterialsBrowser() {

Results for "{searchQuery}"

)} + + + + + setShowAddMaterial(false)} /> +
{filteredMaterials.map((material) => ( -
+
{getFormatIcon(material.instruction_medium?.[0] || "")} {material.instruction_medium?.[0] || "N/A"}
- {material.assessment && Assessment} + {material.assessment && Assessment}
- {material.course_name} - {material.review} + {material.course_name} + {material.review}
@@ -651,12 +659,12 @@ export default function TrainingMaterialsBrowser() {
{material.url && ( - - Access Material + + Access Material )}
-
+
+
diff --git a/model/reproinventory_data.yaml b/model/reproinventory_data.yaml index 29830a3..9995185 100644 --- a/model/reproinventory_data.yaml +++ b/model/reproinventory_data.yaml @@ -1152,7 +1152,7 @@ - CF - SS - JB - course_name: "The Princeton Handbook for Reproducible Neuroimaging\xB6" + course_name: The Princeton Handbook for Reproducible Neuroimaging¶ url: https://brainhack-princeton.github.io/handbook/ level: - Beginner @@ -1524,26 +1524,21 @@ - JB course_name: Andy's brain book url: https://andysbrainbook.readthedocs.io/en/latest/ + course_length: NA level: null platform: null keywords: null course_length: 1+ weeks - instruction_medium: null + instruction_medium: + - blog post + - Hands-on tutorial / notebooks delivery: null language: null programming_language: null neuroimaging_software: null imaging_modality: null open_dataset: NA - last_updated: null - functionality: null - assessment: null - prerequisite: null - source: null - review: null - alias_links: null - notes: null - quadrants: null + last_updated: 2026 - id: 59 tag_team: - JB @@ -1574,9 +1569,11 @@ - JB course_name: ABCD Repronim ML course url: https://www.abcd-repronim.org/ml.html - level: null + level: + - Intermediate platform: null - keywords: null + keywords: + - Machine Learning course_length: - 1+ weeks instruction_medium: null @@ -1626,3 +1623,13 @@ alias_links: null notes: null quadrants: null +- id: 62 + course_name: test course + platform: + - Mac + instruction_medium: + - blog post + delivery: + - instructor + imaging_modality: + - Behavioral