diff --git a/dist/assets/index-Dnv_KkUR.js b/dist/assets/index-Dnv_KkUR.js new file mode 100644 index 0000000..28595d9 --- /dev/null +++ b/dist/assets/index-Dnv_KkUR.js @@ -0,0 +1,506 @@ +(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const a of document.querySelectorAll('link[rel="modulepreload"]'))r(a);new MutationObserver(a=>{for(const s of a)if(s.type==="childList")for(const l of s.addedNodes)l.tagName==="LINK"&&l.rel==="modulepreload"&&r(l)}).observe(document,{childList:!0,subtree:!0});function n(a){const s={};return a.integrity&&(s.integrity=a.integrity),a.referrerPolicy&&(s.referrerPolicy=a.referrerPolicy),a.crossOrigin==="use-credentials"?s.credentials="include":a.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function r(a){if(a.ep)return;a.ep=!0;const s=n(a);fetch(a.href,s)}})();function Ki(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var qi={exports:{}},La={},Yi={exports:{}},H={};/** + * @license React + * react.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Cr=Symbol.for("react.element"),wd=Symbol.for("react.portal"),kd=Symbol.for("react.fragment"),bd=Symbol.for("react.strict_mode"),Sd=Symbol.for("react.profiler"),Nd=Symbol.for("react.provider"),jd=Symbol.for("react.context"),Cd=Symbol.for("react.forward_ref"),Ed=Symbol.for("react.suspense"),Ad=Symbol.for("react.memo"),_d=Symbol.for("react.lazy"),So=Symbol.iterator;function Pd(e){return e===null||typeof e!="object"?null:(e=So&&e[So]||e["@@iterator"],typeof e=="function"?e:null)}var Xi={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},Ji=Object.assign,Zi={};function Mn(e,t,n){this.props=e,this.context=t,this.refs=Zi,this.updater=n||Xi}Mn.prototype.isReactComponent={};Mn.prototype.setState=function(e,t){if(typeof e!="object"&&typeof e!="function"&&e!=null)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,e,t,"setState")};Mn.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")};function eu(){}eu.prototype=Mn.prototype;function Nl(e,t,n){this.props=e,this.context=t,this.refs=Zi,this.updater=n||Xi}var jl=Nl.prototype=new eu;jl.constructor=Nl;Ji(jl,Mn.prototype);jl.isPureReactComponent=!0;var No=Array.isArray,tu=Object.prototype.hasOwnProperty,Cl={current:null},nu={key:!0,ref:!0,__self:!0,__source:!0};function ru(e,t,n){var r,a={},s=null,l=null;if(t!=null)for(r in t.ref!==void 0&&(l=t.ref),t.key!==void 0&&(s=""+t.key),t)tu.call(t,r)&&!nu.hasOwnProperty(r)&&(a[r]=t[r]);var i=arguments.length-2;if(i===1)a.children=n;else if(1>>1,w=y[z];if(0>>1;za(Q,A))Ga(ne,Q)?(y[z]=ne,y[G]=A,z=G):(y[z]=Q,y[O]=A,z=O);else if(Ga(ne,A))y[z]=ne,y[G]=A,z=G;else break e}}return E}function a(y,E){var A=y.sortIndex-E.sortIndex;return A!==0?A:y.id-E.id}if(typeof performance=="object"&&typeof performance.now=="function"){var s=performance;e.unstable_now=function(){return s.now()}}else{var l=Date,i=l.now();e.unstable_now=function(){return l.now()-i}}var u=[],d=[],g=1,h=null,m=3,v=!1,k=!1,x=!1,_=typeof setTimeout=="function"?setTimeout:null,f=typeof clearTimeout=="function"?clearTimeout:null,c=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function p(y){for(var E=n(d);E!==null;){if(E.callback===null)r(d);else if(E.startTime<=y)r(d),E.sortIndex=E.expirationTime,t(u,E);else break;E=n(d)}}function b(y){if(x=!1,p(y),!k)if(n(u)!==null)k=!0,V(P);else{var E=n(d);E!==null&&U(b,E.startTime-y)}}function P(y,E){k=!1,x&&(x=!1,f(R),R=-1),v=!0;var A=m;try{for(p(E),h=n(u);h!==null&&(!(h.expirationTime>E)||y&&!q());){var z=h.callback;if(typeof z=="function"){h.callback=null,m=h.priorityLevel;var w=z(h.expirationTime<=E);E=e.unstable_now(),typeof w=="function"?h.callback=w:h===n(u)&&r(u),p(E)}else r(u);h=n(u)}if(h!==null)var T=!0;else{var O=n(d);O!==null&&U(b,O.startTime-E),T=!1}return T}finally{h=null,m=A,v=!1}}var j=!1,N=null,R=-1,$=5,D=-1;function q(){return!(e.unstable_now()-D<$)}function Y(){if(N!==null){var y=e.unstable_now();D=y;var E=!0;try{E=N(!0,y)}finally{E?ue():(j=!1,N=null)}}else j=!1}var ue;if(typeof c=="function")ue=function(){c(Y)};else if(typeof MessageChannel<"u"){var pe=new MessageChannel,ce=pe.port2;pe.port1.onmessage=Y,ue=function(){ce.postMessage(null)}}else ue=function(){_(Y,0)};function V(y){N=y,j||(j=!0,ue())}function U(y,E){R=_(function(){y(e.unstable_now())},E)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(y){y.callback=null},e.unstable_continueExecution=function(){k||v||(k=!0,V(P))},e.unstable_forceFrameRate=function(y){0>y||125z?(y.sortIndex=A,t(d,y),n(u)===null&&y===n(d)&&(x?(f(R),R=-1):x=!0,U(b,A-z))):(y.sortIndex=w,t(u,y),k||v||(k=!0,V(P))),y},e.unstable_shouldYield=q,e.unstable_wrapCallback=function(y){var E=m;return function(){var A=m;m=E;try{return y.apply(this,arguments)}finally{m=A}}}})(iu);ou.exports=iu;var Vd=ou.exports;/** + * @license React + * react-dom.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Ud=W,Ve=Vd;function C(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),zs=Object.prototype.hasOwnProperty,Hd=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,Co={},Eo={};function Bd(e){return zs.call(Eo,e)?!0:zs.call(Co,e)?!1:Hd.test(e)?Eo[e]=!0:(Co[e]=!0,!1)}function Qd(e,t,n,r){if(n!==null&&n.type===0)return!1;switch(typeof t){case"function":case"symbol":return!0;case"boolean":return r?!1:n!==null?!n.acceptsBooleans:(e=e.toLowerCase().slice(0,5),e!=="data-"&&e!=="aria-");default:return!1}}function Gd(e,t,n,r){if(t===null||typeof t>"u"||Qd(e,t,n,r))return!0;if(r)return!1;if(n!==null)switch(n.type){case 3:return!t;case 4:return t===!1;case 5:return isNaN(t);case 6:return isNaN(t)||1>t}return!1}function De(e,t,n,r,a,s,l){this.acceptsBooleans=t===2||t===3||t===4,this.attributeName=r,this.attributeNamespace=a,this.mustUseProperty=n,this.propertyName=e,this.type=t,this.sanitizeURL=s,this.removeEmptyString=l}var Se={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(e){Se[e]=new De(e,0,!1,e,null,!1,!1)});[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(e){var t=e[0];Se[t]=new De(t,1,!1,e[1],null,!1,!1)});["contentEditable","draggable","spellCheck","value"].forEach(function(e){Se[e]=new De(e,2,!1,e.toLowerCase(),null,!1,!1)});["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(e){Se[e]=new De(e,2,!1,e,null,!1,!1)});"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(e){Se[e]=new De(e,3,!1,e.toLowerCase(),null,!1,!1)});["checked","multiple","muted","selected"].forEach(function(e){Se[e]=new De(e,3,!0,e,null,!1,!1)});["capture","download"].forEach(function(e){Se[e]=new De(e,4,!1,e,null,!1,!1)});["cols","rows","size","span"].forEach(function(e){Se[e]=new De(e,6,!1,e,null,!1,!1)});["rowSpan","start"].forEach(function(e){Se[e]=new De(e,5,!1,e.toLowerCase(),null,!1,!1)});var Al=/[\-:]([a-z])/g;function _l(e){return e[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(e){var t=e.replace(Al,_l);Se[t]=new De(t,1,!1,e,null,!1,!1)});"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(e){var t=e.replace(Al,_l);Se[t]=new De(t,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)});["xml:base","xml:lang","xml:space"].forEach(function(e){var t=e.replace(Al,_l);Se[t]=new De(t,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)});["tabIndex","crossOrigin"].forEach(function(e){Se[e]=new De(e,1,!1,e.toLowerCase(),null,!1,!1)});Se.xlinkHref=new De("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1);["src","href","action","formAction"].forEach(function(e){Se[e]=new De(e,1,!1,e.toLowerCase(),null,!0,!0)});function Pl(e,t,n,r){var a=Se.hasOwnProperty(t)?Se[t]:null;(a!==null?a.type!==0:r||!(2i||a[l]!==s[i]){var u=` +`+a[l].replace(" at new "," at ");return e.displayName&&u.includes("")&&(u=u.replace("",e.displayName)),u}while(1<=l&&0<=i);break}}}finally{ss=!1,Error.prepareStackTrace=n}return(e=e?e.displayName||e.name:"")?Kn(e):""}function Kd(e){switch(e.tag){case 5:return Kn(e.type);case 16:return Kn("Lazy");case 13:return Kn("Suspense");case 19:return Kn("SuspenseList");case 0:case 2:case 15:return e=ls(e.type,!1),e;case 11:return e=ls(e.type.render,!1),e;case 1:return e=ls(e.type,!0),e;default:return""}}function Ts(e){if(e==null)return null;if(typeof e=="function")return e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case on:return"Fragment";case ln:return"Portal";case Ds:return"Profiler";case zl:return"StrictMode";case Ms:return"Suspense";case Rs:return"SuspenseList"}if(typeof e=="object")switch(e.$$typeof){case du:return(e.displayName||"Context")+".Consumer";case cu:return(e._context.displayName||"Context")+".Provider";case Dl:var t=e.render;return e=e.displayName,e||(e=t.displayName||t.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case Ml:return t=e.displayName||null,t!==null?t:Ts(e.type)||"Memo";case bt:t=e._payload,e=e._init;try{return Ts(e(t))}catch{}}return null}function qd(e){var t=e.type;switch(e.tag){case 24:return"Cache";case 9:return(t.displayName||"Context")+".Consumer";case 10:return(t._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=t.render,e=e.displayName||e.name||"",t.displayName||(e!==""?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return t;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return Ts(t);case 8:return t===zl?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof t=="function")return t.displayName||t.name||null;if(typeof t=="string")return t}return null}function It(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":return e;case"object":return e;default:return""}}function pu(e){var t=e.type;return(e=e.nodeName)&&e.toLowerCase()==="input"&&(t==="checkbox"||t==="radio")}function Yd(e){var t=pu(e)?"checked":"value",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),r=""+e[t];if(!e.hasOwnProperty(t)&&typeof n<"u"&&typeof n.get=="function"&&typeof n.set=="function"){var a=n.get,s=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return a.call(this)},set:function(l){r=""+l,s.call(this,l)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return r},setValue:function(l){r=""+l},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}function Ir(e){e._valueTracker||(e._valueTracker=Yd(e))}function mu(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),r="";return e&&(r=pu(e)?e.checked?"true":"false":e.value),e=r,e!==n?(t.setValue(e),!0):!1}function pa(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}}function Is(e,t){var n=t.checked;return le({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:n??e._wrapperState.initialChecked})}function _o(e,t){var n=t.defaultValue==null?"":t.defaultValue,r=t.checked!=null?t.checked:t.defaultChecked;n=It(t.value!=null?t.value:n),e._wrapperState={initialChecked:r,initialValue:n,controlled:t.type==="checkbox"||t.type==="radio"?t.checked!=null:t.value!=null}}function gu(e,t){t=t.checked,t!=null&&Pl(e,"checked",t,!1)}function Ls(e,t){gu(e,t);var n=It(t.value),r=t.type;if(n!=null)r==="number"?(n===0&&e.value===""||e.value!=n)&&(e.value=""+n):e.value!==""+n&&(e.value=""+n);else if(r==="submit"||r==="reset"){e.removeAttribute("value");return}t.hasOwnProperty("value")?$s(e,t.type,n):t.hasOwnProperty("defaultValue")&&$s(e,t.type,It(t.defaultValue)),t.checked==null&&t.defaultChecked!=null&&(e.defaultChecked=!!t.defaultChecked)}function Po(e,t,n){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var r=t.type;if(!(r!=="submit"&&r!=="reset"||t.value!==void 0&&t.value!==null))return;t=""+e._wrapperState.initialValue,n||t===e.value||(e.value=t),e.defaultValue=t}n=e.name,n!==""&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,n!==""&&(e.name=n)}function $s(e,t,n){(t!=="number"||pa(e.ownerDocument)!==e)&&(n==null?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+n&&(e.defaultValue=""+n))}var qn=Array.isArray;function vn(e,t,n,r){if(e=e.options,t){t={};for(var a=0;a"+t.valueOf().toString()+"",t=Lr.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}});function ir(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&n.nodeType===3){n.nodeValue=t;return}}e.textContent=t}var Jn={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},Xd=["Webkit","ms","Moz","O"];Object.keys(Jn).forEach(function(e){Xd.forEach(function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),Jn[t]=Jn[e]})});function vu(e,t,n){return t==null||typeof t=="boolean"||t===""?"":n||typeof t!="number"||t===0||Jn.hasOwnProperty(e)&&Jn[e]?(""+t).trim():t+"px"}function wu(e,t){e=e.style;for(var n in t)if(t.hasOwnProperty(n)){var r=n.indexOf("--")===0,a=vu(n,t[n],r);n==="float"&&(n="cssFloat"),r?e.setProperty(n,a):e[n]=a}}var Jd=le({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function Ws(e,t){if(t){if(Jd[e]&&(t.children!=null||t.dangerouslySetInnerHTML!=null))throw Error(C(137,e));if(t.dangerouslySetInnerHTML!=null){if(t.children!=null)throw Error(C(60));if(typeof t.dangerouslySetInnerHTML!="object"||!("__html"in t.dangerouslySetInnerHTML))throw Error(C(61))}if(t.style!=null&&typeof t.style!="object")throw Error(C(62))}}function Vs(e,t){if(e.indexOf("-")===-1)return typeof t.is=="string";switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var Us=null;function Rl(e){return e=e.target||e.srcElement||window,e.correspondingUseElement&&(e=e.correspondingUseElement),e.nodeType===3?e.parentNode:e}var Hs=null,wn=null,kn=null;function Mo(e){if(e=_r(e)){if(typeof Hs!="function")throw Error(C(280));var t=e.stateNode;t&&(t=Va(t),Hs(e.stateNode,e.type,t))}}function ku(e){wn?kn?kn.push(e):kn=[e]:wn=e}function bu(){if(wn){var e=wn,t=kn;if(kn=wn=null,Mo(e),t)for(e=0;e>>=0,e===0?32:31-(cf(e)/df|0)|0}var $r=64,Or=4194304;function Yn(e){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: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 e&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return e&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return e}}function ya(e,t){var n=e.pendingLanes;if(n===0)return 0;var r=0,a=e.suspendedLanes,s=e.pingedLanes,l=n&268435455;if(l!==0){var i=l&~a;i!==0?r=Yn(i):(s&=l,s!==0&&(r=Yn(s)))}else l=n&~a,l!==0?r=Yn(l):s!==0&&(r=Yn(s));if(r===0)return 0;if(t!==0&&t!==r&&!(t&a)&&(a=r&-r,s=t&-t,a>=s||a===16&&(s&4194240)!==0))return t;if(r&4&&(r|=n&16),t=e.entangledLanes,t!==0)for(e=e.entanglements,t&=r;0n;n++)t.push(e);return t}function Er(e,t,n){e.pendingLanes|=t,t!==536870912&&(e.suspendedLanes=0,e.pingedLanes=0),e=e.eventTimes,t=31-nt(t),e[t]=n}function gf(e,t){var n=e.pendingLanes&~t;e.pendingLanes=t,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=t,e.mutableReadLanes&=t,e.entangledLanes&=t,t=e.entanglements;var r=e.eventTimes;for(e=e.expirationTimes;0=er),Vo=" ",Uo=!1;function Vu(e,t){switch(e){case"keyup":return Uf.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Uu(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var un=!1;function Bf(e,t){switch(e){case"compositionend":return Uu(t);case"keypress":return t.which!==32?null:(Uo=!0,Vo);case"textInput":return e=t.data,e===Vo&&Uo?null:e;default:return null}}function Qf(e,t){if(un)return e==="compositionend"||!Vl&&Vu(e,t)?(e=Fu(),na=Ol=Ct=null,un=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}e:{for(;n;){if(n.nextSibling){n=n.nextSibling;break e}n=n.parentNode}n=void 0}n=Go(n)}}function Gu(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?Gu(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Ku(){for(var e=window,t=pa();t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href=="string"}catch{n=!1}if(n)e=t.contentWindow;else break;t=pa(e.document)}return t}function Ul(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")}function t0(e){var t=Ku(),n=e.focusedElem,r=e.selectionRange;if(t!==n&&n&&n.ownerDocument&&Gu(n.ownerDocument.documentElement,n)){if(r!==null&&Ul(n)){if(t=r.start,e=r.end,e===void 0&&(e=t),"selectionStart"in n)n.selectionStart=t,n.selectionEnd=Math.min(e,n.value.length);else if(e=(t=n.ownerDocument||document)&&t.defaultView||window,e.getSelection){e=e.getSelection();var a=n.textContent.length,s=Math.min(r.start,a);r=r.end===void 0?s:Math.min(r.end,a),!e.extend&&s>r&&(a=r,r=s,s=a),a=Ko(n,s);var l=Ko(n,r);a&&l&&(e.rangeCount!==1||e.anchorNode!==a.node||e.anchorOffset!==a.offset||e.focusNode!==l.node||e.focusOffset!==l.offset)&&(t=t.createRange(),t.setStart(a.node,a.offset),e.removeAllRanges(),s>r?(e.addRange(t),e.extend(l.node,l.offset)):(t.setEnd(l.node,l.offset),e.addRange(t)))}}for(t=[],e=n;e=e.parentNode;)e.nodeType===1&&t.push({element:e,left:e.scrollLeft,top:e.scrollTop});for(typeof n.focus=="function"&&n.focus(),n=0;n=document.documentMode,cn=null,Ys=null,nr=null,Xs=!1;function qo(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;Xs||cn==null||cn!==pa(r)||(r=cn,"selectionStart"in r&&Ul(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),nr&&mr(nr,r)||(nr=r,r=wa(Ys,"onSelect"),0pn||(e.current=rl[pn],rl[pn]=null,pn--)}function J(e,t){pn++,rl[pn]=e.current,e.current=t}var Lt={},Ae=Ot(Lt),Ie=Ot(!1),Xt=Lt;function Cn(e,t){var n=e.type.contextTypes;if(!n)return Lt;var r=e.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===t)return r.__reactInternalMemoizedMaskedChildContext;var a={},s;for(s in n)a[s]=t[s];return r&&(e=e.stateNode,e.__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=a),a}function Le(e){return e=e.childContextTypes,e!=null}function ba(){ee(Ie),ee(Ae)}function ni(e,t,n){if(Ae.current!==Lt)throw Error(C(168));J(Ae,t),J(Ie,n)}function rc(e,t,n){var r=e.stateNode;if(t=t.childContextTypes,typeof r.getChildContext!="function")return n;r=r.getChildContext();for(var a in r)if(!(a in t))throw Error(C(108,qd(e)||"Unknown",a));return le({},n,r)}function Sa(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||Lt,Xt=Ae.current,J(Ae,e),J(Ie,Ie.current),!0}function ri(e,t,n){var r=e.stateNode;if(!r)throw Error(C(169));n?(e=rc(e,t,Xt),r.__reactInternalMemoizedMergedChildContext=e,ee(Ie),ee(Ae),J(Ae,e)):ee(Ie),J(Ie,n)}var ft=null,Ua=!1,ws=!1;function ac(e){ft===null?ft=[e]:ft.push(e)}function p0(e){Ua=!0,ac(e)}function Ft(){if(!ws&&ft!==null){ws=!0;var e=0,t=K;try{var n=ft;for(K=1;e>=l,a-=l,pt=1<<32-nt(t)+a|n<R?($=N,N=null):$=N.sibling;var D=m(f,N,p[R],b);if(D===null){N===null&&(N=$);break}e&&N&&D.alternate===null&&t(f,N),c=s(D,c,R),j===null?P=D:j.sibling=D,j=D,N=$}if(R===p.length)return n(f,N),te&&Ut(f,R),P;if(N===null){for(;RR?($=N,N=null):$=N.sibling;var q=m(f,N,D.value,b);if(q===null){N===null&&(N=$);break}e&&N&&q.alternate===null&&t(f,N),c=s(q,c,R),j===null?P=q:j.sibling=q,j=q,N=$}if(D.done)return n(f,N),te&&Ut(f,R),P;if(N===null){for(;!D.done;R++,D=p.next())D=h(f,D.value,b),D!==null&&(c=s(D,c,R),j===null?P=D:j.sibling=D,j=D);return te&&Ut(f,R),P}for(N=r(f,N);!D.done;R++,D=p.next())D=v(N,f,R,D.value,b),D!==null&&(e&&D.alternate!==null&&N.delete(D.key===null?R:D.key),c=s(D,c,R),j===null?P=D:j.sibling=D,j=D);return e&&N.forEach(function(Y){return t(f,Y)}),te&&Ut(f,R),P}function _(f,c,p,b){if(typeof p=="object"&&p!==null&&p.type===on&&p.key===null&&(p=p.props.children),typeof p=="object"&&p!==null){switch(p.$$typeof){case Tr:e:{for(var P=p.key,j=c;j!==null;){if(j.key===P){if(P=p.type,P===on){if(j.tag===7){n(f,j.sibling),c=a(j,p.props.children),c.return=f,f=c;break e}}else if(j.elementType===P||typeof P=="object"&&P!==null&&P.$$typeof===bt&&li(P)===j.type){n(f,j.sibling),c=a(j,p.props),c.ref=Un(f,j,p),c.return=f,f=c;break e}n(f,j);break}else t(f,j);j=j.sibling}p.type===on?(c=qt(p.props.children,f.mode,b,p.key),c.return=f,f=c):(b=ca(p.type,p.key,p.props,null,f.mode,b),b.ref=Un(f,c,p),b.return=f,f=b)}return l(f);case ln:e:{for(j=p.key;c!==null;){if(c.key===j)if(c.tag===4&&c.stateNode.containerInfo===p.containerInfo&&c.stateNode.implementation===p.implementation){n(f,c.sibling),c=a(c,p.children||[]),c.return=f,f=c;break e}else{n(f,c);break}else t(f,c);c=c.sibling}c=As(p,f.mode,b),c.return=f,f=c}return l(f);case bt:return j=p._init,_(f,c,j(p._payload),b)}if(qn(p))return k(f,c,p,b);if($n(p))return x(f,c,p,b);Qr(f,p)}return typeof p=="string"&&p!==""||typeof p=="number"?(p=""+p,c!==null&&c.tag===6?(n(f,c.sibling),c=a(c,p),c.return=f,f=c):(n(f,c),c=Es(p,f.mode,b),c.return=f,f=c),l(f)):n(f,c)}return _}var An=ic(!0),uc=ic(!1),Ca=Ot(null),Ea=null,hn=null,Gl=null;function Kl(){Gl=hn=Ea=null}function ql(e){var t=Ca.current;ee(Ca),e._currentValue=t}function ll(e,t,n){for(;e!==null;){var r=e.alternate;if((e.childLanes&t)!==t?(e.childLanes|=t,r!==null&&(r.childLanes|=t)):r!==null&&(r.childLanes&t)!==t&&(r.childLanes|=t),e===n)break;e=e.return}}function Sn(e,t){Ea=e,Gl=hn=null,e=e.dependencies,e!==null&&e.firstContext!==null&&(e.lanes&t&&(Te=!0),e.firstContext=null)}function qe(e){var t=e._currentValue;if(Gl!==e)if(e={context:e,memoizedValue:t,next:null},hn===null){if(Ea===null)throw Error(C(308));hn=e,Ea.dependencies={lanes:0,firstContext:e}}else hn=hn.next=e;return t}var Qt=null;function Yl(e){Qt===null?Qt=[e]:Qt.push(e)}function cc(e,t,n,r){var a=t.interleaved;return a===null?(n.next=n,Yl(t)):(n.next=a.next,a.next=n),t.interleaved=n,xt(e,r)}function xt(e,t){e.lanes|=t;var n=e.alternate;for(n!==null&&(n.lanes|=t),n=e,e=e.return;e!==null;)e.childLanes|=t,n=e.alternate,n!==null&&(n.childLanes|=t),n=e,e=e.return;return n.tag===3?n.stateNode:null}var St=!1;function Xl(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function dc(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,effects:e.effects})}function gt(e,t){return{eventTime:e,lane:t,tag:0,payload:null,callback:null,next:null}}function Dt(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,B&2){var a=r.pending;return a===null?t.next=t:(t.next=a.next,a.next=t),r.pending=t,xt(e,n)}return a=r.interleaved,a===null?(t.next=t,Yl(r)):(t.next=a.next,a.next=t),r.interleaved=t,xt(e,n)}function aa(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,(n&4194240)!==0)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,Il(e,n)}}function oi(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var a=null,s=null;if(n=n.firstBaseUpdate,n!==null){do{var l={eventTime:n.eventTime,lane:n.lane,tag:n.tag,payload:n.payload,callback:n.callback,next:null};s===null?a=s=l:s=s.next=l,n=n.next}while(n!==null);s===null?a=s=t:s=s.next=t}else a=s=t;n={baseState:r.baseState,firstBaseUpdate:a,lastBaseUpdate:s,shared:r.shared,effects:r.effects},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}function Aa(e,t,n,r){var a=e.updateQueue;St=!1;var s=a.firstBaseUpdate,l=a.lastBaseUpdate,i=a.shared.pending;if(i!==null){a.shared.pending=null;var u=i,d=u.next;u.next=null,l===null?s=d:l.next=d,l=u;var g=e.alternate;g!==null&&(g=g.updateQueue,i=g.lastBaseUpdate,i!==l&&(i===null?g.firstBaseUpdate=d:i.next=d,g.lastBaseUpdate=u))}if(s!==null){var h=a.baseState;l=0,g=d=u=null,i=s;do{var m=i.lane,v=i.eventTime;if((r&m)===m){g!==null&&(g=g.next={eventTime:v,lane:0,tag:i.tag,payload:i.payload,callback:i.callback,next:null});e:{var k=e,x=i;switch(m=t,v=n,x.tag){case 1:if(k=x.payload,typeof k=="function"){h=k.call(v,h,m);break e}h=k;break e;case 3:k.flags=k.flags&-65537|128;case 0:if(k=x.payload,m=typeof k=="function"?k.call(v,h,m):k,m==null)break e;h=le({},h,m);break e;case 2:St=!0}}i.callback!==null&&i.lane!==0&&(e.flags|=64,m=a.effects,m===null?a.effects=[i]:m.push(i))}else v={eventTime:v,lane:m,tag:i.tag,payload:i.payload,callback:i.callback,next:null},g===null?(d=g=v,u=h):g=g.next=v,l|=m;if(i=i.next,i===null){if(i=a.shared.pending,i===null)break;m=i,i=m.next,m.next=null,a.lastBaseUpdate=m,a.shared.pending=null}}while(!0);if(g===null&&(u=h),a.baseState=u,a.firstBaseUpdate=d,a.lastBaseUpdate=g,t=a.shared.interleaved,t!==null){a=t;do l|=a.lane,a=a.next;while(a!==t)}else s===null&&(a.shared.lanes=0);en|=l,e.lanes=l,e.memoizedState=h}}function ii(e,t,n){if(e=t.effects,t.effects=null,e!==null)for(t=0;tn?n:4,e(!0);var r=bs.transition;bs.transition={};try{e(!1),t()}finally{K=n,bs.transition=r}}function Ac(){return Ye().memoizedState}function y0(e,t,n){var r=Rt(e);if(n={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null},_c(e))Pc(t,n);else if(n=cc(e,t,n,r),n!==null){var a=Pe();rt(n,e,r,a),zc(n,t,r)}}function x0(e,t,n){var r=Rt(e),a={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null};if(_c(e))Pc(t,a);else{var s=e.alternate;if(e.lanes===0&&(s===null||s.lanes===0)&&(s=t.lastRenderedReducer,s!==null))try{var l=t.lastRenderedState,i=s(l,n);if(a.hasEagerState=!0,a.eagerState=i,at(i,l)){var u=t.interleaved;u===null?(a.next=a,Yl(t)):(a.next=u.next,u.next=a),t.interleaved=a;return}}catch{}finally{}n=cc(e,t,a,r),n!==null&&(a=Pe(),rt(n,e,r,a),zc(n,t,r))}}function _c(e){var t=e.alternate;return e===se||t!==null&&t===se}function Pc(e,t){rr=Pa=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function zc(e,t,n){if(n&4194240){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,Il(e,n)}}var za={readContext:qe,useCallback:je,useContext:je,useEffect:je,useImperativeHandle:je,useInsertionEffect:je,useLayoutEffect:je,useMemo:je,useReducer:je,useRef:je,useState:je,useDebugValue:je,useDeferredValue:je,useTransition:je,useMutableSource:je,useSyncExternalStore:je,useId:je,unstable_isNewReconciler:!1},v0={readContext:qe,useCallback:function(e,t){return lt().memoizedState=[e,t===void 0?null:t],e},useContext:qe,useEffect:ci,useImperativeHandle:function(e,t,n){return n=n!=null?n.concat([e]):null,la(4194308,4,Sc.bind(null,t,e),n)},useLayoutEffect:function(e,t){return la(4194308,4,e,t)},useInsertionEffect:function(e,t){return la(4,2,e,t)},useMemo:function(e,t){var n=lt();return t=t===void 0?null:t,e=e(),n.memoizedState=[e,t],e},useReducer:function(e,t,n){var r=lt();return t=n!==void 0?n(t):t,r.memoizedState=r.baseState=t,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:t},r.queue=e,e=e.dispatch=y0.bind(null,se,e),[r.memoizedState,e]},useRef:function(e){var t=lt();return e={current:e},t.memoizedState=e},useState:ui,useDebugValue:so,useDeferredValue:function(e){return lt().memoizedState=e},useTransition:function(){var e=ui(!1),t=e[0];return e=h0.bind(null,e[1]),lt().memoizedState=e,[t,e]},useMutableSource:function(){},useSyncExternalStore:function(e,t,n){var r=se,a=lt();if(te){if(n===void 0)throw Error(C(407));n=n()}else{if(n=t(),ve===null)throw Error(C(349));Zt&30||gc(r,t,n)}a.memoizedState=n;var s={value:n,getSnapshot:t};return a.queue=s,ci(yc.bind(null,r,s,e),[e]),r.flags|=2048,br(9,hc.bind(null,r,s,n,t),void 0,null),n},useId:function(){var e=lt(),t=ve.identifierPrefix;if(te){var n=mt,r=pt;n=(r&~(1<<32-nt(r)-1)).toString(32)+n,t=":"+t+"R"+n,n=wr++,0<\/script>",e=e.removeChild(e.firstChild)):typeof r.is=="string"?e=l.createElement(n,{is:r.is}):(e=l.createElement(n),n==="select"&&(l=e,r.multiple?l.multiple=!0:r.size&&(l.size=r.size))):e=l.createElementNS(e,n),e[ot]=t,e[yr]=r,Wc(e,t,!1,!1),t.stateNode=e;e:{switch(l=Vs(n,r),n){case"dialog":Z("cancel",e),Z("close",e),a=r;break;case"iframe":case"object":case"embed":Z("load",e),a=r;break;case"video":case"audio":for(a=0;azn&&(t.flags|=128,r=!0,Hn(s,!1),t.lanes=4194304)}else{if(!r)if(e=_a(l),e!==null){if(t.flags|=128,r=!0,n=e.updateQueue,n!==null&&(t.updateQueue=n,t.flags|=4),Hn(s,!0),s.tail===null&&s.tailMode==="hidden"&&!l.alternate&&!te)return Ce(t),null}else 2*fe()-s.renderingStartTime>zn&&n!==1073741824&&(t.flags|=128,r=!0,Hn(s,!1),t.lanes=4194304);s.isBackwards?(l.sibling=t.child,t.child=l):(n=s.last,n!==null?n.sibling=l:t.child=l,s.last=l)}return s.tail!==null?(t=s.tail,s.rendering=t,s.tail=t.sibling,s.renderingStartTime=fe(),t.sibling=null,n=ae.current,J(ae,r?n&1|2:n&1),t):(Ce(t),null);case 22:case 23:return fo(),r=t.memoizedState!==null,e!==null&&e.memoizedState!==null!==r&&(t.flags|=8192),r&&t.mode&1?Oe&1073741824&&(Ce(t),t.subtreeFlags&6&&(t.flags|=8192)):Ce(t),null;case 24:return null;case 25:return null}throw Error(C(156,t.tag))}function E0(e,t){switch(Bl(t),t.tag){case 1:return Le(t.type)&&ba(),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return _n(),ee(Ie),ee(Ae),eo(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 5:return Zl(t),null;case 13:if(ee(ae),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(C(340));En()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return ee(ae),null;case 4:return _n(),null;case 10:return ql(t.type._context),null;case 22:case 23:return fo(),null;case 24:return null;default:return null}}var Kr=!1,Ee=!1,A0=typeof WeakSet=="function"?WeakSet:Set,I=null;function yn(e,t){var n=e.ref;if(n!==null)if(typeof n=="function")try{n(null)}catch(r){ie(e,t,r)}else n.current=null}function gl(e,t,n){try{n()}catch(r){ie(e,t,r)}}var ki=!1;function _0(e,t){if(Js=xa,e=Ku(),Ul(e)){if("selectionStart"in e)var n={start:e.selectionStart,end:e.selectionEnd};else e:{n=(n=e.ownerDocument)&&n.defaultView||window;var r=n.getSelection&&n.getSelection();if(r&&r.rangeCount!==0){n=r.anchorNode;var a=r.anchorOffset,s=r.focusNode;r=r.focusOffset;try{n.nodeType,s.nodeType}catch{n=null;break e}var l=0,i=-1,u=-1,d=0,g=0,h=e,m=null;t:for(;;){for(var v;h!==n||a!==0&&h.nodeType!==3||(i=l+a),h!==s||r!==0&&h.nodeType!==3||(u=l+r),h.nodeType===3&&(l+=h.nodeValue.length),(v=h.firstChild)!==null;)m=h,h=v;for(;;){if(h===e)break t;if(m===n&&++d===a&&(i=l),m===s&&++g===r&&(u=l),(v=h.nextSibling)!==null)break;h=m,m=h.parentNode}h=v}n=i===-1||u===-1?null:{start:i,end:u}}else n=null}n=n||{start:0,end:0}}else n=null;for(Zs={focusedElem:e,selectionRange:n},xa=!1,I=t;I!==null;)if(t=I,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,I=e;else for(;I!==null;){t=I;try{var k=t.alternate;if(t.flags&1024)switch(t.tag){case 0:case 11:case 15:break;case 1:if(k!==null){var x=k.memoizedProps,_=k.memoizedState,f=t.stateNode,c=f.getSnapshotBeforeUpdate(t.elementType===t.type?x:Ze(t.type,x),_);f.__reactInternalSnapshotBeforeUpdate=c}break;case 3:var p=t.stateNode.containerInfo;p.nodeType===1?p.textContent="":p.nodeType===9&&p.documentElement&&p.removeChild(p.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(C(163))}}catch(b){ie(t,t.return,b)}if(e=t.sibling,e!==null){e.return=t.return,I=e;break}I=t.return}return k=ki,ki=!1,k}function ar(e,t,n){var r=t.updateQueue;if(r=r!==null?r.lastEffect:null,r!==null){var a=r=r.next;do{if((a.tag&e)===e){var s=a.destroy;a.destroy=void 0,s!==void 0&&gl(t,n,s)}a=a.next}while(a!==r)}}function Qa(e,t){if(t=t.updateQueue,t=t!==null?t.lastEffect:null,t!==null){var n=t=t.next;do{if((n.tag&e)===e){var r=n.create;n.destroy=r()}n=n.next}while(n!==t)}}function hl(e){var t=e.ref;if(t!==null){var n=e.stateNode;switch(e.tag){case 5:e=n;break;default:e=n}typeof t=="function"?t(e):t.current=e}}function Hc(e){var t=e.alternate;t!==null&&(e.alternate=null,Hc(t)),e.child=null,e.deletions=null,e.sibling=null,e.tag===5&&(t=e.stateNode,t!==null&&(delete t[ot],delete t[yr],delete t[nl],delete t[d0],delete t[f0])),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}function Bc(e){return e.tag===5||e.tag===3||e.tag===4}function bi(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||Bc(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function yl(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.nodeType===8?n.parentNode.insertBefore(e,t):n.insertBefore(e,t):(n.nodeType===8?(t=n.parentNode,t.insertBefore(e,n)):(t=n,t.appendChild(e)),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=ka));else if(r!==4&&(e=e.child,e!==null))for(yl(e,t,n),e=e.sibling;e!==null;)yl(e,t,n),e=e.sibling}function xl(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(r!==4&&(e=e.child,e!==null))for(xl(e,t,n),e=e.sibling;e!==null;)xl(e,t,n),e=e.sibling}var we=null,et=!1;function kt(e,t,n){for(n=n.child;n!==null;)Qc(e,t,n),n=n.sibling}function Qc(e,t,n){if(it&&typeof it.onCommitFiberUnmount=="function")try{it.onCommitFiberUnmount($a,n)}catch{}switch(n.tag){case 5:Ee||yn(n,t);case 6:var r=we,a=et;we=null,kt(e,t,n),we=r,et=a,we!==null&&(et?(e=we,n=n.stateNode,e.nodeType===8?e.parentNode.removeChild(n):e.removeChild(n)):we.removeChild(n.stateNode));break;case 18:we!==null&&(et?(e=we,n=n.stateNode,e.nodeType===8?vs(e.parentNode,n):e.nodeType===1&&vs(e,n),fr(e)):vs(we,n.stateNode));break;case 4:r=we,a=et,we=n.stateNode.containerInfo,et=!0,kt(e,t,n),we=r,et=a;break;case 0:case 11:case 14:case 15:if(!Ee&&(r=n.updateQueue,r!==null&&(r=r.lastEffect,r!==null))){a=r=r.next;do{var s=a,l=s.destroy;s=s.tag,l!==void 0&&(s&2||s&4)&&gl(n,t,l),a=a.next}while(a!==r)}kt(e,t,n);break;case 1:if(!Ee&&(yn(n,t),r=n.stateNode,typeof r.componentWillUnmount=="function"))try{r.props=n.memoizedProps,r.state=n.memoizedState,r.componentWillUnmount()}catch(i){ie(n,t,i)}kt(e,t,n);break;case 21:kt(e,t,n);break;case 22:n.mode&1?(Ee=(r=Ee)||n.memoizedState!==null,kt(e,t,n),Ee=r):kt(e,t,n);break;default:kt(e,t,n)}}function Si(e){var t=e.updateQueue;if(t!==null){e.updateQueue=null;var n=e.stateNode;n===null&&(n=e.stateNode=new A0),t.forEach(function(r){var a=$0.bind(null,e,r);n.has(r)||(n.add(r),r.then(a,a))})}}function Je(e,t){var n=t.deletions;if(n!==null)for(var r=0;ra&&(a=l),r&=~s}if(r=a,r=fe()-r,r=(120>r?120:480>r?480:1080>r?1080:1920>r?1920:3e3>r?3e3:4320>r?4320:1960*z0(r/1960))-r,10e?16:e,Et===null)var r=!1;else{if(e=Et,Et=null,Ra=0,B&6)throw Error(C(331));var a=B;for(B|=4,I=e.current;I!==null;){var s=I,l=s.child;if(I.flags&16){var i=s.deletions;if(i!==null){for(var u=0;ufe()-uo?Kt(e,0):io|=n),$e(e,t)}function ed(e,t){t===0&&(e.mode&1?(t=Or,Or<<=1,!(Or&130023424)&&(Or=4194304)):t=1);var n=Pe();e=xt(e,t),e!==null&&(Er(e,t,n),$e(e,n))}function L0(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),ed(e,n)}function $0(e,t){var n=0;switch(e.tag){case 13:var r=e.stateNode,a=e.memoizedState;a!==null&&(n=a.retryLane);break;case 19:r=e.stateNode;break;default:throw Error(C(314))}r!==null&&r.delete(t),ed(e,n)}var td;td=function(e,t,n){if(e!==null)if(e.memoizedProps!==t.pendingProps||Ie.current)Te=!0;else{if(!(e.lanes&n)&&!(t.flags&128))return Te=!1,j0(e,t,n);Te=!!(e.flags&131072)}else Te=!1,te&&t.flags&1048576&&sc(t,ja,t.index);switch(t.lanes=0,t.tag){case 2:var r=t.type;oa(e,t),e=t.pendingProps;var a=Cn(t,Ae.current);Sn(t,n),a=no(null,t,r,e,a,n);var s=ro();return t.flags|=1,typeof a=="object"&&a!==null&&typeof a.render=="function"&&a.$$typeof===void 0?(t.tag=1,t.memoizedState=null,t.updateQueue=null,Le(r)?(s=!0,Sa(t)):s=!1,t.memoizedState=a.state!==null&&a.state!==void 0?a.state:null,Xl(t),a.updater=Ba,t.stateNode=a,a._reactInternals=t,il(t,r,e,n),t=dl(null,t,r,!0,s,n)):(t.tag=0,te&&s&&Hl(t),_e(null,t,a,n),t=t.child),t;case 16:r=t.elementType;e:{switch(oa(e,t),e=t.pendingProps,a=r._init,r=a(r._payload),t.type=r,a=t.tag=F0(r),e=Ze(r,e),a){case 0:t=cl(null,t,r,e,n);break e;case 1:t=xi(null,t,r,e,n);break e;case 11:t=hi(null,t,r,e,n);break e;case 14:t=yi(null,t,r,Ze(r.type,e),n);break e}throw Error(C(306,r,""))}return t;case 0:return r=t.type,a=t.pendingProps,a=t.elementType===r?a:Ze(r,a),cl(e,t,r,a,n);case 1:return r=t.type,a=t.pendingProps,a=t.elementType===r?a:Ze(r,a),xi(e,t,r,a,n);case 3:e:{if($c(t),e===null)throw Error(C(387));r=t.pendingProps,s=t.memoizedState,a=s.element,dc(e,t),Aa(t,r,null,n);var l=t.memoizedState;if(r=l.element,s.isDehydrated)if(s={element:r,isDehydrated:!1,cache:l.cache,pendingSuspenseBoundaries:l.pendingSuspenseBoundaries,transitions:l.transitions},t.updateQueue.baseState=s,t.memoizedState=s,t.flags&256){a=Pn(Error(C(423)),t),t=vi(e,t,r,n,a);break e}else if(r!==a){a=Pn(Error(C(424)),t),t=vi(e,t,r,n,a);break e}else for(Fe=zt(t.stateNode.containerInfo.firstChild),We=t,te=!0,tt=null,n=uc(t,null,r,n),t.child=n;n;)n.flags=n.flags&-3|4096,n=n.sibling;else{if(En(),r===a){t=vt(e,t,n);break e}_e(e,t,r,n)}t=t.child}return t;case 5:return fc(t),e===null&&sl(t),r=t.type,a=t.pendingProps,s=e!==null?e.memoizedProps:null,l=a.children,el(r,a)?l=null:s!==null&&el(r,s)&&(t.flags|=32),Lc(e,t),_e(e,t,l,n),t.child;case 6:return e===null&&sl(t),null;case 13:return Oc(e,t,n);case 4:return Jl(t,t.stateNode.containerInfo),r=t.pendingProps,e===null?t.child=An(t,null,r,n):_e(e,t,r,n),t.child;case 11:return r=t.type,a=t.pendingProps,a=t.elementType===r?a:Ze(r,a),hi(e,t,r,a,n);case 7:return _e(e,t,t.pendingProps,n),t.child;case 8:return _e(e,t,t.pendingProps.children,n),t.child;case 12:return _e(e,t,t.pendingProps.children,n),t.child;case 10:e:{if(r=t.type._context,a=t.pendingProps,s=t.memoizedProps,l=a.value,J(Ca,r._currentValue),r._currentValue=l,s!==null)if(at(s.value,l)){if(s.children===a.children&&!Ie.current){t=vt(e,t,n);break e}}else for(s=t.child,s!==null&&(s.return=t);s!==null;){var i=s.dependencies;if(i!==null){l=s.child;for(var u=i.firstContext;u!==null;){if(u.context===r){if(s.tag===1){u=gt(-1,n&-n),u.tag=2;var d=s.updateQueue;if(d!==null){d=d.shared;var g=d.pending;g===null?u.next=u:(u.next=g.next,g.next=u),d.pending=u}}s.lanes|=n,u=s.alternate,u!==null&&(u.lanes|=n),ll(s.return,n,t),i.lanes|=n;break}u=u.next}}else if(s.tag===10)l=s.type===t.type?null:s.child;else if(s.tag===18){if(l=s.return,l===null)throw Error(C(341));l.lanes|=n,i=l.alternate,i!==null&&(i.lanes|=n),ll(l,n,t),l=s.sibling}else l=s.child;if(l!==null)l.return=s;else for(l=s;l!==null;){if(l===t){l=null;break}if(s=l.sibling,s!==null){s.return=l.return,l=s;break}l=l.return}s=l}_e(e,t,a.children,n),t=t.child}return t;case 9:return a=t.type,r=t.pendingProps.children,Sn(t,n),a=qe(a),r=r(a),t.flags|=1,_e(e,t,r,n),t.child;case 14:return r=t.type,a=Ze(r,t.pendingProps),a=Ze(r.type,a),yi(e,t,r,a,n);case 15:return Tc(e,t,t.type,t.pendingProps,n);case 17:return r=t.type,a=t.pendingProps,a=t.elementType===r?a:Ze(r,a),oa(e,t),t.tag=1,Le(r)?(e=!0,Sa(t)):e=!1,Sn(t,n),Dc(t,r,a),il(t,r,a,n),dl(null,t,r,!0,e,n);case 19:return Fc(e,t,n);case 22:return Ic(e,t,n)}throw Error(C(156,t.tag))};function nd(e,t){return _u(e,t)}function O0(e,t,n,r){this.tag=e,this.key=n,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function Ge(e,t,n,r){return new O0(e,t,n,r)}function mo(e){return e=e.prototype,!(!e||!e.isReactComponent)}function F0(e){if(typeof e=="function")return mo(e)?1:0;if(e!=null){if(e=e.$$typeof,e===Dl)return 11;if(e===Ml)return 14}return 2}function Tt(e,t){var n=e.alternate;return n===null?(n=Ge(e.tag,t,e.key,e.mode),n.elementType=e.elementType,n.type=e.type,n.stateNode=e.stateNode,n.alternate=e,e.alternate=n):(n.pendingProps=t,n.type=e.type,n.flags=0,n.subtreeFlags=0,n.deletions=null),n.flags=e.flags&14680064,n.childLanes=e.childLanes,n.lanes=e.lanes,n.child=e.child,n.memoizedProps=e.memoizedProps,n.memoizedState=e.memoizedState,n.updateQueue=e.updateQueue,t=e.dependencies,n.dependencies=t===null?null:{lanes:t.lanes,firstContext:t.firstContext},n.sibling=e.sibling,n.index=e.index,n.ref=e.ref,n}function ca(e,t,n,r,a,s){var l=2;if(r=e,typeof e=="function")mo(e)&&(l=1);else if(typeof e=="string")l=5;else e:switch(e){case on:return qt(n.children,a,s,t);case zl:l=8,a|=8;break;case Ds:return e=Ge(12,n,t,a|2),e.elementType=Ds,e.lanes=s,e;case Ms:return e=Ge(13,n,t,a),e.elementType=Ms,e.lanes=s,e;case Rs:return e=Ge(19,n,t,a),e.elementType=Rs,e.lanes=s,e;case fu:return Ka(n,a,s,t);default:if(typeof e=="object"&&e!==null)switch(e.$$typeof){case cu:l=10;break e;case du:l=9;break e;case Dl:l=11;break e;case Ml:l=14;break e;case bt:l=16,r=null;break e}throw Error(C(130,e==null?e:typeof e,""))}return t=Ge(l,n,t,a),t.elementType=e,t.type=r,t.lanes=s,t}function qt(e,t,n,r){return e=Ge(7,e,r,t),e.lanes=n,e}function Ka(e,t,n,r){return e=Ge(22,e,r,t),e.elementType=fu,e.lanes=n,e.stateNode={isHidden:!1},e}function Es(e,t,n){return e=Ge(6,e,null,t),e.lanes=n,e}function As(e,t,n){return t=Ge(4,e.children!==null?e.children:[],e.key,t),t.lanes=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function W0(e,t,n,r,a){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=is(0),this.expirationTimes=is(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=is(0),this.identifierPrefix=r,this.onRecoverableError=a,this.mutableSourceEagerHydrationData=null}function go(e,t,n,r,a,s,l,i,u){return e=new W0(e,t,n,i,u),t===1?(t=1,s===!0&&(t|=8)):t=0,s=Ge(3,null,null,t),e.current=s,s.stateNode=e,s.memoizedState={element:r,isDehydrated:n,cache:null,transitions:null,pendingSuspenseBoundaries:null},Xl(s),e}function V0(e,t,n){var r=3"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(ld)}catch(e){console.error(e)}}ld(),lu.exports=Ue;var G0=lu.exports,od,zi=G0;od=zi.createRoot,zi.hydrateRoot;/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */var K0={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const q0=e=>e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase().trim(),F=(e,t)=>{const n=W.forwardRef(({color:r="currentColor",size:a=24,strokeWidth:s=2,absoluteStrokeWidth:l,className:i="",children:u,...d},g)=>W.createElement("svg",{ref:g,...K0,width:a,height:a,stroke:r,strokeWidth:l?Number(s)*24/Number(a):s,className:["lucide",`lucide-${q0(e)}`,i].join(" "),...d},[...t.map(([h,m])=>W.createElement(h,m)),...Array.isArray(u)?u:[u]]));return n.displayName=`${e}`,n};/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Y0=F("AlertCircle",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["line",{x1:"12",x2:"12",y1:"8",y2:"12",key:"1pkeuh"}],["line",{x1:"12",x2:"12.01",y1:"16",y2:"16",key:"4dfq90"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const X0=F("AlertTriangle",[["path",{d:"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z",key:"c3ski4"}],["path",{d:"M12 9v4",key:"juzpu7"}],["path",{d:"M12 17h.01",key:"p32p05"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const J0=F("ArrowRight",[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"m12 5 7 7-7 7",key:"xquz4c"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Z0=F("BarChart3",[["path",{d:"M3 3v18h18",key:"1s2lah"}],["path",{d:"M18 17V9",key:"2bz60n"}],["path",{d:"M13 17V5",key:"1frdt8"}],["path",{d:"M8 17v-3",key:"17ska0"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const ep=F("BellOff",[["path",{d:"M8.7 3A6 6 0 0 1 18 8a21.3 21.3 0 0 0 .6 5",key:"o7mx20"}],["path",{d:"M17 17H3s3-2 3-9a4.67 4.67 0 0 1 .3-1.7",key:"16f1lm"}],["path",{d:"M10.3 21a1.94 1.94 0 0 0 3.4 0",key:"qgo35s"}],["path",{d:"m2 2 20 20",key:"1ooewy"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const vo=F("Bell",[["path",{d:"M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9",key:"1qo2s2"}],["path",{d:"M10.3 21a1.94 1.94 0 0 0 3.4 0",key:"qgo35s"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const tp=F("BookOpen",[["path",{d:"M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z",key:"vv98re"}],["path",{d:"M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z",key:"1cyq3y"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Nr=F("Bot",[["path",{d:"M12 8V4H8",key:"hb8ula"}],["rect",{width:"16",height:"12",x:"4",y:"8",rx:"2",key:"enze0r"}],["path",{d:"M2 14h2",key:"vft8re"}],["path",{d:"M20 14h2",key:"4cs60a"}],["path",{d:"M15 13v2",key:"1xurst"}],["path",{d:"M9 13v2",key:"rq6x2g"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const id=F("Calendar",[["path",{d:"M8 2v4",key:"1cmpym"}],["path",{d:"M16 2v4",key:"4m81vk"}],["rect",{width:"18",height:"18",x:"3",y:"4",rx:"2",key:"1hopcy"}],["path",{d:"M3 10h18",key:"8toen8"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const np=F("CheckCircle",[["path",{d:"M22 11.08V12a10 10 0 1 1-5.93-9.14",key:"g774vq"}],["path",{d:"m9 11 3 3L22 4",key:"1pflzl"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const rp=F("ChevronDown",[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Di=F("ChevronLeft",[["path",{d:"m15 18-6-6 6-6",key:"1wnfg3"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Mi=F("ChevronRight",[["path",{d:"m9 18 6-6-6-6",key:"mthhwq"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Ri=F("ChevronsLeft",[["path",{d:"m11 17-5-5 5-5",key:"13zhaf"}],["path",{d:"m18 17-5-5 5-5",key:"h8a8et"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Ti=F("ChevronsRight",[["path",{d:"m6 17 5-5-5-5",key:"xnjwq"}],["path",{d:"m13 17 5-5-5-5",key:"17xmmf"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const ap=F("Cloud",[["path",{d:"M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z",key:"p7xjir"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const sp=F("Code",[["polyline",{points:"16 18 22 12 16 6",key:"z7tu5w"}],["polyline",{points:"8 6 2 12 8 18",key:"1eg1df"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const lp=F("Database",[["ellipse",{cx:"12",cy:"5",rx:"9",ry:"3",key:"msslwz"}],["path",{d:"M3 5V19A9 3 0 0 0 21 19V5",key:"1wlel7"}],["path",{d:"M3 12A9 3 0 0 0 21 12",key:"mv7ke4"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const op=F("Download",[["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["polyline",{points:"7 10 12 15 17 10",key:"2ggqvy"}],["line",{x1:"12",x2:"12",y1:"15",y2:"3",key:"1vk2je"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Sl=F("ExternalLink",[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const ip=F("EyeOff",[["path",{d:"M9.88 9.88a3 3 0 1 0 4.24 4.24",key:"1jxqfv"}],["path",{d:"M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68",key:"9wicm4"}],["path",{d:"M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61",key:"1jreej"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22",key:"a6p6uj"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const up=F("Eye",[["path",{d:"M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z",key:"rwhkz3"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const cp=F("FileDown",[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z",key:"1rqfz7"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["path",{d:"M12 18v-6",key:"17g6i2"}],["path",{d:"m9 15 3 3 3-3",key:"1npd3o"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const dp=F("FileUp",[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z",key:"1rqfz7"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["path",{d:"M12 12v6",key:"3ahymv"}],["path",{d:"m15 15-3-3-3 3",key:"15xj92"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const fp=F("Folder",[["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z",key:"1kt360"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const pp=F("Gamepad2",[["line",{x1:"6",x2:"10",y1:"11",y2:"11",key:"1gktln"}],["line",{x1:"8",x2:"8",y1:"9",y2:"13",key:"qnk9ow"}],["line",{x1:"15",x2:"15.01",y1:"12",y2:"12",key:"krot7o"}],["line",{x1:"18",x2:"18.01",y1:"10",y2:"10",key:"1lcuu1"}],["path",{d:"M17.32 5H6.68a4 4 0 0 0-3.978 3.59c-.006.052-.01.101-.017.152C2.604 9.416 2 14.456 2 16a3 3 0 0 0 3 3c1 0 1.5-.5 2-1l1.414-1.414A2 2 0 0 1 9.828 16h4.344a2 2 0 0 1 1.414.586L17 18c.5.5 1 1 2 1a3 3 0 0 0 3-3c0-1.545-.604-6.584-.685-7.258-.007-.05-.011-.1-.017-.151A4 4 0 0 0 17.32 5z",key:"mfqc10"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Ii=F("GitBranch",[["line",{x1:"6",x2:"6",y1:"3",y2:"15",key:"17qcm7"}],["circle",{cx:"18",cy:"6",r:"3",key:"1h7g24"}],["circle",{cx:"6",cy:"18",r:"3",key:"fqmcym"}],["path",{d:"M18 9a9 9 0 0 1-9 9",key:"n2h4wq"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const mp=F("Github",[["path",{d:"M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4",key:"tonef"}],["path",{d:"M9 18c-4.51 2-5-2-7-2",key:"9comsn"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const ud=F("Globe",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20",key:"13o1zl"}],["path",{d:"M2 12h20",key:"9i4pu4"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const gp=F("Info",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 16v-4",key:"1dtifu"}],["path",{d:"M12 8h.01",key:"e9boi3"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const cd=F("Key",[["circle",{cx:"7.5",cy:"15.5",r:"5.5",key:"yqb3hr"}],["path",{d:"m21 2-9.6 9.6",key:"1j0ho8"}],["path",{d:"m15.5 7.5 3 3L22 7l-3-3",key:"1rn1fs"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const hp=F("LogOut",[["path",{d:"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4",key:"1uf3rs"}],["polyline",{points:"16 17 21 12 16 7",key:"1gabdz"}],["line",{x1:"21",x2:"9",y1:"12",y2:"12",key:"1uyos4"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const yp=F("Moon",[["path",{d:"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z",key:"a7tn18"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const xp=F("Package",[["path",{d:"m7.5 4.27 9 5.15",key:"1c824w"}],["path",{d:"M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z",key:"hh9hay"}],["path",{d:"m3.3 7 8.7 5 8.7-5",key:"g66t2b"}],["path",{d:"M12 22V12",key:"d0xqtd"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const vp=F("Palette",[["circle",{cx:"13.5",cy:"6.5",r:".5",fill:"currentColor",key:"1okk4w"}],["circle",{cx:"17.5",cy:"10.5",r:".5",fill:"currentColor",key:"f64h9f"}],["circle",{cx:"8.5",cy:"7.5",r:".5",fill:"currentColor",key:"fotxhn"}],["circle",{cx:"6.5",cy:"12.5",r:".5",fill:"currentColor",key:"qy21gx"}],["path",{d:"M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z",key:"12rzf8"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const wp=F("Pause",[["rect",{width:"4",height:"16",x:"6",y:"4",key:"iffhe4"}],["rect",{width:"4",height:"16",x:"14",y:"4",key:"sjin7j"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const kp=F("Play",[["polygon",{points:"5 3 19 12 5 21 5 3",key:"191637"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Li=F("Plus",[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"M12 5v14",key:"s699le"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const dd=F("RefreshCw",[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const $i=F("Save",[["path",{d:"M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z",key:"1owoqh"}],["polyline",{points:"17 21 17 13 7 13 7 21",key:"1md35c"}],["polyline",{points:"7 3 7 8 15 8",key:"8nz8an"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const wo=F("Search",[["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}],["path",{d:"m21 21-4.3-4.3",key:"1qie3q"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const fd=F("Settings",[["path",{d:"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z",key:"1qme2f"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const bp=F("Shield",[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Sp=F("SlidersHorizontal",[["line",{x1:"21",x2:"14",y1:"4",y2:"4",key:"obuewd"}],["line",{x1:"10",x2:"3",y1:"4",y2:"4",key:"1q6298"}],["line",{x1:"21",x2:"12",y1:"12",y2:"12",key:"1iu8h1"}],["line",{x1:"8",x2:"3",y1:"12",y2:"12",key:"ntss68"}],["line",{x1:"21",x2:"16",y1:"20",y2:"20",key:"14d8ph"}],["line",{x1:"12",x2:"3",y1:"20",y2:"20",key:"m0wm8r"}],["line",{x1:"14",x2:"14",y1:"2",y2:"6",key:"14e1ph"}],["line",{x1:"8",x2:"8",y1:"10",y2:"14",key:"1i6ji0"}],["line",{x1:"16",x2:"16",y1:"18",y2:"22",key:"1lctlv"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Np=F("Smartphone",[["rect",{width:"14",height:"20",x:"5",y:"2",rx:"2",ry:"2",key:"1yt0o3"}],["path",{d:"M12 18h.01",key:"mhygvu"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const ko=F("Star",[["polygon",{points:"12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2",key:"8f66p6"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const jp=F("Sun",[["circle",{cx:"12",cy:"12",r:"4",key:"4exip2"}],["path",{d:"M12 2v2",key:"tus03m"}],["path",{d:"M12 20v2",key:"1lh1kg"}],["path",{d:"m4.93 4.93 1.41 1.41",key:"149t6j"}],["path",{d:"m17.66 17.66 1.41 1.41",key:"ptbguv"}],["path",{d:"M2 12h2",key:"1t8f8n"}],["path",{d:"M20 12h2",key:"1q8mjw"}],["path",{d:"m6.34 17.66-1.41 1.41",key:"1m8zz5"}],["path",{d:"m19.07 4.93-1.41 1.41",key:"1shlcs"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Cp=F("Tag",[["path",{d:"M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z",key:"vktsd0"}],["circle",{cx:"7.5",cy:"7.5",r:".5",fill:"currentColor",key:"kqv944"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Oi=F("TestTube",[["path",{d:"M14.5 2v17.5c0 1.4-1.1 2.5-2.5 2.5h0c-1.4 0-2.5-1.1-2.5-2.5V2",key:"187lwq"}],["path",{d:"M8.5 2h7",key:"csnxdl"}],["path",{d:"M14.5 16h-5",key:"1ox875"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Fi=F("Trash2",[["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6",key:"4alrt4"}],["path",{d:"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2",key:"v07s0e"}],["line",{x1:"10",x2:"10",y1:"11",y2:"17",key:"1uufr5"}],["line",{x1:"14",x2:"14",y1:"11",y2:"17",key:"xtxkd"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Ep=F("Upload",[["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["polyline",{points:"17 8 12 3 7 8",key:"t8dd8p"}],["line",{x1:"12",x2:"12",y1:"3",y2:"15",key:"widbto"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Ap=F("Users",[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",key:"1yyitq"}],["circle",{cx:"9",cy:"7",r:"4",key:"nufk8"}],["path",{d:"M22 21v-2a4 4 0 0 0-3-3.87",key:"kshegd"}],["path",{d:"M16 3.13a4 4 0 0 1 0 7.75",key:"1da9ce"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const _p=F("Wrench",[["path",{d:"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z",key:"cbrjhi"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Yt=F("X",[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]]);/** + * @license lucide-react v0.344.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Pp=F("Zap",[["polygon",{points:"13 2 3 14 12 14 11 22 21 10 12 10 13 2",key:"45s27k"}]]),zp={BASE_URL:"/",DEV:!1,MODE:"production",PROD:!0,SSR:!1},Wi=e=>{let t;const n=new Set,r=(g,h)=>{const m=typeof g=="function"?g(t):g;if(!Object.is(m,t)){const v=t;t=h??(typeof m!="object"||m===null)?m:Object.assign({},t,m),n.forEach(k=>k(t,v))}},a=()=>t,u={setState:r,getState:a,getInitialState:()=>d,subscribe:g=>(n.add(g),()=>n.delete(g)),destroy:()=>{(zp?"production":void 0)!=="production"&&console.warn("[DEPRECATED] The `destroy` method will be unsupported in a future version. Instead use unsubscribe function returned by subscribe. Everything will be garbage-collected if store is garbage-collected."),n.clear()}},d=t=e(r,a,u);return u},Dp=e=>e?Wi(e):Wi;var pd={exports:{}},md={},gd={exports:{}},hd={};/** + * @license React + * use-sync-external-store-shim.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 Dn=W;function Mp(e,t){return e===t&&(e!==0||1/e===1/t)||e!==e&&t!==t}var Rp=typeof Object.is=="function"?Object.is:Mp,Tp=Dn.useState,Ip=Dn.useEffect,Lp=Dn.useLayoutEffect,$p=Dn.useDebugValue;function Op(e,t){var n=t(),r=Tp({inst:{value:n,getSnapshot:t}}),a=r[0].inst,s=r[1];return Lp(function(){a.value=n,a.getSnapshot=t,_s(a)&&s({inst:a})},[e,n,t]),Ip(function(){return _s(a)&&s({inst:a}),e(function(){_s(a)&&s({inst:a})})},[e]),$p(n),n}function _s(e){var t=e.getSnapshot;e=e.value;try{var n=t();return!Rp(e,n)}catch{return!0}}function Fp(e,t){return t()}var Wp=typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"?Fp:Op;hd.useSyncExternalStore=Dn.useSyncExternalStore!==void 0?Dn.useSyncExternalStore:Wp;gd.exports=hd;var Vp=gd.exports;/** + * @license React + * use-sync-external-store-shim/with-selector.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 Za=W,Up=Vp;function Hp(e,t){return e===t&&(e!==0||1/e===1/t)||e!==e&&t!==t}var Bp=typeof Object.is=="function"?Object.is:Hp,Qp=Up.useSyncExternalStore,Gp=Za.useRef,Kp=Za.useEffect,qp=Za.useMemo,Yp=Za.useDebugValue;md.useSyncExternalStoreWithSelector=function(e,t,n,r,a){var s=Gp(null);if(s.current===null){var l={hasValue:!1,value:null};s.current=l}else l=s.current;s=qp(function(){function u(v){if(!d){if(d=!0,g=v,v=r(v),a!==void 0&&l.hasValue){var k=l.value;if(a(k,v))return h=k}return h=v}if(k=h,Bp(g,v))return k;var x=r(v);return a!==void 0&&a(k,x)?(g=v,k):(g=v,h=x)}var d=!1,g,h,m=n===void 0?null:n;return[function(){return u(t())},m===null?void 0:function(){return u(m())}]},[t,n,r,a]);var i=Qp(e,s[0],s[1]);return Kp(function(){l.hasValue=!0,l.value=i},[i]),Yp(i),i};pd.exports=md;var Xp=pd.exports;const Jp=Ki(Xp),yd={BASE_URL:"/",DEV:!1,MODE:"production",PROD:!0,SSR:!1},{useDebugValue:Zp}=Td,{useSyncExternalStoreWithSelector:em}=Jp;let Vi=!1;const tm=e=>e;function nm(e,t=tm,n){(yd?"production":void 0)!=="production"&&n&&!Vi&&(console.warn("[DEPRECATED] Use `createWithEqualityFn` instead of `create` or use `useStoreWithEqualityFn` instead of `useStore`. They can be imported from 'zustand/traditional'. https://github.com/pmndrs/zustand/discussions/1937"),Vi=!0);const r=em(e.subscribe,e.getState,e.getServerState||e.getInitialState,t,n);return Zp(r),r}const rm=e=>{(yd?"production":void 0)!=="production"&&typeof e!="function"&&console.warn("[DEPRECATED] Passing a vanilla store will be unsupported in a future version. Instead use `import { useStore } from 'zustand'`.");const t=typeof e=="function"?Dp(e):e,n=(r,a)=>nm(t,r,a);return Object.assign(n,t),n},am=e=>rm,sm={BASE_URL:"/",DEV:!1,MODE:"production",PROD:!0,SSR:!1};function lm(e,t){let n;try{n=e()}catch{return}return{getItem:a=>{var s;const l=u=>u===null?null:JSON.parse(u,void 0),i=(s=n.getItem(a))!=null?s:null;return i instanceof Promise?i.then(l):l(i)},setItem:(a,s)=>n.setItem(a,JSON.stringify(s,void 0)),removeItem:a=>n.removeItem(a)}}const jr=e=>t=>{try{const n=e(t);return n instanceof Promise?n:{then(r){return jr(r)(n)},catch(r){return this}}}catch(n){return{then(r){return this},catch(r){return jr(r)(n)}}}},om=(e,t)=>(n,r,a)=>{let s={getStorage:()=>localStorage,serialize:JSON.stringify,deserialize:JSON.parse,partialize:_=>_,version:0,merge:(_,f)=>({...f,..._}),...t},l=!1;const i=new Set,u=new Set;let d;try{d=s.getStorage()}catch{}if(!d)return e((..._)=>{console.warn(`[zustand persist middleware] Unable to update item '${s.name}', the given storage is currently unavailable.`),n(..._)},r,a);const g=jr(s.serialize),h=()=>{const _=s.partialize({...r()});let f;const c=g({state:_,version:s.version}).then(p=>d.setItem(s.name,p)).catch(p=>{f=p});if(f)throw f;return c},m=a.setState;a.setState=(_,f)=>{m(_,f),h()};const v=e((..._)=>{n(..._),h()},r,a);let k;const x=()=>{var _;if(!d)return;l=!1,i.forEach(c=>c(r()));const f=((_=s.onRehydrateStorage)==null?void 0:_.call(s,r()))||void 0;return jr(d.getItem.bind(d))(s.name).then(c=>{if(c)return s.deserialize(c)}).then(c=>{if(c)if(typeof c.version=="number"&&c.version!==s.version){if(s.migrate)return s.migrate(c.state,c.version);console.error("State loaded from storage couldn't be migrated since no migrate function was provided")}else return c.state}).then(c=>{var p;return k=s.merge(c,(p=r())!=null?p:v),n(k,!0),h()}).then(()=>{f==null||f(k,void 0),l=!0,u.forEach(c=>c(k))}).catch(c=>{f==null||f(void 0,c)})};return a.persist={setOptions:_=>{s={...s,..._},_.getStorage&&(d=_.getStorage())},clearStorage:()=>{d==null||d.removeItem(s.name)},getOptions:()=>s,rehydrate:()=>x(),hasHydrated:()=>l,onHydrate:_=>(i.add(_),()=>{i.delete(_)}),onFinishHydration:_=>(u.add(_),()=>{u.delete(_)})},x(),k||v},im=(e,t)=>(n,r,a)=>{let s={storage:lm(()=>localStorage),partialize:x=>x,version:0,merge:(x,_)=>({..._,...x}),...t},l=!1;const i=new Set,u=new Set;let d=s.storage;if(!d)return e((...x)=>{console.warn(`[zustand persist middleware] Unable to update item '${s.name}', the given storage is currently unavailable.`),n(...x)},r,a);const g=()=>{const x=s.partialize({...r()});return d.setItem(s.name,{state:x,version:s.version})},h=a.setState;a.setState=(x,_)=>{h(x,_),g()};const m=e((...x)=>{n(...x),g()},r,a);a.getInitialState=()=>m;let v;const k=()=>{var x,_;if(!d)return;l=!1,i.forEach(c=>{var p;return c((p=r())!=null?p:m)});const f=((_=s.onRehydrateStorage)==null?void 0:_.call(s,(x=r())!=null?x:m))||void 0;return jr(d.getItem.bind(d))(s.name).then(c=>{if(c)if(typeof c.version=="number"&&c.version!==s.version){if(s.migrate)return[!0,s.migrate(c.state,c.version)];console.error("State loaded from storage couldn't be migrated since no migrate function was provided")}else return[!1,c.state];return[!1,void 0]}).then(c=>{var p;const[b,P]=c;if(v=s.merge(P,(p=r())!=null?p:m),n(v,!0),b)return g()}).then(()=>{f==null||f(v,void 0),v=r(),l=!0,u.forEach(c=>c(v))}).catch(c=>{f==null||f(void 0,c)})};return a.persist={setOptions:x=>{s={...s,...x},x.storage&&(d=x.storage)},clearStorage:()=>{d==null||d.removeItem(s.name)},getOptions:()=>s,rehydrate:()=>k(),hasHydrated:()=>l,onHydrate:x=>(i.add(x),()=>{i.delete(x)}),onFinishHydration:x=>(u.add(x),()=>{u.delete(x)})},s.skipHydration||k(),v||m},um=(e,t)=>"getStorage"in t||"serialize"in t||"deserialize"in t?((sm?"production":void 0)!=="production"&&console.warn("[DEPRECATED] `getStorage`, `serialize` and `deserialize` options are deprecated. Use `storage` option instead."),om(e,t)):im(e,t),cm=um,Ui={query:"",tags:[],languages:[],platforms:[],sortBy:"stars",sortOrder:"desc",isAnalyzed:void 0,isSubscribed:void 0},Wt=am()(cm((e,t)=>({user:null,githubToken:null,isAuthenticated:!1,repositories:[],isLoading:!1,lastSync:null,aiConfigs:[],activeAIConfig:null,webdavConfigs:[],activeWebDAVConfig:null,lastBackup:null,searchFilters:Ui,searchResults:[],releases:[],releaseSubscriptions:new Set,theme:"light",currentView:"repositories",language:"zh",setUser:n=>{console.log("Setting user:",n),e({user:n,isAuthenticated:!!n})},setGitHubToken:n=>{console.log("Setting GitHub token:",!!n),e({githubToken:n})},logout:()=>e({user:null,githubToken:null,isAuthenticated:!1,repositories:[],releases:[],releaseSubscriptions:new Set,searchResults:[],lastSync:null}),setRepositories:n=>e({repositories:n,searchResults:n}),updateRepository:n=>e(r=>({repositories:r.repositories.map(s=>s.id===n.id?n:s),searchResults:r.searchResults.map(s=>s.id===n.id?n:s)})),setLoading:n=>e({isLoading:n}),setLastSync:n=>e({lastSync:n}),addAIConfig:n=>e(r=>({aiConfigs:[...r.aiConfigs,n]})),updateAIConfig:(n,r)=>e(a=>({aiConfigs:a.aiConfigs.map(s=>s.id===n?{...s,...r}:s)})),deleteAIConfig:n=>e(r=>({aiConfigs:r.aiConfigs.filter(a=>a.id!==n),activeAIConfig:r.activeAIConfig===n?null:r.activeAIConfig})),setActiveAIConfig:n=>e({activeAIConfig:n}),addWebDAVConfig:n=>e(r=>({webdavConfigs:[...r.webdavConfigs,n]})),updateWebDAVConfig:(n,r)=>e(a=>({webdavConfigs:a.webdavConfigs.map(s=>s.id===n?{...s,...r}:s)})),deleteWebDAVConfig:n=>e(r=>({webdavConfigs:r.webdavConfigs.filter(a=>a.id!==n),activeWebDAVConfig:r.activeWebDAVConfig===n?null:r.activeWebDAVConfig})),setActiveWebDAVConfig:n=>e({activeWebDAVConfig:n}),setLastBackup:n=>e({lastBackup:n}),setSearchFilters:n=>e(r=>({searchFilters:{...r.searchFilters,...n}})),setSearchResults:n=>e({searchResults:n}),setReleases:n=>e({releases:n}),addReleases:n=>e(r=>{const a=new Set(r.releases.map(l=>l.id)),s=n.filter(l=>!a.has(l.id));return{releases:[...r.releases,...s]}}),toggleReleaseSubscription:n=>e(r=>{const a=new Set(r.releaseSubscriptions);return a.has(n)?a.delete(n):a.add(n),{releaseSubscriptions:a}}),setTheme:n=>e({theme:n}),setCurrentView:n=>e({currentView:n}),setLanguage:n=>e({language:n})}),{name:"github-stars-manager",partialize:e=>({user:e.user,githubToken:e.githubToken,isAuthenticated:e.isAuthenticated,repositories:e.repositories,lastSync:e.lastSync,aiConfigs:e.aiConfigs,activeAIConfig:e.activeAIConfig,webdavConfigs:e.webdavConfigs,activeWebDAVConfig:e.activeWebDAVConfig,lastBackup:e.lastBackup,releaseSubscriptions:Array.from(e.releaseSubscriptions),releases:e.releases,theme:e.theme,language:e.language}),onRehydrateStorage:()=>e=>{var t,n;e&&(Array.isArray(e.releaseSubscriptions)?e.releaseSubscriptions=new Set(e.releaseSubscriptions):e.releaseSubscriptions=new Set,e.isAuthenticated=!!(e.user&&e.githubToken),e.searchResults=e.repositories||[],e.searchFilters=Ui,e.language||(e.language="zh"),e.webdavConfigs||(e.webdavConfigs=[]),console.log("Store rehydrated:",{isAuthenticated:e.isAuthenticated,repositoriesCount:((t=e.repositories)==null?void 0:t.length)||0,lastSync:e.lastSync,language:e.language,webdavConfigsCount:((n=e.webdavConfigs)==null?void 0:n.length)||0}))}})),dm="https://api.github.com";class zr{constructor(t){this.token=t}async makeRequest(t,n={}){const r=await fetch(`${dm}${t}`,{...n,headers:{Authorization:`Bearer ${this.token}`,Accept:"application/vnd.github.v3+json","X-GitHub-Api-Version":"2022-11-28",...n.headers}});if(!r.ok)throw r.status===401?new Error("GitHub token expired or invalid"):new Error(`GitHub API error: ${r.status} ${r.statusText}`);return r.json()}async getCurrentUser(){return this.makeRequest("/user")}async getStarredRepositories(t=1,n=100){return await this.makeRequest(`/user/starred?page=${t}&per_page=${n}&sort=updated`)}async getAllStarredRepositories(){let t=[],n=1;const r=100;for(;;){const a=await this.getStarredRepositories(n,r);if(a.length===0||(t=[...t,...a],a.lengthsetTimeout(s,100))}return t}async getRepositoryReadme(t,n){try{const r=await this.makeRequest(`/repos/${t}/${n}/readme`);return r.encoding==="base64"?atob(r.content):r.content}catch(r){return console.warn(`Failed to fetch README for ${t}/${n}:`,r),""}}async getRepositoryReleases(t,n,r=1,a=30){try{return(await this.makeRequest(`/repos/${t}/${n}/releases?page=${r}&per_page=${a}`)).map(l=>({id:l.id,tag_name:l.tag_name,name:l.name||l.tag_name,body:l.body||"",published_at:l.published_at,html_url:l.html_url,repository:{id:0,full_name:`${t}/${n}`,name:n}}))}catch(s){return console.warn(`Failed to fetch releases for ${t}/${n}:`,s),[]}}async getMultipleRepositoryReleases(t){const n=[];for(const r of t){const[a,s]=r.full_name.split("/"),l=await this.getRepositoryReleases(a,s,1,5);l.forEach(i=>{i.repository.id=r.id}),n.push(...l),await new Promise(i=>setTimeout(i,150))}return n.sort((r,a)=>new Date(a.published_at).getTime()-new Date(r.published_at).getTime())}async getIncrementalRepositoryReleases(t,n,r,a=10){try{let s=`/repos/${t}/${n}/releases?per_page=${a}`;const i=(await this.makeRequest(s)).map(u=>({id:u.id,tag_name:u.tag_name,name:u.name||u.tag_name,body:u.body||"",published_at:u.published_at,html_url:u.html_url,repository:{id:0,full_name:`${t}/${n}`,name:n}}));if(r){const u=new Date(r);return i.filter(d=>new Date(d.published_at)>u)}return i}catch(s){return console.warn(`Failed to fetch incremental releases for ${t}/${n}:`,s),[]}}async checkRateLimit(){const t=await this.makeRequest("/rate_limit");return{remaining:t.rate.remaining,reset:t.rate.reset}}}const fm=()=>{const[e,t]=W.useState(""),[n,r]=W.useState(!1),[a,s]=W.useState(""),{setUser:l,setGitHubToken:i,repositories:u,lastSync:d}=Wt(),g=async()=>{if(!e.trim()){s("Please enter a valid GitHub token");return}r(!0),s("");try{const v=await new zr(e).getCurrentUser();i(e),l(v),console.log("Successfully authenticated user:",v)}catch(m){console.error("Authentication failed:",m),s(m instanceof Error?m.message:"Failed to authenticate. Please check your token.")}finally{r(!1)}},h=m=>{m.key==="Enter"&&!n&&g()};return o.jsx("div",{className:"min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100 flex items-center justify-center p-4",children:o.jsxs("div",{className:"max-w-md w-full",children:[o.jsxs("div",{className:"text-center mb-8",children:[o.jsx("div",{className:"flex items-center justify-center w-16 h-16 bg-blue-600 rounded-2xl mx-auto mb-4 shadow-lg",children:o.jsx(ko,{className:"w-8 h-8 text-white"})}),o.jsx("h1",{className:"text-3xl font-bold text-gray-900 mb-2",children:"GitHub Stars Manager"}),o.jsx("p",{className:"text-gray-600 text-lg",children:"AI-powered repository management"})]}),o.jsxs("div",{className:"bg-white rounded-2xl shadow-xl border border-gray-200 p-8",children:[o.jsxs("div",{className:"text-center mb-6",children:[o.jsx(mp,{className:"w-10 h-10 text-gray-700 mx-auto mb-3"}),o.jsx("h2",{className:"text-xl font-semibold text-gray-900 mb-2",children:"Connect with GitHub"}),o.jsx("p",{className:"text-gray-600 text-sm",children:"Enter your GitHub personal access token to get started"})]}),u.length>0&&d&&o.jsxs("div",{className:"mb-4 p-3 bg-green-50 border border-green-200 rounded-lg",children:[o.jsxs("div",{className:"flex items-center space-x-2 text-green-700",children:[o.jsx("div",{className:"w-2 h-2 bg-green-500 rounded-full"}),o.jsxs("span",{className:"text-sm font-medium",children:["已缓存 ",u.length," 个仓库"]})]}),o.jsxs("p",{className:"text-xs text-green-600 mt-1",children:["上次同步: ",new Date(d).toLocaleString()]})]}),o.jsxs("div",{className:"space-y-4",children:[o.jsxs("div",{children:[o.jsx("label",{className:"block text-sm font-medium text-gray-700 mb-2",children:"GitHub Personal Access Token"}),o.jsxs("div",{className:"relative",children:[o.jsx(cd,{className:"absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-5 h-5"}),o.jsx("input",{type:"password",placeholder:"ghp_xxxxxxxxxxxxxxxxxxxx",value:e,onChange:m=>{t(m.target.value),s("")},onKeyPress:h,disabled:n,className:"w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-white text-gray-900 disabled:bg-gray-50 disabled:text-gray-500"})]})]}),a&&o.jsxs("div",{className:"flex items-center space-x-2 p-3 bg-red-50 border border-red-200 rounded-lg",children:[o.jsx(Y0,{className:"w-5 h-5 text-red-500 flex-shrink-0"}),o.jsx("p",{className:"text-sm text-red-700",children:a})]}),o.jsx("button",{onClick:g,disabled:n||!e.trim(),className:"w-full flex items-center justify-center space-x-2 px-6 py-3 bg-blue-600 hover:bg-blue-700 disabled:bg-gray-400 disabled:cursor-not-allowed text-white rounded-lg font-medium transition-colors",children:n?o.jsxs(o.Fragment,{children:[o.jsx("div",{className:"w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin"}),o.jsx("span",{children:"Connecting..."})]}):o.jsxs(o.Fragment,{children:[o.jsx("span",{children:"Connect to GitHub"}),o.jsx(J0,{className:"w-5 h-5"})]})})]}),o.jsxs("div",{className:"mt-6 p-4 bg-gray-50 rounded-lg",children:[o.jsx("h3",{className:"font-medium text-gray-900 mb-2 text-sm",children:"How to create a GitHub token:"}),o.jsxs("ol",{className:"text-xs text-gray-600 space-y-1",children:[o.jsx("li",{children:"1. Go to GitHub Settings → Developer settings → Personal access tokens"}),o.jsx("li",{children:'2. Click "Generate new token (classic)"'}),o.jsxs("li",{children:["3. Select scopes: ",o.jsx("strong",{children:"repo"})," and ",o.jsx("strong",{children:"user"})]}),o.jsx("li",{children:"4. Copy the generated token and paste it above"})]}),o.jsx("div",{className:"mt-3",children:o.jsx("a",{href:"https://github.com/settings/tokens",target:"_blank",rel:"noopener noreferrer",className:"text-blue-600 hover:text-blue-700 text-sm font-medium hover:underline",children:"Create token on GitHub →"})})]})]})]})})},pm=()=>{const{user:e,theme:t,currentView:n,isLoading:r,lastSync:a,githubToken:s,repositories:l,setTheme:i,setCurrentView:u,setRepositories:d,setReleases:g,setLoading:h,setLastSync:m,logout:v}=Wt(),k=async()=>{if(!s){alert("GitHub token not found. Please login again.");return}h(!0);try{const _=new zr(s);console.log("Fetching starred repositories...");const f=await _.getAllStarredRepositories(),c=new Map(l.map(j=>[j.id,j])),p=f.map(j=>{const N=c.get(j.id);return N?{...j,ai_summary:N.ai_summary,ai_tags:N.ai_tags,ai_platforms:N.ai_platforms,analyzed_at:N.analyzed_at}:j});d(p),console.log("Fetching releases...");const b=await _.getMultipleRepositoryReleases(p.slice(0,20));g(b),m(new Date().toISOString()),console.log("Sync completed successfully");const P=f.length-l.length;P>0?alert(`同步完成!发现 ${P} 个新仓库。`):alert("同步完成!所有仓库都是最新的。")}catch(_){console.error("Sync failed:",_),_ instanceof Error&&_.message.includes("token")?(alert("GitHub token 已过期或无效,请重新登录。"),v()):alert("同步失败,请检查网络连接。")}finally{h(!1)}},x=_=>{if(!_)return"Never";const f=new Date(_),p=new Date().getTime()-f.getTime(),b=Math.floor(p/(1e3*60*60));return b<1?"Just now":b<24?`${b}h ago`:f.toLocaleDateString()};return o.jsx("header",{className:"bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 sticky top-0 z-50",children:o.jsx("div",{className:"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8",children:o.jsxs("div",{className:"flex items-center justify-between h-16",children:[o.jsxs("div",{className:"flex items-center space-x-3",children:[o.jsx("div",{className:"flex items-center justify-center w-10 h-10 bg-blue-600 rounded-lg",children:o.jsx(ko,{className:"w-6 h-6 text-white"})}),o.jsxs("div",{children:[o.jsx("h1",{className:"text-xl font-bold text-gray-900 dark:text-white",children:"GitHub Stars Manager"}),o.jsx("p",{className:"text-sm text-gray-500 dark:text-gray-400",children:"AI-powered repository management"})]})]}),o.jsxs("nav",{className:"hidden md:flex items-center space-x-1",children:[o.jsxs("button",{onClick:()=>u("repositories"),className:`px-4 py-2 rounded-lg font-medium transition-colors ${n==="repositories"?"bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300":"text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"}`,children:[o.jsx(wo,{className:"w-4 h-4 inline mr-2"}),"Repositories (",l.length,")"]}),o.jsxs("button",{onClick:()=>u("releases"),className:`px-4 py-2 rounded-lg font-medium transition-colors ${n==="releases"?"bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300":"text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"}`,children:[o.jsx(id,{className:"w-4 h-4 inline mr-2"}),"Releases"]}),o.jsxs("button",{onClick:()=>u("settings"),className:`px-4 py-2 rounded-lg font-medium transition-colors ${n==="settings"?"bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300":"text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"}`,children:[o.jsx(fd,{className:"w-4 h-4 inline mr-2"}),"Settings"]})]}),o.jsxs("div",{className:"flex items-center space-x-3",children:[o.jsxs("div",{className:"hidden sm:flex items-center space-x-2 text-sm text-gray-500 dark:text-gray-400",children:[o.jsxs("span",{children:["Last sync: ",x(a)]}),o.jsx("button",{onClick:k,disabled:r,className:"p-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors disabled:opacity-50",title:"Sync repositories",children:o.jsx(dd,{className:`w-4 h-4 ${r?"animate-spin":""}`})})]}),o.jsx("button",{onClick:()=>i(t==="light"?"dark":"light"),className:"p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors",title:"Toggle theme",children:t==="light"?o.jsx(yp,{className:"w-5 h-5 text-gray-700 dark:text-gray-300"}):o.jsx(jp,{className:"w-5 h-5 text-gray-700 dark:text-gray-300"})}),e&&o.jsxs("div",{className:"flex items-center space-x-3",children:[o.jsx("img",{src:e.avatar_url,alt:e.name||e.login,className:"w-8 h-8 rounded-full"}),o.jsx("div",{className:"hidden sm:block",children:o.jsx("p",{className:"text-sm font-medium text-gray-900 dark:text-white",children:e.name||e.login})}),o.jsx("button",{onClick:v,className:"p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors",title:"Logout",children:o.jsx(hp,{className:"w-4 h-4 text-gray-700 dark:text-gray-300"})})]})]})]})})})};class es{constructor(t,n="zh"){this.config=t,this.language=n}async analyzeRepository(t,n){var a,s;const r=this.createAnalysisPrompt(t,n);try{const l=await fetch(`${this.config.baseUrl}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.config.apiKey}`},body:JSON.stringify({model:this.config.model,messages:[{role:"system",content:this.language==="zh"?"你是一个专业的GitHub仓库分析助手。请用中文简洁地分析仓库,提供实用的概述、分类标签和支持的平台类型。":"You are a professional GitHub repository analysis assistant. Please analyze repositories concisely in English, providing practical overviews, category tags, and supported platform types."},{role:"user",content:r}],temperature:.3,max_tokens:400})});if(!l.ok)throw new Error(`AI API error: ${l.status} ${l.statusText}`);const u=(s=(a=(await l.json()).choices[0])==null?void 0:a.message)==null?void 0:s.content;if(!u)throw new Error("No content received from AI service");return this.parseAIResponse(u)}catch(l){return console.error("AI analysis failed:",l),this.fallbackAnalysis(t)}}createAnalysisPrompt(t,n){var a;const r=` +${this.language==="zh"?"仓库名称":"Repository Name"}: ${t.full_name} +${this.language==="zh"?"描述":"Description"}: ${t.description||(this.language==="zh"?"无描述":"No description")} +${this.language==="zh"?"编程语言":"Programming Language"}: ${t.language||(this.language==="zh"?"未知":"Unknown")} +${this.language==="zh"?"Star数":"Stars"}: ${t.stargazers_count} +${this.language==="zh"?"主题标签":"Topics"}: ${((a=t.topics)==null?void 0:a.join(", "))||(this.language==="zh"?"无":"None")} + +${this.language==="zh"?"README内容 (前2000字符)":"README Content (first 2000 characters)"}: +${n.substring(0,2e3)} + `.trim();return this.language==="zh"?` +请分析这个GitHub仓库并提供: + +1. 一个简洁的中文概述(不超过50字),说明这个仓库的主要功能和用途 +2. 3-5个相关的应用类型标签(用中文,类似应用商店的分类,如:开发工具、Web应用、移动应用、数据库、AI工具等) +3. 支持的平台类型(从以下选择:mac、windows、linux、ios、android、docker、web、cli) + +请以JSON格式回复: +{ + "summary": "你的中文概述", + "tags": ["标签1", "标签2", "标签3", "标签4", "标签5"], + "platforms": ["platform1", "platform2", "platform3"] +} + +仓库信息: +${r} + +重点关注实用性和准确的分类,帮助用户快速理解仓库的用途和支持的平台。 + `.trim():` +Please analyze this GitHub repository and provide: + +1. A concise English overview (no more than 50 words) explaining the main functionality and purpose of this repository +2. 3-5 relevant application type tags (in English, similar to app store categories, such as: development tools, web apps, mobile apps, database, AI tools, etc.) +3. Supported platform types (choose from: mac, windows, linux, ios, android, docker, web, cli) + +Please reply in JSON format: +{ + "summary": "Your English overview", + "tags": ["tag1", "tag2", "tag3", "tag4", "tag5"], + "platforms": ["platform1", "platform2", "platform3"] +} + +Repository information: +${r} + +Focus on practicality and accurate categorization to help users quickly understand the repository's purpose and supported platforms. + `.trim()}parseAIResponse(t){try{const n=t.match(/\{[\s\S]*\}/);if(n){const r=JSON.parse(n[0]);return{summary:r.summary||(this.language==="zh"?"无法生成概述":"Unable to generate summary"),tags:Array.isArray(r.tags)?r.tags.slice(0,5):[],platforms:Array.isArray(r.platforms)?r.platforms.slice(0,8):[]}}return{summary:t.substring(0,50)+"...",tags:[],platforms:[]}}catch(n){return console.error("Failed to parse AI response:",n),{summary:this.language==="zh"?"分析失败":"Analysis failed",tags:[],platforms:[]}}}fallbackAnalysis(t){const n=t.description?`${t.description}(${t.language||(this.language==="zh"?"未知语言":"Unknown language")}${this.language==="zh"?"项目":" project"})`:this.language==="zh"?`一个${t.language||"软件"}项目,拥有${t.stargazers_count}个星标`:`A ${t.language||"software"} project with ${t.stargazers_count} stars`,r=[],a=[];if(t.language){const g=(this.language==="zh"?{JavaScript:{tag:"Web应用",platforms:["web","cli"]},TypeScript:{tag:"Web应用",platforms:["web","cli"]},Python:{tag:"Python工具",platforms:["linux","mac","windows","cli"]},Java:{tag:"Java应用",platforms:["linux","mac","windows"]},Go:{tag:"系统工具",platforms:["linux","mac","windows","cli"]},Rust:{tag:"系统工具",platforms:["linux","mac","windows","cli"]},"C++":{tag:"系统软件",platforms:["linux","mac","windows"]},C:{tag:"系统软件",platforms:["linux","mac","windows"]},Swift:{tag:"移动应用",platforms:["ios","mac"]},Kotlin:{tag:"移动应用",platforms:["android"]},Dart:{tag:"移动应用",platforms:["ios","android"]},PHP:{tag:"Web应用",platforms:["web","linux"]},Ruby:{tag:"Web应用",platforms:["web","linux","mac"]},Shell:{tag:"脚本工具",platforms:["linux","mac","cli"]}}:{JavaScript:{tag:"Web App",platforms:["web","cli"]},TypeScript:{tag:"Web App",platforms:["web","cli"]},Python:{tag:"Python Tool",platforms:["linux","mac","windows","cli"]},Java:{tag:"Java App",platforms:["linux","mac","windows"]},Go:{tag:"System Tool",platforms:["linux","mac","windows","cli"]},Rust:{tag:"System Tool",platforms:["linux","mac","windows","cli"]},"C++":{tag:"System Software",platforms:["linux","mac","windows"]},C:{tag:"System Software",platforms:["linux","mac","windows"]},Swift:{tag:"Mobile App",platforms:["ios","mac"]},Kotlin:{tag:"Mobile App",platforms:["android"]},Dart:{tag:"Mobile App",platforms:["ios","android"]},PHP:{tag:"Web App",platforms:["web","linux"]},Ruby:{tag:"Web App",platforms:["web","linux","mac"]},Shell:{tag:"Script Tool",platforms:["linux","mac","cli"]}})[t.language];g&&(r.push(g.tag),a.push(...g.platforms))}const s=(t.description||"").toLowerCase(),l=t.name.toLowerCase(),i=`${s} ${l}`,u=this.language==="zh"?{web:{keywords:["web","frontend","website"],tag:"Web应用",platforms:["web"]},api:{keywords:["api","backend","server"],tag:"后端服务",platforms:["linux","docker"]},cli:{keywords:["cli","command","tool"],tag:"命令行工具",platforms:["cli","linux","mac","windows"]},library:{keywords:["library","framework","sdk"],tag:"开发库",platforms:[]},mobile:{keywords:["mobile","android","ios"],tag:"移动应用",platforms:[]},game:{keywords:["game","gaming"],tag:"游戏",platforms:["windows","mac","linux"]},ai:{keywords:["ai","ml","machine learning"],tag:"AI工具",platforms:["linux","mac","windows"]},database:{keywords:["database","db","storage"],tag:"数据库",platforms:["linux","docker"]},docker:{keywords:["docker","container"],tag:"容器化",platforms:["docker"]}}:{web:{keywords:["web","frontend","website"],tag:"Web App",platforms:["web"]},api:{keywords:["api","backend","server"],tag:"Backend Service",platforms:["linux","docker"]},cli:{keywords:["cli","command","tool"],tag:"CLI Tool",platforms:["cli","linux","mac","windows"]},library:{keywords:["library","framework","sdk"],tag:"Development Library",platforms:[]},mobile:{keywords:["mobile","android","ios"],tag:"Mobile App",platforms:[]},game:{keywords:["game","gaming"],tag:"Game",platforms:["windows","mac","linux"]},ai:{keywords:["ai","ml","machine learning"],tag:"AI Tool",platforms:["linux","mac","windows"]},database:{keywords:["database","db","storage"],tag:"Database",platforms:["linux","docker"]},docker:{keywords:["docker","container"],tag:"Containerized",platforms:["docker"]}};return Object.values(u).forEach(({keywords:d,tag:g,platforms:h})=>{d.some(m=>i.includes(m))&&(r.push(g),a.push(...h))}),i.includes("android")&&a.push("android"),i.includes("ios")&&a.push("ios"),{summary:n.substring(0,50),tags:[...new Set(r)].slice(0,5),platforms:[...new Set(a)].slice(0,8)}}async testConnection(){try{return(await fetch(`${this.config.baseUrl}/models`,{method:"GET",headers:{Authorization:`Bearer ${this.config.apiKey}`}})).ok}catch{return!1}}async searchRepositories(t,n){var r,a;if(!n.trim())return t;try{const s=this.createSearchPrompt(n),l=await fetch(`${this.config.baseUrl}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.config.apiKey}`},body:JSON.stringify({model:this.config.model,messages:[{role:"system",content:this.language==="zh"?"你是一个智能搜索助手。请分析用户的搜索意图,提取关键词并提供多语言翻译。":"You are an intelligent search assistant. Please analyze user search intent, extract keywords and provide multilingual translations."},{role:"user",content:s}],temperature:.1,max_tokens:200})});if(l.ok){const u=(a=(r=(await l.json()).choices[0])==null?void 0:r.message)==null?void 0:a.content;if(u){const d=this.parseSearchResponse(u);return this.performEnhancedSearch(t,n,d)}}}catch(s){console.warn("AI search failed, falling back to basic search:",s)}return this.performBasicSearch(t,n)}createSearchPrompt(t){return this.language==="zh"?` +用户搜索查询: "${t}" + +请分析这个搜索查询并提供: +1. 主要关键词(中英文) +2. 相关的技术术语和同义词 +3. 可能的应用类型或分类 + +以JSON格式回复: +{ + "keywords": ["关键词1", "keyword1", "关键词2", "keyword2"], + "categories": ["分类1", "category1"], + "synonyms": ["同义词1", "synonym1"] +} + `.trim():` +User search query: "${t}" + +Please analyze this search query and provide: +1. Main keywords (in English and Chinese) +2. Related technical terms and synonyms +3. Possible application types or categories + +Reply in JSON format: +{ + "keywords": ["keyword1", "关键词1", "keyword2", "关键词2"], + "categories": ["category1", "分类1"], + "synonyms": ["synonym1", "同义词1"] +} + `.trim()}parseSearchResponse(t){try{const n=t.match(/\{[\s\S]*\}/);if(n){const r=JSON.parse(n[0]);return[...r.keywords||[],...r.categories||[],...r.synonyms||[]].filter(s=>typeof s=="string"&&s.length>0)}}catch(n){console.warn("Failed to parse AI search response:",n)}return[]}performEnhancedSearch(t,n,r){const a=[n,...r];return t.filter(s=>{const l=[s.name,s.full_name,s.description||"",s.language||"",...s.topics||[],s.ai_summary||"",...s.ai_tags||[],...s.ai_platforms||[]].join(" ").toLowerCase();return a.some(i=>{const u=i.toLowerCase();return l.includes(u)||u.split(/\s+/).every(d=>l.includes(d))})})}performBasicSearch(t,n){const r=n.toLowerCase();return t.filter(a=>{const s=[a.name,a.full_name,a.description||"",a.language||"",...a.topics||[],a.ai_summary||"",...a.ai_tags||[],...a.ai_platforms||[]].join(" ").toLowerCase();return r.split(/\s+/).every(i=>s.includes(i))})}static async searchRepositories(t,n){if(!n.trim())return t;const r=n.toLowerCase();return t.filter(a=>{const s=[a.name,a.full_name,a.description||"",a.language||"",...a.topics||[],a.ai_summary||"",...a.ai_tags||[],...a.ai_platforms||[]].join(" ").toLowerCase();return r.split(/\s+/).every(i=>s.includes(i))})}}const mm=()=>{const{searchFilters:e,repositories:t,releaseSubscriptions:n,aiConfigs:r,activeAIConfig:a,language:s,setSearchFilters:l,setSearchResults:i}=Wt(),[u,d]=W.useState(!1),[g,h]=W.useState(e.query),[m,v]=W.useState(!1),[k,x]=W.useState([]),[_,f]=W.useState([]),[c,p]=W.useState([]);W.useEffect(()=>{const y=[...new Set(t.map(z=>z.language).filter(Boolean))],E=[...new Set([...t.flatMap(z=>z.ai_tags||[]),...t.flatMap(z=>z.topics||[])])],A=[...new Set(t.flatMap(z=>z.ai_platforms||[]))];x(y),f(E),p(A)},[t]),W.useEffect(()=>{(async()=>{e.query&&!m?(v(!0),await b(),v(!1)):e.query||P()})()},[e,t,n]);const b=async()=>{let y=t;if(e.query){const E=r.find(A=>A.id===a);if(E)try{y=await new es(E,s).searchRepositories(y,e.query)}catch(A){console.warn("AI search failed, falling back to basic search:",A),y=j(y,e.query)}else y=j(y,e.query)}y=N(y),i(y)},P=()=>{const y=N(t);i(y)},j=(y,E)=>{const A=E.toLowerCase();return y.filter(z=>{const w=[z.name,z.full_name,z.description||"",z.language||"",...z.topics||[],z.ai_summary||"",...z.ai_tags||[],...z.ai_platforms||[]].join(" ").toLowerCase();return A.split(/\s+/).every(O=>w.includes(O))})},N=y=>{let E=y;return e.languages.length>0&&(E=E.filter(A=>A.language&&e.languages.includes(A.language))),e.tags.length>0&&(E=E.filter(A=>{const z=[...A.ai_tags||[],...A.topics||[]];return e.tags.some(w=>z.includes(w))})),e.platforms.length>0&&(E=E.filter(A=>{const z=A.ai_platforms||[];return e.platforms.some(w=>z.includes(w))})),e.isAnalyzed!==void 0&&(E=E.filter(A=>e.isAnalyzed?!!A.analyzed_at:!A.analyzed_at)),e.isSubscribed!==void 0&&(E=E.filter(A=>e.isSubscribed?n.has(A.id):!n.has(A.id))),e.minStars!==void 0&&(E=E.filter(A=>A.stargazers_count>=e.minStars)),e.maxStars!==void 0&&(E=E.filter(A=>A.stargazers_count<=e.maxStars)),E.sort((A,z)=>{let w,T;switch(e.sortBy){case"stars":w=A.stargazers_count,T=z.stargazers_count;break;case"updated":w=new Date(A.updated_at).getTime(),T=new Date(z.updated_at).getTime();break;case"name":w=A.name.toLowerCase(),T=z.name.toLowerCase();break;default:w=new Date(A.updated_at).getTime(),T=new Date(z.updated_at).getTime()}return e.sortOrder==="desc"?T>w?1:-1:w>T?1:-1}),E},R=()=>{l({query:g})},$=()=>{h(""),l({query:""})},D=y=>{y.key==="Enter"&&R()},q=y=>{const E=e.languages.includes(y)?e.languages.filter(A=>A!==y):[...e.languages,y];l({languages:E})},Y=y=>{const E=e.tags.includes(y)?e.tags.filter(A=>A!==y):[...e.tags,y];l({tags:E})},ue=y=>{const E=e.platforms.includes(y)?e.platforms.filter(A=>A!==y):[...e.platforms,y];l({platforms:E})},pe=()=>{h(""),l({query:"",tags:[],languages:[],platforms:[],sortBy:"stars",sortOrder:"desc",minStars:void 0,maxStars:void 0,isAnalyzed:void 0,isSubscribed:void 0})},ce=e.languages.length+e.tags.length+e.platforms.length+(e.minStars!==void 0?1:0)+(e.maxStars!==void 0?1:0)+(e.isAnalyzed!==void 0?1:0)+(e.isSubscribed!==void 0?1:0),V=y=>({mac:"fab fa-apple",macos:"fab fa-apple",windows:"fab fa-windows",win:"fab fa-windows",linux:"fab fa-linux",ios:"fab fa-apple",android:"fab fa-android",web:"fas fa-globe",cli:"fas fa-terminal",docker:"fab fa-docker"})[y.toLowerCase()]||"fas fa-desktop",U=(y,E)=>s==="zh"?y:E;return o.jsxs("div",{className:"bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-6 mb-6",children:[o.jsxs("div",{className:"relative mb-4",children:[o.jsx(wo,{className:"absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-5 h-5"}),o.jsx("input",{type:"text",placeholder:U("使用自然语言搜索仓库 (例如: '查找所有笔记应用')","Search repositories with natural language (e.g., 'find all note-taking apps')"),value:g,onChange:y=>h(y.target.value),onKeyPress:D,className:"w-full pl-10 pr-32 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-white dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-500 dark:placeholder-gray-400"}),o.jsxs("div",{className:"absolute right-2 top-1/2 transform -translate-y-1/2 flex items-center space-x-2",children:[g&&o.jsx("button",{onClick:$,className:"p-1.5 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors",title:U("清除搜索","Clear search"),children:o.jsx(Yt,{className:"w-4 h-4"})}),o.jsx("button",{onClick:R,disabled:m,className:"px-4 py-1.5 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors text-sm font-medium disabled:opacity-50",children:m?U("搜索中...","Searching..."):U("搜索","Search")})]})]}),o.jsxs("div",{className:"flex items-center justify-between",children:[o.jsxs("div",{className:"flex items-center space-x-3",children:[o.jsxs("button",{onClick:()=>d(!u),className:`flex items-center space-x-2 px-4 py-2 rounded-lg transition-colors ${u||ce>0?"bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300":"bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600"}`,children:[o.jsx(Sp,{className:"w-4 h-4"}),o.jsx("span",{children:U("过滤器","Filters")}),ce>0&&o.jsx("span",{className:"bg-blue-600 text-white rounded-full px-2 py-0.5 text-xs",children:ce})]}),ce>0&&o.jsxs("button",{onClick:pe,className:"flex items-center space-x-1 px-3 py-2 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200 transition-colors",children:[o.jsx(Yt,{className:"w-4 h-4"}),o.jsx("span",{children:U("清除全部","Clear all")})]})]}),o.jsxs("div",{className:"flex items-center space-x-3",children:[o.jsxs("select",{value:e.sortBy,onChange:y=>l({sortBy:y.target.value}),className:"px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white text-sm",children:[o.jsx("option",{value:"stars",children:U("按星标排序","Sort by Stars")}),o.jsx("option",{value:"updated",children:U("按更新排序","Sort by Updated")}),o.jsx("option",{value:"name",children:U("按名称排序","Sort by Name")})]}),o.jsx("button",{onClick:()=>l({sortOrder:e.sortOrder==="desc"?"asc":"desc"}),className:"px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white text-sm hover:bg-gray-50 dark:hover:bg-gray-600 transition-colors",children:e.sortOrder==="desc"?"↓":"↑"})]})]}),u&&o.jsxs("div",{className:"mt-6 pt-6 border-t border-gray-200 dark:border-gray-700 space-y-6",children:[o.jsxs("div",{children:[o.jsx("h4",{className:"text-sm font-medium text-gray-900 dark:text-white mb-3",children:U("状态过滤","Status Filters")}),o.jsxs("div",{className:"flex flex-wrap gap-2",children:[o.jsxs("button",{onClick:()=>l({isAnalyzed:e.isAnalyzed===!0?void 0:!0}),className:`flex items-center space-x-2 px-3 py-1.5 rounded-lg text-sm transition-colors ${e.isAnalyzed===!0?"bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-300":"bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600"}`,children:[o.jsx(np,{className:"w-4 h-4"}),o.jsx("span",{children:U("已AI分析","AI Analyzed")})]}),o.jsxs("button",{onClick:()=>l({isAnalyzed:e.isAnalyzed===!1?void 0:!1}),className:`flex items-center space-x-2 px-3 py-1.5 rounded-lg text-sm transition-colors ${e.isAnalyzed===!1?"bg-orange-100 text-orange-700 dark:bg-orange-900 dark:text-orange-300":"bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600"}`,children:[o.jsx(Yt,{className:"w-4 h-4"}),o.jsx("span",{children:U("未AI分析","Not Analyzed")})]}),o.jsxs("button",{onClick:()=>l({isSubscribed:e.isSubscribed===!0?void 0:!0}),className:`flex items-center space-x-2 px-3 py-1.5 rounded-lg text-sm transition-colors ${e.isSubscribed===!0?"bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300":"bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600"}`,children:[o.jsx(vo,{className:"w-4 h-4"}),o.jsx("span",{children:U("已订阅Release","Subscribed to Releases")})]})]})]}),k.length>0&&o.jsxs("div",{children:[o.jsx("h4",{className:"text-sm font-medium text-gray-900 dark:text-white mb-3",children:U("编程语言","Programming Languages")}),o.jsx("div",{className:"flex flex-wrap gap-2",children:k.slice(0,12).map(y=>o.jsx("button",{onClick:()=>q(y),className:`px-3 py-1.5 rounded-lg text-sm transition-colors ${e.languages.includes(y)?"bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300":"bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600"}`,children:y},y))})]}),c.length>0&&o.jsxs("div",{children:[o.jsx("h4",{className:"text-sm font-medium text-gray-900 dark:text-white mb-3",children:U("支持平台","Supported Platforms")}),o.jsx("div",{className:"flex flex-wrap gap-2",children:c.map(y=>o.jsxs("button",{onClick:()=>ue(y),className:`flex items-center space-x-2 px-3 py-1.5 rounded-lg text-sm transition-colors ${e.platforms.includes(y)?"bg-purple-100 text-purple-700 dark:bg-purple-900 dark:text-purple-300":"bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600"}`,children:[o.jsx("i",{className:`${V(y)} w-4 h-4`}),o.jsx("span",{children:y})]},y))})]}),_.length>0&&o.jsxs("div",{children:[o.jsx("h4",{className:"text-sm font-medium text-gray-900 dark:text-white mb-3",children:U("标签","Tags")}),o.jsx("div",{className:"flex flex-wrap gap-2",children:_.slice(0,15).map(y=>o.jsx("button",{onClick:()=>Y(y),className:`px-3 py-1.5 rounded-lg text-sm transition-colors ${e.tags.includes(y)?"bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-300":"bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600"}`,children:y},y))})]}),o.jsxs("div",{children:[o.jsx("h4",{className:"text-sm font-medium text-gray-900 dark:text-white mb-3",children:U("Star数量范围","Star Count Range")}),o.jsxs("div",{className:"flex items-center space-x-4",children:[o.jsxs("div",{className:"flex items-center space-x-2",children:[o.jsx("label",{className:"text-sm text-gray-600 dark:text-gray-400",children:U("最小:","Min:")}),o.jsx("input",{type:"number",placeholder:"0",value:e.minStars||"",onChange:y=>l({minStars:y.target.value?parseInt(y.target.value):void 0}),className:"w-24 px-3 py-1.5 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white text-sm"})]}),o.jsxs("div",{className:"flex items-center space-x-2",children:[o.jsx("label",{className:"text-sm text-gray-600 dark:text-gray-400",children:U("最大:","Max:")}),o.jsx("input",{type:"number",placeholder:"∞",value:e.maxStars||"",onChange:y=>l({maxStars:y.target.value?parseInt(y.target.value):void 0}),className:"w-24 px-3 py-1.5 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white text-sm"})]})]})]})]})]})};function ke(e){const t=Object.prototype.toString.call(e);return e instanceof Date||typeof e=="object"&&t==="[object Date]"?new e.constructor(+e):typeof e=="number"||t==="[object Number]"||typeof e=="string"||t==="[object String]"?new Date(e):new Date(NaN)}function gm(e,t){return e instanceof Date?new e.constructor(t):new Date(t)}const Xr=43200,Hi=1440;let hm={};function ym(){return hm}function Bi(e){const t=ke(e),n=new Date(Date.UTC(t.getFullYear(),t.getMonth(),t.getDate(),t.getHours(),t.getMinutes(),t.getSeconds(),t.getMilliseconds()));return n.setUTCFullYear(t.getFullYear()),+e-+n}function da(e,t){const n=ke(e),r=ke(t),a=n.getTime()-r.getTime();return a<0?-1:a>0?1:a}function xm(e){return gm(e,Date.now())}function vm(e,t){const n=ke(e),r=ke(t),a=n.getFullYear()-r.getFullYear(),s=n.getMonth()-r.getMonth();return a*12+s}function wm(e){return t=>{const r=(e?Math[e]:Math.trunc)(t);return r===0?0:r}}function km(e,t){return+ke(e)-+ke(t)}function bm(e){const t=ke(e);return t.setHours(23,59,59,999),t}function Sm(e){const t=ke(e),n=t.getMonth();return t.setFullYear(t.getFullYear(),n+1,0),t.setHours(23,59,59,999),t}function Nm(e){const t=ke(e);return+bm(t)==+Sm(t)}function jm(e,t){const n=ke(e),r=ke(t),a=da(n,r),s=Math.abs(vm(n,r));let l;if(s<1)l=0;else{n.getMonth()===1&&n.getDate()>27&&n.setDate(30),n.setMonth(n.getMonth()-a*s);let i=da(n,r)===-a;Nm(ke(e))&&s===1&&da(e,r)===1&&(i=!1),l=a*(s-Number(i))}return l===0?0:l}function Cm(e,t,n){const r=km(e,t)/1e3;return wm(n==null?void 0:n.roundingMethod)(r)}const Em={lessThanXSeconds:{one:"less than a second",other:"less than {{count}} seconds"},xSeconds:{one:"1 second",other:"{{count}} seconds"},halfAMinute:"half a minute",lessThanXMinutes:{one:"less than a minute",other:"less than {{count}} minutes"},xMinutes:{one:"1 minute",other:"{{count}} minutes"},aboutXHours:{one:"about 1 hour",other:"about {{count}} hours"},xHours:{one:"1 hour",other:"{{count}} hours"},xDays:{one:"1 day",other:"{{count}} days"},aboutXWeeks:{one:"about 1 week",other:"about {{count}} weeks"},xWeeks:{one:"1 week",other:"{{count}} weeks"},aboutXMonths:{one:"about 1 month",other:"about {{count}} months"},xMonths:{one:"1 month",other:"{{count}} months"},aboutXYears:{one:"about 1 year",other:"about {{count}} years"},xYears:{one:"1 year",other:"{{count}} years"},overXYears:{one:"over 1 year",other:"over {{count}} years"},almostXYears:{one:"almost 1 year",other:"almost {{count}} years"}},Am=(e,t,n)=>{let r;const a=Em[e];return typeof a=="string"?r=a:t===1?r=a.one:r=a.other.replace("{{count}}",t.toString()),n!=null&&n.addSuffix?n.comparison&&n.comparison>0?"in "+r:r+" ago":r};function Ps(e){return(t={})=>{const n=t.width?String(t.width):e.defaultWidth;return e.formats[n]||e.formats[e.defaultWidth]}}const _m={full:"EEEE, MMMM do, y",long:"MMMM do, y",medium:"MMM d, y",short:"MM/dd/yyyy"},Pm={full:"h:mm:ss a zzzz",long:"h:mm:ss a z",medium:"h:mm:ss a",short:"h:mm a"},zm={full:"{{date}} 'at' {{time}}",long:"{{date}} 'at' {{time}}",medium:"{{date}}, {{time}}",short:"{{date}}, {{time}}"},Dm={date:Ps({formats:_m,defaultWidth:"full"}),time:Ps({formats:Pm,defaultWidth:"full"}),dateTime:Ps({formats:zm,defaultWidth:"full"})},Mm={lastWeek:"'last' eeee 'at' p",yesterday:"'yesterday at' p",today:"'today at' p",tomorrow:"'tomorrow at' p",nextWeek:"eeee 'at' p",other:"P"},Rm=(e,t,n,r)=>Mm[e];function Qn(e){return(t,n)=>{const r=n!=null&&n.context?String(n.context):"standalone";let a;if(r==="formatting"&&e.formattingValues){const l=e.defaultFormattingWidth||e.defaultWidth,i=n!=null&&n.width?String(n.width):l;a=e.formattingValues[i]||e.formattingValues[l]}else{const l=e.defaultWidth,i=n!=null&&n.width?String(n.width):e.defaultWidth;a=e.values[i]||e.values[l]}const s=e.argumentCallback?e.argumentCallback(t):t;return a[s]}}const Tm={narrow:["B","A"],abbreviated:["BC","AD"],wide:["Before Christ","Anno Domini"]},Im={narrow:["1","2","3","4"],abbreviated:["Q1","Q2","Q3","Q4"],wide:["1st quarter","2nd quarter","3rd quarter","4th quarter"]},Lm={narrow:["J","F","M","A","M","J","J","A","S","O","N","D"],abbreviated:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],wide:["January","February","March","April","May","June","July","August","September","October","November","December"]},$m={narrow:["S","M","T","W","T","F","S"],short:["Su","Mo","Tu","We","Th","Fr","Sa"],abbreviated:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],wide:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]},Om={narrow:{am:"a",pm:"p",midnight:"mi",noon:"n",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"},abbreviated:{am:"AM",pm:"PM",midnight:"midnight",noon:"noon",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"},wide:{am:"a.m.",pm:"p.m.",midnight:"midnight",noon:"noon",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"}},Fm={narrow:{am:"a",pm:"p",midnight:"mi",noon:"n",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"},abbreviated:{am:"AM",pm:"PM",midnight:"midnight",noon:"noon",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"},wide:{am:"a.m.",pm:"p.m.",midnight:"midnight",noon:"noon",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"}},Wm=(e,t)=>{const n=Number(e),r=n%100;if(r>20||r<10)switch(r%10){case 1:return n+"st";case 2:return n+"nd";case 3:return n+"rd"}return n+"th"},Vm={ordinalNumber:Wm,era:Qn({values:Tm,defaultWidth:"wide"}),quarter:Qn({values:Im,defaultWidth:"wide",argumentCallback:e=>e-1}),month:Qn({values:Lm,defaultWidth:"wide"}),day:Qn({values:$m,defaultWidth:"wide"}),dayPeriod:Qn({values:Om,defaultWidth:"wide",formattingValues:Fm,defaultFormattingWidth:"wide"})};function Gn(e){return(t,n={})=>{const r=n.width,a=r&&e.matchPatterns[r]||e.matchPatterns[e.defaultMatchWidth],s=t.match(a);if(!s)return null;const l=s[0],i=r&&e.parsePatterns[r]||e.parsePatterns[e.defaultParseWidth],u=Array.isArray(i)?Hm(i,h=>h.test(l)):Um(i,h=>h.test(l));let d;d=e.valueCallback?e.valueCallback(u):u,d=n.valueCallback?n.valueCallback(d):d;const g=t.slice(l.length);return{value:d,rest:g}}}function Um(e,t){for(const n in e)if(Object.prototype.hasOwnProperty.call(e,n)&&t(e[n]))return n}function Hm(e,t){for(let n=0;n{const r=t.match(e.matchPattern);if(!r)return null;const a=r[0],s=t.match(e.parsePattern);if(!s)return null;let l=e.valueCallback?e.valueCallback(s[0]):s[0];l=n.valueCallback?n.valueCallback(l):l;const i=t.slice(a.length);return{value:l,rest:i}}}const Qm=/^(\d+)(th|st|nd|rd)?/i,Gm=/\d+/i,Km={narrow:/^(b|a)/i,abbreviated:/^(b\.?\s?c\.?|b\.?\s?c\.?\s?e\.?|a\.?\s?d\.?|c\.?\s?e\.?)/i,wide:/^(before christ|before common era|anno domini|common era)/i},qm={any:[/^b/i,/^(a|c)/i]},Ym={narrow:/^[1234]/i,abbreviated:/^q[1234]/i,wide:/^[1234](th|st|nd|rd)? quarter/i},Xm={any:[/1/i,/2/i,/3/i,/4/i]},Jm={narrow:/^[jfmasond]/i,abbreviated:/^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i,wide:/^(january|february|march|april|may|june|july|august|september|october|november|december)/i},Zm={narrow:[/^j/i,/^f/i,/^m/i,/^a/i,/^m/i,/^j/i,/^j/i,/^a/i,/^s/i,/^o/i,/^n/i,/^d/i],any:[/^ja/i,/^f/i,/^mar/i,/^ap/i,/^may/i,/^jun/i,/^jul/i,/^au/i,/^s/i,/^o/i,/^n/i,/^d/i]},eg={narrow:/^[smtwf]/i,short:/^(su|mo|tu|we|th|fr|sa)/i,abbreviated:/^(sun|mon|tue|wed|thu|fri|sat)/i,wide:/^(sunday|monday|tuesday|wednesday|thursday|friday|saturday)/i},tg={narrow:[/^s/i,/^m/i,/^t/i,/^w/i,/^t/i,/^f/i,/^s/i],any:[/^su/i,/^m/i,/^tu/i,/^w/i,/^th/i,/^f/i,/^sa/i]},ng={narrow:/^(a|p|mi|n|(in the|at) (morning|afternoon|evening|night))/i,any:/^([ap]\.?\s?m\.?|midnight|noon|(in the|at) (morning|afternoon|evening|night))/i},rg={any:{am:/^a/i,pm:/^p/i,midnight:/^mi/i,noon:/^no/i,morning:/morning/i,afternoon:/afternoon/i,evening:/evening/i,night:/night/i}},ag={ordinalNumber:Bm({matchPattern:Qm,parsePattern:Gm,valueCallback:e=>parseInt(e,10)}),era:Gn({matchPatterns:Km,defaultMatchWidth:"wide",parsePatterns:qm,defaultParseWidth:"any"}),quarter:Gn({matchPatterns:Ym,defaultMatchWidth:"wide",parsePatterns:Xm,defaultParseWidth:"any",valueCallback:e=>e+1}),month:Gn({matchPatterns:Jm,defaultMatchWidth:"wide",parsePatterns:Zm,defaultParseWidth:"any"}),day:Gn({matchPatterns:eg,defaultMatchWidth:"wide",parsePatterns:tg,defaultParseWidth:"any"}),dayPeriod:Gn({matchPatterns:ng,defaultMatchWidth:"any",parsePatterns:rg,defaultParseWidth:"any"})},sg={code:"en-US",formatDistance:Am,formatLong:Dm,formatRelative:Rm,localize:Vm,match:ag,options:{weekStartsOn:0,firstWeekContainsDate:1}};function lg(e,t,n){const r=ym(),a=(n==null?void 0:n.locale)??r.locale??sg,s=2520,l=da(e,t);if(isNaN(l))throw new RangeError("Invalid time value");const i=Object.assign({},n,{addSuffix:n==null?void 0:n.addSuffix,comparison:l});let u,d;l>0?(u=ke(t),d=ke(e)):(u=ke(e),d=ke(t));const g=Cm(d,u),h=(Bi(d)-Bi(u))/1e3,m=Math.round((g-h)/60);let v;if(m<2)return n!=null&&n.includeSeconds?g<5?a.formatDistance("lessThanXSeconds",5,i):g<10?a.formatDistance("lessThanXSeconds",10,i):g<20?a.formatDistance("lessThanXSeconds",20,i):g<40?a.formatDistance("halfAMinute",0,i):g<60?a.formatDistance("lessThanXMinutes",1,i):a.formatDistance("xMinutes",1,i):m===0?a.formatDistance("lessThanXMinutes",1,i):a.formatDistance("xMinutes",m,i);if(m<45)return a.formatDistance("xMinutes",m,i);if(m<90)return a.formatDistance("aboutXHours",1,i);if(m{var c,p,b,P;const{releaseSubscriptions:n,toggleReleaseSubscription:r,updateRepository:a,githubToken:s,aiConfigs:l,activeAIConfig:i,isLoading:u,setLoading:d,language:g}=Wt(),h=n.has(e.id),m=j=>j>=1e6?`${(j/1e6).toFixed(1)}M`:j>=1e3?`${(j/1e3).toFixed(1)}K`:j.toString(),v=j=>({JavaScript:"#f1e05a",TypeScript:"#3178c6",Python:"#3572A5",Java:"#b07219","C++":"#f34b7d",C:"#555555","C#":"#239120",Go:"#00ADD8",Rust:"#dea584",PHP:"#4F5D95",Ruby:"#701516",Swift:"#fa7343",Kotlin:"#A97BFF",Dart:"#00B4AB",Shell:"#89e051",HTML:"#e34c26",CSS:"#1572B6",Vue:"#4FC08D",React:"#61DAFB"})[j]||"#6b7280",k=j=>({mac:"fab fa-apple",macos:"fab fa-apple",windows:"fab fa-windows",win:"fab fa-windows",linux:"fab fa-linux",ios:"fab fa-apple",android:"fab fa-android",web:"fas fa-globe",cli:"fas fa-terminal",docker:"fab fa-docker"})[j.toLowerCase()]||"fas fa-desktop",x=async()=>{if(!s){alert("GitHub token not found. Please login again.");return}const j=l.find(N=>N.id===i);if(!j){alert("请先在设置中配置AI服务。");return}d(!0);try{const N=new zr(s),R=new es(j,g),[$,D]=e.full_name.split("/"),q=await N.getRepositoryReadme($,D),Y=await R.analyzeRepository(e,q),ue={...e,ai_summary:Y.summary,ai_tags:Y.tags,ai_platforms:Y.platforms,analyzed_at:new Date().toISOString()};a(ue),alert("AI分析完成!")}catch(N){console.error("AI analysis failed:",N),alert("AI分析失败,请检查AI配置和网络连接。")}finally{d(!1)}},f=t&&e.ai_summary?{content:e.ai_summary,isAI:!0}:e.description?{content:e.description,isAI:!1}:{content:g==="zh"?"暂无描述":"No description available",isAI:!1};return o.jsxs("div",{className:"bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-6 hover:shadow-lg transition-all duration-200 hover:border-blue-300 dark:hover:border-blue-600 animate-slide-up flex flex-col h-full",children:[o.jsxs("div",{className:"flex items-center space-x-3 mb-3",children:[o.jsx("img",{src:e.owner.avatar_url,alt:e.owner.login,className:"w-8 h-8 rounded-full flex-shrink-0"}),o.jsxs("div",{className:"min-w-0 flex-1",children:[o.jsx("h3",{className:"font-semibold text-gray-900 dark:text-white truncate",children:e.name}),o.jsx("p",{className:"text-sm text-gray-500 dark:text-gray-400 truncate",children:e.owner.login})]})]}),o.jsxs("div",{className:"flex items-center justify-between mb-4",children:[o.jsxs("div",{className:"flex items-center space-x-2",children:[o.jsx("button",{onClick:x,disabled:u,className:`p-2 rounded-lg transition-colors ${e.analyzed_at?"bg-green-100 text-green-600 dark:bg-green-900 dark:text-green-400":"bg-purple-100 text-purple-600 dark:bg-purple-900 dark:text-purple-400 hover:bg-purple-200 dark:hover:bg-purple-800"} disabled:opacity-50`,title:e.analyzed_at?g==="zh"?"已AI分析":"AI Analyzed":g==="zh"?"AI分析此仓库":"Analyze with AI",children:o.jsx(Nr,{className:"w-4 h-4"})}),o.jsx("button",{onClick:()=>r(e.id),className:`p-2 rounded-lg transition-colors ${h?"bg-blue-100 text-blue-600 dark:bg-blue-900 dark:text-blue-400":"bg-gray-100 text-gray-500 dark:bg-gray-700 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600"}`,title:h?"Unsubscribe from releases":"Subscribe to releases",children:h?o.jsx(vo,{className:"w-4 h-4"}):o.jsx(ep,{className:"w-4 h-4"})})]}),o.jsx("div",{children:o.jsx("a",{href:e.html_url,target:"_blank",rel:"noopener noreferrer",className:"flex items-center justify-center w-8 h-8 rounded-lg bg-gray-100 text-gray-500 dark:bg-gray-700 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors",title:"View on GitHub",children:o.jsx(Sl,{className:"w-4 h-4"})})})]}),o.jsxs("div",{className:"mb-4 flex-1",children:[o.jsx("p",{className:"text-gray-700 dark:text-gray-300 text-sm leading-relaxed line-clamp-3 mb-2",children:f.content}),f.isAI&&o.jsxs("div",{className:"flex items-center space-x-1 text-xs text-green-600 dark:text-green-400",children:[o.jsx(Nr,{className:"w-3 h-3"}),o.jsx("span",{children:g==="zh"?"AI总结":"AI Summary"})]})]}),(((c=e.ai_tags)==null?void 0:c.length)||((p=e.topics)==null?void 0:p.length))&&o.jsxs("div",{className:"flex flex-wrap gap-2 mb-4",children:[(b=e.ai_tags)==null?void 0:b.slice(0,3).map((j,N)=>o.jsxs("span",{className:"px-2 py-1 bg-purple-100 text-purple-700 dark:bg-purple-900 dark:text-purple-300 rounded-md text-xs font-medium",children:[o.jsx(Cp,{className:"w-3 h-3 inline mr-1"}),j]},`ai-${N}`)),(P=e.topics)==null?void 0:P.slice(0,2).map((j,N)=>o.jsx("span",{className:"px-2 py-1 bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 rounded-md text-xs",children:j},`topic-${N}`))]}),e.ai_platforms&&e.ai_platforms.length>0&&o.jsxs("div",{className:"flex items-center space-x-2 mb-4",children:[o.jsx("span",{className:"text-xs text-gray-500 dark:text-gray-400",children:g==="zh"?"支持平台:":"Platforms:"}),o.jsx("div",{className:"flex space-x-1",children:e.ai_platforms.slice(0,6).map((j,N)=>o.jsx("div",{className:"w-6 h-6 flex items-center justify-center bg-gray-100 dark:bg-gray-700 rounded text-gray-600 dark:text-gray-400",title:j,children:o.jsx("i",{className:`${k(j)} text-xs`})},N))})]}),o.jsxs("div",{className:"space-y-3 mt-auto",children:[o.jsxs("div",{className:"flex items-center justify-between text-sm text-gray-500 dark:text-gray-400",children:[o.jsxs("div",{className:"flex items-center space-x-4",children:[e.language&&o.jsxs("div",{className:"flex items-center space-x-1",children:[o.jsx("div",{className:"w-3 h-3 rounded-full",style:{backgroundColor:v(e.language)}}),o.jsx("span",{className:"truncate max-w-20",children:e.language})]}),o.jsxs("div",{className:"flex items-center space-x-1",children:[o.jsx(ko,{className:"w-4 h-4"}),o.jsx("span",{children:m(e.stargazers_count)})]})]}),e.analyzed_at&&o.jsxs("div",{className:"flex items-center space-x-1 text-xs",children:[o.jsx("div",{className:"w-2 h-2 bg-green-500 rounded-full"}),o.jsx("span",{children:g==="zh"?"AI已分析":"AI analyzed"})]})]}),o.jsxs("div",{className:"flex items-center space-x-1 text-sm text-gray-500 dark:text-gray-400 pt-2 border-t border-gray-100 dark:border-gray-700",children:[o.jsx(id,{className:"w-4 h-4 flex-shrink-0"}),o.jsxs("span",{className:"truncate",children:[g==="zh"?"更新于":"Updated"," ",fa(new Date(e.updated_at),{addSuffix:!0})]})]})]})]})},ig=({repositories:e,selectedCategory:t})=>{const{githubToken:n,aiConfigs:r,activeAIConfig:a,isLoading:s,setLoading:l,updateRepository:i,language:u}=Wt(),[d,g]=W.useState(!0),[h,m]=W.useState(!1),[v,k]=W.useState({current:0,total:0}),[x,_]=W.useState(!1),f=W.useRef(!1),c=W.useRef(!1),p=e.filter(D=>{if(t==="all")return!0;if(D.ai_tags&&D.ai_tags.length>0){const ue=Qi(t);return D.ai_tags.some(pe=>ue.some(ce=>pe.toLowerCase().includes(ce.toLowerCase())||ce.toLowerCase().includes(pe.toLowerCase())))}const q=[D.name,D.description||"",D.language||"",...D.topics||[],D.ai_summary||""].join(" ").toLowerCase();return Qi(t).some(ue=>q.includes(ue.toLowerCase()))}),b=async(D=!1)=>{if(!n){alert(u==="zh"?"GitHub token 未找到,请重新登录。":"GitHub token not found. Please login again.");return}const q=r.find(V=>V.id===a);if(!q){alert(u==="zh"?"请先在设置中配置AI服务。":"Please configure AI service in settings first.");return}const Y=D?p.filter(V=>!V.analyzed_at):p;if(Y.length===0){alert(u==="zh"?D?"所有仓库都已经分析过了!":"没有可分析的仓库!":D?"All repositories have been analyzed!":"No repositories to analyze!");return}const ue=u==="zh"?D?"未分析":"全部":D?"unanalyzed":"all",pe=u==="zh"?`将对 ${Y.length} 个${ue}仓库进行AI分析,这可能需要几分钟时间。是否继续?`:`Will analyze ${Y.length} ${ue} repositories with AI. This may take several minutes. Continue?`;if(confirm(pe)){f.current=!1,c.current=!0,l(!0),k({current:0,total:Y.length}),m(!1),_(!1);try{const V=new zr(n),U=new es(q,u);let y=0;for(let A=0;AsetTimeout(w,1e3));if(f.current){console.log("Analysis stopped during pause");break}const z=Y[A];k({current:A+1,total:Y.length});try{const[w,T]=z.full_name.split("/"),O=await V.getRepositoryReadme(w,T),Q=await U.analyzeRepository(z,O),G={...z,ai_summary:Q.summary,ai_tags:Q.tags,ai_platforms:Q.platforms,analyzed_at:new Date().toISOString()};i(G),y++,await new Promise(ne=>setTimeout(ne,1e3))}catch(w){console.warn(`Failed to analyze ${z.full_name}:`,w)}}const E=f.current?u==="zh"?`AI分析已停止!已成功分析了 ${y} 个仓库。`:`AI analysis stopped! Successfully analyzed ${y} repositories.`:u==="zh"?`AI分析完成!成功分析了 ${y} 个仓库。`:`AI analysis completed! Successfully analyzed ${y} repositories.`;alert(E)}catch(V){console.error("AI analysis failed:",V),alert(u==="zh"?"AI分析失败,请检查AI配置和网络连接。":"AI analysis failed. Please check AI configuration and network connection.")}finally{c.current=!1,f.current=!1,l(!1),k({current:0,total:0}),_(!1)}}},P=()=>{c.current&&(_(!x),console.log(x?"Analysis resumed":"Analysis paused"))},j=()=>{if(!c.current)return;confirm(u==="zh"?"确定要停止AI分析吗?已分析的结果将会保存。":"Are you sure you want to stop AI analysis? Analyzed results will be saved.")&&(f.current=!0,_(!1),console.log("Stop requested by user"))};if(p.length===0)return o.jsx("div",{className:"text-center py-12",children:o.jsx("p",{className:"text-gray-500 dark:text-gray-400",children:t==="all"?u==="zh"?"未找到仓库。点击同步加载您的星标仓库。":"No repositories found. Click sync to load your starred repositories.":u==="zh"?`在"${Gi(t)}"分类中未找到仓库。`:`No repositories found in "${Gi(t)}" category.`})});const N=p.filter(D=>!D.analyzed_at).length,R=p.filter(D=>D.analyzed_at).length,$=(D,q)=>u==="zh"?D:q;return o.jsxs("div",{className:"space-y-6",children:[o.jsxs("div",{className:"flex items-center justify-between bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-4",children:[o.jsxs("div",{className:"flex items-center space-x-4",children:[o.jsxs("div",{className:"relative",children:[o.jsxs("button",{onClick:()=>m(!h),disabled:s,className:"flex items-center space-x-2 px-4 py-2 bg-purple-100 text-purple-700 dark:bg-purple-900 dark:text-purple-300 rounded-lg hover:bg-purple-200 dark:hover:bg-purple-800 transition-colors disabled:opacity-50",children:[o.jsx(Nr,{className:"w-4 h-4"}),o.jsx("span",{children:s?$(`AI分析中... (${v.current}/${v.total})`,`AI Analyzing... (${v.current}/${v.total})`):$("AI分析","AI Analysis")}),o.jsx(rp,{className:"w-4 h-4"})]}),h&&!s&&o.jsxs("div",{className:"absolute top-full left-0 mt-2 w-56 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg z-10",children:[o.jsxs("button",{onClick:()=>b(!1),className:"w-full px-4 py-3 text-left hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors border-b border-gray-100 dark:border-gray-600",children:[o.jsx("div",{className:"font-medium text-gray-900 dark:text-white",children:$("分析全部","Analyze All")}),o.jsx("div",{className:"text-sm text-gray-500 dark:text-gray-400",children:$(`分析 ${p.length} 个仓库`,`Analyze ${p.length} repositories`)})]}),o.jsxs("button",{onClick:()=>b(!0),disabled:N===0,className:"w-full px-4 py-3 text-left hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed",children:[o.jsx("div",{className:"font-medium text-gray-900 dark:text-white",children:$("分析未分析的","Analyze Unanalyzed")}),o.jsx("div",{className:"text-sm text-gray-500 dark:text-gray-400",children:$(`分析 ${N} 个未分析仓库`,`Analyze ${N} unanalyzed repositories`)})]})]})]}),s&&v.total>0&&o.jsxs("div",{className:"flex items-center space-x-3",children:[o.jsx("div",{className:"w-32 bg-gray-200 dark:bg-gray-700 rounded-full h-2",children:o.jsx("div",{className:"bg-purple-600 h-2 rounded-full transition-all duration-300",style:{width:`${v.current/v.total*100}%`}})}),o.jsxs("span",{className:"text-sm text-gray-600 dark:text-gray-400",children:[Math.round(v.current/v.total*100),"%"]}),o.jsx("button",{onClick:P,className:"p-1.5 rounded-lg bg-yellow-100 text-yellow-700 dark:bg-yellow-900 dark:text-yellow-300 hover:bg-yellow-200 dark:hover:bg-yellow-800 transition-colors",title:x?$("继续","Resume"):$("暂停","Pause"),children:x?o.jsx(kp,{className:"w-4 h-4"}):o.jsx(wp,{className:"w-4 h-4"})}),o.jsx("button",{onClick:j,className:"px-3 py-1.5 rounded-lg bg-red-100 text-red-700 dark:bg-red-900 dark:text-red-300 hover:bg-red-200 dark:hover:bg-red-800 transition-colors text-sm",children:$("停止","Stop")})]}),!s&&o.jsxs("div",{className:"flex items-center space-x-3",children:[o.jsx("span",{className:"text-sm text-gray-600 dark:text-gray-400",children:$("显示内容:","Display:")}),o.jsxs("div",{className:"flex items-center space-x-4",children:[o.jsxs("label",{className:"flex items-center space-x-2 cursor-pointer",children:[o.jsx("input",{type:"radio",name:"displayContent",checked:d,onChange:()=>g(!0),className:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"}),o.jsx("span",{className:"text-sm font-medium text-gray-700 dark:text-gray-300",children:$("AI总结","AI Summary")})]}),o.jsxs("label",{className:"flex items-center space-x-2 cursor-pointer",children:[o.jsx("input",{type:"radio",name:"displayContent",checked:!d,onChange:()=>g(!1),className:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"}),o.jsx("span",{className:"text-sm font-medium text-gray-700 dark:text-gray-300",children:$("原始描述","Original Description")})]})]})]})]}),o.jsxs("div",{className:"text-sm text-gray-500 dark:text-gray-400",children:[$(`显示 ${p.length} 个仓库`,`Showing ${p.length} repositories`),R>0&&o.jsxs("span",{className:"ml-2",children:["• ",R," ",$("个已AI分析","AI analyzed")]}),N>0&&o.jsxs("span",{className:"ml-2",children:["• ",N," ",$("个未分析","unanalyzed")]})]})]}),o.jsx("div",{className:"grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-6",children:p.map(D=>o.jsx(og,{repository:D,showAISummary:d},D.id))})]})};function Qi(e){return{web:["web应用","web","website","frontend","react","vue","angular"],mobile:["移动应用","mobile","android","ios","flutter","react-native"],desktop:["桌面应用","desktop","electron","gui","qt","gtk"],database:["数据库","database","sql","nosql","mongodb","mysql","postgresql"],ai:["ai工具","ai","ml","machine learning","deep learning","neural"],devtools:["开发工具","tool","cli","build","deploy","debug","test","automation"],security:["安全工具","security","encryption","auth","vulnerability"],game:["游戏","game","gaming","unity","unreal","godot"],design:["设计工具","design","ui","ux","graphics","image"],productivity:["效率工具","productivity","note","todo","calendar","task"],education:["教育学习","education","learning","tutorial","course"],social:["社交网络","social","chat","messaging","communication"],analytics:["数据分析","analytics","data","visualization","chart"]}[e]||[]}function Gi(e){return{web:"Web应用",mobile:"移动应用",desktop:"桌面应用",database:"数据库",ai:"AI/机器学习",devtools:"开发工具",security:"安全工具",game:"游戏",design:"设计工具",productivity:"效率工具",education:"教育学习",social:"社交网络",analytics:"数据分析"}[e]||e}const ug=[{id:"all",name:"全部分类",icon:fp,keywords:[]},{id:"web",name:"Web应用",icon:ud,keywords:["web应用","web","website","frontend","react","vue","angular"]},{id:"mobile",name:"移动应用",icon:Np,keywords:["移动应用","mobile","android","ios","flutter","react-native"]},{id:"desktop",name:"桌面应用",icon:sp,keywords:["桌面应用","desktop","electron","gui","qt","gtk"]},{id:"database",name:"数据库",icon:lp,keywords:["数据库","database","sql","nosql","mongodb","mysql","postgresql"]},{id:"ai",name:"AI/机器学习",icon:Nr,keywords:["ai工具","ai","ml","machine learning","deep learning","neural"]},{id:"devtools",name:"开发工具",icon:_p,keywords:["开发工具","tool","cli","build","deploy","debug","test","automation"]},{id:"security",name:"安全工具",icon:bp,keywords:["安全工具","security","encryption","auth","vulnerability"]},{id:"game",name:"游戏",icon:pp,keywords:["游戏","game","gaming","unity","unreal","godot"]},{id:"design",name:"设计工具",icon:vp,keywords:["设计工具","design","ui","ux","graphics","image"]},{id:"productivity",name:"效率工具",icon:Pp,keywords:["效率工具","productivity","note","todo","calendar","task"]},{id:"education",name:"教育学习",icon:tp,keywords:["教育学习","education","learning","tutorial","course"]},{id:"social",name:"社交网络",icon:Ap,keywords:["社交网络","social","chat","messaging","communication"]},{id:"analytics",name:"数据分析",icon:Z0,keywords:["数据分析","analytics","data","visualization","chart"]}],cg=({repositories:e,selectedCategory:t,onCategorySelect:n})=>{const r=a=>a.id==="all"?e.length:e.filter(s=>{if(s.ai_tags&&s.ai_tags.length>0)return s.ai_tags.some(i=>a.keywords.some(u=>i.toLowerCase().includes(u.toLowerCase())||u.toLowerCase().includes(i.toLowerCase())));const l=[s.name,s.description||"",s.language||"",...s.topics||[],s.ai_summary||""].join(" ").toLowerCase();return a.keywords.some(i=>l.includes(i.toLowerCase()))}).length;return o.jsxs("div",{className:"w-64 bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-4 h-fit sticky top-24",children:[o.jsx("h3",{className:"text-lg font-semibold text-gray-900 dark:text-white mb-4",children:"应用分类"}),o.jsx("div",{className:"space-y-1",children:ug.map(a=>{const s=r(a),l=a.icon,i=t===a.id;return o.jsxs("button",{onClick:()=>n(a.id),className:`w-full flex items-center justify-between px-3 py-2.5 rounded-lg text-left transition-colors ${i?"bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300":"text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"}`,children:[o.jsxs("div",{className:"flex items-center space-x-3",children:[o.jsx(l,{className:"w-4 h-4"}),o.jsx("span",{className:"text-sm font-medium",children:a.name})]}),o.jsx("span",{className:`text-xs px-2 py-1 rounded-full ${i?"bg-blue-200 text-blue-800 dark:bg-blue-800 dark:text-blue-200":"bg-gray-200 text-gray-600 dark:bg-gray-600 dark:text-gray-400"}`,children:s})]},a.id)})})]})},dg=()=>{const{releases:e,repositories:t,releaseSubscriptions:n,githubToken:r,language:a,setReleases:s,addReleases:l}=Wt(),[i,u]=W.useState(""),[d,g]=W.useState([]),[h,m]=W.useState(!1),[v,k]=W.useState(null),[x,_]=W.useState(1),[f,c]=W.useState(100),[p,b]=W.useState("compact"),P=w=>{const T=w.toLowerCase(),O=[];return Object.entries({windows:[".exe",".msi",".zip",".7z","windows","win32","win64","win-x64","win-x86","win-arm64","-win.",".win.","-windows.",".windows.","setup","installer"],macos:[".dmg",".pkg",".app.zip","darwin","macos","mac-os","osx","mac-universal","-mac.",".mac.","-macos.",".macos.","-darwin.",".darwin.","universal","x86_64-apple","arm64-apple"],linux:[".deb",".rpm",".tar.gz",".tar.xz",".tar.bz2",".appimage","linux","ubuntu","debian","fedora","centos","arch","alpine","-linux.",".linux.","x86_64-unknown-linux","aarch64-unknown-linux","musl","gnu"],android:[".apk",".aab","android","-android.",".android.","arm64-v8a","armeabi-v7a","x86","x86_64"],ios:[".ipa","ios","-ios.",".ios.","iphone","ipad"]}).forEach(([G,ne])=>{ne.some(Me=>T.includes(Me))&&O.push(G)}),O.length===0&&(T.includes("source")||T.includes("src")||T.includes("universal")||T.includes("all")||T.match(/\.(zip|tar\.gz|tar\.xz)$/)&&!T.includes("win")&&!T.includes("mac")&&!T.includes("linux"))&&O.push("universal"),O.length>0?O:["universal"]},j=w=>{const T=/\[([^\]]+)\]\((https?:\/\/[^\)]+)\)/g,O=[];let Q;for(;(Q=T.exec(w.body))!==null;){const[,ne,Me]=Q;if(Me.includes("/download/")||Me.includes("/releases/")||ne.toLowerCase().includes("download")||/\.(exe|dmg|deb|rpm|apk|ipa|zip|tar\.gz|msi|pkg|appimage)$/i.test(Me)){const Vt=P(ne+" "+Me);O.push({name:ne,url:Me,platforms:Vt})}}const G=/https:\/\/github\.com\/[^\/]+\/[^\/]+\/releases\/download\/[^\/]+\/([^\s\)]+)/g;for(;(Q=G.exec(w.body))!==null;){const[ne,Me]=Q,Vt=P(Me);O.some(Xe=>Xe.url===ne)||O.push({name:Me,url:ne,platforms:Vt})}return O},N=e.filter(w=>n.has(w.repository.id)),R=W.useMemo(()=>{let w=N;if(i.trim()){const T=i.toLowerCase();w=w.filter(O=>O.repository.name.toLowerCase().includes(T)||O.repository.full_name.toLowerCase().includes(T)||O.tag_name.toLowerCase().includes(T)||O.name.toLowerCase().includes(T)||O.body.toLowerCase().includes(T))}return d.length>0&&(w=w.filter(T=>j(T).some(Q=>d.some(G=>Q.platforms.includes(G))))),w.sort((T,O)=>new Date(O.published_at).getTime()-new Date(T.published_at).getTime())},[N,i,d]),$=Math.ceil(R.length/f),D=(x-1)*f,q=R.slice(D,D+f),Y=W.useMemo(()=>{const w=new Set;return N.forEach(T=>{j(T).forEach(Q=>{Q.platforms.forEach(G=>w.add(G))})}),Array.from(w).sort()},[N]),ue=async()=>{if(!r){alert(a==="zh"?"GitHub token 未找到,请重新登录。":"GitHub token not found. Please login again.");return}m(!0);try{const w=new zr(r),T=t.filter(Xe=>n.has(Xe.id));if(T.length===0){alert(a==="zh"?"没有订阅的仓库。":"No subscribed repositories.");return}let O=0;const Q=[],G=e.length>0?Math.max(...e.map(Xe=>new Date(Xe.published_at).getTime())):0,ne=G>0?new Date(G).toISOString():void 0;for(const Xe of T){const[Dr,Mr]=Xe.full_name.split("/"),ts=e.some(S=>S.repository.id===Xe.id);let M;ts?M=await w.getIncrementalRepositoryReleases(Dr,Mr,ne,10):M=await w.getRepositoryReleases(Dr,Mr,1,10),M.forEach(S=>{S.repository.id=Xe.id}),Q.push(...M),O+=M.length,await new Promise(S=>setTimeout(S,200))}Q.length>0&&l(Q);const Me=new Date().toISOString();k(Me);const Vt=a==="zh"?`刷新完成!发现 ${O} 个新Release。`:`Refresh completed! Found ${O} new releases.`;alert(Vt)}catch(w){console.error("Refresh failed:",w),alert(a==="zh"?"Release刷新失败,请检查网络连接。":"Release refresh failed. Please check your network connection.")}finally{m(!1)}},pe=w=>{g(T=>T.includes(w)?T.filter(O=>O!==w):[...T,w]),_(1)},ce=()=>{u(""),g([]),_(1)},V=w=>{_(Math.max(1,Math.min(w,$)))},U=()=>{const T=[],O=[];for(let Q=Math.max(2,x-2);Q<=Math.min($-1,x+2);Q++)T.push(Q);return x-2>2?O.push(1,"..."):O.push(1),O.push(...T),x+2<$-1?O.push("...",$):$>1&&O.push($),O},y=w=>({windows:"fab fa-windows",macos:"fab fa-apple",linux:"fab fa-linux",android:"fab fa-android",ios:"fab fa-apple",universal:"fas fa-download"})[w]||"fas fa-download",E=w=>({windows:"text-blue-600 dark:text-blue-400",macos:"text-gray-600 dark:text-gray-400",linux:"text-yellow-600 dark:text-yellow-400",android:"text-green-600 dark:text-green-400",ios:"text-gray-600 dark:text-gray-400",universal:"text-purple-600 dark:text-purple-400"})[w]||"text-gray-600 dark:text-gray-400",A=(w,T=200)=>w.length<=T?w:w.substring(0,T)+"...",z=(w,T)=>a==="zh"?w:T;if(N.length===0){const w=n.size;return o.jsxs("div",{className:"text-center py-12",children:[o.jsx(xp,{className:"w-16 h-16 text-gray-400 dark:text-gray-600 mx-auto mb-4"}),o.jsx("h3",{className:"text-lg font-medium text-gray-900 dark:text-white mb-2",children:w===0?z("没有Release订阅","No Release Subscriptions"):z("没有最近的Release","No Recent Releases")}),o.jsx("p",{className:"text-gray-500 dark:text-gray-400 mb-6 max-w-md mx-auto",children:w===0?z("从仓库页面订阅仓库Release以在此查看更新。","Subscribe to repository releases from the Repositories tab to see updates here."):z(`您已订阅 ${w} 个仓库,但没有找到最近的Release。尝试同步以获取最新更新。`,`You're subscribed to ${w} repositories, but no recent releases were found. Try syncing to get the latest updates.`)}),w===0&&o.jsxs("div",{className:"bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-4 max-w-md mx-auto",children:[o.jsxs("div",{className:"flex items-center space-x-2 text-blue-700 dark:text-blue-300",children:[o.jsx(vo,{className:"w-5 h-5"}),o.jsx("span",{className:"font-medium",children:z("如何订阅:","How to subscribe:")})]}),o.jsx("p",{className:"text-sm text-blue-600 dark:text-blue-400 mt-2",children:z("转到仓库页面,点击任何仓库卡片上的铃铛图标以订阅其Release。","Go to the Repositories tab and click the bell icon on any repository card to subscribe to its releases.")})]})]})}return o.jsxs("div",{className:"max-w-7xl mx-auto",children:[o.jsxs("div",{className:"mb-8",children:[o.jsxs("div",{className:"flex items-center justify-between mb-4",children:[o.jsxs("div",{children:[o.jsx("h2",{className:"text-2xl font-bold text-gray-900 dark:text-white mb-2",children:z("Release时间线","Release Timeline")}),o.jsx("p",{className:"text-gray-600 dark:text-gray-400",children:z(`来自您的 ${n.size} 个订阅仓库的最新Release`,`Latest releases from your ${n.size} subscribed repositories`)})]}),o.jsxs("div",{className:"flex items-center space-x-3",children:[o.jsxs("div",{className:"flex items-center space-x-2",children:[o.jsx("button",{onClick:()=>b("compact"),className:`p-2 rounded-lg transition-colors ${p==="compact"?"bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300":"bg-gray-100 text-gray-500 dark:bg-gray-700 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600"}`,title:z("精简视图","Compact View"),children:o.jsx(ip,{className:"w-4 h-4"})}),o.jsx("button",{onClick:()=>b("detailed"),className:`p-2 rounded-lg transition-colors ${p==="detailed"?"bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300":"bg-gray-100 text-gray-500 dark:bg-gray-700 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600"}`,title:z("详细视图","Detailed View"),children:o.jsx(up,{className:"w-4 h-4"})})]}),v&&o.jsxs("span",{className:"text-sm text-gray-500 dark:text-gray-400",children:[z("上次刷新:","Last refresh:")," ",fa(new Date(v),{addSuffix:!0})]}),o.jsxs("button",{onClick:ue,disabled:h,className:"flex items-center space-x-2 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed",children:[o.jsx(dd,{className:`w-4 h-4 ${h?"animate-spin":""}`}),o.jsx("span",{children:h?z("刷新中...","Refreshing..."):z("刷新","Refresh")})]})]})]}),o.jsxs("div",{className:"bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-4 mb-6",children:[o.jsxs("div",{className:"relative mb-4",children:[o.jsx(wo,{className:"absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-5 h-5"}),o.jsx("input",{type:"text",placeholder:z("搜索Release...","Search releases..."),value:i,onChange:w=>{u(w.target.value),_(1)},className:"w-full pl-10 pr-10 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-white dark:bg-gray-700 text-gray-900 dark:text-white"}),i&&o.jsx("button",{onClick:()=>{u(""),_(1)},className:"absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300",children:o.jsx(Yt,{className:"w-4 h-4"})})]}),Y.length>0&&o.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[o.jsx("span",{className:"text-sm font-medium text-gray-700 dark:text-gray-300 mr-2",children:z("平台:","Platforms:")}),Y.map(w=>o.jsxs("button",{onClick:()=>pe(w),className:`flex items-center space-x-2 px-3 py-1.5 rounded-lg text-sm transition-colors ${d.includes(w)?"bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300":"bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600"}`,children:[o.jsx("i",{className:`${y(w)} w-4 h-4`}),o.jsx("span",{className:"capitalize",children:w})]},w)),(i||d.length>0)&&o.jsxs("button",{onClick:ce,className:"flex items-center space-x-1 px-3 py-1.5 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200 transition-colors",children:[o.jsx(Yt,{className:"w-4 h-4"}),o.jsx("span",{children:z("清除","Clear")})]})]})]}),o.jsxs("div",{className:"flex items-center justify-between mb-6",children:[o.jsxs("div",{className:"flex items-center space-x-4",children:[o.jsx("span",{className:"text-sm text-gray-600 dark:text-gray-400",children:z(`显示 ${D+1}-${Math.min(D+f,R.length)} 共 ${R.length} 个Release`,`Showing ${D+1}-${Math.min(D+f,R.length)} of ${R.length} releases`)}),(i||d.length>0)&&o.jsxs("span",{className:"text-sm text-blue-600 dark:text-blue-400",children:["(",z("已筛选","filtered"),")"]})]}),o.jsxs("div",{className:"flex items-center space-x-4",children:[o.jsxs("div",{className:"flex items-center space-x-2",children:[o.jsx("span",{className:"text-sm text-gray-600 dark:text-gray-400",children:z("每页:","Per page:")}),o.jsxs("select",{value:f,onChange:w=>{c(Number(w.target.value)),_(1)},className:"px-3 py-1 border border-gray-300 dark:border-gray-600 rounded bg-white dark:bg-gray-700 text-gray-900 dark:text-white text-sm",children:[o.jsx("option",{value:50,children:"50"}),o.jsx("option",{value:100,children:"100"}),o.jsx("option",{value:200,children:"200"}),o.jsx("option",{value:500,children:"500"})]})]}),$>1&&o.jsxs("div",{className:"flex items-center space-x-1",children:[o.jsx("button",{onClick:()=>V(1),disabled:x===1,className:"p-2 rounded-lg bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600 disabled:opacity-50 disabled:cursor-not-allowed",children:o.jsx(Ri,{className:"w-4 h-4"})}),o.jsx("button",{onClick:()=>V(x-1),disabled:x===1,className:"p-2 rounded-lg bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600 disabled:opacity-50 disabled:cursor-not-allowed",children:o.jsx(Di,{className:"w-4 h-4"})}),U().map((w,T)=>o.jsx("button",{onClick:()=>typeof w=="number"?V(w):void 0,disabled:typeof w!="number",className:`px-3 py-2 rounded-lg text-sm ${w===x?"bg-blue-600 text-white":typeof w=="number"?"bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600":"text-gray-400 cursor-default"}`,children:w},T)),o.jsx("button",{onClick:()=>V(x+1),disabled:x===$,className:"p-2 rounded-lg bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600 disabled:opacity-50 disabled:cursor-not-allowed",children:o.jsx(Mi,{className:"w-4 h-4"})}),o.jsx("button",{onClick:()=>V($),disabled:x===$,className:"p-2 rounded-lg bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600 disabled:opacity-50 disabled:cursor-not-allowed",children:o.jsx(Ti,{className:"w-4 h-4"})})]})]})]})]}),o.jsx("div",{className:"space-y-4",children:q.map(w=>{const T=j(w);return o.jsx("div",{className:"bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 hover:shadow-lg transition-shadow",children:p==="detailed"?o.jsxs("div",{className:"p-6",children:[o.jsxs("div",{className:"flex items-start justify-between mb-4",children:[o.jsxs("div",{className:"flex items-center space-x-3 flex-1 min-w-0",children:[o.jsx("div",{className:"flex items-center justify-center w-10 h-10 bg-green-100 dark:bg-green-900 rounded-lg flex-shrink-0",children:o.jsx(Ii,{className:"w-5 h-5 text-green-600 dark:text-green-400"})}),o.jsxs("div",{className:"min-w-0 flex-1",children:[o.jsxs("h4",{className:"font-semibold text-gray-900 dark:text-white truncate",children:[w.repository.name," ",w.tag_name]}),o.jsx("p",{className:"text-sm text-gray-500 dark:text-gray-400 truncate",children:w.repository.full_name})]})]}),o.jsxs("div",{className:"flex items-center space-x-2 flex-shrink-0",children:[o.jsx("span",{className:"text-sm text-gray-500 dark:text-gray-400",children:fa(new Date(w.published_at),{addSuffix:!0})}),o.jsx("a",{href:w.html_url,target:"_blank",rel:"noopener noreferrer",className:"p-2 rounded-lg bg-gray-100 text-gray-500 dark:bg-gray-700 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors",title:z("在GitHub上查看","View on GitHub"),children:o.jsx(Sl,{className:"w-4 h-4"})})]})]}),w.name&&w.name!==w.tag_name&&o.jsx("h5",{className:"font-medium text-gray-800 dark:text-gray-200 mb-2",children:w.name}),T.length>0&&o.jsxs("div",{className:"mb-4",children:[o.jsx("h6",{className:"text-sm font-medium text-gray-700 dark:text-gray-300 mb-2",children:z("下载:","Downloads:")}),o.jsx("div",{className:"flex flex-wrap gap-2",children:T.map((O,Q)=>o.jsxs("a",{href:O.url,target:"_blank",rel:"noopener noreferrer",className:"flex items-center space-x-2 px-3 py-2 bg-gray-100 dark:bg-gray-700 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors text-sm",title:O.name,children:[o.jsx("div",{className:"flex items-center space-x-1",children:O.platforms.map((G,ne)=>o.jsx("i",{className:`${y(G)} w-4 h-4 ${E(G)}`,title:G},ne))}),o.jsx("span",{className:"truncate max-w-32",children:O.name})]},Q))})]}),w.body&&o.jsxs("div",{className:"prose prose-sm dark:prose-invert max-w-none",children:[o.jsx("div",{className:"text-gray-700 dark:text-gray-300 whitespace-pre-wrap",children:A(w.body)}),w.body.length>200&&o.jsx("a",{href:w.html_url,target:"_blank",rel:"noopener noreferrer",className:"text-blue-600 dark:text-blue-400 hover:underline text-sm mt-2 inline-block",children:z("阅读完整Release说明 →","Read full release notes →")})]})]}):o.jsx("div",{className:"p-4",children:o.jsxs("div",{className:"grid grid-cols-12 gap-4 items-center",children:[o.jsx("div",{className:"col-span-3 min-w-0",children:o.jsxs("div",{className:"flex items-center space-x-2",children:[o.jsx("div",{className:"w-6 h-6 bg-green-100 dark:bg-green-900 rounded flex items-center justify-center flex-shrink-0",children:o.jsx(Ii,{className:"w-3 h-3 text-green-600 dark:text-green-400"})}),o.jsxs("div",{className:"min-w-0 flex-1",children:[o.jsx("p",{className:"font-medium text-gray-900 dark:text-white text-sm truncate",children:w.repository.name}),o.jsx("p",{className:"text-xs text-gray-500 dark:text-gray-400 truncate",children:w.tag_name})]})]})}),o.jsx("div",{className:"col-span-3 min-w-0",children:o.jsx("p",{className:"text-sm text-gray-900 dark:text-white truncate",title:w.name||w.tag_name,children:w.name||w.tag_name})}),o.jsx("div",{className:"col-span-4 min-w-0",children:T.length>0?o.jsxs("div",{className:"flex flex-wrap gap-1",children:[T.slice(0,6).map((O,Q)=>o.jsxs("a",{href:O.url,target:"_blank",rel:"noopener noreferrer",className:"flex items-center space-x-1 px-2 py-1 bg-gray-100 dark:bg-gray-700 rounded hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors",title:`${O.name} (${O.platforms.join(", ")})`,children:[o.jsx("div",{className:"flex items-center space-x-0.5",children:O.platforms.map((G,ne)=>o.jsx("i",{className:`${y(G)} w-3 h-3 ${E(G)}`,title:G},ne))}),o.jsx("span",{className:"text-xs text-gray-700 dark:text-gray-300 truncate max-w-16",children:O.name.split(".").pop()||O.name})]},Q)),T.length>6&&o.jsxs("span",{className:"text-xs text-gray-500 dark:text-gray-400 px-2 py-1",children:["+",T.length-6]})]}):o.jsx("span",{className:"text-xs text-gray-400 dark:text-gray-500",children:z("无下载","No downloads")})}),o.jsxs("div",{className:"col-span-2 flex items-center justify-end space-x-2",children:[o.jsx("span",{className:"text-xs text-gray-500 dark:text-gray-400",children:fa(new Date(w.published_at),{addSuffix:!0})}),o.jsx("a",{href:w.html_url,target:"_blank",rel:"noopener noreferrer",className:"p-1.5 rounded bg-gray-100 text-gray-500 dark:bg-gray-700 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors",title:z("在GitHub上查看","View on GitHub"),children:o.jsx(Sl,{className:"w-3 h-3"})})]})]})})},w.id)})}),$>1&&o.jsx("div",{className:"flex items-center justify-center mt-8",children:o.jsxs("div",{className:"flex items-center space-x-1",children:[o.jsx("button",{onClick:()=>V(1),disabled:x===1,className:"p-2 rounded-lg bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600 disabled:opacity-50 disabled:cursor-not-allowed",children:o.jsx(Ri,{className:"w-4 h-4"})}),o.jsx("button",{onClick:()=>V(x-1),disabled:x===1,className:"p-2 rounded-lg bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600 disabled:opacity-50 disabled:cursor-not-allowed",children:o.jsx(Di,{className:"w-4 h-4"})}),U().map((w,T)=>o.jsx("button",{onClick:()=>typeof w=="number"?V(w):void 0,disabled:typeof w!="number",className:`px-3 py-2 rounded-lg text-sm ${w===x?"bg-blue-600 text-white":typeof w=="number"?"bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600":"text-gray-400 cursor-default"}`,children:w},T)),o.jsx("button",{onClick:()=>V(x+1),disabled:x===$,className:"p-2 rounded-lg bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600 disabled:opacity-50 disabled:cursor-not-allowed",children:o.jsx(Mi,{className:"w-4 h-4"})}),o.jsx("button",{onClick:()=>V($),disabled:x===$,className:"p-2 rounded-lg bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600 disabled:opacity-50 disabled:cursor-not-allowed",children:o.jsx(Ti,{className:"w-4 h-4"})})]})})]})};class Jr{constructor(t){this.config=t}getAuthHeader(){return`Basic ${btoa(`${this.config.username}:${this.config.password}`)}`}getFullPath(t){const n=this.config.path.endsWith("/")?this.config.path:`${this.config.path}/`;return`${this.config.url}${n}${t}`}handleNetworkError(t,n){throw console.error(`WebDAV ${n} failed:`,t),t.name==="TypeError"&&t.message.includes("Failed to fetch")||t.message&&t.message.includes("NetworkError when attempting to fetch resource")||t.name==="NetworkError"||t.message&&t.message.includes("NetworkError")?new Error(`CORS策略阻止了连接到WebDAV服务器。 + +这是一个常见的浏览器安全限制。要解决此问题,您需要: + +1. 在WebDAV服务器上配置CORS头: + • Access-Control-Allow-Origin: ${window.location.origin} + • Access-Control-Allow-Methods: GET, PUT, PROPFIND, HEAD, OPTIONS, MKCOL + • Access-Control-Allow-Headers: Authorization, Content-Type, Depth + +2. 常见WebDAV服务器配置示例: + + Apache (.htaccess): + Header always set Access-Control-Allow-Origin "${window.location.origin}" + Header always set Access-Control-Allow-Methods "GET, PUT, PROPFIND, HEAD, OPTIONS, MKCOL" + Header always set Access-Control-Allow-Headers "Authorization, Content-Type, Depth" + + Nginx: + add_header Access-Control-Allow-Origin "${window.location.origin}"; + add_header Access-Control-Allow-Methods "GET, PUT, PROPFIND, HEAD, OPTIONS, MKCOL"; + add_header Access-Control-Allow-Headers "Authorization, Content-Type, Depth"; + +3. 其他检查项: + • 确保WebDAV服务器正在运行 + • 验证URL格式正确(包含协议 http:// 或 https://) + • 如果应用使用HTTPS,WebDAV服务器也应使用HTTPS + +技术详情: ${t.message}`):new Error(`WebDAV ${n} 失败: ${t.message||"未知错误"}`)}async testConnection(){try{if(!this.config.url.startsWith("http://")&&!this.config.url.startsWith("https://"))throw new Error("WebDAV URL必须以 http:// 或 https:// 开头");const t=new AbortController,n=setTimeout(()=>t.abort(),1e4);try{const r=await fetch(this.config.url,{method:"OPTIONS",headers:{Authorization:this.getAuthHeader()},signal:t.signal});if(clearTimeout(n),r.ok)return!0;const a=await fetch(this.config.url,{method:"PROPFIND",headers:{Authorization:this.getAuthHeader(),Depth:"0"}});return a.ok||a.status===207}catch(r){throw clearTimeout(n),r.name==="AbortError"?new Error("连接超时。请检查WebDAV服务器是否可访问。"):r}}catch(t){this.handleNetworkError(t,"连接测试")}}async uploadFile(t,n){try{if(!this.config.url.startsWith("http://")&&!this.config.url.startsWith("https://"))throw new Error("WebDAV URL必须以 http:// 或 https:// 开头");await this.ensureDirectoryExists();const r=new AbortController,a=setTimeout(()=>r.abort(),3e4);try{const s=await fetch(this.getFullPath(t),{method:"PUT",headers:{Authorization:this.getAuthHeader(),"Content-Type":"application/json"},body:n,signal:r.signal});if(clearTimeout(a),!s.ok)throw s.status===401?new Error("身份验证失败。请检查用户名和密码。"):s.status===403?new Error("访问被拒绝。请检查指定路径的权限。"):s.status===404?new Error("路径未找到。请验证WebDAV URL和路径是否正确。"):s.status===507?new Error("服务器存储空间不足。"):new Error(`上传失败,HTTP状态码 ${s.status}: ${s.statusText}`);return!0}catch(s){throw clearTimeout(a),s.name==="AbortError"?new Error("上传超时。文件可能太大或网络连接缓慢。"):s}}catch(r){if(r.message.includes("身份验证失败")||r.message.includes("访问被拒绝")||r.message.includes("路径未找到")||r.message.includes("存储空间不足")||r.message.includes("上传失败,HTTP状态码")||r.message.includes("上传超时")||r.message.includes("WebDAV URL必须"))throw r;this.handleNetworkError(r,"上传")}}async ensureDirectoryExists(){try{if(!this.config.path||this.config.path==="/")return;const t=this.config.url+this.config.path,n=await fetch(t,{method:"MKCOL",headers:{Authorization:this.getAuthHeader()}});!n.ok&&n.status!==405&&console.warn("无法创建目录,可能已存在或权限不足")}catch(t){console.warn("目录创建检查失败:",t)}}async downloadFile(t){try{const n=new AbortController,r=setTimeout(()=>n.abort(),3e4);try{const a=await fetch(this.getFullPath(t),{method:"GET",headers:{Authorization:this.getAuthHeader()},signal:n.signal});if(clearTimeout(r),a.ok)return await a.text();if(a.status===404)return null;throw a.status===401?new Error("身份验证失败。请检查用户名和密码。"):new Error(`下载失败,HTTP状态码 ${a.status}: ${a.statusText}`)}catch(a){throw clearTimeout(r),a.name==="AbortError"?new Error("下载超时。请检查网络连接。"):a}}catch(n){if(n.message.includes("身份验证失败")||n.message.includes("下载超时"))throw n;if(n.message.includes("HTTP 404"))return null;this.handleNetworkError(n,"下载")}}async fileExists(t){try{const n=new AbortController,r=setTimeout(()=>n.abort(),1e4),a=await fetch(this.getFullPath(t),{method:"HEAD",headers:{Authorization:this.getAuthHeader()},signal:n.signal});return clearTimeout(r),a.ok}catch(n){return console.error("WebDAV文件检查失败:",n),!1}}async listFiles(){try{const t=new AbortController,n=setTimeout(()=>t.abort(),15e3);try{const r=await fetch(this.config.url+this.config.path,{method:"PROPFIND",headers:{Authorization:this.getAuthHeader(),Depth:"1","Content-Type":"application/xml"},body:` + + + + + + + `,signal:t.signal});if(clearTimeout(n),r.ok||r.status===207){const s=(await r.text()).match(/([^<]+)<\/D:displayname>/g);if(s)return s.map(l=>l.replace(/<\/?D:displayname>/g,"")).filter(l=>l.endsWith(".json"))}else throw r.status===401?new Error("身份验证失败。请检查用户名和密码。"):new Error(`列出文件失败,HTTP状态码 ${r.status}: ${r.statusText}`);return[]}catch(r){throw clearTimeout(n),r.name==="AbortError"?new Error("列出文件超时。请检查网络连接。"):r}}catch(t){if(t.message.includes("身份验证失败")||t.message.includes("列出文件超时"))throw t;this.handleNetworkError(t,"列出文件")}}static validateConfig(t){const n=[];return t.url?!t.url.startsWith("http://")&&!t.url.startsWith("https://")&&n.push("WebDAV URL必须以 http:// 或 https:// 开头"):n.push("WebDAV URL是必需的"),t.username||n.push("用户名是必需的"),t.password||n.push("密码是必需的"),t.path?t.path.startsWith("/")||n.push("路径必须以 / 开头"):n.push("路径是必需的"),n}async getServerInfo(){try{const t=await fetch(this.config.url,{method:"OPTIONS",headers:{Authorization:this.getAuthHeader()}});if(t.ok)return{server:t.headers.get("Server")||void 0,davLevel:t.headers.get("DAV")||void 0}}catch(t){console.warn("无法获取服务器信息:",t)}return{}}}const fg=()=>{const{aiConfigs:e,activeAIConfig:t,webdavConfigs:n,activeWebDAVConfig:r,lastBackup:a,githubToken:s,language:l,repositories:i,releaseSubscriptions:u,addAIConfig:d,updateAIConfig:g,deleteAIConfig:h,setActiveAIConfig:m,addWebDAVConfig:v,updateWebDAVConfig:k,deleteWebDAVConfig:x,setActiveWebDAVConfig:_,setLastBackup:f,setGitHubToken:c,setLanguage:p,setRepositories:b,setReleases:P}=Wt(),[j,N]=W.useState(!1),[R,$]=W.useState(!1);W.useState(null);const[D,q]=W.useState(null),[Y,ue]=W.useState(null),[pe,ce]=W.useState("idle"),[V,U]=W.useState({name:"",baseUrl:"https://api.openai.com/v1",apiKey:"",model:"gpt-3.5-turbo"}),[y,E]=W.useState({name:"",url:"",username:"",password:"",path:"/github-stars-backup"}),A=W.useRef(null),z=()=>{if(!V.name||!V.baseUrl||!V.apiKey||!V.model){alert(l==="zh"?"请填写所有字段":"Please fill in all fields");return}const S={id:Date.now().toString(),name:V.name,baseUrl:V.baseUrl,apiKey:V.apiKey,model:V.model,isActive:e.length===0};d(S),S.isActive&&m(S.id),U({name:"",baseUrl:"https://api.openai.com/v1",apiKey:"",model:"gpt-3.5-turbo"}),N(!1)},w=()=>{const S=Jr.validateConfig(y);if(S.length>0){alert(S.join(` +`));return}const L={id:Date.now().toString(),name:y.name,url:y.url,username:y.username,password:y.password,path:y.path,isActive:n.length===0};v(L),L.isActive&&_(L.id),E({name:"",url:"",username:"",password:"",path:"/github-stars-backup"}),$(!1)},T=async S=>{q(S.id);try{const oe=await new es(S,l).testConnection();alert(oe?l==="zh"?"✅ 连接成功!AI配置正常工作。":"✅ Connection successful! AI configuration is working.":l==="zh"?"❌ 连接失败。请检查您的配置。":"❌ Connection failed. Please check your configuration.")}catch(L){const oe=l==="zh"?`❌ 连接失败: ${L instanceof Error?L.message:"未知错误"}`:`❌ Connection failed: ${L instanceof Error?L.message:"Unknown error"}`;alert(oe)}finally{q(null)}},O=async S=>{ue(S.id);try{const L=new Jr(S);if(await L.testConnection()){const ye=await L.getServerInfo();let X=l==="zh"?"✅ WebDAV连接成功!":"✅ WebDAV connection successful!";ye.server&&(X+=` +${l==="zh"?"服务器":"Server"}: ${ye.server}`),ye.davLevel&&(X+=` +${l==="zh"?"DAV级别":"DAV Level"}: ${ye.davLevel}`),alert(X)}else alert(l==="zh"?"❌ WebDAV连接失败。请检查您的配置。":"❌ WebDAV connection failed. Please check your configuration.")}catch(L){const oe=l==="zh"?`❌ WebDAV连接测试失败: + +${L instanceof Error?L.message:"未知错误"}`:`❌ WebDAV connection test failed: + +${L instanceof Error?L.message:"Unknown error"}`;alert(oe)}finally{ue(null)}},Q=S=>{e.forEach(L=>{g(L.id,{isActive:L.id===S})}),m(S)},G=S=>{n.forEach(L=>{k(L.id,{isActive:L.id===S})}),_(S)},ne=async()=>{const S=n.find(L=>L.id===r);if(!S){alert(l==="zh"?"请先配置并激活WebDAV服务。":"Please configure and activate WebDAV service first.");return}ce("backing-up");try{const L=new Jr(S),oe={version:"1.0",timestamp:new Date().toISOString(),repositories:i,aiConfigs:e,webdavConfigs:n,releaseSubscriptions:Array.from(u),settings:{language:l,lastBackup:a,activeAIConfig:t,activeWebDAVConfig:r}},ye=`github-stars-backup-${new Date().toISOString().split("T")[0]}.json`,X=JSON.stringify(oe,null,2);await L.uploadFile(ye,X);const ct=new Date().toISOString();f(ct),alert(l==="zh"?`✅ 备份成功! +文件名: ${ye} +备份时间: ${new Date(ct).toLocaleString()}`:`✅ Backup successful! +Filename: ${ye} +Backup time: ${new Date(ct).toLocaleString()}`)}catch(L){console.error("Backup failed:",L);const oe=l==="zh"?`❌ 备份失败: + +${L instanceof Error?L.message:"未知错误"}`:`❌ Backup failed: + +${L instanceof Error?L.message:"Unknown error"}`;alert(oe)}finally{ce("idle")}},Me=async()=>{var oe,ye;const S=n.find(X=>X.id===r);if(!S){alert(l==="zh"?"请先配置并激活WebDAV服务。":"Please configure and activate WebDAV service first.");return}if(confirm(l==="zh"?`⚠️ 恢复操作将覆盖当前的仓库数据和配置。 + +确定要继续吗?`:`⚠️ Restore operation will overwrite current repository data and configurations. + +Are you sure you want to continue?`)){ce("restoring");try{const X=new Jr(S),In=(await X.listFiles()).filter(de=>de.startsWith("github-stars-backup-"));if(In.length===0){alert(l==="zh"?"没有找到备份文件。":"No backup files found.");return}const an=In.sort().reverse()[0],Ln=await X.downloadFile(an);if(!Ln){alert(l==="zh"?"无法读取备份文件。":"Unable to read backup file.");return}const Ne=JSON.parse(Ln);Ne.repositories&&b(Ne.repositories),Ne.releases&&P(Ne.releases),alert(l==="zh"?`✅ 恢复成功! +备份文件: ${an} +备份时间: ${new Date(Ne.timestamp).toLocaleString()} +仓库数量: ${((oe=Ne.repositories)==null?void 0:oe.length)||0} + +页面将刷新以应用更改。`:`✅ Restore successful! +Backup file: ${an} +Backup time: ${new Date(Ne.timestamp).toLocaleString()} +Repositories: ${((ye=Ne.repositories)==null?void 0:ye.length)||0} + +Page will refresh to apply changes.`),setTimeout(()=>window.location.reload(),2e3)}catch(X){console.error("Restore failed:",X);const ct=l==="zh"?`❌ 恢复失败: + +${X instanceof Error?X.message:"未知错误"}`:`❌ Restore failed: + +${X instanceof Error?X.message:"Unknown error"}`;alert(ct)}finally{ce("idle")}}},Vt=()=>{ce("exporting");try{const S={version:"1.0",timestamp:new Date().toISOString(),aiConfigs:e,webdavConfigs:n,settings:{language:l,activeAIConfig:t,activeWebDAVConfig:r}},L=JSON.stringify(S,null,2),oe=new Blob([L],{type:"application/json"}),ye=URL.createObjectURL(oe),X=document.createElement("a");X.href=ye,X.download=`github-stars-config-${new Date().toISOString().split("T")[0]}.json`,document.body.appendChild(X),X.click(),document.body.removeChild(X),URL.revokeObjectURL(ye),alert(l==="zh"?`✅ 配置导出成功!文件已下载到您的设备。 + +注意:此文件包含敏感信息(API密钥、密码),请妥善保管。`:`✅ Configuration exported successfully! File has been downloaded to your device. + +Note: This file contains sensitive information (API keys, passwords), please keep it secure.`)}catch(S){console.error("Export failed:",S),alert(l==="zh"?`❌ 导出失败: ${S instanceof Error?S.message:"未知错误"}`:`❌ Export failed: ${S instanceof Error?S.message:"Unknown error"}`)}finally{ce("idle")}},Xe=()=>{var S;(S=A.current)==null||S.click()},Dr=async S=>{var oe,ye,X,ct,In,an,Ln;const L=(oe=S.target.files)==null?void 0:oe[0];if(L){ce("importing");try{const Ne=await L.text(),de=JSON.parse(Ne);if(!de.version||!de.timestamp)throw new Error(l==="zh"?"无效的配置文件格式":"Invalid configuration file format");const vd=l==="zh"?`⚠️ 导入配置将覆盖当前的AI和WebDAV配置。 + +配置文件信息: +• 创建时间: ${new Date(de.timestamp).toLocaleString()} +• AI配置: ${((ye=de.aiConfigs)==null?void 0:ye.length)||0} 个 +• WebDAV配置: ${((X=de.webdavConfigs)==null?void 0:X.length)||0} 个 + +确定要继续吗?`:`⚠️ Importing configuration will overwrite current AI and WebDAV configurations. + +Configuration file info: +• Created: ${new Date(de.timestamp).toLocaleString()} +• AI configs: ${((ct=de.aiConfigs)==null?void 0:ct.length)||0} +• WebDAV configs: ${((In=de.webdavConfigs)==null?void 0:In.length)||0} + +Are you sure you want to continue?`;if(!confirm(vd))return;de.aiConfigs&&Array.isArray(de.aiConfigs)&&de.aiConfigs.forEach(re=>{if(re.name&&re.baseUrl&&re.model){const ns={id:Date.now().toString()+Math.random().toString(36).substr(2,9),name:`${re.name} (导入)`,baseUrl:re.baseUrl,apiKey:re.apiKey||"",model:re.model,isActive:!1};d(ns)}}),de.webdavConfigs&&Array.isArray(de.webdavConfigs)&&de.webdavConfigs.forEach(re=>{if(re.name&&re.url&&re.username&&re.path){const ns={id:Date.now().toString()+Math.random().toString(36).substr(2,9),name:`${re.name} (导入)`,url:re.url,username:re.username,password:re.password||"",path:re.path,isActive:!1};v(ns)}}),de.settings&&de.settings.language&&p(de.settings.language);const bo=((an=de.aiConfigs)==null?void 0:an.some(re=>re.apiKey&&re.apiKey!=="***"))||((Ln=de.webdavConfigs)==null?void 0:Ln.some(re=>re.password&&re.password!=="***"));alert(l==="zh"?`✅ 配置导入成功!${bo?` + +所有配置信息(包括API密钥和密码)已完整导入。`:` + +注意:如果配置中缺少API密钥和密码,请手动补充。`}`:`✅ Configuration imported successfully!${bo?` + +All configuration information (including API keys and passwords) has been imported completely.`:` + +Note: If API keys and passwords are missing from the configuration, please add them manually.`}`)}catch(Ne){console.error("Import failed:",Ne),alert(l==="zh"?`❌ 导入失败: ${Ne instanceof Error?Ne.message:"未知错误"}`:`❌ Import failed: ${Ne instanceof Error?Ne.message:"Unknown error"}`)}finally{ce("idle"),A.current&&(A.current.value="")}}},Mr=[{name:"OpenAI GPT-3.5",baseUrl:"https://api.openai.com/v1",model:"gpt-3.5-turbo"},{name:"OpenAI GPT-4",baseUrl:"https://api.openai.com/v1",model:"gpt-4"},{name:"Anthropic Claude",baseUrl:"https://api.anthropic.com/v1",model:"claude-3-sonnet-20240229"}],ts=[{name:"Nextcloud",url:"https://your-nextcloud.com/remote.php/dav/files/username",path:"/github-stars-backup"},{name:"ownCloud",url:"https://your-owncloud.com/remote.php/webdav",path:"/github-stars-backup"},{name:"坚果云",url:"https://dav.jianguoyun.com/dav",path:"/github-stars-backup"}],M=(S,L)=>l==="zh"?S:L;return o.jsxs("div",{className:"max-w-4xl mx-auto space-y-8",children:[o.jsxs("div",{className:"mb-8",children:[o.jsx("h2",{className:"text-2xl font-bold text-gray-900 dark:text-white mb-2",children:M("设置","Settings")}),o.jsx("p",{className:"text-gray-600 dark:text-gray-400",children:M("配置您的AI服务、WebDAV备份和应用程序偏好","Configure your AI services, WebDAV backup, and application preferences")})]}),o.jsxs("div",{className:"bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-6",children:[o.jsxs("div",{className:"flex items-center space-x-3 mb-4",children:[o.jsx("div",{className:"flex items-center justify-center w-10 h-10 bg-indigo-100 dark:bg-indigo-900 rounded-lg",children:o.jsx(fd,{className:"w-5 h-5 text-indigo-600 dark:text-indigo-400"})}),o.jsxs("div",{children:[o.jsx("h3",{className:"text-lg font-semibold text-gray-900 dark:text-white",children:M("配置管理","Configuration Management")}),o.jsx("p",{className:"text-sm text-gray-500 dark:text-gray-400",children:M("导入和导出您的应用配置","Import and export your application configurations")})]})]}),o.jsxs("div",{className:"flex flex-col sm:flex-row gap-4",children:[o.jsxs("button",{onClick:Vt,disabled:pe!=="idle",className:"flex items-center justify-center space-x-2 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed",children:[o.jsx(cp,{className:"w-4 h-4"}),o.jsx("span",{children:pe==="exporting"?M("导出中...","Exporting..."):M("导出配置","Export Configuration")})]}),o.jsxs("button",{onClick:Xe,disabled:pe!=="idle",className:"flex items-center justify-center space-x-2 px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed",children:[o.jsx(dp,{className:"w-4 h-4"}),o.jsx("span",{children:pe==="importing"?M("导入中...","Importing..."):M("导入配置","Import Configuration")})]})]}),o.jsx("input",{ref:A,type:"file",accept:".json",onChange:Dr,className:"hidden"}),o.jsx("div",{className:"mt-4 p-3 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg",children:o.jsxs("div",{className:"flex items-start space-x-2",children:[o.jsx(gp,{className:"w-5 h-5 text-blue-600 dark:text-blue-400 flex-shrink-0 mt-0.5"}),o.jsxs("div",{className:"text-sm text-blue-700 dark:text-blue-300",children:[o.jsx("p",{className:"font-medium mb-1",children:M("配置导入导出说明","Configuration Import/Export Notes")}),o.jsxs("ul",{className:"list-disc list-inside space-y-1 text-xs",children:[o.jsx("li",{children:M("导出的配置文件包含完整的API密钥和密码信息","Exported configuration files contain complete API keys and password information")}),o.jsx("li",{children:M("请妥善保管导出的配置文件,避免泄露敏感信息","Please keep exported configuration files secure to avoid leaking sensitive information")}),o.jsx("li",{children:M("导入配置将完整恢复所有设置,包括敏感信息","Importing configuration will completely restore all settings, including sensitive information")}),o.jsx("li",{children:M("建议定期导出配置作为备份","It is recommended to export configuration regularly as backup")})]})]})]})})]}),o.jsxs("div",{className:"bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-6",children:[o.jsxs("div",{className:"flex items-center space-x-3 mb-4",children:[o.jsx("div",{className:"flex items-center justify-center w-10 h-10 bg-blue-100 dark:bg-blue-900 rounded-lg",children:o.jsx(ud,{className:"w-5 h-5 text-blue-600 dark:text-blue-400"})}),o.jsxs("div",{children:[o.jsx("h3",{className:"text-lg font-semibold text-gray-900 dark:text-white",children:M("语言设置","Language Settings")}),o.jsx("p",{className:"text-sm text-gray-500 dark:text-gray-400",children:M("选择界面语言和AI分析语言","Choose interface language and AI analysis language")})]})]}),o.jsxs("div",{className:"space-y-3",children:[o.jsxs("div",{children:[o.jsx("label",{className:"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2",children:M("界面语言","Interface Language")}),o.jsxs("select",{value:l,onChange:S=>p(S.target.value),className:"w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white",children:[o.jsx("option",{value:"zh",children:"中文"}),o.jsx("option",{value:"en",children:"English"})]})]}),o.jsx("p",{className:"text-xs text-gray-500 dark:text-gray-400",children:M("此设置将影响界面显示语言和AI分析生成的标签、描述的语言。","This setting affects the interface display language and the language of AI-generated tags and descriptions.")})]})]}),o.jsxs("div",{className:"bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-6",children:[o.jsxs("div",{className:"flex items-center space-x-3 mb-4",children:[o.jsx("div",{className:"flex items-center justify-center w-10 h-10 bg-gray-100 dark:bg-gray-700 rounded-lg",children:o.jsx(cd,{className:"w-5 h-5 text-gray-600 dark:text-gray-400"})}),o.jsxs("div",{children:[o.jsx("h3",{className:"text-lg font-semibold text-gray-900 dark:text-white",children:M("GitHub访问令牌","GitHub Access Token")}),o.jsx("p",{className:"text-sm text-gray-500 dark:text-gray-400",children:M("用于GitHub API的个人访问令牌","Personal access token for GitHub API")})]})]}),o.jsxs("div",{className:"space-y-3",children:[o.jsxs("div",{className:"flex items-center space-x-3",children:[o.jsx("input",{type:"password",placeholder:"ghp_xxxxxxxxxxxxxxxxxxxx",value:s||"",onChange:S=>c(S.target.value),className:"flex-1 px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white"}),o.jsx("span",{className:`px-3 py-2 rounded-lg text-sm ${s?"bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-300":"bg-red-100 text-red-700 dark:bg-red-900 dark:text-red-300"}`,children:s?M("已连接","Connected"):M("未设置","Not Set")})]}),o.jsxs("p",{className:"text-xs text-gray-500 dark:text-gray-400",children:[M("在","Create a personal access token at")," ",o.jsx("a",{href:"https://github.com/settings/tokens",target:"_blank",rel:"noopener noreferrer",className:"text-blue-600 dark:text-blue-400 hover:underline",children:M("GitHub设置","GitHub Settings")})," ",M("创建个人访问令牌,需要'repo'和'user'权限。","with 'repo' and 'user' scopes.")]})]})]}),o.jsxs("div",{className:"bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-6",children:[o.jsxs("div",{className:"flex items-center justify-between mb-6",children:[o.jsxs("div",{className:"flex items-center space-x-3",children:[o.jsx("div",{className:"flex items-center justify-center w-10 h-10 bg-green-100 dark:bg-green-900 rounded-lg",children:o.jsx(ap,{className:"w-5 h-5 text-green-600 dark:text-green-400"})}),o.jsxs("div",{children:[o.jsx("h3",{className:"text-lg font-semibold text-gray-900 dark:text-white",children:M("WebDAV备份","WebDAV Backup")}),o.jsx("p",{className:"text-sm text-gray-500 dark:text-gray-400",children:M("配置WebDAV服务器以备份和恢复数据","Configure WebDAV server for data backup and restore")})]})]}),o.jsxs("button",{onClick:()=>$(!0),className:"flex items-center space-x-2 px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors",children:[o.jsx(Li,{className:"w-4 h-4"}),o.jsx("span",{children:M("添加WebDAV","Add WebDAV")})]})]}),n.length>0&&o.jsxs("div",{className:"mb-6 p-4 bg-gray-50 dark:bg-gray-700 rounded-lg",children:[o.jsxs("div",{className:"flex items-center justify-between mb-4",children:[o.jsxs("div",{className:"flex items-center space-x-3",children:[o.jsx("div",{className:`w-3 h-3 rounded-full ${r?"bg-green-500":"bg-gray-400"}`}),o.jsx("span",{className:"text-sm font-medium text-gray-900 dark:text-white",children:r?M("WebDAV已配置","WebDAV Configured"):M("WebDAV未激活","WebDAV Not Active")}),a&&o.jsxs("span",{className:"text-xs text-gray-500 dark:text-gray-400",children:[M("上次备份:","Last backup:")," ",new Date(a).toLocaleString()]})]}),o.jsxs("div",{className:"flex items-center space-x-2",children:[o.jsxs("button",{onClick:ne,disabled:!r||pe!=="idle",className:"flex items-center space-x-2 px-3 py-1.5 bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300 rounded-lg hover:bg-blue-200 dark:hover:bg-blue-800 transition-colors text-sm disabled:opacity-50",children:[o.jsx(Ep,{className:"w-4 h-4"}),o.jsx("span",{children:pe==="backing-up"?M("备份中...","Backing up..."):M("备份","Backup")})]}),o.jsxs("button",{onClick:Me,disabled:!r||pe!=="idle",className:"flex items-center space-x-2 px-3 py-1.5 bg-orange-100 text-orange-700 dark:bg-orange-900 dark:text-orange-300 rounded-lg hover:bg-orange-200 dark:hover:bg-orange-800 transition-colors text-sm disabled:opacity-50",children:[o.jsx(op,{className:"w-4 h-4"}),o.jsx("span",{children:pe==="restoring"?M("恢复中...","Restoring..."):M("恢复","Restore")})]})]})]}),o.jsxs("div",{className:"flex items-start space-x-3 p-3 bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg",children:[o.jsx(X0,{className:"w-5 h-5 text-yellow-600 dark:text-yellow-400 flex-shrink-0 mt-0.5"}),o.jsxs("div",{className:"text-sm",children:[o.jsx("p",{className:"font-medium text-yellow-800 dark:text-yellow-200 mb-1",children:M("重要提示:CORS配置","Important: CORS Configuration")}),o.jsx("p",{className:"text-yellow-700 dark:text-yellow-300",children:M("如果遇到连接错误,请确保您的WebDAV服务器配置了正确的CORS头。点击测试连接按钮查看详细的错误信息和解决方案。","If you encounter connection errors, ensure your WebDAV server is configured with proper CORS headers. Click the test connection button for detailed error messages and solutions.")})]})]})]}),o.jsx("div",{className:"space-y-4",children:n.map(S=>o.jsx("div",{className:`p-4 border rounded-lg transition-colors ${S.id===r?"border-green-300 bg-green-50 dark:border-green-700 dark:bg-green-950":"border-gray-200 dark:border-gray-600"}`,children:o.jsxs("div",{className:"flex items-center justify-between",children:[o.jsxs("div",{children:[o.jsxs("h4",{className:"font-medium text-gray-900 dark:text-white",children:[S.name,S.id===r&&o.jsx("span",{className:"ml-2 px-2 py-1 bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-300 rounded text-xs",children:M("活跃","Active")})]}),o.jsxs("p",{className:"text-sm text-gray-500 dark:text-gray-400",children:[S.url," • ",S.path]})]}),o.jsxs("div",{className:"flex items-center space-x-2",children:[o.jsxs("button",{onClick:()=>O(S),disabled:Y===S.id,className:"flex items-center space-x-2 px-3 py-1.5 bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors text-sm",children:[o.jsx(Oi,{className:"w-4 h-4"}),o.jsx("span",{children:Y===S.id?M("测试中...","Testing..."):M("测试","Test")})]}),S.id!==r&&o.jsx("button",{onClick:()=>G(S.id),className:"px-3 py-1.5 bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-300 rounded-lg hover:bg-green-200 dark:hover:bg-green-800 transition-colors text-sm",children:M("设为活跃","Set Active")}),o.jsx("button",{onClick:()=>x(S.id),className:"p-1.5 text-red-600 dark:text-red-400 hover:bg-red-100 dark:hover:bg-red-900 rounded-lg transition-colors",children:o.jsx(Fi,{className:"w-4 h-4"})})]})]})},S.id))}),R&&o.jsxs("div",{className:"mt-6 p-4 border border-gray-200 dark:border-gray-600 rounded-lg bg-gray-50 dark:bg-gray-750",children:[o.jsx("h4",{className:"font-medium text-gray-900 dark:text-white mb-4",children:M("添加新的WebDAV配置","Add New WebDAV Configuration")}),o.jsxs("div",{className:"mb-4",children:[o.jsx("label",{className:"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2",children:M("快速设置(可选)","Quick Setup (Optional)")}),o.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-3 gap-2",children:ts.map((S,L)=>o.jsxs("button",{onClick:()=>E(oe=>({...oe,...S})),className:"p-3 text-left border border-gray-200 dark:border-gray-600 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors",children:[o.jsx("p",{className:"font-medium text-sm text-gray-900 dark:text-white",children:S.name}),o.jsx("p",{className:"text-xs text-gray-500 dark:text-gray-400",children:S.url})]},L))})]}),o.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4 mb-4",children:[o.jsxs("div",{children:[o.jsxs("label",{className:"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2",children:[M("配置名称","Configuration Name")," *"]}),o.jsx("input",{type:"text",placeholder:M("我的WebDAV服务器","My WebDAV Server"),value:y.name||"",onChange:S=>E(L=>({...L,name:S.target.value})),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white"})]}),o.jsxs("div",{children:[o.jsxs("label",{className:"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2",children:[M("用户名","Username")," *"]}),o.jsx("input",{type:"text",placeholder:"username",value:y.username||"",onChange:S=>E(L=>({...L,username:S.target.value})),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white"})]})]}),o.jsxs("div",{className:"mb-4",children:[o.jsxs("label",{className:"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2",children:[M("WebDAV服务器URL","WebDAV Server URL")," *"]}),o.jsx("input",{type:"url",placeholder:"https://your-server.com/webdav",value:y.url||"",onChange:S=>E(L=>({...L,url:S.target.value})),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white"})]}),o.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4 mb-4",children:[o.jsxs("div",{children:[o.jsxs("label",{className:"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2",children:[M("密码","Password")," *"]}),o.jsx("input",{type:"password",placeholder:"password",value:y.password||"",onChange:S=>E(L=>({...L,password:S.target.value})),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white"})]}),o.jsxs("div",{children:[o.jsxs("label",{className:"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2",children:[M("备份路径","Backup Path")," *"]}),o.jsx("input",{type:"text",placeholder:"/github-stars-backup",value:y.path||"",onChange:S=>E(L=>({...L,path:S.target.value})),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white"})]})]}),o.jsxs("div",{className:"flex items-center space-x-3",children:[o.jsxs("button",{onClick:w,className:"flex items-center space-x-2 px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors",children:[o.jsx($i,{className:"w-4 h-4"}),o.jsx("span",{children:M("保存配置","Save Configuration")})]}),o.jsxs("button",{onClick:()=>{$(!1),E({name:"",url:"",username:"",password:"",path:"/github-stars-backup"})},className:"flex items-center space-x-2 px-4 py-2 bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors",children:[o.jsx(Yt,{className:"w-4 h-4"}),o.jsx("span",{children:M("取消","Cancel")})]})]})]})]}),o.jsxs("div",{className:"bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-6",children:[o.jsxs("div",{className:"flex items-center justify-between mb-6",children:[o.jsxs("div",{className:"flex items-center space-x-3",children:[o.jsx("div",{className:"flex items-center justify-center w-10 h-10 bg-purple-100 dark:bg-purple-900 rounded-lg",children:o.jsx(Nr,{className:"w-5 h-5 text-purple-600 dark:text-purple-400"})}),o.jsxs("div",{children:[o.jsx("h3",{className:"text-lg font-semibold text-gray-900 dark:text-white",children:M("AI配置","AI Configurations")}),o.jsx("p",{className:"text-sm text-gray-500 dark:text-gray-400",children:M("管理用于仓库分析的AI服务配置","Manage your AI service configurations for repository analysis")})]})]}),o.jsxs("button",{onClick:()=>N(!0),className:"flex items-center space-x-2 px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors",children:[o.jsx(Li,{className:"w-4 h-4"}),o.jsx("span",{children:M("添加配置","Add Configuration")})]})]}),o.jsx("div",{className:"space-y-4",children:e.map(S=>o.jsx("div",{className:`p-4 border rounded-lg transition-colors ${S.id===t?"border-purple-300 bg-purple-50 dark:border-purple-700 dark:bg-purple-950":"border-gray-200 dark:border-gray-600"}`,children:o.jsxs("div",{className:"flex items-center justify-between",children:[o.jsxs("div",{children:[o.jsxs("h4",{className:"font-medium text-gray-900 dark:text-white",children:[S.name,S.id===t&&o.jsx("span",{className:"ml-2 px-2 py-1 bg-purple-100 text-purple-700 dark:bg-purple-900 dark:text-purple-300 rounded text-xs",children:M("活跃","Active")})]}),o.jsxs("p",{className:"text-sm text-gray-500 dark:text-gray-400",children:[S.baseUrl," • ",S.model]})]}),o.jsxs("div",{className:"flex items-center space-x-2",children:[o.jsxs("button",{onClick:()=>T(S),disabled:D===S.id,className:"flex items-center space-x-2 px-3 py-1.5 bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors text-sm",children:[o.jsx(Oi,{className:"w-4 h-4"}),o.jsx("span",{children:D===S.id?M("测试中...","Testing..."):M("测试","Test")})]}),S.id!==t&&o.jsx("button",{onClick:()=>Q(S.id),className:"px-3 py-1.5 bg-purple-100 text-purple-700 dark:bg-purple-900 dark:text-purple-300 rounded-lg hover:bg-purple-200 dark:hover:bg-purple-800 transition-colors text-sm",children:M("设为活跃","Set Active")}),o.jsx("button",{onClick:()=>h(S.id),className:"p-1.5 text-red-600 dark:text-red-400 hover:bg-red-100 dark:hover:bg-red-900 rounded-lg transition-colors",children:o.jsx(Fi,{className:"w-4 h-4"})})]})]})},S.id))}),j&&o.jsxs("div",{className:"mt-6 p-4 border border-gray-200 dark:border-gray-600 rounded-lg bg-gray-50 dark:bg-gray-750",children:[o.jsx("h4",{className:"font-medium text-gray-900 dark:text-white mb-4",children:M("添加新的AI配置","Add New AI Configuration")}),o.jsxs("div",{className:"mb-4",children:[o.jsx("label",{className:"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2",children:M("快速设置(可选)","Quick Setup (Optional)")}),o.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-3 gap-2",children:Mr.map((S,L)=>o.jsxs("button",{onClick:()=>U(oe=>({...oe,...S})),className:"p-3 text-left border border-gray-200 dark:border-gray-600 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors",children:[o.jsx("p",{className:"font-medium text-sm text-gray-900 dark:text-white",children:S.name}),o.jsx("p",{className:"text-xs text-gray-500 dark:text-gray-400",children:S.model})]},L))})]}),o.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4 mb-4",children:[o.jsxs("div",{children:[o.jsx("label",{className:"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2",children:M("配置名称","Configuration Name")}),o.jsx("input",{type:"text",placeholder:M("我的OpenAI配置","My OpenAI Config"),value:V.name||"",onChange:S=>U(L=>({...L,name:S.target.value})),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white"})]}),o.jsxs("div",{children:[o.jsx("label",{className:"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2",children:M("模型","Model")}),o.jsx("input",{type:"text",placeholder:"gpt-3.5-turbo",value:V.model||"",onChange:S=>U(L=>({...L,model:S.target.value})),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white"})]})]}),o.jsxs("div",{className:"mb-4",children:[o.jsx("label",{className:"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2",children:M("API基础URL","API Base URL")}),o.jsx("input",{type:"url",placeholder:"https://api.openai.com/v1",value:V.baseUrl||"",onChange:S=>U(L=>({...L,baseUrl:S.target.value})),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white"})]}),o.jsxs("div",{className:"mb-4",children:[o.jsx("label",{className:"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2",children:M("API密钥","API Key")}),o.jsx("input",{type:"password",placeholder:"sk-xxxxxxxxxxxxxxxxxxxx",value:V.apiKey||"",onChange:S=>U(L=>({...L,apiKey:S.target.value})),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white"})]}),o.jsxs("div",{className:"flex items-center space-x-3",children:[o.jsxs("button",{onClick:z,className:"flex items-center space-x-2 px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors",children:[o.jsx($i,{className:"w-4 h-4"}),o.jsx("span",{children:M("保存配置","Save Configuration")})]}),o.jsxs("button",{onClick:()=>{N(!1),U({name:"",baseUrl:"https://api.openai.com/v1",apiKey:"",model:"gpt-3.5-turbo"})},className:"flex items-center space-x-2 px-4 py-2 bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors",children:[o.jsx(Yt,{className:"w-4 h-4"}),o.jsx("span",{children:M("取消","Cancel")})]})]})]})]})]})};function pg(){const{isAuthenticated:e,currentView:t,theme:n,searchResults:r,repositories:a}=Wt(),[s,l]=W.useState("all");if(W.useEffect(()=>{n==="dark"?document.documentElement.classList.add("dark"):document.documentElement.classList.remove("dark")},[n]),!e)return o.jsx(fm,{});const i=()=>{switch(t){case"repositories":return o.jsxs("div",{className:"flex space-x-6",children:[o.jsx(cg,{repositories:a,selectedCategory:s,onCategorySelect:l}),o.jsxs("div",{className:"flex-1 space-y-6",children:[o.jsx(mm,{}),o.jsx(ig,{repositories:r.length>0?r:a,selectedCategory:s})]})]});case"releases":return o.jsx(dg,{});case"settings":return o.jsx(fg,{});default:return null}};return o.jsxs("div",{className:"min-h-screen bg-gray-50 dark:bg-gray-900",children:[o.jsx(pm,{}),o.jsx("main",{className:"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8",children:i()})]})}console.log("Main.tsx loading...");const xd=document.getElementById("root");if(!xd)throw new Error("Root element not found");console.log("Root element found, creating React root...");const mg=od(xd);mg.render(o.jsx(W.StrictMode,{children:o.jsx(pg,{})}));console.log("React app rendered"); diff --git a/dist/assets/index-m15jYu--.css b/dist/assets/index-m15jYu--.css new file mode 100644 index 0000000..0c71cb2 --- /dev/null +++ b/dist/assets/index-m15jYu--.css @@ -0,0 +1 @@ +*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.container{width:100%}@media (min-width: 640px){.container{max-width:640px}}@media (min-width: 768px){.container{max-width:768px}}@media (min-width: 1024px){.container{max-width:1024px}}@media (min-width: 1280px){.container{max-width:1280px}}@media (min-width: 1536px){.container{max-width:1536px}}.static{position:static}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.left-0{left:0}.left-3{left:.75rem}.right-2{right:.5rem}.right-3{right:.75rem}.top-0{top:0}.top-1\/2{top:50%}.top-24{top:6rem}.top-full{top:100%}.z-10{z-index:10}.z-50{z-index:50}.col-span-2{grid-column:span 2 / span 2}.col-span-3{grid-column:span 3 / span 3}.col-span-4{grid-column:span 4 / span 4}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-2{margin-left:.5rem}.mr-1{margin-right:.25rem}.mr-2{margin-right:.5rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.mt-auto{margin-top:auto}.line-clamp-3{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.grid{display:grid}.hidden{display:none}.h-10{height:2.5rem}.h-16{height:4rem}.h-2{height:.5rem}.h-3{height:.75rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-fit{height:-moz-fit-content;height:fit-content}.h-full{height:100%}.min-h-screen{min-height:100vh}.w-10{width:2.5rem}.w-16{width:4rem}.w-2{width:.5rem}.w-24{width:6rem}.w-3{width:.75rem}.w-32{width:8rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-56{width:14rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-8{width:2rem}.w-full{width:100%}.min-w-0{min-width:0px}.max-w-16{max-width:4rem}.max-w-20{max-width:5rem}.max-w-32{max-width:8rem}.max-w-4xl{max-width:56rem}.max-w-7xl{max-width:80rem}.max-w-md{max-width:28rem}.max-w-none{max-width:none}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.-translate-y-1\/2{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes slideUp{0%{transform:translateY(10px);opacity:0}to{transform:translateY(0);opacity:1}}.animate-slide-up{animation:slideUp .3s ease-out}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.list-inside{list-style-position:inside}.list-disc{list-style-type:disc}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.space-x-0\.5>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.125rem * var(--tw-space-x-reverse));margin-left:calc(.125rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.25rem * var(--tw-space-x-reverse));margin-left:calc(.25rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.5rem * var(--tw-space-x-reverse));margin-left:calc(.5rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.75rem * var(--tw-space-x-reverse));margin-left:calc(.75rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(1rem * var(--tw-space-x-reverse));margin-left:calc(1rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-6>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(1.5rem * var(--tw-space-x-reverse));margin-left:calc(1.5rem * calc(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(2rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem * var(--tw-space-y-reverse))}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-blue-200{--tw-border-opacity: 1;border-color:rgb(191 219 254 / var(--tw-border-opacity, 1))}.border-gray-100{--tw-border-opacity: 1;border-color:rgb(243 244 246 / var(--tw-border-opacity, 1))}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity, 1))}.border-gray-300{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1))}.border-green-200{--tw-border-opacity: 1;border-color:rgb(187 247 208 / var(--tw-border-opacity, 1))}.border-green-300{--tw-border-opacity: 1;border-color:rgb(134 239 172 / var(--tw-border-opacity, 1))}.border-purple-300{--tw-border-opacity: 1;border-color:rgb(216 180 254 / var(--tw-border-opacity, 1))}.border-red-200{--tw-border-opacity: 1;border-color:rgb(254 202 202 / var(--tw-border-opacity, 1))}.border-white{--tw-border-opacity: 1;border-color:rgb(255 255 255 / var(--tw-border-opacity, 1))}.border-yellow-200{--tw-border-opacity: 1;border-color:rgb(254 240 138 / var(--tw-border-opacity, 1))}.border-t-transparent{border-top-color:transparent}.bg-blue-100{--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1))}.bg-blue-200{--tw-bg-opacity: 1;background-color:rgb(191 219 254 / var(--tw-bg-opacity, 1))}.bg-blue-50{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.bg-blue-600{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity, 1))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.bg-gray-200{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.bg-gray-400{--tw-bg-opacity: 1;background-color:rgb(156 163 175 / var(--tw-bg-opacity, 1))}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.bg-green-100{--tw-bg-opacity: 1;background-color:rgb(220 252 231 / var(--tw-bg-opacity, 1))}.bg-green-50{--tw-bg-opacity: 1;background-color:rgb(240 253 244 / var(--tw-bg-opacity, 1))}.bg-green-500{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.bg-green-600{--tw-bg-opacity: 1;background-color:rgb(22 163 74 / var(--tw-bg-opacity, 1))}.bg-indigo-100{--tw-bg-opacity: 1;background-color:rgb(224 231 255 / var(--tw-bg-opacity, 1))}.bg-orange-100{--tw-bg-opacity: 1;background-color:rgb(255 237 213 / var(--tw-bg-opacity, 1))}.bg-purple-100{--tw-bg-opacity: 1;background-color:rgb(243 232 255 / var(--tw-bg-opacity, 1))}.bg-purple-50{--tw-bg-opacity: 1;background-color:rgb(250 245 255 / var(--tw-bg-opacity, 1))}.bg-purple-600{--tw-bg-opacity: 1;background-color:rgb(147 51 234 / var(--tw-bg-opacity, 1))}.bg-red-100{--tw-bg-opacity: 1;background-color:rgb(254 226 226 / var(--tw-bg-opacity, 1))}.bg-red-50{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-yellow-100{--tw-bg-opacity: 1;background-color:rgb(254 249 195 / var(--tw-bg-opacity, 1))}.bg-yellow-50{--tw-bg-opacity: 1;background-color:rgb(254 252 232 / var(--tw-bg-opacity, 1))}.bg-gradient-to-br{background-image:linear-gradient(to bottom right,var(--tw-gradient-stops))}.from-blue-50{--tw-gradient-from: #eff6ff var(--tw-gradient-from-position);--tw-gradient-to: rgb(239 246 255 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.to-indigo-100{--tw-gradient-to: #e0e7ff var(--tw-gradient-to-position)}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pl-10{padding-left:2.5rem}.pr-10{padding-right:2.5rem}.pr-32{padding-right:8rem}.pr-4{padding-right:1rem}.pt-2{padding-top:.5rem}.pt-6{padding-top:1.5rem}.text-left{text-align:left}.text-center{text-align:center}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.capitalize{text-transform:capitalize}.leading-relaxed{line-height:1.625}.text-blue-600{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.text-blue-700{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.text-blue-800{--tw-text-opacity: 1;color:rgb(30 64 175 / var(--tw-text-opacity, 1))}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.text-gray-800{--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity, 1))}.text-gray-900{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.text-green-600{--tw-text-opacity: 1;color:rgb(22 163 74 / var(--tw-text-opacity, 1))}.text-green-700{--tw-text-opacity: 1;color:rgb(21 128 61 / var(--tw-text-opacity, 1))}.text-indigo-600{--tw-text-opacity: 1;color:rgb(79 70 229 / var(--tw-text-opacity, 1))}.text-orange-700{--tw-text-opacity: 1;color:rgb(194 65 12 / var(--tw-text-opacity, 1))}.text-purple-600{--tw-text-opacity: 1;color:rgb(147 51 234 / var(--tw-text-opacity, 1))}.text-purple-700{--tw-text-opacity: 1;color:rgb(126 34 206 / var(--tw-text-opacity, 1))}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-red-700{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-yellow-600{--tw-text-opacity: 1;color:rgb(202 138 4 / var(--tw-text-opacity, 1))}.text-yellow-700{--tw-text-opacity: 1;color:rgb(161 98 7 / var(--tw-text-opacity, 1))}.text-yellow-800{--tw-text-opacity: 1;color:rgb(133 77 14 / var(--tw-text-opacity, 1))}.placeholder-gray-500::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(107 114 128 / var(--tw-placeholder-opacity, 1))}.placeholder-gray-500::placeholder{--tw-placeholder-opacity: 1;color:rgb(107 114 128 / var(--tw-placeholder-opacity, 1))}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-shadow{transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.line-clamp-3{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.hover\:border-blue-300:hover{--tw-border-opacity: 1;border-color:rgb(147 197 253 / var(--tw-border-opacity, 1))}.hover\:bg-blue-200:hover{--tw-bg-opacity: 1;background-color:rgb(191 219 254 / var(--tw-bg-opacity, 1))}.hover\:bg-blue-700:hover{--tw-bg-opacity: 1;background-color:rgb(29 78 216 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-100:hover{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-200:hover{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-50:hover{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.hover\:bg-green-200:hover{--tw-bg-opacity: 1;background-color:rgb(187 247 208 / var(--tw-bg-opacity, 1))}.hover\:bg-green-700:hover{--tw-bg-opacity: 1;background-color:rgb(21 128 61 / var(--tw-bg-opacity, 1))}.hover\:bg-orange-200:hover{--tw-bg-opacity: 1;background-color:rgb(254 215 170 / var(--tw-bg-opacity, 1))}.hover\:bg-purple-200:hover{--tw-bg-opacity: 1;background-color:rgb(233 213 255 / var(--tw-bg-opacity, 1))}.hover\:bg-purple-700:hover{--tw-bg-opacity: 1;background-color:rgb(126 34 206 / var(--tw-bg-opacity, 1))}.hover\:bg-red-100:hover{--tw-bg-opacity: 1;background-color:rgb(254 226 226 / var(--tw-bg-opacity, 1))}.hover\:bg-red-200:hover{--tw-bg-opacity: 1;background-color:rgb(254 202 202 / var(--tw-bg-opacity, 1))}.hover\:bg-yellow-200:hover{--tw-bg-opacity: 1;background-color:rgb(254 240 138 / var(--tw-bg-opacity, 1))}.hover\:text-blue-700:hover{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.hover\:text-gray-600:hover{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.hover\:text-gray-800:hover{--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity, 1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:shadow-lg:hover{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.focus\:border-transparent:focus{border-color:transparent}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-blue-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-gray-400:disabled{--tw-bg-opacity: 1;background-color:rgb(156 163 175 / var(--tw-bg-opacity, 1))}.disabled\:bg-gray-50:disabled{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.disabled\:text-gray-500:disabled{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.disabled\:opacity-50:disabled{opacity:.5}.dark\:border-blue-800:is(.dark *){--tw-border-opacity: 1;border-color:rgb(30 64 175 / var(--tw-border-opacity, 1))}.dark\:border-gray-600:is(.dark *){--tw-border-opacity: 1;border-color:rgb(75 85 99 / var(--tw-border-opacity, 1))}.dark\:border-gray-700:is(.dark *){--tw-border-opacity: 1;border-color:rgb(55 65 81 / var(--tw-border-opacity, 1))}.dark\:border-green-700:is(.dark *){--tw-border-opacity: 1;border-color:rgb(21 128 61 / var(--tw-border-opacity, 1))}.dark\:border-purple-700:is(.dark *){--tw-border-opacity: 1;border-color:rgb(126 34 206 / var(--tw-border-opacity, 1))}.dark\:border-yellow-800:is(.dark *){--tw-border-opacity: 1;border-color:rgb(133 77 14 / var(--tw-border-opacity, 1))}.dark\:bg-blue-800:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(30 64 175 / var(--tw-bg-opacity, 1))}.dark\:bg-blue-900:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(30 58 138 / var(--tw-bg-opacity, 1))}.dark\:bg-blue-900\/20:is(.dark *){background-color:#1e3a8a33}.dark\:bg-gray-600:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(75 85 99 / var(--tw-bg-opacity, 1))}.dark\:bg-gray-700:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(55 65 81 / var(--tw-bg-opacity, 1))}.dark\:bg-gray-800:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(31 41 55 / var(--tw-bg-opacity, 1))}.dark\:bg-gray-900:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(17 24 39 / var(--tw-bg-opacity, 1))}.dark\:bg-green-900:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(20 83 45 / var(--tw-bg-opacity, 1))}.dark\:bg-green-950:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(5 46 22 / var(--tw-bg-opacity, 1))}.dark\:bg-indigo-900:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(49 46 129 / var(--tw-bg-opacity, 1))}.dark\:bg-orange-900:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(124 45 18 / var(--tw-bg-opacity, 1))}.dark\:bg-purple-900:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(88 28 135 / var(--tw-bg-opacity, 1))}.dark\:bg-purple-950:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(59 7 100 / var(--tw-bg-opacity, 1))}.dark\:bg-red-900:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(127 29 29 / var(--tw-bg-opacity, 1))}.dark\:bg-yellow-900:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(113 63 18 / var(--tw-bg-opacity, 1))}.dark\:bg-yellow-900\/20:is(.dark *){background-color:#713f1233}.dark\:text-blue-200:is(.dark *){--tw-text-opacity: 1;color:rgb(191 219 254 / var(--tw-text-opacity, 1))}.dark\:text-blue-300:is(.dark *){--tw-text-opacity: 1;color:rgb(147 197 253 / var(--tw-text-opacity, 1))}.dark\:text-blue-400:is(.dark *){--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1))}.dark\:text-gray-200:is(.dark *){--tw-text-opacity: 1;color:rgb(229 231 235 / var(--tw-text-opacity, 1))}.dark\:text-gray-300:is(.dark *){--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.dark\:text-gray-400:is(.dark *){--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.dark\:text-gray-500:is(.dark *){--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.dark\:text-gray-600:is(.dark *){--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.dark\:text-green-300:is(.dark *){--tw-text-opacity: 1;color:rgb(134 239 172 / var(--tw-text-opacity, 1))}.dark\:text-green-400:is(.dark *){--tw-text-opacity: 1;color:rgb(74 222 128 / var(--tw-text-opacity, 1))}.dark\:text-indigo-400:is(.dark *){--tw-text-opacity: 1;color:rgb(129 140 248 / var(--tw-text-opacity, 1))}.dark\:text-orange-300:is(.dark *){--tw-text-opacity: 1;color:rgb(253 186 116 / var(--tw-text-opacity, 1))}.dark\:text-purple-300:is(.dark *){--tw-text-opacity: 1;color:rgb(216 180 254 / var(--tw-text-opacity, 1))}.dark\:text-purple-400:is(.dark *){--tw-text-opacity: 1;color:rgb(192 132 252 / var(--tw-text-opacity, 1))}.dark\:text-red-300:is(.dark *){--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity, 1))}.dark\:text-red-400:is(.dark *){--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.dark\:text-white:is(.dark *){--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.dark\:text-yellow-200:is(.dark *){--tw-text-opacity: 1;color:rgb(254 240 138 / var(--tw-text-opacity, 1))}.dark\:text-yellow-300:is(.dark *){--tw-text-opacity: 1;color:rgb(253 224 71 / var(--tw-text-opacity, 1))}.dark\:text-yellow-400:is(.dark *){--tw-text-opacity: 1;color:rgb(250 204 21 / var(--tw-text-opacity, 1))}.dark\:placeholder-gray-400:is(.dark *)::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(156 163 175 / var(--tw-placeholder-opacity, 1))}.dark\:placeholder-gray-400:is(.dark *)::placeholder{--tw-placeholder-opacity: 1;color:rgb(156 163 175 / var(--tw-placeholder-opacity, 1))}.dark\:ring-offset-gray-800:is(.dark *){--tw-ring-offset-color: #1f2937}.dark\:hover\:border-blue-600:hover:is(.dark *){--tw-border-opacity: 1;border-color:rgb(37 99 235 / var(--tw-border-opacity, 1))}.dark\:hover\:bg-blue-800:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(30 64 175 / var(--tw-bg-opacity, 1))}.dark\:hover\:bg-gray-600:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(75 85 99 / var(--tw-bg-opacity, 1))}.dark\:hover\:bg-gray-700:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(55 65 81 / var(--tw-bg-opacity, 1))}.dark\:hover\:bg-green-800:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(22 101 52 / var(--tw-bg-opacity, 1))}.dark\:hover\:bg-orange-800:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(154 52 18 / var(--tw-bg-opacity, 1))}.dark\:hover\:bg-purple-800:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(107 33 168 / var(--tw-bg-opacity, 1))}.dark\:hover\:bg-red-800:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(153 27 27 / var(--tw-bg-opacity, 1))}.dark\:hover\:bg-red-900:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(127 29 29 / var(--tw-bg-opacity, 1))}.dark\:hover\:bg-yellow-800:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(133 77 14 / var(--tw-bg-opacity, 1))}.dark\:hover\:text-gray-200:hover:is(.dark *){--tw-text-opacity: 1;color:rgb(229 231 235 / var(--tw-text-opacity, 1))}.dark\:hover\:text-gray-300:hover:is(.dark *){--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.dark\:focus\:ring-blue-600:focus:is(.dark *){--tw-ring-opacity: 1;--tw-ring-color: rgb(37 99 235 / var(--tw-ring-opacity, 1))}@media (min-width: 640px){.sm\:block{display:block}.sm\:flex{display:flex}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}}@media (min-width: 768px){.md\:flex{display:flex}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width: 1024px){.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:px-8{padding-left:2rem;padding-right:2rem}}@media (min-width: 1280px){.xl\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}} diff --git a/dist/index.html b/dist/index.html new file mode 100644 index 0000000..036d755 --- /dev/null +++ b/dist/index.html @@ -0,0 +1,19 @@ + + + + + + + GitHub Stars Manager - AI-Powered Repository Management + + + + + + + + + +
+ + \ No newline at end of file diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..82c2e20 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,28 @@ +import js from '@eslint/js'; +import globals from 'globals'; +import reactHooks from 'eslint-plugin-react-hooks'; +import reactRefresh from 'eslint-plugin-react-refresh'; +import tseslint from 'typescript-eslint'; + +export default tseslint.config( + { ignores: ['dist'] }, + { + extends: [js.configs.recommended, ...tseslint.configs.recommended], + files: ['**/*.{ts,tsx}'], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + }, + plugins: { + 'react-hooks': reactHooks, + 'react-refresh': reactRefresh, + }, + rules: { + ...reactHooks.configs.recommended.rules, + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + }, + } +); diff --git a/index.html b/index.html new file mode 100644 index 0000000..f40da33 --- /dev/null +++ b/index.html @@ -0,0 +1,18 @@ + + + + + + + GitHub Stars Manager - AI-Powered Repository Management + + + + + + + +
+ + + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..1a63c48 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,4133 @@ +{ + "name": "github-stars-manager", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "github-stars-manager", + "version": "1.0.0", + "dependencies": { + "date-fns": "^3.3.1", + "lucide-react": "^0.344.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^6.22.0", + "zustand": "^4.5.0" + }, + "devDependencies": { + "@eslint/js": "^9.9.1", + "@types/react": "^18.3.5", + "@types/react-dom": "^18.3.0", + "@vitejs/plugin-react": "^4.3.1", + "autoprefixer": "^10.4.18", + "eslint": "^9.9.1", + "eslint-plugin-react-hooks": "^5.1.0-rc.0", + "eslint-plugin-react-refresh": "^0.4.11", + "globals": "^15.9.0", + "postcss": "^8.4.35", + "tailwindcss": "^3.4.1", + "typescript": "^5.5.3", + "typescript-eslint": "^8.3.0", + "vite": "^5.4.2" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz", + "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.25.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.7.tgz", + "integrity": "sha512-9ickoLz+hcXCeh7jrcin+/SLWm+GkxE2kTvoYyp38p4WkdFXfQJxDFGWp/YHjiKLPx06z2A7W8XKuqbReXDzsw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.7.tgz", + "integrity": "sha512-yJ474Zv3cwiSOO9nXJuqzvwEeM+chDuQ8GJirw+pZ91sCGCyOZ3dJkVE09fTV0VEVzXyLWhh3G/AolYTPX7Mow==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.25.7", + "@babel/generator": "^7.25.7", + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helpers": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/template": "^7.25.7", + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.7.tgz", + "integrity": "sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.25.7", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.7.tgz", + "integrity": "sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.25.7", + "@babel/helper-validator-option": "^7.25.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.7.tgz", + "integrity": "sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.7.tgz", + "integrity": "sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.25.7", + "@babel/helper-simple-access": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "@babel/traverse": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.7.tgz", + "integrity": "sha512-eaPZai0PiqCi09pPs3pAFfl/zYgGaE6IdXtYvmf0qlcDTd3WCtO7JWCcRd64e0EQrcYgiHibEZnOGsSY4QSgaw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.7.tgz", + "integrity": "sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", + "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", + "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.7.tgz", + "integrity": "sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.7.tgz", + "integrity": "sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==", + "dev": true, + "dependencies": { + "@babel/template": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz", + "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.7.tgz", + "integrity": "sha512-aZn7ETtQsjjGG5HruveUK06cU3Hljuhd9Iojm4M8WWv3wLE6OkE5PWbDUkItmMgegmccaITudyuW5RPYrYlgWw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.25.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.7.tgz", + "integrity": "sha512-JD9MUnLbPL0WdVK8AWC7F7tTG2OS6u/AKKnsK+NdRhUiVdnzyR1S3kKQCaRLOiaULvUiqK6Z4JQE635VgtCFeg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.7.tgz", + "integrity": "sha512-S/JXG/KrbIY06iyJPKfxr0qRxnhNOdkNXYBl/rmwgDd72cQLH9tEGkDm/yJPGvcSIUoikzfjMios9i+xT/uv9w==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.7.tgz", + "integrity": "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.7.tgz", + "integrity": "sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.25.7", + "@babel/generator": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/template": "^7.25.7", + "@babel/types": "^7.25.7", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.7.tgz", + "integrity": "sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", + "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", + "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.6.0.tgz", + "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.12.0.tgz", + "integrity": "sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", + "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", + "dev": true, + "dependencies": { + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", + "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", + "dev": true, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", + "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", + "dev": true, + "dependencies": { + "@humanfs/core": "^0.19.0", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@remix-run/router": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.0.tgz", + "integrity": "sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz", + "integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz", + "integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz", + "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz", + "integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz", + "integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz", + "integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz", + "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz", + "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz", + "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz", + "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz", + "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz", + "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz", + "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz", + "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz", + "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz", + "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/prop-types": { + "version": "15.7.13", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", + "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==", + "devOptional": true + }, + "node_modules/@types/react": { + "version": "18.3.11", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.11.tgz", + "integrity": "sha512-r6QZ069rFTjrEYgFdOck1gK7FLVsgJE7tTz0pQBczlBNUhBNk0MQH4UbnFSwjpQLMkLzgqvBBa+qGpLje16eTQ==", + "devOptional": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.1.tgz", + "integrity": "sha512-xfvdgA8AP/vxHgtgU310+WBnLB4uJQ9XdyP17RebG26rLtDrQJV3ZYrcopX91GrHmMoH8bdSwMRh2a//TiJ1jQ==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.8.1", + "@typescript-eslint/type-utils": "8.8.1", + "@typescript-eslint/utils": "8.8.1", + "@typescript-eslint/visitor-keys": "8.8.1", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.1.tgz", + "integrity": "sha512-hQUVn2Lij2NAxVFEdvIGxT9gP1tq2yM83m+by3whWFsWC+1y8pxxxHUFE1UqDu2VsGi2i6RLcv4QvouM84U+ow==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "8.8.1", + "@typescript-eslint/types": "8.8.1", + "@typescript-eslint/typescript-estree": "8.8.1", + "@typescript-eslint/visitor-keys": "8.8.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.1.tgz", + "integrity": "sha512-X4JdU+66Mazev/J0gfXlcC/dV6JI37h+93W9BRYXrSn0hrE64IoWgVkO9MSJgEzoWkxONgaQpICWg8vAN74wlA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.8.1", + "@typescript-eslint/visitor-keys": "8.8.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.1.tgz", + "integrity": "sha512-qSVnpcbLP8CALORf0za+vjLYj1Wp8HSoiI8zYU5tHxRVj30702Z1Yw4cLwfNKhTPWp5+P+k1pjmD5Zd1nhxiZA==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "8.8.1", + "@typescript-eslint/utils": "8.8.1", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.1.tgz", + "integrity": "sha512-WCcTP4SDXzMd23N27u66zTKMuEevH4uzU8C9jf0RO4E04yVHgQgW+r+TeVTNnO1KIfrL8ebgVVYYMMO3+jC55Q==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.1.tgz", + "integrity": "sha512-A5d1R9p+X+1js4JogdNilDuuq+EHZdsH9MjTVxXOdVFfTJXunKJR/v+fNNyO4TnoOn5HqobzfRlc70NC6HTcdg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.8.1", + "@typescript-eslint/visitor-keys": "8.8.1", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.1.tgz", + "integrity": "sha512-/QkNJDbV0bdL7H7d0/y0qBbV2HTtf0TIyjSDTvvmQEzeVx8jEImEbLuOA4EsvE8gIgqMitns0ifb5uQhMj8d9w==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.8.1", + "@typescript-eslint/types": "8.8.1", + "@typescript-eslint/typescript-estree": "8.8.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.1.tgz", + "integrity": "sha512-0/TdC3aeRAsW7MDvYRwEc1Uwm0TIBfzjPFgg60UU2Haj5qsCs9cc3zNgY71edqE3LbWfF/WoZQd3lJoDXFQpag==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.8.1", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.2.tgz", + "integrity": "sha512-hieu+o05v4glEBucTcKMK3dlES0OeJlD9YVOAPraVMOInBCwzumaIFiUjr4bHK7NPgnAHgiskUoceKercrN8vg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.25.2", + "@babel/plugin-transform-react-jsx-self": "^7.24.7", + "@babel/plugin-transform-react-jsx-source": "^7.24.7", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.14.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0" + } + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/autoprefixer": { + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", + "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001663", + "electron-to-chromium": "^1.5.28", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001667", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001667.tgz", + "integrity": "sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "devOptional": true + }, + "node_modules/date-fns": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.5.33", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.33.tgz", + "integrity": "sha512-+cYTcFB1QqD4j4LegwLfpCNxifb6dDFUAwk6RsLusCwIaZI6or2f+q8rs5tTB2YC53HhOlIbEaqHMAAC8IOIwA==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.12.0.tgz", + "integrity": "sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.18.0", + "@eslint/core": "^0.6.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.12.0", + "@eslint/plugin-kit": "^0.2.0", + "@humanfs/node": "^0.16.5", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.1", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.1.0", + "eslint-visitor-keys": "^4.1.0", + "espree": "^10.2.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.1.0-rc-fb9a90fa48-20240614", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.1.0-rc-fb9a90fa48-20240614.tgz", + "integrity": "sha512-xsiRwaDNF5wWNC4ZHLut+x/YcAxksUd9Rizt7LaEn3bV8VyYRpXnRJQlLOfYaVy9esk4DFP4zPPnoNVjq5Gc0w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.12", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.12.tgz", + "integrity": "sha512-9neVjoGv20FwYtCP6CB1dzR1vr57ZDNOXst21wd2xJ/cTlM2xLq0GWVlSNTdMn/4BtP6cHYBMCSp1wFBJ9jBsg==", + "dev": true, + "peerDependencies": { + "eslint": ">=7" + } + }, + "node_modules/eslint-scope": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", + "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", + "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", + "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", + "dev": true, + "dependencies": { + "acorn": "^8.12.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "15.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.11.0.tgz", + "integrity": "sha512-yeyNSjdbyVaWurlwCpcA6XNBrHTMIeDdj0/hnvX/OLJ9ekOXYbLsLinH/MucQyGvNnXhidTdNhTtJaffL2sMfw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "dev": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lucide-react": { + "version": "0.344.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.344.0.tgz", + "integrity": "sha512-6YyBnn91GB45VuVT96bYCOKElbJzUHqp65vX8cDcu55MQL9T969v4dhGClpljamuI/+KMO9P6w9Acq1CVQGvIQ==", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss": { + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-router": { + "version": "6.30.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.1.tgz", + "integrity": "sha512-X1m21aEmxGXqENEPG3T6u0Th7g0aS4ZmoNynhbs+Cn+q+QGTLt+d5IQ2bHAXKzKcxGJjxACpVbnYQSCRcfxHlQ==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.23.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.30.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.1.tgz", + "integrity": "sha512-llKsgOkZdbPU1Eg3zK8lCn+sjD9wMRZZPuzmdWWX5SUs8OFkN5HnFVC0u5KMeMaC9aoancFI/KoLuKPqN+hxHw==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.23.0", + "react-router": "6.30.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz", + "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.6" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.24.0", + "@rollup/rollup-android-arm64": "4.24.0", + "@rollup/rollup-darwin-arm64": "4.24.0", + "@rollup/rollup-darwin-x64": "4.24.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.24.0", + "@rollup/rollup-linux-arm-musleabihf": "4.24.0", + "@rollup/rollup-linux-arm64-gnu": "4.24.0", + "@rollup/rollup-linux-arm64-musl": "4.24.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.24.0", + "@rollup/rollup-linux-riscv64-gnu": "4.24.0", + "@rollup/rollup-linux-s390x-gnu": "4.24.0", + "@rollup/rollup-linux-x64-gnu": "4.24.0", + "@rollup/rollup-linux-x64-musl": "4.24.0", + "@rollup/rollup-win32-arm64-msvc": "4.24.0", + "@rollup/rollup-win32-ia32-msvc": "4.24.0", + "@rollup/rollup-win32-x64-msvc": "4.24.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.17", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", + "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", + "dev": true, + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.6", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.8.1.tgz", + "integrity": "sha512-R0dsXFt6t4SAFjUSKFjMh4pXDtq04SsFKCVGDP3ZOzNP7itF0jBcZYU4fMsZr4y7O7V7Nc751dDeESbe4PbQMQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.8.1", + "@typescript-eslint/parser": "8.8.1", + "@typescript-eslint/utils": "8.8.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", + "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/vite": { + "version": "5.4.8", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz", + "integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==", + "dev": true, + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yaml": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "dev": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zustand": { + "version": "4.5.7", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.7.tgz", + "integrity": "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==", + "license": "MIT", + "dependencies": { + "use-sync-external-store": "^1.2.2" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "immer": ">=9.0.6", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + } + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..c0afaa1 --- /dev/null +++ b/package.json @@ -0,0 +1,36 @@ +{ + "name": "github-stars-manager", + "private": true, + "version": "1.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "lucide-react": "^0.344.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^6.22.0", + "zustand": "^4.5.0", + "date-fns": "^3.3.1" + }, + "devDependencies": { + "@eslint/js": "^9.9.1", + "@types/react": "^18.3.5", + "@types/react-dom": "^18.3.0", + "@vitejs/plugin-react": "^4.3.1", + "autoprefixer": "^10.4.18", + "eslint": "^9.9.1", + "eslint-plugin-react-hooks": "^5.1.0-rc.0", + "eslint-plugin-react-refresh": "^0.4.11", + "globals": "^15.9.0", + "postcss": "^8.4.35", + "tailwindcss": "^3.4.1", + "typescript": "^5.5.3", + "typescript-eslint": "^8.3.0", + "vite": "^5.4.2" + } +} \ No newline at end of file diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..2aa7205 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..ea748ad --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,75 @@ +import React, { useEffect, useState } from 'react'; +import { LoginScreen } from './components/LoginScreen'; +import { Header } from './components/Header'; +import { SearchBar } from './components/SearchBar'; +import { RepositoryList } from './components/RepositoryList'; +import { CategorySidebar } from './components/CategorySidebar'; +import { ReleaseTimeline } from './components/ReleaseTimeline'; +import { SettingsPanel } from './components/SettingsPanel'; +import { useAppStore } from './store/useAppStore'; + +function App() { + const { + isAuthenticated, + currentView, + theme, + searchResults, + repositories + } = useAppStore(); + + const [selectedCategory, setSelectedCategory] = useState('all'); + + // Apply theme to document + useEffect(() => { + if (theme === 'dark') { + document.documentElement.classList.add('dark'); + } else { + document.documentElement.classList.remove('dark'); + } + }, [theme]); + + // Show login screen if not authenticated + if (!isAuthenticated) { + return ; + } + + // Main application interface + const renderCurrentView = () => { + switch (currentView) { + case 'repositories': + return ( +
+ +
+ + 0 ? searchResults : repositories} + selectedCategory={selectedCategory} + /> +
+
+ ); + case 'releases': + return ; + case 'settings': + return ; + default: + return null; + } + }; + + return ( +
+
+
+ {renderCurrentView()} +
+
+ ); +} + +export default App; \ No newline at end of file diff --git a/src/components/CategorySidebar.tsx b/src/components/CategorySidebar.tsx new file mode 100644 index 0000000..5535848 --- /dev/null +++ b/src/components/CategorySidebar.tsx @@ -0,0 +1,194 @@ +import React from 'react'; +import { + Folder, + Code, + Globe, + Smartphone, + Database, + Shield, + Gamepad2, + Palette, + Bot, + Wrench, + BookOpen, + Zap, + Users, + BarChart3 +} from 'lucide-react'; +import { Repository } from '../types'; + +interface CategorySidebarProps { + repositories: Repository[]; + selectedCategory: string; + onCategorySelect: (category: string) => void; +} + +interface Category { + id: string; + name: string; + icon: React.ComponentType; + keywords: string[]; +} + +const categories: Category[] = [ + { + id: 'all', + name: '全部分类', + icon: Folder, + keywords: [] + }, + { + id: 'web', + name: 'Web应用', + icon: Globe, + keywords: ['web应用', 'web', 'website', 'frontend', 'react', 'vue', 'angular'] + }, + { + id: 'mobile', + name: '移动应用', + icon: Smartphone, + keywords: ['移动应用', 'mobile', 'android', 'ios', 'flutter', 'react-native'] + }, + { + id: 'desktop', + name: '桌面应用', + icon: Code, + keywords: ['桌面应用', 'desktop', 'electron', 'gui', 'qt', 'gtk'] + }, + { + id: 'database', + name: '数据库', + icon: Database, + keywords: ['数据库', 'database', 'sql', 'nosql', 'mongodb', 'mysql', 'postgresql'] + }, + { + id: 'ai', + name: 'AI/机器学习', + icon: Bot, + keywords: ['ai工具', 'ai', 'ml', 'machine learning', 'deep learning', 'neural'] + }, + { + id: 'devtools', + name: '开发工具', + icon: Wrench, + keywords: ['开发工具', 'tool', 'cli', 'build', 'deploy', 'debug', 'test', 'automation'] + }, + { + id: 'security', + name: '安全工具', + icon: Shield, + keywords: ['安全工具', 'security', 'encryption', 'auth', 'vulnerability'] + }, + { + id: 'game', + name: '游戏', + icon: Gamepad2, + keywords: ['游戏', 'game', 'gaming', 'unity', 'unreal', 'godot'] + }, + { + id: 'design', + name: '设计工具', + icon: Palette, + keywords: ['设计工具', 'design', 'ui', 'ux', 'graphics', 'image'] + }, + { + id: 'productivity', + name: '效率工具', + icon: Zap, + keywords: ['效率工具', 'productivity', 'note', 'todo', 'calendar', 'task'] + }, + { + id: 'education', + name: '教育学习', + icon: BookOpen, + keywords: ['教育学习', 'education', 'learning', 'tutorial', 'course'] + }, + { + id: 'social', + name: '社交网络', + icon: Users, + keywords: ['社交网络', 'social', 'chat', 'messaging', 'communication'] + }, + { + id: 'analytics', + name: '数据分析', + icon: BarChart3, + keywords: ['数据分析', 'analytics', 'data', 'visualization', 'chart'] + } +]; + +export const CategorySidebar: React.FC = ({ + repositories, + selectedCategory, + onCategorySelect +}) => { + // Calculate repository count for each category + const getCategoryCount = (category: Category) => { + if (category.id === 'all') return repositories.length; + + return repositories.filter(repo => { + // 优先使用AI标签进行匹配 + if (repo.ai_tags && repo.ai_tags.length > 0) { + return repo.ai_tags.some(tag => + category.keywords.some(keyword => + tag.toLowerCase().includes(keyword.toLowerCase()) || + keyword.toLowerCase().includes(tag.toLowerCase()) + ) + ); + } + + // 如果没有AI标签,使用传统方式匹配 + const repoText = [ + repo.name, + repo.description || '', + repo.language || '', + ...(repo.topics || []), + repo.ai_summary || '' + ].join(' ').toLowerCase(); + + return category.keywords.some(keyword => + repoText.includes(keyword.toLowerCase()) + ); + }).length; + }; + + return ( +
+

+ 应用分类 +

+ +
+ {categories.map(category => { + const count = getCategoryCount(category); + const Icon = category.icon; + const isSelected = selectedCategory === category.id; + + return ( + + ); + })} +
+
+ ); +}; \ No newline at end of file diff --git a/src/components/Header.tsx b/src/components/Header.tsx new file mode 100644 index 0000000..dbddeb1 --- /dev/null +++ b/src/components/Header.tsx @@ -0,0 +1,208 @@ +import React from 'react'; +import { Star, Settings, Calendar, Search, Moon, Sun, LogOut, RefreshCw } from 'lucide-react'; +import { useAppStore } from '../store/useAppStore'; +import { GitHubApiService } from '../services/githubApi'; + +export const Header: React.FC = () => { + const { + user, + theme, + currentView, + isLoading, + lastSync, + githubToken, + repositories, + setTheme, + setCurrentView, + setRepositories, + setReleases, + setLoading, + setLastSync, + logout, + } = useAppStore(); + + const handleSync = async () => { + if (!githubToken) { + alert('GitHub token not found. Please login again.'); + return; + } + + setLoading(true); + try { + const githubApi = new GitHubApiService(githubToken); + + // 1. 获取所有starred仓库 + console.log('Fetching starred repositories...'); + const newRepositories = await githubApi.getAllStarredRepositories(); + + // 2. 合并现有仓库数据(保留AI分析结果) + const existingRepoMap = new Map(repositories.map(repo => [repo.id, repo])); + const mergedRepositories = newRepositories.map(newRepo => { + const existing = existingRepoMap.get(newRepo.id); + if (existing) { + // 保留AI分析结果,更新其他信息 + return { + ...newRepo, + ai_summary: existing.ai_summary, + ai_tags: existing.ai_tags, + ai_platforms: existing.ai_platforms, + analyzed_at: existing.analyzed_at, + }; + } + return newRepo; + }); + + setRepositories(mergedRepositories); + + // 3. 获取Release信息 + console.log('Fetching releases...'); + const releases = await githubApi.getMultipleRepositoryReleases(mergedRepositories.slice(0, 20)); + setReleases(releases); + + setLastSync(new Date().toISOString()); + console.log('Sync completed successfully'); + + // 显示同步结果 + const newRepoCount = newRepositories.length - repositories.length; + if (newRepoCount > 0) { + alert(`同步完成!发现 ${newRepoCount} 个新仓库。`); + } else { + alert('同步完成!所有仓库都是最新的。'); + } + } catch (error) { + console.error('Sync failed:', error); + if (error instanceof Error && error.message.includes('token')) { + alert('GitHub token 已过期或无效,请重新登录。'); + logout(); + } else { + alert('同步失败,请检查网络连接。'); + } + } finally { + setLoading(false); + } + }; + + const formatLastSync = (timestamp: string | null) => { + if (!timestamp) return 'Never'; + const date = new Date(timestamp); + const now = new Date(); + const diffMs = now.getTime() - date.getTime(); + const diffHours = Math.floor(diffMs / (1000 * 60 * 60)); + + if (diffHours < 1) return 'Just now'; + if (diffHours < 24) return `${diffHours}h ago`; + return date.toLocaleDateString(); + }; + + return ( +
+
+
+ {/* Logo and Title */} +
+
+ +
+
+

+ GitHub Stars Manager +

+

+ AI-powered repository management +

+
+
+ + {/* Navigation */} + + + {/* User Actions */} +
+ {/* Sync Status */} +
+ Last sync: {formatLastSync(lastSync)} + +
+ + {/* Theme Toggle */} + + + {/* User Profile */} + {user && ( +
+ {user.name +
+

+ {user.name || user.login} +

+
+ +
+ )} +
+
+
+
+ ); +}; \ No newline at end of file diff --git a/src/components/LoginScreen.tsx b/src/components/LoginScreen.tsx new file mode 100644 index 0000000..b79746b --- /dev/null +++ b/src/components/LoginScreen.tsx @@ -0,0 +1,163 @@ +import React, { useState } from 'react'; +import { Star, Github, Key, ArrowRight, AlertCircle } from 'lucide-react'; +import { useAppStore } from '../store/useAppStore'; +import { GitHubApiService } from '../services/githubApi'; + +export const LoginScreen: React.FC = () => { + const [token, setToken] = useState(''); + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(''); + const { setUser, setGitHubToken, repositories, lastSync } = useAppStore(); + + const handleConnect = async () => { + if (!token.trim()) { + setError('Please enter a valid GitHub token'); + return; + } + + setIsLoading(true); + setError(''); + + try { + // Test the token by fetching user info + const githubApi = new GitHubApiService(token); + const user = await githubApi.getCurrentUser(); + + // If successful, save the token and user info + setGitHubToken(token); + setUser(user); + + console.log('Successfully authenticated user:', user); + } catch (error) { + console.error('Authentication failed:', error); + setError( + error instanceof Error + ? error.message + : 'Failed to authenticate. Please check your token.' + ); + } finally { + setIsLoading(false); + } + }; + + const handleKeyPress = (e: React.KeyboardEvent) => { + if (e.key === 'Enter' && !isLoading) { + handleConnect(); + } + }; + + return ( +
+
+
+
+ +
+

+ GitHub Stars Manager +

+

+ AI-powered repository management +

+
+ +
+
+ +

+ Connect with GitHub +

+

+ Enter your GitHub personal access token to get started +

+
+ + {/* 显示缓存状态 */} + {repositories.length > 0 && lastSync && ( +
+
+
+ + 已缓存 {repositories.length} 个仓库 + +
+

+ 上次同步: {new Date(lastSync).toLocaleString()} +

+
+ )} + +
+
+ +
+ + { + setToken(e.target.value); + setError(''); // Clear error when user types + }} + onKeyPress={handleKeyPress} + disabled={isLoading} + className="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-white text-gray-900 disabled:bg-gray-50 disabled:text-gray-500" + /> +
+
+ + {error && ( +
+ +

{error}

+
+ )} + + +
+ +
+

+ How to create a GitHub token: +

+
    +
  1. 1. Go to GitHub Settings → Developer settings → Personal access tokens
  2. +
  3. 2. Click "Generate new token (classic)"
  4. +
  5. 3. Select scopes: repo and user
  6. +
  7. 4. Copy the generated token and paste it above
  8. +
+ +
+
+
+
+ ); +}; \ No newline at end of file diff --git a/src/components/ReleaseTimeline.tsx b/src/components/ReleaseTimeline.tsx new file mode 100644 index 0000000..e22c38c --- /dev/null +++ b/src/components/ReleaseTimeline.tsx @@ -0,0 +1,804 @@ +import React, { useState, useMemo } from 'react'; +import { ExternalLink, GitBranch, Calendar, Package, Bell, Search, X, RefreshCw, ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight, Eye, EyeOff } from 'lucide-react'; +import { Release } from '../types'; +import { useAppStore } from '../store/useAppStore'; +import { GitHubApiService } from '../services/githubApi'; +import { formatDistanceToNow, format } from 'date-fns'; + +export const ReleaseTimeline: React.FC = () => { + const { + releases, + repositories, + releaseSubscriptions, + githubToken, + language, + setReleases, + addReleases, + } = useAppStore(); + + const [searchQuery, setSearchQuery] = useState(''); + const [selectedPlatforms, setSelectedPlatforms] = useState([]); + const [isRefreshing, setIsRefreshing] = useState(false); + const [lastRefreshTime, setLastRefreshTime] = useState(null); + const [currentPage, setCurrentPage] = useState(1); + const [itemsPerPage, setItemsPerPage] = useState(100); + const [viewMode, setViewMode] = useState<'compact' | 'detailed'>('compact'); + + // Enhanced platform detection based on the userscript + const detectPlatforms = (filename: string): string[] => { + const name = filename.toLowerCase(); + const platforms: string[] = []; + + // Platform detection rules based on the userscript + const platformRules = { + windows: [ + '.exe', '.msi', '.zip', '.7z', + 'windows', 'win32', 'win64', 'win-x64', 'win-x86', 'win-arm64', + '-win.', '.win.', '-windows.', '.windows.', + 'setup', 'installer' + ], + macos: [ + '.dmg', '.pkg', '.app.zip', + 'darwin', 'macos', 'mac-os', 'osx', 'mac-universal', + '-mac.', '.mac.', '-macos.', '.macos.', '-darwin.', '.darwin.', + 'universal', 'x86_64-apple', 'arm64-apple' + ], + linux: [ + '.deb', '.rpm', '.tar.gz', '.tar.xz', '.tar.bz2', '.appimage', + 'linux', 'ubuntu', 'debian', 'fedora', 'centos', 'arch', 'alpine', + '-linux.', '.linux.', 'x86_64-unknown-linux', 'aarch64-unknown-linux', + 'musl', 'gnu' + ], + android: [ + '.apk', '.aab', + 'android', '-android.', '.android.', + 'arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64' + ], + ios: [ + '.ipa', + 'ios', '-ios.', '.ios.', + 'iphone', 'ipad' + ] + }; + + // Check each platform + Object.entries(platformRules).forEach(([platform, keywords]) => { + if (keywords.some(keyword => name.includes(keyword))) { + platforms.push(platform); + } + }); + + // Special handling for universal files + if (platforms.length === 0) { + // Check for source code or universal packages + if (name.includes('source') || name.includes('src') || + name.includes('universal') || name.includes('all') || + name.match(/\.(zip|tar\.gz|tar\.xz)$/) && !name.includes('win') && !name.includes('mac') && !name.includes('linux')) { + platforms.push('universal'); + } + } + + return platforms.length > 0 ? platforms : ['universal']; + }; + + const getDownloadLinks = (release: Release) => { + // Extract download links from release body + const downloadRegex = /\[([^\]]+)\]\((https?:\/\/[^\)]+)\)/g; + const links: Array<{ name: string; url: string; platforms: string[] }> = []; + + let match; + while ((match = downloadRegex.exec(release.body)) !== null) { + const [, name, url] = match; + // Only include actual download links (not documentation, etc.) + if (url.includes('/download/') || url.includes('/releases/') || + name.toLowerCase().includes('download') || + /\.(exe|dmg|deb|rpm|apk|ipa|zip|tar\.gz|msi|pkg|appimage)$/i.test(url)) { + const platforms = detectPlatforms(name + ' ' + url); + links.push({ name, url, platforms }); + } + } + + // Also check for GitHub release assets pattern + const assetRegex = /https:\/\/github\.com\/[^\/]+\/[^\/]+\/releases\/download\/[^\/]+\/([^\s\)]+)/g; + while ((match = assetRegex.exec(release.body)) !== null) { + const [url, filename] = match; + const platforms = detectPlatforms(filename); + // Avoid duplicates + if (!links.some(link => link.url === url)) { + links.push({ name: filename, url, platforms }); + } + } + + return links; + }; + + // Filter releases for subscribed repositories + const subscribedReleases = releases.filter(release => + releaseSubscriptions.has(release.repository.id) + ); + + // Apply search and platform filters + const filteredReleases = useMemo(() => { + let filtered = subscribedReleases; + + // Search filter + if (searchQuery.trim()) { + const query = searchQuery.toLowerCase(); + filtered = filtered.filter(release => + release.repository.name.toLowerCase().includes(query) || + release.repository.full_name.toLowerCase().includes(query) || + release.tag_name.toLowerCase().includes(query) || + release.name.toLowerCase().includes(query) || + release.body.toLowerCase().includes(query) + ); + } + + // Platform filter + if (selectedPlatforms.length > 0) { + filtered = filtered.filter(release => { + const downloadLinks = getDownloadLinks(release); + return downloadLinks.some(link => + selectedPlatforms.some(platform => link.platforms.includes(platform)) + ); + }); + } + + return filtered.sort((a, b) => + new Date(b.published_at).getTime() - new Date(a.published_at).getTime() + ); + }, [subscribedReleases, searchQuery, selectedPlatforms]); + + // Pagination + const totalPages = Math.ceil(filteredReleases.length / itemsPerPage); + const startIndex = (currentPage - 1) * itemsPerPage; + const paginatedReleases = filteredReleases.slice(startIndex, startIndex + itemsPerPage); + + // Get available platforms from all releases + const availablePlatforms = useMemo(() => { + const platforms = new Set(); + subscribedReleases.forEach(release => { + const downloadLinks = getDownloadLinks(release); + downloadLinks.forEach(link => { + link.platforms.forEach(platform => platforms.add(platform)); + }); + }); + return Array.from(platforms).sort(); + }, [subscribedReleases]); + + const handleRefresh = async () => { + if (!githubToken) { + alert(language === 'zh' ? 'GitHub token 未找到,请重新登录。' : 'GitHub token not found. Please login again.'); + return; + } + + setIsRefreshing(true); + try { + const githubApi = new GitHubApiService(githubToken); + const subscribedRepos = repositories.filter(repo => releaseSubscriptions.has(repo.id)); + + if (subscribedRepos.length === 0) { + alert(language === 'zh' ? '没有订阅的仓库。' : 'No subscribed repositories.'); + return; + } + + let newReleasesCount = 0; + const allNewReleases: Release[] = []; + + // 获取最新的release时间戳 + const latestReleaseTime = releases.length > 0 + ? Math.max(...releases.map(r => new Date(r.published_at).getTime())) + : 0; + const sinceTimestamp = latestReleaseTime > 0 ? new Date(latestReleaseTime).toISOString() : undefined; + + for (const repo of subscribedRepos) { + const [owner, name] = repo.full_name.split('/'); + + // 检查这个仓库是否是新订阅的(没有任何release记录) + const hasExistingReleases = releases.some(r => r.repository.id === repo.id); + + let repoReleases: Release[]; + if (!hasExistingReleases) { + // 新订阅的仓库,获取全部releases + repoReleases = await githubApi.getRepositoryReleases(owner, name, 1, 10); + } else { + // 已有记录的仓库,增量更新 + repoReleases = await githubApi.getIncrementalRepositoryReleases(owner, name, sinceTimestamp, 10); + } + + // 设置repository信息 + repoReleases.forEach(release => { + release.repository.id = repo.id; + }); + + allNewReleases.push(...repoReleases); + newReleasesCount += repoReleases.length; + + // Rate limiting protection + await new Promise(resolve => setTimeout(resolve, 200)); + } + + if (allNewReleases.length > 0) { + addReleases(allNewReleases); + } + + const now = new Date().toISOString(); + setLastRefreshTime(now); + + const message = language === 'zh' + ? `刷新完成!发现 ${newReleasesCount} 个新Release。` + : `Refresh completed! Found ${newReleasesCount} new releases.`; + + alert(message); + } catch (error) { + console.error('Refresh failed:', error); + const errorMessage = language === 'zh' + ? 'Release刷新失败,请检查网络连接。' + : 'Release refresh failed. Please check your network connection.'; + alert(errorMessage); + } finally { + setIsRefreshing(false); + } + }; + + const handlePlatformToggle = (platform: string) => { + setSelectedPlatforms(prev => + prev.includes(platform) + ? prev.filter(p => p !== platform) + : [...prev, platform] + ); + setCurrentPage(1); // Reset to first page when filtering + }; + + const clearFilters = () => { + setSearchQuery(''); + setSelectedPlatforms([]); + setCurrentPage(1); + }; + + const handlePageChange = (page: number) => { + setCurrentPage(Math.max(1, Math.min(page, totalPages))); + }; + + const getPageNumbers = () => { + const delta = 2; + const range = []; + const rangeWithDots = []; + + for (let i = Math.max(2, currentPage - delta); i <= Math.min(totalPages - 1, currentPage + delta); i++) { + range.push(i); + } + + if (currentPage - delta > 2) { + rangeWithDots.push(1, '...'); + } else { + rangeWithDots.push(1); + } + + rangeWithDots.push(...range); + + if (currentPage + delta < totalPages - 1) { + rangeWithDots.push('...', totalPages); + } else if (totalPages > 1) { + rangeWithDots.push(totalPages); + } + + return rangeWithDots; + }; + + const getPlatformIcon = (platform: string) => { + const iconMap: Record = { + windows: 'fab fa-windows', + macos: 'fab fa-apple', + linux: 'fab fa-linux', + android: 'fab fa-android', + ios: 'fab fa-apple', + universal: 'fas fa-download' + }; + return iconMap[platform] || 'fas fa-download'; + }; + + const getPlatformColor = (platform: string) => { + const colorMap: Record = { + windows: 'text-blue-600 dark:text-blue-400', + macos: 'text-gray-600 dark:text-gray-400', + linux: 'text-yellow-600 dark:text-yellow-400', + android: 'text-green-600 dark:text-green-400', + ios: 'text-gray-600 dark:text-gray-400', + universal: 'text-purple-600 dark:text-purple-400' + }; + return colorMap[platform] || 'text-gray-600 dark:text-gray-400'; + }; + + const truncateBody = (body: string, maxLength = 200) => { + if (body.length <= maxLength) return body; + return body.substring(0, maxLength) + '...'; + }; + + const t = (zh: string, en: string) => language === 'zh' ? zh : en; + + if (subscribedReleases.length === 0) { + const subscribedRepoCount = releaseSubscriptions.size; + + return ( +
+ +

+ {subscribedRepoCount === 0 ? t('没有Release订阅', 'No Release Subscriptions') : t('没有最近的Release', 'No Recent Releases')} +

+

+ {subscribedRepoCount === 0 + ? t('从仓库页面订阅仓库Release以在此查看更新。', 'Subscribe to repository releases from the Repositories tab to see updates here.') + : t(`您已订阅 ${subscribedRepoCount} 个仓库,但没有找到最近的Release。尝试同步以获取最新更新。`, `You're subscribed to ${subscribedRepoCount} repositories, but no recent releases were found. Try syncing to get the latest updates.`) + } +

+ {subscribedRepoCount === 0 && ( +
+
+ + {t('如何订阅:', 'How to subscribe:')} +
+

+ {t('转到仓库页面,点击任何仓库卡片上的铃铛图标以订阅其Release。', 'Go to the Repositories tab and click the bell icon on any repository card to subscribe to its releases.')} +

+
+ )} +
+ ); + } + + return ( +
+ {/* Header */} +
+
+
+

+ {t('Release时间线', 'Release Timeline')} +

+

+ {t(`来自您的 ${releaseSubscriptions.size} 个订阅仓库的最新Release`, `Latest releases from your ${releaseSubscriptions.size} subscribed repositories`)} +

+
+
+ {/* View Mode Toggle */} +
+ + +
+ + {/* Last Refresh Time */} + {lastRefreshTime && ( + + {t('上次刷新:', 'Last refresh:')} {formatDistanceToNow(new Date(lastRefreshTime), { addSuffix: true })} + + )} + + {/* Refresh Button */} + +
+
+ + {/* Search and Filters */} +
+ {/* Search Bar */} +
+ + { + setSearchQuery(e.target.value); + setCurrentPage(1); + }} + className="w-full pl-10 pr-10 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-white dark:bg-gray-700 text-gray-900 dark:text-white" + /> + {searchQuery && ( + + )} +
+ + {/* Platform Filters */} + {availablePlatforms.length > 0 && ( +
+ + {t('平台:', 'Platforms:')} + + {availablePlatforms.map(platform => ( + + ))} + {(searchQuery || selectedPlatforms.length > 0) && ( + + )} +
+ )} +
+ + {/* Results Info and Pagination Controls */} +
+
+ + {t( + `显示 ${startIndex + 1}-${Math.min(startIndex + itemsPerPage, filteredReleases.length)} 共 ${filteredReleases.length} 个Release`, + `Showing ${startIndex + 1}-${Math.min(startIndex + itemsPerPage, filteredReleases.length)} of ${filteredReleases.length} releases` + )} + + {(searchQuery || selectedPlatforms.length > 0) && ( + + ({t('已筛选', 'filtered')}) + + )} +
+ +
+ {/* Items per page selector */} +
+ {t('每页:', 'Per page:')} + +
+ + {/* Pagination */} + {totalPages > 1 && ( +
+ + + + {getPageNumbers().map((page, index) => ( + + ))} + + + +
+ )} +
+
+
+ + {/* Releases List */} +
+ {paginatedReleases.map(release => { + const downloadLinks = getDownloadLinks(release); + + return ( +
+ {viewMode === 'detailed' ? ( + // Detailed View +
+
+
+
+ +
+
+

+ {release.repository.name} {release.tag_name} +

+

+ {release.repository.full_name} +

+
+
+
+ + {formatDistanceToNow(new Date(release.published_at), { addSuffix: true })} + + + + +
+
+ + {release.name && release.name !== release.tag_name && ( +
+ {release.name} +
+ )} + + {/* Download Links */} + {downloadLinks.length > 0 && ( +
+
+ {t('下载:', 'Downloads:')} +
+
+ {downloadLinks.map((link, index) => ( + +
+ {link.platforms.map((platform, pIndex) => ( + + ))} +
+ {link.name} +
+ ))} +
+
+ )} + + {release.body && ( +
+
+ {truncateBody(release.body)} +
+ {release.body.length > 200 && ( + + {t('阅读完整Release说明 →', 'Read full release notes →')} + + )} +
+ )} +
+ ) : ( + // Compact View - Table-like layout +
+
+ {/* Repository and Version - 缩小列宽 */} +
+
+
+ +
+
+

+ {release.repository.name} +

+

+ {release.tag_name} +

+
+
+
+ + {/* Release Name */} +
+

+ {release.name || release.tag_name} +

+
+ + {/* Download Links - 横向排列,可换行 */} +
+ {downloadLinks.length > 0 ? ( +
+ {downloadLinks.slice(0, 6).map((link, index) => ( + +
+ {link.platforms.map((platform, pIndex) => ( + + ))} +
+ + {link.name.split('.').pop() || link.name} + +
+ ))} + {downloadLinks.length > 6 && ( + + +{downloadLinks.length - 6} + + )} +
+ ) : ( + + {t('无下载', 'No downloads')} + + )} +
+ + {/* Time and Actions */} +
+ + {formatDistanceToNow(new Date(release.published_at), { addSuffix: true })} + + + + +
+
+
+ )} +
+ ); + })} +
+ + {/* Bottom Pagination */} + {totalPages > 1 && ( +
+
+ + + + {getPageNumbers().map((page, index) => ( + + ))} + + + +
+
+ )} +
+ ); +}; \ No newline at end of file diff --git a/src/components/RepositoryCard.tsx b/src/components/RepositoryCard.tsx new file mode 100644 index 0000000..4448b5f --- /dev/null +++ b/src/components/RepositoryCard.tsx @@ -0,0 +1,300 @@ +import React from 'react'; +import { Star, GitFork, Eye, ExternalLink, Calendar, Tag, Bell, BellOff, Bot, Monitor, Smartphone, Globe, Terminal, Package } from 'lucide-react'; +import { Repository } from '../types'; +import { useAppStore } from '../store/useAppStore'; +import { GitHubApiService } from '../services/githubApi'; +import { AIService } from '../services/aiService'; +import { formatDistanceToNow } from 'date-fns'; + +interface RepositoryCardProps { + repository: Repository; + showAISummary?: boolean; +} + +export const RepositoryCard: React.FC = ({ + repository, + showAISummary = true +}) => { + const { + releaseSubscriptions, + toggleReleaseSubscription, + updateRepository, + githubToken, + aiConfigs, + activeAIConfig, + isLoading, + setLoading, + language + } = useAppStore(); + + const isSubscribed = releaseSubscriptions.has(repository.id); + + const formatNumber = (num: number) => { + if (num >= 1000000) return `${(num / 1000000).toFixed(1)}M`; + if (num >= 1000) return `${(num / 1000).toFixed(1)}K`; + return num.toString(); + }; + + const getLanguageColor = (language: string | null) => { + const colors = { + JavaScript: '#f1e05a', + TypeScript: '#3178c6', + Python: '#3572A5', + Java: '#b07219', + 'C++': '#f34b7d', + C: '#555555', + 'C#': '#239120', + Go: '#00ADD8', + Rust: '#dea584', + PHP: '#4F5D95', + Ruby: '#701516', + Swift: '#fa7343', + Kotlin: '#A97BFF', + Dart: '#00B4AB', + Shell: '#89e051', + HTML: '#e34c26', + CSS: '#1572B6', + Vue: '#4FC08D', + React: '#61DAFB', + }; + return colors[language as keyof typeof colors] || '#6b7280'; + }; + + const getPlatformIcon = (platform: string) => { + const iconMap: Record = { + mac: 'fab fa-apple', + macos: 'fab fa-apple', + windows: 'fab fa-windows', + win: 'fab fa-windows', + linux: 'fab fa-linux', + ios: 'fab fa-apple', + android: 'fab fa-android', + web: 'fas fa-globe', + cli: 'fas fa-terminal', + docker: 'fab fa-docker', + }; + return iconMap[platform.toLowerCase()] || 'fas fa-desktop'; + }; + + const handleAIAnalyze = async () => { + if (!githubToken) { + alert('GitHub token not found. Please login again.'); + return; + } + + const activeConfig = aiConfigs.find(config => config.id === activeAIConfig); + if (!activeConfig) { + alert('请先在设置中配置AI服务。'); + return; + } + + setLoading(true); + try { + const githubApi = new GitHubApiService(githubToken); + const aiService = new AIService(activeConfig, language); + + // 获取README内容 + const [owner, name] = repository.full_name.split('/'); + const readmeContent = await githubApi.getRepositoryReadme(owner, name); + + // AI分析 + const analysis = await aiService.analyzeRepository(repository, readmeContent); + + // 更新仓库信息 + const updatedRepo = { + ...repository, + ai_summary: analysis.summary, + ai_tags: analysis.tags, + ai_platforms: analysis.platforms, + analyzed_at: new Date().toISOString() + }; + + updateRepository(updatedRepo); + alert('AI分析完成!'); + } catch (error) { + console.error('AI analysis failed:', error); + alert('AI分析失败,请检查AI配置和网络连接。'); + } finally { + setLoading(false); + } + }; + + // 根据切换状态决定显示的内容 + const getDisplayContent = () => { + if (showAISummary && repository.ai_summary) { + return { + content: repository.ai_summary, + isAI: true + }; + } else if (repository.description) { + return { + content: repository.description, + isAI: false + }; + } else { + return { + content: language === 'zh' ? '暂无描述' : 'No description available', + isAI: false + }; + } + }; + + const displayContent = getDisplayContent(); + + return ( +
+ {/* Header - Repository Info */} +
+ {repository.owner.login} +
+

+ {repository.name} +

+

+ {repository.owner.login} +

+
+
+ + {/* Action Buttons Row - Left and Right Aligned */} +
+ {/* Left side: AI Analysis and Release Subscription */} +
+ + +
+ + {/* Right side: GitHub Link - Fixed square container */} +
+ + + +
+
+ + {/* Description */} +
+

+ {displayContent.content} +

+ {displayContent.isAI && ( +
+ + {language === 'zh' ? 'AI总结' : 'AI Summary'} +
+ )} +
+ + {/* Tags */} + {(repository.ai_tags?.length || repository.topics?.length) && ( +
+ {repository.ai_tags?.slice(0, 3).map((tag, index) => ( + + + {tag} + + ))} + {repository.topics?.slice(0, 2).map((topic, index) => ( + + {topic} + + ))} +
+ )} + + {/* Platform Icons */} + {repository.ai_platforms && repository.ai_platforms.length > 0 && ( +
+ + {language === 'zh' ? '支持平台:' : 'Platforms:'} + +
+ {repository.ai_platforms.slice(0, 6).map((platform, index) => ( +
+ +
+ ))} +
+
+ )} + + {/* Stats */} +
+ {/* Language and Stars */} +
+
+ {repository.language && ( +
+
+ {repository.language} +
+ )} +
+ + {formatNumber(repository.stargazers_count)} +
+
+ + {repository.analyzed_at && ( +
+
+ {language === 'zh' ? 'AI已分析' : 'AI analyzed'} +
+ )} +
+ + {/* Update Time - Separate Row */} +
+ + + {language === 'zh' ? '更新于' : 'Updated'} {formatDistanceToNow(new Date(repository.updated_at), { addSuffix: true })} + +
+
+
+ ); +}; \ No newline at end of file diff --git a/src/components/RepositoryList.tsx b/src/components/RepositoryList.tsx new file mode 100644 index 0000000..ca6038e --- /dev/null +++ b/src/components/RepositoryList.tsx @@ -0,0 +1,416 @@ +import React, { useState, useRef } from 'react'; +import { Bot, ChevronDown, Pause, Play } from 'lucide-react'; +import { RepositoryCard } from './RepositoryCard'; +import { Repository } from '../types'; +import { useAppStore } from '../store/useAppStore'; +import { GitHubApiService } from '../services/githubApi'; +import { AIService } from '../services/aiService'; + +interface RepositoryListProps { + repositories: Repository[]; + selectedCategory: string; +} + +export const RepositoryList: React.FC = ({ + repositories, + selectedCategory +}) => { + const { + githubToken, + aiConfigs, + activeAIConfig, + isLoading, + setLoading, + updateRepository, + language, + } = useAppStore(); + + const [showAISummary, setShowAISummary] = useState(true); + const [showDropdown, setShowDropdown] = useState(false); + const [analysisProgress, setAnalysisProgress] = useState({ current: 0, total: 0 }); + const [isPaused, setIsPaused] = useState(false); + + // 使用 useRef 来管理停止状态,确保在异步操作中能正确访问最新值 + const shouldStopRef = useRef(false); + const isAnalyzingRef = useRef(false); + + // Filter repositories by selected category + const filteredRepositories = repositories.filter(repo => { + if (selectedCategory === 'all') return true; + + // 优先使用AI标签进行匹配 + if (repo.ai_tags && repo.ai_tags.length > 0) { + const categoryKeywords = getCategoryKeywords(selectedCategory); + return repo.ai_tags.some(tag => + categoryKeywords.some(keyword => + tag.toLowerCase().includes(keyword.toLowerCase()) || + keyword.toLowerCase().includes(tag.toLowerCase()) + ) + ); + } + + // 如果没有AI标签,使用传统方式匹配 + const repoText = [ + repo.name, + repo.description || '', + repo.language || '', + ...(repo.topics || []), + repo.ai_summary || '' + ].join(' ').toLowerCase(); + + const categoryKeywords = getCategoryKeywords(selectedCategory); + return categoryKeywords.some(keyword => + repoText.includes(keyword.toLowerCase()) + ); + }); + + const handleAIAnalyze = async (analyzeUnanalyzedOnly: boolean = false) => { + if (!githubToken) { + alert(language === 'zh' ? 'GitHub token 未找到,请重新登录。' : 'GitHub token not found. Please login again.'); + return; + } + + const activeConfig = aiConfigs.find(config => config.id === activeAIConfig); + if (!activeConfig) { + alert(language === 'zh' ? '请先在设置中配置AI服务。' : 'Please configure AI service in settings first.'); + return; + } + + const targetRepos = analyzeUnanalyzedOnly + ? filteredRepositories.filter(repo => !repo.analyzed_at) + : filteredRepositories; + + if (targetRepos.length === 0) { + alert(language === 'zh' + ? (analyzeUnanalyzedOnly ? '所有仓库都已经分析过了!' : '没有可分析的仓库!') + : (analyzeUnanalyzedOnly ? 'All repositories have been analyzed!' : 'No repositories to analyze!') + ); + return; + } + + const actionText = language === 'zh' + ? (analyzeUnanalyzedOnly ? '未分析' : '全部') + : (analyzeUnanalyzedOnly ? 'unanalyzed' : 'all'); + + const confirmMessage = language === 'zh' + ? `将对 ${targetRepos.length} 个${actionText}仓库进行AI分析,这可能需要几分钟时间。是否继续?` + : `Will analyze ${targetRepos.length} ${actionText} repositories with AI. This may take several minutes. Continue?`; + + const confirmed = confirm(confirmMessage); + if (!confirmed) return; + + // 重置状态 + shouldStopRef.current = false; + isAnalyzingRef.current = true; + setLoading(true); + setAnalysisProgress({ current: 0, total: targetRepos.length }); + setShowDropdown(false); + setIsPaused(false); + + try { + const githubApi = new GitHubApiService(githubToken); + const aiService = new AIService(activeConfig, language); + + let analyzed = 0; + + for (let i = 0; i < targetRepos.length; i++) { + // 检查是否需要停止 + if (shouldStopRef.current) { + console.log('Analysis stopped by user'); + break; + } + + // 处理暂停 + while (isPaused && !shouldStopRef.current) { + await new Promise(resolve => setTimeout(resolve, 1000)); + } + + // 再次检查停止状态(暂停期间可能被停止) + if (shouldStopRef.current) { + console.log('Analysis stopped during pause'); + break; + } + + const repo = targetRepos[i]; + setAnalysisProgress({ current: i + 1, total: targetRepos.length }); + + try { + // 获取README内容 + const [owner, name] = repo.full_name.split('/'); + const readmeContent = await githubApi.getRepositoryReadme(owner, name); + + // AI分析 + const analysis = await aiService.analyzeRepository(repo, readmeContent); + + // 更新仓库信息 + const updatedRepo = { + ...repo, + ai_summary: analysis.summary, + ai_tags: analysis.tags, + ai_platforms: analysis.platforms, + analyzed_at: new Date().toISOString() + }; + + updateRepository(updatedRepo); + analyzed++; + + // 避免API限制 + await new Promise(resolve => setTimeout(resolve, 1000)); + } catch (error) { + console.warn(`Failed to analyze ${repo.full_name}:`, error); + } + } + + const completionMessage = shouldStopRef.current + ? (language === 'zh' + ? `AI分析已停止!已成功分析了 ${analyzed} 个仓库。` + : `AI analysis stopped! Successfully analyzed ${analyzed} repositories.`) + : (language === 'zh' + ? `AI分析完成!成功分析了 ${analyzed} 个仓库。` + : `AI analysis completed! Successfully analyzed ${analyzed} repositories.`); + + alert(completionMessage); + } catch (error) { + console.error('AI analysis failed:', error); + const errorMessage = language === 'zh' + ? 'AI分析失败,请检查AI配置和网络连接。' + : 'AI analysis failed. Please check AI configuration and network connection.'; + alert(errorMessage); + } finally { + // 清理状态 + isAnalyzingRef.current = false; + shouldStopRef.current = false; + setLoading(false); + setAnalysisProgress({ current: 0, total: 0 }); + setIsPaused(false); + } + }; + + const handlePauseResume = () => { + if (!isAnalyzingRef.current) return; + setIsPaused(!isPaused); + console.log(isPaused ? 'Analysis resumed' : 'Analysis paused'); + }; + + const handleStop = () => { + if (!isAnalyzingRef.current) return; + + const confirmMessage = language === 'zh' + ? '确定要停止AI分析吗?已分析的结果将会保存。' + : 'Are you sure you want to stop AI analysis? Analyzed results will be saved.'; + + if (confirm(confirmMessage)) { + shouldStopRef.current = true; + setIsPaused(false); + console.log('Stop requested by user'); + } + }; + + if (filteredRepositories.length === 0) { + return ( +
+

+ {selectedCategory === 'all' + ? (language === 'zh' ? '未找到仓库。点击同步加载您的星标仓库。' : 'No repositories found. Click sync to load your starred repositories.') + : (language === 'zh' + ? `在"${getCategoryName(selectedCategory)}"分类中未找到仓库。` + : `No repositories found in "${getCategoryName(selectedCategory)}" category.` + ) + } +

+
+ ); + } + + const unanalyzedCount = filteredRepositories.filter(r => !r.analyzed_at).length; + const analyzedCount = filteredRepositories.filter(r => r.analyzed_at).length; + + const t = (zh: string, en: string) => language === 'zh' ? zh : en; + + return ( +
+ {/* AI Analysis Controls */} +
+
+ {/* AI Analysis Dropdown Button */} +
+ + + {/* Dropdown Menu */} + {showDropdown && !isLoading && ( +
+ + +
+ )} +
+ + {/* Progress Bar and Controls */} + {isLoading && analysisProgress.total > 0 && ( +
+
+
+
+ + {Math.round((analysisProgress.current / analysisProgress.total) * 100)}% + + + +
+ )} + + {/* Description Toggle - Radio Style */} + {!isLoading && ( +
+ + {t('显示内容:', 'Display:')} + +
+ + +
+
+ )} +
+ + {/* Statistics */} +
+ {t(`显示 ${filteredRepositories.length} 个仓库`, `Showing ${filteredRepositories.length} repositories`)} + {analyzedCount > 0 && ( + + • {analyzedCount} {t('个已AI分析', 'AI analyzed')} + + )} + {unanalyzedCount > 0 && ( + + • {unanalyzedCount} {t('个未分析', 'unanalyzed')} + + )} +
+
+ + {/* Repository Grid */} +
+ {filteredRepositories.map(repo => ( + + ))} +
+
+ ); +}; + +// Helper function to get category keywords +function getCategoryKeywords(categoryId: string): string[] { + const categoryMap: Record = { + 'web': ['web应用', 'web', 'website', 'frontend', 'react', 'vue', 'angular'], + 'mobile': ['移动应用', 'mobile', 'android', 'ios', 'flutter', 'react-native'], + 'desktop': ['桌面应用', 'desktop', 'electron', 'gui', 'qt', 'gtk'], + 'database': ['数据库', 'database', 'sql', 'nosql', 'mongodb', 'mysql', 'postgresql'], + 'ai': ['ai工具', 'ai', 'ml', 'machine learning', 'deep learning', 'neural'], + 'devtools': ['开发工具', 'tool', 'cli', 'build', 'deploy', 'debug', 'test', 'automation'], + 'security': ['安全工具', 'security', 'encryption', 'auth', 'vulnerability'], + 'game': ['游戏', 'game', 'gaming', 'unity', 'unreal', 'godot'], + 'design': ['设计工具', 'design', 'ui', 'ux', 'graphics', 'image'], + 'productivity': ['效率工具', 'productivity', 'note', 'todo', 'calendar', 'task'], + 'education': ['教育学习', 'education', 'learning', 'tutorial', 'course'], + 'social': ['社交网络', 'social', 'chat', 'messaging', 'communication'], + 'analytics': ['数据分析', 'analytics', 'data', 'visualization', 'chart'] + }; + + return categoryMap[categoryId] || []; +} + +// Helper function to get category name +function getCategoryName(categoryId: string): string { + const nameMap: Record = { + 'web': 'Web应用', + 'mobile': '移动应用', + 'desktop': '桌面应用', + 'database': '数据库', + 'ai': 'AI/机器学习', + 'devtools': '开发工具', + 'security': '安全工具', + 'game': '游戏', + 'design': '设计工具', + 'productivity': '效率工具', + 'education': '教育学习', + 'social': '社交网络', + 'analytics': '数据分析' + }; + + return nameMap[categoryId] || categoryId; +} \ No newline at end of file diff --git a/src/components/SearchBar.tsx b/src/components/SearchBar.tsx new file mode 100644 index 0000000..35d8abe --- /dev/null +++ b/src/components/SearchBar.tsx @@ -0,0 +1,520 @@ +import React, { useState, useEffect } from 'react'; +import { Search, Filter, X, SlidersHorizontal, Monitor, Smartphone, Globe, Terminal, Package, CheckCircle, Bell } from 'lucide-react'; +import { useAppStore } from '../store/useAppStore'; +import { AIService } from '../services/aiService'; + +export const SearchBar: React.FC = () => { + const { + searchFilters, + repositories, + releaseSubscriptions, + aiConfigs, + activeAIConfig, + language, + setSearchFilters, + setSearchResults, + } = useAppStore(); + + const [showFilters, setShowFilters] = useState(false); + const [searchQuery, setSearchQuery] = useState(searchFilters.query); + const [isSearching, setIsSearching] = useState(false); + const [availableLanguages, setAvailableLanguages] = useState([]); + const [availableTags, setAvailableTags] = useState([]); + const [availablePlatforms, setAvailablePlatforms] = useState([]); + + useEffect(() => { + // Extract unique languages, tags, and platforms from repositories + const languages = [...new Set(repositories.map(r => r.language).filter(Boolean))]; + const tags = [...new Set([ + ...repositories.flatMap(r => r.ai_tags || []), + ...repositories.flatMap(r => r.topics || []) + ])]; + const platforms = [...new Set(repositories.flatMap(r => r.ai_platforms || []))]; + + setAvailableLanguages(languages); + setAvailableTags(tags); + setAvailablePlatforms(platforms); + }, [repositories]); + + useEffect(() => { + // Perform search when filters change (except query) + const performSearch = async () => { + if (searchFilters.query && !isSearching) { + setIsSearching(true); + await performAdvancedSearch(); + setIsSearching(false); + } else if (!searchFilters.query) { + performBasicFilter(); + } + }; + + performSearch(); + }, [searchFilters, repositories, releaseSubscriptions]); + + const performAdvancedSearch = async () => { + let filtered = repositories; + + // AI-powered natural language search + if (searchFilters.query) { + const activeConfig = aiConfigs.find(config => config.id === activeAIConfig); + if (activeConfig) { + try { + const aiService = new AIService(activeConfig, language); + filtered = await aiService.searchRepositories(filtered, searchFilters.query); + } catch (error) { + console.warn('AI search failed, falling back to basic search:', error); + // Fallback to basic text search + filtered = performBasicTextSearch(filtered, searchFilters.query); + } + } else { + // Basic text search if no AI config + filtered = performBasicTextSearch(filtered, searchFilters.query); + } + } + + // Apply other filters + filtered = applyFilters(filtered); + setSearchResults(filtered); + }; + + const performBasicFilter = () => { + const filtered = applyFilters(repositories); + setSearchResults(filtered); + }; + + const performBasicTextSearch = (repos: typeof repositories, query: string) => { + const normalizedQuery = query.toLowerCase(); + + return repos.filter(repo => { + const searchableText = [ + repo.name, + repo.full_name, + repo.description || '', + repo.language || '', + ...(repo.topics || []), + repo.ai_summary || '', + ...(repo.ai_tags || []), + ...(repo.ai_platforms || []), + ].join(' ').toLowerCase(); + + // Split query into words and check if all words are present + const queryWords = normalizedQuery.split(/\s+/); + return queryWords.every(word => searchableText.includes(word)); + }); + }; + + const applyFilters = (repos: typeof repositories) => { + let filtered = repos; + + // Language filter + if (searchFilters.languages.length > 0) { + filtered = filtered.filter(repo => + repo.language && searchFilters.languages.includes(repo.language) + ); + } + + // Tag filter + if (searchFilters.tags.length > 0) { + filtered = filtered.filter(repo => { + const repoTags = [...(repo.ai_tags || []), ...(repo.topics || [])]; + return searchFilters.tags.some(tag => repoTags.includes(tag)); + }); + } + + // Platform filter + if (searchFilters.platforms.length > 0) { + filtered = filtered.filter(repo => { + const repoPlatforms = repo.ai_platforms || []; + return searchFilters.platforms.some(platform => repoPlatforms.includes(platform)); + }); + } + + // AI analyzed filter + if (searchFilters.isAnalyzed !== undefined) { + filtered = filtered.filter(repo => + searchFilters.isAnalyzed ? !!repo.analyzed_at : !repo.analyzed_at + ); + } + + // Release subscription filter + if (searchFilters.isSubscribed !== undefined) { + filtered = filtered.filter(repo => + searchFilters.isSubscribed ? releaseSubscriptions.has(repo.id) : !releaseSubscriptions.has(repo.id) + ); + } + + // Star count filter + if (searchFilters.minStars !== undefined) { + filtered = filtered.filter(repo => repo.stargazers_count >= searchFilters.minStars!); + } + if (searchFilters.maxStars !== undefined) { + filtered = filtered.filter(repo => repo.stargazers_count <= searchFilters.maxStars!); + } + + // Sort + filtered.sort((a, b) => { + let aValue: any, bValue: any; + + switch (searchFilters.sortBy) { + case 'stars': + aValue = a.stargazers_count; + bValue = b.stargazers_count; + break; + case 'updated': + aValue = new Date(a.updated_at).getTime(); + bValue = new Date(b.updated_at).getTime(); + break; + case 'name': + aValue = a.name.toLowerCase(); + bValue = b.name.toLowerCase(); + break; + default: + aValue = new Date(a.updated_at).getTime(); + bValue = new Date(b.updated_at).getTime(); + } + + if (searchFilters.sortOrder === 'desc') { + return bValue > aValue ? 1 : -1; + } else { + return aValue > bValue ? 1 : -1; + } + }); + + return filtered; + }; + + const handleSearch = () => { + setSearchFilters({ query: searchQuery }); + }; + + const handleClearSearch = () => { + setSearchQuery(''); + setSearchFilters({ query: '' }); + }; + + const handleKeyPress = (e: React.KeyboardEvent) => { + if (e.key === 'Enter') { + handleSearch(); + } + }; + + const handleLanguageToggle = (language: string) => { + const newLanguages = searchFilters.languages.includes(language) + ? searchFilters.languages.filter(l => l !== language) + : [...searchFilters.languages, language]; + setSearchFilters({ languages: newLanguages }); + }; + + const handleTagToggle = (tag: string) => { + const newTags = searchFilters.tags.includes(tag) + ? searchFilters.tags.filter(t => t !== tag) + : [...searchFilters.tags, tag]; + setSearchFilters({ tags: newTags }); + }; + + const handlePlatformToggle = (platform: string) => { + const newPlatforms = searchFilters.platforms.includes(platform) + ? searchFilters.platforms.filter(p => p !== platform) + : [...searchFilters.platforms, platform]; + setSearchFilters({ platforms: newPlatforms }); + }; + + const clearFilters = () => { + setSearchQuery(''); + setSearchFilters({ + query: '', + tags: [], + languages: [], + platforms: [], + sortBy: 'stars', + sortOrder: 'desc', + minStars: undefined, + maxStars: undefined, + isAnalyzed: undefined, + isSubscribed: undefined, + }); + }; + + const activeFiltersCount = + searchFilters.languages.length + + searchFilters.tags.length + + searchFilters.platforms.length + + (searchFilters.minStars !== undefined ? 1 : 0) + + (searchFilters.maxStars !== undefined ? 1 : 0) + + (searchFilters.isAnalyzed !== undefined ? 1 : 0) + + (searchFilters.isSubscribed !== undefined ? 1 : 0); + + const getPlatformIcon = (platform: string) => { + const iconMap: Record = { + mac: 'fab fa-apple', + macos: 'fab fa-apple', + windows: 'fab fa-windows', + win: 'fab fa-windows', + linux: 'fab fa-linux', + ios: 'fab fa-apple', + android: 'fab fa-android', + web: 'fas fa-globe', + cli: 'fas fa-terminal', + docker: 'fab fa-docker', + }; + return iconMap[platform.toLowerCase()] || 'fas fa-desktop'; + }; + + const t = (zh: string, en: string) => language === 'zh' ? zh : en; + + return ( +
+ {/* Search Input */} +
+ + setSearchQuery(e.target.value)} + onKeyPress={handleKeyPress} + className="w-full pl-10 pr-32 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-white dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-500 dark:placeholder-gray-400" + /> +
+ {searchQuery && ( + + )} + +
+
+ + {/* Filter Controls */} +
+
+ + + {activeFiltersCount > 0 && ( + + )} +
+ + {/* Sort Controls */} +
+ + +
+
+ + {/* Advanced Filters */} + {showFilters && ( +
+ {/* Status Filters */} +
+

+ {t('状态过滤', 'Status Filters')} +

+
+ + + +
+
+ + {/* Languages */} + {availableLanguages.length > 0 && ( +
+

+ {t('编程语言', 'Programming Languages')} +

+
+ {availableLanguages.slice(0, 12).map(language => ( + + ))} +
+
+ )} + + {/* Platforms */} + {availablePlatforms.length > 0 && ( +
+

+ {t('支持平台', 'Supported Platforms')} +

+
+ {availablePlatforms.map(platform => ( + + ))} +
+
+ )} + + {/* Tags */} + {availableTags.length > 0 && ( +
+

+ {t('标签', 'Tags')} +

+
+ {availableTags.slice(0, 15).map(tag => ( + + ))} +
+
+ )} + + {/* Star Range */} +
+

+ {t('Star数量范围', 'Star Count Range')} +

+
+
+ + setSearchFilters({ + minStars: e.target.value ? parseInt(e.target.value) : undefined + })} + className="w-24 px-3 py-1.5 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white text-sm" + /> +
+
+ + setSearchFilters({ + maxStars: e.target.value ? parseInt(e.target.value) : undefined + })} + className="w-24 px-3 py-1.5 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white text-sm" + /> +
+
+
+
+ )} +
+ ); +}; \ No newline at end of file diff --git a/src/components/SettingsPanel.tsx b/src/components/SettingsPanel.tsx new file mode 100644 index 0000000..13df0a8 --- /dev/null +++ b/src/components/SettingsPanel.tsx @@ -0,0 +1,1112 @@ +import React, { useState, useRef } from 'react'; +import { Plus, Save, Trash2, Check, X, Settings, Bot, Key, TestTube, Globe, Cloud, Upload, Download, AlertTriangle, CheckCircle, Info, FileDown, FileUp } from 'lucide-react'; +import { useAppStore } from '../store/useAppStore'; +import { AIConfig, WebDAVConfig } from '../types'; +import { AIService } from '../services/aiService'; +import { WebDAVService } from '../services/webdavService'; + +export const SettingsPanel: React.FC = () => { + const { + aiConfigs, + activeAIConfig, + webdavConfigs, + activeWebDAVConfig, + lastBackup, + githubToken, + language, + repositories, + releaseSubscriptions, + addAIConfig, + updateAIConfig, + deleteAIConfig, + setActiveAIConfig, + addWebDAVConfig, + updateWebDAVConfig, + deleteWebDAVConfig, + setActiveWebDAVConfig, + setLastBackup, + setGitHubToken, + setLanguage, + setRepositories, + setReleases, + } = useAppStore(); + + const [isAddingAIConfig, setIsAddingAIConfig] = useState(false); + const [isAddingWebDAVConfig, setIsAddingWebDAVConfig] = useState(false); + const [editingConfigId, setEditingConfigId] = useState(null); + const [testingConfigId, setTestingConfigId] = useState(null); + const [testingWebDAVId, setTestingWebDAVId] = useState(null); + const [backupStatus, setBackupStatus] = useState<'idle' | 'backing-up' | 'restoring' | 'exporting' | 'importing'>('idle'); + const [newAIConfig, setNewAIConfig] = useState>({ + name: '', + baseUrl: 'https://api.openai.com/v1', + apiKey: '', + model: 'gpt-3.5-turbo', + }); + const [newWebDAVConfig, setNewWebDAVConfig] = useState>({ + name: '', + url: '', + username: '', + password: '', + path: '/github-stars-backup', + }); + + const fileInputRef = useRef(null); + + const handleSaveAIConfig = () => { + if (!newAIConfig.name || !newAIConfig.baseUrl || !newAIConfig.apiKey || !newAIConfig.model) { + alert(language === 'zh' ? '请填写所有字段' : 'Please fill in all fields'); + return; + } + + const config: AIConfig = { + id: Date.now().toString(), + name: newAIConfig.name, + baseUrl: newAIConfig.baseUrl, + apiKey: newAIConfig.apiKey, + model: newAIConfig.model, + isActive: aiConfigs.length === 0, + }; + + addAIConfig(config); + if (config.isActive) { + setActiveAIConfig(config.id); + } + + setNewAIConfig({ + name: '', + baseUrl: 'https://api.openai.com/v1', + apiKey: '', + model: 'gpt-3.5-turbo', + }); + setIsAddingAIConfig(false); + }; + + const handleSaveWebDAVConfig = () => { + const errors = WebDAVService.validateConfig(newWebDAVConfig); + if (errors.length > 0) { + alert(errors.join('\n')); + return; + } + + const config: WebDAVConfig = { + id: Date.now().toString(), + name: newWebDAVConfig.name!, + url: newWebDAVConfig.url!, + username: newWebDAVConfig.username!, + password: newWebDAVConfig.password!, + path: newWebDAVConfig.path!, + isActive: webdavConfigs.length === 0, + }; + + addWebDAVConfig(config); + if (config.isActive) { + setActiveWebDAVConfig(config.id); + } + + setNewWebDAVConfig({ + name: '', + url: '', + username: '', + password: '', + path: '/github-stars-backup', + }); + setIsAddingWebDAVConfig(false); + }; + + const handleTestAIConfig = async (config: AIConfig) => { + setTestingConfigId(config.id); + try { + const aiService = new AIService(config, language); + const isWorking = await aiService.testConnection(); + + const successMessage = language === 'zh' + ? '✅ 连接成功!AI配置正常工作。' + : '✅ Connection successful! AI configuration is working.'; + + const failMessage = language === 'zh' + ? '❌ 连接失败。请检查您的配置。' + : '❌ Connection failed. Please check your configuration.'; + + alert(isWorking ? successMessage : failMessage); + } catch (error) { + const errorMessage = language === 'zh' + ? `❌ 连接失败: ${error instanceof Error ? error.message : '未知错误'}` + : `❌ Connection failed: ${error instanceof Error ? error.message : 'Unknown error'}`; + alert(errorMessage); + } finally { + setTestingConfigId(null); + } + }; + + const handleTestWebDAVConfig = async (config: WebDAVConfig) => { + setTestingWebDAVId(config.id); + try { + const webdavService = new WebDAVService(config); + const isWorking = await webdavService.testConnection(); + + if (isWorking) { + // 获取服务器信息 + const serverInfo = await webdavService.getServerInfo(); + let message = language === 'zh' + ? '✅ WebDAV连接成功!' + : '✅ WebDAV connection successful!'; + + if (serverInfo.server) { + message += `\n${language === 'zh' ? '服务器' : 'Server'}: ${serverInfo.server}`; + } + if (serverInfo.davLevel) { + message += `\n${language === 'zh' ? 'DAV级别' : 'DAV Level'}: ${serverInfo.davLevel}`; + } + + alert(message); + } else { + alert(language === 'zh' + ? '❌ WebDAV连接失败。请检查您的配置。' + : '❌ WebDAV connection failed. Please check your configuration.'); + } + } catch (error) { + const errorMessage = language === 'zh' + ? `❌ WebDAV连接测试失败:\n\n${error instanceof Error ? error.message : '未知错误'}` + : `❌ WebDAV connection test failed:\n\n${error instanceof Error ? error.message : 'Unknown error'}`; + alert(errorMessage); + } finally { + setTestingWebDAVId(null); + } + }; + + const handleSetActiveAI = (configId: string) => { + aiConfigs.forEach(config => { + updateAIConfig(config.id, { isActive: config.id === configId }); + }); + setActiveAIConfig(configId); + }; + + const handleSetActiveWebDAV = (configId: string) => { + webdavConfigs.forEach(config => { + updateWebDAVConfig(config.id, { isActive: config.id === configId }); + }); + setActiveWebDAVConfig(configId); + }; + + const handleBackupToWebDAV = async () => { + const activeConfig = webdavConfigs.find(config => config.id === activeWebDAVConfig); + if (!activeConfig) { + alert(language === 'zh' ? '请先配置并激活WebDAV服务。' : 'Please configure and activate WebDAV service first.'); + return; + } + + setBackupStatus('backing-up'); + try { + const webdavService = new WebDAVService(activeConfig); + + // 准备备份数据 - 保留真实的敏感信息 + const backupData = { + version: '1.0', + timestamp: new Date().toISOString(), + repositories: repositories, + aiConfigs: aiConfigs, // 保留完整的AI配置包括API密钥 + webdavConfigs: webdavConfigs, // 保留完整的WebDAV配置包括密码 + releaseSubscriptions: Array.from(releaseSubscriptions), + settings: { + language, + lastBackup, + activeAIConfig, + activeWebDAVConfig, + } + }; + + const filename = `github-stars-backup-${new Date().toISOString().split('T')[0]}.json`; + const content = JSON.stringify(backupData, null, 2); + + await webdavService.uploadFile(filename, content); + + const now = new Date().toISOString(); + setLastBackup(now); + + alert(language === 'zh' + ? `✅ 备份成功!\n文件名: ${filename}\n备份时间: ${new Date(now).toLocaleString()}` + : `✅ Backup successful!\nFilename: ${filename}\nBackup time: ${new Date(now).toLocaleString()}` + ); + } catch (error) { + console.error('Backup failed:', error); + const errorMessage = language === 'zh' + ? `❌ 备份失败:\n\n${error instanceof Error ? error.message : '未知错误'}` + : `❌ Backup failed:\n\n${error instanceof Error ? error.message : 'Unknown error'}`; + alert(errorMessage); + } finally { + setBackupStatus('idle'); + } + }; + + const handleRestoreFromWebDAV = async () => { + const activeConfig = webdavConfigs.find(config => config.id === activeWebDAVConfig); + if (!activeConfig) { + alert(language === 'zh' ? '请先配置并激活WebDAV服务。' : 'Please configure and activate WebDAV service first.'); + return; + } + + const confirmMessage = language === 'zh' + ? '⚠️ 恢复操作将覆盖当前的仓库数据和配置。\n\n确定要继续吗?' + : '⚠️ Restore operation will overwrite current repository data and configurations.\n\nAre you sure you want to continue?'; + + if (!confirm(confirmMessage)) return; + + setBackupStatus('restoring'); + try { + const webdavService = new WebDAVService(activeConfig); + + // 列出可用的备份文件 + const files = await webdavService.listFiles(); + const backupFiles = files.filter(file => file.startsWith('github-stars-backup-')); + + if (backupFiles.length === 0) { + alert(language === 'zh' ? '没有找到备份文件。' : 'No backup files found.'); + return; + } + + // 选择最新的备份文件 + const latestBackup = backupFiles.sort().reverse()[0]; + const content = await webdavService.downloadFile(latestBackup); + + if (!content) { + alert(language === 'zh' ? '无法读取备份文件。' : 'Unable to read backup file.'); + return; + } + + const backupData = JSON.parse(content); + + // 恢复数据 + if (backupData.repositories) { + setRepositories(backupData.repositories); + } + if (backupData.releases) { + setReleases(backupData.releases); + } + + alert(language === 'zh' + ? `✅ 恢复成功!\n备份文件: ${latestBackup}\n备份时间: ${new Date(backupData.timestamp).toLocaleString()}\n仓库数量: ${backupData.repositories?.length || 0}\n\n页面将刷新以应用更改。` + : `✅ Restore successful!\nBackup file: ${latestBackup}\nBackup time: ${new Date(backupData.timestamp).toLocaleString()}\nRepositories: ${backupData.repositories?.length || 0}\n\nPage will refresh to apply changes.` + ); + + // 刷新页面以确保所有状态正确更新 + setTimeout(() => window.location.reload(), 2000); + } catch (error) { + console.error('Restore failed:', error); + const errorMessage = language === 'zh' + ? `❌ 恢复失败:\n\n${error instanceof Error ? error.message : '未知错误'}` + : `❌ Restore failed:\n\n${error instanceof Error ? error.message : 'Unknown error'}`; + alert(errorMessage); + } finally { + setBackupStatus('idle'); + } + }; + + const handleExportConfig = () => { + setBackupStatus('exporting'); + try { + // 准备导出数据 - 保留真实的敏感信息用于本地备份 + const exportData = { + version: '1.0', + timestamp: new Date().toISOString(), + aiConfigs: aiConfigs, // 保留完整的AI配置包括API密钥 + webdavConfigs: webdavConfigs, // 保留完整的WebDAV配置包括密码 + settings: { + language, + activeAIConfig, + activeWebDAVConfig, + } + }; + + const content = JSON.stringify(exportData, null, 2); + const blob = new Blob([content], { type: 'application/json' }); + const url = URL.createObjectURL(blob); + + const a = document.createElement('a'); + a.href = url; + a.download = `github-stars-config-${new Date().toISOString().split('T')[0]}.json`; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); + + alert(language === 'zh' + ? '✅ 配置导出成功!文件已下载到您的设备。\n\n注意:此文件包含敏感信息(API密钥、密码),请妥善保管。' + : '✅ Configuration exported successfully! File has been downloaded to your device.\n\nNote: This file contains sensitive information (API keys, passwords), please keep it secure.' + ); + } catch (error) { + console.error('Export failed:', error); + alert(language === 'zh' + ? `❌ 导出失败: ${error instanceof Error ? error.message : '未知错误'}` + : `❌ Export failed: ${error instanceof Error ? error.message : 'Unknown error'}` + ); + } finally { + setBackupStatus('idle'); + } + }; + + const handleImportConfig = () => { + fileInputRef.current?.click(); + }; + + const handleFileImport = async (event: React.ChangeEvent) => { + const file = event.target.files?.[0]; + if (!file) return; + + setBackupStatus('importing'); + try { + const content = await file.text(); + const importData = JSON.parse(content); + + // 验证导入数据格式 + if (!importData.version || !importData.timestamp) { + throw new Error(language === 'zh' ? '无效的配置文件格式' : 'Invalid configuration file format'); + } + + const confirmMessage = language === 'zh' + ? `⚠️ 导入配置将覆盖当前的AI和WebDAV配置。\n\n配置文件信息:\n• 创建时间: ${new Date(importData.timestamp).toLocaleString()}\n• AI配置: ${importData.aiConfigs?.length || 0} 个\n• WebDAV配置: ${importData.webdavConfigs?.length || 0} 个\n\n确定要继续吗?` + : `⚠️ Importing configuration will overwrite current AI and WebDAV configurations.\n\nConfiguration file info:\n• Created: ${new Date(importData.timestamp).toLocaleString()}\n• AI configs: ${importData.aiConfigs?.length || 0}\n• WebDAV configs: ${importData.webdavConfigs?.length || 0}\n\nAre you sure you want to continue?`; + + if (!confirm(confirmMessage)) return; + + // 导入AI配置(包含完整信息) + if (importData.aiConfigs && Array.isArray(importData.aiConfigs)) { + importData.aiConfigs.forEach((config: any) => { + if (config.name && config.baseUrl && config.model) { + const newConfig: AIConfig = { + id: Date.now().toString() + Math.random().toString(36).substr(2, 9), + name: `${config.name} (导入)`, + baseUrl: config.baseUrl, + apiKey: config.apiKey || '', // 保留原始API密钥 + model: config.model, + isActive: false, + }; + addAIConfig(newConfig); + } + }); + } + + // 导入WebDAV配置(包含完整信息) + if (importData.webdavConfigs && Array.isArray(importData.webdavConfigs)) { + importData.webdavConfigs.forEach((config: any) => { + if (config.name && config.url && config.username && config.path) { + const newConfig: WebDAVConfig = { + id: Date.now().toString() + Math.random().toString(36).substr(2, 9), + name: `${config.name} (导入)`, + url: config.url, + username: config.username, + password: config.password || '', // 保留原始密码 + path: config.path, + isActive: false, + }; + addWebDAVConfig(newConfig); + } + }); + } + + // 导入设置 + if (importData.settings) { + if (importData.settings.language) { + setLanguage(importData.settings.language); + } + } + + const hasCredentials = importData.aiConfigs?.some((c: any) => c.apiKey && c.apiKey !== '***') || + importData.webdavConfigs?.some((c: any) => c.password && c.password !== '***'); + + alert(language === 'zh' + ? `✅ 配置导入成功!${hasCredentials ? '\n\n所有配置信息(包括API密钥和密码)已完整导入。' : '\n\n注意:如果配置中缺少API密钥和密码,请手动补充。'}` + : `✅ Configuration imported successfully!${hasCredentials ? '\n\nAll configuration information (including API keys and passwords) has been imported completely.' : '\n\nNote: If API keys and passwords are missing from the configuration, please add them manually.'}` + ); + } catch (error) { + console.error('Import failed:', error); + alert(language === 'zh' + ? `❌ 导入失败: ${error instanceof Error ? error.message : '未知错误'}` + : `❌ Import failed: ${error instanceof Error ? error.message : 'Unknown error'}` + ); + } finally { + setBackupStatus('idle'); + // 清除文件输入 + if (fileInputRef.current) { + fileInputRef.current.value = ''; + } + } + }; + + const presetAIConfigs = [ + { + name: 'OpenAI GPT-3.5', + baseUrl: 'https://api.openai.com/v1', + model: 'gpt-3.5-turbo', + }, + { + name: 'OpenAI GPT-4', + baseUrl: 'https://api.openai.com/v1', + model: 'gpt-4', + }, + { + name: 'Anthropic Claude', + baseUrl: 'https://api.anthropic.com/v1', + model: 'claude-3-sonnet-20240229', + }, + ]; + + const presetWebDAVConfigs = [ + { + name: 'Nextcloud', + url: 'https://your-nextcloud.com/remote.php/dav/files/username', + path: '/github-stars-backup', + }, + { + name: 'ownCloud', + url: 'https://your-owncloud.com/remote.php/webdav', + path: '/github-stars-backup', + }, + { + name: '坚果云', + url: 'https://dav.jianguoyun.com/dav', + path: '/github-stars-backup', + }, + ]; + + const t = (zh: string, en: string) => language === 'zh' ? zh : en; + + return ( +
+
+

+ {t('设置', 'Settings')} +

+

+ {t('配置您的AI服务、WebDAV备份和应用程序偏好', 'Configure your AI services, WebDAV backup, and application preferences')} +

+
+ + {/* Configuration Import/Export Section */} +
+
+
+ +
+
+

+ {t('配置管理', 'Configuration Management')} +

+

+ {t('导入和导出您的应用配置', 'Import and export your application configurations')} +

+
+
+ +
+ + + +
+ + + +
+
+ +
+

{t('配置导入导出说明', 'Configuration Import/Export Notes')}

+
    +
  • {t('导出的配置文件包含完整的API密钥和密码信息', 'Exported configuration files contain complete API keys and password information')}
  • +
  • {t('请妥善保管导出的配置文件,避免泄露敏感信息', 'Please keep exported configuration files secure to avoid leaking sensitive information')}
  • +
  • {t('导入配置将完整恢复所有设置,包括敏感信息', 'Importing configuration will completely restore all settings, including sensitive information')}
  • +
  • {t('建议定期导出配置作为备份', 'It is recommended to export configuration regularly as backup')}
  • +
+
+
+
+
+ + {/* Language Settings */} +
+
+
+ +
+
+

+ {t('语言设置', 'Language Settings')} +

+

+ {t('选择界面语言和AI分析语言', 'Choose interface language and AI analysis language')} +

+
+
+ +
+
+ + +
+

+ {t( + '此设置将影响界面显示语言和AI分析生成的标签、描述的语言。', + 'This setting affects the interface display language and the language of AI-generated tags and descriptions.' + )} +

+
+
+ + {/* GitHub Token Section */} +
+
+
+ +
+
+

+ {t('GitHub访问令牌', 'GitHub Access Token')} +

+

+ {t('用于GitHub API的个人访问令牌', 'Personal access token for GitHub API')} +

+
+
+ +
+
+ setGitHubToken(e.target.value)} + className="flex-1 px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white" + /> + + {githubToken ? t('已连接', 'Connected') : t('未设置', 'Not Set')} + +
+

+ {t('在', 'Create a personal access token at')}{' '} + + {t('GitHub设置', 'GitHub Settings')} + {' '} + {t('创建个人访问令牌,需要\'repo\'和\'user\'权限。', 'with \'repo\' and \'user\' scopes.')} +

+
+
+ + {/* WebDAV Backup Section */} +
+
+
+
+ +
+
+

+ {t('WebDAV备份', 'WebDAV Backup')} +

+

+ {t('配置WebDAV服务器以备份和恢复数据', 'Configure WebDAV server for data backup and restore')} +

+
+
+ +
+ + {/* WebDAV Status and Actions */} + {webdavConfigs.length > 0 && ( +
+
+
+
+ + {activeWebDAVConfig + ? t('WebDAV已配置', 'WebDAV Configured') + : t('WebDAV未激活', 'WebDAV Not Active') + } + + {lastBackup && ( + + {t('上次备份:', 'Last backup:')} {new Date(lastBackup).toLocaleString()} + + )} +
+
+ + +
+
+ + {/* CORS Warning */} +
+ +
+

+ {t('重要提示:CORS配置', 'Important: CORS Configuration')} +

+

+ {t( + '如果遇到连接错误,请确保您的WebDAV服务器配置了正确的CORS头。点击测试连接按钮查看详细的错误信息和解决方案。', + 'If you encounter connection errors, ensure your WebDAV server is configured with proper CORS headers. Click the test connection button for detailed error messages and solutions.' + )} +

+
+
+
+ )} + + {/* Existing WebDAV Configurations */} +
+ {webdavConfigs.map(config => ( +
+
+
+

+ {config.name} + {config.id === activeWebDAVConfig && ( + + {t('活跃', 'Active')} + + )} +

+

+ {config.url} • {config.path} +

+
+
+ + {config.id !== activeWebDAVConfig && ( + + )} + +
+
+
+ ))} +
+ + {/* Add New WebDAV Configuration Form */} + {isAddingWebDAVConfig && ( +
+

+ {t('添加新的WebDAV配置', 'Add New WebDAV Configuration')} +

+ + {/* Preset Selection */} +
+ +
+ {presetWebDAVConfigs.map((preset, index) => ( + + ))} +
+
+ +
+
+ + setNewWebDAVConfig(prev => ({ ...prev, name: e.target.value }))} + className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white" + /> +
+
+ + setNewWebDAVConfig(prev => ({ ...prev, username: e.target.value }))} + className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white" + /> +
+
+ +
+ + setNewWebDAVConfig(prev => ({ ...prev, url: e.target.value }))} + className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white" + /> +
+ +
+
+ + setNewWebDAVConfig(prev => ({ ...prev, password: e.target.value }))} + className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white" + /> +
+
+ + setNewWebDAVConfig(prev => ({ ...prev, path: e.target.value }))} + className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white" + /> +
+
+ +
+ + +
+
+ )} +
+ + {/* AI Configurations Section */} +
+
+
+
+ +
+
+

+ {t('AI配置', 'AI Configurations')} +

+

+ {t('管理用于仓库分析的AI服务配置', 'Manage your AI service configurations for repository analysis')} +

+
+
+ +
+ + {/* Existing AI Configurations */} +
+ {aiConfigs.map(config => ( +
+
+
+

+ {config.name} + {config.id === activeAIConfig && ( + + {t('活跃', 'Active')} + + )} +

+

+ {config.baseUrl} • {config.model} +

+
+
+ + {config.id !== activeAIConfig && ( + + )} + +
+
+
+ ))} +
+ + {/* Add New AI Configuration Form */} + {isAddingAIConfig && ( +
+

+ {t('添加新的AI配置', 'Add New AI Configuration')} +

+ + {/* Preset Selection */} +
+ +
+ {presetAIConfigs.map((preset, index) => ( + + ))} +
+
+ +
+
+ + setNewAIConfig(prev => ({ ...prev, name: e.target.value }))} + className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white" + /> +
+
+ + setNewAIConfig(prev => ({ ...prev, model: e.target.value }))} + className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white" + /> +
+
+ +
+ + setNewAIConfig(prev => ({ ...prev, baseUrl: e.target.value }))} + className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white" + /> +
+ +
+ + setNewAIConfig(prev => ({ ...prev, apiKey: e.target.value }))} + className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white" + /> +
+ +
+ + +
+
+ )} +
+
+ ); +}; \ No newline at end of file diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..32ea20b --- /dev/null +++ b/src/index.css @@ -0,0 +1,12 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer utilities { + .line-clamp-3 { + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; + } +} \ No newline at end of file diff --git a/src/main.tsx b/src/main.tsx new file mode 100644 index 0000000..0507716 --- /dev/null +++ b/src/main.tsx @@ -0,0 +1,22 @@ +import { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; +import App from './App.tsx'; +import './index.css'; + +console.log('Main.tsx loading...'); + +const rootElement = document.getElementById('root'); +if (!rootElement) { + throw new Error('Root element not found'); +} + +console.log('Root element found, creating React root...'); + +const root = createRoot(rootElement); +root.render( + + + +); + +console.log('React app rendered'); \ No newline at end of file diff --git a/src/services/aiService.ts b/src/services/aiService.ts new file mode 100644 index 0000000..4603fb8 --- /dev/null +++ b/src/services/aiService.ts @@ -0,0 +1,431 @@ +import { Repository, AIConfig } from '../types'; + +export class AIService { + private config: AIConfig; + private language: string; + + constructor(config: AIConfig, language: string = 'zh') { + this.config = config; + this.language = language; + } + + async analyzeRepository(repository: Repository, readmeContent: string): Promise<{ + summary: string; + tags: string[]; + platforms: string[]; + }> { + const prompt = this.createAnalysisPrompt(repository, readmeContent); + + try { + const response = await fetch(`${this.config.baseUrl}/chat/completions`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${this.config.apiKey}`, + }, + body: JSON.stringify({ + model: this.config.model, + messages: [ + { + role: 'system', + content: this.language === 'zh' + ? '你是一个专业的GitHub仓库分析助手。请用中文简洁地分析仓库,提供实用的概述、分类标签和支持的平台类型。' + : 'You are a professional GitHub repository analysis assistant. Please analyze repositories concisely in English, providing practical overviews, category tags, and supported platform types.', + }, + { + role: 'user', + content: prompt, + }, + ], + temperature: 0.3, + max_tokens: 400, + }), + }); + + if (!response.ok) { + throw new Error(`AI API error: ${response.status} ${response.statusText}`); + } + + const data = await response.json(); + const content = data.choices[0]?.message?.content; + + if (!content) { + throw new Error('No content received from AI service'); + } + + return this.parseAIResponse(content); + } catch (error) { + console.error('AI analysis failed:', error); + // Fallback to basic analysis + return this.fallbackAnalysis(repository); + } + } + + private createAnalysisPrompt(repository: Repository, readmeContent: string): string { + const repoInfo = ` +${this.language === 'zh' ? '仓库名称' : 'Repository Name'}: ${repository.full_name} +${this.language === 'zh' ? '描述' : 'Description'}: ${repository.description || (this.language === 'zh' ? '无描述' : 'No description')} +${this.language === 'zh' ? '编程语言' : 'Programming Language'}: ${repository.language || (this.language === 'zh' ? '未知' : 'Unknown')} +${this.language === 'zh' ? 'Star数' : 'Stars'}: ${repository.stargazers_count} +${this.language === 'zh' ? '主题标签' : 'Topics'}: ${repository.topics?.join(', ') || (this.language === 'zh' ? '无' : 'None')} + +${this.language === 'zh' ? 'README内容 (前2000字符)' : 'README Content (first 2000 characters)'}: +${readmeContent.substring(0, 2000)} + `.trim(); + + if (this.language === 'zh') { + return ` +请分析这个GitHub仓库并提供: + +1. 一个简洁的中文概述(不超过50字),说明这个仓库的主要功能和用途 +2. 3-5个相关的应用类型标签(用中文,类似应用商店的分类,如:开发工具、Web应用、移动应用、数据库、AI工具等) +3. 支持的平台类型(从以下选择:mac、windows、linux、ios、android、docker、web、cli) + +请以JSON格式回复: +{ + "summary": "你的中文概述", + "tags": ["标签1", "标签2", "标签3", "标签4", "标签5"], + "platforms": ["platform1", "platform2", "platform3"] +} + +仓库信息: +${repoInfo} + +重点关注实用性和准确的分类,帮助用户快速理解仓库的用途和支持的平台。 + `.trim(); + } else { + return ` +Please analyze this GitHub repository and provide: + +1. A concise English overview (no more than 50 words) explaining the main functionality and purpose of this repository +2. 3-5 relevant application type tags (in English, similar to app store categories, such as: development tools, web apps, mobile apps, database, AI tools, etc.) +3. Supported platform types (choose from: mac, windows, linux, ios, android, docker, web, cli) + +Please reply in JSON format: +{ + "summary": "Your English overview", + "tags": ["tag1", "tag2", "tag3", "tag4", "tag5"], + "platforms": ["platform1", "platform2", "platform3"] +} + +Repository information: +${repoInfo} + +Focus on practicality and accurate categorization to help users quickly understand the repository's purpose and supported platforms. + `.trim(); + } + } + + private parseAIResponse(content: string): { summary: string; tags: string[]; platforms: string[] } { + try { + // Try to extract JSON from the response + const jsonMatch = content.match(/\{[\s\S]*\}/); + if (jsonMatch) { + const parsed = JSON.parse(jsonMatch[0]); + return { + summary: parsed.summary || (this.language === 'zh' ? '无法生成概述' : 'Unable to generate summary'), + tags: Array.isArray(parsed.tags) ? parsed.tags.slice(0, 5) : [], + platforms: Array.isArray(parsed.platforms) ? parsed.platforms.slice(0, 8) : [], + }; + } + + // Fallback parsing + return { + summary: content.substring(0, 50) + '...', + tags: [], + platforms: [], + }; + } catch (error) { + console.error('Failed to parse AI response:', error); + return { + summary: this.language === 'zh' ? '分析失败' : 'Analysis failed', + tags: [], + platforms: [], + }; + } + } + + private fallbackAnalysis(repository: Repository): { summary: string; tags: string[]; platforms: string[] } { + const summary = repository.description + ? `${repository.description}(${repository.language || (this.language === 'zh' ? '未知语言' : 'Unknown language')}${this.language === 'zh' ? '项目' : ' project'})` + : (this.language === 'zh' + ? `一个${repository.language || '软件'}项目,拥有${repository.stargazers_count}个星标` + : `A ${repository.language || 'software'} project with ${repository.stargazers_count} stars` + ); + + const tags: string[] = []; + const platforms: string[] = []; + + // Add language-based tags and platforms + if (repository.language) { + const langMap: Record = this.language === 'zh' ? { + 'JavaScript': { tag: 'Web应用', platforms: ['web', 'cli'] }, + 'TypeScript': { tag: 'Web应用', platforms: ['web', 'cli'] }, + 'Python': { tag: 'Python工具', platforms: ['linux', 'mac', 'windows', 'cli'] }, + 'Java': { tag: 'Java应用', platforms: ['linux', 'mac', 'windows'] }, + 'Go': { tag: '系统工具', platforms: ['linux', 'mac', 'windows', 'cli'] }, + 'Rust': { tag: '系统工具', platforms: ['linux', 'mac', 'windows', 'cli'] }, + 'C++': { tag: '系统软件', platforms: ['linux', 'mac', 'windows'] }, + 'C': { tag: '系统软件', platforms: ['linux', 'mac', 'windows'] }, + 'Swift': { tag: '移动应用', platforms: ['ios', 'mac'] }, + 'Kotlin': { tag: '移动应用', platforms: ['android'] }, + 'Dart': { tag: '移动应用', platforms: ['ios', 'android'] }, + 'PHP': { tag: 'Web应用', platforms: ['web', 'linux'] }, + 'Ruby': { tag: 'Web应用', platforms: ['web', 'linux', 'mac'] }, + 'Shell': { tag: '脚本工具', platforms: ['linux', 'mac', 'cli'] } + } : { + 'JavaScript': { tag: 'Web App', platforms: ['web', 'cli'] }, + 'TypeScript': { tag: 'Web App', platforms: ['web', 'cli'] }, + 'Python': { tag: 'Python Tool', platforms: ['linux', 'mac', 'windows', 'cli'] }, + 'Java': { tag: 'Java App', platforms: ['linux', 'mac', 'windows'] }, + 'Go': { tag: 'System Tool', platforms: ['linux', 'mac', 'windows', 'cli'] }, + 'Rust': { tag: 'System Tool', platforms: ['linux', 'mac', 'windows', 'cli'] }, + 'C++': { tag: 'System Software', platforms: ['linux', 'mac', 'windows'] }, + 'C': { tag: 'System Software', platforms: ['linux', 'mac', 'windows'] }, + 'Swift': { tag: 'Mobile App', platforms: ['ios', 'mac'] }, + 'Kotlin': { tag: 'Mobile App', platforms: ['android'] }, + 'Dart': { tag: 'Mobile App', platforms: ['ios', 'android'] }, + 'PHP': { tag: 'Web App', platforms: ['web', 'linux'] }, + 'Ruby': { tag: 'Web App', platforms: ['web', 'linux', 'mac'] }, + 'Shell': { tag: 'Script Tool', platforms: ['linux', 'mac', 'cli'] } + }; + + const langInfo = langMap[repository.language]; + if (langInfo) { + tags.push(langInfo.tag); + platforms.push(...langInfo.platforms); + } + } + + // Add category based on keywords + const desc = (repository.description || '').toLowerCase(); + const name = repository.name.toLowerCase(); + const searchText = `${desc} ${name}`; + + const keywordMap = this.language === 'zh' ? { + web: { keywords: ['web', 'frontend', 'website'], tag: 'Web应用', platforms: ['web'] }, + api: { keywords: ['api', 'backend', 'server'], tag: '后端服务', platforms: ['linux', 'docker'] }, + cli: { keywords: ['cli', 'command', 'tool'], tag: '命令行工具', platforms: ['cli', 'linux', 'mac', 'windows'] }, + library: { keywords: ['library', 'framework', 'sdk'], tag: '开发库', platforms: [] }, + mobile: { keywords: ['mobile', 'android', 'ios'], tag: '移动应用', platforms: [] }, + game: { keywords: ['game', 'gaming'], tag: '游戏', platforms: ['windows', 'mac', 'linux'] }, + ai: { keywords: ['ai', 'ml', 'machine learning'], tag: 'AI工具', platforms: ['linux', 'mac', 'windows'] }, + database: { keywords: ['database', 'db', 'storage'], tag: '数据库', platforms: ['linux', 'docker'] }, + docker: { keywords: ['docker', 'container'], tag: '容器化', platforms: ['docker'] } + } : { + web: { keywords: ['web', 'frontend', 'website'], tag: 'Web App', platforms: ['web'] }, + api: { keywords: ['api', 'backend', 'server'], tag: 'Backend Service', platforms: ['linux', 'docker'] }, + cli: { keywords: ['cli', 'command', 'tool'], tag: 'CLI Tool', platforms: ['cli', 'linux', 'mac', 'windows'] }, + library: { keywords: ['library', 'framework', 'sdk'], tag: 'Development Library', platforms: [] }, + mobile: { keywords: ['mobile', 'android', 'ios'], tag: 'Mobile App', platforms: [] }, + game: { keywords: ['game', 'gaming'], tag: 'Game', platforms: ['windows', 'mac', 'linux'] }, + ai: { keywords: ['ai', 'ml', 'machine learning'], tag: 'AI Tool', platforms: ['linux', 'mac', 'windows'] }, + database: { keywords: ['database', 'db', 'storage'], tag: 'Database', platforms: ['linux', 'docker'] }, + docker: { keywords: ['docker', 'container'], tag: 'Containerized', platforms: ['docker'] } + }; + + Object.values(keywordMap).forEach(({ keywords, tag, platforms: keywordPlatforms }) => { + if (keywords.some(keyword => searchText.includes(keyword))) { + tags.push(tag); + platforms.push(...keywordPlatforms); + } + }); + + // Handle specific mobile platforms + if (searchText.includes('android')) platforms.push('android'); + if (searchText.includes('ios')) platforms.push('ios'); + + return { + summary: summary.substring(0, 50), + tags: [...new Set(tags)].slice(0, 5), // Remove duplicates and limit to 5 + platforms: [...new Set(platforms)].slice(0, 8), // Remove duplicates and limit to 8 + }; + } + + async testConnection(): Promise { + try { + const response = await fetch(`${this.config.baseUrl}/models`, { + method: 'GET', + headers: { + 'Authorization': `Bearer ${this.config.apiKey}`, + }, + }); + return response.ok; + } catch (error) { + return false; + } + } + + async searchRepositories(repositories: Repository[], query: string): Promise { + if (!query.trim()) return repositories; + + try { + // Use AI to understand and translate the search query + const searchPrompt = this.createSearchPrompt(query); + + const response = await fetch(`${this.config.baseUrl}/chat/completions`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${this.config.apiKey}`, + }, + body: JSON.stringify({ + model: this.config.model, + messages: [ + { + role: 'system', + content: this.language === 'zh' + ? '你是一个智能搜索助手。请分析用户的搜索意图,提取关键词并提供多语言翻译。' + : 'You are an intelligent search assistant. Please analyze user search intent, extract keywords and provide multilingual translations.', + }, + { + role: 'user', + content: searchPrompt, + }, + ], + temperature: 0.1, + max_tokens: 200, + }), + }); + + if (response.ok) { + const data = await response.json(); + const content = data.choices[0]?.message?.content; + + if (content) { + const searchTerms = this.parseSearchResponse(content); + return this.performEnhancedSearch(repositories, query, searchTerms); + } + } + } catch (error) { + console.warn('AI search failed, falling back to basic search:', error); + } + + // Fallback to basic search + return this.performBasicSearch(repositories, query); + } + + private createSearchPrompt(query: string): string { + if (this.language === 'zh') { + return ` +用户搜索查询: "${query}" + +请分析这个搜索查询并提供: +1. 主要关键词(中英文) +2. 相关的技术术语和同义词 +3. 可能的应用类型或分类 + +以JSON格式回复: +{ + "keywords": ["关键词1", "keyword1", "关键词2", "keyword2"], + "categories": ["分类1", "category1"], + "synonyms": ["同义词1", "synonym1"] +} + `.trim(); + } else { + return ` +User search query: "${query}" + +Please analyze this search query and provide: +1. Main keywords (in English and Chinese) +2. Related technical terms and synonyms +3. Possible application types or categories + +Reply in JSON format: +{ + "keywords": ["keyword1", "关键词1", "keyword2", "关键词2"], + "categories": ["category1", "分类1"], + "synonyms": ["synonym1", "同义词1"] +} + `.trim(); + } + } + + private parseSearchResponse(content: string): string[] { + try { + const jsonMatch = content.match(/\{[\s\S]*\}/); + if (jsonMatch) { + const parsed = JSON.parse(jsonMatch[0]); + const allTerms = [ + ...(parsed.keywords || []), + ...(parsed.categories || []), + ...(parsed.synonyms || []) + ]; + return allTerms.filter(term => typeof term === 'string' && term.length > 0); + } + } catch (error) { + console.warn('Failed to parse AI search response:', error); + } + return []; + } + + private performEnhancedSearch(repositories: Repository[], originalQuery: string, aiTerms: string[]): Repository[] { + const allSearchTerms = [originalQuery, ...aiTerms]; + + return repositories.filter(repo => { + const searchableText = [ + repo.name, + repo.full_name, + repo.description || '', + repo.language || '', + ...(repo.topics || []), + repo.ai_summary || '', + ...(repo.ai_tags || []), + ...(repo.ai_platforms || []), + ].join(' ').toLowerCase(); + + // Check if any of the AI-enhanced terms match + return allSearchTerms.some(term => { + const normalizedTerm = term.toLowerCase(); + return searchableText.includes(normalizedTerm) || + // Fuzzy matching for partial matches + normalizedTerm.split(/\s+/).every(word => searchableText.includes(word)); + }); + }); + } + + private performBasicSearch(repositories: Repository[], query: string): Repository[] { + const normalizedQuery = query.toLowerCase(); + + return repositories.filter(repo => { + const searchableText = [ + repo.name, + repo.full_name, + repo.description || '', + repo.language || '', + ...(repo.topics || []), + repo.ai_summary || '', + ...(repo.ai_tags || []), + ...(repo.ai_platforms || []), + ].join(' ').toLowerCase(); + + // Split query into words and check if all words are present + const queryWords = normalizedQuery.split(/\s+/); + return queryWords.every(word => searchableText.includes(word)); + }); + } + + static async searchRepositories(repositories: Repository[], query: string): Promise { + // This is a static fallback method for when no AI config is available + if (!query.trim()) return repositories; + + const normalizedQuery = query.toLowerCase(); + + return repositories.filter(repo => { + const searchableText = [ + repo.name, + repo.full_name, + repo.description || '', + repo.language || '', + ...(repo.topics || []), + repo.ai_summary || '', + ...(repo.ai_tags || []), + ...(repo.ai_platforms || []), + ].join(' ').toLowerCase(); + + // Split query into words and check if all words are present + const queryWords = normalizedQuery.split(/\s+/); + return queryWords.every(word => searchableText.includes(word)); + }); + } +} \ No newline at end of file diff --git a/src/services/githubApi.ts b/src/services/githubApi.ts new file mode 100644 index 0000000..2a32dc9 --- /dev/null +++ b/src/services/githubApi.ts @@ -0,0 +1,189 @@ +import { Repository, Release, GitHubUser } from '../types'; + +const GITHUB_API_BASE = 'https://api.github.com'; + +export class GitHubApiService { + private token: string; + + constructor(token: string) { + this.token = token; + } + + private async makeRequest(endpoint: string, options: RequestInit = {}): Promise { + const response = await fetch(`${GITHUB_API_BASE}${endpoint}`, { + ...options, + headers: { + 'Authorization': `Bearer ${this.token}`, + 'Accept': 'application/vnd.github.v3+json', + 'X-GitHub-Api-Version': '2022-11-28', + ...options.headers, + }, + }); + + if (!response.ok) { + if (response.status === 401) { + throw new Error('GitHub token expired or invalid'); + } + throw new Error(`GitHub API error: ${response.status} ${response.statusText}`); + } + + return response.json(); + } + + async getCurrentUser(): Promise { + return this.makeRequest('/user'); + } + + async getStarredRepositories(page = 1, perPage = 100): Promise { + const repos = await this.makeRequest( + `/user/starred?page=${page}&per_page=${perPage}&sort=updated` + ); + return repos; + } + + async getAllStarredRepositories(): Promise { + let allRepos: Repository[] = []; + let page = 1; + const perPage = 100; + + while (true) { + const repos = await this.getStarredRepositories(page, perPage); + if (repos.length === 0) break; + + allRepos = [...allRepos, ...repos]; + + if (repos.length < perPage) break; + page++; + + // Rate limiting protection + await new Promise(resolve => setTimeout(resolve, 100)); + } + + return allRepos; + } + + async getRepositoryReadme(owner: string, repo: string): Promise { + try { + const response = await this.makeRequest<{ content: string; encoding: string }>( + `/repos/${owner}/${repo}/readme` + ); + + if (response.encoding === 'base64') { + return atob(response.content); + } + return response.content; + } catch (error) { + console.warn(`Failed to fetch README for ${owner}/${repo}:`, error); + return ''; + } + } + + async getRepositoryReleases(owner: string, repo: string, page = 1, perPage = 30): Promise { + try { + const releases = await this.makeRequest( + `/repos/${owner}/${repo}/releases?page=${page}&per_page=${perPage}` + ); + + return releases.map(release => ({ + id: release.id, + tag_name: release.tag_name, + name: release.name || release.tag_name, + body: release.body || '', + published_at: release.published_at, + html_url: release.html_url, + repository: { + id: 0, // Will be set by caller + full_name: `${owner}/${repo}`, + name: repo, + }, + })); + } catch (error) { + console.warn(`Failed to fetch releases for ${owner}/${repo}:`, error); + return []; + } + } + + async getMultipleRepositoryReleases(repositories: Repository[]): Promise { + const allReleases: Release[] = []; + + for (const repo of repositories) { + const [owner, name] = repo.full_name.split('/'); + const releases = await this.getRepositoryReleases(owner, name, 1, 5); + + // Add repository info to releases + releases.forEach(release => { + release.repository.id = repo.id; + }); + + allReleases.push(...releases); + + // Rate limiting protection + await new Promise(resolve => setTimeout(resolve, 150)); + } + + // Sort by published date (newest first) + return allReleases.sort((a, b) => + new Date(b.published_at).getTime() - new Date(a.published_at).getTime() + ); + } + + // 新增:获取仓库的增量releases(基于时间戳) + async getIncrementalRepositoryReleases( + owner: string, + repo: string, + since?: string, + perPage = 10 + ): Promise { + try { + let endpoint = `/repos/${owner}/${repo}/releases?per_page=${perPage}`; + + const releases = await this.makeRequest(endpoint); + + const mappedReleases = releases.map(release => ({ + id: release.id, + tag_name: release.tag_name, + name: release.name || release.tag_name, + body: release.body || '', + published_at: release.published_at, + html_url: release.html_url, + repository: { + id: 0, // Will be set by caller + full_name: `${owner}/${repo}`, + name: repo, + }, + })); + + // 如果提供了since时间戳,只返回更新的releases + if (since) { + const sinceDate = new Date(since); + return mappedReleases.filter(release => + new Date(release.published_at) > sinceDate + ); + } + + return mappedReleases; + } catch (error) { + console.warn(`Failed to fetch incremental releases for ${owner}/${repo}:`, error); + return []; + } + } + + async checkRateLimit(): Promise<{ remaining: number; reset: number }> { + const response = await this.makeRequest('/rate_limit'); + return { + remaining: response.rate.remaining, + reset: response.rate.reset, + }; + } +} + +export const createGitHubOAuthUrl = (clientId: string, redirectUri: string): string => { + const params = new URLSearchParams({ + client_id: clientId, + redirect_uri: redirectUri, + scope: 'read:user user:email repo', + state: Math.random().toString(36).substring(7), + }); + + return `https://github.com/login/oauth/authorize?${params.toString()}`; +}; \ No newline at end of file diff --git a/src/services/webdavService.ts b/src/services/webdavService.ts new file mode 100644 index 0000000..f238ac0 --- /dev/null +++ b/src/services/webdavService.ts @@ -0,0 +1,384 @@ +import { WebDAVConfig } from '../types'; + +export class WebDAVService { + private config: WebDAVConfig; + + constructor(config: WebDAVConfig) { + this.config = config; + } + + private getAuthHeader(): string { + const credentials = btoa(`${this.config.username}:${this.config.password}`); + return `Basic ${credentials}`; + } + + private getFullPath(filename: string): string { + const basePath = this.config.path.endsWith('/') ? this.config.path : `${this.config.path}/`; + return `${this.config.url}${basePath}${filename}`; + } + + private handleNetworkError(error: any, operation: string): never { + console.error(`WebDAV ${operation} failed:`, error); + + // Check for CORS-related errors (most common issue) + const isCorsError = ( + (error.name === 'TypeError' && error.message.includes('Failed to fetch')) || + (error.message && error.message.includes('NetworkError when attempting to fetch resource')) || + (error.name === 'NetworkError') || + (error.message && error.message.includes('NetworkError')) + ); + + if (isCorsError) { + throw new Error(`CORS策略阻止了连接到WebDAV服务器。 + +这是一个常见的浏览器安全限制。要解决此问题,您需要: + +1. 在WebDAV服务器上配置CORS头: + • Access-Control-Allow-Origin: ${window.location.origin} + • Access-Control-Allow-Methods: GET, PUT, PROPFIND, HEAD, OPTIONS, MKCOL + • Access-Control-Allow-Headers: Authorization, Content-Type, Depth + +2. 常见WebDAV服务器配置示例: + + Apache (.htaccess): + Header always set Access-Control-Allow-Origin "${window.location.origin}" + Header always set Access-Control-Allow-Methods "GET, PUT, PROPFIND, HEAD, OPTIONS, MKCOL" + Header always set Access-Control-Allow-Headers "Authorization, Content-Type, Depth" + + Nginx: + add_header Access-Control-Allow-Origin "${window.location.origin}"; + add_header Access-Control-Allow-Methods "GET, PUT, PROPFIND, HEAD, OPTIONS, MKCOL"; + add_header Access-Control-Allow-Headers "Authorization, Content-Type, Depth"; + +3. 其他检查项: + • 确保WebDAV服务器正在运行 + • 验证URL格式正确(包含协议 http:// 或 https://) + • 如果应用使用HTTPS,WebDAV服务器也应使用HTTPS + +技术详情: ${error.message}`); + } + + throw new Error(`WebDAV ${operation} 失败: ${error.message || '未知错误'}`); + } + + async testConnection(): Promise { + try { + // 验证URL格式 + if (!this.config.url.startsWith('http://') && !this.config.url.startsWith('https://')) { + throw new Error('WebDAV URL必须以 http:// 或 https:// 开头'); + } + + // 首先尝试OPTIONS请求检查CORS + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), 10000); // 10秒超时 + + try { + const optionsResponse = await fetch(this.config.url, { + method: 'OPTIONS', + headers: { + 'Authorization': this.getAuthHeader(), + }, + signal: controller.signal, + }); + + clearTimeout(timeoutId); + + // 如果OPTIONS成功,说明CORS配置正确 + if (optionsResponse.ok) { + return true; + } + + // 如果OPTIONS失败,尝试PROPFIND(某些服务器不支持OPTIONS) + const propfindResponse = await fetch(this.config.url, { + method: 'PROPFIND', + headers: { + 'Authorization': this.getAuthHeader(), + 'Depth': '0', + }, + }); + + return propfindResponse.ok || propfindResponse.status === 207; + } catch (fetchError) { + clearTimeout(timeoutId); + + if (fetchError.name === 'AbortError') { + throw new Error('连接超时。请检查WebDAV服务器是否可访问。'); + } + + throw fetchError; + } + } catch (error) { + this.handleNetworkError(error, '连接测试'); + } + } + + async uploadFile(filename: string, content: string): Promise { + try { + // 验证URL格式 + if (!this.config.url.startsWith('http://') && !this.config.url.startsWith('https://')) { + throw new Error('WebDAV URL必须以 http:// 或 https:// 开头'); + } + + // 确保目录存在 + await this.ensureDirectoryExists(); + + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), 30000); // 30秒超时 + + try { + const response = await fetch(this.getFullPath(filename), { + method: 'PUT', + headers: { + 'Authorization': this.getAuthHeader(), + 'Content-Type': 'application/json', + }, + body: content, + signal: controller.signal, + }); + + clearTimeout(timeoutId); + + if (!response.ok) { + if (response.status === 401) { + throw new Error('身份验证失败。请检查用户名和密码。'); + } + if (response.status === 403) { + throw new Error('访问被拒绝。请检查指定路径的权限。'); + } + if (response.status === 404) { + throw new Error('路径未找到。请验证WebDAV URL和路径是否正确。'); + } + if (response.status === 507) { + throw new Error('服务器存储空间不足。'); + } + throw new Error(`上传失败,HTTP状态码 ${response.status}: ${response.statusText}`); + } + + return true; + } catch (fetchError) { + clearTimeout(timeoutId); + + if (fetchError.name === 'AbortError') { + throw new Error('上传超时。文件可能太大或网络连接缓慢。'); + } + + throw fetchError; + } + } catch (error) { + if (error.message.includes('身份验证失败') || + error.message.includes('访问被拒绝') || + error.message.includes('路径未找到') || + error.message.includes('存储空间不足') || + error.message.includes('上传失败,HTTP状态码') || + error.message.includes('上传超时') || + error.message.includes('WebDAV URL必须')) { + throw error; // 重新抛出特定错误 + } + this.handleNetworkError(error, '上传'); + } + } + + private async ensureDirectoryExists(): Promise { + try { + if (!this.config.path || this.config.path === '/') { + return; // 根目录总是存在 + } + + const dirPath = this.config.url + this.config.path; + const response = await fetch(dirPath, { + method: 'MKCOL', + headers: { + 'Authorization': this.getAuthHeader(), + }, + }); + + // 201 = 已创建, 405 = 已存在, 都是正常的 + if (!response.ok && response.status !== 405) { + console.warn('无法创建目录,可能已存在或权限不足'); + } + } catch (error) { + console.warn('目录创建检查失败:', error); + // 不在这里抛出错误,因为目录可能已经存在 + } + } + + async downloadFile(filename: string): Promise { + try { + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), 30000); // 30秒超时 + + try { + const response = await fetch(this.getFullPath(filename), { + method: 'GET', + headers: { + 'Authorization': this.getAuthHeader(), + }, + signal: controller.signal, + }); + + clearTimeout(timeoutId); + + if (response.ok) { + return await response.text(); + } + + if (response.status === 404) { + return null; // 文件未找到是预期行为 + } + + if (response.status === 401) { + throw new Error('身份验证失败。请检查用户名和密码。'); + } + + throw new Error(`下载失败,HTTP状态码 ${response.status}: ${response.statusText}`); + } catch (fetchError) { + clearTimeout(timeoutId); + + if (fetchError.name === 'AbortError') { + throw new Error('下载超时。请检查网络连接。'); + } + + throw fetchError; + } + } catch (error) { + if (error.message.includes('身份验证失败') || + error.message.includes('下载超时')) { + throw error; + } + if (error.message.includes('HTTP 404')) { + return null; + } + this.handleNetworkError(error, '下载'); + } + } + + async fileExists(filename: string): Promise { + try { + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), 10000); // 10秒超时 + + const response = await fetch(this.getFullPath(filename), { + method: 'HEAD', + headers: { + 'Authorization': this.getAuthHeader(), + }, + signal: controller.signal, + }); + + clearTimeout(timeoutId); + return response.ok; + } catch (error) { + console.error('WebDAV文件检查失败:', error); + return false; + } + } + + async listFiles(): Promise { + try { + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), 15000); // 15秒超时 + + try { + const response = await fetch(this.config.url + this.config.path, { + method: 'PROPFIND', + headers: { + 'Authorization': this.getAuthHeader(), + 'Depth': '1', + 'Content-Type': 'application/xml', + }, + body: ` + + + + + + + `, + signal: controller.signal, + }); + + clearTimeout(timeoutId); + + if (response.ok || response.status === 207) { + const xmlText = await response.text(); + // 简单的XML解析提取文件名 + const fileMatches = xmlText.match(/([^<]+)<\/D:displayname>/g); + if (fileMatches) { + return fileMatches + .map(match => match.replace(/<\/?D:displayname>/g, '')) + .filter(name => name.endsWith('.json')); + } + } else if (response.status === 401) { + throw new Error('身份验证失败。请检查用户名和密码。'); + } else { + throw new Error(`列出文件失败,HTTP状态码 ${response.status}: ${response.statusText}`); + } + return []; + } catch (fetchError) { + clearTimeout(timeoutId); + + if (fetchError.name === 'AbortError') { + throw new Error('列出文件超时。请检查网络连接。'); + } + + throw fetchError; + } + } catch (error) { + if (error.message.includes('身份验证失败') || + error.message.includes('列出文件超时')) { + throw error; + } + this.handleNetworkError(error, '列出文件'); + } + } + + // 新增:验证配置的静态方法 + static validateConfig(config: Partial): string[] { + const errors: string[] = []; + + if (!config.url) { + errors.push('WebDAV URL是必需的'); + } else if (!config.url.startsWith('http://') && !config.url.startsWith('https://')) { + errors.push('WebDAV URL必须以 http:// 或 https:// 开头'); + } + + if (!config.username) { + errors.push('用户名是必需的'); + } + + if (!config.password) { + errors.push('密码是必需的'); + } + + if (!config.path) { + errors.push('路径是必需的'); + } else if (!config.path.startsWith('/')) { + errors.push('路径必须以 / 开头'); + } + + return errors; + } + + // 新增:获取服务器信息 + async getServerInfo(): Promise<{ server?: string; davLevel?: string }> { + try { + const response = await fetch(this.config.url, { + method: 'OPTIONS', + headers: { + 'Authorization': this.getAuthHeader(), + }, + }); + + if (response.ok) { + return { + server: response.headers.get('Server') || undefined, + davLevel: response.headers.get('DAV') || undefined, + }; + } + } catch (error) { + console.warn('无法获取服务器信息:', error); + } + + return {}; + } +} \ No newline at end of file diff --git a/src/store/useAppStore.ts b/src/store/useAppStore.ts new file mode 100644 index 0000000..f1a43d1 --- /dev/null +++ b/src/store/useAppStore.ts @@ -0,0 +1,238 @@ +import { create } from 'zustand'; +import { persist } from 'zustand/middleware'; +import { AppState, Repository, Release, AIConfig, WebDAVConfig, SearchFilters, GitHubUser } from '../types'; + +interface AppActions { + // Auth actions + setUser: (user: GitHubUser | null) => void; + setGitHubToken: (token: string | null) => void; + logout: () => void; + + // Repository actions + setRepositories: (repos: Repository[]) => void; + updateRepository: (repo: Repository) => void; + setLoading: (loading: boolean) => void; + setLastSync: (timestamp: string) => void; + + // AI actions + addAIConfig: (config: AIConfig) => void; + updateAIConfig: (id: string, updates: Partial) => void; + deleteAIConfig: (id: string) => void; + setActiveAIConfig: (id: string | null) => void; + + // WebDAV actions + addWebDAVConfig: (config: WebDAVConfig) => void; + updateWebDAVConfig: (id: string, updates: Partial) => void; + deleteWebDAVConfig: (id: string) => void; + setActiveWebDAVConfig: (id: string | null) => void; + setLastBackup: (timestamp: string) => void; + + // Search actions + setSearchFilters: (filters: Partial) => void; + setSearchResults: (results: Repository[]) => void; + + // Release actions + setReleases: (releases: Release[]) => void; + addReleases: (releases: Release[]) => void; + toggleReleaseSubscription: (repoId: number) => void; + + // UI actions + setTheme: (theme: 'light' | 'dark') => void; + setCurrentView: (view: 'repositories' | 'releases' | 'settings') => void; + setLanguage: (language: 'zh' | 'en') => void; +} + +const initialSearchFilters: SearchFilters = { + query: '', + tags: [], + languages: [], + platforms: [], + sortBy: 'stars', + sortOrder: 'desc', + isAnalyzed: undefined, + isSubscribed: undefined, +}; + +export const useAppStore = create()( + persist( + (set, get) => ({ + // Initial state + user: null, + githubToken: null, + isAuthenticated: false, + repositories: [], + isLoading: false, + lastSync: null, + aiConfigs: [], + activeAIConfig: null, + webdavConfigs: [], + activeWebDAVConfig: null, + lastBackup: null, + searchFilters: initialSearchFilters, + searchResults: [], + releases: [], + releaseSubscriptions: new Set(), + theme: 'light', + currentView: 'repositories', + language: 'zh', + + // Auth actions + setUser: (user) => { + console.log('Setting user:', user); + set({ user, isAuthenticated: !!user }); + }, + setGitHubToken: (token) => { + console.log('Setting GitHub token:', !!token); + set({ githubToken: token }); + }, + logout: () => set({ + user: null, + githubToken: null, + isAuthenticated: false, + repositories: [], + releases: [], + releaseSubscriptions: new Set(), + searchResults: [], + lastSync: null, + }), + + // Repository actions + setRepositories: (repositories) => set({ repositories, searchResults: repositories }), + updateRepository: (repo) => set((state) => { + const updatedRepositories = state.repositories.map(r => r.id === repo.id ? repo : r); + return { + repositories: updatedRepositories, + searchResults: state.searchResults.map(r => r.id === repo.id ? repo : r) + }; + }), + setLoading: (isLoading) => set({ isLoading }), + setLastSync: (lastSync) => set({ lastSync }), + + // AI actions + addAIConfig: (config) => set((state) => ({ + aiConfigs: [...state.aiConfigs, config] + })), + updateAIConfig: (id, updates) => set((state) => ({ + aiConfigs: state.aiConfigs.map(config => + config.id === id ? { ...config, ...updates } : config + ) + })), + deleteAIConfig: (id) => set((state) => ({ + aiConfigs: state.aiConfigs.filter(config => config.id !== id), + activeAIConfig: state.activeAIConfig === id ? null : state.activeAIConfig + })), + setActiveAIConfig: (activeAIConfig) => set({ activeAIConfig }), + + // WebDAV actions + addWebDAVConfig: (config) => set((state) => ({ + webdavConfigs: [...state.webdavConfigs, config] + })), + updateWebDAVConfig: (id, updates) => set((state) => ({ + webdavConfigs: state.webdavConfigs.map(config => + config.id === id ? { ...config, ...updates } : config + ) + })), + deleteWebDAVConfig: (id) => set((state) => ({ + webdavConfigs: state.webdavConfigs.filter(config => config.id !== id), + activeWebDAVConfig: state.activeWebDAVConfig === id ? null : state.activeWebDAVConfig + })), + setActiveWebDAVConfig: (activeWebDAVConfig) => set({ activeWebDAVConfig }), + setLastBackup: (lastBackup) => set({ lastBackup }), + + // Search actions + setSearchFilters: (filters) => set((state) => ({ + searchFilters: { ...state.searchFilters, ...filters } + })), + setSearchResults: (searchResults) => set({ searchResults }), + + // Release actions + setReleases: (releases) => set({ releases }), + addReleases: (newReleases) => set((state) => { + const existingIds = new Set(state.releases.map(r => r.id)); + const uniqueReleases = newReleases.filter(r => !existingIds.has(r.id)); + return { releases: [...state.releases, ...uniqueReleases] }; + }), + toggleReleaseSubscription: (repoId) => set((state) => { + const newSubscriptions = new Set(state.releaseSubscriptions); + if (newSubscriptions.has(repoId)) { + newSubscriptions.delete(repoId); + } else { + newSubscriptions.add(repoId); + } + return { releaseSubscriptions: newSubscriptions }; + }), + + // UI actions + setTheme: (theme) => set({ theme }), + setCurrentView: (currentView) => set({ currentView }), + setLanguage: (language) => set({ language }), + }), + { + name: 'github-stars-manager', + partialize: (state) => ({ + // 持久化用户信息和认证状态 + user: state.user, + githubToken: state.githubToken, + isAuthenticated: state.isAuthenticated, + + // 持久化仓库数据 + repositories: state.repositories, + lastSync: state.lastSync, + + // 持久化AI配置 + aiConfigs: state.aiConfigs, + activeAIConfig: state.activeAIConfig, + + // 持久化WebDAV配置 + webdavConfigs: state.webdavConfigs, + activeWebDAVConfig: state.activeWebDAVConfig, + lastBackup: state.lastBackup, + + // 持久化Release订阅 + releaseSubscriptions: Array.from(state.releaseSubscriptions), + releases: state.releases, + + // 持久化UI设置 + theme: state.theme, + language: state.language, + }), + onRehydrateStorage: () => (state) => { + if (state) { + // Convert array back to Set + if (Array.isArray(state.releaseSubscriptions)) { + state.releaseSubscriptions = new Set(state.releaseSubscriptions as number[]); + } else { + state.releaseSubscriptions = new Set(); + } + + // 确保认证状态正确 + state.isAuthenticated = !!(state.user && state.githubToken); + + // 初始化搜索结果为所有仓库 + state.searchResults = state.repositories || []; + + // 重置搜索过滤器 + state.searchFilters = initialSearchFilters; + + // 确保语言设置存在 + if (!state.language) { + state.language = 'zh'; + } + + // 初始化WebDAV配置数组 + if (!state.webdavConfigs) { + state.webdavConfigs = []; + } + + console.log('Store rehydrated:', { + isAuthenticated: state.isAuthenticated, + repositoriesCount: state.repositories?.length || 0, + lastSync: state.lastSync, + language: state.language, + webdavConfigsCount: state.webdavConfigs?.length || 0 + }); + } + }, + } + ) +); \ No newline at end of file diff --git a/src/types/index.ts b/src/types/index.ts new file mode 100644 index 0000000..fab3af9 --- /dev/null +++ b/src/types/index.ts @@ -0,0 +1,111 @@ +export interface Repository { + id: number; + name: string; + full_name: string; + description: string | null; + html_url: string; + stargazers_count: number; + language: string | null; + updated_at: string; + pushed_at: string; + owner: { + login: string; + avatar_url: string; + }; + topics: string[]; + // AI generated fields + ai_summary?: string; + ai_tags?: string[]; + ai_platforms?: string[]; // 新增:支持的平台类型 + analyzed_at?: string; + // Release subscription + subscribed_to_releases?: boolean; +} + +export interface Release { + id: number; + tag_name: string; + name: string; + body: string; + published_at: string; + html_url: string; + repository: { + id: number; + full_name: string; + name: string; + }; +} + +export interface GitHubUser { + id: number; + login: string; + name: string; + avatar_url: string; + email: string | null; +} + +export interface AIConfig { + id: string; + name: string; + baseUrl: string; + apiKey: string; + model: string; + isActive: boolean; +} + +export interface WebDAVConfig { + id: string; + name: string; + url: string; + username: string; + password: string; + path: string; + isActive: boolean; +} + +export interface SearchFilters { + query: string; + tags: string[]; + languages: string[]; + platforms: string[]; // 新增:平台过滤 + sortBy: 'stars' | 'updated' | 'name' | 'created'; + sortOrder: 'desc' | 'asc'; + minStars?: number; + maxStars?: number; + isAnalyzed?: boolean; // 新增:是否已AI分析 + isSubscribed?: boolean; // 新增:是否订阅Release +} + +export interface AppState { + // Auth + user: GitHubUser | null; + githubToken: string | null; + isAuthenticated: boolean; + + // Repositories + repositories: Repository[]; + isLoading: boolean; + lastSync: string | null; + + // AI + aiConfigs: AIConfig[]; + activeAIConfig: string | null; + + // WebDAV + webdavConfigs: WebDAVConfig[]; + activeWebDAVConfig: string | null; + lastBackup: string | null; + + // Search + searchFilters: SearchFilters; + searchResults: Repository[]; + + // Releases + releases: Release[]; + releaseSubscriptions: Set; + + // UI + theme: 'light' | 'dark'; + currentView: 'repositories' | 'releases' | 'settings'; + language: 'zh' | 'en'; +} \ No newline at end of file diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..b4beec8 --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,68 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'], + darkMode: 'class', + theme: { + extend: { + colors: { + primary: { + 50: '#eff6ff', + 100: '#dbeafe', + 200: '#bfdbfe', + 300: '#93c5fd', + 400: '#60a5fa', + 500: '#3b82f6', + 600: '#0066CC', + 700: '#1d4ed8', + 800: '#1e40af', + 900: '#1e3a8a', + }, + secondary: { + 50: '#f5f3ff', + 100: '#ede9fe', + 200: '#ddd6fe', + 300: '#c4b5fd', + 400: '#a78bfa', + 500: '#8b5cf6', + 600: '#7c3aed', + 700: '#6d28d9', + 800: '#5b21b6', + 900: '#4c1d95', + }, + accent: { + 50: '#fefbf0', + 100: '#fef3c7', + 200: '#fde68a', + 300: '#fcd34d', + 400: '#fbbf24', + 500: '#f59e0b', + 600: '#d97706', + 700: '#b45309', + 800: '#92400e', + 900: '#78350f', + } + }, + animation: { + 'fade-in': 'fadeIn 0.5s ease-in-out', + 'slide-up': 'slideUp 0.3s ease-out', + 'bounce-gentle': 'bounceGentle 2s ease-in-out infinite', + }, + keyframes: { + fadeIn: { + '0%': { opacity: '0' }, + '100%': { opacity: '1' }, + }, + slideUp: { + '0%': { transform: 'translateY(10px)', opacity: '0' }, + '100%': { transform: 'translateY(0)', opacity: '1' }, + }, + bounceGentle: { + '0%, 20%, 50%, 80%, 100%': { transform: 'translateY(0)' }, + '40%': { transform: 'translateY(-4px)' }, + '60%': { transform: 'translateY(-2px)' }, + } + } + }, + }, + plugins: [], +}; \ No newline at end of file diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..f0a2350 --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..1ffef60 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..0d3d714 --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2023"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["vite.config.ts"] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..147380a --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], + optimizeDeps: { + exclude: ['lucide-react'], + }, +});