secure-ui-components 0.3.3 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -13
- package/dist/components/secure-card/secure-card.d.ts +17 -3
- package/dist/components/secure-card/secure-card.d.ts.map +1 -1
- package/dist/components/secure-card/secure-card.js +1 -1
- package/dist/components/secure-card/secure-card.js.map +1 -1
- package/dist/components/secure-form/secure-form.d.ts +11 -1
- package/dist/components/secure-form/secure-form.d.ts.map +1 -1
- package/dist/components/secure-form/secure-form.js +1 -1
- package/dist/components/secure-form/secure-form.js.map +1 -1
- package/dist/components/secure-input/secure-input.d.ts.map +1 -1
- package/dist/components/secure-input/secure-input.js +1 -1
- package/dist/components/secure-input/secure-input.js.map +1 -1
- package/dist/components/secure-telemetry-provider/secure-telemetry-provider.d.ts +30 -5
- package/dist/components/secure-telemetry-provider/secure-telemetry-provider.d.ts.map +1 -1
- package/dist/components/secure-telemetry-provider/secure-telemetry-provider.js +1 -1
- package/dist/components/secure-telemetry-provider/secure-telemetry-provider.js.map +1 -1
- package/dist/core/base-component.d.ts +23 -0
- package/dist/core/base-component.d.ts.map +1 -1
- package/dist/core/base-component.js.map +1 -1
- package/dist/core/types.d.ts +15 -5
- package/dist/core/types.d.ts.map +1 -1
- package/dist/package.json +1 -1
- package/dist/secure-ui.bundle.js +15 -15
- package/package.json +1 -1
package/dist/secure-ui.bundle.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var u=Object.freeze({PUBLIC:"public",AUTHENTICATED:"authenticated",SENSITIVE:"sensitive",CRITICAL:"critical"}),w=Object.freeze({[u.PUBLIC]:Object.freeze({name:"Public",level:1,validation:Object.freeze({required:!1,strict:!1,maxLength:5e3,pattern:null,sanitizeHtml:!0}),masking:Object.freeze({enabled:!1,character:"\u2022",partial:!1}),storage:Object.freeze({allowAutocomplete:!0,allowCache:!0,allowHistory:!0}),audit:Object.freeze({logAccess:!1,logChanges:!1,logSubmission:!1,includeMetadata:!1}),rateLimit:Object.freeze({enabled:!1,maxAttempts:0,windowMs:0})}),[u.AUTHENTICATED]:Object.freeze({name:"Authenticated",level:2,validation:Object.freeze({required:!0,strict:!1,maxLength:1e3,pattern:null,sanitizeHtml:!0}),masking:Object.freeze({enabled:!1,character:"\u2022",partial:!1}),storage:Object.freeze({allowAutocomplete:!0,allowCache:!1,allowHistory:!1}),audit:Object.freeze({logAccess:!1,logChanges:!0,logSubmission:!0,includeMetadata:!0}),rateLimit:Object.freeze({enabled:!1,maxAttempts:0,windowMs:0})}),[u.SENSITIVE]:Object.freeze({name:"Sensitive",level:3,validation:Object.freeze({required:!0,strict:!0,maxLength:500,pattern:null,sanitizeHtml:!0}),masking:Object.freeze({enabled:!0,character:"\u2022",partial:!0}),storage:Object.freeze({allowAutocomplete:!1,allowCache:!1,allowHistory:!1}),audit:Object.freeze({logAccess:!0,logChanges:!0,logSubmission:!0,includeMetadata:!0}),rateLimit:Object.freeze({enabled:!0,maxAttempts:10,windowMs:6e4})}),[u.CRITICAL]:Object.freeze({name:"Critical",level:4,validation:Object.freeze({required:!0,strict:!0,maxLength:256,pattern:null,sanitizeHtml:!0}),masking:Object.freeze({enabled:!0,character:"\u2022",partial:!1}),storage:Object.freeze({allowAutocomplete:!1,allowCache:!1,allowHistory:!1}),audit:Object.freeze({logAccess:!0,logChanges:!0,logSubmission:!0,includeMetadata:!0}),rateLimit:Object.freeze({enabled:!0,maxAttempts:5,windowMs:6e4})})});function v(l){return!l||!w[l]?(console.warn(`Invalid security tier "${l}", defaulting to CRITICAL`),w[u.CRITICAL]):w[l]}function A(l){return Object.values(u).includes(l)}function B(l,e){let t=v(l),i=v(e);return Math.sign(t.level-i.level)}function G(l,e){return B(l,e)>=0?l:e}var Q=Object.freeze({[u.PUBLIC]:Object.freeze({"default-src":["'self'"],"script-src":["'self'"],"style-src":["'self'"]}),[u.AUTHENTICATED]:Object.freeze({"default-src":["'self'"],"script-src":["'self'"],"style-src":["'self'"],"form-action":["'self'"]}),[u.SENSITIVE]:Object.freeze({"default-src":["'self'"],"script-src":["'self'"],"style-src":["'self'"],"form-action":["'self'"],"frame-ancestors":["'none'"],"upgrade-insecure-requests":[]}),[u.CRITICAL]:Object.freeze({"default-src":["'self'"],"script-src":["'self'"],"style-src":["'self'"],"form-action":["'self'"],"frame-ancestors":["'none'"],"upgrade-insecure-requests":[],"block-all-mixed-content":[],"base-uri":["'none'"]})}),ee=Object.freeze({"X-Content-Type-Options":"nosniff","X-Frame-Options":"DENY","X-XSS-Protection":"1; mode=block","Referrer-Policy":"strict-origin-when-cross-origin","Permissions-Policy":"geolocation=(), microphone=(), camera=()"});var p=class l extends HTMLElement{static#e=1e3;static#t={"script-tag":"Script injection blocked","js-protocol":"JavaScript protocol blocked","event-handler":"Event handler injection blocked","html-injection":"HTML element injection blocked","css-expression":"CSS expression injection blocked",vbscript:"VBScript injection blocked","data-uri-html":"Data URI injection blocked","template-syntax":"Template injection blocked"};static#i=[{id:"script-tag",pattern:/<script[\s>/]/i},{id:"js-protocol",pattern:/javascript\s*:/i},{id:"event-handler",pattern:/\bon\w+\s*=/i},{id:"html-injection",pattern:/<\s*(img|svg|iframe|object|embed|link|meta|base)[^>]*/i},{id:"css-expression",pattern:/expression\s*\(/i},{id:"vbscript",pattern:/vbscript\s*:/i},{id:"data-uri-html",pattern:/data:\s*text\/html/i},{id:"template-syntax",pattern:/\{\{[\s\S]*?\}\}/}];#s=u.CRITICAL;#r;#n;#o=[];#a=null;#l={attempts:0,windowStart:Date.now()};#c=!1;#d={focusAt:null,firstKeystrokeAt:null,blurAt:null,keyCount:0,correctionCount:0,pasteDetected:!1,autofillDetected:!1,focusCount:0,blurWithoutChange:0,lastInputLength:0};constructor(){super(),this.#n=this.attachShadow({mode:"closed"}),this.#r=v(this.#s)}static get observedAttributes(){return["security-tier","disabled","readonly","threat-feedback"]}connectedCallback(){this.#c||(this.#p(),this.#c=!0)}#p(){this.initializeSecurity(),this.#u()}initializeSecurity(){let e=this.getAttribute("security-tier");e&&A(e)&&(this.#s=e),this.#r=v(this.#s),this.#h("component_initialized",{tier:this.#s,timestamp:new Date().toISOString()})}attributeChangedCallback(e,t,i){if(e==="security-tier"&&this.#c){console.warn(`Security tier cannot be changed after initialization. Attempted change from "${t}" to "${i}" blocked.`),t!==null&&this.setAttribute("security-tier",t);return}this.#c&&this.handleAttributeChange(e,t,i)}handleAttributeChange(e,t,i){}#u(){this.#n.innerHTML="",this.addComponentStyles(`:host { display: block; box-sizing: border-box; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 1.5; } :host([hidden]) { display: none; } * { box-sizing: border-box; } .hidden { display: none; } .external-error { margin-block-start: var(--secure-ui-space-1, 0.25rem); padding-block: var(--secure-ui-space-1, 0.25rem); padding-inline: var(--secure-ui-space-2, 0.5rem); font-size: var(--secure-ui-font-size-xs, 0.75rem); border-radius: var(--secure-ui-border-radius-sm, 0.25rem); border-inline-start: 3px solid currentColor; } .external-error:not([data-variant]), .external-error[data-variant="error"] { color: var(--secure-ui-color-error, #ef4444); background-color: color-mix(in oklch, var(--secure-ui-color-error, #ef4444) 10%, transparent); } .external-error[data-variant="warning"] { color: var(--secure-ui-color-warning, #f59e0b); background-color: color-mix(in oklch, var(--secure-ui-color-warning, #f59e0b) 10%, transparent); } @keyframes secure-autofill-detect { from {} to {} } @keyframes secure-autofill-cancel { from {} to {} } input:-webkit-autofill { animation-name: secure-autofill-detect; animation-duration: 1ms; } input:not(:-webkit-autofill) { animation-name: secure-autofill-cancel; animation-duration: 1ms; } .security-badge { display: inline-block; padding: var(--secure-ui-badge-padding, 2px 6px); margin-left: var(--secure-ui-space-2, 0.5rem); font-size: var(--secure-ui-badge-font-size, 0.6875rem); font-weight: var(--secure-ui-font-weight-semibold, 600); border-radius: var(--secure-ui-badge-border-radius, 0.25rem); text-transform: uppercase; background-color: var(--secure-ui-color-bg-tertiary); color: var(--secure-ui-color-text-secondary); border: var(--secure-ui-border-width-thin, 1px) solid var(--secure-ui-color-border); }`);let e=this.render();e&&this.#n.appendChild(e),this.#a=document.createElement("div"),this.#a.className="external-error hidden",this.#a.setAttribute("aria-live","polite"),this.#n.appendChild(this.#a)}getBaseStylesheetUrl(){return`:host { display: block; box-sizing: border-box; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 1.5; } :host([hidden]) { display: none; } * { box-sizing: border-box; } .hidden { display: none; } .external-error { margin-block-start: var(--secure-ui-space-1, 0.25rem); padding-block: var(--secure-ui-space-1, 0.25rem); padding-inline: var(--secure-ui-space-2, 0.5rem); font-size: var(--secure-ui-font-size-xs, 0.75rem); border-radius: var(--secure-ui-border-radius-sm, 0.25rem); border-inline-start: 3px solid currentColor; } .external-error:not([data-variant]), .external-error[data-variant="error"] { color: var(--secure-ui-color-error, #ef4444); background-color: color-mix(in oklch, var(--secure-ui-color-error, #ef4444) 10%, transparent); } .external-error[data-variant="warning"] { color: var(--secure-ui-color-warning, #f59e0b); background-color: color-mix(in oklch, var(--secure-ui-color-warning, #f59e0b) 10%, transparent); } @keyframes secure-autofill-detect { from {} to {} } @keyframes secure-autofill-cancel { from {} to {} } input:-webkit-autofill { animation-name: secure-autofill-detect; animation-duration: 1ms; } input:not(:-webkit-autofill) { animation-name: secure-autofill-cancel; animation-duration: 1ms; } .security-badge { display: inline-block; padding: var(--secure-ui-badge-padding, 2px 6px); margin-left: var(--secure-ui-space-2, 0.5rem); font-size: var(--secure-ui-badge-font-size, 0.6875rem); font-weight: var(--secure-ui-font-weight-semibold, 600); border-radius: var(--secure-ui-badge-border-radius, 0.25rem); text-transform: uppercase; background-color: var(--secure-ui-color-bg-tertiary); color: var(--secure-ui-color-text-secondary); border: var(--secure-ui-border-width-thin, 1px) solid var(--secure-ui-color-border); }`}addComponentStyles(e){if(e.includes("{")){let t=new CSSStyleSheet;t.replaceSync(e),this.#n.adoptedStyleSheets=[...this.#n.adoptedStyleSheets,t]}else{let t=document.createElement("link");t.rel="stylesheet",t.href=e,this.#n.appendChild(t)}}sanitizeValue(e){if(typeof e!="string")return"";let t=document.createElement("div");return t.textContent=e,t.innerHTML}validateInput(e,t={}){let i=[],r=this.#r;(t.required!==void 0?t.required:r.validation.required)&&(!e||e.trim().length===0)&&i.push("This field is required");let n=t.maxLength||r.validation.maxLength;e&&e.length>n&&i.push(`Value exceeds maximum length of ${n}`);let a=t.minLength||0;e&&e.length<a&&i.push(`Value must be at least ${a} characters`);let o=t.pattern||r.validation.pattern;return o&&e&&!o.test(e)&&i.push("Value does not match required format"),r.validation.strict&&i.length>0&&this.#h("validation_failed",{errors:i,valueLength:e?e.length:0}),{valid:i.length===0,errors:i}}checkRateLimit(){if(!this.#r.rateLimit.enabled)return{allowed:!0,retryAfter:0};let e=Date.now(),t=this.#r.rateLimit.windowMs;if(e-this.#l.windowStart>t&&(this.#l.attempts=0,this.#l.windowStart=e),this.#l.attempts>=this.#r.rateLimit.maxAttempts){let i=t-(e-this.#l.windowStart);return this.#h("rate_limit_exceeded",{attempts:this.#l.attempts,retryAfter:i}),{allowed:!1,retryAfter:i}}return this.#l.attempts++,{allowed:!0,retryAfter:0}}#h(e,t={}){let i=this.#r.audit;if(!(e.includes("access")&&i.logAccess||e.includes("change")&&i.logChanges||e.includes("submit")&&i.logSubmission||e.includes("initialized")||e.includes("rate_limit")||e.includes("validation")||e.includes("threat")))return;let s={event:e,tier:this.#s,timestamp:new Date().toISOString(),data:Object.keys(t).length>0?t:void 0};i.includeMetadata&&(s.userAgent=navigator.userAgent,s.language=navigator.language),this.#o.length>=l.#e&&this.#o.shift(),this.#o.push(s),this.dispatchEvent(new CustomEvent("secure-audit",{detail:s,bubbles:!0,composed:!0}))}get shadowRoot(){return this.#n}get securityTier(){return this.#s}get config(){return this.#r}getAuditLog(){return[...this.#o]}reportError(e,t="error"){this.#a&&(this.#a.textContent=e,this.#a.dataset.variant=t,t==="error"?this.#a.setAttribute("role","alert"):this.#a.removeAttribute("role"),this.#a.classList.remove("hidden"))}clearExternalError(){this.#a&&(this.#a.removeAttribute("role"),this.#a.classList.add("hidden"),this.#a.textContent="",delete this.#a.dataset.variant)}clearAuditLog(){this.#o=[]}audit(e,t){this.#h(e,t)}detectInjection(e,t,i=!1){let r=i||this.hasAttribute("threat-feedback");for(let{id:s,pattern:n}of l.#i)if(n.test(e)){this.audit("threat_detected",{fieldName:t,patternId:s,threatType:"injection"}),this.dispatchEvent(new CustomEvent("secure-threat-detected",{detail:{fieldName:t,threatType:"injection",patternId:s,tier:this.securityTier,timestamp:Date.now()},bubbles:!0,composed:!0})),r&&this.showThreatFeedback(s);return}r&&this.clearThreatFeedback()}showThreatFeedback(e){}clearThreatFeedback(){}getThreatLabel(e){return l.#t[e]??`Injection blocked: ${e}`}rerender(){this.#u()}recordTelemetryFocus(){let e=this.#d;e.focusAt=Date.now(),e.blurAt=null,e.focusCount++;let t=this.shadowRoot.querySelector('input:not([type="hidden"]), textarea, select');e.lastInputLength=t?t.value.length:0}recordTelemetryInput(e){let t=this.#d,i=Date.now();t.firstKeystrokeAt===null&&(t.firstKeystrokeAt=i);let s=e.inputType??"";if(s==="insertFromPaste"||s==="insertFromPasteAsQuotation")t.pasteDetected=!0;else if(s==="insertReplacementText")t.autofillDetected=!0;else if(s===""){let a=e.target;(a instanceof HTMLInputElement||a instanceof HTMLTextAreaElement)&&(t.autofillDetected=!0)}else s.startsWith("delete")||s==="historyUndo"||s==="historyRedo"?t.correctionCount++:t.keyCount++;let n=e.target;n&&(t.lastInputLength=n.value.length)}recordTelemetryBlur(){let e=this.#d;e.blurAt=Date.now();let t=this.shadowRoot.querySelector('input:not([type="hidden"]), textarea, select');(t?t.value.length:0)===e.lastInputLength&&e.keyCount===0&&!e.pasteDetected&&e.blurWithoutChange++}setupAutofillDetection(e){e.addEventListener("animationstart",t=>{t.animationName==="secure-autofill-detect"&&(this.#d.autofillDetected=!0)})}getFieldTelemetry(){let e=this.#d,t=e.focusAt??Date.now(),i=e.firstKeystrokeAt,r=e.blurAt??Date.now(),s=i!==null?i-t:0,n=i!==null?r-i:0,a=n/1e3,o=a>0?e.keyCount/a:0;return{dwell:s,completionTime:n,velocity:Math.round(o*100)/100,corrections:e.correctionCount,pasteDetected:e.pasteDetected,autofillDetected:e.autofillDetected,focusCount:e.focusCount,blurWithoutChange:e.blurWithoutChange}}#y(){this.#d={focusAt:null,firstKeystrokeAt:null,blurAt:null,keyCount:0,correctionCount:0,pasteDetected:!1,autofillDetected:!1,focusCount:0,blurWithoutChange:0,lastInputLength:0}}disconnectedCallback(){this.#l={attempts:0,windowStart:Date.now()},this.#y(),this.#r.audit.logAccess&&this.#h("component_disconnected",{timestamp:new Date().toISOString()})}};var I=class l extends p{static#e=new Set(["text","url","search"]);#t=null;#i=null;#s=null;#r=null;#n="";#o=!1;#a=null;#l=null;#c=`secure-input-${Math.random().toString(36).substring(2,11)}`;static get observedAttributes(){return[...super.observedAttributes,"name","type","label","placeholder","required","pattern","minlength","maxlength","autocomplete","value"]}render(){let e=document.createDocumentFragment(),t=document.createElement("div");t.className="input-container",t.setAttribute("part","container");let i=this.getAttribute("label");i&&(this.#i=document.createElement("label"),this.#i.htmlFor=this.#c,this.#i.textContent=this.sanitizeValue(i),this.#i.setAttribute("part","label"),t.appendChild(this.#i));let r=document.createElement("div");return r.className="input-wrapper",r.setAttribute("part","wrapper"),this.#t=document.createElement("input"),this.#t.id=this.#c,this.#t.className="input-field",this.#t.setAttribute("part","input"),this.#h(),this.#y(),r.appendChild(this.#t),t.appendChild(r),this.#s=document.createElement("div"),this.#s.className="error-container hidden",this.#s.setAttribute("role","alert"),this.#s.setAttribute("part","error"),this.#s.id=`${this.#c}-error`,t.appendChild(this.#s),this.#r=document.createElement("div"),this.#r.className="threat-container hidden",this.#r.setAttribute("role","alert"),this.#r.setAttribute("part","threat"),this.#r.id=`${this.#c}-threat`,t.appendChild(this.#r),this.#d(),this.#u(),this.addComponentStyles(this.#A()),e.appendChild(t),e}#d(){let e=this.getAttribute("name");e&&(this.closest("secure-form")||(this.#a=document.createElement("input"),this.#a.type="hidden",this.#a.name=e,this.#a.value=this.#n||"",this.appendChild(this.#a)))}#p(){this.#a&&(this.#a.value=this.#n||"")}#u(){this.querySelectorAll("input, textarea, select").forEach(t=>{if(t===this.#a)return;let i=t;i.removeAttribute("required"),i.removeAttribute("name"),i.removeAttribute("minlength"),i.removeAttribute("maxlength"),i.removeAttribute("pattern"),i.setAttribute("tabindex","-1"),i.setAttribute("aria-hidden","true")})}#h(){let e=this.config,t=this.getAttribute("name");t&&(this.#t.name=this.sanitizeValue(t)),!this.getAttribute("label")&&t&&this.#t.setAttribute("aria-label",this.sanitizeValue(t)),this.#t.setAttribute("aria-describedby",`${this.#c}-error`);let i=this.getAttribute("type")||"text";this.#t.type=i;let r=this.getAttribute("placeholder");r&&(this.#t.placeholder=this.sanitizeValue(r)),(this.hasAttribute("required")||e.validation.required)&&(this.#t.required=!0,this.#t.setAttribute("aria-required","true"));let s=this.getAttribute("pattern");s&&(this.#t.pattern=s);let n=this.getAttribute("minlength");n&&(this.#t.minLength=parseInt(n,10));let a=this.getAttribute("maxlength")||e.validation.maxLength;if(a&&(this.#t.maxLength=parseInt(String(a),10)),e.storage.allowAutocomplete){let c=this.getAttribute("autocomplete")||"on";this.#t.autocomplete=c}else this.#t.autocomplete="off",this.#t.type==="password"&&(this.#t.autocomplete="new-password");this.hasAttribute("disabled")&&(this.#t.disabled=!0),this.hasAttribute("readonly")&&(this.#t.readOnly=!0);let o=this.getAttribute("value");o&&this.#g(o);let d=new Set(["email","url","tel"]);e.masking.enabled&&this.#t.type!=="password"&&!d.has(this.#t.type)&&(this.#o=!0)}#y(){this.setupAutofillDetection(this.#t),this.#t.addEventListener("focus",()=>{this.recordTelemetryFocus(),this.audit("input_focused",{name:this.#t.name})}),this.#t.addEventListener("input",e=>{this.recordTelemetryInput(e),this.#E(e)}),this.#t.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#f(),this.audit("input_blurred",{name:this.#t.name,hasValue:this.#n.length>0})}),this.#t.addEventListener("paste",e=>{this.#o&&(this.#l=e.clipboardData?.getData("text/plain")??null)}),this.#t.addEventListener("change",()=>{this.audit("input_changed",{name:this.#t.name,valueLength:this.#n.length})})}#E(e){if(this.#o&&this.#t.type!=="password"){let i=e,r=i.inputType,s=i.data||"",n=this.#t.selectionStart||0;if(r==="deleteContentBackward")n<this.#n.length&&(this.#n=this.#n.substring(0,n)+this.#n.substring(n+1));else if(r==="deleteContentForward")this.#n=this.#n.substring(0,n)+this.#n.substring(n+1);else if(r==="insertText")this.#n=this.#n.substring(0,n-s.length)+s+this.#n.substring(n-s.length);else if(r==="insertFromPaste"){let o=this.#l??s;this.#l=null,o&&(this.#n=this.#n.substring(0,n-o.length)+o+this.#n.substring(n-o.length))}else this.#n="",this.#t.value="";let a=this.#w(this.#n);this.#t.value=a,this.#t.setSelectionRange(n,n)}else this.#n=this.#t.value;let t=this.#t.type;t!=="number"&&this.detectInjection(this.#n,this.#t.name,l.#e.has(t)),this.#b(),this.#p(),this.dispatchEvent(new CustomEvent("secure-input-change",{detail:{name:this.#t.name,value:this.#n,masked:this.#o,tier:this.securityTier},bubbles:!0,composed:!0}))}#w(e){let t=this.config,i=t.masking.character;if(!t.masking.partial||this.securityTier===u.CRITICAL||e.length<=4)return i.repeat(e.length);let r=i.repeat(e.length-4),s=e.slice(-4);return r+s}#x(e){if(!this.#t||this.#t.type!=="password"||!e||e.length===0)return null;let t=this.securityTier;if(t==="critical"){if(e.length<8)return"Password must be at least 8 characters";if(!/[a-z]/.test(e))return"Password must include a lowercase letter";if(!/[A-Z]/.test(e))return"Password must include an uppercase letter";if(!/[0-9]/.test(e))return"Password must include a number";if(!/[^a-zA-Z0-9]/.test(e))return"Password must include a special character"}else if(t==="sensitive"){if(e.length<8)return"Password must be at least 8 characters";if(!/[a-z]/.test(e))return"Password must include a lowercase letter";if(!/[A-Z]/.test(e))return"Password must include an uppercase letter";if(!/[0-9]/.test(e))return"Password must include a number"}else if(t==="authenticated"&&e.length<6)return"Password must be at least 6 characters";return null}#v(e){if(!this.#t||this.#t.type!=="number"||!e||e.length===0)return null;let t=Number(e);if(!Number.isFinite(t))return"Value must be a valid number";if(!e.includes(".")&&!Number.isSafeInteger(t))return"Value exceeds safe integer range";let i=this.getAttribute("min"),r=this.getAttribute("max");if(i!==null){let s=Number(i);if(Number.isFinite(s)&&t<s)return`Value must be at least ${s}`}if(r!==null){let s=Number(r);if(Number.isFinite(s)&&t>s)return`Value must be at most ${s}`}return null}#f(){let e=this.checkRateLimit();if(!e.allowed){this.#m(`Too many attempts. Please wait ${Math.ceil(e.retryAfter/1e3)} seconds.`);return}let t=this.getAttribute("pattern"),i=this.getAttribute("minlength"),r=this.getAttribute("maxlength"),s=null;if(t)try{s=new RegExp(t)}catch{}let n=this.validateInput(this.#n,{required:this.hasAttribute("required")||this.config.validation.required,pattern:s,minLength:i?parseInt(i,10):0,maxLength:r?parseInt(r,10):this.config.validation.maxLength});if(!n.valid){this.#m(n.errors.join(", "));return}let a=this.#x(this.#n);if(a){this.#m(a);return}let o=this.#v(this.#n);if(o){this.#m(o);return}if(this.#t&&this.#n){let d,c;if(this.#o){let m=this.#t.value;this.#t.value=this.#n,d=this.#t.checkValidity(),c=this.#t.validationMessage,this.#t.value=m}else d=this.#t.checkValidity(),c=this.#t.validationMessage;if(!d){this.#m(c);return}}}#m(e){this.#s.textContent=e,this.#s.offsetHeight,this.#s.classList.remove("hidden"),this.#t.classList.add("error"),this.#t.setAttribute("aria-invalid","true")}#b(){this.#s.classList.add("hidden"),this.#s.addEventListener("transitionend",()=>{this.#s.classList.contains("hidden")&&(this.#s.textContent="")},{once:!0}),this.#t.classList.remove("error"),this.#t.removeAttribute("aria-invalid")}#g(e){this.#n=e,this.#o&&this.#t.type!=="password"?this.#t.value=this.#w(e):this.#t.value=e,this.#p()}#A(){return".input-container { margin-bottom: var(--secure-ui-form-gap); font-family: var(--secure-ui-font-family-base); } label { display: flex; align-items: flex-end; margin-bottom: var(--secure-ui-form-label-margin-bottom); font-size: var(--secure-ui-label-font-size); font-weight: var(--secure-ui-label-font-weight); color: var(--secure-ui-label-color); } .label-suffix { font-weight: var(--secure-ui-font-weight-normal); color: var(--secure-ui-color-text-secondary); font-size: var(--secure-ui-font-size-xs); margin-left: var(--secure-ui-space-1); } .security-badge { display: inline-block; padding: var(--secure-ui-badge-padding); margin-left: var(--secure-ui-space-2); font-size: var(--secure-ui-badge-font-size); font-weight: var(--secure-ui-font-weight-semibold); border-radius: var(--secure-ui-badge-border-radius); text-transform: uppercase; background-color: var(--secure-ui-color-bg-tertiary); color: var(--secure-ui-color-text-secondary); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); } .input-wrapper { position: relative; } .input-field { width: 100%; height: var(--secure-ui-input-height); padding: var(--secure-ui-input-padding-y) var(--secure-ui-input-padding-x); font-family: var(--secure-ui-font-family-base); font-size: var(--secure-ui-input-font-size); line-height: var(--secure-ui-line-height-normal); color: var(--secure-ui-input-text-color); background-color: var(--secure-ui-input-bg); border: var(--secure-ui-input-border-width) solid var(--secure-ui-input-border-color); border-radius: var(--secure-ui-input-border-radius); transition: all var(--secure-ui-transition-base) var(--secure-ui-transition-ease-in-out); box-sizing: border-box; } .input-field::placeholder { color: var(--secure-ui-input-placeholder-color); } .input-field:hover:not(:disabled) { border-color: var(--secure-ui-input-border-color-hover); } .input-field:focus { outline: none; border-color: var(--secure-ui-input-border-color-focus); box-shadow: var(--secure-ui-shadow-focus); } .input-field.error { border-color: var(--secure-ui-color-error) !important; } .input-field.error:focus { box-shadow: var(--secure-ui-shadow-focus-error); } .input-field:disabled { background-color: var(--secure-ui-input-disabled-bg); cursor: not-allowed; opacity: var(--secure-ui-input-disabled-opacity); } .input-field:read-only:not(:disabled) { background-color: var(--secure-ui-color-bg-secondary); cursor: default; } .error-container { position: absolute; margin-top: var(--secure-ui-form-error-margin-top); font-size: var(--secure-ui-error-font-size); color: var(--secure-ui-error-color); line-height: var(--secure-ui-line-height-normal); overflow: hidden; max-height: 40px; opacity: 1; transform: translateY(0); transition: all 0.5s ease-in-out; } .error-container.hidden { max-height: 0; opacity: 0; transform: translateY(-4px); margin-top: 0; transition: all 0.2s ease-in-out; } @media (prefers-reduced-motion: reduce) { .input-field, .error-container, .threat-container { transition: none !important; } } .threat-container { margin-top: var(--secure-ui-form-error-margin-top); font-size: var(--secure-ui-error-font-size); color: var(--secure-ui-color-warning); line-height: var(--secure-ui-line-height-normal); overflow: hidden; max-height: 40px; opacity: 1; transform: translateY(0); transition: all 0.5s ease-in-out; display: flex; align-items: center; gap: var(--secure-ui-space-1, 4px); flex-wrap: wrap; } .threat-container.hidden { max-height: 0; opacity: 0; transform: translateY(-4px); margin-top: 0; transition: all 0.2s ease-in-out; } .threat-message { flex: 1; min-width: 0; } .threat-badge { display: inline-block; padding: var(--secure-ui-badge-padding); font-size: var(--secure-ui-badge-font-size); font-weight: var(--secure-ui-font-weight-semibold); border-radius: var(--secure-ui-badge-border-radius); background-color: color-mix(in srgb, var(--secure-ui-color-warning) 12%, transparent); color: var(--secure-ui-color-warning); border: var(--secure-ui-border-width-thin) solid currentColor; font-family: var(--secure-ui-font-family-mono, monospace); white-space: nowrap; } .input-field.threat { border-color: var(--secure-ui-color-warning) !important; } .input-field.threat:focus { box-shadow: 0 0 0 3px color-mix(in srgb, var(--secure-ui-color-warning) 25%, transparent); } .input-field:-webkit-autofill { -webkit-box-shadow: 0 0 0 1000px var(--secure-ui-input-bg) inset; -webkit-text-fill-color: var(--secure-ui-input-text-color); }"}handleAttributeChange(e,t,i){if(this.#t)switch(e){case"disabled":this.#t.disabled=this.hasAttribute("disabled");break;case"readonly":this.#t.readOnly=this.hasAttribute("readonly");break;case"value":i!==this.#n&&this.#g(i||"");break}}get value(){return this.#n}set value(e){this.#g(e||"")}get name(){return this.#t?this.#t.name:""}get valid(){let e=this.getAttribute("pattern"),t=this.getAttribute("minlength"),i=this.getAttribute("maxlength"),r=null;if(e)try{r=new RegExp(e)}catch{}if(!this.validateInput(this.#n,{required:this.hasAttribute("required")||this.config.validation.required,pattern:r,minLength:t?parseInt(t,10):0,maxLength:i?parseInt(i,10):this.config.validation.maxLength}).valid||this.#x(this.#n)!==null||this.#v(this.#n)!==null)return!1;if(this.#t&&this.#n){let n;if(this.#o){let a=this.#t.value;this.#t.value=this.#n,n=this.#t.checkValidity(),this.#t.value=a}else n=this.#t.checkValidity();if(!n)return!1}return!0}focus(){this.#t&&this.#t.focus()}blur(){this.#t&&this.#t.blur()}showThreatFeedback(e){if(!this.#r||!this.#t)return;this.#r.textContent="";let t=document.createElement("span");t.className="threat-message",t.textContent=this.getThreatLabel(e);let i=document.createElement("span");i.className="threat-badge",i.textContent=e,this.#r.appendChild(t),this.#r.appendChild(i),this.#r.offsetHeight,this.#r.classList.remove("hidden"),this.#t.classList.add("threat"),this.#t.setAttribute("aria-invalid","true")}clearThreatFeedback(){!this.#r||!this.#t||(this.#r.classList.add("hidden"),this.#r.addEventListener("transitionend",()=>{this.#r.classList.contains("hidden")&&(this.#r.textContent="")},{once:!0}),this.#t.classList.remove("threat"),this.#t.removeAttribute("aria-invalid"))}disconnectedCallback(){super.disconnectedCallback(),this.#n="",this.#l=null,this.#t&&(this.#t.value="")}};customElements.define("secure-input",I);var M=class extends p{#e=null;#t=null;#i=null;#s=null;#r=null;#n=`secure-textarea-${Math.random().toString(36).substring(2,11)}`;static get observedAttributes(){return[...super.observedAttributes,"name","label","placeholder","required","minlength","maxlength","rows","cols","wrap","value"]}render(){let e=document.createDocumentFragment(),t=document.createElement("div");t.className="textarea-container",t.setAttribute("part","container");let i=this.getAttribute("label");i&&(this.#t=document.createElement("label"),this.#t.htmlFor=this.#n,this.#t.textContent=this.sanitizeValue(i),this.#t.setAttribute("part","label"),t.appendChild(this.#t));let r=document.createElement("div");return r.className="textarea-wrapper",r.setAttribute("part","wrapper"),this.#e=document.createElement("textarea"),this.#e.id=this.#n,this.#e.className="textarea-field",this.#e.setAttribute("part","textarea"),this.#o(),this.#a(),r.appendChild(this.#e),t.appendChild(r),this.#r=document.createElement("span"),this.#r.className="char-count",this.#c(),t.appendChild(this.#r),this.#i=document.createElement("div"),this.#i.className="error-container hidden",this.#i.setAttribute("role","alert"),this.#i.setAttribute("part","error"),this.#i.id=`${this.#n}-error`,t.appendChild(this.#i),this.#s=document.createElement("div"),this.#s.className="threat-container hidden",this.#s.setAttribute("role","alert"),this.#s.setAttribute("part","threat"),this.#s.id=`${this.#n}-threat`,t.appendChild(this.#s),this.addComponentStyles(this.#h()),e.appendChild(t),e}#o(){let e=this.config,t=this.getAttribute("name");t&&(this.#e.name=this.sanitizeValue(t)),!this.getAttribute("label")&&t&&this.#e.setAttribute("aria-label",this.sanitizeValue(t)),this.#e.setAttribute("aria-describedby",`${this.#n}-error`);let i=this.getAttribute("placeholder");i&&(this.#e.placeholder=this.sanitizeValue(i)),(this.hasAttribute("required")||e.validation.required)&&(this.#e.required=!0,this.#e.setAttribute("aria-required","true"));let r=this.getAttribute("minlength");r&&(this.#e.minLength=parseInt(r,10));let s=this.getAttribute("maxlength")||e.validation.maxLength;s&&(this.#e.maxLength=parseInt(String(s),10));let n=this.getAttribute("rows")||3;this.#e.rows=parseInt(String(n),10);let a=this.getAttribute("cols");a&&(this.#e.cols=parseInt(a,10));let o=this.getAttribute("wrap")||"soft";if(this.#e.wrap=o,e.storage.allowAutocomplete){let c=this.getAttribute("autocomplete")||"on";this.#e.autocomplete=c}else this.#e.autocomplete="off";this.hasAttribute("disabled")&&(this.#e.disabled=!0),this.hasAttribute("readonly")&&(this.#e.readOnly=!0);let d=this.getAttribute("value");d&&(this.#e.value=d)}#a(){this.setupAutofillDetection(this.#e),this.#e.addEventListener("focus",()=>{this.recordTelemetryFocus(),this.audit("textarea_focused",{name:this.#e.name})}),this.#e.addEventListener("input",e=>{this.recordTelemetryInput(e),this.#l(e)}),this.#e.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#d(),this.audit("textarea_blurred",{name:this.#e.name,hasValue:this.#e.value.length>0})}),this.#e.addEventListener("change",()=>{this.audit("textarea_changed",{name:this.#e.name,valueLength:this.#e.value.length})})}#l(e){this.detectInjection(this.#e.value,this.#e.name),this.#c(),this.#u(),this.dispatchEvent(new CustomEvent("secure-textarea-change",{detail:{name:this.#e.name,value:this.#e.value,tier:this.securityTier},bubbles:!0,composed:!0}))}#c(){let e=this.#e.value.length,t=this.#e.maxLength;t>0?(this.#r.textContent=`${e} / ${t}`,e>t*.9?this.#r.classList.add("warning"):this.#r.classList.remove("warning")):this.#r.textContent=`${e}`}#d(){let e=this.checkRateLimit();if(!e.allowed){this.#p(`Too many attempts. Please wait ${Math.ceil(e.retryAfter/1e3)} seconds.`);return}let t=this.getAttribute("minlength"),i=this.getAttribute("maxlength"),r=this.validateInput(this.#e.value,{required:this.hasAttribute("required")||this.config.validation.required,minLength:t?parseInt(t,10):0,maxLength:i?parseInt(i,10):this.config.validation.maxLength});r.valid||this.#p(r.errors.join(", "))}#p(e){this.#i.textContent=e,this.#i.offsetHeight,this.#i.classList.remove("hidden"),this.#e.classList.add("error"),this.#e.setAttribute("aria-invalid","true")}#u(){this.#i.classList.add("hidden"),this.#i.addEventListener("transitionend",()=>{this.#i.classList.contains("hidden")&&(this.#i.textContent="")},{once:!0}),this.#e.classList.remove("error"),this.#e.removeAttribute("aria-invalid")}#h(){return'.textarea-container { margin-bottom: var(--secure-ui-form-gap); font-family: var(--secure-ui-font-family-base); } label { display: block; margin-bottom: var(--secure-ui-form-label-margin-bottom); font-size: var(--secure-ui-label-font-size); font-weight: var(--secure-ui-label-font-weight); color: var(--secure-ui-label-color); } .label-suffix { font-weight: var(--secure-ui-font-weight-normal); color: var(--secure-ui-color-text-secondary); font-size: var(--secure-ui-font-size-xs); margin-left: var(--secure-ui-space-1); } .security-badge { display: inline-block; padding: var(--secure-ui-badge-padding); margin-left: var(--secure-ui-space-2); font-size: var(--secure-ui-badge-font-size); font-weight: var(--secure-ui-font-weight-semibold); border-radius: var(--secure-ui-badge-border-radius); text-transform: uppercase; background-color: var(--secure-ui-color-bg-tertiary); color: var(--secure-ui-color-text-secondary); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); } .textarea-wrapper { position: relative; } .textarea-field { width: 100%; min-height: var(--secure-ui-textarea-min-height); padding: var(--secure-ui-textarea-padding); font-family: var(--secure-ui-font-family-base); font-size: var(--secure-ui-input-font-size); line-height: var(--secure-ui-line-height-normal); color: var(--secure-ui-input-text-color); background-color: var(--secure-ui-input-bg); border: var(--secure-ui-input-border-width) solid var(--secure-ui-input-border-color); border-radius: var(--secure-ui-input-border-radius); transition: all var(--secure-ui-transition-base) var(--secure-ui-transition-ease-in-out); resize: vertical; box-sizing: border-box; } .textarea-field::placeholder { color: var(--secure-ui-input-placeholder-color); } .textarea-field:hover:not(:disabled) { border-color: var(--secure-ui-input-border-color-hover); } .textarea-field:focus { outline: none; border-color: var(--secure-ui-input-border-color-focus); box-shadow: var(--secure-ui-shadow-focus); } .textarea-field.error { border-color: var(--secure-ui-color-error); } .textarea-field.error:focus { box-shadow: var(--secure-ui-shadow-focus-error); } .textarea-field:read-only:not(:disabled) { background-color: var(--secure-ui-color-bg-secondary); cursor: default; resize: none; } .textarea-field:disabled { background-color: var(--secure-ui-input-disabled-bg); cursor: not-allowed; opacity: var(--secure-ui-input-disabled-opacity); } .char-count { display: block; margin-top: var(--secure-ui-space-1); font-size: var(--secure-ui-font-size-xs); color: var(--secure-ui-color-text-secondary); text-align: right; } .char-count.warning { color: var(--secure-ui-color-warning); font-weight: var(--secure-ui-font-weight-medium); } .error-container { margin-top: var(--secure-ui-form-error-margin-top); font-size: var(--secure-ui-error-font-size); color: var(--secure-ui-error-color); line-height: var(--secure-ui-line-height-normal); overflow: hidden; max-height: 40px; opacity: 1; transform: translateY(0); transition: opacity 0.2s ease-out, transform 0.2s ease-out, max-height 0.2s ease-out, margin-top 0.2s ease-out; } .error-container.hidden { max-height: 0; opacity: 0; transform: translateY(-4px); margin-top: 0; } @media (prefers-reduced-motion: reduce) { .textarea-field, .error-container, .threat-container { transition: none !important; } } .threat-container { margin-top: var(--secure-ui-form-error-margin-top); font-size: var(--secure-ui-error-font-size); color: var(--secure-ui-color-warning); line-height: var(--secure-ui-line-height-normal); overflow: hidden; max-height: 40px; opacity: 1; transform: translateY(0); transition: opacity 0.2s ease-out, transform 0.2s ease-out, max-height 0.2s ease-out, margin-top 0.2s ease-out; display: flex; align-items: center; gap: var(--secure-ui-space-1, 4px); flex-wrap: wrap; } .threat-container.hidden { max-height: 0; opacity: 0; transform: translateY(-4px); margin-top: 0; } .threat-message { flex: 1; min-width: 0; } .threat-badge { display: inline-block; padding: var(--secure-ui-badge-padding); font-size: var(--secure-ui-badge-font-size); font-weight: var(--secure-ui-font-weight-semibold); border-radius: var(--secure-ui-badge-border-radius); background-color: color-mix(in srgb, var(--secure-ui-color-warning) 12%, transparent); color: var(--secure-ui-color-warning); border: var(--secure-ui-border-width-thin) solid currentColor; font-family: var(--secure-ui-font-family-mono, monospace); white-space: nowrap; } .textarea-field.threat { border-color: var(--secure-ui-color-warning) !important; } .textarea-field.threat:focus { box-shadow: 0 0 0 3px color-mix(in srgb, var(--secure-ui-color-warning) 25%, transparent); } :host([security-tier="authenticated"]) .textarea-field { border-color: var(--secure-ui-tier-authenticated); } :host([security-tier="sensitive"]) .textarea-field { border-color: var(--secure-ui-tier-sensitive); } :host([security-tier="critical"]) .textarea-field { border-color: var(--secure-ui-tier-critical); }'}handleAttributeChange(e,t,i){if(this.#e)switch(e){case"disabled":this.#e.disabled=this.hasAttribute("disabled");break;case"readonly":this.#e.readOnly=this.hasAttribute("readonly");break;case"value":i!==this.#e.value&&(this.#e.value=i||"",this.#c());break}}get value(){return this.#e?this.#e.value:""}set value(e){this.#e&&(this.#e.value=e||"",this.#c())}get name(){return this.#e?this.#e.name:""}get valid(){let e=this.getAttribute("minlength"),t=this.getAttribute("maxlength");return this.validateInput(this.#e.value,{required:this.hasAttribute("required")||this.config.validation.required,minLength:e?parseInt(e,10):0,maxLength:t?parseInt(t,10):this.config.validation.maxLength}).valid}focus(){this.#e&&this.#e.focus()}blur(){this.#e&&this.#e.blur()}showThreatFeedback(e){if(!this.#s||!this.#e)return;this.#s.textContent="";let t=document.createElement("span");t.className="threat-message",t.textContent=this.getThreatLabel(e);let i=document.createElement("span");i.className="threat-badge",i.textContent=e,this.#s.appendChild(t),this.#s.appendChild(i),this.#s.offsetHeight,this.#s.classList.remove("hidden"),this.#e.classList.add("threat"),this.#e.setAttribute("aria-invalid","true")}clearThreatFeedback(){!this.#s||!this.#e||(this.#s.classList.add("hidden"),this.#s.addEventListener("transitionend",()=>{this.#s.classList.contains("hidden")&&(this.#s.textContent="")},{once:!0}),this.#e.classList.remove("threat"),this.#e.removeAttribute("aria-invalid"))}disconnectedCallback(){super.disconnectedCallback(),this.#e&&(this.#e.value="")}};customElements.define("secure-textarea",M);var D=class extends p{#e=null;#t=null;#i=null;#s=`secure-select-${Math.random().toString(36).substring(2,11)}`;#r=new Set;#n=!1;#o=!1;static get observedAttributes(){return[...super.observedAttributes,"name","label","required","multiple","size","value"]}render(){let e=document.createDocumentFragment(),t=document.createElement("div");t.className="select-container",t.setAttribute("part","container"),this.#o=this.hasAttribute("multiple");let i=this.getAttribute("label");i&&(this.#t=document.createElement("label"),this.#t.htmlFor=this.#s,this.#t.textContent=this.sanitizeValue(i),this.#t.setAttribute("part","label"),t.appendChild(this.#t));let r=document.createElement("div");return r.className="select-wrapper",r.setAttribute("part","wrapper"),this.#e=document.createElement("select"),this.#e.id=this.#s,this.#e.className="select-field",this.#e.setAttribute("part","select"),this.#a(),this.#c(),queueMicrotask(()=>{this.#l()}),r.appendChild(this.#e),t.appendChild(r),this.#i=document.createElement("div"),this.#i.className="error-container hidden",this.#i.setAttribute("role","alert"),this.#i.setAttribute("part","error"),this.#i.id=`${this.#s}-error`,t.appendChild(this.#i),this.addComponentStyles(this.#y()),e.appendChild(t),e}#a(){let e=this.config,t=this.getAttribute("name");t&&(this.#e.name=this.sanitizeValue(t)),!this.getAttribute("label")&&t&&this.#e.setAttribute("aria-label",this.sanitizeValue(t)),this.#e.setAttribute("aria-describedby",`${this.#s}-error`),(this.hasAttribute("required")||e.validation.required)&&(this.#e.required=!0,this.#e.setAttribute("aria-required","true")),this.hasAttribute("multiple")&&(this.#e.multiple=!0);let i=this.getAttribute("size");i&&(this.#e.size=parseInt(i,10)),this.hasAttribute("disabled")&&(this.#e.disabled=!0),e.storage.allowAutocomplete||(this.#e.autocomplete="off")}#l(){if(this.#n)return;this.#n=!0;let e=Array.from(this.querySelectorAll("option"));if(e.length===0)return;let t=[];if(e.forEach(i=>{let r=document.createElement("option"),s=i.getAttribute("value")||"";r.value=this.sanitizeValue(s),this.#r.add(r.value),r.textContent=this.sanitizeValue(i.textContent||""),i.hasAttribute("selected")&&(r.selected=!0,t.push(r.value)),i.hasAttribute("disabled")&&(r.disabled=!0),this.#e.appendChild(r)}),!this.#o){let i=this.getAttribute("value");i?this.#e.value=i:t.length>0&&(this.#e.value=t[0])}}#c(){this.#e.addEventListener("focus",()=>{this.recordTelemetryFocus(),this.audit("select_focused",{name:this.#e.name})}),this.#e.addEventListener("change",e=>{this.recordTelemetryInput(e),this.#d(e)}),this.#e.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#p(),this.audit("select_blurred",{name:this.#e.name,hasValue:this.#o?this.#e.selectedOptions.length>0:this.#e.value.length>0})})}#d(e){if(this.#o){let t=Array.from(this.#e.selectedOptions).map(r=>r.value),i=t.filter(r=>r&&!this.#r.has(r));if(i.length>0){this.#u("Invalid option selected"),this.audit("invalid_option_detected",{name:this.#e.name,attemptedValues:i});return}this.#h(),this.audit("select_changed",{name:this.#e.name,values:t}),this.dispatchEvent(new CustomEvent("secure-select-change",{detail:{name:this.#e.name,value:t,tier:this.securityTier},bubbles:!0,composed:!0}))}else{let t=this.#e.value;if(t&&!this.#r.has(t)){this.#u("Invalid option selected"),this.audit("invalid_option_detected",{name:this.#e.name,attemptedValue:t}),this.#e.value="";return}this.#h(),this.audit("select_changed",{name:this.#e.name,value:t}),this.dispatchEvent(new CustomEvent("secure-select-change",{detail:{name:this.#e.name,value:t,tier:this.securityTier},bubbles:!0,composed:!0}))}}#p(){let e=this.checkRateLimit();if(!e.allowed){this.#u(`Too many attempts. Please wait ${Math.ceil(e.retryAfter/1e3)} seconds.`);return}let t=this.hasAttribute("required")||this.config.validation.required;if(this.#o){let i=Array.from(this.#e.selectedOptions).map(s=>s.value).filter(s=>s!=="");if(t&&i.length===0){this.#u("Please select at least one option");return}if(i.filter(s=>!this.#r.has(s)).length>0){this.#u("Invalid option selected");return}}else{if(t&&!this.#e.value){this.#u("Please select an option");return}let i=this.#e.value;if(i&&!this.#r.has(i)){this.#u("Invalid option selected");return}}}#u(e){this.#i.textContent=e,this.#i.offsetHeight,this.#i.classList.remove("hidden"),this.#e.classList.add("error"),this.#e.setAttribute("aria-invalid","true")}#h(){this.#i.classList.add("hidden"),this.#i.addEventListener("transitionend",()=>{this.#i.classList.contains("hidden")&&(this.#i.textContent="")},{once:!0}),this.#e.classList.remove("error"),this.#e.removeAttribute("aria-invalid")}#y(){return'.select-container { margin-bottom: var(--secure-ui-form-gap); font-family: var(--secure-ui-font-family-base); } label { display: block; margin-bottom: var(--secure-ui-form-label-margin-bottom); font-size: var(--secure-ui-label-font-size); font-weight: var(--secure-ui-label-font-weight); color: var(--secure-ui-label-color); } .label-suffix { font-weight: var(--secure-ui-font-weight-normal); color: var(--secure-ui-color-text-secondary); font-size: var(--secure-ui-font-size-xs); margin-left: var(--secure-ui-space-1); } .security-badge { display: inline-block; padding: var(--secure-ui-badge-padding); margin-left: var(--secure-ui-space-2); font-size: var(--secure-ui-badge-font-size); font-weight: var(--secure-ui-font-weight-semibold); border-radius: var(--secure-ui-badge-border-radius); text-transform: uppercase; background-color: var(--secure-ui-color-bg-tertiary); color: var(--secure-ui-color-text-secondary); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); } .select-wrapper { position: relative; } .select-field { width: 100%; height: var(--secure-ui-select-height); padding: var(--secure-ui-select-padding); font-family: var(--secure-ui-font-family-base); font-size: var(--secure-ui-input-font-size); line-height: var(--secure-ui-line-height-normal); color: var(--secure-ui-select-color); background-color: var(--secure-ui-select-background-color); border: var(--secure-ui-input-border-width) solid var(--secure-ui-input-border-color); border-radius: var(--secure-ui-input-border-radius); transition: all var(--secure-ui-transition-base) var(--secure-ui-transition-ease-in-out); cursor: pointer; box-sizing: border-box; } .select-field, ::picker(select) { appearance: base-select; border-radius: .25rem; } .select-field::picker-icon { color: #999999; transition: 0.2s rotate; } .select-field:open::picker-icon { rotate: 180deg; } .select-field option { display: flex; justify-content: flex-start; color: var(--secure-ui-select-color); background-color: var(--secure-ui-select-background-color); padding: .5rem; } .select-field option:hover { box-shadow: 0px 0px 4px 0px var(--secure-ui-input-border-color) inset; transition: all 0.2s ease-in-out; } .select-field option:first-of-type { border-top-left-radius: none; border-top-right-radius: none; } .select-field option:last-of-type { border-bottom-left-radius: none; border-bottom-right-radius: none; } .select-field option:nth-of-type(odd) { } .select-field option:checked { font-weight: bold; } .select-field option::checkmark { order: 1; margin-left: auto; content: "\u2713"; } .select-field option + option { border-top: 1px solid var(--secure-ui-input-border-color); } .select-field:hover:not(:disabled) { border-color: var(--secure-ui-input-border-color-hover); } .select-field:focus { outline: none; border-color: var(--secure-ui-input-border-color-focus); box-shadow: var(--secure-ui-shadow-focus); } .select-field.error { border-color: var(--secure-ui-color-error); } .select-field.error:focus { box-shadow: var(--secure-ui-shadow-focus-error); } .select-field:disabled { background-color: var(--secure-ui-input-disabled-bg); cursor: not-allowed; opacity: var(--secure-ui-input-disabled-opacity); } .select-field[multiple] { height: auto; min-height: calc(var(--secure-ui-select-height) * 2); padding: var(--secure-ui-space-2); } .error-container { position: absolute; margin-top: var(--secure-ui-form-error-margin-top); font-size: var(--secure-ui-error-font-size); color: var(--secure-ui-error-color); line-height: var(--secure-ui-line-height-normal); overflow: hidden; max-height: 40px; opacity: 1; transform: translateY(0); transition: opacity 0.2s ease-out, transform 0.2s ease-out, max-height 0.2s ease-out, margin-top 0.2s ease-out; } .error-container.hidden { max-height: 0; opacity: 0; transform: translateY(-4px); margin-top: 0; } @media (prefers-reduced-motion: reduce) { .select-field, .error-container { transition: none !important; } }'}handleAttributeChange(e,t,i){if(this.#e)switch(e){case"disabled":this.#e.disabled=this.hasAttribute("disabled");break;case"value":i!==this.#e.value&&(this.#e.value=i||"");break}}get value(){return this.#e?this.#o?Array.from(this.#e.selectedOptions).map(e=>e.value).filter(e=>e!==""):this.#e.value:this.#o?[]:""}set value(e){if(this.#e)if(this.#o){let t=Array.isArray(e)?e:e.split(",").map(i=>i.trim()).filter(i=>i!=="");Array.from(this.#e.options).forEach(i=>{i.selected=!1}),t.forEach(i=>{if(this.#r.has(i)){let r=Array.from(this.#e.options).find(s=>s.value===i);r&&(r.selected=!0)}})}else{let t=Array.isArray(e)?e[0]??"":e;this.#r.has(t)&&(this.#e.value=t)}}get name(){return this.#e?this.#e.name:""}get selectedOptions(){return this.#e?Array.from(this.#e.selectedOptions).map(e=>e.value):[]}get valid(){let e=this.hasAttribute("required")||this.config.validation.required;if(this.#o){let i=Array.from(this.#e.selectedOptions).map(r=>r.value).filter(r=>r!=="");return e&&i.length===0?!1:i.every(r=>this.#r.has(r))}if(e&&!this.#e.value)return!1;let t=this.#e.value;return!(t&&!this.#r.has(t))}focus(){this.#e&&this.#e.focus()}blur(){this.#e&&this.#e.blur()}addOption(e,t,i=!1){if(!this.#e)return;let r=document.createElement("option");r.value=this.sanitizeValue(e),r.textContent=this.sanitizeValue(t),r.selected=i,this.#r.add(r.value),this.#e.appendChild(r)}removeOption(e){if(!this.#e)return;let i=Array.from(this.#e.options).find(r=>r.value===e);i&&(this.#e.removeChild(i),this.#r.delete(e))}clearOptions(){this.#e&&(this.#e.innerHTML="",this.#r.clear())}disconnectedCallback(){super.disconnectedCallback()}};customElements.define("secure-select",D);var H=class l extends HTMLElement{static#e=!1;#t=null;#i=null;#s=null;#r=!1;#n=Date.now();#o={attempts:0,windowStart:Date.now()};#a=`secure-form-${Math.random().toString(36).substring(2,11)}`;#l=u.PUBLIC;static get observedAttributes(){return["security-tier","action","method","enctype","csrf-token","csrf-header-name","csrf-field-name","novalidate"]}constructor(){super()}connectedCallback(){if(this.#t)return;this.#n=Date.now();let e=this.getAttribute("security-tier");e&&A(e)&&(this.#l=e);let t=this.querySelector("form");if(t){this.#t=t,this.#t.id=this.#a,this.#t.classList.contains("secure-form")||this.#t.classList.add("secure-form"),this.#d();let i=this.getAttribute("csrf-field-name")||"csrf_token",r=t.querySelector(`input[name="${CSS.escape(i)}"]`);if(r){this.#i=r;let s=this.getAttribute("csrf-token");s&&r.value!==s&&(r.value=s)}else this.#p()}else{for(this.#t=document.createElement("form"),this.#t.id=this.#a,this.#t.className="secure-form",this.#d(),this.#p();this.firstChild;)this.#t.appendChild(this.firstChild);this.appendChild(this.#t)}this.#s=document.createElement("div"),this.#s.className="form-status form-status-hidden",this.#s.setAttribute("role","status"),this.#s.setAttribute("aria-live","polite"),this.#t.insertBefore(this.#s,this.#t.firstChild),this.#c(),this.#u(),this.audit("form_initialized",{formId:this.#a,action:this.#t.action,method:this.#t.method})}#c(){if(!l.#e){let e='secure-form { display: block; } secure-form .secure-form { padding: 16px; border: 2px solid #e0e0e0; border-radius: 8px; background-color: transparent; } secure-form[security-tier="critical"] .secure-form { padding: 20px; } secure-form[security-tier="public"] .secure-form { border: none; } secure-form .form-status { padding: 12px; margin-bottom: 16px; border-radius: 4px; font-size: 14px; } secure-form .form-status-hidden { display: none; } secure-form .form-status-info { display: block; background-color: #E3F2FD; color: #1976D2; border: 1px solid #1976D2; } secure-form .form-status-success { display: block; background-color: #E8F5E9; color: #388E3C; border: 1px solid #388E3C; } secure-form .form-status-error { display: block; background-color: #FFEBEE; color: #D32F2F; border: 1px solid #D32F2F; } secure-form .secure-form { transition: outline-color 200ms ease, outline-offset 200ms ease; outline: 3px solid transparent; outline-offset: 2px; } secure-form[data-state="success"] .secure-form { outline-color: var(--secure-ui-color-success, #10b981); } secure-form[data-state="blocked"] .secure-form, secure-form[data-state="error"] .secure-form { outline-color: var(--secure-ui-color-error, #ef4444); } @media (prefers-reduced-motion: reduce) { secure-form .secure-form { transition: none; } }';if(e.includes("{")){let t=new CSSStyleSheet;t.replaceSync(e),document.adoptedStyleSheets=[...document.adoptedStyleSheets,t]}else{let t=document.createElement("link");t.rel="stylesheet",t.href=e,document.head.appendChild(t)}l.#e=!0}}#d(){let e=this.getAttribute("action");e&&(this.#t.action=e);let t=this.getAttribute("method")||"POST";this.#t.method=t.toUpperCase();let i=this.getAttribute("enctype")||"application/x-www-form-urlencoded";this.#t.enctype=i,this.hasAttribute("novalidate")&&(this.#t.noValidate=!0),(this.#l===u.SENSITIVE||this.#l===u.CRITICAL)&&(this.#t.autocomplete="off")}#p(){let e=this.getAttribute("csrf-token");if(e){this.#i=document.createElement("input"),this.#i.type="hidden";let t=this.getAttribute("csrf-field-name")||"csrf_token";this.#i.name=t,this.#i.value=e,this.#t.appendChild(this.#i),this.audit("csrf_token_injected",{formId:this.#a,fieldName:t})}else(this.securityTier===u.SENSITIVE||this.securityTier===u.CRITICAL)&&console.warn("CSRF token not provided for SENSITIVE/CRITICAL tier form")}#u(){this.#t.addEventListener("submit",e=>{this.#y(e)}),this.addEventListener("secure-input-change",e=>{this.#h(e)}),this.addEventListener("secure-textarea-change",e=>{this.#h(e)}),this.addEventListener("secure-select-change",e=>{this.#h(e)}),this.addEventListener("secure-threat-detected",e=>{let t=e.detail;t&&(this.#v.push(t),t.threatType==="injection"&&(this.#L("blocked"),this.#I(t.fieldName,"Injection attempt blocked \u2014 clear this field to submit","error")))})}#h(e){this.#S()}async#y(e){let t=this.hasAttribute("use-fetch");if(this.#r){e.preventDefault();return}(this.#l===u.SENSITIVE||this.#l===u.CRITICAL)&&!this.#i?.value&&this.dispatchEvent(new CustomEvent("secure-threat-detected",{detail:{fieldName:this.#a,threatType:"csrf-token-absent",patternId:"csrf-token-absent",tier:this.#l,timestamp:Date.now()},bubbles:!0,composed:!0}));let i=this.checkRateLimit();if(!i.allowed){e.preventDefault(),this.#C(`Too many submission attempts. Please wait ${Math.ceil(i.retryAfter/1e3)} seconds.`,"error"),this.audit("form_rate_limited",{formId:this.#a,retryAfter:i.retryAfter});return}let r=this.#w();if(!r.valid){e.preventDefault(),this.#C(r.errors.join(", "),"error"),this.audit("form_validation_failed",{formId:this.#a,errors:r.errors});return}if(this.#v.some(c=>c.threatType==="injection")){e.preventDefault(),this.#L("blocked"),this.#C("Submission blocked: injection attempt detected. Clear the highlighted field(s) and try again.","error"),this.audit("form_blocked_injection",{formId:this.#a,count:this.#v.filter(c=>c.threatType==="injection").length});return}if(!t){this.#E(),this.audit("form_submitted_native",{formId:this.#a,action:this.#t.action,method:this.#t.method});return}e.preventDefault(),this.#r=!0,this.#C("Submitting...","info"),this.#g();let n=this.#x(),a=this.#z();this.#H(a.fields),this.audit("form_submitted_enhanced",{formId:this.#a,action:this.#t.action,method:this.#t.method,fieldCount:Object.keys(n).length,riskScore:a.riskScore,riskSignals:a.riskSignals});let o=new CustomEvent("secure-form-submit",{detail:{formData:n,telemetry:a,cancelSubmission:()=>{this.#r=!1,this.#A()}},bubbles:!0,composed:!0,cancelable:!0});if(!this.dispatchEvent(o)){this.#r=!1,this.#A();return}try{await this.#b(n,a),this.#L("success"),this.#f!==null&&clearTimeout(this.#f),this.#f=setTimeout(()=>{this.#L(null),this.#f=null},3e3),this.#D()}catch(c){this.#L("error"),this.#C("Submission failed. Please try again.","error"),this.audit("form_submission_error",{formId:this.#a,error:c.message})}finally{this.#r=!1,this.#A()}}#E(){this.#t.querySelectorAll("secure-input, secure-textarea, secure-select, secure-datetime, secure-file-upload").forEach(t=>{let i=t.getAttribute("name");if(!i)return;t.querySelectorAll(`input[name="${i}"], textarea[name="${i}"], select[name="${i}"]`).forEach(n=>{n.removeAttribute("name")});let s=this.#t.querySelector(`input[type="hidden"][data-secure-input="${i}"]`);s||(s=document.createElement("input"),s.type="hidden",s.setAttribute("data-secure-input",i),s.name=i,this.#t.appendChild(s)),s.value=t.value||""})}#w(){let e=[];return this.#t.querySelectorAll("secure-input, secure-textarea, secure-select, secure-datetime, secure-file-upload").forEach(i=>{if(typeof i.valid=="boolean"&&!i.valid){let r=i.getAttribute("label")||i.getAttribute("name")||"Field";e.push(`${r} is invalid`)}}),{valid:e.length===0,errors:e}}#x(){let e=Object.create(null);return this.#t.querySelectorAll("secure-input, secure-textarea, secure-select, secure-datetime, secure-file-upload").forEach(r=>{let s=r;s.name&&(e[s.name]=s.value)}),this.#t.querySelectorAll('input:not([type="hidden"]), textarea, select').forEach(r=>{let s=r;s.name&&(e[s.name]=this.sanitizeValue(s.value))}),this.#i&&(e[this.#i.name]=this.#i.value),e}#v=[];#f=null;#m=null;async#b(e,t){this.#m?.abort(),this.#m=new AbortController;let i=this.#t.action,r=this.#t.method,s={"Content-Type":"application/json"},n=this.getAttribute("csrf-header-name");n&&this.#i&&(s[n]=this.#i.value);let a={...e,_telemetry:t},o=await fetch(i,{method:r,headers:s,body:JSON.stringify(a),credentials:"same-origin",mode:"cors",cache:"no-cache",redirect:"follow",signal:this.#m.signal});if(!o.ok)throw new Error(`HTTP ${o.status}: ${o.statusText}`);return this.#C("Form submitted successfully!","success"),this.dispatchEvent(new CustomEvent("secure-form-success",{detail:{formData:e,response:o,telemetry:t},bubbles:!0,composed:!0})),o}#g(){this.#t.querySelectorAll("input, textarea, select, button").forEach(i=>{i.disabled=!0}),this.querySelectorAll("secure-input, secure-textarea, secure-select, secure-datetime, secure-file-upload").forEach(i=>{i.setAttribute("disabled","")})}#A(){this.#t.querySelectorAll("input, textarea, select, button").forEach(i=>{i.disabled=!1}),this.querySelectorAll("secure-input, secure-textarea, secure-select, secure-datetime, secure-file-upload").forEach(i=>{i.removeAttribute("disabled")})}#C(e,t="info"){this.#s.textContent=e,this.#s.className=`form-status form-status-${t}`}#S(){this.#s.textContent="",this.#s.className="form-status form-status-hidden"}#z(){let t=this.querySelectorAll("secure-input, secure-textarea, secure-select, secure-datetime, secure-card"),i=[];t.forEach(a=>{let o=a;if(typeof o.getFieldTelemetry!="function")return;let d=a.getAttribute("name")??a.tagName.toLowerCase(),c={...o.getFieldTelemetry(),fieldName:d,fieldType:a.tagName.toLowerCase()};i.push(c)});let r=Date.now()-this.#n,{riskScore:s,riskSignals:n}=this.#M(i,r,this.#v);return{sessionDuration:r,fieldCount:i.length,fields:i,riskScore:s,riskSignals:n,submittedAt:new Date().toISOString(),detectedThreats:this.#v.length>0?[...this.#v]:void 0}}#M(e,t,i=[]){let r=[],s=0,n=i.filter(h=>h.threatType==="injection"),a=i.some(h=>h.threatType==="csrf-token-absent");if(n.length>0&&(s+=40,r.push("injection_detected")),a&&(s+=20,r.push("csrf_token_absent")),t<3e3?(s+=30,r.push("session_too_fast")):t<8e3&&(s+=10,r.push("session_fast")),e.length===0)return{riskScore:Math.min(s,100),riskSignals:r};e.every(h=>h.pasteDetected&&h.velocity===0)&&(s+=25,r.push("all_fields_pasted")),e.some(h=>h.velocity>15)&&(s+=15,r.push("high_velocity_typing")),e.some(h=>h.focusCount===0)&&(s+=15,r.push("field_filled_without_focus")),e.some(h=>h.focusCount>1&&h.blurWithoutChange>1)&&(s+=10,r.push("form_probing")),e.some(h=>h.corrections>5)&&(s+=5,r.push("high_correction_count"));let f=e.filter(h=>h.autofillDetected);return f.length>0&&f.length===e.length&&(s-=10,r.push("autofill_detected")),{riskScore:Math.max(0,Math.min(s,100)),riskSignals:r}}#L(e){e===null?delete this.dataset.state:this.dataset.state=e}#D(){this.querySelectorAll("secure-input, secure-textarea, secure-select, secure-datetime, secure-card, secure-file-upload").forEach(t=>{t.clearExternalError?.()})}#I(e,t,i="error"){if(!e)return;this.querySelector(`[name="${CSS.escape(e)}"]`)?.reportError?.(t,i)}#H(e){for(let t of e){let i=null;t.focusCount===0?i="Field was filled without interaction":t.velocity>15?i="Unusually fast input detected":t.pasteDetected&&t.velocity===0?i="Paste-only entry detected":t.focusCount>1&&t.blurWithoutChange>1?i="Repeated focus without entry":t.corrections>5&&(i="Excessive corrections detected"),i!==null&&this.#I(t.fieldName,i,"warning")}}getData(){return this.#x()}reset(){this.#t&&(this.#t.reset(),this.#S(),this.#v=[],this.#f!==null&&(clearTimeout(this.#f),this.#f=null),this.#L(null),this.#D(),this.audit("form_reset",{formId:this.#a}))}submit(){this.#t&&this.#t.dispatchEvent(new Event("submit",{bubbles:!0,cancelable:!0}))}get valid(){return this.#w().valid}disconnectedCallback(){this.#m?.abort(),this.#f!==null&&(clearTimeout(this.#f),this.#f=null),this.#t&&this.#t.reset()}attributeChangedCallback(e,t,i){if(this.#t)switch(e){case"security-tier":console.warn(`SecureForm: security-tier cannot be changed after initialization. Attempted change from "${t}" to "${i}" blocked.`);return;case"action":this.#t.action=i;break;case"method":this.#t.method=i;break;case"csrf-token":this.#i&&(this.#i.value=i);break}}get securityTier(){return this.#l}sanitizeValue(e){if(typeof e!="string")return"";let t=document.createElement("div");return t.textContent=e,t.innerHTML}audit(e,t){console.debug&&console.debug(`[secure-form] ${e}`,t)}checkRateLimit(){let e=w[this.#l];if(!e.rateLimit.enabled)return{allowed:!0,retryAfter:0};let{maxAttempts:t,windowMs:i}=e.rateLimit,r=Date.now();return r-this.#o.windowStart>i&&(this.#o.attempts=0,this.#o.windowStart=r),this.#o.attempts>=t?{allowed:!1,retryAfter:i-(r-this.#o.windowStart)}:(this.#o.attempts++,{allowed:!0,retryAfter:0})}};customElements.define("secure-form",H);var N=class extends p{#e=null;#t=null;#i=null;#s=null;#r=null;#n=null;#o=null;#a=`secure-file-upload-${Math.random().toString(36).substring(2,11)}`;#l=new Set;#c=5*1024*1024;#d=null;#p=!1;static get observedAttributes(){return[...super.observedAttributes,"name","label","accept","max-size","multiple","required","capture"]}constructor(){super()}render(){let e=document.createDocumentFragment(),t=document.createElement("div");t.className="file-upload-container",t.setAttribute("part","container");let i=this.getAttribute("label");i&&(this.#t=document.createElement("label"),this.#t.htmlFor=this.#a,this.#t.textContent=this.sanitizeValue(i),this.#t.setAttribute("part","label"),t.appendChild(this.#t)),this.#r=document.createElement("div"),this.#r.className="drop-zone",this.#r.setAttribute("part","wrapper"),this.#e=document.createElement("input"),this.#e.type="file",this.#e.id=this.#a,this.#e.className="file-input",this.#e.setAttribute("part","input"),this.#u(),this.#v();let r=document.createElement("div");r.className="drop-zone-content has-name";let s=document.createElement("span");s.className="file-cta";let n=document.createElement("span");n.className="drop-icon";let a=document.createElementNS("http://www.w3.org/2000/svg","svg");a.setAttribute("width","16"),a.setAttribute("height","16"),a.setAttribute("viewBox","0 0 24 24"),a.setAttribute("fill","none"),a.setAttribute("stroke","currentColor"),a.setAttribute("stroke-width","2"),a.setAttribute("stroke-linecap","round"),a.setAttribute("stroke-linejoin","round"),a.setAttribute("aria-hidden","true"),a.setAttribute("focusable","false");let o=document.createElementNS("http://www.w3.org/2000/svg","path");o.setAttribute("d","M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4");let d=document.createElementNS("http://www.w3.org/2000/svg","polyline");d.setAttribute("points","17 8 12 3 7 8");let c=document.createElementNS("http://www.w3.org/2000/svg","line");c.setAttribute("x1","12"),c.setAttribute("y1","3"),c.setAttribute("x2","12"),c.setAttribute("y2","15"),a.appendChild(o),a.appendChild(d),a.appendChild(c),n.appendChild(a),s.appendChild(n);let m=document.createElement("span");m.className="drop-text",m.textContent="Choose a file\u2026",s.appendChild(m),r.appendChild(s),this.#n=document.createElement("span"),this.#n.className="file-name-display",this.#n.textContent="No file selected",r.appendChild(this.#n),this.#r.appendChild(this.#e),this.#r.appendChild(r),t.appendChild(this.#r);let g=document.createElement("div");return g.className="drop-hint",g.textContent=this.#x(),t.appendChild(g),this.#s=document.createElement("div"),this.#s.className="preview-container",t.appendChild(this.#s),this.#i=document.createElement("div"),this.#i.className="error-container hidden",this.#i.setAttribute("role","alert"),this.#i.setAttribute("part","error"),this.#i.id=`${this.#a}-error`,t.appendChild(this.#i),this.#e.setAttribute("aria-describedby",`${this.#a}-error`),this.addComponentStyles(this.#P()),e.appendChild(t),e}#u(){let e=this.config,t=this.getAttribute("name");t&&(this.#e.name=this.sanitizeValue(t));let i=this.getAttribute("accept");if(i)this.#e.accept=i,this.#h(i);else{let n=this.#E();this.#e.accept=n,this.#h(n)}let r=this.getAttribute("max-size");r?this.#c=parseInt(r,10):this.#c=this.#w(),this.hasAttribute("multiple")&&(this.#e.multiple=!0),(this.hasAttribute("required")||e.validation.required)&&(this.#e.required=!0);let s=this.getAttribute("capture");s&&(this.#e.capture=s),this.hasAttribute("disabled")&&(this.#e.disabled=!0)}#h(e){this.#l.clear(),e.split(",").map(i=>i.trim()).forEach(i=>{if(i.startsWith(".")){let r=this.#y(i);r&&this.#l.add(r)}else this.#l.add(i)})}#y(e){return{".pdf":"application/pdf",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".txt":"text/plain",".csv":"text/csv",".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png",".gif":"image/gif",".svg":"image/svg+xml",".zip":"application/zip",".json":"application/json"}[e.toLowerCase()]||null}#E(){switch(this.securityTier){case u.CRITICAL:return".pdf,.txt";case u.SENSITIVE:return".pdf,.doc,.docx,.txt,.jpg,.jpeg,.png";case u.AUTHENTICATED:return".pdf,.doc,.docx,.xls,.xlsx,.txt,.csv,.jpg,.jpeg,.png,.gif";case u.PUBLIC:default:return".pdf,.doc,.docx,.xls,.xlsx,.txt,.csv,.jpg,.jpeg,.png,.gif,.zip"}}#w(){switch(this.securityTier){case u.CRITICAL:return 2*1024*1024;case u.SENSITIVE:return 5*1024*1024;case u.AUTHENTICATED:return 10*1024*1024;case u.PUBLIC:default:return 20*1024*1024}}#x(){let e=(this.#c/1048576).toFixed(1);return`Accepted: ${this.#e.accept||"all files"} (max ${e}MB)`}#v(){this.#e.addEventListener("change",e=>{this.#f(e)}),this.#r.addEventListener("dragover",e=>{e.preventDefault(),e.stopPropagation(),this.#r.classList.add("drag-over")}),this.#r.addEventListener("dragleave",e=>{e.preventDefault(),e.stopPropagation(),this.#r.classList.remove("drag-over")}),this.#r.addEventListener("drop",e=>{e.preventDefault(),e.stopPropagation(),this.#r.classList.remove("drag-over");let t=e;if(!t.dataTransfer)return;let i=t.dataTransfer.files;i.length>0&&(this.#e.files=i,this.#f({target:this.#e}))})}async#f(e){let t=e.target.files;if(!t||t.length===0)return;let i=this.checkRateLimit();if(!i.allowed){this.#H(`Too many upload attempts. Please wait ${Math.ceil(i.retryAfter/1e3)} seconds.`),this.#e.value="";return}this.#F();let r=await this.#m(t);if(!r.valid){this.#H(r.errors.join(", ")),this.#e.value="",this.#o=null;return}this.#o=t,this.#M(t),this.#L(t),this.audit("files_selected",{name:this.#e.name,fileCount:t.length,totalSize:Array.from(t).reduce((s,n)=>s+n.size,0)}),this.dispatchEvent(new CustomEvent("secure-file-change",{detail:{name:this.#e.name,files:Array.from(t),tier:this.securityTier},bubbles:!0,composed:!0}))}async#m(e){let t=[];!this.#e.multiple&&e.length>1&&t.push("Only one file is allowed");for(let i=0;i<e.length;i++){let r=e[i];if(r.size>this.#c){let s=(this.#c/1048576).toFixed(1);t.push(`${r.name}: File size exceeds ${s}MB`);continue}if(this.#l.size>0&&!this.#b(r)){t.push(`${r.name}: File type not allowed`);continue}if(this.#g(r.name)){t.push(`${r.name}: Invalid file name`);continue}if(this.securityTier===u.CRITICAL){let s=await this.#z(r);if(!s.valid){t.push(`${r.name}: ${s.error}`);continue}}if(this.#d){let s=await this.#A(r);if(!s.valid){t.push(`${r.name}: ${s.reason||"Rejected by scan"}`);continue}}}return{valid:t.length===0,errors:t}}#b(e){if(this.#l.has(e.type))return!0;for(let t of this.#l)if(t.endsWith("/*")){let i=t.slice(0,-2);if(e.type.startsWith(i))return!0}return!1}#g(e){return!!(e.includes("..")||e.includes("/")||e.includes("\\")||["web.config",".htaccess",".env","config.php"].includes(e.toLowerCase()))}async#A(e){this.#p=!0,this.#C(e.name),this.audit("scan_started",{name:this.#e?.name??"",fileName:e.name,fileSize:e.size});try{let t=await this.#d(e);return this.audit(t.valid?"scan_passed":"scan_rejected",{name:this.#e?.name??"",fileName:e.name,reason:t.reason??""}),t}catch(t){let i=t instanceof Error?t.message:"Scan failed";return this.audit("scan_error",{name:this.#e?.name??"",fileName:e.name,error:i}),{valid:!1,reason:`Scan error: ${i}`}}finally{this.#p=!1,this.#S()}}#C(e){this.#r&&this.#r.classList.add("scanning"),this.#e&&(this.#e.disabled=!0),this.#n&&(this.#n.textContent=`Scanning ${e}\u2026`)}#S(){this.#r&&this.#r.classList.remove("scanning"),this.#e&&!this.hasAttribute("disabled")&&(this.#e.disabled=!1)}async#z(e){try{let t=await e.slice(0,4).arrayBuffer(),i=new Uint8Array(t),r={"application/pdf":[37,80,68,70],"image/jpeg":[255,216,255],"image/png":[137,80,78,71]};return r[e.type]&&!r[e.type].every((a,o)=>i[o]===a)?{valid:!1,error:"File content does not match declared type"}:{valid:!0}}catch{return{valid:!1,error:"Failed to validate file content"}}}#M(e){this.#n&&(!e||e.length===0?(this.#n.textContent="No file selected",this.#n.classList.remove("has-file")):e.length===1?(this.#n.textContent=e[0].name,this.#n.classList.add("has-file")):(this.#n.textContent=`${e.length} files selected`,this.#n.classList.add("has-file")))}#L(e){this.#s.innerHTML="",Array.from(e).forEach(t=>{let i=document.createElement("div");i.className="file-preview";let r=document.createElement("div");r.className="file-name",r.textContent=t.name;let s=document.createElement("div");s.className="file-size",s.textContent=this.#D(t.size);let n=document.createElement("button");n.className="remove-file",n.textContent="\u2715",n.type="button",n.onclick=()=>{this.#I()},i.appendChild(r),i.appendChild(s),i.appendChild(n),this.#s.appendChild(i)})}#D(e){return e<1024?e+" B":e<1024*1024?(e/1024).toFixed(1)+" KB":(e/(1024*1024)).toFixed(1)+" MB"}#I(){this.#e.value="",this.#o=null,this.#s.innerHTML="",this.#M(null),this.#F(),this.audit("file_removed",{name:this.#e.name})}#H(e){this.#i.textContent=e,this.#i.classList.remove("hidden"),this.#r.classList.add("error")}#F(){this.#i.textContent="",this.#i.classList.add("hidden"),this.#r.classList.remove("error")}#P(){return".file-upload-container { position: relative; margin-bottom: var(--secure-ui-form-gap); font-family: var(--secure-ui-font-family-base); } label { display: block; margin-bottom: var(--secure-ui-form-label-margin-bottom); font-size: var(--secure-ui-label-font-size); font-weight: var(--secure-ui-label-font-weight); color: var(--secure-ui-label-color); } .label-suffix { font-weight: var(--secure-ui-font-weight-normal); color: var(--secure-ui-color-text-secondary); font-size: var(--secure-ui-font-size-xs); margin-left: var(--secure-ui-space-1); } .security-badge { display: inline-block; padding: var(--secure-ui-badge-padding); margin-left: var(--secure-ui-space-2); font-size: var(--secure-ui-badge-font-size); font-weight: var(--secure-ui-font-weight-semibold); border-radius: var(--secure-ui-badge-border-radius); text-transform: uppercase; background-color: var(--secure-ui-color-bg-tertiary); color: var(--secure-ui-color-text-secondary); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); } .drop-zone { position: relative; display: inline-flex; align-items: stretch; justify-content: flex-start; border-radius: var(--secure-ui-input-border-radius); cursor: pointer; width: 100%; } .drop-zone.drag-over { transform: scale(1.01); } .drop-zone.error .file-cta { border-color: var(--secure-ui-color-error); color: var(--secure-ui-color-error); } .file-input { position: absolute; top: 0; left: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; z-index: 1; } .file-input:focus { outline: none; } .drop-zone:focus-within .file-cta { outline: 2px solid var(--secure-ui-color-border-focus); outline-offset: 2px; box-shadow: var(--secure-ui-shadow-focus); } @media (forced-colors: active) { .drop-zone:focus-within .file-cta { outline: 2px solid ButtonText; box-shadow: none; } } .drop-zone-content { display: flex; align-items: stretch; width: 100%; pointer-events: none; } .file-cta { display: flex; align-items: center; justify-content: center; padding: var(--secure-ui-input-padding-y) var(--secure-ui-input-padding-x); background-color: var(--secure-ui-color-bg-secondary); border: var(--secure-ui-input-border-width) solid var(--secure-ui-input-border-color); border-radius: var(--secure-ui-input-border-radius); color: var(--secure-ui-color-text-primary); font-size: var(--secure-ui-input-font-size); font-weight: var(--secure-ui-font-weight-medium); white-space: nowrap; transition: all var(--secure-ui-transition-base) var(--secure-ui-transition-ease-in-out); } .drop-zone:hover .file-cta { background-color: var(--secure-ui-color-bg-tertiary); border-color: var(--secure-ui-input-border-color-hover); } .drop-zone:active .file-cta { background-color: var(--secure-ui-color-bg-tertiary); } .drop-zone.drag-over .file-cta { background-color: var(--secure-ui-color-primary-light, rgba(102, 126, 234, 0.1)); border-color: var(--secure-ui-color-primary); color: var(--secure-ui-color-primary); } .drop-icon { font-size: var(--secure-ui-font-size-base); margin-right: var(--secure-ui-space-2); display: flex; align-items: center; } .drop-text { font-size: var(--secure-ui-font-size-base); } .file-name-display { display: flex; align-items: center; flex: 1; padding: var(--secure-ui-input-padding-y) var(--secure-ui-input-padding-x); border: var(--secure-ui-input-border-width) solid var(--secure-ui-input-border-color); border-left: none; border-radius: 0 var(--secure-ui-input-border-radius) var(--secure-ui-input-border-radius) 0; background-color: var(--secure-ui-input-bg); color: var(--secure-ui-input-placeholder-color); font-size: var(--secure-ui-input-font-size); max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .file-name-display.has-file { color: var(--secure-ui-input-text-color); } .drop-zone-content.has-name .file-cta { border-radius: var(--secure-ui-input-border-radius) 0 0 var(--secure-ui-input-border-radius); border-right: none; } .drop-hint { display: block; text-align: right; margin-top: var(--secure-ui-space-1); font-size: var(--secure-ui-font-size-xs); color: var(--secure-ui-color-text-secondary); } .preview-container { margin-top: var(--secure-ui-space-3); } .file-preview { display: flex; align-items: center; padding: var(--secure-ui-space-3); background-color: var(--secure-ui-color-bg-secondary); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); border-radius: var(--secure-ui-input-border-radius); margin-bottom: var(--secure-ui-space-2); } .file-name { flex: 1; font-size: var(--secure-ui-font-size-sm); color: var(--secure-ui-color-text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .file-size { font-size: var(--secure-ui-font-size-xs); color: var(--secure-ui-color-text-secondary); margin-left: var(--secure-ui-space-3); white-space: nowrap; } .remove-file { background: none; border: none; color: var(--secure-ui-color-error); font-size: var(--secure-ui-font-size-base); cursor: pointer; padding: var(--secure-ui-space-1) var(--secure-ui-space-2); margin-left: var(--secure-ui-space-2); border-radius: var(--secure-ui-border-radius-sm); transition: background-color var(--secure-ui-transition-base) var(--secure-ui-transition-ease-in-out); pointer-events: auto; } .remove-file:hover { background-color: var(--secure-ui-color-error-light, rgba(239, 68, 68, 0.1)); } .error-container { position: absolute; bottom: -1rem; left: 0; display: var(--error-display); margin-top: var(--secure-ui-form-error-margin-top); padding: var(--secure-ui-space-2) var(--secure-ui-space-3); background-color: var(--secure-ui-color-error-light, rgba(239, 68, 68, 0.1)); border-radius: var(--secure-ui-border-radius-sm); color: var(--secure-ui-color-error); font-size: var(--secure-ui-error-font-size); } .error-container.hidden { max-height: 0; opacity: 0; transform: translateY(-4px); margin-top: 0; } .drop-zone.disabled { opacity: var(--secure-ui-input-disabled-opacity); cursor: not-allowed; } .drop-zone.disabled .file-cta { background-color: var(--secure-ui-input-disabled-bg); } .drop-zone.scanning { pointer-events: none; opacity: 0.7; } .drop-zone.scanning .file-cta { border-color: var(--secure-ui-color-primary); } .drop-zone.scanning .file-name-display { color: var(--secure-ui-color-primary); animation: scanning-pulse 1.2s ease-in-out infinite; } @keyframes scanning-pulse { 0%, 100% { opacity: 0.5; } 50% { opacity: 1; } }"}handleAttributeChange(e,t,i){if(this.#e)switch(e){case"disabled":this.#e.disabled=this.hasAttribute("disabled");break;case"accept":this.#e.accept=i,this.#h(i);break}}get files(){return this.#o}get name(){return this.#e?this.#e.name:""}get valid(){return!((this.hasAttribute("required")||this.config.validation.required)&&(!this.#o||this.#o.length===0))}clear(){this.#I()}setScanHook(e){if(typeof e!="function")throw new TypeError("setScanHook expects a function");this.#d=e,this.audit("scan_hook_registered",{name:this.#e?.name??""})}get hasScanHook(){return this.#d!==null}get scanning(){return this.#p}disconnectedCallback(){super.disconnectedCallback(),this.#o=null,this.#e&&(this.#e.value="")}};customElements.define("secure-file-upload",N);var F=class extends p{#e=null;#t=null;#i=null;#s=null;#r=`secure-datetime-${Math.random().toString(36).substring(2,11)}`;static get observedAttributes(){return[...super.observedAttributes,"name","type","label","required","min","max","step","value","show-timezone"]}constructor(){super()}render(){let e=document.createDocumentFragment(),t=document.createElement("div");t.className="datetime-container",t.setAttribute("part","container");let i=this.getAttribute("label");i&&(this.#t=document.createElement("label"),this.#t.htmlFor=this.#r,this.#t.textContent=this.sanitizeValue(i),this.#t.setAttribute("part","label"),t.appendChild(this.#t));let r=document.createElement("div");return r.className="input-wrapper",r.setAttribute("part","wrapper"),this.#e=document.createElement("input"),this.#e.id=this.#r,this.#e.className="datetime-field",this.#e.setAttribute("part","input"),this.#n(),this.#l(),r.appendChild(this.#e),this.hasAttribute("show-timezone")&&(this.#s=document.createElement("span"),this.#s.className="timezone-display",this.#s.textContent=this.#a(),r.appendChild(this.#s)),t.appendChild(r),this.#i=document.createElement("div"),this.#i.className="error-container hidden",this.#i.setAttribute("role","alert"),this.#i.setAttribute("part","error"),this.#i.id=`${this.#r}-error`,t.appendChild(this.#i),this.addComponentStyles(this.#E()),e.appendChild(t),e}#n(){let e=this.config,t=this.getAttribute("name");t&&(this.#e.name=this.sanitizeValue(t)),!this.getAttribute("label")&&t&&this.#e.setAttribute("aria-label",this.sanitizeValue(t)),this.#e.setAttribute("aria-describedby",`${this.#r}-error`),this.#s&&this.#s.setAttribute("aria-label",`Timezone: ${this.#a()}`);let i=this.getAttribute("type")||"date";["date","time","datetime-local","month","week"].includes(i)?this.#e.type=i:(console.warn(`Invalid datetime type "${i}", defaulting to "date"`),this.#e.type="date"),(this.hasAttribute("required")||e.validation.required)&&(this.#e.required=!0,this.#e.setAttribute("aria-required","true"));let s=this.getAttribute("min");s&&(this.#e.min=this.#o(s));let n=this.getAttribute("max");n&&(this.#e.max=this.#o(n));let a=this.getAttribute("step");a&&(this.#e.step=a),this.hasAttribute("disabled")&&(this.#e.disabled=!0),this.hasAttribute("readonly")&&(this.#e.readOnly=!0),e.storage.allowAutocomplete||(this.#e.autocomplete="off");let o=this.getAttribute("value");o&&(this.#e.value=this.#o(o))}#o(e){if(!e)return"";let t=this.#e?.type||this.getAttribute("type")||"date",i={date:/^\d{4}-\d{2}-\d{2}$/,time:/^\d{2}:\d{2}(:\d{2})?$/,"datetime-local":/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2})?$/,month:/^\d{4}-\d{2}$/,week:/^\d{4}-W\d{2}$/},r=Object.hasOwn(i,t)?i[t]:void 0;return r&&!r.test(e)?(console.warn(`Invalid ${t} format: ${e}`),""):e}#a(){let e=new Date().getTimezoneOffset(),t=Math.abs(Math.floor(e/60)),i=Math.abs(e%60);return`UTC${e<=0?"+":"-"}${t.toString().padStart(2,"0")}:${i.toString().padStart(2,"0")}`}#l(){this.setupAutofillDetection(this.#e),this.#e.addEventListener("focus",()=>{this.recordTelemetryFocus(),this.audit("datetime_focused",{name:this.#e.name,type:this.#e.type})}),this.#e.addEventListener("input",e=>{this.recordTelemetryInput(e),this.#c(e)}),this.#e.addEventListener("change",e=>{this.#d(e)}),this.#e.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#p(),this.audit("datetime_blurred",{name:this.#e.name,hasValue:this.#e.value.length>0})})}#c(e){this.#y(),this.dispatchEvent(new CustomEvent("secure-datetime-change",{detail:{name:this.#e.name,value:this.#e.value,type:this.#e.type,tier:this.securityTier},bubbles:!0,composed:!0}))}#d(e){let t=this.#e.value;if(!this.#o(t)&&t){this.#h("Invalid date/time format");return}this.#y(),this.audit("datetime_changed",{name:this.#e.name,type:this.#e.type,value:t})}#p(){let e=this.checkRateLimit();if(!e.allowed){this.#h(`Too many attempts. Please wait ${Math.ceil(e.retryAfter/1e3)} seconds.`);return}let t=this.#e.value;if(this.#e.required&&!t){this.#h("This field is required");return}if(t){if(this.#e.min&&t<this.#e.min){this.#h(`Value must be after ${this.#u(this.#e.min)}`);return}if(this.#e.max&&t>this.#e.max){this.#h(`Value must be before ${this.#u(this.#e.max)}`);return}}if(this.securityTier===u.CRITICAL&&t){let i=new Date(t);if(isNaN(i.getTime())){this.#h("Invalid date/time");return}let r=i.getFullYear();if(r<1900||r>2100){this.#h("Date must be between 1900 and 2100");return}}}#u(e){try{return new Date(e).toLocaleString()}catch{return e}}#h(e){this.#i.textContent=e,this.#i.offsetHeight,this.#i.classList.remove("hidden"),this.#e.classList.add("error"),this.#e.setAttribute("aria-invalid","true")}#y(){this.#i.classList.add("hidden"),this.#i.addEventListener("transitionend",()=>{this.#i.classList.contains("hidden")&&(this.#i.textContent="")},{once:!0}),this.#e.classList.remove("error"),this.#e.removeAttribute("aria-invalid")}#E(){return`.datetime-container { margin-bottom: var(--secure-ui-form-gap); font-family: var(--secure-ui-font-family-base); } label { display: block; margin-bottom: var(--secure-ui-form-label-margin-bottom); font-size: var(--secure-ui-label-font-size); font-weight: var(--secure-ui-label-font-weight); color: var(--secure-ui-label-color); } .label-suffix { font-weight: var(--secure-ui-font-weight-normal); color: var(--secure-ui-color-text-secondary); font-size: var(--secure-ui-font-size-xs); margin-left: var(--secure-ui-space-1); } .security-badge { display: inline-block; padding: var(--secure-ui-badge-padding); margin-left: var(--secure-ui-space-2); font-size: var(--secure-ui-badge-font-size); font-weight: var(--secure-ui-font-weight-semibold); border-radius: var(--secure-ui-badge-border-radius); text-transform: uppercase; background-color: var(--secure-ui-color-bg-tertiary); color: var(--secure-ui-color-text-secondary); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); } .input-wrapper { position: relative; } .datetime-field { width: 100%; height: var(--secure-ui-input-height); padding: var(--secure-ui-input-padding-y) var(--secure-ui-input-padding-x); font-family: var(--secure-ui-font-family-base); font-size: var(--secure-ui-input-font-size); line-height: var(--secure-ui-line-height-normal); color: var(--secure-ui-input-text-color); background-color: var(--secure-ui-input-bg); border: var(--secure-ui-input-border-width) solid var(--secure-ui-input-border-color); border-radius: var(--secure-ui-input-border-radius); transition: all var(--secure-ui-transition-base) var(--secure-ui-transition-ease-in-out); cursor: pointer; box-sizing: border-box; } .datetime-field::placeholder { color: var(--secure-ui-input-placeholder-color); } .datetime-field:hover:not(:disabled):not([readonly]) { border-color: var(--secure-ui-input-border-color-hover); } .datetime-field:focus { outline: none; border-color: var(--secure-ui-input-border-color-focus); box-shadow: var(--secure-ui-shadow-focus); } .datetime-field.error { border-color: var(--secure-ui-color-error); } .datetime-field.error:focus { box-shadow: var(--secure-ui-shadow-focus-error); } .datetime-field:disabled { background-color: var(--secure-ui-input-disabled-bg); cursor: not-allowed; opacity: var(--secure-ui-input-disabled-opacity); } .datetime-field[readonly] { background-color: var(--secure-ui-color-bg-secondary); cursor: default; } .input-wrapper::after { content: '\u{1F4C5}' / ''; position: absolute; right: var(--secure-ui-space-3); top: 50%; transform: translateY(-50%); pointer-events: none; font-size: var(--secure-ui-font-size-lg); color: var(--secure-ui-color-text-secondary); } .input-wrapper[data-type="time"]::after { content: '\u{1F550}' / ''; } .input-wrapper[data-type="datetime-local"]::after { content: '\u{1F4C5}' / ''; } .input-wrapper[data-type="month"]::after { content: '\u{1F4C6}' / ''; } .input-wrapper[data-type="week"]::after { content: '\u{1F4C5}' / ''; } .input-wrapper .timezone-display { position: absolute; right: 0; bottom: -1.25rem; } .range-display { display: none; margin-top: var(--secure-ui-space-2); padding: var(--secure-ui-space-2) var(--secure-ui-space-3); background-color: var(--secure-ui-color-bg-secondary); border-radius: var(--secure-ui-border-radius-sm); font-size: var(--secure-ui-font-size-xs); color: var(--secure-ui-color-text-secondary); } .range-display.visible { display: block; } .range-item { margin-bottom: var(--secure-ui-space-1); } .range-item:last-child { margin-bottom: 0; } .range-label { font-weight: var(--secure-ui-font-weight-medium); margin-right: var(--secure-ui-space-1); } .helper-text { margin-top: var(--secure-ui-space-2); font-size: var(--secure-ui-font-size-xs); color: var(--secure-ui-color-text-secondary); line-height: var(--secure-ui-line-height-normal); } .error-container { position: absolute; margin-top: var(--secure-ui-form-error-margin-top); font-size: var(--secure-ui-error-font-size); color: var(--secure-ui-error-color); line-height: var(--secure-ui-line-height-normal); overflow: hidden; max-height: 40px; opacity: 1; transform: translateY(0); transition: opacity 0.2s ease-out, transform 0.2s ease-out, max-height 0.2s ease-out, margin-top 0.2s ease-out; } .error-container.hidden { max-height: 0; opacity: 0; transform: translateY(-4px); margin-top: 0; } @media (prefers-reduced-motion: reduce) { .datetime-field, .error-container { transition: none !important; } } .datetime-field::-webkit-calendar-picker-indicator { display: inline-block; cursor: pointer; opacity: 1; padding: 4px; margin-left: 4px; } .datetime-field:disabled::-webkit-calendar-picker-indicator { cursor: not-allowed; opacity: 0.3; } .datetime-field::-webkit-inner-spin-button { height: auto; opacity: 0.6; cursor: pointer; } .datetime-field:valid:not(:placeholder-shown):not(:focus) { border-color: var(--secure-ui-color-success); } .datetime-field:invalid:not(:placeholder-shown):not(:focus) { border-color: var(--secure-ui-color-error); } .datetime-container:focus-within label { color: var(--secure-ui-color-primary); } .datetime-container.disabled { opacity: var(--secure-ui-input-disabled-opacity); } .datetime-container.disabled label { color: var(--secure-ui-color-text-disabled); } label .required { color: var(--secure-ui-color-error); margin-left: var(--secure-ui-space-1); }`}handleAttributeChange(e,t,i){if(this.#e)switch(e){case"disabled":this.#e.disabled=this.hasAttribute("disabled");break;case"readonly":this.#e.readOnly=this.hasAttribute("readonly");break;case"value":i!==this.#e.value&&(this.#e.value=this.#o(i||""));break;case"min":this.#e.min=this.#o(i||"");break;case"max":this.#e.max=this.#o(i||"");break}}get value(){return this.#e?this.#e.value:""}set value(e){this.#e&&(this.#e.value=this.#o(e||""))}get name(){return this.#e?this.#e.name:""}getValueAsDate(){if(!this.#e||!this.#e.value)return null;try{let e=new Date(this.#e.value);return isNaN(e.getTime())?null:e}catch{return null}}setValueFromDate(e){if(!this.#e||!(e instanceof Date))return;let t=this.#e.type,i="";switch(t){case"date":i=e.toISOString().split("T")[0];break;case"time":i=e.toTimeString().slice(0,5);break;case"datetime-local":i=e.toISOString().slice(0,16);break;case"month":i=e.toISOString().slice(0,7);break;case"week":let r=new Date(e);r.setHours(0,0,0,0),r.setDate(r.getDate()+4-(r.getDay()||7));let s=new Date(r.getFullYear(),0,1),n=Math.ceil(((r.getTime()-s.getTime())/864e5+1)/7);i=`${r.getFullYear()}-W${n.toString().padStart(2,"0")}`;break}this.#e.value=i}get valid(){let e=this.hasAttribute("required")||this.config.validation.required,t=this.#e?this.#e.value:"";return!(e&&!t||t&&!this.#o(t)||this.#e&&(this.#e.min&&t<this.#e.min||this.#e.max&&t>this.#e.max))}focus(){this.#e&&this.#e.focus()}blur(){this.#e&&this.#e.blur()}disconnectedCallback(){super.disconnectedCallback(),this.#e&&(this.#e.value="")}};customElements.define("secure-datetime",F);var $=class l extends p{#e=[];#t=[];#i=[];#s="";#r={column:null,direction:"asc"};#n={currentPage:1,pageSize:10};#o=!1;constructor(){super()}render(){return null}connectedCallback(){this.initializeSecurity();let e=this.querySelector('table[slot="table"]'),t=this.#a();t&&(this.#o=!0,this.#t=t.columns,this.#e=t.data,this.#i=[...t.data],e&&e.remove()),this.#m(),this.audit("table_mounted",{rowCount:this.#e.length,columnCount:this.#t.length,usingSlottedContent:this.#o})}#a(){let e=this.querySelector('table[slot="table"]');if(!e)return null;try{let t=e.querySelectorAll("thead th");if(t.length===0)return null;let i=Array.from(t).map(n=>({key:n.getAttribute("data-key")||n.textContent.trim().toLowerCase().replace(/\s+/g,"_"),label:n.textContent.trim().replace(/\s+$/,""),sortable:n.hasAttribute("data-sortable")?n.getAttribute("data-sortable")!=="false":!0,filterable:n.hasAttribute("data-filterable")?n.getAttribute("data-filterable")!=="false":void 0,tier:n.getAttribute("data-tier")||void 0,width:n.getAttribute("data-width")||void 0,render:n.hasAttribute("data-render-html")?this.#l(n):void 0})),r=e.querySelectorAll("tbody tr"),s=Array.from(r).map((n,a)=>{let o=n.querySelectorAll("td"),d=Object.create(null);return o.forEach((c,m)=>{if(m<i.length){let g=i[m],f=c.getAttribute("data-key")||g.key;if(f==="__proto__"||f==="constructor"||f==="prototype")return;c.innerHTML.trim().includes("<")?(d[f]=c.textContent?.trim()??"",d[`${f}_html`]=c.innerHTML.trim()):d[f]=c.textContent?.trim()??""}}),d});return{columns:i,data:s}}catch(t){return console.error("SecureTable: Error parsing slotted table",t),null}}#l(e){return(t,i,r)=>{let s=`${r}_html`,n=Object.hasOwn(i,s)?i[s]:null;return n?this.#E(n):this.#u(t)}}set data(e){Array.isArray(e)&&(this.#e=e,this.#i=[...e],this.#m())}get data(){return this.#e}set columns(e){Array.isArray(e)&&(this.#t=e,this.#m())}get columns(){return this.#t}#c(e){this.#s=e.toLowerCase(),this.#s?this.#i=this.#e.filter(t=>this.#t.some(i=>i.filterable===!1?!1:String(t[i.key]??"").toLowerCase().includes(this.#s))):this.#i=[...this.#e],this.#n.currentPage=1,this.#b(),this.audit("table_filtered",{filterTerm:e,resultCount:this.#i.length})}#d(e){this.#r.column===e?this.#r.direction=this.#r.direction==="asc"?"desc":"asc":(this.#r.column=e,this.#r.direction="asc"),this.#i.sort((t,i)=>{let r=Object.hasOwn(t,e)?t[e]:void 0,s=Object.hasOwn(i,e)?i[e]:void 0,n=r==null,a=s==null;if(n&&a)return 0;if(n)return 1;if(a)return-1;let o=typeof r=="number"?r:String(r),d=typeof s=="number"?s:String(s),c=0;return o>d?c=1:o<d&&(c=-1),this.#r.direction==="asc"?c:-c}),this.#b(),this.audit("table_sorted",{column:e,direction:this.#r.direction})}#p(e){let t=Math.ceil(this.#i.length/this.#n.pageSize);e<1||e>t||(this.#n.currentPage=e,this.#b())}#u(e){return e==null||e===""?"":String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}static#h=new Set(["a","abbr","b","br","button","code","em","i","s","small","span","strong","time","u"]);static#y=new Set(["class","href","title","aria-label","aria-hidden","type","datetime"]);#E(e){if(!e)return"";let t=new DOMParser().parseFromString(`<!DOCTYPE html><body>${e}`,"text/html");return this.#w(t.body),t.body.innerHTML}#w(e){for(let t of Array.from(e.childNodes)){if(t.nodeType===Node.TEXT_NODE)continue;if(t.nodeType!==Node.ELEMENT_NODE){e.removeChild(t);continue}let i=t,r=i.tagName.toLowerCase();if(!l.#h.has(r)){let s=document.createDocumentFragment();for(;i.firstChild;)s.appendChild(i.firstChild);e.replaceChild(s,i);continue}for(let s of Array.from(i.attributes)){let n=s.name.toLowerCase();if(n.startsWith("on")){i.removeAttribute(s.name);continue}if((n==="href"||n==="src"||n==="action")&&/^\s*(javascript|data)\s*:/i.test(s.value)){i.removeAttribute(s.name);continue}!l.#y.has(n)&&!n.startsWith("data-")&&i.removeAttribute(s.name)}this.#w(i)}}#x(e,t){if(e==null||e==="")return"-";let i=String(e);return t===u.SENSITIVE&&i.length>4?"\u2022".repeat(i.length-4)+i.slice(-4):t===u.CRITICAL?"\u2022".repeat(i.length):this.#u(i)}#v(e,t,i){if(typeof i.render=="function")return this.#E(i.render(e,t,i.key));let r=`${i.key}_html`;return Object.hasOwn(t,r)&&t[r]?this.#E(t[r]):this.#x(e,i.tier)}#f(){let e=Math.ceil(this.#i.length/this.#n.pageSize),t=(this.#n.currentPage-1)*this.#n.pageSize,i=t+this.#n.pageSize,r=this.#i.slice(t,i),s,n;if(r.length===0||this.#t.length===0){let a=this.#t.length===0?"No columns configured":"No results found",o=this.#t.length===0?"Set the columns property to configure the table":"Try adjusting your search term";s=`
|
|
1
|
+
var u=Object.freeze({PUBLIC:"public",AUTHENTICATED:"authenticated",SENSITIVE:"sensitive",CRITICAL:"critical"}),y=Object.freeze({[u.PUBLIC]:Object.freeze({name:"Public",level:1,validation:Object.freeze({required:!1,strict:!1,maxLength:5e3,pattern:null,sanitizeHtml:!0}),masking:Object.freeze({enabled:!1,character:"\u2022",partial:!1}),storage:Object.freeze({allowAutocomplete:!0,allowCache:!0,allowHistory:!0}),audit:Object.freeze({logAccess:!1,logChanges:!1,logSubmission:!1,includeMetadata:!1}),rateLimit:Object.freeze({enabled:!1,maxAttempts:0,windowMs:0})}),[u.AUTHENTICATED]:Object.freeze({name:"Authenticated",level:2,validation:Object.freeze({required:!0,strict:!1,maxLength:1e3,pattern:null,sanitizeHtml:!0}),masking:Object.freeze({enabled:!1,character:"\u2022",partial:!1}),storage:Object.freeze({allowAutocomplete:!0,allowCache:!1,allowHistory:!1}),audit:Object.freeze({logAccess:!1,logChanges:!0,logSubmission:!0,includeMetadata:!0}),rateLimit:Object.freeze({enabled:!1,maxAttempts:0,windowMs:0})}),[u.SENSITIVE]:Object.freeze({name:"Sensitive",level:3,validation:Object.freeze({required:!0,strict:!0,maxLength:500,pattern:null,sanitizeHtml:!0}),masking:Object.freeze({enabled:!0,character:"\u2022",partial:!0}),storage:Object.freeze({allowAutocomplete:!1,allowCache:!1,allowHistory:!1}),audit:Object.freeze({logAccess:!0,logChanges:!0,logSubmission:!0,includeMetadata:!0}),rateLimit:Object.freeze({enabled:!0,maxAttempts:10,windowMs:6e4})}),[u.CRITICAL]:Object.freeze({name:"Critical",level:4,validation:Object.freeze({required:!0,strict:!0,maxLength:256,pattern:null,sanitizeHtml:!0}),masking:Object.freeze({enabled:!0,character:"\u2022",partial:!1}),storage:Object.freeze({allowAutocomplete:!1,allowCache:!1,allowHistory:!1}),audit:Object.freeze({logAccess:!0,logChanges:!0,logSubmission:!0,includeMetadata:!0}),rateLimit:Object.freeze({enabled:!0,maxAttempts:5,windowMs:6e4})})});function v(l){return!l||!y[l]?(console.warn(`Invalid security tier "${l}", defaulting to CRITICAL`),y[u.CRITICAL]):y[l]}function A(l){return Object.values(u).includes(l)}function B(l,e){let t=v(l),i=v(e);return Math.sign(t.level-i.level)}function G(l,e){return B(l,e)>=0?l:e}var Q=Object.freeze({[u.PUBLIC]:Object.freeze({"default-src":["'self'"],"script-src":["'self'"],"style-src":["'self'"]}),[u.AUTHENTICATED]:Object.freeze({"default-src":["'self'"],"script-src":["'self'"],"style-src":["'self'"],"form-action":["'self'"]}),[u.SENSITIVE]:Object.freeze({"default-src":["'self'"],"script-src":["'self'"],"style-src":["'self'"],"form-action":["'self'"],"frame-ancestors":["'none'"],"upgrade-insecure-requests":[]}),[u.CRITICAL]:Object.freeze({"default-src":["'self'"],"script-src":["'self'"],"style-src":["'self'"],"form-action":["'self'"],"frame-ancestors":["'none'"],"upgrade-insecure-requests":[],"block-all-mixed-content":[],"base-uri":["'none'"]})}),ee=Object.freeze({"X-Content-Type-Options":"nosniff","X-Frame-Options":"DENY","X-XSS-Protection":"1; mode=block","Referrer-Policy":"strict-origin-when-cross-origin","Permissions-Policy":"geolocation=(), microphone=(), camera=()"});var p=class l extends HTMLElement{static#e=1e3;static#t={"script-tag":"Script injection blocked","js-protocol":"JavaScript protocol blocked","event-handler":"Event handler injection blocked","html-injection":"HTML element injection blocked","css-expression":"CSS expression injection blocked",vbscript:"VBScript injection blocked","data-uri-html":"Data URI injection blocked","template-syntax":"Template injection blocked"};static#i=[{id:"script-tag",pattern:/<script[\s>/]/i},{id:"js-protocol",pattern:/javascript\s*:/i},{id:"event-handler",pattern:/\bon\w+\s*=/i},{id:"html-injection",pattern:/<\s*(img|svg|iframe|object|embed|link|meta|base)[^>]*/i},{id:"css-expression",pattern:/expression\s*\(/i},{id:"vbscript",pattern:/vbscript\s*:/i},{id:"data-uri-html",pattern:/data:\s*text\/html/i},{id:"template-syntax",pattern:/\{\{[\s\S]*?\}\}/}];#n=u.CRITICAL;#r;#s;#a=[];#o=null;#c={attempts:0,windowStart:Date.now()};#l=!1;#u={focusAt:null,firstKeystrokeAt:null,blurAt:null,keyCount:0,correctionCount:0,pasteDetected:!1,autofillDetected:!1,focusCount:0,blurWithoutChange:0,lastInputLength:0};constructor(){super(),this.#s=this.attachShadow({mode:"closed"}),this.#r=v(this.#n)}static get observedAttributes(){return["security-tier","disabled","readonly","threat-feedback"]}connectedCallback(){this.#l||(this.#p(),this.#l=!0)}#p(){this.initializeSecurity(),this.#d()}initializeSecurity(){let e=this.getAttribute("security-tier");e&&A(e)&&(this.#n=e),this.#r=v(this.#n),this.#h("component_initialized",{tier:this.#n,timestamp:new Date().toISOString()})}attributeChangedCallback(e,t,i){if(e==="security-tier"&&this.#l){console.warn(`Security tier cannot be changed after initialization. Attempted change from "${t}" to "${i}" blocked.`),t!==null&&this.setAttribute("security-tier",t);return}this.#l&&this.handleAttributeChange(e,t,i)}handleAttributeChange(e,t,i){}#d(){this.#s.innerHTML="",this.addComponentStyles(`:host { display: block; box-sizing: border-box; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 1.5; } :host([hidden]) { display: none; } * { box-sizing: border-box; } .hidden { display: none; } .external-error { margin-block-start: var(--secure-ui-space-1, 0.25rem); padding-block: var(--secure-ui-space-1, 0.25rem); padding-inline: var(--secure-ui-space-2, 0.5rem); font-size: var(--secure-ui-font-size-xs, 0.75rem); border-radius: var(--secure-ui-border-radius-sm, 0.25rem); border-inline-start: 3px solid currentColor; } .external-error:not([data-variant]), .external-error[data-variant="error"] { color: var(--secure-ui-color-error, #ef4444); background-color: color-mix(in oklch, var(--secure-ui-color-error, #ef4444) 10%, transparent); } .external-error[data-variant="warning"] { color: var(--secure-ui-color-warning, #f59e0b); background-color: color-mix(in oklch, var(--secure-ui-color-warning, #f59e0b) 10%, transparent); } @keyframes secure-autofill-detect { from {} to {} } @keyframes secure-autofill-cancel { from {} to {} } input:-webkit-autofill { animation-name: secure-autofill-detect; animation-duration: 1ms; } input:not(:-webkit-autofill) { animation-name: secure-autofill-cancel; animation-duration: 1ms; } .security-badge { display: inline-block; padding: var(--secure-ui-badge-padding, 2px 6px); margin-left: var(--secure-ui-space-2, 0.5rem); font-size: var(--secure-ui-badge-font-size, 0.6875rem); font-weight: var(--secure-ui-font-weight-semibold, 600); border-radius: var(--secure-ui-badge-border-radius, 0.25rem); text-transform: uppercase; background-color: var(--secure-ui-color-bg-tertiary); color: var(--secure-ui-color-text-secondary); border: var(--secure-ui-border-width-thin, 1px) solid var(--secure-ui-color-border); }`);let e=this.render();e&&this.#s.appendChild(e),this.#o=document.createElement("div"),this.#o.className="external-error hidden",this.#o.setAttribute("aria-live","polite"),this.#s.appendChild(this.#o)}getBaseStylesheetUrl(){return`:host { display: block; box-sizing: border-box; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 1.5; } :host([hidden]) { display: none; } * { box-sizing: border-box; } .hidden { display: none; } .external-error { margin-block-start: var(--secure-ui-space-1, 0.25rem); padding-block: var(--secure-ui-space-1, 0.25rem); padding-inline: var(--secure-ui-space-2, 0.5rem); font-size: var(--secure-ui-font-size-xs, 0.75rem); border-radius: var(--secure-ui-border-radius-sm, 0.25rem); border-inline-start: 3px solid currentColor; } .external-error:not([data-variant]), .external-error[data-variant="error"] { color: var(--secure-ui-color-error, #ef4444); background-color: color-mix(in oklch, var(--secure-ui-color-error, #ef4444) 10%, transparent); } .external-error[data-variant="warning"] { color: var(--secure-ui-color-warning, #f59e0b); background-color: color-mix(in oklch, var(--secure-ui-color-warning, #f59e0b) 10%, transparent); } @keyframes secure-autofill-detect { from {} to {} } @keyframes secure-autofill-cancel { from {} to {} } input:-webkit-autofill { animation-name: secure-autofill-detect; animation-duration: 1ms; } input:not(:-webkit-autofill) { animation-name: secure-autofill-cancel; animation-duration: 1ms; } .security-badge { display: inline-block; padding: var(--secure-ui-badge-padding, 2px 6px); margin-left: var(--secure-ui-space-2, 0.5rem); font-size: var(--secure-ui-badge-font-size, 0.6875rem); font-weight: var(--secure-ui-font-weight-semibold, 600); border-radius: var(--secure-ui-badge-border-radius, 0.25rem); text-transform: uppercase; background-color: var(--secure-ui-color-bg-tertiary); color: var(--secure-ui-color-text-secondary); border: var(--secure-ui-border-width-thin, 1px) solid var(--secure-ui-color-border); }`}addComponentStyles(e){if(e.includes("{")){let t=new CSSStyleSheet;t.replaceSync(e),this.#s.adoptedStyleSheets=[...this.#s.adoptedStyleSheets,t]}else{let t=document.createElement("link");t.rel="stylesheet",t.href=e,this.#s.appendChild(t)}}sanitizeValue(e){if(typeof e!="string")return"";let t=document.createElement("div");return t.textContent=e,t.innerHTML}validateInput(e,t={}){let i=[],r=this.#r;(t.required!==void 0?t.required:r.validation.required)&&(!e||e.trim().length===0)&&i.push("This field is required");let n=t.maxLength||r.validation.maxLength;e&&e.length>n&&i.push(`Value exceeds maximum length of ${n}`);let a=t.minLength||0;e&&e.length<a&&i.push(`Value must be at least ${a} characters`);let o=t.pattern||r.validation.pattern;return o&&e&&!o.test(e)&&i.push("Value does not match required format"),r.validation.strict&&i.length>0&&this.#h("validation_failed",{errors:i,valueLength:e?e.length:0}),{valid:i.length===0,errors:i}}checkRateLimit(){if(!this.#r.rateLimit.enabled)return{allowed:!0,retryAfter:0};let e=Date.now(),t=this.#r.rateLimit.windowMs;if(e-this.#c.windowStart>t&&(this.#c.attempts=0,this.#c.windowStart=e),this.#c.attempts>=this.#r.rateLimit.maxAttempts){let i=t-(e-this.#c.windowStart);return this.#h("rate_limit_exceeded",{attempts:this.#c.attempts,retryAfter:i}),{allowed:!1,retryAfter:i}}return this.#c.attempts++,{allowed:!0,retryAfter:0}}#h(e,t={}){let i=this.#r.audit;if(!(e.includes("access")&&i.logAccess||e.includes("change")&&i.logChanges||e.includes("submit")&&i.logSubmission||e.includes("initialized")||e.includes("rate_limit")||e.includes("validation")||e.includes("threat")))return;let s={event:e,tier:this.#n,timestamp:new Date().toISOString(),data:Object.keys(t).length>0?t:void 0};i.includeMetadata&&(s.userAgent=navigator.userAgent,s.language=navigator.language),this.#a.length>=l.#e&&this.#a.shift(),this.#a.push(s),this.dispatchEvent(new CustomEvent("secure-audit",{detail:s,bubbles:!0,composed:!0}))}get shadowRoot(){return this.#s}get securityTier(){return this.#n}get config(){return this.#r}getAuditLog(){return[...this.#a]}reportError(e,t="error"){this.#o&&(this.#o.textContent=e,this.#o.dataset.variant=t,t==="error"?this.#o.setAttribute("role","alert"):this.#o.removeAttribute("role"),this.#o.classList.remove("hidden"))}clearExternalError(){this.#o&&(this.#o.removeAttribute("role"),this.#o.classList.add("hidden"),this.#o.textContent="",delete this.#o.dataset.variant)}clearAuditLog(){this.#a=[]}audit(e,t){this.#h(e,t)}detectInjection(e,t,i=!1){let r=i||this.hasAttribute("threat-feedback");for(let{id:s,pattern:n}of l.#i)if(n.test(e)){this.audit("threat_detected",{fieldName:t,patternId:s,threatType:"injection"}),this.dispatchEvent(new CustomEvent("secure-threat-detected",{detail:{fieldName:t,threatType:"injection",patternId:s,tier:this.securityTier,timestamp:Date.now()},bubbles:!0,composed:!0})),r&&this.showThreatFeedback(s);return}r&&this.clearThreatFeedback()}showThreatFeedback(e){}clearThreatFeedback(){}getThreatLabel(e){return l.#t[e]??`Injection blocked: ${e}`}rerender(){this.#d()}recordTelemetryFocus(){let e=this.#u;e.focusAt=Date.now(),e.blurAt=null,e.focusCount++;let t=this.shadowRoot.querySelector('input:not([type="hidden"]), textarea, select');e.lastInputLength=t?t.value.length:0}recordTelemetryInput(e){let t=this.#u,i=Date.now();t.firstKeystrokeAt===null&&(t.firstKeystrokeAt=i);let s=e.inputType??"";if(s==="insertFromPaste"||s==="insertFromPasteAsQuotation")t.pasteDetected=!0;else if(s==="insertReplacementText")t.autofillDetected=!0;else if(s===""){let a=e.target;(a instanceof HTMLInputElement||a instanceof HTMLTextAreaElement)&&(t.autofillDetected=!0)}else s.startsWith("delete")||s==="historyUndo"||s==="historyRedo"?t.correctionCount++:t.keyCount++;let n=e.target;n&&(t.lastInputLength=n.value.length)}recordTelemetryBlur(){let e=this.#u;e.blurAt=Date.now();let t=this.shadowRoot.querySelector('input:not([type="hidden"]), textarea, select');(t?t.value.length:0)===e.lastInputLength&&e.keyCount===0&&!e.pasteDetected&&e.blurWithoutChange++}setupAutofillDetection(e){e.addEventListener("animationstart",t=>{t.animationName==="secure-autofill-detect"&&(this.#u.autofillDetected=!0)})}getFieldTelemetry(){let e=this.#u,t=e.focusAt??Date.now(),i=e.firstKeystrokeAt,r=e.blurAt??Date.now(),s=i!==null?i-t:0,n=i!==null?r-i:0,a=n/1e3,o=a>0?e.keyCount/a:0;return{dwell:s,completionTime:n,velocity:Math.round(o*100)/100,corrections:e.correctionCount,pasteDetected:e.pasteDetected,autofillDetected:e.autofillDetected,focusCount:e.focusCount,blurWithoutChange:e.blurWithoutChange}}#g(){this.#u={focusAt:null,firstKeystrokeAt:null,blurAt:null,keyCount:0,correctionCount:0,pasteDetected:!1,autofillDetected:!1,focusCount:0,blurWithoutChange:0,lastInputLength:0}}disconnectedCallback(){this.#c={attempts:0,windowStart:Date.now()},this.#g(),this.#r.audit.logAccess&&this.#h("component_disconnected",{timestamp:new Date().toISOString()})}};var I=class l extends p{static#e=new Set(["text","url","search"]);#t=null;#i=null;#n=null;#r=null;#s="";#a=!1;#o=null;#c=null;#l=`secure-input-${Math.random().toString(36).substring(2,11)}`;static get observedAttributes(){return[...super.observedAttributes,"name","type","label","placeholder","required","pattern","minlength","maxlength","autocomplete","value"]}render(){let e=document.createDocumentFragment(),t=document.createElement("div");t.className="input-container",t.setAttribute("part","container");let i=this.getAttribute("label");i&&(this.#i=document.createElement("label"),this.#i.htmlFor=this.#l,this.#i.textContent=this.sanitizeValue(i),this.#i.setAttribute("part","label"),t.appendChild(this.#i));let r=document.createElement("div");return r.className="input-wrapper",r.setAttribute("part","wrapper"),this.#t=document.createElement("input"),this.#t.id=this.#l,this.#t.className="input-field",this.#t.setAttribute("part","input"),this.#h(),this.#g(),r.appendChild(this.#t),t.appendChild(r),this.#n=document.createElement("div"),this.#n.className="error-container hidden",this.#n.setAttribute("role","alert"),this.#n.setAttribute("part","error"),this.#n.id=`${this.#l}-error`,t.appendChild(this.#n),this.#r=document.createElement("div"),this.#r.className="threat-container hidden",this.#r.setAttribute("role","alert"),this.#r.setAttribute("part","threat"),this.#r.id=`${this.#l}-threat`,t.appendChild(this.#r),this.#u(),this.#d(),this.addComponentStyles(this.#A()),e.appendChild(t),e}#u(){let e=this.getAttribute("name");e&&(this.closest("secure-form")||(this.#o=document.createElement("input"),this.#o.type="hidden",this.#o.name=e,this.#o.value=this.#s||"",this.appendChild(this.#o)))}#p(){this.#o&&(this.#o.value=this.#s||"")}#d(){this.querySelectorAll("input, textarea, select").forEach(t=>{if(t===this.#o)return;let i=t;i.removeAttribute("required"),i.removeAttribute("name"),i.removeAttribute("minlength"),i.removeAttribute("maxlength"),i.removeAttribute("pattern"),i.setAttribute("tabindex","-1"),i.setAttribute("aria-hidden","true")})}#h(){let e=this.config,t=this.getAttribute("name");t&&(this.#t.name=this.sanitizeValue(t)),!this.getAttribute("label")&&t&&this.#t.setAttribute("aria-label",this.sanitizeValue(t)),this.#t.setAttribute("aria-describedby",`${this.#l}-error`);let i=this.getAttribute("type")||"text";this.#t.type=i;let r=this.getAttribute("placeholder");r&&(this.#t.placeholder=this.sanitizeValue(r)),(this.hasAttribute("required")||e.validation.required)&&(this.#t.required=!0,this.#t.setAttribute("aria-required","true"));let s=this.getAttribute("pattern");s&&(this.#t.pattern=s);let n=this.getAttribute("minlength");n&&(this.#t.minLength=parseInt(n,10));let a=this.getAttribute("maxlength")||e.validation.maxLength;if(a&&(this.#t.maxLength=parseInt(String(a),10)),e.storage.allowAutocomplete){let c=this.getAttribute("autocomplete")||"on";this.#t.autocomplete=c}else this.#t.autocomplete="off",this.#t.type==="password"&&(this.#t.autocomplete="new-password");this.hasAttribute("disabled")&&(this.#t.disabled=!0),this.hasAttribute("readonly")&&(this.#t.readOnly=!0);let o=this.getAttribute("value");o&&this.#m(o);let d=new Set(["email","url","tel"]);e.masking.enabled&&this.#t.type!=="password"&&!d.has(this.#t.type)&&(this.#a=!0)}#g(){this.setupAutofillDetection(this.#t),this.#t.addEventListener("focus",()=>{this.recordTelemetryFocus(),this.audit("input_focused",{name:this.#t.name})}),this.#t.addEventListener("input",e=>{this.recordTelemetryInput(e),this.#x(e)}),this.#t.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#E(),this.audit("input_blurred",{name:this.#t.name,hasValue:this.#s.length>0})}),this.#t.addEventListener("paste",e=>{this.#a&&(this.#c=e.clipboardData?.getData("text/plain")??null)}),this.#t.addEventListener("change",()=>{this.audit("input_changed",{name:this.#t.name,valueLength:this.#s.length})})}#x(e){if(this.#a&&this.#t.type!=="password"){let i=e,r=i.inputType,s=i.data||"",n=this.#t.selectionStart||0;if(r==="deleteContentBackward")n<this.#s.length&&(this.#s=this.#s.substring(0,n)+this.#s.substring(n+1));else if(r==="deleteContentForward")this.#s=this.#s.substring(0,n)+this.#s.substring(n+1);else if(r==="insertText")this.#s=this.#s.substring(0,n-s.length)+s+this.#s.substring(n-s.length);else if(r==="insertFromPaste"){let o=this.#c??s;this.#c=null,o&&(this.#s=this.#s.substring(0,n-o.length)+o+this.#s.substring(n-o.length))}else this.#s="",this.#t.value="";let a=this.#y(this.#s);this.#t.value=a,this.#t.setSelectionRange(n,n)}else this.#s=this.#t.value;let t=this.#t.type;t!=="number"&&this.detectInjection(this.#s,this.#t.name,l.#e.has(t)),this.#f(),this.#p(),this.dispatchEvent(new CustomEvent("secure-input-change",{detail:{name:this.#t.name,masked:this.#a,tier:this.securityTier},bubbles:!0,composed:!0}))}#y(e){let t=this.config,i=t.masking.character;if(!t.masking.partial||this.securityTier===u.CRITICAL||e.length<=4)return i.repeat(e.length);let r=i.repeat(e.length-4),s=e.slice(-4);return r+s}#v(e){if(!this.#t||this.#t.type!=="password"||!e||e.length===0)return null;let t=this.securityTier;if(t==="critical"){if(e.length<8)return"Password must be at least 8 characters";if(!/[a-z]/.test(e))return"Password must include a lowercase letter";if(!/[A-Z]/.test(e))return"Password must include an uppercase letter";if(!/[0-9]/.test(e))return"Password must include a number";if(!/[^a-zA-Z0-9]/.test(e))return"Password must include a special character"}else if(t==="sensitive"){if(e.length<8)return"Password must be at least 8 characters";if(!/[a-z]/.test(e))return"Password must include a lowercase letter";if(!/[A-Z]/.test(e))return"Password must include an uppercase letter";if(!/[0-9]/.test(e))return"Password must include a number"}else if(t==="authenticated"&&e.length<6)return"Password must be at least 6 characters";return null}#w(e){if(!this.#t||this.#t.type!=="number"||!e||e.length===0)return null;let t=Number(e);if(!Number.isFinite(t))return"Value must be a valid number";if(!e.includes(".")&&!Number.isSafeInteger(t))return"Value exceeds safe integer range";let i=this.getAttribute("min"),r=this.getAttribute("max");if(i!==null){let s=Number(i);if(Number.isFinite(s)&&t<s)return`Value must be at least ${s}`}if(r!==null){let s=Number(r);if(Number.isFinite(s)&&t>s)return`Value must be at most ${s}`}return null}#E(){let e=this.checkRateLimit();if(!e.allowed){this.#b(`Too many attempts. Please wait ${Math.ceil(e.retryAfter/1e3)} seconds.`);return}let t=this.getAttribute("minlength"),i=this.getAttribute("maxlength"),r=this.getAttribute("pattern"),s=null;if(r&&r.length<=200)try{s=new RegExp(r)}catch{}let n=this.validateInput(this.#s,{required:this.hasAttribute("required")||this.config.validation.required,pattern:s,minLength:t?parseInt(t,10):0,maxLength:i?parseInt(i,10):this.config.validation.maxLength});if(!n.valid){this.#b(n.errors.join(", "));return}let a=this.#v(this.#s);if(a){this.#b(a);return}let o=this.#w(this.#s);if(o){this.#b(o);return}if(this.#t&&this.#s){let d,c;if(this.#a){let m=this.#t.value;this.#t.value=this.#s,d=this.#t.checkValidity(),c=this.#t.validationMessage,this.#t.value=m}else d=this.#t.checkValidity(),c=this.#t.validationMessage;if(!d){this.#b(c);return}}}#b(e){this.#n.textContent=e,this.#n.offsetHeight,this.#n.classList.remove("hidden"),this.#t.classList.add("error"),this.#t.setAttribute("aria-invalid","true")}#f(){this.#n.classList.add("hidden"),this.#n.addEventListener("transitionend",()=>{this.#n.classList.contains("hidden")&&(this.#n.textContent="")},{once:!0}),this.#t.classList.remove("error"),this.#t.removeAttribute("aria-invalid")}#m(e){this.#s=e,this.#a&&this.#t.type!=="password"?this.#t.value=this.#y(e):this.#t.value=e,this.#p()}#A(){return".input-container { margin-bottom: var(--secure-ui-form-gap); font-family: var(--secure-ui-font-family-base); } label { display: flex; align-items: flex-end; margin-bottom: var(--secure-ui-form-label-margin-bottom); font-size: var(--secure-ui-label-font-size); font-weight: var(--secure-ui-label-font-weight); color: var(--secure-ui-label-color); } .label-suffix { font-weight: var(--secure-ui-font-weight-normal); color: var(--secure-ui-color-text-secondary); font-size: var(--secure-ui-font-size-xs); margin-left: var(--secure-ui-space-1); } .security-badge { display: inline-block; padding: var(--secure-ui-badge-padding); margin-left: var(--secure-ui-space-2); font-size: var(--secure-ui-badge-font-size); font-weight: var(--secure-ui-font-weight-semibold); border-radius: var(--secure-ui-badge-border-radius); text-transform: uppercase; background-color: var(--secure-ui-color-bg-tertiary); color: var(--secure-ui-color-text-secondary); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); } .input-wrapper { position: relative; } .input-field { width: 100%; height: var(--secure-ui-input-height); padding: var(--secure-ui-input-padding-y) var(--secure-ui-input-padding-x); font-family: var(--secure-ui-font-family-base); font-size: var(--secure-ui-input-font-size); line-height: var(--secure-ui-line-height-normal); color: var(--secure-ui-input-text-color); background-color: var(--secure-ui-input-bg); border: var(--secure-ui-input-border-width) solid var(--secure-ui-input-border-color); border-radius: var(--secure-ui-input-border-radius); transition: all var(--secure-ui-transition-base) var(--secure-ui-transition-ease-in-out); box-sizing: border-box; } .input-field::placeholder { color: var(--secure-ui-input-placeholder-color); } .input-field:hover:not(:disabled) { border-color: var(--secure-ui-input-border-color-hover); } .input-field:focus { outline: none; border-color: var(--secure-ui-input-border-color-focus); box-shadow: var(--secure-ui-shadow-focus); } .input-field.error { border-color: var(--secure-ui-color-error) !important; } .input-field.error:focus { box-shadow: var(--secure-ui-shadow-focus-error); } .input-field:disabled { background-color: var(--secure-ui-input-disabled-bg); cursor: not-allowed; opacity: var(--secure-ui-input-disabled-opacity); } .input-field:read-only:not(:disabled) { background-color: var(--secure-ui-color-bg-secondary); cursor: default; } .error-container { position: absolute; margin-top: var(--secure-ui-form-error-margin-top); font-size: var(--secure-ui-error-font-size); color: var(--secure-ui-error-color); line-height: var(--secure-ui-line-height-normal); overflow: hidden; max-height: 40px; opacity: 1; transform: translateY(0); transition: all 0.5s ease-in-out; } .error-container.hidden { max-height: 0; opacity: 0; transform: translateY(-4px); margin-top: 0; transition: all 0.2s ease-in-out; } @media (prefers-reduced-motion: reduce) { .input-field, .error-container, .threat-container { transition: none !important; } } .threat-container { margin-top: var(--secure-ui-form-error-margin-top); font-size: var(--secure-ui-error-font-size); color: var(--secure-ui-color-warning); line-height: var(--secure-ui-line-height-normal); overflow: hidden; max-height: 40px; opacity: 1; transform: translateY(0); transition: all 0.5s ease-in-out; display: flex; align-items: center; gap: var(--secure-ui-space-1, 4px); flex-wrap: wrap; } .threat-container.hidden { max-height: 0; opacity: 0; transform: translateY(-4px); margin-top: 0; transition: all 0.2s ease-in-out; } .threat-message { flex: 1; min-width: 0; } .threat-badge { display: inline-block; padding: var(--secure-ui-badge-padding); font-size: var(--secure-ui-badge-font-size); font-weight: var(--secure-ui-font-weight-semibold); border-radius: var(--secure-ui-badge-border-radius); background-color: color-mix(in srgb, var(--secure-ui-color-warning) 12%, transparent); color: var(--secure-ui-color-warning); border: var(--secure-ui-border-width-thin) solid currentColor; font-family: var(--secure-ui-font-family-mono, monospace); white-space: nowrap; } .input-field.threat { border-color: var(--secure-ui-color-warning) !important; } .input-field.threat:focus { box-shadow: 0 0 0 3px color-mix(in srgb, var(--secure-ui-color-warning) 25%, transparent); } .input-field:-webkit-autofill { -webkit-box-shadow: 0 0 0 1000px var(--secure-ui-input-bg) inset; -webkit-text-fill-color: var(--secure-ui-input-text-color); }"}handleAttributeChange(e,t,i){if(this.#t)switch(e){case"disabled":this.#t.disabled=this.hasAttribute("disabled");break;case"readonly":this.#t.readOnly=this.hasAttribute("readonly");break;case"value":i!==this.#s&&this.#m(i||"");break}}get value(){return this.#s}set value(e){this.#m(e||"")}get name(){return this.#t?this.#t.name:""}get valid(){let e=this.getAttribute("minlength"),t=this.getAttribute("maxlength"),i=this.getAttribute("pattern"),r=null;if(i&&i.length<=200)try{r=new RegExp(i)}catch{}if(!this.validateInput(this.#s,{required:this.hasAttribute("required")||this.config.validation.required,pattern:r,minLength:e?parseInt(e,10):0,maxLength:t?parseInt(t,10):this.config.validation.maxLength}).valid||this.#v(this.#s)!==null||this.#w(this.#s)!==null)return!1;if(this.#t&&this.#s){let n;if(this.#a){let a=this.#t.value;this.#t.value=this.#s,n=this.#t.checkValidity(),this.#t.value=a}else n=this.#t.checkValidity();if(!n)return!1}return!0}focus(){this.#t&&this.#t.focus()}blur(){this.#t&&this.#t.blur()}showThreatFeedback(e){if(!this.#r||!this.#t)return;this.#r.textContent="";let t=document.createElement("span");t.className="threat-message",t.textContent=this.getThreatLabel(e);let i=document.createElement("span");i.className="threat-badge",i.textContent=e,this.#r.appendChild(t),this.#r.appendChild(i),this.#r.offsetHeight,this.#r.classList.remove("hidden"),this.#t.classList.add("threat"),this.#t.setAttribute("aria-invalid","true")}clearThreatFeedback(){!this.#r||!this.#t||(this.#r.classList.add("hidden"),this.#r.addEventListener("transitionend",()=>{this.#r.classList.contains("hidden")&&(this.#r.textContent="")},{once:!0}),this.#t.classList.remove("threat"),this.#t.removeAttribute("aria-invalid"))}disconnectedCallback(){super.disconnectedCallback(),this.#s="",this.#c=null,this.#t&&(this.#t.value="")}};customElements.define("secure-input",I);var M=class extends p{#e=null;#t=null;#i=null;#n=null;#r=null;#s=`secure-textarea-${Math.random().toString(36).substring(2,11)}`;static get observedAttributes(){return[...super.observedAttributes,"name","label","placeholder","required","minlength","maxlength","rows","cols","wrap","value"]}render(){let e=document.createDocumentFragment(),t=document.createElement("div");t.className="textarea-container",t.setAttribute("part","container");let i=this.getAttribute("label");i&&(this.#t=document.createElement("label"),this.#t.htmlFor=this.#s,this.#t.textContent=this.sanitizeValue(i),this.#t.setAttribute("part","label"),t.appendChild(this.#t));let r=document.createElement("div");return r.className="textarea-wrapper",r.setAttribute("part","wrapper"),this.#e=document.createElement("textarea"),this.#e.id=this.#s,this.#e.className="textarea-field",this.#e.setAttribute("part","textarea"),this.#a(),this.#o(),r.appendChild(this.#e),t.appendChild(r),this.#r=document.createElement("span"),this.#r.className="char-count",this.#l(),t.appendChild(this.#r),this.#i=document.createElement("div"),this.#i.className="error-container hidden",this.#i.setAttribute("role","alert"),this.#i.setAttribute("part","error"),this.#i.id=`${this.#s}-error`,t.appendChild(this.#i),this.#n=document.createElement("div"),this.#n.className="threat-container hidden",this.#n.setAttribute("role","alert"),this.#n.setAttribute("part","threat"),this.#n.id=`${this.#s}-threat`,t.appendChild(this.#n),this.addComponentStyles(this.#h()),e.appendChild(t),e}#a(){let e=this.config,t=this.getAttribute("name");t&&(this.#e.name=this.sanitizeValue(t)),!this.getAttribute("label")&&t&&this.#e.setAttribute("aria-label",this.sanitizeValue(t)),this.#e.setAttribute("aria-describedby",`${this.#s}-error`);let i=this.getAttribute("placeholder");i&&(this.#e.placeholder=this.sanitizeValue(i)),(this.hasAttribute("required")||e.validation.required)&&(this.#e.required=!0,this.#e.setAttribute("aria-required","true"));let r=this.getAttribute("minlength");r&&(this.#e.minLength=parseInt(r,10));let s=this.getAttribute("maxlength")||e.validation.maxLength;s&&(this.#e.maxLength=parseInt(String(s),10));let n=this.getAttribute("rows")||3;this.#e.rows=parseInt(String(n),10);let a=this.getAttribute("cols");a&&(this.#e.cols=parseInt(a,10));let o=this.getAttribute("wrap")||"soft";if(this.#e.wrap=o,e.storage.allowAutocomplete){let c=this.getAttribute("autocomplete")||"on";this.#e.autocomplete=c}else this.#e.autocomplete="off";this.hasAttribute("disabled")&&(this.#e.disabled=!0),this.hasAttribute("readonly")&&(this.#e.readOnly=!0);let d=this.getAttribute("value");d&&(this.#e.value=d)}#o(){this.setupAutofillDetection(this.#e),this.#e.addEventListener("focus",()=>{this.recordTelemetryFocus(),this.audit("textarea_focused",{name:this.#e.name})}),this.#e.addEventListener("input",e=>{this.recordTelemetryInput(e),this.#c(e)}),this.#e.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#u(),this.audit("textarea_blurred",{name:this.#e.name,hasValue:this.#e.value.length>0})}),this.#e.addEventListener("change",()=>{this.audit("textarea_changed",{name:this.#e.name,valueLength:this.#e.value.length})})}#c(e){this.detectInjection(this.#e.value,this.#e.name),this.#l(),this.#d(),this.dispatchEvent(new CustomEvent("secure-textarea-change",{detail:{name:this.#e.name,value:this.#e.value,tier:this.securityTier},bubbles:!0,composed:!0}))}#l(){let e=this.#e.value.length,t=this.#e.maxLength;t>0?(this.#r.textContent=`${e} / ${t}`,e>t*.9?this.#r.classList.add("warning"):this.#r.classList.remove("warning")):this.#r.textContent=`${e}`}#u(){let e=this.checkRateLimit();if(!e.allowed){this.#p(`Too many attempts. Please wait ${Math.ceil(e.retryAfter/1e3)} seconds.`);return}let t=this.getAttribute("minlength"),i=this.getAttribute("maxlength"),r=this.validateInput(this.#e.value,{required:this.hasAttribute("required")||this.config.validation.required,minLength:t?parseInt(t,10):0,maxLength:i?parseInt(i,10):this.config.validation.maxLength});r.valid||this.#p(r.errors.join(", "))}#p(e){this.#i.textContent=e,this.#i.offsetHeight,this.#i.classList.remove("hidden"),this.#e.classList.add("error"),this.#e.setAttribute("aria-invalid","true")}#d(){this.#i.classList.add("hidden"),this.#i.addEventListener("transitionend",()=>{this.#i.classList.contains("hidden")&&(this.#i.textContent="")},{once:!0}),this.#e.classList.remove("error"),this.#e.removeAttribute("aria-invalid")}#h(){return'.textarea-container { margin-bottom: var(--secure-ui-form-gap); font-family: var(--secure-ui-font-family-base); } label { display: block; margin-bottom: var(--secure-ui-form-label-margin-bottom); font-size: var(--secure-ui-label-font-size); font-weight: var(--secure-ui-label-font-weight); color: var(--secure-ui-label-color); } .label-suffix { font-weight: var(--secure-ui-font-weight-normal); color: var(--secure-ui-color-text-secondary); font-size: var(--secure-ui-font-size-xs); margin-left: var(--secure-ui-space-1); } .security-badge { display: inline-block; padding: var(--secure-ui-badge-padding); margin-left: var(--secure-ui-space-2); font-size: var(--secure-ui-badge-font-size); font-weight: var(--secure-ui-font-weight-semibold); border-radius: var(--secure-ui-badge-border-radius); text-transform: uppercase; background-color: var(--secure-ui-color-bg-tertiary); color: var(--secure-ui-color-text-secondary); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); } .textarea-wrapper { position: relative; } .textarea-field { width: 100%; min-height: var(--secure-ui-textarea-min-height); padding: var(--secure-ui-textarea-padding); font-family: var(--secure-ui-font-family-base); font-size: var(--secure-ui-input-font-size); line-height: var(--secure-ui-line-height-normal); color: var(--secure-ui-input-text-color); background-color: var(--secure-ui-input-bg); border: var(--secure-ui-input-border-width) solid var(--secure-ui-input-border-color); border-radius: var(--secure-ui-input-border-radius); transition: all var(--secure-ui-transition-base) var(--secure-ui-transition-ease-in-out); resize: vertical; box-sizing: border-box; } .textarea-field::placeholder { color: var(--secure-ui-input-placeholder-color); } .textarea-field:hover:not(:disabled) { border-color: var(--secure-ui-input-border-color-hover); } .textarea-field:focus { outline: none; border-color: var(--secure-ui-input-border-color-focus); box-shadow: var(--secure-ui-shadow-focus); } .textarea-field.error { border-color: var(--secure-ui-color-error); } .textarea-field.error:focus { box-shadow: var(--secure-ui-shadow-focus-error); } .textarea-field:read-only:not(:disabled) { background-color: var(--secure-ui-color-bg-secondary); cursor: default; resize: none; } .textarea-field:disabled { background-color: var(--secure-ui-input-disabled-bg); cursor: not-allowed; opacity: var(--secure-ui-input-disabled-opacity); } .char-count { display: block; margin-top: var(--secure-ui-space-1); font-size: var(--secure-ui-font-size-xs); color: var(--secure-ui-color-text-secondary); text-align: right; } .char-count.warning { color: var(--secure-ui-color-warning); font-weight: var(--secure-ui-font-weight-medium); } .error-container { margin-top: var(--secure-ui-form-error-margin-top); font-size: var(--secure-ui-error-font-size); color: var(--secure-ui-error-color); line-height: var(--secure-ui-line-height-normal); overflow: hidden; max-height: 40px; opacity: 1; transform: translateY(0); transition: opacity 0.2s ease-out, transform 0.2s ease-out, max-height 0.2s ease-out, margin-top 0.2s ease-out; } .error-container.hidden { max-height: 0; opacity: 0; transform: translateY(-4px); margin-top: 0; } @media (prefers-reduced-motion: reduce) { .textarea-field, .error-container, .threat-container { transition: none !important; } } .threat-container { margin-top: var(--secure-ui-form-error-margin-top); font-size: var(--secure-ui-error-font-size); color: var(--secure-ui-color-warning); line-height: var(--secure-ui-line-height-normal); overflow: hidden; max-height: 40px; opacity: 1; transform: translateY(0); transition: opacity 0.2s ease-out, transform 0.2s ease-out, max-height 0.2s ease-out, margin-top 0.2s ease-out; display: flex; align-items: center; gap: var(--secure-ui-space-1, 4px); flex-wrap: wrap; } .threat-container.hidden { max-height: 0; opacity: 0; transform: translateY(-4px); margin-top: 0; } .threat-message { flex: 1; min-width: 0; } .threat-badge { display: inline-block; padding: var(--secure-ui-badge-padding); font-size: var(--secure-ui-badge-font-size); font-weight: var(--secure-ui-font-weight-semibold); border-radius: var(--secure-ui-badge-border-radius); background-color: color-mix(in srgb, var(--secure-ui-color-warning) 12%, transparent); color: var(--secure-ui-color-warning); border: var(--secure-ui-border-width-thin) solid currentColor; font-family: var(--secure-ui-font-family-mono, monospace); white-space: nowrap; } .textarea-field.threat { border-color: var(--secure-ui-color-warning) !important; } .textarea-field.threat:focus { box-shadow: 0 0 0 3px color-mix(in srgb, var(--secure-ui-color-warning) 25%, transparent); } :host([security-tier="authenticated"]) .textarea-field { border-color: var(--secure-ui-tier-authenticated); } :host([security-tier="sensitive"]) .textarea-field { border-color: var(--secure-ui-tier-sensitive); } :host([security-tier="critical"]) .textarea-field { border-color: var(--secure-ui-tier-critical); }'}handleAttributeChange(e,t,i){if(this.#e)switch(e){case"disabled":this.#e.disabled=this.hasAttribute("disabled");break;case"readonly":this.#e.readOnly=this.hasAttribute("readonly");break;case"value":i!==this.#e.value&&(this.#e.value=i||"",this.#l());break}}get value(){return this.#e?this.#e.value:""}set value(e){this.#e&&(this.#e.value=e||"",this.#l())}get name(){return this.#e?this.#e.name:""}get valid(){let e=this.getAttribute("minlength"),t=this.getAttribute("maxlength");return this.validateInput(this.#e.value,{required:this.hasAttribute("required")||this.config.validation.required,minLength:e?parseInt(e,10):0,maxLength:t?parseInt(t,10):this.config.validation.maxLength}).valid}focus(){this.#e&&this.#e.focus()}blur(){this.#e&&this.#e.blur()}showThreatFeedback(e){if(!this.#n||!this.#e)return;this.#n.textContent="";let t=document.createElement("span");t.className="threat-message",t.textContent=this.getThreatLabel(e);let i=document.createElement("span");i.className="threat-badge",i.textContent=e,this.#n.appendChild(t),this.#n.appendChild(i),this.#n.offsetHeight,this.#n.classList.remove("hidden"),this.#e.classList.add("threat"),this.#e.setAttribute("aria-invalid","true")}clearThreatFeedback(){!this.#n||!this.#e||(this.#n.classList.add("hidden"),this.#n.addEventListener("transitionend",()=>{this.#n.classList.contains("hidden")&&(this.#n.textContent="")},{once:!0}),this.#e.classList.remove("threat"),this.#e.removeAttribute("aria-invalid"))}disconnectedCallback(){super.disconnectedCallback(),this.#e&&(this.#e.value="")}};customElements.define("secure-textarea",M);var D=class extends p{#e=null;#t=null;#i=null;#n=`secure-select-${Math.random().toString(36).substring(2,11)}`;#r=new Set;#s=!1;#a=!1;static get observedAttributes(){return[...super.observedAttributes,"name","label","required","multiple","size","value"]}render(){let e=document.createDocumentFragment(),t=document.createElement("div");t.className="select-container",t.setAttribute("part","container"),this.#a=this.hasAttribute("multiple");let i=this.getAttribute("label");i&&(this.#t=document.createElement("label"),this.#t.htmlFor=this.#n,this.#t.textContent=this.sanitizeValue(i),this.#t.setAttribute("part","label"),t.appendChild(this.#t));let r=document.createElement("div");return r.className="select-wrapper",r.setAttribute("part","wrapper"),this.#e=document.createElement("select"),this.#e.id=this.#n,this.#e.className="select-field",this.#e.setAttribute("part","select"),this.#o(),this.#l(),queueMicrotask(()=>{this.#c()}),r.appendChild(this.#e),t.appendChild(r),this.#i=document.createElement("div"),this.#i.className="error-container hidden",this.#i.setAttribute("role","alert"),this.#i.setAttribute("part","error"),this.#i.id=`${this.#n}-error`,t.appendChild(this.#i),this.addComponentStyles(this.#g()),e.appendChild(t),e}#o(){let e=this.config,t=this.getAttribute("name");t&&(this.#e.name=this.sanitizeValue(t)),!this.getAttribute("label")&&t&&this.#e.setAttribute("aria-label",this.sanitizeValue(t)),this.#e.setAttribute("aria-describedby",`${this.#n}-error`),(this.hasAttribute("required")||e.validation.required)&&(this.#e.required=!0,this.#e.setAttribute("aria-required","true")),this.hasAttribute("multiple")&&(this.#e.multiple=!0);let i=this.getAttribute("size");i&&(this.#e.size=parseInt(i,10)),this.hasAttribute("disabled")&&(this.#e.disabled=!0),e.storage.allowAutocomplete||(this.#e.autocomplete="off")}#c(){if(this.#s)return;this.#s=!0;let e=Array.from(this.querySelectorAll("option"));if(e.length===0)return;let t=[];if(e.forEach(i=>{let r=document.createElement("option"),s=i.getAttribute("value")||"";r.value=this.sanitizeValue(s),this.#r.add(r.value),r.textContent=this.sanitizeValue(i.textContent||""),i.hasAttribute("selected")&&(r.selected=!0,t.push(r.value)),i.hasAttribute("disabled")&&(r.disabled=!0),this.#e.appendChild(r)}),!this.#a){let i=this.getAttribute("value");i?this.#e.value=i:t.length>0&&(this.#e.value=t[0])}}#l(){this.#e.addEventListener("focus",()=>{this.recordTelemetryFocus(),this.audit("select_focused",{name:this.#e.name})}),this.#e.addEventListener("change",e=>{this.recordTelemetryInput(e),this.#u(e)}),this.#e.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#p(),this.audit("select_blurred",{name:this.#e.name,hasValue:this.#a?this.#e.selectedOptions.length>0:this.#e.value.length>0})})}#u(e){if(this.#a){let t=Array.from(this.#e.selectedOptions).map(r=>r.value),i=t.filter(r=>r&&!this.#r.has(r));if(i.length>0){this.#d("Invalid option selected"),this.audit("invalid_option_detected",{name:this.#e.name,attemptedValues:i});return}this.#h(),this.audit("select_changed",{name:this.#e.name,values:t}),this.dispatchEvent(new CustomEvent("secure-select-change",{detail:{name:this.#e.name,value:t,tier:this.securityTier},bubbles:!0,composed:!0}))}else{let t=this.#e.value;if(t&&!this.#r.has(t)){this.#d("Invalid option selected"),this.audit("invalid_option_detected",{name:this.#e.name,attemptedValue:t}),this.#e.value="";return}this.#h(),this.audit("select_changed",{name:this.#e.name,value:t}),this.dispatchEvent(new CustomEvent("secure-select-change",{detail:{name:this.#e.name,value:t,tier:this.securityTier},bubbles:!0,composed:!0}))}}#p(){let e=this.checkRateLimit();if(!e.allowed){this.#d(`Too many attempts. Please wait ${Math.ceil(e.retryAfter/1e3)} seconds.`);return}let t=this.hasAttribute("required")||this.config.validation.required;if(this.#a){let i=Array.from(this.#e.selectedOptions).map(s=>s.value).filter(s=>s!=="");if(t&&i.length===0){this.#d("Please select at least one option");return}if(i.filter(s=>!this.#r.has(s)).length>0){this.#d("Invalid option selected");return}}else{if(t&&!this.#e.value){this.#d("Please select an option");return}let i=this.#e.value;if(i&&!this.#r.has(i)){this.#d("Invalid option selected");return}}}#d(e){this.#i.textContent=e,this.#i.offsetHeight,this.#i.classList.remove("hidden"),this.#e.classList.add("error"),this.#e.setAttribute("aria-invalid","true")}#h(){this.#i.classList.add("hidden"),this.#i.addEventListener("transitionend",()=>{this.#i.classList.contains("hidden")&&(this.#i.textContent="")},{once:!0}),this.#e.classList.remove("error"),this.#e.removeAttribute("aria-invalid")}#g(){return'.select-container { margin-bottom: var(--secure-ui-form-gap); font-family: var(--secure-ui-font-family-base); } label { display: block; margin-bottom: var(--secure-ui-form-label-margin-bottom); font-size: var(--secure-ui-label-font-size); font-weight: var(--secure-ui-label-font-weight); color: var(--secure-ui-label-color); } .label-suffix { font-weight: var(--secure-ui-font-weight-normal); color: var(--secure-ui-color-text-secondary); font-size: var(--secure-ui-font-size-xs); margin-left: var(--secure-ui-space-1); } .security-badge { display: inline-block; padding: var(--secure-ui-badge-padding); margin-left: var(--secure-ui-space-2); font-size: var(--secure-ui-badge-font-size); font-weight: var(--secure-ui-font-weight-semibold); border-radius: var(--secure-ui-badge-border-radius); text-transform: uppercase; background-color: var(--secure-ui-color-bg-tertiary); color: var(--secure-ui-color-text-secondary); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); } .select-wrapper { position: relative; } .select-field { width: 100%; height: var(--secure-ui-select-height); padding: var(--secure-ui-select-padding); font-family: var(--secure-ui-font-family-base); font-size: var(--secure-ui-input-font-size); line-height: var(--secure-ui-line-height-normal); color: var(--secure-ui-select-color); background-color: var(--secure-ui-select-background-color); border: var(--secure-ui-input-border-width) solid var(--secure-ui-input-border-color); border-radius: var(--secure-ui-input-border-radius); transition: all var(--secure-ui-transition-base) var(--secure-ui-transition-ease-in-out); cursor: pointer; box-sizing: border-box; } .select-field, ::picker(select) { appearance: base-select; border-radius: .25rem; } .select-field::picker-icon { color: #999999; transition: 0.2s rotate; } .select-field:open::picker-icon { rotate: 180deg; } .select-field option { display: flex; justify-content: flex-start; color: var(--secure-ui-select-color); background-color: var(--secure-ui-select-background-color); padding: .5rem; } .select-field option:hover { box-shadow: 0px 0px 4px 0px var(--secure-ui-input-border-color) inset; transition: all 0.2s ease-in-out; } .select-field option:first-of-type { border-top-left-radius: none; border-top-right-radius: none; } .select-field option:last-of-type { border-bottom-left-radius: none; border-bottom-right-radius: none; } .select-field option:nth-of-type(odd) { } .select-field option:checked { font-weight: bold; } .select-field option::checkmark { order: 1; margin-left: auto; content: "\u2713"; } .select-field option + option { border-top: 1px solid var(--secure-ui-input-border-color); } .select-field:hover:not(:disabled) { border-color: var(--secure-ui-input-border-color-hover); } .select-field:focus { outline: none; border-color: var(--secure-ui-input-border-color-focus); box-shadow: var(--secure-ui-shadow-focus); } .select-field.error { border-color: var(--secure-ui-color-error); } .select-field.error:focus { box-shadow: var(--secure-ui-shadow-focus-error); } .select-field:disabled { background-color: var(--secure-ui-input-disabled-bg); cursor: not-allowed; opacity: var(--secure-ui-input-disabled-opacity); } .select-field[multiple] { height: auto; min-height: calc(var(--secure-ui-select-height) * 2); padding: var(--secure-ui-space-2); } .error-container { position: absolute; margin-top: var(--secure-ui-form-error-margin-top); font-size: var(--secure-ui-error-font-size); color: var(--secure-ui-error-color); line-height: var(--secure-ui-line-height-normal); overflow: hidden; max-height: 40px; opacity: 1; transform: translateY(0); transition: opacity 0.2s ease-out, transform 0.2s ease-out, max-height 0.2s ease-out, margin-top 0.2s ease-out; } .error-container.hidden { max-height: 0; opacity: 0; transform: translateY(-4px); margin-top: 0; } @media (prefers-reduced-motion: reduce) { .select-field, .error-container { transition: none !important; } }'}handleAttributeChange(e,t,i){if(this.#e)switch(e){case"disabled":this.#e.disabled=this.hasAttribute("disabled");break;case"value":i!==this.#e.value&&(this.#e.value=i||"");break}}get value(){return this.#e?this.#a?Array.from(this.#e.selectedOptions).map(e=>e.value).filter(e=>e!==""):this.#e.value:this.#a?[]:""}set value(e){if(this.#e)if(this.#a){let t=Array.isArray(e)?e:e.split(",").map(i=>i.trim()).filter(i=>i!=="");Array.from(this.#e.options).forEach(i=>{i.selected=!1}),t.forEach(i=>{if(this.#r.has(i)){let r=Array.from(this.#e.options).find(s=>s.value===i);r&&(r.selected=!0)}})}else{let t=Array.isArray(e)?e[0]??"":e;this.#r.has(t)&&(this.#e.value=t)}}get name(){return this.#e?this.#e.name:""}get selectedOptions(){return this.#e?Array.from(this.#e.selectedOptions).map(e=>e.value):[]}get valid(){let e=this.hasAttribute("required")||this.config.validation.required;if(this.#a){let i=Array.from(this.#e.selectedOptions).map(r=>r.value).filter(r=>r!=="");return e&&i.length===0?!1:i.every(r=>this.#r.has(r))}if(e&&!this.#e.value)return!1;let t=this.#e.value;return!(t&&!this.#r.has(t))}focus(){this.#e&&this.#e.focus()}blur(){this.#e&&this.#e.blur()}addOption(e,t,i=!1){if(!this.#e)return;let r=document.createElement("option");r.value=this.sanitizeValue(e),r.textContent=this.sanitizeValue(t),r.selected=i,this.#r.add(r.value),this.#e.appendChild(r)}removeOption(e){if(!this.#e)return;let i=Array.from(this.#e.options).find(r=>r.value===e);i&&(this.#e.removeChild(i),this.#r.delete(e))}clearOptions(){this.#e&&(this.#e.innerHTML="",this.#r.clear())}disconnectedCallback(){super.disconnectedCallback()}};customElements.define("secure-select",D);var N=class l extends HTMLElement{static#e=!1;static#t=1e3;#i=null;#n=[];#r=null;#s=null;#a=!1;#o=Date.now();#c={attempts:0,windowStart:Date.now()};#l=`secure-form-${Math.random().toString(36).substring(2,11)}`;#u=u.CRITICAL;static get observedAttributes(){return["security-tier","action","method","enctype","csrf-token","csrf-header-name","csrf-field-name","novalidate"]}constructor(){super()}connectedCallback(){if(this.#i)return;this.#o=Date.now();let e=this.getAttribute("security-tier");e&&A(e)&&(this.#u=e);let t=this.querySelector("form");if(t){this.#i=t,this.#i.id=this.#l,this.#i.classList.contains("secure-form")||this.#i.classList.add("secure-form"),this.#h();let i=this.getAttribute("csrf-field-name")||"csrf_token",r=t.querySelector(`input[name="${CSS.escape(i)}"]`);if(r){this.#r=r;let s=this.getAttribute("csrf-token");s&&r.value!==s&&(r.value=s)}else this.#g()}else{for(this.#i=document.createElement("form"),this.#i.id=this.#l,this.#i.className="secure-form",this.#h(),this.#g();this.firstChild;)this.#i.appendChild(this.firstChild);this.appendChild(this.#i)}this.#s=document.createElement("div"),this.#s.className="form-status form-status-hidden",this.#s.setAttribute("role","status"),this.#s.setAttribute("aria-live","polite"),this.#i.insertBefore(this.#s,this.#i.firstChild),this.#p(),this.#x(),this.audit("form_initialized",{formId:this.#l,action:this.#i.action,method:this.#i.method})}#p(){if(!l.#e){let e='secure-form { display: block; } secure-form .secure-form { padding: 16px; border: 2px solid #e0e0e0; border-radius: 8px; background-color: transparent; } secure-form[security-tier="critical"] .secure-form { padding: 20px; } secure-form[security-tier="public"] .secure-form { border: none; } secure-form .form-status { padding: 12px; margin-bottom: 16px; border-radius: 4px; font-size: 14px; } secure-form .form-status-hidden { display: none; } secure-form .form-status-info { display: block; background-color: #E3F2FD; color: #1976D2; border: 1px solid #1976D2; } secure-form .form-status-success { display: block; background-color: #E8F5E9; color: #388E3C; border: 1px solid #388E3C; } secure-form .form-status-error { display: block; background-color: #FFEBEE; color: #D32F2F; border: 1px solid #D32F2F; } secure-form .secure-form { transition: outline-color 200ms ease, outline-offset 200ms ease; outline: 3px solid transparent; outline-offset: 2px; } secure-form[data-state="success"] .secure-form { outline-color: var(--secure-ui-color-success, #10b981); } secure-form[data-state="blocked"] .secure-form, secure-form[data-state="error"] .secure-form { outline-color: var(--secure-ui-color-error, #ef4444); } @media (prefers-reduced-motion: reduce) { secure-form .secure-form { transition: none; } }';if(e.includes("{")){let t=new CSSStyleSheet;t.replaceSync(e),document.adoptedStyleSheets=[...document.adoptedStyleSheets,t]}else{let t=document.createElement("link");t.rel="stylesheet",t.href=e,document.head.appendChild(t)}l.#e=!0}}#d(e){if(!e)return!0;try{let t=new URL(e,window.location.href);return(t.protocol==="https:"||t.protocol==="http:")&&t.origin===window.location.origin}catch{return!1}}#h(){let e=this.getAttribute("action");e&&(this.#d(e)?this.#i.action=e:(console.warn(`SecureForm: cross-origin or non-http action "${e}" rejected. Forms must submit to the same origin to prevent credential exfiltration.`),this.audit("form_action_rejected",{action:e})));let t=this.getAttribute("method")||"POST";this.#i.method=t.toUpperCase();let i=this.getAttribute("enctype")||"application/x-www-form-urlencoded";this.#i.enctype=i,this.hasAttribute("novalidate")&&(this.#i.noValidate=!0),(this.#u===u.SENSITIVE||this.#u===u.CRITICAL)&&(this.#i.autocomplete="off")}#g(){let e=this.getAttribute("csrf-token");if(e){this.#r=document.createElement("input"),this.#r.type="hidden";let t=this.getAttribute("csrf-field-name")||"csrf_token";this.#r.name=t,this.#r.value=e,this.#i.appendChild(this.#r),this.audit("csrf_token_injected",{formId:this.#l,fieldName:t})}else(this.securityTier===u.SENSITIVE||this.securityTier===u.CRITICAL)&&console.warn("CSRF token not provided for SENSITIVE/CRITICAL tier form")}#x(){this.#i.addEventListener("submit",e=>{this.#v(e)}),this.addEventListener("secure-input-change",e=>{this.#y(e)}),this.addEventListener("secure-textarea-change",e=>{this.#y(e)}),this.addEventListener("secure-select-change",e=>{this.#y(e)}),this.addEventListener("secure-threat-detected",e=>{let t=e.detail;t&&(this.#f.push(t),t.threatType==="injection"&&(this.#L("blocked"),this.#F(t.fieldName,"Injection attempt blocked \u2014 clear this field to submit","error")))})}#y(e){this.#N()}async#v(e){let t=this.hasAttribute("use-fetch");if(this.#a){e.preventDefault();return}(this.#u===u.SENSITIVE||this.#u===u.CRITICAL)&&!this.#r?.value&&this.dispatchEvent(new CustomEvent("secure-threat-detected",{detail:{fieldName:this.#l,threatType:"csrf-token-absent",patternId:"csrf-token-absent",tier:this.#u,timestamp:Date.now()},bubbles:!0,composed:!0}));let i=this.checkRateLimit();if(!i.allowed){e.preventDefault(),this.#T(`Too many submission attempts. Please wait ${Math.ceil(i.retryAfter/1e3)} seconds.`,"error"),this.audit("form_rate_limited",{formId:this.#l,retryAfter:i.retryAfter});return}let r=this.#E();if(!r.valid){e.preventDefault(),this.#T(r.errors.join(", "),"error"),this.audit("form_validation_failed",{formId:this.#l,errors:r.errors});return}if(this.#f.some(c=>c.threatType==="injection")){e.preventDefault(),this.#L("blocked"),this.#T("Submission blocked: injection attempt detected. Clear the highlighted field(s) and try again.","error"),this.audit("form_blocked_injection",{formId:this.#l,count:this.#f.filter(c=>c.threatType==="injection").length});return}if(!t){this.#w(),this.audit("form_submitted_native",{formId:this.#l,action:this.#i.action,method:this.#i.method});return}e.preventDefault(),this.#a=!0,this.#T("Submitting...","info"),this.#M();let n=this.#b(),a=this.#$();this.#I(a.fields),this.audit("form_submitted_enhanced",{formId:this.#l,action:this.#i.action,method:this.#i.method,fieldCount:Object.keys(n).length,riskScore:a.riskScore,riskSignals:a.riskSignals});let o=new CustomEvent("secure-form-submit",{detail:{formData:n,telemetry:a,cancelSubmission:()=>{this.#a=!1,this.#k()}},bubbles:!0,composed:!0,cancelable:!0});if(!this.dispatchEvent(o)){this.#a=!1,this.#k();return}try{await this.#S(n,a),this.#L("success"),this.#m!==null&&clearTimeout(this.#m),this.#m=setTimeout(()=>{this.#L(null),this.#m=null},3e3),this.#D()}catch(c){this.#L("error"),this.#T("Submission failed. Please try again.","error"),this.audit("form_submission_error",{formId:this.#l,error:c.message})}finally{this.#a=!1,this.#k()}}#w(){this.#i.querySelectorAll("secure-input, secure-textarea, secure-select, secure-datetime, secure-file-upload").forEach(t=>{let i=t.getAttribute("name");if(!i)return;let r=CSS.escape(i);t.querySelectorAll(`input[name="${r}"], textarea[name="${r}"], select[name="${r}"]`).forEach(a=>{a.removeAttribute("name")});let n=this.#i.querySelector(`input[type="hidden"][data-secure-input="${i}"]`);n||(n=document.createElement("input"),n.type="hidden",n.setAttribute("data-secure-input",i),n.name=i,this.#i.appendChild(n)),n.value=t.value||""})}#E(){let e=[];return this.#i.querySelectorAll("secure-input, secure-textarea, secure-select, secure-datetime, secure-file-upload").forEach(i=>{if(typeof i.valid=="boolean"&&!i.valid){let r=i.getAttribute("label")||i.getAttribute("name")||"Field";e.push(`${r} is invalid`)}}),{valid:e.length===0,errors:e}}#b(){let e=Object.create(null);return this.#i.querySelectorAll("secure-input, secure-textarea, secure-select, secure-datetime, secure-file-upload").forEach(r=>{let s=r;s.name&&(e[s.name]=s.value)}),this.#i.querySelectorAll('input:not([type="hidden"]), textarea, select').forEach(r=>{let s=r;s.name&&(e[s.name]=this.sanitizeValue(s.value))}),this.#r&&(e[this.#r.name]=this.#r.value),e}#f=[];#m=null;#A=null;async#S(e,t){this.#A?.abort(),this.#A=new AbortController;let i=this.#i.action,r=this.#i.method,s={"Content-Type":"application/json"},n=this.getAttribute("csrf-header-name");n&&this.#r&&(s[n]=this.#r.value);let a={...e,_telemetry:t},o=await fetch(i,{method:r,headers:s,body:JSON.stringify(a),credentials:"same-origin",mode:"cors",cache:"no-cache",redirect:"follow",signal:this.#A.signal});if(!o.ok)throw new Error(`HTTP ${o.status}: ${o.statusText}`);return this.#T("Form submitted successfully!","success"),this.dispatchEvent(new CustomEvent("secure-form-success",{detail:{status:o.status,ok:o.ok,telemetry:t},bubbles:!0,composed:!0})),o}#M(){this.#i.querySelectorAll("input, textarea, select, button").forEach(i=>{i.disabled=!0}),this.querySelectorAll("secure-input, secure-textarea, secure-select, secure-datetime, secure-file-upload").forEach(i=>{i.setAttribute("disabled","")})}#k(){this.#i.querySelectorAll("input, textarea, select, button").forEach(i=>{i.disabled=!1}),this.querySelectorAll("secure-input, secure-textarea, secure-select, secure-datetime, secure-file-upload").forEach(i=>{i.removeAttribute("disabled")})}#T(e,t="info"){this.#s.textContent=e,this.#s.className=`form-status form-status-${t}`}#N(){this.#s.textContent="",this.#s.className="form-status form-status-hidden"}#$(){let t=this.querySelectorAll("secure-input, secure-textarea, secure-select, secure-datetime, secure-card"),i=[];t.forEach(a=>{let o=a;if(typeof o.getFieldTelemetry!="function")return;let d=a.getAttribute("name")??a.tagName.toLowerCase(),c={...o.getFieldTelemetry(),fieldName:d,fieldType:a.tagName.toLowerCase()};i.push(c)});let r=Date.now()-this.#o,{riskScore:s,riskSignals:n}=this.#H(i,r,this.#f);return{sessionDuration:r,fieldCount:i.length,fields:i,riskScore:s,riskSignals:n,submittedAt:new Date().toISOString(),detectedThreats:this.#f.length>0?[...this.#f]:void 0}}#H(e,t,i=[]){let r=[],s=0,n=i.filter(h=>h.threatType==="injection"),a=i.some(h=>h.threatType==="csrf-token-absent");if(n.length>0&&(s+=40,r.push("injection_detected")),a&&(s+=20,r.push("csrf_token_absent")),t<3e3?(s+=30,r.push("session_too_fast")):t<8e3&&(s+=10,r.push("session_fast")),e.length===0)return{riskScore:Math.min(s,100),riskSignals:r};e.every(h=>h.pasteDetected&&h.velocity===0)&&(s+=25,r.push("all_fields_pasted")),e.some(h=>h.velocity>15)&&(s+=15,r.push("high_velocity_typing")),e.some(h=>h.focusCount===0)&&(s+=15,r.push("field_filled_without_focus")),e.some(h=>h.focusCount>1&&h.blurWithoutChange>1)&&(s+=10,r.push("form_probing")),e.some(h=>h.corrections>5)&&(s+=5,r.push("high_correction_count"));let f=e.filter(h=>h.autofillDetected);return f.length>0&&f.length===e.length&&(s-=10,r.push("autofill_detected")),{riskScore:Math.max(0,Math.min(s,100)),riskSignals:r}}#L(e){e===null?delete this.dataset.state:this.dataset.state=e}#D(){this.querySelectorAll("secure-input, secure-textarea, secure-select, secure-datetime, secure-card, secure-file-upload").forEach(t=>{t.clearExternalError?.()})}#F(e,t,i="error"){if(!e)return;this.querySelector(`[name="${CSS.escape(e)}"]`)?.reportError?.(t,i)}#I(e){for(let t of e){let i=null;t.focusCount===0?i="Field was filled without interaction":t.velocity>15?i="Unusually fast input detected":t.pasteDetected&&t.velocity===0?i="Paste-only entry detected":t.focusCount>1&&t.blurWithoutChange>1?i="Repeated focus without entry":t.corrections>5&&(i="Excessive corrections detected"),i!==null&&this.#F(t.fieldName,i,"warning")}}getData(){return this.#b()}reset(){this.#i&&(this.#i.reset(),this.#N(),this.#f=[],this.#m!==null&&(clearTimeout(this.#m),this.#m=null),this.#L(null),this.#D(),this.audit("form_reset",{formId:this.#l}))}submit(){this.#i&&this.#i.dispatchEvent(new Event("submit",{bubbles:!0,cancelable:!0}))}get valid(){return this.#E().valid}disconnectedCallback(){this.#A?.abort(),this.#m!==null&&(clearTimeout(this.#m),this.#m=null),this.#i&&this.#i.reset()}attributeChangedCallback(e,t,i){if(this.#i)switch(e){case"security-tier":console.warn(`SecureForm: security-tier cannot be changed after initialization. Attempted change from "${t}" to "${i}" blocked.`);return;case"action":i&&this.#d(i)?this.#i.action=i:i&&(console.warn(`SecureForm: cross-origin or non-http action "${i}" rejected.`),this.audit("form_action_rejected",{action:i}));break;case"method":this.#i.method=i;break;case"csrf-token":this.#r&&(this.#r.value=i);break}}get securityTier(){return this.#u}sanitizeValue(e){if(typeof e!="string")return"";let t=document.createElement("div");return t.textContent=e,t.innerHTML}audit(e,t){let i=y[this.#u],r={event:e,tier:this.#u,timestamp:new Date().toISOString(),...Object.keys(t).length>0?{data:t}:{},...i.audit.includeMetadata?{userAgent:navigator.userAgent,language:navigator.language}:{}};this.#n.length>=l.#t&&this.#n.shift(),this.#n.push(r),this.dispatchEvent(new CustomEvent("secure-audit",{detail:r,bubbles:!0,composed:!0}))}getAuditLog(){return[...this.#n]}checkRateLimit(){let e=y[this.#u];if(!e.rateLimit.enabled)return{allowed:!0,retryAfter:0};let{maxAttempts:t,windowMs:i}=e.rateLimit,r=Date.now();return r-this.#c.windowStart>i&&(this.#c.attempts=0,this.#c.windowStart=r),this.#c.attempts>=t?{allowed:!1,retryAfter:i-(r-this.#c.windowStart)}:(this.#c.attempts++,{allowed:!0,retryAfter:0})}};customElements.define("secure-form",N);var H=class extends p{#e=null;#t=null;#i=null;#n=null;#r=null;#s=null;#a=null;#o=`secure-file-upload-${Math.random().toString(36).substring(2,11)}`;#c=new Set;#l=5*1024*1024;#u=null;#p=!1;static get observedAttributes(){return[...super.observedAttributes,"name","label","accept","max-size","multiple","required","capture"]}constructor(){super()}render(){let e=document.createDocumentFragment(),t=document.createElement("div");t.className="file-upload-container",t.setAttribute("part","container");let i=this.getAttribute("label");i&&(this.#t=document.createElement("label"),this.#t.htmlFor=this.#o,this.#t.textContent=this.sanitizeValue(i),this.#t.setAttribute("part","label"),t.appendChild(this.#t)),this.#r=document.createElement("div"),this.#r.className="drop-zone",this.#r.setAttribute("part","wrapper"),this.#e=document.createElement("input"),this.#e.type="file",this.#e.id=this.#o,this.#e.className="file-input",this.#e.setAttribute("part","input"),this.#d(),this.#w();let r=document.createElement("div");r.className="drop-zone-content has-name";let s=document.createElement("span");s.className="file-cta";let n=document.createElement("span");n.className="drop-icon";let a=document.createElementNS("http://www.w3.org/2000/svg","svg");a.setAttribute("width","16"),a.setAttribute("height","16"),a.setAttribute("viewBox","0 0 24 24"),a.setAttribute("fill","none"),a.setAttribute("stroke","currentColor"),a.setAttribute("stroke-width","2"),a.setAttribute("stroke-linecap","round"),a.setAttribute("stroke-linejoin","round"),a.setAttribute("aria-hidden","true"),a.setAttribute("focusable","false");let o=document.createElementNS("http://www.w3.org/2000/svg","path");o.setAttribute("d","M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4");let d=document.createElementNS("http://www.w3.org/2000/svg","polyline");d.setAttribute("points","17 8 12 3 7 8");let c=document.createElementNS("http://www.w3.org/2000/svg","line");c.setAttribute("x1","12"),c.setAttribute("y1","3"),c.setAttribute("x2","12"),c.setAttribute("y2","15"),a.appendChild(o),a.appendChild(d),a.appendChild(c),n.appendChild(a),s.appendChild(n);let m=document.createElement("span");m.className="drop-text",m.textContent="Choose a file\u2026",s.appendChild(m),r.appendChild(s),this.#s=document.createElement("span"),this.#s.className="file-name-display",this.#s.textContent="No file selected",r.appendChild(this.#s),this.#r.appendChild(this.#e),this.#r.appendChild(r),t.appendChild(this.#r);let g=document.createElement("div");return g.className="drop-hint",g.textContent=this.#v(),t.appendChild(g),this.#n=document.createElement("div"),this.#n.className="preview-container",t.appendChild(this.#n),this.#i=document.createElement("div"),this.#i.className="error-container hidden",this.#i.setAttribute("role","alert"),this.#i.setAttribute("part","error"),this.#i.id=`${this.#o}-error`,t.appendChild(this.#i),this.#e.setAttribute("aria-describedby",`${this.#o}-error`),this.addComponentStyles(this.#F()),e.appendChild(t),e}#d(){let e=this.config,t=this.getAttribute("name");t&&(this.#e.name=this.sanitizeValue(t));let i=this.getAttribute("accept");if(i)this.#e.accept=i,this.#h(i);else{let n=this.#x();this.#e.accept=n,this.#h(n)}let r=this.getAttribute("max-size");r?this.#l=parseInt(r,10):this.#l=this.#y(),this.hasAttribute("multiple")&&(this.#e.multiple=!0),(this.hasAttribute("required")||e.validation.required)&&(this.#e.required=!0);let s=this.getAttribute("capture");s&&(this.#e.capture=s),this.hasAttribute("disabled")&&(this.#e.disabled=!0)}#h(e){this.#c.clear(),e.split(",").map(i=>i.trim()).forEach(i=>{if(i.startsWith(".")){let r=this.#g(i);r&&this.#c.add(r)}else this.#c.add(i)})}#g(e){return{".pdf":"application/pdf",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".txt":"text/plain",".csv":"text/csv",".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png",".gif":"image/gif",".svg":"image/svg+xml",".zip":"application/zip",".json":"application/json"}[e.toLowerCase()]||null}#x(){switch(this.securityTier){case u.CRITICAL:return".pdf,.txt";case u.SENSITIVE:return".pdf,.doc,.docx,.txt,.jpg,.jpeg,.png";case u.AUTHENTICATED:return".pdf,.doc,.docx,.xls,.xlsx,.txt,.csv,.jpg,.jpeg,.png,.gif";case u.PUBLIC:default:return".pdf,.doc,.docx,.xls,.xlsx,.txt,.csv,.jpg,.jpeg,.png,.gif,.zip"}}#y(){switch(this.securityTier){case u.CRITICAL:return 2*1024*1024;case u.SENSITIVE:return 5*1024*1024;case u.AUTHENTICATED:return 10*1024*1024;case u.PUBLIC:default:return 20*1024*1024}}#v(){let e=(this.#l/1048576).toFixed(1);return`Accepted: ${this.#e.accept||"all files"} (max ${e}MB)`}#w(){this.#e.addEventListener("change",e=>{this.#E(e)}),this.#r.addEventListener("dragover",e=>{e.preventDefault(),e.stopPropagation(),this.#r.classList.add("drag-over")}),this.#r.addEventListener("dragleave",e=>{e.preventDefault(),e.stopPropagation(),this.#r.classList.remove("drag-over")}),this.#r.addEventListener("drop",e=>{e.preventDefault(),e.stopPropagation(),this.#r.classList.remove("drag-over");let t=e;if(!t.dataTransfer)return;let i=t.dataTransfer.files;i.length>0&&(this.#e.files=i,this.#E({target:this.#e}))})}async#E(e){let t=e.target.files;if(!t||t.length===0)return;let i=this.checkRateLimit();if(!i.allowed){this.#L(`Too many upload attempts. Please wait ${Math.ceil(i.retryAfter/1e3)} seconds.`),this.#e.value="";return}this.#D();let r=await this.#b(t);if(!r.valid){this.#L(r.errors.join(", ")),this.#e.value="",this.#a=null;return}this.#a=t,this.#T(t),this.#N(t),this.audit("files_selected",{name:this.#e.name,fileCount:t.length,totalSize:Array.from(t).reduce((s,n)=>s+n.size,0)}),this.dispatchEvent(new CustomEvent("secure-file-change",{detail:{name:this.#e.name,files:Array.from(t),tier:this.securityTier},bubbles:!0,composed:!0}))}async#b(e){let t=[];!this.#e.multiple&&e.length>1&&t.push("Only one file is allowed");for(let i=0;i<e.length;i++){let r=e[i];if(r.size>this.#l){let s=(this.#l/1048576).toFixed(1);t.push(`${r.name}: File size exceeds ${s}MB`);continue}if(this.#c.size>0&&!this.#f(r)){t.push(`${r.name}: File type not allowed`);continue}if(this.#m(r.name)){t.push(`${r.name}: Invalid file name`);continue}if(this.securityTier===u.CRITICAL){let s=await this.#k(r);if(!s.valid){t.push(`${r.name}: ${s.error}`);continue}}if(this.#u){let s=await this.#A(r);if(!s.valid){t.push(`${r.name}: ${s.reason||"Rejected by scan"}`);continue}}}return{valid:t.length===0,errors:t}}#f(e){if(this.#c.has(e.type))return!0;for(let t of this.#c)if(t.endsWith("/*")){let i=t.slice(0,-2);if(e.type.startsWith(i))return!0}return!1}#m(e){return!!(e.includes("..")||e.includes("/")||e.includes("\\")||["web.config",".htaccess",".env","config.php"].includes(e.toLowerCase()))}async#A(e){this.#p=!0,this.#S(e.name),this.audit("scan_started",{name:this.#e?.name??"",fileName:e.name,fileSize:e.size});try{let t=await this.#u(e);return this.audit(t.valid?"scan_passed":"scan_rejected",{name:this.#e?.name??"",fileName:e.name,reason:t.reason??""}),t}catch(t){let i=t instanceof Error?t.message:"Scan failed";return this.audit("scan_error",{name:this.#e?.name??"",fileName:e.name,error:i}),{valid:!1,reason:`Scan error: ${i}`}}finally{this.#p=!1,this.#M()}}#S(e){this.#r&&this.#r.classList.add("scanning"),this.#e&&(this.#e.disabled=!0),this.#s&&(this.#s.textContent=`Scanning ${e}\u2026`)}#M(){this.#r&&this.#r.classList.remove("scanning"),this.#e&&!this.hasAttribute("disabled")&&(this.#e.disabled=!1)}async#k(e){try{let t=await e.slice(0,4).arrayBuffer(),i=new Uint8Array(t),r={"application/pdf":[37,80,68,70],"image/jpeg":[255,216,255],"image/png":[137,80,78,71]};return r[e.type]&&!r[e.type].every((a,o)=>i[o]===a)?{valid:!1,error:"File content does not match declared type"}:{valid:!0}}catch{return{valid:!1,error:"Failed to validate file content"}}}#T(e){this.#s&&(!e||e.length===0?(this.#s.textContent="No file selected",this.#s.classList.remove("has-file")):e.length===1?(this.#s.textContent=e[0].name,this.#s.classList.add("has-file")):(this.#s.textContent=`${e.length} files selected`,this.#s.classList.add("has-file")))}#N(e){this.#n.innerHTML="",Array.from(e).forEach(t=>{let i=document.createElement("div");i.className="file-preview";let r=document.createElement("div");r.className="file-name",r.textContent=t.name;let s=document.createElement("div");s.className="file-size",s.textContent=this.#$(t.size);let n=document.createElement("button");n.className="remove-file",n.textContent="\u2715",n.type="button",n.onclick=()=>{this.#H()},i.appendChild(r),i.appendChild(s),i.appendChild(n),this.#n.appendChild(i)})}#$(e){return e<1024?e+" B":e<1024*1024?(e/1024).toFixed(1)+" KB":(e/(1024*1024)).toFixed(1)+" MB"}#H(){this.#e.value="",this.#a=null,this.#n.innerHTML="",this.#T(null),this.#D(),this.audit("file_removed",{name:this.#e.name})}#L(e){this.#i.textContent=e,this.#i.classList.remove("hidden"),this.#r.classList.add("error")}#D(){this.#i.textContent="",this.#i.classList.add("hidden"),this.#r.classList.remove("error")}#F(){return".file-upload-container { position: relative; margin-bottom: var(--secure-ui-form-gap); font-family: var(--secure-ui-font-family-base); } label { display: block; margin-bottom: var(--secure-ui-form-label-margin-bottom); font-size: var(--secure-ui-label-font-size); font-weight: var(--secure-ui-label-font-weight); color: var(--secure-ui-label-color); } .label-suffix { font-weight: var(--secure-ui-font-weight-normal); color: var(--secure-ui-color-text-secondary); font-size: var(--secure-ui-font-size-xs); margin-left: var(--secure-ui-space-1); } .security-badge { display: inline-block; padding: var(--secure-ui-badge-padding); margin-left: var(--secure-ui-space-2); font-size: var(--secure-ui-badge-font-size); font-weight: var(--secure-ui-font-weight-semibold); border-radius: var(--secure-ui-badge-border-radius); text-transform: uppercase; background-color: var(--secure-ui-color-bg-tertiary); color: var(--secure-ui-color-text-secondary); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); } .drop-zone { position: relative; display: inline-flex; align-items: stretch; justify-content: flex-start; border-radius: var(--secure-ui-input-border-radius); cursor: pointer; width: 100%; } .drop-zone.drag-over { transform: scale(1.01); } .drop-zone.error .file-cta { border-color: var(--secure-ui-color-error); color: var(--secure-ui-color-error); } .file-input { position: absolute; top: 0; left: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; z-index: 1; } .file-input:focus { outline: none; } .drop-zone:focus-within .file-cta { outline: 2px solid var(--secure-ui-color-border-focus); outline-offset: 2px; box-shadow: var(--secure-ui-shadow-focus); } @media (forced-colors: active) { .drop-zone:focus-within .file-cta { outline: 2px solid ButtonText; box-shadow: none; } } .drop-zone-content { display: flex; align-items: stretch; width: 100%; pointer-events: none; } .file-cta { display: flex; align-items: center; justify-content: center; padding: var(--secure-ui-input-padding-y) var(--secure-ui-input-padding-x); background-color: var(--secure-ui-color-bg-secondary); border: var(--secure-ui-input-border-width) solid var(--secure-ui-input-border-color); border-radius: var(--secure-ui-input-border-radius); color: var(--secure-ui-color-text-primary); font-size: var(--secure-ui-input-font-size); font-weight: var(--secure-ui-font-weight-medium); white-space: nowrap; transition: all var(--secure-ui-transition-base) var(--secure-ui-transition-ease-in-out); } .drop-zone:hover .file-cta { background-color: var(--secure-ui-color-bg-tertiary); border-color: var(--secure-ui-input-border-color-hover); } .drop-zone:active .file-cta { background-color: var(--secure-ui-color-bg-tertiary); } .drop-zone.drag-over .file-cta { background-color: var(--secure-ui-color-primary-light, rgba(102, 126, 234, 0.1)); border-color: var(--secure-ui-color-primary); color: var(--secure-ui-color-primary); } .drop-icon { font-size: var(--secure-ui-font-size-base); margin-right: var(--secure-ui-space-2); display: flex; align-items: center; } .drop-text { font-size: var(--secure-ui-font-size-base); } .file-name-display { display: flex; align-items: center; flex: 1; padding: var(--secure-ui-input-padding-y) var(--secure-ui-input-padding-x); border: var(--secure-ui-input-border-width) solid var(--secure-ui-input-border-color); border-left: none; border-radius: 0 var(--secure-ui-input-border-radius) var(--secure-ui-input-border-radius) 0; background-color: var(--secure-ui-input-bg); color: var(--secure-ui-input-placeholder-color); font-size: var(--secure-ui-input-font-size); max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .file-name-display.has-file { color: var(--secure-ui-input-text-color); } .drop-zone-content.has-name .file-cta { border-radius: var(--secure-ui-input-border-radius) 0 0 var(--secure-ui-input-border-radius); border-right: none; } .drop-hint { display: block; text-align: right; margin-top: var(--secure-ui-space-1); font-size: var(--secure-ui-font-size-xs); color: var(--secure-ui-color-text-secondary); } .preview-container { margin-top: var(--secure-ui-space-3); } .file-preview { display: flex; align-items: center; padding: var(--secure-ui-space-3); background-color: var(--secure-ui-color-bg-secondary); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); border-radius: var(--secure-ui-input-border-radius); margin-bottom: var(--secure-ui-space-2); } .file-name { flex: 1; font-size: var(--secure-ui-font-size-sm); color: var(--secure-ui-color-text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .file-size { font-size: var(--secure-ui-font-size-xs); color: var(--secure-ui-color-text-secondary); margin-left: var(--secure-ui-space-3); white-space: nowrap; } .remove-file { background: none; border: none; color: var(--secure-ui-color-error); font-size: var(--secure-ui-font-size-base); cursor: pointer; padding: var(--secure-ui-space-1) var(--secure-ui-space-2); margin-left: var(--secure-ui-space-2); border-radius: var(--secure-ui-border-radius-sm); transition: background-color var(--secure-ui-transition-base) var(--secure-ui-transition-ease-in-out); pointer-events: auto; } .remove-file:hover { background-color: var(--secure-ui-color-error-light, rgba(239, 68, 68, 0.1)); } .error-container { position: absolute; bottom: -1rem; left: 0; display: var(--error-display); margin-top: var(--secure-ui-form-error-margin-top); padding: var(--secure-ui-space-2) var(--secure-ui-space-3); background-color: var(--secure-ui-color-error-light, rgba(239, 68, 68, 0.1)); border-radius: var(--secure-ui-border-radius-sm); color: var(--secure-ui-color-error); font-size: var(--secure-ui-error-font-size); } .error-container.hidden { max-height: 0; opacity: 0; transform: translateY(-4px); margin-top: 0; } .drop-zone.disabled { opacity: var(--secure-ui-input-disabled-opacity); cursor: not-allowed; } .drop-zone.disabled .file-cta { background-color: var(--secure-ui-input-disabled-bg); } .drop-zone.scanning { pointer-events: none; opacity: 0.7; } .drop-zone.scanning .file-cta { border-color: var(--secure-ui-color-primary); } .drop-zone.scanning .file-name-display { color: var(--secure-ui-color-primary); animation: scanning-pulse 1.2s ease-in-out infinite; } @keyframes scanning-pulse { 0%, 100% { opacity: 0.5; } 50% { opacity: 1; } }"}handleAttributeChange(e,t,i){if(this.#e)switch(e){case"disabled":this.#e.disabled=this.hasAttribute("disabled");break;case"accept":this.#e.accept=i,this.#h(i);break}}get files(){return this.#a}get name(){return this.#e?this.#e.name:""}get valid(){return!((this.hasAttribute("required")||this.config.validation.required)&&(!this.#a||this.#a.length===0))}clear(){this.#H()}setScanHook(e){if(typeof e!="function")throw new TypeError("setScanHook expects a function");this.#u=e,this.audit("scan_hook_registered",{name:this.#e?.name??""})}get hasScanHook(){return this.#u!==null}get scanning(){return this.#p}disconnectedCallback(){super.disconnectedCallback(),this.#a=null,this.#e&&(this.#e.value="")}};customElements.define("secure-file-upload",H);var F=class extends p{#e=null;#t=null;#i=null;#n=null;#r=`secure-datetime-${Math.random().toString(36).substring(2,11)}`;static get observedAttributes(){return[...super.observedAttributes,"name","type","label","required","min","max","step","value","show-timezone"]}constructor(){super()}render(){let e=document.createDocumentFragment(),t=document.createElement("div");t.className="datetime-container",t.setAttribute("part","container");let i=this.getAttribute("label");i&&(this.#t=document.createElement("label"),this.#t.htmlFor=this.#r,this.#t.textContent=this.sanitizeValue(i),this.#t.setAttribute("part","label"),t.appendChild(this.#t));let r=document.createElement("div");return r.className="input-wrapper",r.setAttribute("part","wrapper"),this.#e=document.createElement("input"),this.#e.id=this.#r,this.#e.className="datetime-field",this.#e.setAttribute("part","input"),this.#s(),this.#c(),r.appendChild(this.#e),this.hasAttribute("show-timezone")&&(this.#n=document.createElement("span"),this.#n.className="timezone-display",this.#n.textContent=this.#o(),r.appendChild(this.#n)),t.appendChild(r),this.#i=document.createElement("div"),this.#i.className="error-container hidden",this.#i.setAttribute("role","alert"),this.#i.setAttribute("part","error"),this.#i.id=`${this.#r}-error`,t.appendChild(this.#i),this.addComponentStyles(this.#x()),e.appendChild(t),e}#s(){let e=this.config,t=this.getAttribute("name");t&&(this.#e.name=this.sanitizeValue(t)),!this.getAttribute("label")&&t&&this.#e.setAttribute("aria-label",this.sanitizeValue(t)),this.#e.setAttribute("aria-describedby",`${this.#r}-error`),this.#n&&this.#n.setAttribute("aria-label",`Timezone: ${this.#o()}`);let i=this.getAttribute("type")||"date";["date","time","datetime-local","month","week"].includes(i)?this.#e.type=i:(console.warn(`Invalid datetime type "${i}", defaulting to "date"`),this.#e.type="date"),(this.hasAttribute("required")||e.validation.required)&&(this.#e.required=!0,this.#e.setAttribute("aria-required","true"));let s=this.getAttribute("min");s&&(this.#e.min=this.#a(s));let n=this.getAttribute("max");n&&(this.#e.max=this.#a(n));let a=this.getAttribute("step");a&&(this.#e.step=a),this.hasAttribute("disabled")&&(this.#e.disabled=!0),this.hasAttribute("readonly")&&(this.#e.readOnly=!0),e.storage.allowAutocomplete||(this.#e.autocomplete="off");let o=this.getAttribute("value");o&&(this.#e.value=this.#a(o))}#a(e){if(!e)return"";let t=this.#e?.type||this.getAttribute("type")||"date",i={date:/^\d{4}-\d{2}-\d{2}$/,time:/^\d{2}:\d{2}(:\d{2})?$/,"datetime-local":/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2})?$/,month:/^\d{4}-\d{2}$/,week:/^\d{4}-W\d{2}$/},r=Object.hasOwn(i,t)?i[t]:void 0;return r&&!r.test(e)?(console.warn(`Invalid ${t} format: ${e}`),""):e}#o(){let e=new Date().getTimezoneOffset(),t=Math.abs(Math.floor(e/60)),i=Math.abs(e%60);return`UTC${e<=0?"+":"-"}${t.toString().padStart(2,"0")}:${i.toString().padStart(2,"0")}`}#c(){this.setupAutofillDetection(this.#e),this.#e.addEventListener("focus",()=>{this.recordTelemetryFocus(),this.audit("datetime_focused",{name:this.#e.name,type:this.#e.type})}),this.#e.addEventListener("input",e=>{this.recordTelemetryInput(e),this.#l(e)}),this.#e.addEventListener("change",e=>{this.#u(e)}),this.#e.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#p(),this.audit("datetime_blurred",{name:this.#e.name,hasValue:this.#e.value.length>0})})}#l(e){this.#g(),this.dispatchEvent(new CustomEvent("secure-datetime-change",{detail:{name:this.#e.name,value:this.#e.value,type:this.#e.type,tier:this.securityTier},bubbles:!0,composed:!0}))}#u(e){let t=this.#e.value;if(!this.#a(t)&&t){this.#h("Invalid date/time format");return}this.#g(),this.audit("datetime_changed",{name:this.#e.name,type:this.#e.type,value:t})}#p(){let e=this.checkRateLimit();if(!e.allowed){this.#h(`Too many attempts. Please wait ${Math.ceil(e.retryAfter/1e3)} seconds.`);return}let t=this.#e.value;if(this.#e.required&&!t){this.#h("This field is required");return}if(t){if(this.#e.min&&t<this.#e.min){this.#h(`Value must be after ${this.#d(this.#e.min)}`);return}if(this.#e.max&&t>this.#e.max){this.#h(`Value must be before ${this.#d(this.#e.max)}`);return}}if(this.securityTier===u.CRITICAL&&t){let i=new Date(t);if(isNaN(i.getTime())){this.#h("Invalid date/time");return}let r=i.getFullYear();if(r<1900||r>2100){this.#h("Date must be between 1900 and 2100");return}}}#d(e){try{return new Date(e).toLocaleString()}catch{return e}}#h(e){this.#i.textContent=e,this.#i.offsetHeight,this.#i.classList.remove("hidden"),this.#e.classList.add("error"),this.#e.setAttribute("aria-invalid","true")}#g(){this.#i.classList.add("hidden"),this.#i.addEventListener("transitionend",()=>{this.#i.classList.contains("hidden")&&(this.#i.textContent="")},{once:!0}),this.#e.classList.remove("error"),this.#e.removeAttribute("aria-invalid")}#x(){return`.datetime-container { margin-bottom: var(--secure-ui-form-gap); font-family: var(--secure-ui-font-family-base); } label { display: block; margin-bottom: var(--secure-ui-form-label-margin-bottom); font-size: var(--secure-ui-label-font-size); font-weight: var(--secure-ui-label-font-weight); color: var(--secure-ui-label-color); } .label-suffix { font-weight: var(--secure-ui-font-weight-normal); color: var(--secure-ui-color-text-secondary); font-size: var(--secure-ui-font-size-xs); margin-left: var(--secure-ui-space-1); } .security-badge { display: inline-block; padding: var(--secure-ui-badge-padding); margin-left: var(--secure-ui-space-2); font-size: var(--secure-ui-badge-font-size); font-weight: var(--secure-ui-font-weight-semibold); border-radius: var(--secure-ui-badge-border-radius); text-transform: uppercase; background-color: var(--secure-ui-color-bg-tertiary); color: var(--secure-ui-color-text-secondary); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); } .input-wrapper { position: relative; } .datetime-field { width: 100%; height: var(--secure-ui-input-height); padding: var(--secure-ui-input-padding-y) var(--secure-ui-input-padding-x); font-family: var(--secure-ui-font-family-base); font-size: var(--secure-ui-input-font-size); line-height: var(--secure-ui-line-height-normal); color: var(--secure-ui-input-text-color); background-color: var(--secure-ui-input-bg); border: var(--secure-ui-input-border-width) solid var(--secure-ui-input-border-color); border-radius: var(--secure-ui-input-border-radius); transition: all var(--secure-ui-transition-base) var(--secure-ui-transition-ease-in-out); cursor: pointer; box-sizing: border-box; } .datetime-field::placeholder { color: var(--secure-ui-input-placeholder-color); } .datetime-field:hover:not(:disabled):not([readonly]) { border-color: var(--secure-ui-input-border-color-hover); } .datetime-field:focus { outline: none; border-color: var(--secure-ui-input-border-color-focus); box-shadow: var(--secure-ui-shadow-focus); } .datetime-field.error { border-color: var(--secure-ui-color-error); } .datetime-field.error:focus { box-shadow: var(--secure-ui-shadow-focus-error); } .datetime-field:disabled { background-color: var(--secure-ui-input-disabled-bg); cursor: not-allowed; opacity: var(--secure-ui-input-disabled-opacity); } .datetime-field[readonly] { background-color: var(--secure-ui-color-bg-secondary); cursor: default; } .input-wrapper::after { content: '\u{1F4C5}' / ''; position: absolute; right: var(--secure-ui-space-3); top: 50%; transform: translateY(-50%); pointer-events: none; font-size: var(--secure-ui-font-size-lg); color: var(--secure-ui-color-text-secondary); } .input-wrapper[data-type="time"]::after { content: '\u{1F550}' / ''; } .input-wrapper[data-type="datetime-local"]::after { content: '\u{1F4C5}' / ''; } .input-wrapper[data-type="month"]::after { content: '\u{1F4C6}' / ''; } .input-wrapper[data-type="week"]::after { content: '\u{1F4C5}' / ''; } .input-wrapper .timezone-display { position: absolute; right: 0; bottom: -1.25rem; } .range-display { display: none; margin-top: var(--secure-ui-space-2); padding: var(--secure-ui-space-2) var(--secure-ui-space-3); background-color: var(--secure-ui-color-bg-secondary); border-radius: var(--secure-ui-border-radius-sm); font-size: var(--secure-ui-font-size-xs); color: var(--secure-ui-color-text-secondary); } .range-display.visible { display: block; } .range-item { margin-bottom: var(--secure-ui-space-1); } .range-item:last-child { margin-bottom: 0; } .range-label { font-weight: var(--secure-ui-font-weight-medium); margin-right: var(--secure-ui-space-1); } .helper-text { margin-top: var(--secure-ui-space-2); font-size: var(--secure-ui-font-size-xs); color: var(--secure-ui-color-text-secondary); line-height: var(--secure-ui-line-height-normal); } .error-container { position: absolute; margin-top: var(--secure-ui-form-error-margin-top); font-size: var(--secure-ui-error-font-size); color: var(--secure-ui-error-color); line-height: var(--secure-ui-line-height-normal); overflow: hidden; max-height: 40px; opacity: 1; transform: translateY(0); transition: opacity 0.2s ease-out, transform 0.2s ease-out, max-height 0.2s ease-out, margin-top 0.2s ease-out; } .error-container.hidden { max-height: 0; opacity: 0; transform: translateY(-4px); margin-top: 0; } @media (prefers-reduced-motion: reduce) { .datetime-field, .error-container { transition: none !important; } } .datetime-field::-webkit-calendar-picker-indicator { display: inline-block; cursor: pointer; opacity: 1; padding: 4px; margin-left: 4px; } .datetime-field:disabled::-webkit-calendar-picker-indicator { cursor: not-allowed; opacity: 0.3; } .datetime-field::-webkit-inner-spin-button { height: auto; opacity: 0.6; cursor: pointer; } .datetime-field:valid:not(:placeholder-shown):not(:focus) { border-color: var(--secure-ui-color-success); } .datetime-field:invalid:not(:placeholder-shown):not(:focus) { border-color: var(--secure-ui-color-error); } .datetime-container:focus-within label { color: var(--secure-ui-color-primary); } .datetime-container.disabled { opacity: var(--secure-ui-input-disabled-opacity); } .datetime-container.disabled label { color: var(--secure-ui-color-text-disabled); } label .required { color: var(--secure-ui-color-error); margin-left: var(--secure-ui-space-1); }`}handleAttributeChange(e,t,i){if(this.#e)switch(e){case"disabled":this.#e.disabled=this.hasAttribute("disabled");break;case"readonly":this.#e.readOnly=this.hasAttribute("readonly");break;case"value":i!==this.#e.value&&(this.#e.value=this.#a(i||""));break;case"min":this.#e.min=this.#a(i||"");break;case"max":this.#e.max=this.#a(i||"");break}}get value(){return this.#e?this.#e.value:""}set value(e){this.#e&&(this.#e.value=this.#a(e||""))}get name(){return this.#e?this.#e.name:""}getValueAsDate(){if(!this.#e||!this.#e.value)return null;try{let e=new Date(this.#e.value);return isNaN(e.getTime())?null:e}catch{return null}}setValueFromDate(e){if(!this.#e||!(e instanceof Date))return;let t=this.#e.type,i="";switch(t){case"date":i=e.toISOString().split("T")[0];break;case"time":i=e.toTimeString().slice(0,5);break;case"datetime-local":i=e.toISOString().slice(0,16);break;case"month":i=e.toISOString().slice(0,7);break;case"week":let r=new Date(e);r.setHours(0,0,0,0),r.setDate(r.getDate()+4-(r.getDay()||7));let s=new Date(r.getFullYear(),0,1),n=Math.ceil(((r.getTime()-s.getTime())/864e5+1)/7);i=`${r.getFullYear()}-W${n.toString().padStart(2,"0")}`;break}this.#e.value=i}get valid(){let e=this.hasAttribute("required")||this.config.validation.required,t=this.#e?this.#e.value:"";return!(e&&!t||t&&!this.#a(t)||this.#e&&(this.#e.min&&t<this.#e.min||this.#e.max&&t>this.#e.max))}focus(){this.#e&&this.#e.focus()}blur(){this.#e&&this.#e.blur()}disconnectedCallback(){super.disconnectedCallback(),this.#e&&(this.#e.value="")}};customElements.define("secure-datetime",F);var $=class l extends p{#e=[];#t=[];#i=[];#n="";#r={column:null,direction:"asc"};#s={currentPage:1,pageSize:10};#a=!1;constructor(){super()}render(){return null}connectedCallback(){this.initializeSecurity();let e=this.querySelector('table[slot="table"]'),t=this.#o();t&&(this.#a=!0,this.#t=t.columns,this.#e=t.data,this.#i=[...t.data],e&&e.remove()),this.#b(),this.audit("table_mounted",{rowCount:this.#e.length,columnCount:this.#t.length,usingSlottedContent:this.#a})}#o(){let e=this.querySelector('table[slot="table"]');if(!e)return null;try{let t=e.querySelectorAll("thead th");if(t.length===0)return null;let i=Array.from(t).map(n=>({key:n.getAttribute("data-key")||n.textContent.trim().toLowerCase().replace(/\s+/g,"_"),label:n.textContent.trim().replace(/\s+$/,""),sortable:n.hasAttribute("data-sortable")?n.getAttribute("data-sortable")!=="false":!0,filterable:n.hasAttribute("data-filterable")?n.getAttribute("data-filterable")!=="false":void 0,tier:n.getAttribute("data-tier")||void 0,width:n.getAttribute("data-width")||void 0,render:n.hasAttribute("data-render-html")?this.#c(n):void 0})),r=e.querySelectorAll("tbody tr"),s=Array.from(r).map((n,a)=>{let o=n.querySelectorAll("td"),d=Object.create(null);return o.forEach((c,m)=>{if(m<i.length){let g=i[m],f=c.getAttribute("data-key")||g.key;if(f==="__proto__"||f==="constructor"||f==="prototype")return;c.innerHTML.trim().includes("<")?(d[f]=c.textContent?.trim()??"",d[`${f}_html`]=c.innerHTML.trim()):d[f]=c.textContent?.trim()??""}}),d});return{columns:i,data:s}}catch(t){return console.error("SecureTable: Error parsing slotted table",t),null}}#c(e){return(t,i,r)=>{let s=`${r}_html`,n=Object.hasOwn(i,s)?i[s]:null;return n?this.#x(n):this.#d(t)}}set data(e){Array.isArray(e)&&(this.#e=e,this.#i=[...e],this.#b())}get data(){return this.#e}set columns(e){Array.isArray(e)&&(this.#t=e,this.#b())}get columns(){return this.#t}#l(e){this.#n=e.toLowerCase(),this.#n?this.#i=this.#e.filter(t=>this.#t.some(i=>i.filterable===!1?!1:String(t[i.key]??"").toLowerCase().includes(this.#n))):this.#i=[...this.#e],this.#s.currentPage=1,this.#f(),this.audit("table_filtered",{filterTerm:e,resultCount:this.#i.length})}#u(e){this.#r.column===e?this.#r.direction=this.#r.direction==="asc"?"desc":"asc":(this.#r.column=e,this.#r.direction="asc"),this.#i.sort((t,i)=>{let r=Object.hasOwn(t,e)?t[e]:void 0,s=Object.hasOwn(i,e)?i[e]:void 0,n=r==null,a=s==null;if(n&&a)return 0;if(n)return 1;if(a)return-1;let o=typeof r=="number"?r:String(r),d=typeof s=="number"?s:String(s),c=0;return o>d?c=1:o<d&&(c=-1),this.#r.direction==="asc"?c:-c}),this.#f(),this.audit("table_sorted",{column:e,direction:this.#r.direction})}#p(e){let t=Math.ceil(this.#i.length/this.#s.pageSize);e<1||e>t||(this.#s.currentPage=e,this.#f())}#d(e){return e==null||e===""?"":String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}static#h=new Set(["a","abbr","b","br","button","code","em","i","s","small","span","strong","time","u"]);static#g=new Set(["class","href","title","aria-label","aria-hidden","type","datetime"]);#x(e){if(!e)return"";let t=new DOMParser().parseFromString(`<!DOCTYPE html><body>${e}`,"text/html");return this.#y(t.body),t.body.innerHTML}#y(e){for(let t of Array.from(e.childNodes)){if(t.nodeType===Node.TEXT_NODE)continue;if(t.nodeType!==Node.ELEMENT_NODE){e.removeChild(t);continue}let i=t,r=i.tagName.toLowerCase();if(!l.#h.has(r)){let s=document.createDocumentFragment();for(;i.firstChild;)s.appendChild(i.firstChild);e.replaceChild(s,i);continue}for(let s of Array.from(i.attributes)){let n=s.name.toLowerCase();if(n.startsWith("on")){i.removeAttribute(s.name);continue}if((n==="href"||n==="src"||n==="action")&&/^\s*(javascript|data)\s*:/i.test(s.value)){i.removeAttribute(s.name);continue}!l.#g.has(n)&&!n.startsWith("data-")&&i.removeAttribute(s.name)}this.#y(i)}}#v(e,t){if(e==null||e==="")return"-";let i=String(e);return t===u.SENSITIVE&&i.length>4?"\u2022".repeat(i.length-4)+i.slice(-4):t===u.CRITICAL?"\u2022".repeat(i.length):this.#d(i)}#w(e,t,i){if(typeof i.render=="function")return this.#x(i.render(e,t,i.key));let r=`${i.key}_html`;return Object.hasOwn(t,r)&&t[r]?this.#x(t[r]):this.#v(e,i.tier)}#E(){let e=Math.ceil(this.#i.length/this.#s.pageSize),t=(this.#s.currentPage-1)*this.#s.pageSize,i=t+this.#s.pageSize,r=this.#i.slice(t,i),s,n;if(r.length===0||this.#t.length===0){let a=this.#t.length===0?"No columns configured":"No results found",o=this.#t.length===0?"Set the columns property to configure the table":"Try adjusting your search term";s=`
|
|
2
2
|
<div class="empty-state">
|
|
3
3
|
<div class="empty-state-icon" aria-hidden="true">\u{1F50D}</div>
|
|
4
|
-
<h3>${this.#
|
|
5
|
-
<p>${this.#
|
|
4
|
+
<h3>${this.#d(a)}</h3>
|
|
5
|
+
<p>${this.#d(o)}</p>
|
|
6
6
|
</div>`,n=""}else s=`
|
|
7
7
|
<div class="table-wrapper">
|
|
8
8
|
<table class="data-table">
|
|
@@ -11,12 +11,12 @@ var u=Object.freeze({PUBLIC:"public",AUTHENTICATED:"authenticated",SENSITIVE:"se
|
|
|
11
11
|
${this.#t.map(a=>{let o=this.#r.column===a.key,d=o?this.#r.direction==="asc"?"\u25B2":"\u25BC":"\u25B2",c=a.sortable!==!1?`aria-sort="${o?this.#r.direction==="asc"?"ascending":"descending":"none"}"`:"";return`
|
|
12
12
|
<th
|
|
13
13
|
class="${a.sortable!==!1?"sortable":""} ${o?"sorted":""}"
|
|
14
|
-
data-column="${this.#
|
|
14
|
+
data-column="${this.#d(a.key)}"
|
|
15
15
|
${c}
|
|
16
16
|
>
|
|
17
|
-
${this.#
|
|
17
|
+
${this.#d(a.label)}
|
|
18
18
|
${a.sortable!==!1?`<span class="sort-indicator" aria-hidden="true">${d}</span>`:""}
|
|
19
|
-
${a.tier?`<span class="security-badge" aria-hidden="true">${this.#
|
|
19
|
+
${a.tier?`<span class="security-badge" aria-hidden="true">${this.#d(a.tier)}</span>`:""}
|
|
20
20
|
</th>`}).join("")}
|
|
21
21
|
</tr>
|
|
22
22
|
</thead>
|
|
@@ -24,7 +24,7 @@ var u=Object.freeze({PUBLIC:"public",AUTHENTICATED:"authenticated",SENSITIVE:"se
|
|
|
24
24
|
${r.map(a=>`
|
|
25
25
|
<tr>
|
|
26
26
|
${this.#t.map(o=>`
|
|
27
|
-
<td>${this.#
|
|
27
|
+
<td>${this.#w(a[o.key],a,o)}</td>
|
|
28
28
|
`).join("")}
|
|
29
29
|
</tr>
|
|
30
30
|
`).join("")}
|
|
@@ -36,34 +36,34 @@ var u=Object.freeze({PUBLIC:"public",AUTHENTICATED:"authenticated",SENSITIVE:"se
|
|
|
36
36
|
Showing ${t+1}-${Math.min(i,this.#i.length)} of ${this.#i.length} results
|
|
37
37
|
</div>
|
|
38
38
|
<div class="pagination-controls">
|
|
39
|
-
<button class="pagination-button" id="prevBtn" ${this.#
|
|
39
|
+
<button class="pagination-button" id="prevBtn" ${this.#s.currentPage===1?"disabled":""}>
|
|
40
40
|
\u2190 Previous
|
|
41
41
|
</button>
|
|
42
|
-
${this.#
|
|
43
|
-
<button class="pagination-button" id="nextBtn" ${this.#
|
|
42
|
+
${this.#m(e)}
|
|
43
|
+
<button class="pagination-button" id="nextBtn" ${this.#s.currentPage===e?"disabled":""}>
|
|
44
44
|
Next \u2192
|
|
45
45
|
</button>
|
|
46
46
|
</div>
|
|
47
|
-
</div>`:"";return{tableHtml:s,paginationHtml:n}}#
|
|
47
|
+
</div>`:"";return{tableHtml:s,paginationHtml:n}}#b(){if(!this.shadowRoot)return;let{tableHtml:e,paginationHtml:t}=this.#E();this.shadowRoot.innerHTML="",this.addComponentStyles(this.getBaseStylesheetUrl()),this.addComponentStyles(':host { display: block; font-family: var(--secure-ui-font-family-base); } .table-container { background: var(--secure-ui-color-bg-primary); border-radius: var(--secure-ui-border-radius-lg); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); overflow: hidden; } .table-header { display: flex; justify-content: space-between; align-items: center; padding: var(--secure-ui-space-4); background-color: var(--secure-ui-color-bg-secondary); border-bottom: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); gap: var(--secure-ui-space-3); flex-wrap: wrap; } .table-title { font-size: var(--secure-ui-font-size-lg); font-weight: var(--secure-ui-font-weight-semibold); color: var(--secure-ui-color-text-primary); margin: 0; } .table-controls { display: flex; gap: var(--secure-ui-space-3); align-items: center; } .search-input { padding: var(--secure-ui-space-2) var(--secure-ui-space-3); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); border-radius: var(--secure-ui-border-radius-base); font-size: var(--secure-ui-font-size-sm); font-family: var(--secure-ui-font-family-base); color: var(--secure-ui-color-text-primary); background-color: var(--secure-ui-color-bg-primary); min-width: 200px; transition: all var(--secure-ui-transition-base) var(--secure-ui-transition-ease-in-out); } .search-input:focus { outline: none; border-color: var(--secure-ui-color-primary); box-shadow: var(--secure-ui-shadow-focus); } .search-input::placeholder { color: var(--secure-ui-color-text-secondary); } .table-wrapper { overflow-x: auto; overflow-y: visible; } .data-table { width: 100%; border-collapse: collapse; font-size: var(--secure-ui-font-size-sm); color: var(--secure-ui-table-font-color); } .data-table thead { background-color: var(--secure-ui-color-bg-tertiary); border-bottom: var(--secure-ui-border-width-base) solid var(--secure-ui-color-border); } .data-table th { padding: var(--secure-ui-space-3) var(--secure-ui-space-4); text-align: left; font-weight: var(--secure-ui-font-weight-semibold); color: var(--secure-ui-color-text-primary); white-space: nowrap; position: relative; } .data-table th.sortable { cursor: pointer; user-select: none; transition: background-color var(--secure-ui-transition-fast) var(--secure-ui-transition-ease-in-out); } .data-table th.sortable:hover { background-color: var(--secure-ui-color-bg-secondary); } .data-table th.sorted { color: var(--secure-ui-color-primary); } .sort-indicator { display: inline-block; margin-left: var(--secure-ui-space-1); font-size: var(--secure-ui-font-size-xs); opacity: 0.5; transition: opacity var(--secure-ui-transition-fast) var(--secure-ui-transition-ease-in-out); } .data-table th.sorted .sort-indicator { opacity: 1; } .data-table tbody tr { border-bottom: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); transition: background-color var(--secure-ui-transition-fast) var(--secure-ui-transition-ease-in-out); } .data-table tbody tr:hover { background-color: var(--secure-ui-color-bg-secondary); } .data-table tbody tr:last-child { border-bottom: none; } .data-table td { padding: var(--secure-ui-space-3) var(--secure-ui-space-4); color: var(--secure-ui-color-text-primary); vertical-align: middle; } .masked-cell { font-family: var(--secure-ui-font-family-mono); color: var(--secure-ui-color-text-secondary); letter-spacing: 0.1em; } .empty-state { padding: var(--secure-ui-space-8) var(--secure-ui-space-4); text-align: center; color: var(--secure-ui-color-text-secondary); } .empty-state-icon { font-size: var(--secure-ui-font-size-3xl); margin-bottom: var(--secure-ui-space-2); } .empty-state-text { font-size: var(--secure-ui-font-size-base); margin: 0; } .pagination { display: flex; justify-content: space-between; align-items: center; padding: var(--secure-ui-space-4); background-color: var(--secure-ui-color-bg-secondary); border-top: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); gap: var(--secure-ui-space-3); flex-wrap: wrap; } .pagination-info { font-size: var(--secure-ui-font-size-sm); color: var(--secure-ui-color-text-secondary); } .pagination-controls { display: flex; gap: var(--secure-ui-space-2); } .pagination-button { padding: var(--secure-ui-space-2) var(--secure-ui-space-3); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); border-radius: var(--secure-ui-border-radius-base); background-color: var(--secure-ui-color-bg-primary); color: var(--secure-ui-color-text-primary); font-size: var(--secure-ui-font-size-sm); font-family: var(--secure-ui-font-family-base); cursor: pointer; transition: all var(--secure-ui-transition-base) var(--secure-ui-transition-ease-in-out); } .pagination-button:hover:not(:disabled) { background-color: var(--secure-ui-color-primary); color: var(--secure-ui-color-text-inverse); border-color: var(--secure-ui-color-primary); } .pagination-button:disabled { opacity: var(--secure-ui-input-disabled-opacity); cursor: not-allowed; } .pagination-button.active { background-color: var(--secure-ui-color-primary); color: var(--secure-ui-color-text-inverse); border-color: var(--secure-ui-color-primary); } .page-size-selector { display: flex; align-items: center; gap: var(--secure-ui-space-2); font-size: var(--secure-ui-font-size-sm); color: var(--secure-ui-color-text-secondary); } .page-size-select { padding: var(--secure-ui-space-1) var(--secure-ui-space-2); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); border-radius: var(--secure-ui-border-radius-base); background-color: var(--secure-ui-color-bg-primary); color: var(--secure-ui-color-text-primary); font-size: var(--secure-ui-font-size-sm); font-family: var(--secure-ui-font-family-base); cursor: pointer; } .loading-overlay { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(255, 255, 255, 0.8); display: flex; justify-content: center; align-items: center; z-index: var(--secure-ui-z-sticky); } .loading-spinner { width: 40px; height: 40px; border: 4px solid var(--secure-ui-color-border); border-top-color: var(--secure-ui-color-primary); border-radius: 50%; animation: spin 0.8s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } :host([security-tier="authenticated"]) .table-container { border-top: var(--secure-ui-border-width-thick) solid var(--secure-ui-tier-authenticated); } :host([security-tier="sensitive"]) .table-container { border-top: var(--secure-ui-border-width-thick) solid var(--secure-ui-tier-sensitive); } :host([security-tier="critical"]) .table-container { border-top: var(--secure-ui-border-width-thick) solid var(--secure-ui-tier-critical); } .security-badge { display: inline-block; padding: var(--secure-ui-badge-padding); margin-left: var(--secure-ui-space-2); font-size: var(--secure-ui-badge-font-size); font-weight: var(--secure-ui-font-weight-semibold); border-radius: var(--secure-ui-badge-border-radius); text-transform: uppercase; background-color: var(--secure-ui-color-bg-tertiary); color: var(--secure-ui-color-text-secondary); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); } @media (max-width: 768px) { .table-header { flex-direction: column; align-items: stretch; } .table-controls { flex-direction: column; width: 100%; } .search-input { width: 100%; min-width: auto; } .pagination { flex-direction: column; align-items: stretch; } .pagination-controls { justify-content: center; } .table-wrapper { position: relative; background: linear-gradient(to right, var(--secure-ui-color-bg-primary) 0%, transparent 100%) left, linear-gradient(to left, var(--secure-ui-color-bg-primary) 0%, transparent 100%) right, radial-gradient(farthest-side at 0 50%, rgba(0,0,0,.12), transparent) left, radial-gradient(farthest-side at 100% 50%, rgba(0,0,0,.12), transparent) right; background-repeat: no-repeat; background-size: 32px 100%, 32px 100%, 10px 100%, 10px 100%; background-attachment: local, local, scroll, scroll; } } .data-table tbody tr:nth-child(even) { background-color: rgba(0, 0, 0, 0.01); } .data-table tbody tr:nth-child(even):hover { background-color: var(--secure-ui-color-bg-secondary); }');let i=document.createElement("slot");i.name="table",this.shadowRoot.appendChild(i);let r=document.createElement("div");r.className="table-container",r.innerHTML=`
|
|
48
48
|
<div class="table-header">
|
|
49
49
|
<input
|
|
50
50
|
type="search"
|
|
51
51
|
class="search-input"
|
|
52
52
|
placeholder="Search across all columns..."
|
|
53
|
-
value="${this.#
|
|
53
|
+
value="${this.#d(this.#n)}"
|
|
54
54
|
id="searchInput"
|
|
55
55
|
/>
|
|
56
56
|
</div>
|
|
57
57
|
<div id="tableContent">${e}</div>
|
|
58
58
|
<div id="paginationContent">${t}</div>
|
|
59
|
-
`,this.shadowRoot.appendChild(r),this.#A()}#
|
|
59
|
+
`,this.shadowRoot.appendChild(r),this.#A()}#f(){if(!this.shadowRoot)return;let e=this.shadowRoot.getElementById("tableContent"),t=this.shadowRoot.getElementById("paginationContent");if(!e){this.#b();return}let{tableHtml:i,paginationHtml:r}=this.#E();e.innerHTML=i,t&&(t.innerHTML=r),this.#S()}#m(e){let i=Math.max(1,this.#s.currentPage-Math.floor(2.5)),r=Math.min(e,i+5-1);r-i<4&&(i=Math.max(1,r-5+1));let s="";for(let n=i;n<=r;n++)s+=`
|
|
60
60
|
<button
|
|
61
|
-
class="pagination-button ${n===this.#
|
|
61
|
+
class="pagination-button ${n===this.#s.currentPage?"active":""}"
|
|
62
62
|
data-page="${n}"
|
|
63
63
|
>
|
|
64
64
|
${n}
|
|
65
65
|
</button>
|
|
66
|
-
`;return s}#A(){let e=this.shadowRoot.getElementById("searchInput");e&&e.addEventListener("input",t=>{this.#c(t.target.value)}),this.#C()}#C(){this.shadowRoot.querySelectorAll("th.sortable").forEach(n=>{n.addEventListener("click",()=>{let a=n.getAttribute("data-column");a&&this.#d(a)})});let t=this.shadowRoot.getElementById("prevBtn"),i=this.shadowRoot.getElementById("nextBtn");t&&t.addEventListener("click",()=>{this.#p(this.#n.currentPage-1)}),i&&i.addEventListener("click",()=>{this.#p(this.#n.currentPage+1)}),this.shadowRoot.querySelectorAll(".pagination-button[data-page]").forEach(n=>{n.addEventListener("click",()=>{let a=parseInt(n.getAttribute("data-page"),10);this.#p(a)})});let s=this.shadowRoot.getElementById("tableContent");s&&s.addEventListener("click",n=>{let a=n.target.closest("[data-action]");if(!a)return;let o=a.getAttribute("data-action"),d=Object.create(null);d.action=o;for(let c of Array.from(a.attributes))if(c.name.startsWith("data-")&&c.name!=="data-action"){let m=c.name.slice(5).replace(/-([a-z])/g,(g,f)=>f.toUpperCase());if(m==="__proto__"||m==="constructor"||m==="prototype")continue;d[m]=c.value}this.dispatchEvent(new CustomEvent("secure-table-action",{bubbles:!0,composed:!0,detail:d})),this.audit("table_action",d)})}};customElements.define("secure-table",$);function _(l){if(l===null)return!1;let e=l;return typeof e.securityTier=="string"&&typeof e.valid=="boolean"&&typeof e.submit=="function"}var R=class extends p{#e=null;#t=null;#i=null;#s=null;#r=!1;#n=!1;#o="critical";#a;#l=`secure-submit-button-${Math.random().toString(36).substring(2,11)}`;#c;#d;#p;static get observedAttributes(){return[...super.observedAttributes,"label","loading-label","disabled"]}constructor(){super(),this.#a=v(this.#o),this.#c=this.#E.bind(this),this.#d=this.#f.bind(this),this.#p=()=>{this.#m(!1)}}connectedCallback(){super.connectedCallback(),queueMicrotask(()=>{this.#u(),this.#h(),this.#y(),this.#w(),this.audit("submit_button_initialized",{tier:this.#o,hasParentForm:!!this.#s})})}render(){let e=document.createDocumentFragment(),t=document.createElement("div");t.className="submit-container";let i=`${this.#l}-hint`,r=document.createElement("p");r.id=i,r.className="sr-only",r.textContent="Complete all required fields to enable this button",t.appendChild(r),this.#e=document.createElement("button"),this.#e.type="button",this.#e.className="submit-btn",this.#e.disabled=!0,this.#e.setAttribute("aria-disabled","true"),this.#e.setAttribute("aria-describedby",i),this.#t=document.createElement("span"),this.#t.className="btn-label",this.#t.textContent=this.sanitizeValue(this.getAttribute("label")||"Submit"),this.#i=document.createElement("span"),this.#i.className="btn-loading hidden",this.#i.setAttribute("aria-hidden","true");let s=document.createElement("span");s.className="spinner";let n=document.createElement("span");return n.textContent=this.sanitizeValue(this.getAttribute("loading-label")||"Submitting..."),this.#i.appendChild(s),this.#i.appendChild(n),this.#e.appendChild(this.#t),this.#e.appendChild(this.#i),this.#e.addEventListener("click",this.#d),t.appendChild(this.#e),e.appendChild(t),this.addComponentStyles(this.#b()),e}#u(){this.#s=this.closest("secure-form")}#h(){!this.getAttribute("security-tier")&&_(this.#s)?this.#o=this.#s.securityTier:this.#o=this.securityTier,this.#a=v(this.#o)}#y(){let e=this.#s||this.parentElement;e&&(e.addEventListener("secure-input-change",this.#c),e.addEventListener("secure-textarea-change",this.#c),e.addEventListener("secure-select-change",this.#c),e.addEventListener("secure-datetime-change",this.#c),e.addEventListener("secure-form-success",this.#p))}#E(e){this.#w()}#w(){if(this.hasAttribute("disabled")){this.#v(!0);return}if(!this.#n){if(!this.#a.validation.required){this.#r=!0,this.#v(!1);return}_(this.#s)?this.#r=this.#s.valid:this.#r=this.#x(),this.#v(!this.#r)}}#x(){let e=this.#s||this.parentElement;if(!e)return!1;let t=e.querySelectorAll("secure-input, secure-textarea, secure-select, secure-datetime, secure-file-upload");for(let i of t){let r=i;if(typeof r.valid=="boolean"&&!r.valid)return!1}return t.length>0}#v(e){this.#e&&(this.#e.disabled=e,this.#e.setAttribute("aria-disabled",String(e)))}#f(){if(this.#n||this.#e?.disabled)return;let e=this.checkRateLimit();if(!e.allowed){this.audit("submit_button_rate_limited",{retryAfter:e.retryAfter});return}this.audit("submit_button_clicked",{tier:this.#o,formValid:this.#r}),this.#m(!0),_(this.#s)?this.#s.submit():this.#m(!1)}#m(e){this.#n=e,this.#e&&(this.#e.disabled=e,this.#e.setAttribute("aria-disabled",String(e))),this.#t&&this.#t.classList.toggle("hidden",e),this.#i&&(this.#i.classList.toggle("hidden",!e),this.#i.setAttribute("aria-hidden",String(!e)))}handleAttributeChange(e,t,i){switch(e){case"label":this.#t&&(this.#t.textContent=this.sanitizeValue(i||"Submit"));break;case"loading-label":if(this.#i){let r=this.#i.querySelector("span:last-child");r&&(r.textContent=this.sanitizeValue(i||"Submitting..."))}break;case"disabled":this.#w();break}}get disabled(){return this.#e?this.#e.disabled:!0}set disabled(e){e?this.setAttribute("disabled",""):this.removeAttribute("disabled"),this.#w()}get label(){return this.getAttribute("label")||"Submit"}set label(e){this.setAttribute("label",e)}#b(){return":host { display: inline-block; } .submit-container { margin-top: 8px; position: relative; } .submit-btn { display: inline-flex; align-items: center; justify-content: center; gap: var(--secure-ui-space-2); padding: var(--secure-ui-button-padding-y) var(--secure-ui-button-padding-x); min-height: var(--secure-ui-button-height); font-family: inherit; font-size: var(--secure-ui-font-size-sm); font-weight: var(--secure-ui-button-font-weight); line-height: 1; border-radius: var(--secure-ui-button-border-radius); border: var(--secure-ui-border-width-base) solid transparent; cursor: pointer; transition: background-color var(--secure-ui-transition-base) var(--secure-ui-transition-ease-out), border-color var(--secure-ui-transition-base) var(--secure-ui-transition-ease-out), opacity var(--secure-ui-transition-base) var(--secure-ui-transition-ease-out), box-shadow var(--secure-ui-transition-base) var(--secure-ui-transition-ease-out), color var(--secure-ui-transition-base) var(--secure-ui-transition-ease-out), transform var(--secure-ui-transition-fast) var(--secure-ui-transition-ease-out); background-color: var(--secure-ui-color-info); color: var(--secure-ui-color-text-inverse); user-select: none; } .submit-btn:hover:not(:disabled) { background-color: color-mix(in srgb, var(--secure-ui-color-info) 82%, black); transform: translateY(-1px); box-shadow: 0 2px 8px rgba(59, 130, 246, 0.25); } .submit-btn:focus-visible { outline: 2px solid var(--secure-ui-color-info); outline-offset: 2px; box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.3); } @media (forced-colors: active) { .submit-btn:focus-visible { outline: 2px solid ButtonText; box-shadow: none; } } .submit-btn:active:not(:disabled) { background-color: color-mix(in srgb, var(--secure-ui-color-info) 72%, black); transform: scale(0.98); box-shadow: none; } .submit-btn:disabled { background-color: var(--secure-ui-color-bg-disabled); color: var(--secure-ui-color-text-disabled); border-color: var(--secure-ui-color-border); cursor: not-allowed; opacity: 0.7; transform: none; box-shadow: none; } .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; } .btn-label, .btn-loading { display: inline-flex; align-items: center; gap: 8px; transition: opacity 0.2s ease-out; } .btn-label.hidden, .btn-loading.hidden { display: none; } .spinner { display: inline-block; width: 14px; height: 14px; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: spin 0.6s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } @media (prefers-reduced-motion: reduce) { .submit-btn { transition: none !important; } .btn-label, .btn-loading { transition: none !important; } .spinner { animation: none; border-right-color: currentColor; opacity: 0.5; } }"}disconnectedCallback(){super.disconnectedCallback(),this.#m(!1);let e=this.#s||this.parentElement;e&&(e.removeEventListener("secure-input-change",this.#c),e.removeEventListener("secure-textarea-change",this.#c),e.removeEventListener("secure-select-change",this.#c),e.removeEventListener("secure-datetime-change",this.#c),e.removeEventListener("secure-form-success",this.#p))}};customElements.define("secure-submit-button",R);var W=Object.freeze([{type:"amex",pattern:/^3[47]/,format:[4,6,5],cvcLength:4,lengths:[15],label:"Amex"},{type:"diners",pattern:/^3(?:0[0-5]|[68])/,format:[4,6,4],cvcLength:3,lengths:[14],label:"Diners"},{type:"discover",pattern:/^6(?:011|5[0-9]{2})/,format:[4,4,4,4],cvcLength:3,lengths:[16],label:"Discover"},{type:"jcb",pattern:/^(?:2131|1800|35\d{3})/,format:[4,4,4,4],cvcLength:3,lengths:[16],label:"JCB"},{type:"mastercard",pattern:/^(?:5[1-5]|2[2-7])/,format:[4,4,4,4],cvcLength:3,lengths:[16],label:"Mastercard"},{type:"visa",pattern:/^4/,format:[4,4,4,4],cvcLength:3,lengths:[13,16,19],label:"Visa"}]);function Z(l){return l?W.find(e=>e.pattern.test(l))??null:null}function E(l,e){let t="",i=0;for(let r=0;r<e.length;r++){let s=l.slice(i,i+e[r]);if(!s)break;r>0&&(t+=" "),t+=s,i+=e[r]}return t}function X(l,e){let t=e.reduce((n,a)=>n+a,0);if(!l)return E("\u2022".repeat(t),e);let i=l.padEnd(t,"\u2022").slice(0,t),r=Math.max(0,i.length-4),s="\u2022".repeat(r)+i.slice(r);return E(s,e)}function Y(l){if(!l||l.length<12)return!1;let e=0,t=!1;for(let i=l.length-1;i>=0;i--){let r=l[i];if(!r)return!1;let s=parseInt(r,10);if(isNaN(s))return!1;let n=s;t&&(n*=2,n>9&&(n-=9)),e+=n,t=!t}return e%10===0}function U(l,e){let t=new Date,i=t.getFullYear()%100,r=t.getMonth()+1;return!(e<i||e===i&&l<r)}var J=0,P=class extends p{#e=null;#t=null;#i=null;#s=null;#r=null;#n=null;#o=null;#a=null;#l=null;#c=null;#d=null;#p=null;#u=null;#h=null;#y=null;#E=null;#w=null;#x="";#v="";#f="";#m="";#b=null;#g;constructor(){super(),this.#g=`secure-card-${++J}`}static get observedAttributes(){return[...super.observedAttributes,"name","label","show-name"]}render(){let e=document.createDocumentFragment(),t=this.hasAttribute("disabled"),i=this.hasAttribute("show-name"),r=this.getAttribute("label")??"",s=document.createElement("div");s.className="card-container",s.setAttribute("part","container");let n=document.createElement("div");n.className="card-scene",n.setAttribute("aria-hidden","true"),this.#r=document.createElement("div"),this.#r.className="card";let a=document.createElement("div");a.className="card-face card-front";let o=document.createElement("div");o.className="card-top-row";let d=document.createElement("div");d.className="card-chip",this.#l=document.createElement("div"),this.#l.className="card-type-label",o.appendChild(d),o.appendChild(this.#l),a.appendChild(o),this.#n=document.createElement("div"),this.#n.className="card-number-display",this.#n.textContent="\u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022",a.appendChild(this.#n);let c=document.createElement("div");c.className="card-bottom-row";let m=document.createElement("div");m.className="card-name-section";let g=document.createElement("div");g.className="card-field-label",g.textContent="Card holder",this.#a=document.createElement("div"),this.#a.className="card-name-display",this.#a.textContent="FULL NAME",m.appendChild(g),m.appendChild(this.#a);let f=document.createElement("div");f.className="card-expiry-section";let h=document.createElement("div");h.className="card-field-label",h.textContent="Expires",this.#o=document.createElement("div"),this.#o.className="card-expiry-display",this.#o.textContent="MM/YY",f.appendChild(h),f.appendChild(this.#o),c.appendChild(m),c.appendChild(f),a.appendChild(c);let C=document.createElement("div");C.className="card-face card-back";let O=document.createElement("div");O.className="card-strip";let T=document.createElement("div");T.className="card-cvc-area";let V=document.createElement("div");V.className="card-cvc-label",V.textContent="CVC",this.#c=document.createElement("div"),this.#c.className="card-cvc-display",this.#c.textContent="\u2022\u2022\u2022",T.appendChild(V),T.appendChild(this.#c),C.appendChild(O),C.appendChild(T),this.#r.appendChild(a),this.#r.appendChild(C),n.appendChild(this.#r);let y=document.createElement("div");if(y.className="card-fields",r){let b=document.createElement("div");b.className="card-legend",b.setAttribute("part","label"),b.textContent=this.sanitizeValue(r),y.appendChild(b)}let L=this.#A(`${this.#g}-number`),K=L.querySelector("label");K.textContent="Card number",this.#e=document.createElement("input"),this.#e.id=`${this.#g}-number`,this.#e.className="card-input card-number-input",this.#e.setAttribute("type","text"),this.#e.setAttribute("inputmode","numeric"),this.#e.setAttribute("autocomplete","cc-number"),this.#e.setAttribute("placeholder","0000 0000 0000 0000"),this.#e.setAttribute("maxlength","23"),this.#e.setAttribute("aria-required","true"),this.#e.setAttribute("aria-describedby",`${this.#g}-number-error`),this.#e.setAttribute("part","number-input"),t&&(this.#e.disabled=!0),this.#d=L.querySelector(".error-container"),this.#d.id=`${this.#g}-number-error`,L.querySelector(".input-wrapper").appendChild(this.#e),y.appendChild(L);let k=document.createElement("div");k.className="field-row";let S=this.#A(`${this.#g}-expiry`);S.querySelector("label").textContent="Expiry date",this.#t=document.createElement("input"),this.#t.id=`${this.#g}-expiry`,this.#t.className="card-input",this.#t.setAttribute("type","text"),this.#t.setAttribute("inputmode","numeric"),this.#t.setAttribute("autocomplete","cc-exp"),this.#t.setAttribute("placeholder","MM/YY"),this.#t.setAttribute("maxlength","5"),this.#t.setAttribute("aria-required","true"),this.#t.setAttribute("aria-describedby",`${this.#g}-expiry-error`),this.#t.setAttribute("part","expiry-input"),t&&(this.#t.disabled=!0),this.#p=S.querySelector(".error-container"),this.#p.id=`${this.#g}-expiry-error`,S.querySelector(".input-wrapper").appendChild(this.#t);let z=this.#A(`${this.#g}-cvc`);z.querySelector("label").textContent="Security code",this.#i=document.createElement("input"),this.#i.id=`${this.#g}-cvc`,this.#i.className="card-input cvc-input",this.#i.setAttribute("type","password"),this.#i.setAttribute("inputmode","numeric"),this.#i.setAttribute("autocomplete","cc-csc"),this.#i.setAttribute("placeholder","\u2022\u2022\u2022"),this.#i.setAttribute("maxlength","4"),this.#i.setAttribute("aria-required","true"),this.#i.setAttribute("aria-describedby",`${this.#g}-cvc-error`),this.#i.setAttribute("part","cvc-input"),t&&(this.#i.disabled=!0),this.#u=z.querySelector(".error-container"),this.#u.id=`${this.#g}-cvc-error`,z.querySelector(".input-wrapper").appendChild(this.#i),k.appendChild(S),k.appendChild(z),y.appendChild(k);let x=this.#A(`${this.#g}-name`);return x.id=`${this.#g}-name-group`,x.querySelector("label").textContent="Cardholder name",i||(x.hidden=!0),this.#s=document.createElement("input"),this.#s.id=`${this.#g}-name`,this.#s.className="card-input",this.#s.setAttribute("type","text"),this.#s.setAttribute("autocomplete","cc-name"),this.#s.setAttribute("placeholder","Name as it appears on card"),this.#s.setAttribute("spellcheck","false"),this.#s.setAttribute("aria-describedby",`${this.#g}-name-error`),this.#s.setAttribute("part","name-input"),t&&(this.#s.disabled=!0),this.#h=x.querySelector(".error-container"),this.#h.id=`${this.#g}-name-error`,x.querySelector(".input-wrapper").appendChild(this.#s),y.appendChild(x),s.appendChild(n),s.appendChild(y),this.#q(),this.addComponentStyles(":host { --secure-card-width: 340px; --secure-card-radius: 16px; --secure-card-font: var(--secure-ui-font-family-mono, 'Courier New', monospace); --secure-card-transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1); --secure-card-gradient: linear-gradient(135deg, #1e2a4a 0%, #2d4a8a 100%); display: block; } .card-container { width: 100%; max-width: 480px; font-family: var(--secure-ui-font-family-sans, system-ui, sans-serif); } .card-scene { width: var(--secure-card-width); max-width: 100%; aspect-ratio: 85.6 / 54; perspective: 1000px; margin-inline: auto; margin-block-end: var(--secure-ui-space-6, 1.5rem); user-select: none; } .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: var(--secure-card-transition); border-radius: var(--secure-card-radius); filter: drop-shadow(0 8px 24px rgba(0, 0, 0, 0.35)); } .card.is-flipped { transform: rotateY(180deg); } .card-face { position: absolute; inset: 0; border-radius: var(--secure-card-radius); backface-visibility: hidden; -webkit-backface-visibility: hidden; background: var(--secure-card-gradient); color: #fff; overflow: hidden; } .card-face::before { content: ''; position: absolute; inset: 0; background: linear-gradient( 135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0) 60% ); border-radius: inherit; pointer-events: none; } .card-back { transform: rotateY(180deg); } .card--visa { --secure-card-gradient: linear-gradient(135deg, #1a1f71 0%, #2563eb 100%); } .card--mastercard { --secure-card-gradient: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #e63946 100%); } .card--amex { --secure-card-gradient: linear-gradient(135deg, #007b5e 0%, #00b894 100%); } .card--discover { --secure-card-gradient: linear-gradient(135deg, #b34700 0%, #e65c00 50%, #f9a825 100%); } .card--diners { --secure-card-gradient: linear-gradient(135deg, #005c97 0%, #363795 100%); } .card--jcb { --secure-card-gradient: linear-gradient(135deg, #0e4c96 0%, #e63946 100%); } .card-front { display: flex; flex-direction: column; justify-content: space-between; padding: 20px 24px 18px; } .card-top-row { display: flex; align-items: center; justify-content: space-between; } .card-chip { width: 42px; height: 32px; background: linear-gradient(135deg, #c8a84b 0%, #f0d060 40%, #c8a84b 100%); border-radius: 5px; position: relative; flex-shrink: 0; } .card-chip::before { content: ''; position: absolute; inset: 9px 0; border-top: 1.5px solid rgba(0, 0, 0, 0.25); border-bottom: 1.5px solid rgba(0, 0, 0, 0.25); } .card-chip::after { content: ''; position: absolute; inset: 0 13px; border-left: 1.5px solid rgba(0, 0, 0, 0.2); border-right: 1.5px solid rgba(0, 0, 0, 0.2); border-radius: 2px; } .card-type-label { font-size: 1rem; font-weight: 700; letter-spacing: 0.06em; font-style: italic; opacity: 0.95; min-width: 52px; text-align: end; text-transform: uppercase; } .card--mastercard .card-type-label { position: relative; width: 52px; height: 32px; font-size: 0; } .card--mastercard .card-type-label::before, .card--mastercard .card-type-label::after { content: ''; position: absolute; top: 50%; transform: translateY(-50%); width: 28px; height: 28px; border-radius: 50%; } .card--mastercard .card-type-label::before { background: #eb001b; inset-inline-start: 0; } .card--mastercard .card-type-label::after { background: #f79e1b; inset-inline-start: 16px; mix-blend-mode: multiply; } .card-number-display { font-family: var(--secure-card-font); font-size: clamp(0.85rem, 2.5vw, 1.1rem); letter-spacing: 0.18em; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.4); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .card-bottom-row { display: flex; justify-content: space-between; align-items: flex-end; gap: var(--secure-ui-space-3, 0.75rem); } .card-field-label { font-size: 0.6rem; text-transform: uppercase; letter-spacing: 0.12em; opacity: 0.7; margin-block-end: 2px; } .card-name-display { font-size: clamp(0.7rem, 2vw, 0.85rem); letter-spacing: 0.06em; font-weight: 500; text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 160px; } .card-expiry-display { font-family: var(--secure-card-font); font-size: 0.85rem; letter-spacing: 0.1em; white-space: nowrap; } .card-back { display: flex; flex-direction: column; gap: var(--secure-ui-space-3, 0.75rem); } .card-strip { width: 100%; height: 40px; background: #1a1a1a; margin-block-start: 28px; flex-shrink: 0; } .card-cvc-area { display: flex; flex-direction: column; align-items: flex-end; padding-inline-end: 24px; gap: 4px; } .card-cvc-label { font-size: 0.6rem; text-transform: uppercase; letter-spacing: 0.1em; opacity: 0.7; } .card-cvc-display { background: #fff; color: #1a1a1a; font-family: var(--secure-card-font); font-size: 0.85rem; letter-spacing: 0.2em; padding: 4px 10px; border-radius: 3px; min-width: 52px; text-align: center; } .card-fields { display: flex; flex-direction: column; gap: var(--secure-ui-space-4, 1rem); } .card-legend { font-size: var(--secure-ui-font-size-sm, 0.875rem); font-weight: var(--secure-ui-font-weight-semibold, 600); color: var(--secure-ui-color-neutral-700, #374151); margin-block-end: var(--secure-ui-space-1, 0.25rem); } .field-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--secure-ui-space-4, 1rem); } .field-group { display: flex; flex-direction: column; gap: var(--secure-ui-space-1, 0.25rem); position: relative; } .field-label { font-size: var(--secure-ui-font-size-sm, 0.875rem); font-weight: var(--secure-ui-font-weight-medium, 500); color: var(--secure-ui-color-neutral-700, #374151); line-height: var(--secure-ui-line-height-tight, 1.25); } .input-wrapper { position: relative; } .card-input { width: 100%; box-sizing: border-box; padding: var(--secure-ui-input-padding-y, 0.625rem) var(--secure-ui-input-padding-x, 0.75rem); font-family: var(--secure-ui-font-family-sans, system-ui, sans-serif); font-size: var(--secure-ui-font-size-base, 1rem); line-height: var(--secure-ui-line-height-normal, 1.5); color: var(--secure-ui-input-color, #111827); background: var(--secure-ui-input-bg, #fff); border: var(--secure-ui-border-width, 1px) solid var(--secure-ui-input-border-color, #d1d5db); border-radius: var(--secure-ui-input-border-radius, 6px); outline: none; transition: border-color var(--secure-ui-transition-fast, 150ms) ease, box-shadow var(--secure-ui-transition-fast, 150ms) ease; appearance: none; -webkit-appearance: none; } .card-input:focus { border-color: var(--secure-ui-color-primary-500, #6366f1); box-shadow: 0 0 0 3px var(--secure-ui-color-primary-100, rgba(99, 102, 241, 0.2)); } .card-input[aria-invalid='true'] { border-color: var(--secure-ui-color-error-500, #ef4444) !important; box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.15); } .card-input:disabled { background: var(--secure-ui-input-disabled-bg, #f3f4f6); color: var(--secure-ui-color-neutral-400, #9ca3af); cursor: not-allowed; } .card-number-input { font-family: var(--secure-card-font); letter-spacing: 0.06em; } .cvc-input::-ms-reveal, .cvc-input::-ms-clear { display: none; } .error-container { font-size: var(--secure-ui-font-size-xs, 0.75rem); color: var(--secure-ui-color-error-600, #dc2626); line-height: var(--secure-ui-line-height-tight, 1.25); min-height: 0; max-height: 3rem; overflow: hidden; transition: max-height var(--secure-ui-transition-normal, 250ms) ease, opacity var(--secure-ui-transition-fast, 150ms) ease; opacity: 1; } .error-container.hidden { max-height: 0; opacity: 0; } @media (prefers-color-scheme: dark) { .card-legend { color: var(--secure-ui-color-neutral-200, #e5e7eb); } .field-label { color: var(--secure-ui-color-neutral-200, #e5e7eb); } .card-input { color: var(--secure-ui-input-color, #f9fafb); background: var(--secure-ui-input-bg, #1f2937); border-color: var(--secure-ui-input-border-color, #374151); } .card-input:disabled { background: #111827; color: #6b7280; } .card-cvc-display { background: #f9fafb; color: #111827; } } @media (prefers-reduced-motion: reduce) { .card { transition: none; } .card-input { transition: none; } .error-container { transition: none; } } @media (max-width: 400px) { .field-row { grid-template-columns: 1fr; } }"),this.setupAutofillDetection(this.#e),this.setupAutofillDetection(this.#t),this.setupAutofillDetection(this.#i),this.setupAutofillDetection(this.#s),this.#e.addEventListener("input",b=>{this.recordTelemetryInput(b),this.#C(b)}),this.#e.addEventListener("focus",()=>{this.recordTelemetryFocus(),this.#S()}),this.#e.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#z()}),this.#t.addEventListener("input",b=>{this.recordTelemetryInput(b),this.#L(b)}),this.#t.addEventListener("focus",()=>{this.recordTelemetryFocus(),this.#N(!1)}),this.#t.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#D()}),this.#i.addEventListener("input",b=>{this.recordTelemetryInput(b),this.#I(b)}),this.#i.addEventListener("focus",()=>{this.recordTelemetryFocus(),this.#N(!0)}),this.#i.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#H()}),this.#s.addEventListener("input",b=>{this.recordTelemetryInput(b),this.#F(b)}),this.#s.addEventListener("focus",()=>{this.recordTelemetryFocus(),this.#N(!1)}),this.#s.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#P()}),e.appendChild(s),e}#A(e){let t=document.createElement("div");t.className="field-group";let i=document.createElement("label");i.htmlFor=e,i.className="field-label";let r=document.createElement("div");r.className="input-wrapper",r.setAttribute("part","wrapper");let s=document.createElement("div");return s.className="error-container hidden",s.setAttribute("role","alert"),s.setAttribute("part","error"),t.appendChild(i),t.appendChild(r),t.appendChild(s),t}handleAttributeChange(e,t,i){if(this.shadowRoot)switch(e){case"disabled":{let r=i!==null;this.#e&&(this.#e.disabled=r),this.#t&&(this.#t.disabled=r),this.#i&&(this.#i.disabled=r),this.#s&&(this.#s.disabled=r);break}case"show-name":{let r=this.shadowRoot.querySelector(`#${this.#g}-name-group`);r&&(r.hidden=i===null);break}}}#C(e){let t=e.target,i=t.value.replace(/\D/g,""),r=this.#b?.type;this.#b=Z(i);let s=this.#b?.format??[4,4,4,4],n=s.reduce((a,o)=>a+o,0);if(this.#x=i.slice(0,n),t.value=E(this.#x,s),this.#b?.type!==r){let a=n+s.length-1;t.setAttribute("maxlength",String(a));let o=this.#b?.cvcLength??3;this.#i&&this.#i.setAttribute("maxlength",String(o)),this.#j()}this.#n&&(this.#n.textContent=t.value||E("\u2022".repeat(n),s)),this.#T(this.#d),this.#$(),this.#R()}#S(){if(this.#e&&this.#x){let e=this.#b?.format??[4,4,4,4],t=E(this.#x,e);this.#e.value=t,this.#n&&(this.#n.textContent=t)}this.#N(!1),this.#T(this.#d)}#z(){let e=this.checkRateLimit();if(!e.allowed){this.#k(this.#d,`Too many attempts. Try again in ${Math.ceil(e.retryAfter/1e3)}s.`);return}this.#x?Y(this.#x)?(this.#T(this.#d),this.#e?.removeAttribute("aria-invalid")):(this.#k(this.#d,"Invalid card number"),this.#e?.setAttribute("aria-invalid","true")):(this.#k(this.#d,"Card number is required"),this.#e?.setAttribute("aria-invalid","true")),this.#M(),this.audit("card-number-blur",{cardType:this.#b?.type??"unknown"})}#M(){let e=this.#b?.format??[4,4,4,4],t=X(this.#x,e);this.#e&&(this.#e.value=t),this.#n&&(this.#n.textContent=t)}#L(e){let t=e.target,i=t.value.replace(/\D/g,"").slice(0,4),r=i.length>2?`${i.slice(0,2)}/${i.slice(2)}`:i;t.value=r,this.#f=r,this.#o&&(this.#o.textContent=r||"MM/YY"),this.#T(this.#p),this.#$(),this.#R()}#D(){let e=this.#f.split("/");if(!this.#f){this.#k(this.#p,"Expiry date is required"),this.#t?.setAttribute("aria-invalid","true");return}let t=parseInt(e[0]??"",10),i=parseInt(e[1]??"",10);isNaN(t)||isNaN(i)||t<1||t>12||(e[1]??"").length<2?(this.#k(this.#p,"Enter a valid expiry date (MM/YY)"),this.#t?.setAttribute("aria-invalid","true")):U(t,i)?(this.#T(this.#p),this.#t?.removeAttribute("aria-invalid")):(this.#k(this.#p,"This card has expired"),this.#t?.setAttribute("aria-invalid","true")),this.audit("card-expiry-blur",{})}#I(e){let t=e.target,i=t.value.replace(/\D/g,""),r=this.#b?.cvcLength??3;this.#v=i.slice(0,r),t.value=this.#v,this.#c&&(this.#c.textContent=this.#v.length>0?"\u2022".repeat(this.#v.length):"\u2022\u2022\u2022"),this.#T(this.#u),this.#R()}#H(){let e=this.#b?.cvcLength??3;this.#v?this.#v.length<e?(this.#k(this.#u,`Security code must be ${e} digits`),this.#i?.setAttribute("aria-invalid","true")):(this.#T(this.#u),this.#i?.removeAttribute("aria-invalid")):(this.#k(this.#u,"Security code is required"),this.#i?.setAttribute("aria-invalid","true")),this.#N(!1),this.audit("card-cvc-blur",{})}#F(e){let t=e.target,i=t.value.replace(/[^a-zA-Z\s\-']/g,"").slice(0,50);t.value=i,this.#m=i,this.#a&&(this.#a.textContent=i.toUpperCase()||"FULL NAME"),this.#T(this.#h),this.#$(),this.#R()}#P(){this.hasAttribute("show-name")&&(this.#m.trim()?(this.#T(this.#h),this.#s?.removeAttribute("aria-invalid")):(this.#k(this.#h,"Cardholder name is required"),this.#s?.setAttribute("aria-invalid","true")))}#N(e){this.#r?.classList.toggle("is-flipped",e)}#j(){if(!this.#r)return;for(let t of W)this.#r.classList.remove(`card--${t.type}`);let e=this.#b?.type;e&&this.#r.classList.add(`card--${e}`),this.#l&&(this.#l.textContent=this.#b?.label??"")}#k(e,t){if(!e)return;e.textContent="";let i=document.createElement("span");i.textContent=t,e.appendChild(i),e.classList.remove("hidden")}#T(e){e&&(e.textContent="",e.classList.add("hidden"))}#q(){let e=this.getAttribute("name");e&&(this.#y=document.createElement("input"),this.#y.type="hidden",this.#y.name=e,this.appendChild(this.#y),this.#E=document.createElement("input"),this.#E.type="hidden",this.#E.name=`${e}-expiry`,this.appendChild(this.#E),this.#w=document.createElement("input"),this.#w.type="hidden",this.#w.name=`${e}-holder`,this.appendChild(this.#w))}#$(){this.#y&&(this.#y.value=this.#x.slice(-4)),this.#E&&(this.#E.value=this.#f),this.#w&&(this.#w.value=this.#m)}#R(){let[e,t]=this.#f.split("/");this.dispatchEvent(new CustomEvent("secure-card-change",{bubbles:!0,composed:!0,detail:{name:this.getAttribute("name")??"",cardType:this.#b?.type??"unknown",last4:this.#x.slice(-4),expiryMonth:parseInt(e??"0",10)||0,expiryYear:(()=>{let i=parseInt(t??"0",10);return i>0?2e3+i:0})(),cardholderName:this.#m,valid:this.valid,tier:this.securityTier}}))}disconnectedCallback(){this.#x="",this.#v="",this.#f="",this.#m="",this.#e&&(this.#e.value=""),this.#t&&(this.#t.value=""),this.#i&&(this.#i.value=""),this.#s&&(this.#s.value=""),this.#y&&(this.#y.value=""),this.#E&&(this.#E.value=""),this.#w&&(this.#w.value=""),super.disconnectedCallback()}get valid(){let e=this.#x.length>=12&&Y(this.#x),[t,i]=this.#f.split("/"),r=parseInt(t??"",10),s=parseInt(i??"",10),n=!isNaN(r)&&!isNaN(s)&&r>=1&&r<=12&&(i??"").length>=2&&U(r,s),a=this.#b?.cvcLength??3,o=this.#v.length===a,d=!this.hasAttribute("show-name")||this.#m.trim().length>0;return e&&n&&o&&d}get cardType(){return this.#b?.type??"unknown"}get last4(){return this.#x.slice(-4)}get name(){return this.getAttribute("name")??""}getCardData(){return this.valid?{number:this.#x,expiry:this.#f,cvc:this.#v,name:this.#m}:null}reset(){this.#x="",this.#v="",this.#f="",this.#m="",this.#b=null,this.#e&&(this.#e.value=""),this.#t&&(this.#t.value=""),this.#i&&(this.#i.value=""),this.#s&&(this.#s.value=""),this.#$(),this.#N(!1),this.#j();let e=[4,4,4,4];this.#n&&(this.#n.textContent=E("\u2022".repeat(16),e)),this.#o&&(this.#o.textContent="MM/YY"),this.#a&&(this.#a.textContent="FULL NAME"),this.#c&&(this.#c.textContent="\u2022\u2022\u2022"),this.#T(this.#d),this.#T(this.#p),this.#T(this.#u),this.#T(this.#h),this.audit("card-reset",{})}focus(){this.#e?.focus()}};customElements.define("secure-card",P);var j=class extends HTMLElement{static get observedAttributes(){return["signing-key"]}#e={mouseMovementDetected:!1,keyboardActivityDetected:!1,injectedScriptCount:0,domMutationDetected:!1,pointerType:"none",firstKeystrokeAt:-1,threatSignals:[]};#t=0;#i=null;#s=new Set;#r=null;#n="";#o=()=>{this.#e.mouseMovementDetected=!0};#a=()=>{this.#e.keyboardActivityDetected=!0,this.#e.firstKeystrokeAt<0&&(this.#e.firstKeystrokeAt=performance.now())};#l=e=>{this.#e.pointerType=e.pointerType};#c=e=>{this.#w(e)};#d=e=>{this.#e.threatSignals.push(e.detail)};connectedCallback(){this.#t=performance.now(),document.querySelectorAll("script").forEach(e=>this.#s.add(e)),this.#p(),this.#u()}disconnectedCallback(){this.#i?.disconnect(),this.#i=null,this.#h(),this.#r=null,this.#n=""}attributeChangedCallback(e,t,i){e==="signing-key"&&i!==this.#n&&(this.#r=null,this.#n="")}#p(){this.#i=new MutationObserver(e=>{for(let t of e)if(t.type==="childList")for(let i of Array.from(t.addedNodes))i.tagName==="SCRIPT"&&!this.#s.has(i)&&(this.#e.injectedScriptCount++,this.#e.domMutationDetected=!0,this.#s.add(i))}),this.#i.observe(document.documentElement,{childList:!0,subtree:!0})}#u(){document.addEventListener("mousemove",this.#o,{passive:!0}),document.addEventListener("keydown",this.#a,{passive:!0}),document.addEventListener("pointerdown",this.#l,{passive:!0}),this.addEventListener("secure-form-submit",this.#c),this.addEventListener("secure-threat-detected",this.#d)}#h(){document.removeEventListener("mousemove",this.#o),document.removeEventListener("keydown",this.#a),document.removeEventListener("pointerdown",this.#l),this.removeEventListener("secure-form-submit",this.#c),this.removeEventListener("secure-threat-detected",this.#d)}collectSignals(){let e=navigator,t=e.webdriver===!0||Object.prototype.hasOwnProperty.call(e,"webdriver"),i=navigator.userAgent,r=i.includes("HeadlessChrome")||i.includes("Headless")||typeof window.chrome>"u"&&i.includes("Chrome"),s=screen.width===0||screen.height===0||screen.width<100&&screen.height<100,n=performance.now(),a=this.#e.firstKeystrokeAt>=0?Math.round(this.#e.firstKeystrokeAt-this.#t):-1,o=Math.round(n-this.#t);return{webdriverDetected:t,headlessDetected:r,domMutationDetected:this.#e.domMutationDetected,injectedScriptCount:this.#e.injectedScriptCount,suspiciousScreenSize:s,pointerType:this.#e.pointerType,mouseMovementDetected:this.#e.mouseMovementDetected,keyboardActivityDetected:this.#e.keyboardActivityDetected,pageLoadToFirstKeystroke:a,loadToSubmit:o,threatSignals:this.#e.threatSignals.length>0?[...this.#e.threatSignals]:void 0}}async sign(e){let t=this.#y(),i=new Date().toISOString(),r=this.getAttribute("signing-key")??"",s=`${t}.${i}.${JSON.stringify(e)}`,n=await this.#E(r,s);return{nonce:t,issuedAt:i,environment:e,signature:n}}#y(){let e=new Uint8Array(16);return crypto.getRandomValues(e),Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}async#E(e,t){if(!crypto.subtle)return"";let i=new TextEncoder;(this.#r===null||this.#n!==e)&&(this.#r=await crypto.subtle.importKey("raw",i.encode(e),{name:"HMAC",hash:"SHA-256"},!1,["sign"]),this.#n=e);let r=await crypto.subtle.sign("HMAC",this.#r,i.encode(t));return Array.from(new Uint8Array(r),s=>s.toString(16).padStart(2,"0")).join("")}async#w(e){let t=e.detail;if(t?.telemetry)try{let i=this.collectSignals(),r=await this.sign(i);t.telemetry._env=r}catch{}}getEnvironmentalSignals(){return this.collectSignals()}};customElements.define("secure-telemetry-provider",j);var q=class extends p{#e=null;#t=null;#i=null;#s=null;#r=null;#n=null;#o=null;#a="";#l="";#c=!1;#d=!1;#p=!1;#u=null;#h=`secure-password-confirm-${Math.random().toString(36).substring(2,11)}`;connectedCallback(){let e=this.getAttribute("security-tier");e&&e!=="critical"&&console.warn(`secure-password-confirm: security-tier="${e}" ignored \u2014 this component is locked to CRITICAL.`),this.removeAttribute("security-tier"),super.connectedCallback()}static get observedAttributes(){return[...super.observedAttributes,"name","label","password-label","confirm-label","required","minlength"]}render(){let e=document.createDocumentFragment(),t=document.createElement("div");t.className="container",t.setAttribute("part","container");let i=this.getAttribute("label");if(i){let a=document.createElement("div");a.className="group-label",a.textContent=this.sanitizeValue(i),t.appendChild(a)}let r=this.hasAttribute("required"),s=this.#y({inputPart:"password-input",wrapperPart:"password-wrapper",labelPart:"password-label",errorPart:"password-error",togglePart:"password-toggle",labelText:this.getAttribute("password-label")??"New Password",inputId:`${this.#h}-password`,errorId:`${this.#h}-password-error`,isRequired:r});this.#e=s.querySelector('[part="password-input"]'),this.#n=s.querySelector('[part="password-toggle"]'),this.#i=s.querySelector('[part="password-error"]');let n=this.#y({inputPart:"confirm-input",wrapperPart:"confirm-wrapper",labelPart:"confirm-label",errorPart:"confirm-error",togglePart:"confirm-toggle",labelText:this.getAttribute("confirm-label")??"Confirm Password",inputId:`${this.#h}-confirm`,errorId:`${this.#h}-confirm-error`,isRequired:r});return this.#t=n.querySelector('[part="confirm-input"]'),this.#o=n.querySelector('[part="confirm-toggle"]'),this.#s=n.querySelector('[part="confirm-error"]'),this.#r=document.createElement("div"),this.#r.setAttribute("part","match-indicator"),this.#r.className="match-indicator",this.#r.setAttribute("aria-hidden","true"),t.appendChild(s),t.appendChild(n),t.appendChild(this.#r),this.#E(),this.#w(),this.#x(),this.#S(),this.addComponentStyles('.container { display: flex; flex-direction: column; gap: var(--secure-ui-form-gap); font-family: var(--secure-ui-font-family-base); } .group-label { font-size: var(--secure-ui-label-font-size); font-weight: var(--secure-ui-label-font-weight); color: var(--secure-ui-label-color); margin-bottom: var(--secure-ui-space-1); } .field-section { display: flex; flex-direction: column; gap: var(--secure-ui-form-label-margin-bottom); } label { font-size: var(--secure-ui-label-font-size); font-weight: var(--secure-ui-label-font-weight); color: var(--secure-ui-label-color); } .input-wrapper { position: relative; display: flex; align-items: center; } input[type="password"], input[type="text"] { flex: 1; height: var(--secure-ui-input-height); padding: var(--secure-ui-input-padding-y) var(--secure-ui-input-padding-x); padding-inline-end: calc(var(--secure-ui-input-padding-x) * 3.5); font-family: var(--secure-ui-font-family-base); font-size: var(--secure-ui-input-font-size); color: var(--secure-ui-input-text-color); background-color: var(--secure-ui-input-bg); border: var(--secure-ui-input-border-width) solid var(--secure-ui-input-border-color); border-radius: var(--secure-ui-input-border-radius); box-sizing: border-box; transition: border-color var(--secure-ui-transition-base), box-shadow var(--secure-ui-transition-base); } input:hover:not(:disabled) { border-color: var(--secure-ui-input-border-color-hover); } input:focus { outline: none; border-color: var(--secure-ui-input-border-color-focus); box-shadow: var(--secure-ui-shadow-focus); } input[aria-invalid="true"] { border-color: var(--secure-ui-color-error) !important; } input[aria-invalid="true"]:focus { box-shadow: var(--secure-ui-shadow-focus-error); } .toggle-btn { position: absolute; inset-inline-end: var(--secure-ui-space-2); display: flex; align-items: center; justify-content: center; background: none; border: none; cursor: pointer; color: var(--secure-ui-color-text-secondary); padding: var(--secure-ui-space-1); border-radius: var(--secure-ui-border-radius-sm); line-height: 1; transition: color var(--secure-ui-transition-base); } .toggle-btn:hover { color: var(--secure-ui-color-text-primary); } .toggle-btn:focus-visible { outline: 2px solid var(--secure-ui-input-border-color-focus); outline-offset: 2px; } .toggle-btn:active .eye-icon { transform: scale(0.85); } .eye-icon { display: block; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; transition: transform 0.15s ease; overflow: visible; } .eye-outline { transition: d 0.2s ease; } .eye-pupil { transform-origin: 12px 12px; transition: opacity 0.2s ease, transform 0.2s ease; } .eye-slash { stroke-dasharray: 26; stroke-dashoffset: 26; transition: stroke-dashoffset 0.3s ease; } .toggle-btn.is-visible .eye-pupil { opacity: 0; transform: scale(0.2); } .toggle-btn.is-visible .eye-slash { stroke-dashoffset: 0; } .error-container { font-size: var(--secure-ui-error-font-size); color: var(--secure-ui-error-color); line-height: var(--secure-ui-line-height-normal); overflow: hidden; max-height: 40px; opacity: 1; transition: all 0.2s ease-in-out; } .error-container.hidden { max-height: 0; opacity: 0; pointer-events: none; } .match-indicator { font-size: var(--secure-ui-font-size-sm); line-height: var(--secure-ui-line-height-normal); min-height: 1.25em; } .match-indicator.matched { color: var(--secure-ui-color-success, #2e7d32); } .match-indicator.mismatched { color: var(--secure-ui-color-error); } @media (prefers-reduced-motion: reduce) { input, .error-container, .eye-icon, .eye-pupil, .eye-slash { transition: none !important; } }'),e.appendChild(t),e}#y(e){let t=document.createElement("div");t.className="field-section";let i=document.createElement("label");i.setAttribute("part",e.labelPart),i.htmlFor=e.inputId,i.textContent=this.sanitizeValue(e.labelText);let r=document.createElement("div");r.className="input-wrapper",r.setAttribute("part",e.wrapperPart);let s=document.createElement("input");s.id=e.inputId,s.type="password",s.autocomplete="new-password",s.setAttribute("part",e.inputPart),s.setAttribute("aria-describedby",e.errorId),e.isRequired&&(s.required=!0,s.setAttribute("aria-required","true"));let n=document.createElement("button");n.type="button",n.className="toggle-btn",n.setAttribute("part",e.togglePart),n.setAttribute("aria-label","Show password"),n.appendChild(this.#v()),r.appendChild(s),r.appendChild(n);let a=document.createElement("div");return a.id=e.errorId,a.setAttribute("part",e.errorPart),a.setAttribute("role","alert"),a.className="error-container hidden",t.appendChild(i),t.appendChild(r),t.appendChild(a),t}#E(){this.setupAutofillDetection(this.#e),this.#e.addEventListener("focus",()=>{this.recordTelemetryFocus()}),this.#e.addEventListener("input",e=>{this.recordTelemetryInput(e),this.#a=this.#e.value,this.detectInjection(this.#a,this.getAttribute("name")??""),this.#c&&this.#b(),this.dispatchEvent(new CustomEvent("secure-input-change",{detail:{name:this.getAttribute("name")??"",field:"password"},bubbles:!0,composed:!0}))}),this.#e.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#f()})}#w(){this.#t.addEventListener("input",()=>{this.#l=this.#t.value,this.detectInjection(this.#l,this.getAttribute("name")??""),this.#c&&this.#b()}),this.#t.addEventListener("blur",()=>{this.#c=!0,this.#l=this.#t.value,this.#b()})}#x(){this.#n.addEventListener("click",()=>{this.#d=!this.#d,this.#e.type=this.#d?"text":"password",this.#n.classList.toggle("is-visible",this.#d),this.#n.setAttribute("aria-label",this.#d?"Hide password":"Show password")}),this.#o.addEventListener("click",()=>{this.#p=!this.#p,this.#t.type=this.#p?"text":"password",this.#o.classList.toggle("is-visible",this.#p),this.#o.setAttribute("aria-label",this.#p?"Hide confirm password":"Show confirm password")})}#v(){let e="http://www.w3.org/2000/svg",t=document.createElementNS(e,"svg");t.setAttribute("viewBox","0 0 24 24"),t.setAttribute("aria-hidden","true"),t.setAttribute("class","eye-icon"),t.setAttribute("width","18"),t.setAttribute("height","18");let i=document.createElementNS(e,"path");i.setAttribute("class","eye-outline"),i.setAttribute("d","M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z");let r=document.createElementNS(e,"circle");r.setAttribute("class","eye-pupil"),r.setAttribute("cx","12"),r.setAttribute("cy","12"),r.setAttribute("r","3");let s=document.createElementNS(e,"line");return s.setAttribute("class","eye-slash"),s.setAttribute("x1","3"),s.setAttribute("y1","3"),s.setAttribute("x2","21"),s.setAttribute("y2","21"),t.append(i,r,s),t}#f(){let e=this.#m(this.#a);e?this.#g(this.#i,this.#e,e):this.#A(this.#i,this.#e)}#m(e){return e?e.length<8?"Password must be at least 8 characters":/[a-z]/.test(e)?/[A-Z]/.test(e)?/[0-9]/.test(e)?/[^a-zA-Z0-9]/.test(e)?null:"Password must include a special character":"Password must include a number":"Password must include an uppercase letter":"Password must include a lowercase letter":null}#b(){let e=this.#a.length>0&&this.#a===this.#l;if(this.#z(e),this.#C(e),e)this.#A(this.#s,this.#t),this.dispatchEvent(new CustomEvent("secure-password-match",{detail:{name:this.getAttribute("name")??"",matched:!0},bubbles:!0,composed:!0}));else{let t=this.#l.length>0?"Passwords do not match":"Please confirm your password";this.#g(this.#s,this.#t,t),this.dispatchEvent(new CustomEvent("secure-password-mismatch",{detail:{name:this.getAttribute("name")??"",matched:!1},bubbles:!0,composed:!0}))}}#g(e,t,i){e.textContent=i,e.classList.remove("hidden"),t.setAttribute("aria-invalid","true")}#A(e,t){e.classList.add("hidden"),e.textContent="",t.removeAttribute("aria-invalid")}#C(e){this.#r&&(this.#r.className=`match-indicator ${e?"matched":"mismatched"}`,this.#r.textContent=e?"\u2713 Passwords match":"\u2717 Passwords do not match")}#S(){let e=this.getAttribute("name");!e||this.closest("secure-form")||(this.#u=document.createElement("input"),this.#u.type="hidden",this.#u.name=e,this.#u.value="",this.appendChild(this.#u))}#z(e){this.#u&&(this.#u.value=e?this.#a:"")}getPasswordValue(){return!this.#a||!this.#l||this.#a!==this.#l?null:this.#a}get valid(){return!this.#a||!this.#l||this.#a!==this.#l?!1:this.#m(this.#a)===null}get name(){return this.getAttribute("name")??""}disconnectedCallback(){super.disconnectedCallback(),this.#a="",this.#l="",this.#e&&(this.#e.value=""),this.#t&&(this.#t.value=""),this.#u&&(this.#u.value="")}};customElements.define("secure-password-confirm",q);export{P as SecureCard,F as SecureDateTime,N as SecureFileUpload,H as SecureForm,I as SecureInput,q as SecurePasswordConfirm,D as SecureSelect,R as SecureSubmitButton,$ as SecureTable,j as SecureTelemetryProvider,M as SecureTextarea,u as SecurityTier,w as TIER_CONFIG,B as compareTiers,G as getMoreSecureTier,v as getTierConfig,A as isValidTier};
|
|
66
|
+
`;return s}#A(){let e=this.shadowRoot.getElementById("searchInput");e&&e.addEventListener("input",t=>{this.#l(t.target.value)}),this.#S()}#S(){this.shadowRoot.querySelectorAll("th.sortable").forEach(n=>{n.addEventListener("click",()=>{let a=n.getAttribute("data-column");a&&this.#u(a)})});let t=this.shadowRoot.getElementById("prevBtn"),i=this.shadowRoot.getElementById("nextBtn");t&&t.addEventListener("click",()=>{this.#p(this.#s.currentPage-1)}),i&&i.addEventListener("click",()=>{this.#p(this.#s.currentPage+1)}),this.shadowRoot.querySelectorAll(".pagination-button[data-page]").forEach(n=>{n.addEventListener("click",()=>{let a=parseInt(n.getAttribute("data-page"),10);this.#p(a)})});let s=this.shadowRoot.getElementById("tableContent");s&&s.addEventListener("click",n=>{let a=n.target.closest("[data-action]");if(!a)return;let o=a.getAttribute("data-action"),d=Object.create(null);d.action=o;for(let c of Array.from(a.attributes))if(c.name.startsWith("data-")&&c.name!=="data-action"){let m=c.name.slice(5).replace(/-([a-z])/g,(g,f)=>f.toUpperCase());if(m==="__proto__"||m==="constructor"||m==="prototype")continue;d[m]=c.value}this.dispatchEvent(new CustomEvent("secure-table-action",{bubbles:!0,composed:!0,detail:d})),this.audit("table_action",d)})}};customElements.define("secure-table",$);function V(l){if(l===null)return!1;let e=l;return typeof e.securityTier=="string"&&typeof e.valid=="boolean"&&typeof e.submit=="function"}var R=class extends p{#e=null;#t=null;#i=null;#n=null;#r=!1;#s=!1;#a="critical";#o;#c=`secure-submit-button-${Math.random().toString(36).substring(2,11)}`;#l;#u;#p;static get observedAttributes(){return[...super.observedAttributes,"label","loading-label","disabled"]}constructor(){super(),this.#o=v(this.#a),this.#l=this.#x.bind(this),this.#u=this.#E.bind(this),this.#p=()=>{this.#b(!1)}}connectedCallback(){super.connectedCallback(),queueMicrotask(()=>{this.#d(),this.#h(),this.#g(),this.#y(),this.audit("submit_button_initialized",{tier:this.#a,hasParentForm:!!this.#n})})}render(){let e=document.createDocumentFragment(),t=document.createElement("div");t.className="submit-container";let i=`${this.#c}-hint`,r=document.createElement("p");r.id=i,r.className="sr-only",r.textContent="Complete all required fields to enable this button",t.appendChild(r),this.#e=document.createElement("button"),this.#e.type="button",this.#e.className="submit-btn",this.#e.disabled=!0,this.#e.setAttribute("aria-disabled","true"),this.#e.setAttribute("aria-describedby",i),this.#t=document.createElement("span"),this.#t.className="btn-label",this.#t.textContent=this.sanitizeValue(this.getAttribute("label")||"Submit"),this.#i=document.createElement("span"),this.#i.className="btn-loading hidden",this.#i.setAttribute("aria-hidden","true");let s=document.createElement("span");s.className="spinner";let n=document.createElement("span");return n.textContent=this.sanitizeValue(this.getAttribute("loading-label")||"Submitting..."),this.#i.appendChild(s),this.#i.appendChild(n),this.#e.appendChild(this.#t),this.#e.appendChild(this.#i),this.#e.addEventListener("click",this.#u),t.appendChild(this.#e),e.appendChild(t),this.addComponentStyles(this.#f()),e}#d(){this.#n=this.closest("secure-form")}#h(){!this.getAttribute("security-tier")&&V(this.#n)?this.#a=this.#n.securityTier:this.#a=this.securityTier,this.#o=v(this.#a)}#g(){let e=this.#n||this.parentElement;e&&(e.addEventListener("secure-input-change",this.#l),e.addEventListener("secure-textarea-change",this.#l),e.addEventListener("secure-select-change",this.#l),e.addEventListener("secure-datetime-change",this.#l),e.addEventListener("secure-form-success",this.#p))}#x(e){this.#y()}#y(){if(this.hasAttribute("disabled")){this.#w(!0);return}if(!this.#s){if(!this.#o.validation.required){this.#r=!0,this.#w(!1);return}V(this.#n)?this.#r=this.#n.valid:this.#r=this.#v(),this.#w(!this.#r)}}#v(){let e=this.#n||this.parentElement;if(!e)return!1;let t=e.querySelectorAll("secure-input, secure-textarea, secure-select, secure-datetime, secure-file-upload");for(let i of t){let r=i;if(typeof r.valid=="boolean"&&!r.valid)return!1}return t.length>0}#w(e){this.#e&&(this.#e.disabled=e,this.#e.setAttribute("aria-disabled",String(e)))}#E(){if(this.#s||this.#e?.disabled)return;let e=this.checkRateLimit();if(!e.allowed){this.audit("submit_button_rate_limited",{retryAfter:e.retryAfter});return}this.audit("submit_button_clicked",{tier:this.#a,formValid:this.#r}),this.#b(!0),V(this.#n)?this.#n.submit():this.#b(!1)}#b(e){this.#s=e,this.#e&&(this.#e.disabled=e,this.#e.setAttribute("aria-disabled",String(e))),this.#t&&this.#t.classList.toggle("hidden",e),this.#i&&(this.#i.classList.toggle("hidden",!e),this.#i.setAttribute("aria-hidden",String(!e)))}handleAttributeChange(e,t,i){switch(e){case"label":this.#t&&(this.#t.textContent=this.sanitizeValue(i||"Submit"));break;case"loading-label":if(this.#i){let r=this.#i.querySelector("span:last-child");r&&(r.textContent=this.sanitizeValue(i||"Submitting..."))}break;case"disabled":this.#y();break}}get disabled(){return this.#e?this.#e.disabled:!0}set disabled(e){e?this.setAttribute("disabled",""):this.removeAttribute("disabled"),this.#y()}get label(){return this.getAttribute("label")||"Submit"}set label(e){this.setAttribute("label",e)}#f(){return":host { display: inline-block; } .submit-container { margin-top: 8px; position: relative; } .submit-btn { display: inline-flex; align-items: center; justify-content: center; gap: var(--secure-ui-space-2); padding: var(--secure-ui-button-padding-y) var(--secure-ui-button-padding-x); min-height: var(--secure-ui-button-height); font-family: inherit; font-size: var(--secure-ui-font-size-sm); font-weight: var(--secure-ui-button-font-weight); line-height: 1; border-radius: var(--secure-ui-button-border-radius); border: var(--secure-ui-border-width-base) solid transparent; cursor: pointer; transition: background-color var(--secure-ui-transition-base) var(--secure-ui-transition-ease-out), border-color var(--secure-ui-transition-base) var(--secure-ui-transition-ease-out), opacity var(--secure-ui-transition-base) var(--secure-ui-transition-ease-out), box-shadow var(--secure-ui-transition-base) var(--secure-ui-transition-ease-out), color var(--secure-ui-transition-base) var(--secure-ui-transition-ease-out), transform var(--secure-ui-transition-fast) var(--secure-ui-transition-ease-out); background-color: var(--secure-ui-color-info); color: var(--secure-ui-color-text-inverse); user-select: none; } .submit-btn:hover:not(:disabled) { background-color: color-mix(in srgb, var(--secure-ui-color-info) 82%, black); transform: translateY(-1px); box-shadow: 0 2px 8px rgba(59, 130, 246, 0.25); } .submit-btn:focus-visible { outline: 2px solid var(--secure-ui-color-info); outline-offset: 2px; box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.3); } @media (forced-colors: active) { .submit-btn:focus-visible { outline: 2px solid ButtonText; box-shadow: none; } } .submit-btn:active:not(:disabled) { background-color: color-mix(in srgb, var(--secure-ui-color-info) 72%, black); transform: scale(0.98); box-shadow: none; } .submit-btn:disabled { background-color: var(--secure-ui-color-bg-disabled); color: var(--secure-ui-color-text-disabled); border-color: var(--secure-ui-color-border); cursor: not-allowed; opacity: 0.7; transform: none; box-shadow: none; } .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; } .btn-label, .btn-loading { display: inline-flex; align-items: center; gap: 8px; transition: opacity 0.2s ease-out; } .btn-label.hidden, .btn-loading.hidden { display: none; } .spinner { display: inline-block; width: 14px; height: 14px; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: spin 0.6s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } @media (prefers-reduced-motion: reduce) { .submit-btn { transition: none !important; } .btn-label, .btn-loading { transition: none !important; } .spinner { animation: none; border-right-color: currentColor; opacity: 0.5; } }"}disconnectedCallback(){super.disconnectedCallback(),this.#b(!1);let e=this.#n||this.parentElement;e&&(e.removeEventListener("secure-input-change",this.#l),e.removeEventListener("secure-textarea-change",this.#l),e.removeEventListener("secure-select-change",this.#l),e.removeEventListener("secure-datetime-change",this.#l),e.removeEventListener("secure-form-success",this.#p))}};customElements.define("secure-submit-button",R);var W=Object.freeze([{type:"amex",pattern:/^3[47]/,format:[4,6,5],cvcLength:4,lengths:[15],label:"Amex"},{type:"diners",pattern:/^3(?:0[0-5]|[68])/,format:[4,6,4],cvcLength:3,lengths:[14],label:"Diners"},{type:"discover",pattern:/^6(?:011|5[0-9]{2})/,format:[4,4,4,4],cvcLength:3,lengths:[16],label:"Discover"},{type:"jcb",pattern:/^(?:2131|1800|35\d{3})/,format:[4,4,4,4],cvcLength:3,lengths:[16],label:"JCB"},{type:"mastercard",pattern:/^(?:5[1-5]|2[2-7])/,format:[4,4,4,4],cvcLength:3,lengths:[16],label:"Mastercard"},{type:"visa",pattern:/^4/,format:[4,4,4,4],cvcLength:3,lengths:[13,16,19],label:"Visa"}]);function Z(l){return l?W.find(e=>e.pattern.test(l))??null:null}function E(l,e){let t="",i=0;for(let r=0;r<e.length;r++){let s=l.slice(i,i+e[r]);if(!s)break;r>0&&(t+=" "),t+=s,i+=e[r]}return t}function X(l,e){let t=e.reduce((n,a)=>n+a,0);if(!l)return E("\u2022".repeat(t),e);let i=l.padEnd(t,"\u2022").slice(0,t),r=Math.max(0,i.length-4),s="\u2022".repeat(r)+i.slice(r);return E(s,e)}function Y(l){if(!l||l.length<12)return!1;let e=0,t=!1;for(let i=l.length-1;i>=0;i--){let r=l[i];if(!r)return!1;let s=parseInt(r,10);if(isNaN(s))return!1;let n=s;t&&(n*=2,n>9&&(n-=9)),e+=n,t=!t}return e%10===0}function U(l,e){let t=new Date,i=t.getFullYear()%100,r=t.getMonth()+1;return!(e<i||e===i&&l<r)}var J=0,j=class extends p{#e=null;#t=null;#i=null;#n=null;#r=null;#s=null;#a=null;#o=null;#c=null;#l=null;#u=null;#p=null;#d=null;#h=null;#g=null;#x=null;#y=null;#v="";#w="";#E="";#b="";#f=null;#m;constructor(){super(),this.#m=`secure-card-${++J}`}static get observedAttributes(){return[...super.observedAttributes,"name","label","show-name"]}render(){let e=document.createDocumentFragment(),t=this.hasAttribute("disabled"),i=this.hasAttribute("show-name"),r=this.getAttribute("label")??"",s=document.createElement("div");s.className="card-container",s.setAttribute("part","container");let n=document.createElement("div");n.className="card-scene",n.setAttribute("aria-hidden","true"),this.#r=document.createElement("div"),this.#r.className="card";let a=document.createElement("div");a.className="card-face card-front";let o=document.createElement("div");o.className="card-top-row";let d=document.createElement("div");d.className="card-chip",this.#c=document.createElement("div"),this.#c.className="card-type-label",o.appendChild(d),o.appendChild(this.#c),a.appendChild(o),this.#s=document.createElement("div"),this.#s.className="card-number-display",this.#s.textContent="\u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022",a.appendChild(this.#s);let c=document.createElement("div");c.className="card-bottom-row";let m=document.createElement("div");m.className="card-name-section";let g=document.createElement("div");g.className="card-field-label",g.textContent="Card holder",this.#o=document.createElement("div"),this.#o.className="card-name-display",this.#o.textContent="FULL NAME",m.appendChild(g),m.appendChild(this.#o);let f=document.createElement("div");f.className="card-expiry-section";let h=document.createElement("div");h.className="card-field-label",h.textContent="Expires",this.#a=document.createElement("div"),this.#a.className="card-expiry-display",this.#a.textContent="MM/YY",f.appendChild(h),f.appendChild(this.#a),c.appendChild(m),c.appendChild(f),a.appendChild(c);let C=document.createElement("div");C.className="card-face card-back";let O=document.createElement("div");O.className="card-strip";let T=document.createElement("div");T.className="card-cvc-area";let q=document.createElement("div");q.className="card-cvc-label",q.textContent="CVC",this.#l=document.createElement("div"),this.#l.className="card-cvc-display",this.#l.textContent="\u2022\u2022\u2022",T.appendChild(q),T.appendChild(this.#l),C.appendChild(O),C.appendChild(T),this.#r.appendChild(a),this.#r.appendChild(C),n.appendChild(this.#r);let x=document.createElement("div");if(x.className="card-fields",r){let b=document.createElement("div");b.className="card-legend",b.setAttribute("part","label"),b.textContent=this.sanitizeValue(r),x.appendChild(b)}let L=this.#A(`${this.#m}-number`),K=L.querySelector("label");K.textContent="Card number",this.#e=document.createElement("input"),this.#e.id=`${this.#m}-number`,this.#e.className="card-input card-number-input",this.#e.setAttribute("type","text"),this.#e.setAttribute("inputmode","numeric"),this.#e.setAttribute("autocomplete","off"),this.#e.setAttribute("placeholder","0000 0000 0000 0000"),this.#e.setAttribute("maxlength","23"),this.#e.setAttribute("aria-required","true"),this.#e.setAttribute("aria-describedby",`${this.#m}-number-error`),this.#e.setAttribute("part","number-input"),t&&(this.#e.disabled=!0),this.#u=L.querySelector(".error-container"),this.#u.id=`${this.#m}-number-error`,L.querySelector(".input-wrapper").appendChild(this.#e),x.appendChild(L);let S=document.createElement("div");S.className="field-row";let k=this.#A(`${this.#m}-expiry`);k.querySelector("label").textContent="Expiry date",this.#t=document.createElement("input"),this.#t.id=`${this.#m}-expiry`,this.#t.className="card-input",this.#t.setAttribute("type","text"),this.#t.setAttribute("inputmode","numeric"),this.#t.setAttribute("autocomplete","off"),this.#t.setAttribute("placeholder","MM/YY"),this.#t.setAttribute("maxlength","5"),this.#t.setAttribute("aria-required","true"),this.#t.setAttribute("aria-describedby",`${this.#m}-expiry-error`),this.#t.setAttribute("part","expiry-input"),t&&(this.#t.disabled=!0),this.#p=k.querySelector(".error-container"),this.#p.id=`${this.#m}-expiry-error`,k.querySelector(".input-wrapper").appendChild(this.#t);let z=this.#A(`${this.#m}-cvc`);z.querySelector("label").textContent="Security code",this.#i=document.createElement("input"),this.#i.id=`${this.#m}-cvc`,this.#i.className="card-input cvc-input",this.#i.setAttribute("type","password"),this.#i.setAttribute("inputmode","numeric"),this.#i.setAttribute("autocomplete","off"),this.#i.setAttribute("placeholder","\u2022\u2022\u2022"),this.#i.setAttribute("maxlength","4"),this.#i.setAttribute("aria-required","true"),this.#i.setAttribute("aria-describedby",`${this.#m}-cvc-error`),this.#i.setAttribute("part","cvc-input"),t&&(this.#i.disabled=!0),this.#d=z.querySelector(".error-container"),this.#d.id=`${this.#m}-cvc-error`,z.querySelector(".input-wrapper").appendChild(this.#i),S.appendChild(k),S.appendChild(z),x.appendChild(S);let w=this.#A(`${this.#m}-name`);return w.id=`${this.#m}-name-group`,w.querySelector("label").textContent="Cardholder name",i||(w.hidden=!0),this.#n=document.createElement("input"),this.#n.id=`${this.#m}-name`,this.#n.className="card-input",this.#n.setAttribute("type","text"),this.#n.setAttribute("autocomplete","off"),this.#n.setAttribute("placeholder","Name as it appears on card"),this.#n.setAttribute("spellcheck","false"),this.#n.setAttribute("aria-describedby",`${this.#m}-name-error`),this.#n.setAttribute("part","name-input"),t&&(this.#n.disabled=!0),this.#h=w.querySelector(".error-container"),this.#h.id=`${this.#m}-name-error`,w.querySelector(".input-wrapper").appendChild(this.#n),x.appendChild(w),s.appendChild(n),s.appendChild(x),this.#_(),this.addComponentStyles(":host { --secure-card-width: 340px; --secure-card-radius: 16px; --secure-card-font: var(--secure-ui-font-family-mono, 'Courier New', monospace); --secure-card-transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1); --secure-card-gradient: linear-gradient(135deg, #1e2a4a 0%, #2d4a8a 100%); display: block; } .card-container { width: 100%; max-width: 480px; font-family: var(--secure-ui-font-family-sans, system-ui, sans-serif); } .card-scene { width: var(--secure-card-width); max-width: 100%; aspect-ratio: 85.6 / 54; perspective: 1000px; margin-inline: auto; margin-block-end: var(--secure-ui-space-6, 1.5rem); user-select: none; } .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: var(--secure-card-transition); border-radius: var(--secure-card-radius); filter: drop-shadow(0 8px 24px rgba(0, 0, 0, 0.35)); } .card.is-flipped { transform: rotateY(180deg); } .card-face { position: absolute; inset: 0; border-radius: var(--secure-card-radius); backface-visibility: hidden; -webkit-backface-visibility: hidden; background: var(--secure-card-gradient); color: #fff; overflow: hidden; } .card-face::before { content: ''; position: absolute; inset: 0; background: linear-gradient( 135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0) 60% ); border-radius: inherit; pointer-events: none; } .card-back { transform: rotateY(180deg); } .card--visa { --secure-card-gradient: linear-gradient(135deg, #1a1f71 0%, #2563eb 100%); } .card--mastercard { --secure-card-gradient: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #e63946 100%); } .card--amex { --secure-card-gradient: linear-gradient(135deg, #007b5e 0%, #00b894 100%); } .card--discover { --secure-card-gradient: linear-gradient(135deg, #b34700 0%, #e65c00 50%, #f9a825 100%); } .card--diners { --secure-card-gradient: linear-gradient(135deg, #005c97 0%, #363795 100%); } .card--jcb { --secure-card-gradient: linear-gradient(135deg, #0e4c96 0%, #e63946 100%); } .card-front { display: flex; flex-direction: column; justify-content: space-between; padding: 20px 24px 18px; } .card-top-row { display: flex; align-items: center; justify-content: space-between; } .card-chip { width: 42px; height: 32px; background: linear-gradient(135deg, #c8a84b 0%, #f0d060 40%, #c8a84b 100%); border-radius: 5px; position: relative; flex-shrink: 0; } .card-chip::before { content: ''; position: absolute; inset: 9px 0; border-top: 1.5px solid rgba(0, 0, 0, 0.25); border-bottom: 1.5px solid rgba(0, 0, 0, 0.25); } .card-chip::after { content: ''; position: absolute; inset: 0 13px; border-left: 1.5px solid rgba(0, 0, 0, 0.2); border-right: 1.5px solid rgba(0, 0, 0, 0.2); border-radius: 2px; } .card-type-label { font-size: 1rem; font-weight: 700; letter-spacing: 0.06em; font-style: italic; opacity: 0.95; min-width: 52px; text-align: end; text-transform: uppercase; } .card--mastercard .card-type-label { position: relative; width: 52px; height: 32px; font-size: 0; } .card--mastercard .card-type-label::before, .card--mastercard .card-type-label::after { content: ''; position: absolute; top: 50%; transform: translateY(-50%); width: 28px; height: 28px; border-radius: 50%; } .card--mastercard .card-type-label::before { background: #eb001b; inset-inline-start: 0; } .card--mastercard .card-type-label::after { background: #f79e1b; inset-inline-start: 16px; mix-blend-mode: multiply; } .card-number-display { font-family: var(--secure-card-font); font-size: clamp(0.85rem, 2.5vw, 1.1rem); letter-spacing: 0.18em; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.4); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .card-bottom-row { display: flex; justify-content: space-between; align-items: flex-end; gap: var(--secure-ui-space-3, 0.75rem); } .card-field-label { font-size: 0.6rem; text-transform: uppercase; letter-spacing: 0.12em; opacity: 0.7; margin-block-end: 2px; } .card-name-display { font-size: clamp(0.7rem, 2vw, 0.85rem); letter-spacing: 0.06em; font-weight: 500; text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 160px; } .card-expiry-display { font-family: var(--secure-card-font); font-size: 0.85rem; letter-spacing: 0.1em; white-space: nowrap; } .card-back { display: flex; flex-direction: column; gap: var(--secure-ui-space-3, 0.75rem); } .card-strip { width: 100%; height: 40px; background: #1a1a1a; margin-block-start: 28px; flex-shrink: 0; } .card-cvc-area { display: flex; flex-direction: column; align-items: flex-end; padding-inline-end: 24px; gap: 4px; } .card-cvc-label { font-size: 0.6rem; text-transform: uppercase; letter-spacing: 0.1em; opacity: 0.7; } .card-cvc-display { background: #fff; color: #1a1a1a; font-family: var(--secure-card-font); font-size: 0.85rem; letter-spacing: 0.2em; padding: 4px 10px; border-radius: 3px; min-width: 52px; text-align: center; } .card-fields { display: flex; flex-direction: column; gap: var(--secure-ui-space-4, 1rem); } .card-legend { font-size: var(--secure-ui-font-size-sm, 0.875rem); font-weight: var(--secure-ui-font-weight-semibold, 600); color: var(--secure-ui-color-neutral-700, #374151); margin-block-end: var(--secure-ui-space-1, 0.25rem); } .field-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--secure-ui-space-4, 1rem); } .field-group { display: flex; flex-direction: column; gap: var(--secure-ui-space-1, 0.25rem); position: relative; } .field-label { font-size: var(--secure-ui-font-size-sm, 0.875rem); font-weight: var(--secure-ui-font-weight-medium, 500); color: var(--secure-ui-color-neutral-700, #374151); line-height: var(--secure-ui-line-height-tight, 1.25); } .input-wrapper { position: relative; } .card-input { width: 100%; box-sizing: border-box; padding: var(--secure-ui-input-padding-y, 0.625rem) var(--secure-ui-input-padding-x, 0.75rem); font-family: var(--secure-ui-font-family-sans, system-ui, sans-serif); font-size: var(--secure-ui-font-size-base, 1rem); line-height: var(--secure-ui-line-height-normal, 1.5); color: var(--secure-ui-input-color, #111827); background: var(--secure-ui-input-bg, #fff); border: var(--secure-ui-border-width, 1px) solid var(--secure-ui-input-border-color, #d1d5db); border-radius: var(--secure-ui-input-border-radius, 6px); outline: none; transition: border-color var(--secure-ui-transition-fast, 150ms) ease, box-shadow var(--secure-ui-transition-fast, 150ms) ease; appearance: none; -webkit-appearance: none; } .card-input:focus { border-color: var(--secure-ui-color-primary-500, #6366f1); box-shadow: 0 0 0 3px var(--secure-ui-color-primary-100, rgba(99, 102, 241, 0.2)); } .card-input[aria-invalid='true'] { border-color: var(--secure-ui-color-error-500, #ef4444) !important; box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.15); } .card-input:disabled { background: var(--secure-ui-input-disabled-bg, #f3f4f6); color: var(--secure-ui-color-neutral-400, #9ca3af); cursor: not-allowed; } .card-number-input { font-family: var(--secure-card-font); letter-spacing: 0.06em; } .cvc-input::-ms-reveal, .cvc-input::-ms-clear { display: none; } .error-container { font-size: var(--secure-ui-font-size-xs, 0.75rem); color: var(--secure-ui-color-error-600, #dc2626); line-height: var(--secure-ui-line-height-tight, 1.25); min-height: 0; max-height: 3rem; overflow: hidden; transition: max-height var(--secure-ui-transition-normal, 250ms) ease, opacity var(--secure-ui-transition-fast, 150ms) ease; opacity: 1; } .error-container.hidden { max-height: 0; opacity: 0; } @media (prefers-color-scheme: dark) { .card-legend { color: var(--secure-ui-color-neutral-200, #e5e7eb); } .field-label { color: var(--secure-ui-color-neutral-200, #e5e7eb); } .card-input { color: var(--secure-ui-input-color, #f9fafb); background: var(--secure-ui-input-bg, #1f2937); border-color: var(--secure-ui-input-border-color, #374151); } .card-input:disabled { background: #111827; color: #6b7280; } .card-cvc-display { background: #f9fafb; color: #111827; } } @media (prefers-reduced-motion: reduce) { .card { transition: none; } .card-input { transition: none; } .error-container { transition: none; } } @media (max-width: 400px) { .field-row { grid-template-columns: 1fr; } }"),this.setupAutofillDetection(this.#e),this.setupAutofillDetection(this.#t),this.setupAutofillDetection(this.#i),this.setupAutofillDetection(this.#n),this.#e.addEventListener("input",b=>{this.recordTelemetryInput(b),this.#S(b)}),this.#e.addEventListener("focus",()=>{this.recordTelemetryFocus(),this.#M()}),this.#e.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#k()}),this.#t.addEventListener("input",b=>{this.recordTelemetryInput(b),this.#N(b)}),this.#t.addEventListener("focus",()=>{this.recordTelemetryFocus(),this.#I(!1)}),this.#t.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#$()}),this.#i.addEventListener("input",b=>{this.recordTelemetryInput(b),this.#H(b)}),this.#i.addEventListener("focus",()=>{this.recordTelemetryFocus(),this.#I(!0)}),this.#i.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#L()}),this.#n.addEventListener("input",b=>{this.recordTelemetryInput(b),this.#D(b)}),this.#n.addEventListener("focus",()=>{this.recordTelemetryFocus(),this.#I(!1)}),this.#n.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#F()}),e.appendChild(s),e}#A(e){let t=document.createElement("div");t.className="field-group";let i=document.createElement("label");i.htmlFor=e,i.className="field-label";let r=document.createElement("div");r.className="input-wrapper",r.setAttribute("part","wrapper");let s=document.createElement("div");return s.className="error-container hidden",s.setAttribute("role","alert"),s.setAttribute("part","error"),t.appendChild(i),t.appendChild(r),t.appendChild(s),t}handleAttributeChange(e,t,i){if(this.shadowRoot)switch(e){case"disabled":{let r=i!==null;this.#e&&(this.#e.disabled=r),this.#t&&(this.#t.disabled=r),this.#i&&(this.#i.disabled=r),this.#n&&(this.#n.disabled=r);break}case"show-name":{let r=this.shadowRoot.querySelector(`#${this.#m}-name-group`);r&&(r.hidden=i===null);break}}}#S(e){let t=e.target,i=t.value.replace(/\D/g,""),r=this.#f?.type;this.#f=Z(i);let s=this.#f?.format??[4,4,4,4],n=s.reduce((a,o)=>a+o,0);if(this.#v=i.slice(0,n),t.value=E(this.#v,s),this.#f?.type!==r){let a=n+s.length-1;t.setAttribute("maxlength",String(a));let o=this.#f?.cvcLength??3;this.#i&&this.#i.setAttribute("maxlength",String(o)),this.#P()}this.#s&&(this.#s.textContent=t.value||E("\u2022".repeat(n),s)),this.#C(this.#u),this.#R(),this.#j()}#M(){if(this.#e&&this.#v){let e=this.#f?.format??[4,4,4,4],t=E(this.#v,e);this.#e.value=t,this.#s&&(this.#s.textContent=t)}this.#I(!1),this.#C(this.#u)}#k(){let e=this.checkRateLimit();if(!e.allowed){this.#z(this.#u,`Too many attempts. Try again in ${Math.ceil(e.retryAfter/1e3)}s.`);return}this.#v?Y(this.#v)?(this.#C(this.#u),this.#e?.removeAttribute("aria-invalid")):(this.#z(this.#u,"Invalid card number"),this.#e?.setAttribute("aria-invalid","true")):(this.#z(this.#u,"Card number is required"),this.#e?.setAttribute("aria-invalid","true")),this.#T(),this.audit("card-number-blur",{cardType:this.#f?.type??"unknown"})}#T(){let e=this.#f?.format??[4,4,4,4],t=X(this.#v,e);this.#e&&(this.#e.value=t),this.#s&&(this.#s.textContent=t)}#N(e){let t=e.target,i=t.value.replace(/\D/g,"").slice(0,4),r=i.length>2?`${i.slice(0,2)}/${i.slice(2)}`:i;t.value=r,this.#E=r,this.#a&&(this.#a.textContent=r||"MM/YY"),this.#C(this.#p),this.#R(),this.#j()}#$(){let e=this.#E.split("/");if(!this.#E){this.#z(this.#p,"Expiry date is required"),this.#t?.setAttribute("aria-invalid","true");return}let t=parseInt(e[0]??"",10),i=parseInt(e[1]??"",10);isNaN(t)||isNaN(i)||t<1||t>12||(e[1]??"").length<2?(this.#z(this.#p,"Enter a valid expiry date (MM/YY)"),this.#t?.setAttribute("aria-invalid","true")):U(t,i)?(this.#C(this.#p),this.#t?.removeAttribute("aria-invalid")):(this.#z(this.#p,"This card has expired"),this.#t?.setAttribute("aria-invalid","true")),this.audit("card-expiry-blur",{})}#H(e){let t=e.target,i=t.value.replace(/\D/g,""),r=this.#f?.cvcLength??3;this.#w=i.slice(0,r),t.value=this.#w,this.#l&&(this.#l.textContent=this.#w.length>0?"\u2022".repeat(this.#w.length):"\u2022\u2022\u2022"),this.#C(this.#d),this.#j()}#L(){let e=this.#f?.cvcLength??3;this.#w?this.#w.length<e?(this.#z(this.#d,`Security code must be ${e} digits`),this.#i?.setAttribute("aria-invalid","true")):(this.#C(this.#d),this.#i?.removeAttribute("aria-invalid")):(this.#z(this.#d,"Security code is required"),this.#i?.setAttribute("aria-invalid","true")),this.#I(!1),this.audit("card-cvc-blur",{})}#D(e){let t=e.target,i=t.value.replace(/[^a-zA-Z\s\-']/g,"").slice(0,50);t.value=i,this.#b=i,this.#o&&(this.#o.textContent=i.toUpperCase()||"FULL NAME"),this.#C(this.#h),this.#R(),this.#j()}#F(){this.hasAttribute("show-name")&&(this.#b.trim()?(this.#C(this.#h),this.#n?.removeAttribute("aria-invalid")):(this.#z(this.#h,"Cardholder name is required"),this.#n?.setAttribute("aria-invalid","true")))}#I(e){this.#r?.classList.toggle("is-flipped",e)}#P(){if(!this.#r)return;for(let t of W)this.#r.classList.remove(`card--${t.type}`);let e=this.#f?.type;e&&this.#r.classList.add(`card--${e}`),this.#c&&(this.#c.textContent=this.#f?.label??"")}#z(e,t){if(!e)return;e.textContent="";let i=document.createElement("span");i.textContent=t,e.appendChild(i),e.classList.remove("hidden")}#C(e){e&&(e.textContent="",e.classList.add("hidden"))}#_(){let e=this.getAttribute("name");e&&(this.#g=document.createElement("input"),this.#g.type="hidden",this.#g.name=e,this.appendChild(this.#g),this.#x=document.createElement("input"),this.#x.type="hidden",this.#x.name=`${e}-expiry`,this.appendChild(this.#x),this.#y=document.createElement("input"),this.#y.type="hidden",this.#y.name=`${e}-holder`,this.appendChild(this.#y))}#R(){this.#g&&(this.#g.value=this.#v.slice(-4)),this.#x&&(this.#x.value=this.#E),this.#y&&(this.#y.value=this.#b)}#j(){let[e,t]=this.#E.split("/");this.dispatchEvent(new CustomEvent("secure-card-change",{bubbles:!0,composed:!0,detail:{name:this.getAttribute("name")??"",cardType:this.#f?.type??"unknown",last4:this.#v.slice(-4),expiryMonth:parseInt(e??"0",10)||0,expiryYear:(()=>{let i=parseInt(t??"0",10);return i>0?2e3+i:0})(),cardholderName:this.#b,valid:this.valid,tier:this.securityTier}}))}disconnectedCallback(){this.#v="",this.#w="",this.#E="",this.#b="",this.#e&&(this.#e.value=""),this.#t&&(this.#t.value=""),this.#i&&(this.#i.value=""),this.#n&&(this.#n.value=""),this.#g&&(this.#g.value=""),this.#x&&(this.#x.value=""),this.#y&&(this.#y.value=""),super.disconnectedCallback()}get valid(){let e=this.#v.length>=12&&Y(this.#v),[t,i]=this.#E.split("/"),r=parseInt(t??"",10),s=parseInt(i??"",10),n=!isNaN(r)&&!isNaN(s)&&r>=1&&r<=12&&(i??"").length>=2&&U(r,s),a=this.#f?.cvcLength??3,o=this.#w.length===a,d=!this.hasAttribute("show-name")||this.#b.trim().length>0;return e&&n&&o&&d}get cardType(){return this.#f?.type??"unknown"}get last4(){return this.#v.slice(-4)}get name(){return this.getAttribute("name")??""}getCardData(){return this.valid?{number:this.#v,expiry:this.#E,cvc:this.#w,name:this.#b}:null}reset(){this.#v="",this.#w="",this.#E="",this.#b="",this.#f=null,this.#e&&(this.#e.value=""),this.#t&&(this.#t.value=""),this.#i&&(this.#i.value=""),this.#n&&(this.#n.value=""),this.#R(),this.#I(!1),this.#P();let e=[4,4,4,4];this.#s&&(this.#s.textContent=E("\u2022".repeat(16),e)),this.#a&&(this.#a.textContent="MM/YY"),this.#o&&(this.#o.textContent="FULL NAME"),this.#l&&(this.#l.textContent="\u2022\u2022\u2022"),this.#C(this.#u),this.#C(this.#p),this.#C(this.#d),this.#C(this.#h),this.audit("card-reset",{})}focus(){this.#e?.focus()}};customElements.define("secure-card",j);var P=class extends HTMLElement{static get observedAttributes(){return[]}#e="";#t={mouseMovementDetected:!1,keyboardActivityDetected:!1,injectedScriptCount:0,domMutationDetected:!1,pointerType:"none",firstKeystrokeAt:-1,threatSignals:[]};#i=0;#n=null;#r=new Set;#s=null;#a="";#o=()=>{this.#t.mouseMovementDetected=!0};#c=()=>{this.#t.keyboardActivityDetected=!0,this.#t.firstKeystrokeAt<0&&(this.#t.firstKeystrokeAt=performance.now())};#l=e=>{this.#t.pointerType=e.pointerType};#u=e=>{this.#v(e)};#p=e=>{this.#t.threatSignals.push(e.detail)};connectedCallback(){this.#i=performance.now();let e=this.getAttribute("signing-key");e&&(this.#e=e,this.removeAttribute("signing-key")),document.querySelectorAll("script").forEach(t=>this.#r.add(t)),this.#d(),this.#h()}disconnectedCallback(){this.#n?.disconnect(),this.#n=null,this.#g(),this.#s=null,this.#a="",this.#e=""}setSigningKey(e){e!==this.#e&&(this.#e=e,this.#s=null,this.#a="")}#d(){this.#n=new MutationObserver(e=>{for(let t of e)if(t.type==="childList")for(let i of Array.from(t.addedNodes))i.tagName==="SCRIPT"&&!this.#r.has(i)&&(this.#t.injectedScriptCount++,this.#t.domMutationDetected=!0,this.#r.add(i))}),this.#n.observe(document.documentElement,{childList:!0,subtree:!0})}#h(){document.addEventListener("mousemove",this.#o,{passive:!0}),document.addEventListener("keydown",this.#c,{passive:!0}),document.addEventListener("pointerdown",this.#l,{passive:!0}),this.addEventListener("secure-form-submit",this.#u),this.addEventListener("secure-threat-detected",this.#p)}#g(){document.removeEventListener("mousemove",this.#o),document.removeEventListener("keydown",this.#c),document.removeEventListener("pointerdown",this.#l),this.removeEventListener("secure-form-submit",this.#u),this.removeEventListener("secure-threat-detected",this.#p)}collectSignals(){let e=navigator,t=e.webdriver===!0||Object.prototype.hasOwnProperty.call(e,"webdriver"),i=navigator.userAgent,r=i.includes("HeadlessChrome")||i.includes("Headless")||typeof window.chrome>"u"&&i.includes("Chrome"),s=screen.width===0||screen.height===0||screen.width<100&&screen.height<100,n=performance.now(),a=this.#t.firstKeystrokeAt>=0?Math.round(this.#t.firstKeystrokeAt-this.#i):-1,o=Math.round(n-this.#i);return{webdriverDetected:t,headlessDetected:r,domMutationDetected:this.#t.domMutationDetected,injectedScriptCount:this.#t.injectedScriptCount,suspiciousScreenSize:s,pointerType:this.#t.pointerType,mouseMovementDetected:this.#t.mouseMovementDetected,keyboardActivityDetected:this.#t.keyboardActivityDetected,pageLoadToFirstKeystroke:a,loadToSubmit:o,threatSignals:this.#t.threatSignals.length>0?[...this.#t.threatSignals]:void 0}}async sign(e){let t=this.#x(),i=new Date().toISOString(),r=this.#e,s=`${t}.${i}.${JSON.stringify(e)}`,n=await this.#y(r,s);return{nonce:t,issuedAt:i,environment:e,signature:n}}#x(){let e=new Uint8Array(16);return crypto.getRandomValues(e),Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}async#y(e,t){if(!crypto.subtle)return"";let i=new TextEncoder;(this.#s===null||this.#a!==e)&&(this.#s=await crypto.subtle.importKey("raw",i.encode(e),{name:"HMAC",hash:"SHA-256"},!1,["sign"]),this.#a=e);let r=await crypto.subtle.sign("HMAC",this.#s,i.encode(t));return Array.from(new Uint8Array(r),s=>s.toString(16).padStart(2,"0")).join("")}async#v(e){let t=e.detail;if(t?.telemetry)try{let i=this.collectSignals(),r=await this.sign(i);t.telemetry._env=r}catch{}}getEnvironmentalSignals(){return this.collectSignals()}};customElements.define("secure-telemetry-provider",P);var _=class extends p{#e=null;#t=null;#i=null;#n=null;#r=null;#s=null;#a=null;#o="";#c="";#l=!1;#u=!1;#p=!1;#d=null;#h=`secure-password-confirm-${Math.random().toString(36).substring(2,11)}`;connectedCallback(){let e=this.getAttribute("security-tier");e&&e!=="critical"&&console.warn(`secure-password-confirm: security-tier="${e}" ignored \u2014 this component is locked to CRITICAL.`),this.removeAttribute("security-tier"),super.connectedCallback()}static get observedAttributes(){return[...super.observedAttributes,"name","label","password-label","confirm-label","required","minlength"]}render(){let e=document.createDocumentFragment(),t=document.createElement("div");t.className="container",t.setAttribute("part","container");let i=this.getAttribute("label");if(i){let a=document.createElement("div");a.className="group-label",a.textContent=this.sanitizeValue(i),t.appendChild(a)}let r=this.hasAttribute("required"),s=this.#g({inputPart:"password-input",wrapperPart:"password-wrapper",labelPart:"password-label",errorPart:"password-error",togglePart:"password-toggle",labelText:this.getAttribute("password-label")??"New Password",inputId:`${this.#h}-password`,errorId:`${this.#h}-password-error`,isRequired:r});this.#e=s.querySelector('[part="password-input"]'),this.#s=s.querySelector('[part="password-toggle"]'),this.#i=s.querySelector('[part="password-error"]');let n=this.#g({inputPart:"confirm-input",wrapperPart:"confirm-wrapper",labelPart:"confirm-label",errorPart:"confirm-error",togglePart:"confirm-toggle",labelText:this.getAttribute("confirm-label")??"Confirm Password",inputId:`${this.#h}-confirm`,errorId:`${this.#h}-confirm-error`,isRequired:r});return this.#t=n.querySelector('[part="confirm-input"]'),this.#a=n.querySelector('[part="confirm-toggle"]'),this.#n=n.querySelector('[part="confirm-error"]'),this.#r=document.createElement("div"),this.#r.setAttribute("part","match-indicator"),this.#r.className="match-indicator",this.#r.setAttribute("aria-hidden","true"),t.appendChild(s),t.appendChild(n),t.appendChild(this.#r),this.#x(),this.#y(),this.#v(),this.#M(),this.addComponentStyles('.container { display: flex; flex-direction: column; gap: var(--secure-ui-form-gap); font-family: var(--secure-ui-font-family-base); } .group-label { font-size: var(--secure-ui-label-font-size); font-weight: var(--secure-ui-label-font-weight); color: var(--secure-ui-label-color); margin-bottom: var(--secure-ui-space-1); } .field-section { display: flex; flex-direction: column; gap: var(--secure-ui-form-label-margin-bottom); } label { font-size: var(--secure-ui-label-font-size); font-weight: var(--secure-ui-label-font-weight); color: var(--secure-ui-label-color); } .input-wrapper { position: relative; display: flex; align-items: center; } input[type="password"], input[type="text"] { flex: 1; height: var(--secure-ui-input-height); padding: var(--secure-ui-input-padding-y) var(--secure-ui-input-padding-x); padding-inline-end: calc(var(--secure-ui-input-padding-x) * 3.5); font-family: var(--secure-ui-font-family-base); font-size: var(--secure-ui-input-font-size); color: var(--secure-ui-input-text-color); background-color: var(--secure-ui-input-bg); border: var(--secure-ui-input-border-width) solid var(--secure-ui-input-border-color); border-radius: var(--secure-ui-input-border-radius); box-sizing: border-box; transition: border-color var(--secure-ui-transition-base), box-shadow var(--secure-ui-transition-base); } input:hover:not(:disabled) { border-color: var(--secure-ui-input-border-color-hover); } input:focus { outline: none; border-color: var(--secure-ui-input-border-color-focus); box-shadow: var(--secure-ui-shadow-focus); } input[aria-invalid="true"] { border-color: var(--secure-ui-color-error) !important; } input[aria-invalid="true"]:focus { box-shadow: var(--secure-ui-shadow-focus-error); } .toggle-btn { position: absolute; inset-inline-end: var(--secure-ui-space-2); display: flex; align-items: center; justify-content: center; background: none; border: none; cursor: pointer; color: var(--secure-ui-color-text-secondary); padding: var(--secure-ui-space-1); border-radius: var(--secure-ui-border-radius-sm); line-height: 1; transition: color var(--secure-ui-transition-base); } .toggle-btn:hover { color: var(--secure-ui-color-text-primary); } .toggle-btn:focus-visible { outline: 2px solid var(--secure-ui-input-border-color-focus); outline-offset: 2px; } .toggle-btn:active .eye-icon { transform: scale(0.85); } .eye-icon { display: block; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; transition: transform 0.15s ease; overflow: visible; } .eye-outline { transition: d 0.2s ease; } .eye-pupil { transform-origin: 12px 12px; transition: opacity 0.2s ease, transform 0.2s ease; } .eye-slash { stroke-dasharray: 26; stroke-dashoffset: 26; transition: stroke-dashoffset 0.3s ease; } .toggle-btn.is-visible .eye-pupil { opacity: 0; transform: scale(0.2); } .toggle-btn.is-visible .eye-slash { stroke-dashoffset: 0; } .error-container { font-size: var(--secure-ui-error-font-size); color: var(--secure-ui-error-color); line-height: var(--secure-ui-line-height-normal); overflow: hidden; max-height: 40px; opacity: 1; transition: all 0.2s ease-in-out; } .error-container.hidden { max-height: 0; opacity: 0; pointer-events: none; } .match-indicator { font-size: var(--secure-ui-font-size-sm); line-height: var(--secure-ui-line-height-normal); min-height: 1.25em; } .match-indicator.matched { color: var(--secure-ui-color-success, #2e7d32); } .match-indicator.mismatched { color: var(--secure-ui-color-error); } @media (prefers-reduced-motion: reduce) { input, .error-container, .eye-icon, .eye-pupil, .eye-slash { transition: none !important; } }'),e.appendChild(t),e}#g(e){let t=document.createElement("div");t.className="field-section";let i=document.createElement("label");i.setAttribute("part",e.labelPart),i.htmlFor=e.inputId,i.textContent=this.sanitizeValue(e.labelText);let r=document.createElement("div");r.className="input-wrapper",r.setAttribute("part",e.wrapperPart);let s=document.createElement("input");s.id=e.inputId,s.type="password",s.autocomplete="new-password",s.setAttribute("part",e.inputPart),s.setAttribute("aria-describedby",e.errorId),e.isRequired&&(s.required=!0,s.setAttribute("aria-required","true"));let n=document.createElement("button");n.type="button",n.className="toggle-btn",n.setAttribute("part",e.togglePart),n.setAttribute("aria-label","Show password"),n.appendChild(this.#w()),r.appendChild(s),r.appendChild(n);let a=document.createElement("div");return a.id=e.errorId,a.setAttribute("part",e.errorPart),a.setAttribute("role","alert"),a.className="error-container hidden",t.appendChild(i),t.appendChild(r),t.appendChild(a),t}#x(){this.setupAutofillDetection(this.#e),this.#e.addEventListener("focus",()=>{this.recordTelemetryFocus()}),this.#e.addEventListener("input",e=>{this.recordTelemetryInput(e),this.#o=this.#e.value,this.detectInjection(this.#o,this.getAttribute("name")??""),this.#l&&this.#f(),this.dispatchEvent(new CustomEvent("secure-input-change",{detail:{name:this.getAttribute("name")??"",field:"password"},bubbles:!0,composed:!0}))}),this.#e.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#E()})}#y(){this.#t.addEventListener("input",()=>{this.#c=this.#t.value,this.detectInjection(this.#c,this.getAttribute("name")??""),this.#l&&this.#f()}),this.#t.addEventListener("blur",()=>{this.#l=!0,this.#c=this.#t.value,this.#f()})}#v(){this.#s.addEventListener("click",()=>{this.#u=!this.#u,this.#e.type=this.#u?"text":"password",this.#s.classList.toggle("is-visible",this.#u),this.#s.setAttribute("aria-label",this.#u?"Hide password":"Show password")}),this.#a.addEventListener("click",()=>{this.#p=!this.#p,this.#t.type=this.#p?"text":"password",this.#a.classList.toggle("is-visible",this.#p),this.#a.setAttribute("aria-label",this.#p?"Hide confirm password":"Show confirm password")})}#w(){let e="http://www.w3.org/2000/svg",t=document.createElementNS(e,"svg");t.setAttribute("viewBox","0 0 24 24"),t.setAttribute("aria-hidden","true"),t.setAttribute("class","eye-icon"),t.setAttribute("width","18"),t.setAttribute("height","18");let i=document.createElementNS(e,"path");i.setAttribute("class","eye-outline"),i.setAttribute("d","M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z");let r=document.createElementNS(e,"circle");r.setAttribute("class","eye-pupil"),r.setAttribute("cx","12"),r.setAttribute("cy","12"),r.setAttribute("r","3");let s=document.createElementNS(e,"line");return s.setAttribute("class","eye-slash"),s.setAttribute("x1","3"),s.setAttribute("y1","3"),s.setAttribute("x2","21"),s.setAttribute("y2","21"),t.append(i,r,s),t}#E(){let e=this.#b(this.#o);e?this.#m(this.#i,this.#e,e):this.#A(this.#i,this.#e)}#b(e){return e?e.length<8?"Password must be at least 8 characters":/[a-z]/.test(e)?/[A-Z]/.test(e)?/[0-9]/.test(e)?/[^a-zA-Z0-9]/.test(e)?null:"Password must include a special character":"Password must include a number":"Password must include an uppercase letter":"Password must include a lowercase letter":null}#f(){let e=this.#o.length>0&&this.#o===this.#c;if(this.#k(e),this.#S(e),e)this.#A(this.#n,this.#t),this.dispatchEvent(new CustomEvent("secure-password-match",{detail:{name:this.getAttribute("name")??"",matched:!0},bubbles:!0,composed:!0}));else{let t=this.#c.length>0?"Passwords do not match":"Please confirm your password";this.#m(this.#n,this.#t,t),this.dispatchEvent(new CustomEvent("secure-password-mismatch",{detail:{name:this.getAttribute("name")??"",matched:!1},bubbles:!0,composed:!0}))}}#m(e,t,i){e.textContent=i,e.classList.remove("hidden"),t.setAttribute("aria-invalid","true")}#A(e,t){e.classList.add("hidden"),e.textContent="",t.removeAttribute("aria-invalid")}#S(e){this.#r&&(this.#r.className=`match-indicator ${e?"matched":"mismatched"}`,this.#r.textContent=e?"\u2713 Passwords match":"\u2717 Passwords do not match")}#M(){let e=this.getAttribute("name");!e||this.closest("secure-form")||(this.#d=document.createElement("input"),this.#d.type="hidden",this.#d.name=e,this.#d.value="",this.appendChild(this.#d))}#k(e){this.#d&&(this.#d.value=e?this.#o:"")}getPasswordValue(){return!this.#o||!this.#c||this.#o!==this.#c?null:this.#o}get valid(){return!this.#o||!this.#c||this.#o!==this.#c?!1:this.#b(this.#o)===null}get name(){return this.getAttribute("name")??""}disconnectedCallback(){super.disconnectedCallback(),this.#o="",this.#c="",this.#e&&(this.#e.value=""),this.#t&&(this.#t.value=""),this.#d&&(this.#d.value="")}};customElements.define("secure-password-confirm",_);export{j as SecureCard,F as SecureDateTime,H as SecureFileUpload,N as SecureForm,I as SecureInput,_ as SecurePasswordConfirm,D as SecureSelect,R as SecureSubmitButton,$ as SecureTable,P as SecureTelemetryProvider,M as SecureTextarea,u as SecurityTier,y as TIER_CONFIG,B as compareTiers,G as getMoreSecureTier,v as getTierConfig,A as isValidTier};
|
|
67
67
|
/**
|
|
68
68
|
* @fileoverview Secure File Upload Component
|
|
69
69
|
*
|