js-use-core
Version:
JavaScript Comprehensive tool library, including full screen, copy and paste functions
1 lines • 153 kB
JavaScript
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).JSUseCore={})}(this,function(e){"use strict";class EventEmitter{constructor(){this.events=new Map,this.maxListeners=10}on(e,t,r){if("function"!=typeof t)throw new Error("Listener must be a function");const i={listener:t,once:r?.once||!1,priority:r?.priority||0};this.events.has(e)||this.events.set(e,[]);const n=this.events.get(e);n.length,this.maxListeners;let s=!1;for(let e=0;e<n.length;e++)if(i.priority>(n[e].priority||0)){n.splice(e,0,i),s=!0;break}return s||n.push(i),this}once(e,t,r){return this.on(e,t,{once:!0,priority:r})}off(e,t){if(!this.events.has(e))return this;const r=this.events.get(e);if(t){const i=r.findIndex(e=>e.listener===t);-1!==i&&(r.splice(i,1),0===r.length&&this.events.delete(e))}else this.events.delete(e);return this}emit(e,...t){if(!this.events.has(e))return!1;const r=this.events.get(e).slice(),i=[];for(const e of r)try{e.listener.apply(this,t),e.once&&i.push(e)}catch(e){}if(i.length>0){const t=this.events.get(e);if(t){for(const e of i){const r=t.indexOf(e);-1!==r&&t.splice(r,1)}0===t.length&&this.events.delete(e)}}return!0}listenerCount(e){return this.events.get(e)?.length||0}listeners(e){return this.events.get(e)?.map(e=>e.listener)||[]}eventNames(){return Array.from(this.events.keys())}removeAllListeners(e){return e?this.events.delete(e):this.events.clear(),this}setMaxListeners(e){if(e<0||!Number.isInteger(e))throw new Error("Max listeners must be a non-negative integer");return this.maxListeners=e,this}getMaxListeners(){return this.maxListeners}prependListener(e,t){return this.on(e,t,{priority:Number.MAX_SAFE_INTEGER})}prependOnceListener(e,t){return this.once(e,t,Number.MAX_SAFE_INTEGER)}}var t,r;!function(e){e.USER_ERROR="USER_ERROR",e.SYSTEM_ERROR="SYSTEM_ERROR",e.NETWORK_ERROR="NETWORK_ERROR",e.PERMISSION_ERROR="PERMISSION_ERROR",e.CONFIG_ERROR="CONFIG_ERROR",e.VALIDATION_ERROR="VALIDATION_ERROR",e.TIMEOUT_ERROR="TIMEOUT_ERROR",e.UNSUPPORTED_ERROR="UNSUPPORTED_ERROR",e.INTERNAL_ERROR="INTERNAL_ERROR",e.EXTERNAL_ERROR="EXTERNAL_ERROR",e.UNKNOWN_ERROR="UNKNOWN_ERROR"}(t||(t={})),function(e){e.LOW="low",e.MEDIUM="medium",e.HIGH="high",e.CRITICAL="critical"}(r||(r={})),e.ErrorType=void 0,function(e){e.USER_ERROR="USER_ERROR",e.SYSTEM_ERROR="SYSTEM_ERROR",e.NETWORK_ERROR="NETWORK_ERROR",e.PERMISSION_ERROR="PERMISSION_ERROR",e.CONFIG_ERROR="CONFIG_ERROR",e.TIMEOUT_ERROR="TIMEOUT_ERROR",e.VALIDATION_ERROR="VALIDATION_ERROR",e.INTERNAL_ERROR="INTERNAL_ERROR",e.UNKNOWN_ERROR="UNKNOWN_ERROR"}(e.ErrorType||(e.ErrorType={})),e.LogLevel=void 0,function(e){e[e.DEBUG=0]="DEBUG",e[e.INFO=1]="INFO",e[e.WARN=2]="WARN",e[e.ERROR=3]="ERROR"}(e.LogLevel||(e.LogLevel={}));class Logger{constructor(t="Core",r){this.level=e.LogLevel.INFO,this.logs=[],this.maxLogs=1e3,this.enableConsole=!0,this.module=t,r&&(this.level=r.level??e.LogLevel.INFO,this.maxLogs=r.maxLogs??1e3,this.enableConsole=r.enableConsole??!0)}setLevel(e){this.level=e}getLevel(){return this.level}debug(t,r){this.log(e.LogLevel.DEBUG,t,r)}info(t,r){this.log(e.LogLevel.INFO,t,r)}warn(t,r){this.log(e.LogLevel.WARN,t,r)}error(t,r){this.log(e.LogLevel.ERROR,t,r)}log(e,t,r){if(e<this.level)return;const i={level:e,message:t,timestamp:Date.now(),module:this.module,data:r};this.logs.push(i),this.logs.length>this.maxLogs&&this.logs.shift(),this.enableConsole&&this.outputToConsole(i)}outputToConsole(t){new Date(t.timestamp).toISOString(),e.LogLevel[t.level],t.module,t.message,void 0!==t.data&&t.data;switch(t.level){case e.LogLevel.DEBUG:case e.LogLevel.INFO:case e.LogLevel.WARN:case e.LogLevel.ERROR:}}getLogs(){return[...this.logs]}getLogsByLevel(e){return this.logs.filter(t=>t.level===e)}getLogsByTimeRange(e,t){return this.logs.filter(r=>r.timestamp>=e&&r.timestamp<=t)}clear(){this.logs=[]}setMaxLogs(e){if(e<0)throw new Error("Max logs must be non-negative");this.maxLogs=e,this.logs.length>e&&(this.logs=this.logs.slice(-e))}setConsoleOutput(e){this.enableConsole=e}exportLogs(){return JSON.stringify(this.logs,null,2)}importLogs(e){try{const t=JSON.parse(e);Array.isArray(t)&&(this.logs=t.filter(e=>e&&"number"==typeof e.level&&"string"==typeof e.message&&"number"==typeof e.timestamp))}catch(e){this.error("Failed to import logs",e)}}createChild(e){return new Logger(`${this.module}.${e}`,{level:this.level,maxLogs:this.maxLogs,enableConsole:this.enableConsole})}}class i extends Error{constructor(e,t,r){super(t),this.name="CustomError",this.type=e,this.code=r?.code,this.context=r?.context,this.recoverable=r?.recoverable??!1,r?.cause&&(this.cause=r.cause),Error.captureStackTrace&&Error.captureStackTrace(this,i)}}class ErrorHandler{constructor(e){this.errorSolutions=new Map,this.logger=e||new Logger("ErrorHandler"),this.initializeErrorSolutions()}handleError(e,t){const r=this.classifyError(e),i={module:"Unknown",method:"Unknown",timestamp:Date.now(),userAgent:"undefined"!=typeof navigator?navigator.userAgent:"Node.js",...t},n={type:r,severity:this.getErrorSeverity(r),message:e.message,userMessage:this.getUserFriendlyMessage(e,r),originalError:e,context:i,code:this.getErrorCode(e)||this.generateErrorCode(r),recoverable:this.isRecoverableError(e),solutions:this.getErrorSolutions(e),id:this.generateErrorId(),processedAt:Date.now(),relatedErrors:[]};return this.logger.error(`[${r}] ${n.message}`,{error:e.message,stack:e.stack,context:i,recoverable:n.recoverable}),n}createError(e,t,r){const n={module:"Unknown",method:"Unknown",timestamp:Date.now(),userAgent:"undefined"!=typeof navigator?navigator.userAgent:"Node.js",...r?.context};return new i(e,t,{code:r?.code,context:n,recoverable:r?.recoverable,cause:r?.cause})}isRecoverableError(e){if(e instanceof i)return e.recoverable;switch(this.classifyError(e)){case t.NETWORK_ERROR:case t.TIMEOUT_ERROR:return!0;case t.PERMISSION_ERROR:case t.SYSTEM_ERROR:return!1;case t.USER_ERROR:case t.CONFIG_ERROR:return!0;default:return!1}}getErrorSolution(e){const t=this.getErrorCode(e);if(t&&this.errorSolutions.has(t))return this.errorSolutions.get(t);const r=this.classifyError(e);return this.getDefaultSolution(r)}getErrorSolutions(e){const t=this.getErrorSolution(e);return t?[{description:t,steps:[t],automatic:!1,priority:1}]:[]}getErrorSeverity(e){switch(e){case t.USER_ERROR:case t.CONFIG_ERROR:return r.LOW;case t.NETWORK_ERROR:case t.TIMEOUT_ERROR:return r.MEDIUM;case t.PERMISSION_ERROR:case t.VALIDATION_ERROR:return r.HIGH;case t.SYSTEM_ERROR:case t.INTERNAL_ERROR:return r.CRITICAL;default:return r.MEDIUM}}generateErrorCode(e){return`${e}_${Date.now().toString(36)}_${Math.random().toString(36).substr(2,5)}`.toUpperCase()}generateErrorId(){return`error_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}addErrorSolution(e,t){this.errorSolutions.set(e,t)}addErrorSolutions(e){for(const[t,r]of Object.entries(e))this.errorSolutions.set(t,r)}classifyError(e){if(e instanceof i)return e.type;const r=(e.message||"").toLowerCase(),n=(e.name||"").toLowerCase();return r.includes("network")||r.includes("fetch")||r.includes("xhr")||n.includes("networkerror")?t.NETWORK_ERROR:r.includes("timeout")||r.includes("timed out")||n.includes("timeouterror")?t.TIMEOUT_ERROR:r.includes("permission")||r.includes("denied")||r.includes("unauthorized")||r.includes("forbidden")||n.includes("notallowederror")?t.PERMISSION_ERROR:r.includes("not supported")||r.includes("not available")||r.includes("not implemented")||n.includes("notsupportederror")?t.SYSTEM_ERROR:r.includes("invalid")||r.includes("configuration")||r.includes("config")||n.includes("configerror")?t.CONFIG_ERROR:e instanceof TypeError||e instanceof RangeError||r.includes("invalid argument")||r.includes("invalid parameter")?t.USER_ERROR:t.UNKNOWN_ERROR}getUserFriendlyMessage(e,r){switch(r){case t.NETWORK_ERROR:return"网络连接失败,请检查网络连接后重试";case t.TIMEOUT_ERROR:return"操作超时,请稍后重试";case t.PERMISSION_ERROR:return"权限不足,请检查浏览器权限设置";case t.SYSTEM_ERROR:return"当前浏览器不支持此功能,请使用其他浏览器或升级浏览器版本";case t.CONFIG_ERROR:return"配置参数错误,请检查配置";case t.USER_ERROR:return"输入参数错误,请检查输入参数";default:return e.message||"发生未知错误"}}getErrorCode(e){if(e instanceof i)return e.code;const t=e;return t.code||t.errno||void 0}getDefaultSolution(e){switch(e){case t.NETWORK_ERROR:return"请检查网络连接,确保网络正常后重试";case t.TIMEOUT_ERROR:return"请稍后重试,或增加超时时间设置";case t.PERMISSION_ERROR:return"请在浏览器设置中允许相关权限,或使用HTTPS协议";case t.SYSTEM_ERROR:return"请使用支持此功能的现代浏览器,或升级浏览器版本";case t.CONFIG_ERROR:return"请检查配置参数是否正确,参考文档进行配置";case t.USER_ERROR:return"请检查输入参数的类型和格式是否正确";default:return null}}initializeErrorSolutions(){this.errorSolutions.set("ENOTFOUND","域名解析失败,请检查网络连接"),this.errorSolutions.set("ECONNREFUSED","连接被拒绝,请检查服务器状态"),this.errorSolutions.set("ETIMEDOUT","连接超时,请检查网络连接或稍后重试"),this.errorSolutions.set("CERT_UNTRUSTED","SSL证书不受信任,请检查证书配置"),this.errorSolutions.set("MIXED_CONTENT","混合内容错误,请使用HTTPS协议")}}class Cache{constructor(e){this.cache=new Map,this.config={maxSize:e?.maxSize??100,defaultTTL:e?.defaultTTL??3e5,enableLRU:e?.enableLRU??!0,cleanupInterval:e?.cleanupInterval??6e4},this.startCleanup()}set(e,t,r){const i=Date.now(),n={value:t,expireAt:i+(r??this.config.defaultTTL),createdAt:i,accessCount:0,lastAccessed:i};this.cache.size>=this.config.maxSize&&!this.cache.has(e)&&this.evictLRU(),this.cache.set(e,n)}get(e){const t=this.cache.get(e);if(!t)return;const r=Date.now();if(!(r>t.expireAt))return t.accessCount++,t.lastAccessed=r,t.value;this.cache.delete(e)}has(e){const t=this.cache.get(e);return!!t&&(!(Date.now()>t.expireAt)||(this.cache.delete(e),!1))}delete(e){return this.cache.delete(e)}clear(){this.cache.clear()}size(){return this.cache.size}keys(){return Array.from(this.cache.keys())}getInfo(e){const t=this.cache.get(e);if(t){if(!(Date.now()>t.expireAt))return{...t};this.cache.delete(e)}}touch(e,t){const r=this.cache.get(e);if(!r)return!1;const i=Date.now();if(i>r.expireAt)return this.cache.delete(e),!1;const n=t??this.config.defaultTTL;return r.expireAt=i+n,r.lastAccessed=i,!0}async getOrSet(e,t,r){const i=this.get(e);if(void 0!==i)return i;const n=await t();return this.set(e,n,r),n}mset(e,t){for(const[r,i]of e)this.set(r,i,t)}mget(e){return e.map(e=>this.get(e))}mdel(e){let t=0;for(const r of e)this.delete(r)&&t++;return t}getStats(){let e=0,t=0;const r=Date.now();for(const[i,n]of this.cache.entries())e+=n.accessCount,r>n.expireAt&&t++;return{size:this.cache.size,maxSize:this.config.maxSize,hitRate:e>0?(e-t)/e:0,totalAccess:e,expiredCount:t}}cleanup(){const e=Date.now();let t=0;for(const[r,i]of this.cache.entries())e>i.expireAt&&(this.cache.delete(r),t++);return t}evictLRU(){if(!this.config.enableLRU||0===this.cache.size)return;let e=null,t=1/0;for(const[r,i]of this.cache.entries())i.lastAccessed<t&&(t=i.lastAccessed,e=r);e&&this.cache.delete(e)}startCleanup(){this.cleanupTimer&&clearInterval(this.cleanupTimer),this.cleanupTimer=setInterval(()=>{this.cleanup()},this.config.cleanupInterval)}stopCleanup(){this.cleanupTimer&&(clearInterval(this.cleanupTimer),this.cleanupTimer=void 0)}updateConfig(e){if(this.config={...this.config,...e},void 0!==e.cleanupInterval&&this.startCleanup(),void 0!==e.maxSize&&this.cache.size>e.maxSize)for(;this.cache.size>e.maxSize;)this.evictLRU()}destroy(){this.stopCleanup(),this.clear()}}class BaseManager{constructor(e,t="BaseManager"){this.initialized=!1,this.destroyed=!1,this.initializing=!1,this.options=this.mergeDefaultOptions(e),this.logger=new Logger(t,{level:this.options.debug?0:1,enableConsole:this.options.debug}),this.eventEmitter=new EventEmitter,this.errorHandler=new ErrorHandler(this.logger),this.options.cache&&(this.cache=new Cache),this.setupErrorHandling(),this.startAutoInitialization()}on(e,t,r){return this.eventEmitter.on(e,t,r),this}off(e,t){return this.eventEmitter.off(e,t),this}emit(e,...t){return this.eventEmitter.emit(e,...t)}once(e,t,r){return this.eventEmitter.once(e,t,r),this}listenerCount(e){return this.eventEmitter.listenerCount(e)}eventNames(){return this.eventEmitter.eventNames()}handleError(e,t){const r={module:this.constructor.name,method:t},i=this.errorHandler.handleError(e,r);return this.emit("error",i),i}validateInput(e,t){try{if(t.type){const r=typeof e;if(r!==t.type)throw this.errorHandler.createError("USER_ERROR",`Expected ${t.type}, got ${r}`,{context:{method:"validateInput"}})}if(t.required&&null==e)throw this.errorHandler.createError("USER_ERROR","Required parameter is missing",{context:{method:"validateInput"}});if(t.isArray&&!Array.isArray(e))throw this.errorHandler.createError("USER_ERROR","Expected array",{context:{method:"validateInput"}});if(t.properties&&"object"==typeof e&&null!==e)for(const[r,i]of Object.entries(t.properties))if(!this.validateInput(e[r],i))return!1;return!0}catch(e){return this.handleError(e,"validateInput"),!1}}async safeExecute(e,t,r){const i=r??this.options.retries??0;let n=null;for(let r=0;r<=i;r++)try{const i=new Promise((e,r)=>{setTimeout(()=>{r(this.errorHandler.createError("TIMEOUT_ERROR",`Operation timed out after ${this.options.timeout}ms`,{context:{method:t}}))},this.options.timeout)}),n=await Promise.race([e(),i]);return r>0&&this.logger.info(`Operation succeeded after ${r} retries`,{context:t}),n}catch(e){if(n=e,r===i||!this.errorHandler.isRecoverableError(n))throw this.handleError(n,t);const s=Math.min(1e3*Math.pow(2,r),5e3);this.logger.warn(`Operation failed, retrying in ${s}ms (attempt ${r+1}/${i+1})`,{context:t,error:n.message}),await new Promise(e=>setTimeout(e,s))}throw this.handleError(n,t)}getCached(e){return this.cache?.get(e)}setCached(e,t,r){this.cache?.set(e,t,r)}async getOrSetCached(e,t,r){return this.cache?this.cache.getOrSet(e,t,r):t()}async ensureInitialized(){if(this.destroyed)throw this.errorHandler.createError("SYSTEM_ERROR","Manager has been destroyed and cannot be used.",{context:{method:"ensureInitialized"}});if(!this.initialized)if(this.initPromise)try{await this.initPromise,this.initPromise=void 0}catch(e){throw this.errorHandler.createError("SYSTEM_ERROR",`Manager initialization failed: ${e.message}`,{context:{method:"ensureInitialized"}})}else if(!this.initializing){this.initializing=!0;try{await this.initialize()}finally{this.initializing=!1}}}ensureInitializedSync(){if(!this.initialized)throw this.errorHandler.createError("SYSTEM_ERROR","Manager not initialized. Operations requiring initialization should be awaited.",{context:{method:"ensureInitializedSync"}})}ensureNotDestroyed(){if(this.destroyed)throw this.errorHandler.createError("SYSTEM_ERROR","Manager has been destroyed and cannot be used.",{context:{method:"ensureNotDestroyed"}})}async ready(){await this.ensureInitialized()}getStatus(){return{initialized:this.initialized,destroyed:this.destroyed,eventListeners:this.eventNames().reduce((e,t)=>e+this.listenerCount(t),0),cacheSize:this.cache?.size(),initializing:this.initializing||!!this.initPromise}}updateOptions(e){this.options={...this.options,...e},void 0!==e.debug&&(this.logger.setLevel(e.debug?0:1),this.logger.setConsoleOutput(e.debug)),this.emit("optionsUpdated",this.options)}mergeDefaultOptions(e){return{...this.getDefaultOptions(),...e}}setupErrorHandling(){"undefined"!=typeof window?window.addEventListener("unhandledrejection",e=>{this.handleError(new Error(e.reason),"unhandledrejection")}):"undefined"!=typeof process&&process.on("unhandledRejection",e=>{this.handleError(new Error(String(e)),"unhandledRejection")})}startAutoInitialization(){this.initPromise=this.initialize().catch(e=>(this.logger.error("Auto-initialization failed:",e),Promise.reject(e))),this.initPromise.catch(()=>{})}baseDestroy(){this.destroyed||(this.emit("beforeDestroy"),this.eventEmitter.removeAllListeners(),this.cache?.destroy(),this.logger.clear(),this.destroyed=!0,this.initialized=!1,this.emit("destroyed"))}}var n=Object.freeze({__proto__:null,BaseManager:BaseManager,Cache:Cache,CustomError:i,ErrorHandler:ErrorHandler,get ErrorType(){return e.ErrorType},EventEmitter:EventEmitter,get LogLevel(){return e.LogLevel},Logger:Logger});class s{constructor(e={}){this.VENDOR_PREFIXES=["","webkit","moz","ms","o"],this.CSS_PREFIXES=["","-webkit-","-moz-","-ms-","-o-"],this.browserInfo=null,this.config={enableCache:!0,cacheTimeout:3e5,debug:!1,customPrefixes:[],...e},this.cache=new Cache({maxSize:200,defaultTTL:this.config.cacheTimeout,enableLRU:!0}),this.logger=new Logger("BrowserAdapter",{level:this.config.debug?0:2,enableConsole:this.config.debug}),this.errorHandler=new ErrorHandler}isSupported(e){return this.detectFeature(e).supported}getPrefixedProperty(e){const t=this.detectFeature(e,"property");return t.supported?t.prefixedName||e:null}getPrefixedMethod(e,t=window){const r=this.detectFeature(e,"method",t);if(!r.supported)return null;return t[r.prefixedName||e]||null}getPrefixedCSSProperty(e){const t=this.detectFeature(e,"css");return t.supported?t.prefixedName||e:null}detectFeature(e,t="property",r=null){const i=`${e}_${t}_${r?"custom":"default"}`;if(this.config.enableCache){const t=this.cache.get(i);if(t)return this.logger.debug(`Feature detection cache hit: ${e}`),t}let n;try{switch(t){case"property":default:n=this.detectProperty(e);break;case"method":n=this.detectMethod(e,null===r?null:r||window);break;case"css":n=this.detectCSSProperty(e);break;case"api":n=this.detectAPI(e);break;case"custom":n=this.detectCustomFeature(e,r)}return n.timestamp=Date.now(),this.config.enableCache&&this.cache.set(i,n),this.logger.debug(`Feature detection result for ${e}:`,n),n}catch(i){const n={module:"BrowserAdapter",method:"detectFeature",input:{feature:e,method:t,target:r},timestamp:Date.now()};return this.errorHandler.handleError(i,n),{supported:!1,method:t,timestamp:Date.now()}}}detectProperty(e){const t=[document.documentElement.style,window,document,navigator];for(const r of t)if(e in r)return{supported:!0,method:"property",timestamp:Date.now()};const r=[...this.VENDOR_PREFIXES.slice(1),...this.config.customPrefixes];for(const i of r){const r=this.getPrefixedName(e,i);for(const e of t)if(r in e)return{supported:!0,prefixedName:r,prefix:i,method:"property",timestamp:Date.now()}}return{supported:!1,method:"property",timestamp:Date.now()}}detectMethod(e,t){if(!t||"object"!=typeof t)return{supported:!1,method:"method",timestamp:Date.now()};if("function"==typeof t[e])return{supported:!0,method:"method",timestamp:Date.now()};const r=[...this.VENDOR_PREFIXES.slice(1),...this.config.customPrefixes];for(const i of r){const r=this.getPrefixedName(e,i);if("function"==typeof t[r])return{supported:!0,prefixedName:r,prefix:i,method:"method",timestamp:Date.now()}}return{supported:!1,method:"method",timestamp:Date.now()}}detectCSSProperty(e){const t=document.createElement("div").style;if(e in t)return{supported:!0,method:"css",timestamp:Date.now()};for(const r of this.CSS_PREFIXES.slice(1)){const i=`${r}${e}`;if(i in t)return{supported:!0,prefixedName:i,prefix:r.replace(/-/g,""),method:"css",timestamp:Date.now()}}try{if(t.setProperty(e,"initial"),t.getPropertyValue(e))return{supported:!0,method:"css",timestamp:Date.now()}}catch{}return{supported:!1,method:"css",timestamp:Date.now()}}detectAPI(e){const t=[e,`window.${e}`,`navigator.${e}`,`document.${e}`];for(const e of t)try{if(void 0!==this.getNestedProperty(window,e))return{supported:!0,method:"api",timestamp:Date.now()}}catch{continue}return{supported:!1,method:"api",timestamp:Date.now()}}detectCustomFeature(e,t){try{let e=!1;return"function"==typeof t?e=t():"boolean"==typeof t?e=t:t&&"function"==typeof t.test&&(e=t.test()),{supported:e,method:"custom",timestamp:Date.now()}}catch{return{supported:!1,method:"custom",timestamp:Date.now()}}}getPrefixedName(e,t){return t?`${t}${e.charAt(0).toUpperCase()}${e.slice(1)}`:e}getNestedProperty(e,t){return t.split(".").reduce((e,t)=>e&&void 0!==e[t]?e[t]:void 0,e)}getBrowserInfo(){if(this.browserInfo)return this.browserInfo;const e=navigator.userAgent,t={name:"Unknown",version:"0.0.0",engine:"Unknown",mobile:!1,os:"Unknown"};if(e.includes("Chrome")){t.name="Chrome",t.engine="Blink";const r=e.match(/Chrome\/(\d+\.\d+)/);r&&(t.version=r[1])}else if(e.includes("Firefox")){t.name="Firefox",t.engine="Gecko";const r=e.match(/Firefox\/(\d+\.\d+)/);r&&(t.version=r[1])}else if(e.includes("Safari")&&!e.includes("Chrome")){t.name="Safari",t.engine="WebKit";const r=e.match(/Version\/(\d+\.\d+)/);r&&(t.version=r[1])}else if(e.includes("Edge")){t.name="Edge",t.engine="Blink";const r=e.match(/Edge\/(\d+\.\d+)/);r&&(t.version=r[1])}return t.mobile=/Mobile|Android|iPhone|iPad/.test(e),e.includes("Windows")?t.os="Windows":e.includes("Mac")?t.os="macOS":e.includes("Linux")?t.os="Linux":e.includes("Android")?t.os="Android":(e.includes("iPhone")||e.includes("iPad"))&&(t.os="iOS"),this.browserInfo=t,t}addEventListenerCompat(e,t,r,i){if(e.addEventListener)return e.addEventListener(t,r,i),()=>e.removeEventListener(t,r,i);const n=e;if(n.attachEvent){const i=t=>{!t.target&&t.srcElement&&Object.defineProperty(t,"target",{value:t.srcElement,writable:!1,enumerable:!0,configurable:!0}),t.preventDefault=t.preventDefault||(()=>{t.returnValue=!1}),t.stopPropagation=t.stopPropagation||(()=>{t.cancelBubble=!0}),r.call(e,t)};return n.attachEvent(`on${t}`,i),()=>n.detachEvent(`on${t}`,i)}const s=`on${t}`,o=e[s];return e[s]=t=>{o&&o.call(e,t),r.call(e,t)},()=>{e[s]=o}}clearCache(){this.cache.clear(),this.browserInfo=null,this.logger.info("Browser adapter cache cleared")}getCacheStats(){const e=this.cache.getStats();return{size:this.cache.size(),hitRate:e.hitRate,maxSize:e.maxSize}}destroy(){this.clearCache(),this.logger.info("Browser adapter destroyed")}}let o=null;function a(e){return o||(o=new s(e)),o}function c(e){return!(!e||"object"!=typeof e||e.nodeType!==Node.ELEMENT_NODE)}function l(e){return c(e)&&e instanceof HTMLElement}function d(e){return e&&e.nodeType===Node.DOCUMENT_NODE}function h(e){if(!e)return null;if(c(e))return e;if("string"==typeof e)try{return document.querySelector(e)}catch(e){return null}return null}function u(e){try{return Array.from(document.querySelectorAll(e))}catch(e){return[]}}const m=["","webkit","moz","ms","o"];function p(e){if(e in document.documentElement.style||e in window||e in document)return{supported:!0};for(const t of m.slice(1)){const r=`${t}${e.charAt(0).toUpperCase()}${e.slice(1)}`;if(r in document.documentElement.style||r in window||r in document)return{supported:!0,prefixedName:r,prefix:t}}return{supported:!1}}function f(e){const t=p(e);return t.supported?t.prefixedName||e:null}function g(e,t){const r=document.createElement("div"),i=f(e);if(!i)return!1;try{return r.style[i]=t||"initial",""!==r.style[i]}catch{return!1}}function y(e){return e in document.createElement("div")}function w(e){return p(e).supported}function E(e){return f(e)}const b=new class{constructor(){this.listeners=new WeakMap}add(e,t,r,i){e.addEventListener(t,r,i),this.listeners.has(e)||this.listeners.set(e,new Map);const n=this.listeners.get(e);return n.has(t)||n.set(t,new Set),n.get(t).add(r),()=>this.remove(e,t,r,i)}remove(e,t,r,i){e.removeEventListener(t,r,i);const n=this.listeners.get(e);if(n){const e=n.get(t);e&&(e.delete(r),0===e.size&&n.delete(t))}}removeAll(e){const t=this.listeners.get(e);if(t){for(const[r,i]of t)for(const t of i)e.removeEventListener(r,t);this.listeners.delete(e)}}};function v(e,t,r,i){const n=(e instanceof Element?e:h(e))||e;if(!n)throw new Error("Invalid event target");return b.add(n,t,r,i)}function R(e,t,r,i){const n=(e instanceof Element?e:h(e))||e;if(!n)throw new Error("Invalid event target");b.remove(n,t,r,i)}function S(e){const t=(e instanceof Element?e:h(e))||e;t&&b.removeAll(t)}function T(e,t,r){return new CustomEvent(e,{detail:t,bubbles:!0,cancelable:!0,...r})}function x(e,t,r,i){const n=h(e);if(!n)throw new Error("Invalid event target for dispatch");const s=T(t,r,i);return n.dispatchEvent(s)}function I(e,t,r,i,n){const s=h(e);if(!s)throw new Error("Invalid container for event delegation");return v(s,r,e=>{const r=e.target.closest(t);r&&s.contains(r)&&i(e,r)},n)}const C=new class{constructor(){this.operations=[],this.rafId=null}add(e){this.operations.push(e),this.schedule()}schedule(){null===this.rafId&&(this.rafId=requestAnimationFrame(()=>{this.flush()}))}flush(){const e=this.operations.splice(0);this.rafId=null;for(const t of e)try{t()}catch(e){}}flushSync(){null!==this.rafId&&(cancelAnimationFrame(this.rafId),this.rafId=null),this.flush()}};function F(e){e.forEach(e=>C.add(e))}function O(){return document.createDocumentFragment()}function D(e,t,r={}){const i=h(e);if(!i)throw new Error("Invalid container element");const{useFragment:n=!0}=r;if(n&&t.length>1){const e=O();t.forEach(t=>{if("string"==typeof t){const r=document.createElement("div");for(r.innerHTML=t;r.firstChild;)e.appendChild(r.firstChild)}else e.appendChild(t)}),i.appendChild(e)}else t.forEach(e=>{"string"==typeof e?i.insertAdjacentHTML("beforeend",e):i.appendChild(e)})}function N(e,t){const r=h(e);if(!r)throw new Error("Invalid target element for style setting");C.add(()=>{Object.assign(r.style,t)})}function L(e,t){const r=h(e);if(!r)throw new Error("Invalid target element for attribute setting");C.add(()=>{Object.entries(t).forEach(([e,t])=>{r.setAttribute(e,t)})})}function A(e){const t=h(e);return t?t.getBoundingClientRect():null}function M(e,t=0){const r=h(e);if(!r)return!1;const i=r.getBoundingClientRect(),n=window.innerHeight||document.documentElement.clientHeight,s=window.innerWidth||document.documentElement.clientWidth;return i.top>=-t&&i.left>=-t&&i.bottom<=n+t&&i.right<=s+t}function _(e){"loading"===document.readyState?document.addEventListener("DOMContentLoaded",e,{once:!0}):e()}function z(e,t=5e3){return new Promise((r,i)=>{const n=h(e);if(n)return void r(n);const s=new MutationObserver(()=>{const t=h(e);t&&(s.disconnect(),clearTimeout(o),r(t))}),o=setTimeout(()=>{s.disconnect(),i(new Error(`Element ${e} not found within ${t}ms`))},t);s.observe(document.body,{childList:!0,subtree:!0})})}function k(){C.flushSync()}class P extends BaseManager{constructor(e){super(e,"FullscreenManager"),this.requestStartTime=0,this.browserAdapter=new s({enableCache:this.options.cache,debug:this.options.debug}),this.currentState={isFullscreen:!1,element:null},this.performanceMetrics={enterTime:0,exitTime:0,duration:0,errorCount:0,successCount:0}}getDefaultOptions(){return{debug:!1,timeout:5e3,retries:2,cache:!0,navigationUI:"auto",enablePerformanceMonitoring:!1,requestTimeout:3e3,allowKeyboardInput:!0}}async initialize(){if(!this.initialized)try{this.initEventListeners(),this.updateCurrentState(),this.initialized=!0,this.logger.info("FullscreenManager initialized successfully",{supported:this.isSupported,enabled:this.isEnabled}),this.emit("initialized")}catch(e){throw this.handleError(e,"initialize")}}destroy(){if(!this.destroyed)try{this.currentState.isFullscreen&&this.exit().catch(()=>{}),this.removeEventListeners(),this.browserAdapter.destroy(),this.baseDestroy(),this.logger.info("FullscreenManager destroyed successfully")}catch(e){this.handleError(e,"destroy")}}get isSupported(){const e="fullscreen_support",t=this.getCached(e);if(void 0!==t)return t;let r=!1;if("undefined"!=typeof document&&document.documentElement){const e=document.documentElement;r=!!("fullscreenEnabled"in document||"webkitFullscreenEnabled"in document||"mozFullScreenEnabled"in document||"msFullscreenEnabled"in document||"requestFullscreen"in e||"webkitRequestFullscreen"in e||"mozRequestFullScreen"in e||"msRequestFullscreen"in e)}return this.setCached(e,r,6e4),r}get isEnabled(){const e="fullscreen_enabled",t=this.getCached(e);if(void 0!==t)return t;const r=!!(document.fullscreenEnabled||document.webkitFullscreenEnabled||document.mozFullScreenEnabled||document.msFullscreenEnabled);return this.setCached(e,r,6e4),r}get isFullscreen(){return this.updateCurrentState(),this.currentState.isFullscreen}get element(){return this.updateCurrentState(),this.currentState.element}get state(){return{...this.currentState}}get performanceData(){return{...this.performanceMetrics}}async request(t,r){return await this.ensureInitialized(),this.ensureNotDestroyed(),this.safeExecute(async()=>{const i=t||document.documentElement;if(!this.validateInput(i,{type:"object",required:!0}))throw this.errorHandler.createError(e.ErrorType.USER_ERROR,"Invalid element provided for fullscreen request",{context:{method:"request",module:"FullscreenManager"}});if(!c(i))throw this.errorHandler.createError(e.ErrorType.USER_ERROR,"Provided element is not a valid DOM element",{context:{method:"request",module:"FullscreenManager"}});if(!this.isSupported)throw this.errorHandler.createError(e.ErrorType.SYSTEM_ERROR,"Fullscreen is not supported in this browser",{context:{method:"request",module:"FullscreenManager"}});if(!this.isEnabled)throw this.errorHandler.createError(e.ErrorType.SYSTEM_ERROR,"Fullscreen is not enabled in this browser",{context:{method:"request",module:"FullscreenManager"}});if(this.currentState.isFullscreen&&this.currentState.element===i)return void this.logger.debug("Element is already in fullscreen mode");this.requestStartTime=this.options.enablePerformanceMonitoring?performance.now():0,this.emit("request",{element:i,options:r});const n={navigationUI:r?.navigationUI||this.options.navigationUI,...r};try{const e=this.getRequestMethodName();if(!e||!(e in i))throw new Error("Fullscreen request method not supported");if("webkitRequestFullscreen"===e){const t=this.options.allowKeyboardInput?Element.ALLOW_KEYBOARD_INPUT:void 0;await i[e](t)}else await i[e](n);this.options.enablePerformanceMonitoring&&this.requestStartTime>0&&(this.performanceMetrics.enterTime=performance.now()-this.requestStartTime,this.performanceMetrics.successCount++),this.logger.info("Fullscreen request successful",{element:i.tagName})}catch(t){throw this.options.enablePerformanceMonitoring&&this.performanceMetrics.errorCount++,this.errorHandler.createError(e.ErrorType.SYSTEM_ERROR,`Failed to enter fullscreen: ${t.message}`,{context:{method:"request",module:"FullscreenManager"},cause:t})}},"request",this.options.retries)}async exit(){return await this.ensureInitialized(),this.ensureNotDestroyed(),this.safeExecute(async()=>{if(!this.currentState.isFullscreen)return void this.logger.debug("Not in fullscreen mode, exit request ignored");const t=this.options.enablePerformanceMonitoring?performance.now():0;this.emit("exit",{element:this.currentState.element});try{const e=this.getExitMethodName();if(!e||!(e in document))throw new Error("Fullscreen exit method not supported");await document[e](),this.options.enablePerformanceMonitoring&&t>0&&(this.performanceMetrics.exitTime=performance.now()-t,this.performanceMetrics.successCount++),this.logger.info("Fullscreen exit successful")}catch(t){throw this.options.enablePerformanceMonitoring&&this.performanceMetrics.errorCount++,this.errorHandler.createError(e.ErrorType.SYSTEM_ERROR,`Failed to exit fullscreen: ${t.message}`,{context:{method:"exit"},cause:t})}},"exit",this.options.retries)}async toggle(e,t){await this.ensureInitialized(),this.ensureNotDestroyed(),this.currentState.isFullscreen?await this.exit():await this.request(e,t)}initEventListeners(){try{const e=this.detectChangeEventName(),t=this.detectErrorEventName();e&&(this.removeChangeListener=this.browserAdapter.addEventListenerCompat(document,e,this.handleFullscreenChange.bind(this)),this.logger.debug(`Listening for fullscreen change event: ${e}`)),t&&(this.removeErrorListener=this.browserAdapter.addEventListenerCompat(document,t,this.handleFullscreenError.bind(this)),this.logger.debug(`Listening for fullscreen error event: ${t}`))}catch(e){this.handleError(e,"initEventListeners")}}removeEventListeners(){try{this.removeChangeListener&&(this.removeChangeListener(),this.removeChangeListener=void 0),this.removeErrorListener&&(this.removeErrorListener(),this.removeErrorListener=void 0),this.logger.debug("Fullscreen event listeners removed")}catch(e){this.handleError(e,"removeEventListeners")}}handleFullscreenChange(e){try{const t=this.currentState.isFullscreen;if(this.updateCurrentState(),t&&!this.currentState.isFullscreen&&this.currentState.startTime){const e=Date.now()-this.currentState.startTime;this.currentState.duration=e,this.options.enablePerformanceMonitoring&&(this.performanceMetrics.duration=e)}this.logger.debug("Fullscreen state changed",{isFullscreen:this.currentState.isFullscreen,element:this.currentState.element?.tagName}),this.emit("change",{isFullscreen:this.currentState.isFullscreen,element:this.currentState.element,event:e})}catch(e){this.handleError(e,"handleFullscreenChange")}}handleFullscreenError(t){try{this.options.enablePerformanceMonitoring&&this.performanceMetrics.errorCount++;const r=this.errorHandler.createError(e.ErrorType.SYSTEM_ERROR,"Fullscreen operation failed",{context:{method:"handleFullscreenError"}});this.logger.error("Fullscreen error occurred",{event:t}),this.emit("error",{error:r,event:t})}catch(e){this.handleError(e,"handleFullscreenError")}}updateCurrentState(){const e=document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement||null,t=!!e;t!==this.currentState.isFullscreen&&(this.currentState=t?{isFullscreen:!0,element:e,startTime:Date.now()}:{isFullscreen:!1,element:null,duration:this.currentState.startTime?Date.now()-this.currentState.startTime:void 0})}detectChangeEventName(){const e="fullscreen_change_event",t=this.getCached(e);if(t)return t;const r=["fullscreenchange","webkitfullscreenchange","mozfullscreenchange","msfullscreenchange"];for(const t of r){if(this.browserAdapter.detectFeature(`on${t}`,"property",document).supported)return this.setCached(e,t,3e5),t}return null}detectErrorEventName(){const e="fullscreen_error_event",t=this.getCached(e);if(t)return t;const r=["fullscreenerror","webkitfullscreenerror","mozfullscreenerror","msfullscreenerror"];for(const t of r){if(this.browserAdapter.detectFeature(`on${t}`,"property",document).supported)return this.setCached(e,t,3e5),t}return null}getRequestMethodName(){const e="fullscreen_request_method",t=this.getCached(e);if(t)return t;const r=["requestFullscreen","webkitRequestFullscreen","mozRequestFullScreen","msRequestFullscreen"];if(document.documentElement)for(const t of r){const r=this.browserAdapter.detectFeature(t,"method",document.documentElement);if(r.supported){const i=r.prefixedName||t;return this.setCached(e,i,3e5),i}}return this.setCached(e,"requestFullscreen",3e5),"requestFullscreen"}getExitMethodName(){const e="fullscreen_exit_method",t=this.getCached(e);if(t)return t;const r=["exitFullscreen","webkitExitFullscreen","mozCancelFullScreen","msExitFullscreen"];for(const t of r){const r=this.browserAdapter.detectFeature(t,"method",document);if(r.supported){const i=r.prefixedName||t;return this.setCached(e,i,3e5),i}}return this.setCached(e,"exitFullscreen",3e5),"exitFullscreen"}}let U=null;const H=(U||(U=new P($)),U);var $,W,B;!function(e){e.GRANTED="granted",e.DENIED="denied",e.PROMPT="prompt",e.UNKNOWN="unknown"}(W||(W={})),function(e){e.MODERN_API="modern",e.EXEC_COMMAND="execCommand",e.SELECTION_API="selection",e.INPUT_ELEMENT="input",e.TEXTAREA_ELEMENT="textarea"}(B||(B={}));class j extends BaseManager{constructor(e){super(e,"ClipboardManager"),this.dataConverters=new Map,this.permissionCache=new Map,this.eventListeners=new Map,this.initializeDataConverters()}getDefaultOptions(){return{debug:!1,timeout:5e3,retries:2,cache:!0,cacheTTL:3e4,defaultFormat:"text",enablePermissionCheck:!0,maxDataSize:10485760,enableDataValidation:!0,enableFallback:!0,permissionTimeout:3e3,enableHtmlSanitization:!0,supportedMimeTypes:["text/plain","text/html","text/rtf","image/png","image/jpeg","image/gif","image/webp"],autoRequestPermissions:!0,fallbackStrategies:["modern","execCommand","selection","input"],enableDataConversion:!0,maxFileCount:10,allowedFileTypes:["image/*","text/*",".pdf",".doc",".docx"]}}async initialize(){if(this.ensureNotDestroyed(),!this.initialized)try{this.logger.info("Initializing ClipboardManager"),await this.checkBrowserSupport(),this.options.enablePermissionCheck&&await this.checkPermissions(),this.setupEventListeners(),this.initializeValidationRules(),this.initialized=!0,this.emit("initialized"),this.logger.info("ClipboardManager initialized successfully")}catch(e){throw this.handleError(e,"initialize")}}destroy(){this.destroyed||(this.logger.info("Destroying ClipboardManager"),this.removeEventListeners(),this.permissionCache.clear(),this.dataConverters.clear(),this.eventListeners.clear(),this.baseDestroy(),this.logger.info("ClipboardManager destroyed"))}get isSupported(){return"undefined"!=typeof navigator&&"clipboard"in navigator&&"writeText"in navigator.clipboard}get canRead(){return"undefined"!=typeof navigator&&"clipboard"in navigator&&"readText"in navigator.clipboard}get canWrite(){return this.isSupported}async copyText(e,r={}){return await this.ensureInitialized(),this.ensureNotDestroyed(),this.safeExecute(async()=>{if(!this.validateInput(e,{type:"string",required:!0}))throw this.errorHandler.createError(t.USER_ERROR,"Invalid text input for clipboard copy",{context:{method:"copyText"}});let i=e;this.options.enableDataValidation&&this.validateClipboardData(e,"text"),r.format&&"text"!==r.format&&(i=await this.convertData(e,"text",r.format,{enableCaching:this.options.cache,enableChunking:!0,maxProcessingTime:this.options.timeout}));const n=`copy_text_${this.hashString(i)}`,s=this.getCached(n);if(void 0!==s)return this.logger.debug("Using cached copy result"),s;let o=!1,a=null;try{if(this.options.enablePermissionCheck&&(a=await this.requestPermissionSmart("write"),!a.granted&&!a.fallbackAvailable))throw a.error||this.errorHandler.createError(t.PERMISSION_ERROR,"Clipboard write permission denied and no fallback available",{context:{method:"copyText"}});if(!this.canWrite||a&&!a.granted){if(!1===r.fallback||!this.options.enableFallback)throw this.errorHandler.createError(t.SYSTEM_ERROR,"Clipboard API not supported and fallback disabled",{context:{method:"copyText"}});o=await this.fallbackCopyText(i),this.logger.debug("Text copied using fallback method")}else await navigator.clipboard.writeText(i),o=!0,this.logger.debug("Text copied using modern API")}catch(e){if(!1===r.fallback||!this.options.enableFallback)throw e;try{o=await this.fallbackCopyText(i),this.logger.warn("Fallback to alternative method after API failure")}catch(t){throw e}}return this.setCached(n,o,5e3),o&&this.emit("copy",{type:"text",data:i,size:i.length,timestamp:Date.now(),mimeType:r.mimeType||"text/plain",encoding:r.encoding||"utf-8"}),o},"copyText")}async copyHTML(e,r={}){return await this.ensureInitialized(),this.ensureNotDestroyed(),this.safeExecute(async()=>{if(!this.validateInput(e,{type:"string",required:!0}))throw this.errorHandler.createError(t.USER_ERROR,"Invalid HTML input for clipboard copy",{context:{method:"copyHTML"}});let i=e;this.options.enableDataValidation&&this.validateClipboardData(e,"html"),!1!==r.sanitizeHtml&&this.options.enableHtmlSanitization&&(i=this.sanitizeHtml(e)),r.format&&"html"!==r.format&&(i=await this.convertData(i,"html",r.format,{enableCaching:this.options.cache,enableChunking:!0,maxProcessingTime:this.options.timeout}));const n=`copy_html_${this.hashString(i)}`,s=this.getCached(n);if(void 0!==s)return this.logger.debug("Using cached HTML copy result"),s;let o=!1,a=null;try{if(this.options.enablePermissionCheck&&(a=await this.requestPermissionSmart("write"),!a.granted&&!a.fallbackAvailable))throw a.error||this.errorHandler.createError(t.PERMISSION_ERROR,"Clipboard write permission denied and no fallback available",{context:{method:"copyHTML"}});if(this.canWrite&&"write"in navigator.clipboard&&"undefined"!=typeof ClipboardItem&&(!a||a.granted)){const e=r.mimeType||"text/html",t=new Blob([i],{type:e}),n=[new ClipboardItem({[e]:t})];await navigator.clipboard.write(n),o=!0,this.logger.debug("HTML copied using modern API")}else{if(!1===r.fallback||!this.options.enableFallback)throw this.errorHandler.createError(t.SYSTEM_ERROR,"Clipboard HTML API not supported and fallback disabled",{context:{method:"copyHTML"}});o=await this.fallbackCopyHTML(i),this.logger.debug("HTML copied using fallback method")}}catch(e){if(!1===r.fallback||!this.options.enableFallback)throw e;try{o=await this.fallbackCopyHTML(i),this.logger.warn("Fallback to alternative method after HTML API failure")}catch(t){throw e}}return this.setCached(n,o,5e3),o&&this.emit("copy",{type:"html",data:i,size:i.length,timestamp:Date.now(),mimeType:r.mimeType||"text/html",encoding:r.encoding||"utf-8"}),o},"copyHTML")}async copyElement(e,r={}){return await this.ensureInitialized(),this.ensureNotDestroyed(),this.safeExecute(async()=>{const i=h(e);if(!i)throw this.errorHandler.createError(t.USER_ERROR,"Invalid element provided for clipboard copy",{context:{method:"copyElement",input:e}});const{format:n=this.options.defaultFormat,fallback:s=this.options.enableFallback}=r;try{return"html"===n?await this.copyHTML(i.innerHTML,r):await this.copyText(i.textContent||"",r)}catch(e){if(s)return this.logger.warn("Attempting fallback element copy method"),await this.fallbackCopyElement(i,n);throw e}},"copyElement")}async readText(e={}){return await this.ensureInitialized(),this.ensureNotDestroyed(),this.safeExecute(async()=>{if(!this.canRead)throw this.errorHandler.createError(t.SYSTEM_ERROR,"Clipboard reading not supported in this browser",{context:{method:"readText"}});let r=null;if(this.options.enablePermissionCheck&&(r=await this.requestPermissionSmart("read"),!r.granted))throw r.error||this.errorHandler.createError(t.PERMISSION_ERROR,"Clipboard read permission denied",{context:{method:"readText",extra:{permission:r.state}}});const i=await navigator.clipboard.readText();if(this.options.enableDataValidation&&this.validateClipboardData(i,"text"),e.maxSize&&i.length>e.maxSize)throw this.errorHandler.createError(t.USER_ERROR,`Clipboard text exceeds maximum size limit (${e.maxSize} characters)`,{context:{method:"readText",extra:{size:i.length,maxSize:e.maxSize}}});let n=i;return e.format&&"text"!==e.format&&(n=await this.convertData(i,"text",e.format,{enableCaching:this.options.cache,enableChunking:!0,maxProcessingTime:this.options.timeout})),"html"===e.format&&!1!==e.sanitizeHtml&&this.options.enableHtmlSanitization&&(n=this.sanitizeHtml(n)),this.logger.debug(`Read ${i.length} characters from clipboard`),this.emit("read",{type:"text",data:n,size:n.length,timestamp:Date.now(),mimeType:"text/plain",encoding:"utf-8"}),n},"readText")}async readHTML(e={}){return await this.ensureInitialized(),this.ensureNotDestroyed(),this.safeExecute(async()=>{if(!this.canRead||!("read"in navigator.clipboard))throw this.errorHandler.createError(t.SYSTEM_ERROR,"Clipboard HTML reading not supported in this browser",{context:{method:"readHTML"}});if(this.options.enablePermissionCheck){const e=await this.checkReadPermission();if(e!==W.GRANTED)throw this.errorHandler.createError(t.PERMISSION_ERROR,"Clipboard read permission denied",{context:{method:"readHTML",extra:{permission:e}}})}const r=await navigator.clipboard.read();for(const i of r)if(i.types.includes("text/html")){const r=await i.getType("text/html"),n=await r.text();if(this.options.enableDataValidation&&this.validateClipboardData(n,"html"),e.maxSize&&n.length>e.maxSize)throw this.errorHandler.createError(t.USER_ERROR,`Clipboard HTML exceeds maximum size limit (${e.maxSize} characters)`,{context:{method:"readHTML",extra:{size:n.length,maxSize:e.maxSize}}});return this.logger.debug(`Read ${n.length} characters of HTML from clipboard`),this.emit("read",{type:"html",data:n,timestamp:Date.now()}),n}throw this.errorHandler.createError(t.USER_ERROR,"No HTML content found in clipboard",{context:{method:"readHTML"}})},"readHTML")}async copyFiles(e,r={}){return await this.ensureInitialized(),this.ensureNotDestroyed(),this.safeExecute(async()=>{if(!Array.isArray(e)||0===e.length)throw this.errorHandler.createError(t.USER_ERROR,"Invalid files input for clipboard copy",{context:{method:"copyFiles"}});this.options.enableDataValidation&&this.validateClipboardData(e,"files");let r=null;if(this.options.enablePermissionCheck&&(r=await this.requestPermissionSmart("write"),!r.granted&&!r.fallbackAvailable))throw r.error||this.errorHandler.createError(t.PERMISSION_ERROR,"Clipboard write permission denied and no fallback available",{context:{method:"copyFiles"}});try{if(this.canWrite&&"write"in navigator.clipboard&&"undefined"!=typeof ClipboardItem){const t=[];for(const r of e)this.options.supportedMimeTypes.includes(r.type)||this.options.supportedMimeTypes.some(e=>e.includes("*")&&r.type.startsWith(e.split("/")[0]))?t.push(new ClipboardItem({[r.type]:r})):this.logger.warn(`File type ${r.type} not supported, skipping file: ${r.name}`);if(t.length>0)return await navigator.clipboard.write(t),this.logger.debug(`${t.length} files copied using modern API`),this.emit("copy",{type:"files",data:e,size:e.reduce((e,t)=>e+t.size,0),timestamp:Date.now()}),!0}throw this.errorHandler.createError(t.SYSTEM_ERROR,"File clipboard copying not supported in this browser",{context:{method:"copyFiles"}})}catch(e){throw this.logger.error("File copy failed:",e),e}},"copyFiles")}async readFiles(e={}){return await this.ensureInitialized(),this.ensureNotDestroyed(),this.safeExecute(async()=>{if(!this.canRead||!("read"in navigator.clipboard))throw this.errorHandler.createError(t.SYSTEM_ERROR,"Clipboard file reading not supported in this browser",{context:{method:"readFiles"}});let r=null;if(this.options.enablePermissionCheck&&(r=await this.requestPermissionSmart("read"),!r.granted))throw r.error||this.errorHandler.createError(t.PERMISSION_ERROR,"Clipboard read permission denied",{context:{method:"readFiles",extra:{permission:r.state}}});const i=await navigator.clipboard.read(),n=[];for(const t of i)for(const r of t.types)if((!e.acceptedTypes||e.acceptedTypes.includes(r))&&this.isFileTypeAllowed(r))try{const e=await t.getType(r),i=new File([e],`clipboard-file.${this.getFileExtension(r)}`,{type:r});n.push(i)}catch(e){this.logger.warn(`Failed to read file of type ${r}:`,e)}return this.options.enableDataValidation&&n.length>0&&this.validateClipboardData(n,"files"),this.logger.debug(`Read ${n.length} files from clipboard`),n.length>0&&this.emit("read",{type:"files",data:n,size:n.reduce((e,t)=>e+t.size,0),timestamp:Date.now()}),n},"readFiles")}async read(e={}){return await this.ensureInitialized(),this.ensureNotDestroyed(),this.safeExecute(async()=>{const{format:t=this.options.defaultFormat,fallback:r=this.options.enableFallback}=e;try{switch(t){case"html":const t=await this.readHTML(e);return{type:"html",data:t,size:t.length,timestamp:Date.now(),mimeType:"text/html",encoding:"utf-8"};case"files":const r=await this.readFiles(e);return{type:"files",data:r,size:r.reduce((e,t)=>e+t.size,0),timestamp:Date.now()};default:const i=await this.readText(e);return{type:"text",data:i,size:i.length,timestamp:Date.now(),mimeType:"text/plain",encoding:"utf-8"}}}catch(e){if(r)return this.logger.warn("Attempting fallback read method"),await this.fallbackRead(t);throw e}},"read")}getFileExtension(e){return{"text/plain":"txt","text/html":"html","text/css":"css","text/javascript":"js","application/json":"json","image/png":"png","image/jpeg":"jpg","image/gif":"gif","image/webp":"webp","image/svg+xml":"svg","application/pdf":"pdf","application/msword":"doc","application/vnd.openxmlformats-officedocument.wordprocessingml.document":"docx"}[e]||"bin"}async checkBrowserSupport(){if("undefined"==typeof navigator)throw this.errorHandler.createError(t.SYSTEM_ERROR,"Navigator not available - running in non-browser environment",{context:{method:"checkBrowserSupport"}});const e={clipboard:"clipboard"in navigator,writeText:this.canWrite,readText:this.canRead,write:this.canWrite&&"write"in navigator.clipboard,read:this.canRead&&"read"in navigator.clipboard,execCommand:"undefined"!=typeof document&&"execCommand"in document};if(this.logger.debug("Browser clipboard support:",e),!e.clipboard&&!e.execCommand)throw this.errorHandler.createError(t.SYSTEM_ERROR,"No clipboard support available in this browser",{context:{method:"checkBrowserSupport",extra:{support:e}}})}async checkPermissions(){if("permissions"in navigator)try{const e=await this.checkWritePermission(),t=await this.checkReadPermission();this.logger.debug("Clipboard permissions:",{write:e,read:t})}catch(e){this.logger.warn("Failed to check clipboard permissions:",e)}else this.logger.warn("Permissions API not available")}async checkWritePermission(){if(!("permissions"in navigator))return W.UNKNOWN;try{return(await navigator.permissions.query({name:"clipboard-write"})).state}catch(e){return this.logger.warn("Failed to check clipboard write permission:",e),W.UNKNOWN}}async checkReadPermission(){if(!("permissions"in navigator))return W.UNKNOWN;try{return(await navigator.permissions.query({name:"clipboard-read"})).state}catch(e){return this.logger.warn("Failed to check clipboard read permission:",e),W.UNKNOWN}}async requestPermissionSmart(e){const r=`permission_${e}`,i=this.permissionCache.get(r);if(i===W.GRANTED)return{granted:!0,state:i,fallbackAvailable:this.options.enableFallback};const n={granted:!1,state:W.UNKNOWN,fallbackAvailable:this.options.enableFallback};try{const i="read"===e?await this.checkReadPermission():await this.checkWritePermission();if(this.permissionCache.set(r,i),i===W.GRANTED)return n.granted=!0,n.state=i,n;if(i===W.DENIED&&!this.options.autoRequestPermissions)return n.state=i,n.error=this.errorHandler.createError(t.PERMISSION_ERROR,`Clipboard ${e} permission denied and auto-request disabled`,{context:{method:"requestPermissionSmart",extra:{operation:e}},recoverable:this.options.enableFallback}),n;"write"===e?await this.triggerWritePermissionRequest():await this.triggerReadPermissionRequest();const s="read"===e?await this.checkReadPermission():await this.checkWritePermission();this.permissionCache.set(r,s),n.granted=s===W.GRANTED,n.state=s,n.granted||(n.error=this.errorHandler.createErr