@formdown/ui
Version:
Pure HTML renderer for Formdown syntax
355 lines (314 loc) • 30.9 kB
JavaScript
(function(d,h){typeof exports=="object"&&typeof module<"u"?h(exports,require("lit"),require("@formdown/core")):typeof define=="function"&&define.amd?define(["exports","lit","@formdown/core"],h):(d=typeof globalThis<"u"?globalThis:d||self,h(d.FormdownUI={},d.Lit,d.FormdownCore))})(this,function(d,h,l){"use strict";/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/const P=n=>(t,e)=>{e!==void 0?e.addInitializer(()=>{customElements.define(n,t)}):customElements.define(n,t)};/**
* @license
* Copyright 2019 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/const w=globalThis,S=w.ShadowRoot&&(w.ShadyCSS===void 0||w.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,$=Symbol(),F=new WeakMap;let R=class{constructor(t,e,r){if(this._$cssResult$=!0,r!==$)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o;const e=this.t;if(S&&t===void 0){const r=e!==void 0&&e.length===1;r&&(t=F.get(e)),t===void 0&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),r&&F.set(e,t))}return t}toString(){return this.cssText}};const O=n=>new R(typeof n=="string"?n:n+"",void 0,$),z=(n,t)=>{if(S)n.adoptedStyleSheets=t.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(const e of t){const r=document.createElement("style"),i=w.litNonce;i!==void 0&&r.setAttribute("nonce",i),r.textContent=e.cssText,n.appendChild(r)}},C=S?n=>n:n=>n instanceof CSSStyleSheet?(t=>{let e="";for(const r of t.cssRules)e+=r.cssText;return O(e)})(n):n;/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/const{is:q,defineProperty:D,getOwnPropertyDescriptor:L,getOwnPropertyNames:j,getOwnPropertySymbols:H,getPrototypeOf:V}=Object,u=globalThis,I=u.trustedTypes,B=I?I.emptyScript:"",_=u.reactiveElementPolyfillSupport,g=(n,t)=>n,v={toAttribute(n,t){switch(t){case Boolean:n=n?B:null;break;case Object:case Array:n=n==null?n:JSON.stringify(n)}return n},fromAttribute(n,t){let e=n;switch(t){case Boolean:e=n!==null;break;case Number:e=n===null?null:Number(n);break;case Object:case Array:try{e=JSON.parse(n)}catch{e=null}}return e}},U=(n,t)=>!q(n,t),k={attribute:!0,type:String,converter:v,reflect:!1,useDefault:!1,hasChanged:U};Symbol.metadata??(Symbol.metadata=Symbol("metadata")),u.litPropertyMetadata??(u.litPropertyMetadata=new WeakMap);class y extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??(this.l=[])).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,e=k){if(e.state&&(e.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((e=Object.create(e)).wrapped=!0),this.elementProperties.set(t,e),!e.noAccessor){const r=Symbol(),i=this.getPropertyDescriptor(t,r,e);i!==void 0&&D(this.prototype,t,i)}}static getPropertyDescriptor(t,e,r){const{get:i,set:o}=L(this.prototype,t)??{get(){return this[e]},set(s){this[e]=s}};return{get:i,set(s){const a=i==null?void 0:i.call(this);o==null||o.call(this,s),this.requestUpdate(t,a,r)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??k}static _$Ei(){if(this.hasOwnProperty(g("elementProperties")))return;const t=V(this);t.finalize(),t.l!==void 0&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(g("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(g("properties"))){const e=this.properties,r=[...j(e),...H(e)];for(const i of r)this.createProperty(i,e[i])}const t=this[Symbol.metadata];if(t!==null){const e=litPropertyMetadata.get(t);if(e!==void 0)for(const[r,i]of e)this.elementProperties.set(r,i)}this._$Eh=new Map;for(const[e,r]of this.elementProperties){const i=this._$Eu(e,r);i!==void 0&&this._$Eh.set(i,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){const e=[];if(Array.isArray(t)){const r=new Set(t.flat(1/0).reverse());for(const i of r)e.unshift(C(i))}else t!==void 0&&e.push(C(t));return e}static _$Eu(t,e){const r=e.attribute;return r===!1?void 0:typeof r=="string"?r:typeof t=="string"?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){var t;this._$ES=new Promise(e=>this.enableUpdating=e),this._$AL=new Map,this._$E_(),this.requestUpdate(),(t=this.constructor.l)==null||t.forEach(e=>e(this))}addController(t){var e;(this._$EO??(this._$EO=new Set)).add(t),this.renderRoot!==void 0&&this.isConnected&&((e=t.hostConnected)==null||e.call(t))}removeController(t){var e;(e=this._$EO)==null||e.delete(t)}_$E_(){const t=new Map,e=this.constructor.elementProperties;for(const r of e.keys())this.hasOwnProperty(r)&&(t.set(r,this[r]),delete this[r]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return z(t,this.constructor.elementStyles),t}connectedCallback(){var t;this.renderRoot??(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),(t=this._$EO)==null||t.forEach(e=>{var r;return(r=e.hostConnected)==null?void 0:r.call(e)})}enableUpdating(t){}disconnectedCallback(){var t;(t=this._$EO)==null||t.forEach(e=>{var r;return(r=e.hostDisconnected)==null?void 0:r.call(e)})}attributeChangedCallback(t,e,r){this._$AK(t,r)}_$ET(t,e){var o;const r=this.constructor.elementProperties.get(t),i=this.constructor._$Eu(t,r);if(i!==void 0&&r.reflect===!0){const s=(((o=r.converter)==null?void 0:o.toAttribute)!==void 0?r.converter:v).toAttribute(e,r.type);this._$Em=t,s==null?this.removeAttribute(i):this.setAttribute(i,s),this._$Em=null}}_$AK(t,e){var o,s;const r=this.constructor,i=r._$Eh.get(t);if(i!==void 0&&this._$Em!==i){const a=r.getPropertyOptions(i),c=typeof a.converter=="function"?{fromAttribute:a.converter}:((o=a.converter)==null?void 0:o.fromAttribute)!==void 0?a.converter:v;this._$Em=i;const x=c.fromAttribute(e,a.type);this[i]=x??((s=this._$Ej)==null?void 0:s.get(i))??x,this._$Em=null}}requestUpdate(t,e,r){var i;if(t!==void 0){const o=this.constructor,s=this[t];if(r??(r=o.getPropertyOptions(t)),!((r.hasChanged??U)(s,e)||r.useDefault&&r.reflect&&s===((i=this._$Ej)==null?void 0:i.get(t))&&!this.hasAttribute(o._$Eu(t,r))))return;this.C(t,e,r)}this.isUpdatePending===!1&&(this._$ES=this._$EP())}C(t,e,{useDefault:r,reflect:i,wrapped:o},s){r&&!(this._$Ej??(this._$Ej=new Map)).has(t)&&(this._$Ej.set(t,s??e??this[t]),o!==!0||s!==void 0)||(this._$AL.has(t)||(this.hasUpdated||r||(e=void 0),this._$AL.set(t,e)),i===!0&&this._$Em!==t&&(this._$Eq??(this._$Eq=new Set)).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(e){Promise.reject(e)}const t=this.scheduleUpdate();return t!=null&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var r;if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??(this.renderRoot=this.createRenderRoot()),this._$Ep){for(const[o,s]of this._$Ep)this[o]=s;this._$Ep=void 0}const i=this.constructor.elementProperties;if(i.size>0)for(const[o,s]of i){const{wrapped:a}=s,c=this[o];a!==!0||this._$AL.has(o)||c===void 0||this.C(o,void 0,s,c)}}let t=!1;const e=this._$AL;try{t=this.shouldUpdate(e),t?(this.willUpdate(e),(r=this._$EO)==null||r.forEach(i=>{var o;return(o=i.hostUpdate)==null?void 0:o.call(i)}),this.update(e)):this._$EM()}catch(i){throw t=!1,this._$EM(),i}t&&this._$AE(e)}willUpdate(t){}_$AE(t){var e;(e=this._$EO)==null||e.forEach(r=>{var i;return(i=r.hostUpdated)==null?void 0:i.call(r)}),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Eq&&(this._$Eq=this._$Eq.forEach(e=>this._$ET(e,this[e]))),this._$EM()}updated(t){}firstUpdated(t){}}y.elementStyles=[],y.shadowRootOptions={mode:"open"},y[g("elementProperties")]=new Map,y[g("finalized")]=new Map,_==null||_({ReactiveElement:y}),(u.reactiveElementVersions??(u.reactiveElementVersions=[])).push("2.1.1");/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/const N={attribute:!0,type:String,converter:v,reflect:!1,hasChanged:U},K=(n=N,t,e)=>{const{kind:r,metadata:i}=e;let o=globalThis.litPropertyMetadata.get(i);if(o===void 0&&globalThis.litPropertyMetadata.set(i,o=new Map),r==="setter"&&((n=Object.create(n)).wrapped=!0),o.set(e.name,n),r==="accessor"){const{name:s}=e;return{set(a){const c=t.get.call(this);t.set.call(this,a),this.requestUpdate(s,c,n)},init(a){return a!==void 0&&this.C(s,void 0,n,a),a}}}if(r==="setter"){const{name:s}=e;return function(a){const c=this[s];t.call(this,a),this.requestUpdate(s,c,n)}}throw Error("Unsupported decorator location: "+r)};function m(n){return(t,e)=>typeof e=="object"?K(n,t,e):((r,i,o)=>{const s=i.hasOwnProperty(o);return i.constructor.createProperty(o,r),s?Object.getOwnPropertyDescriptor(i,o):void 0})(n,t,e)}const p=class p{constructor(){this.initialized=!1}static getInstance(){return p.instance||(p.instance=new p),p.instance}async initialize(){if(!this.initialized)try{await l.extensionManager.initialize(),this.setupUIHooks(),this.initialized=!0}catch(t){console.debug("Extension system already initialized or error:",t)}}setupUIHooks(){l.registerHook({name:"field-render",priority:1,handler:this.handleFieldRender.bind(this)}),l.registerHook({name:"field-validate",priority:1,handler:this.handleFieldValidate.bind(this)})}handleFieldRender(t,e){return e}handleFieldValidate(t,e){return{valid:!0,message:""}}async registerUIPlugin(t){await l.registerPlugin(t)}getExtensionStats(){return l.extensionManager.getStats()}async executeUIHooks(t,e,...r){return l.extensionManager.executeHooks(t,e,...r)}};p.instance=null;let E=p;const A=E.getInstance();var W=Object.defineProperty,J=Object.getOwnPropertyDescriptor,f=(n,t,e,r)=>{for(var i=r>1?void 0:r?J(t,e):t,o=n.length-1,s;o>=0;o--)(s=n[o])&&(i=(r?s(t,e,i):s(i))||i);return r&&i&&W(t,e,i),i};d.FormdownUI=class extends h.LitElement{constructor(){super(),this.content="",this.selectOnFocus=!0,this.formId="",this.showSubmitButton=!0,this.submitText="Submit",this._data={},this.fieldRegistry=new Map,this._isUpdatingUI=!1,this._schema=null,this._uniqueFormId=this.formId||`formdown-${Math.random().toString(36).substring(2,15)}`,this.formManager=new l.FormManager,this.fieldProcessor=this.formManager.createFieldProcessor(),this.domBinder=this.formManager.createDOMBinder(),this.setupCoreUIBridge(),this.setupFormManagerEvents()}getFormId(){return this.formId||this._uniqueFormId}get data(){return this._data}set data(t){if(this._isUpdatingUI)return;const e=this._data;this._data=t!=null&&typeof t=="object"?{...t}:{},this.requestUpdate("data",e),this.formManager&&this._schema&&!this._isUpdatingUI&&this.formManager.updateData(this._data)}updateData(t){this.data=t,this.formManager&&this._schema&&this.formManager.updateData(t)}updateField(t,e){this.data={...this.data,[t]:e},this.formManager&&this._schema&&this.formManager.setFieldValue(t,e)}setupCoreUIBridge(){const t={id:"formdown-ui",type:"ui",emit:(e,r)=>{this.dispatchEvent(new CustomEvent(e,{detail:r,bubbles:!0}))},on:(e,r)=>()=>{}};this.formManager.setupComponentBridge(t)}setupFormManagerEvents(){this.formManager.on("data-change",({formData:t})=>{this._isUpdatingUI||(this._isUpdatingUI=!0,this.data=t,this._isUpdatingUI=!1)}),this.formManager.on("validation-error",({field:t,errors:e})=>{this.dispatchEvent(new CustomEvent("validation-error",{detail:{field:t,errors:e},bubbles:!0}))}),this.formManager.on("form-submit",({formData:t})=>{this.dispatchEvent(new CustomEvent("form-submit",{detail:{formData:t},bubbles:!0}))})}validate(){return!this.formManager||!this._schema?{isValid:!0,errors:[]}:this.formManager.validate()}getSchema(){return this._schema}reset(){this.formManager&&this._schema&&(this.formManager.reset(),this.data=this.formManager.getData())}isDirty(){return!this.formManager||!this._schema?!1:this.formManager.isDirty()}async connectedCallback(){var t;super.connectedCallback();try{await A.initialize()}catch(e){console.debug("Extension system initialization:",e)}!this.content&&((t=this.textContent)!=null&&t.trim())&&(this.content=this.textContent.trim(),this.textContent="")}render(){if(!this.content||!this.content.trim())return h.html`<div class="error">No Formdown content provided</div>`;try{this.formManager.parse(this.content),this._schema=this.formManager.getSchema(),this.data&&Object.keys(this.data).length>0&&this.formManager.updateData(this.data);const t=this.formManager.renderToTemplate({container:this});return!t.html||!t.html.trim()?h.html`<div class="error">Generated HTML is empty</div>`:h.html`<div id="content-container"></div>`}catch(t){const e=t instanceof Error?t.message:String(t);return h.html`<div class="error">Error rendering content: ${e}</div>`}}firstUpdated(){this.updateContent(),setTimeout(()=>{this.syncUIFromData()},0)}updated(t){super.updated(t),t.has("content")&&(this.updateContent(),setTimeout(()=>{this.syncUIFromData()},0)),t.has("data")&&this.syncUIFromData()}updateContent(){var t,e;if(!(!this.content||!this.content.trim()))try{const r=(t=this.shadowRoot)==null?void 0:t.querySelector("#content-container");if(!r)return;this.formManager.parse(this.content),this._schema=this.formManager.getSchema(),this.data&&Object.keys(this.data).length>0&&this.formManager.updateData(this.data);const i=this.formManager.renderToTemplate({container:this});if(!i.html||i.html.trim()===""){r.innerHTML='<div class="error">FormManager returned empty HTML</div>';return}r.innerHTML=i.html,this.injectExtensionAssets(r),this.setupFieldHandlers(r)}catch(r){const i=(e=this.shadowRoot)==null?void 0:e.querySelector("#content-container");if(i){const o=r instanceof Error?r.message:String(r);i.innerHTML=`<div class="error">Error: ${o}</div>`}}}injectExtensionAssets(t){try{const e=this.getUsedFieldTypes(t),r=l.extensionManager.getFieldTypeRegistry().getStylesForTypes(e);r&&this.injectStyles(r);const i=l.extensionManager.getFieldTypeRegistry().getScriptsForTypes(e);i&&this.injectScripts(i)}catch(e){console.debug("Extension asset injection failed:",e)}}getUsedFieldTypes(t){const e=new Set;return t.querySelectorAll("[data-field-type]").forEach(o=>{const s=o.getAttribute("data-field-type");s&&e.add(s)}),t.querySelectorAll('[class*="formdown-"][class*="-field"]').forEach(o=>{const a=o.className.match(/formdown-(\w+)-field/);a&&e.add(a[1])}),Array.from(e)}injectStyles(t){var r,i;if(!t.trim())return;const e=(r=this.shadowRoot)==null?void 0:r.querySelector("#extension-styles");if(e)e.textContent=t;else{const o=document.createElement("style");o.id="extension-styles",o.textContent=t,(i=this.shadowRoot)==null||i.appendChild(o)}}injectScripts(t){if(!t.trim())return;const e="formdown-extension-scripts";if(document.getElementById(e))return;const r=document.createElement("script");r.id=e,r.textContent=t,document.head.appendChild(r)}setupFieldHandlers(t){this.fieldRegistry.clear();const e=t.querySelectorAll('input:not([type="radio"]):not([type="checkbox"]), [contenteditable="true"]');this.setupKeyboardNavigation(e),t.querySelectorAll('input, textarea, select, [contenteditable="true"]').forEach(i=>{const o=i,s=this.getFieldName(o);if(s){this.registerField(s,o);const a=this.data[s];if(a!==void 0)this.setElementValue(o,a);else{const c=this.getSchemaDefaultValue(s);c!==void 0&&this.updateDataReactively(s,c,o)}this.setupFieldEventHandlers(o,s),this.setupFieldSpecificBehaviors(o)}else o.id&&o.id.includes("_other_input")&&this.setupOtherInputHandlers(o)})}setupKeyboardNavigation(t){t.forEach((e,r)=>{e.addEventListener("keydown",i=>{const o=i;if(o.key==="Enter"){if(o.preventDefault(),e.tagName.toLowerCase()==="textarea")return;const s=r+1;s<t.length&&t[s].focus()}})})}setupFieldEventHandlers(t,e){const r=o=>{this.formManager.handleUIEvent(o,this.domBinder)},i={querySelector:o=>{var s;return(s=this.shadowRoot)==null?void 0:s.querySelector(o)},querySelectorAll:o=>{var s;return Array.from(((s=this.shadowRoot)==null?void 0:s.querySelectorAll(o))||[])}};this.domBinder.bindFieldToElement(e,t,i),t.hasAttribute("contenteditable")?t.addEventListener("input",r):(t.addEventListener("input",r),t.addEventListener("change",r))}setupFieldSpecificBehaviors(t){t.hasAttribute("contenteditable")&&this.setupContentEditableBehaviors(t)}setupOtherInputHandlers(t){const e=t.id.replace("_other_input",""),r=()=>{var s,a,c;const i=(s=this.shadowRoot)==null?void 0:s.querySelector(`#${e}_other_radio`),o=(a=this.shadowRoot)==null?void 0:a.querySelector(`#${e}_other_checkbox`);if(i)i.checked=!0,this.updateDataReactively(e,t.value.trim(),t);else if(o){o.checked=!0;const x=(c=this.shadowRoot)==null?void 0:c.querySelectorAll(`input[type="checkbox"][name="${e}"]`),M=[];x.forEach(b=>{if(b.checked)if(b.value===""&&b.id.includes("_other_checkbox")){const T=t.value.trim();T&&M.push(T)}else b.value!==""&&M.push(b.value)}),this.updateDataReactively(e,M,t)}};t.addEventListener("input",r),t.addEventListener("change",r)}setupContentEditableBehaviors(t){var i;const e=t.dataset.placeholder;((i=t.textContent)==null?void 0:i.trim())===e&&(t.textContent=""),t.addEventListener("focus",()=>{var o;if(((o=t.textContent)==null?void 0:o.trim())===e&&(t.textContent=""),this.selectOnFocus){const s=window.getSelection(),a=document.createRange();a.selectNodeContents(t),s==null||s.removeAllRanges(),s==null||s.addRange(a)}}),t.addEventListener("blur",()=>{var o;(o=t.textContent)!=null&&o.trim()||(t.textContent=e||"")}),t.dataset.fieldType==="email"&&t.addEventListener("input",()=>{var s;const o=((s=t.textContent)==null?void 0:s.trim())||"";o&&!o.includes("@")?t.style.color="#dc2626":t.style.color="#1e40af"})}updateDataReactively(t,e,r){this._isUpdatingUI||(this.formManager.setFieldValue(t,e),this.data={...this.data,[t]:e},this.syncUIFromData(t,r),this.emitFieldEvents(t,e))}syncUIFromData(t,e){if(!this._isUpdatingUI){this._isUpdatingUI=!0;try{const r={querySelector:i=>{var o;return(o=this.shadowRoot)==null?void 0:o.querySelector(i)},querySelectorAll:i=>{var o;return Array.from(((o=this.shadowRoot)==null?void 0:o.querySelectorAll(i))||[])}};if(this.domBinder.syncFormData(this.data,r),t){const i=this.data[t]??"",o=this.fieldRegistry.get(t);o==null||o.forEach(s=>{s!==e&&this.setElementValue(s,i)})}}finally{this._isUpdatingUI=!1}}}setElementValue(t,e){const r={querySelector:s=>{var a;return(a=this.shadowRoot)==null?void 0:a.querySelector(s)},querySelectorAll:s=>{var a;return Array.from(((a=this.shadowRoot)==null?void 0:a.querySelectorAll(s))||[])}},i=this.fieldProcessor.getFieldType(t);if(!this.fieldProcessor.setFieldValue(t,e,i,r)&&t instanceof HTMLElement){if(t.hasAttribute("contenteditable")){const s=Array.isArray(e)?e.join(", "):String(e);t.textContent!==s&&(t.textContent=s)}else if(t instanceof HTMLInputElement){if(t.type==="checkbox"&&typeof e=="boolean")t.checked=e;else if(t.type!=="checkbox"&&t.type!=="radio"){const s=Array.isArray(e)?e.join(", "):String(e);t.value!==s&&(t.value=s)}}else if(t instanceof HTMLTextAreaElement||t instanceof HTMLSelectElement){const s=Array.isArray(e)?e.join(", "):String(e);t.value!==s&&(t.value=s)}}}getFieldName(t){return t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement||t instanceof HTMLSelectElement?t.name||t.id||null:t.dataset.fieldName||t.id||null}getElementInitialValue(t){var e,r;if(t instanceof HTMLInputElement)return t.type==="checkbox"?t.hasAttribute("checked")?t.value==="true"?!0:t.value:null:t.type==="radio"?t.hasAttribute("checked")?t.value:null:t.hasAttribute("value")&&t.getAttribute("value")?t.getAttribute("value")||"":null;if(t instanceof HTMLTextAreaElement){const i=(e=t.textContent)==null?void 0:e.trim();return i||null}else if(t instanceof HTMLSelectElement){const i=t.querySelector("option[selected]");return i?i.value:null}else if(t.hasAttribute("contenteditable")){const i=t.getAttribute("data-value");if(i)return i;const o=(r=t.textContent)==null?void 0:r.trim();return o&&o!==t.dataset.placeholder?o:null}return null}registerField(t,e){this.fieldRegistry.has(t)||this.fieldRegistry.set(t,new Set),this.fieldRegistry.get(t).add(e)}emitFieldEvents(t,e){const r=this.getFormData();this.dispatchEvent(new CustomEvent("formdown-change",{detail:{fieldName:t,value:e,formData:r},bubbles:!0})),this.dispatchEvent(new CustomEvent("formdown-data-update",{detail:{formData:r},bubbles:!0}))}syncFieldValue(t,e){this.data={...this.data,[t]:e},this.emitFieldEvents(t,e)}updateFormData(t,e){this.data={...this.data,[t]:e},this.emitFieldEvents(t,e)}getFormData(){return{...this.data}}getDefaultValues(){if(!this._schema)return{};const t={};return Object.entries(this._schema).forEach(([e,r])=>{r.value!==void 0&&(t[e]=r.value)}),t}getSchemaDefaultValue(t){if(!(!this._schema||!this._schema[t]))return this._schema[t].value}clearValidationStates(){var e;const t=(e=this.shadowRoot)==null?void 0:e.querySelector("#content-container");t&&(t.querySelectorAll(".field-error, .field-valid").forEach(r=>{r.classList.remove("field-error","field-valid")}),t.querySelectorAll(".validation-error-message").forEach(r=>{r.remove()}))}resetForm(){var r;const t=this.getFormId(),e=(r=this.shadowRoot)==null?void 0:r.querySelector(`#${t}`);e&&e.reset(),this.data={},this.clearValidationStates()}},d.FormdownUI.styles=h.css`
:host {
display: block;
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
line-height: 1.5;
color: var(--theme-text-primary, #1f2937);
background: var(--theme-bg-primary, #ffffff);
max-width: 100%;
box-sizing: border-box;
overflow-y: auto;
}
* {
box-sizing: border-box;
}
.formdown-form {
max-width: 100%;
width: 100%;
margin: 0;
padding: 0;
display: none; /* Hidden form for form attribute reference */
}
.formdown-field {
margin-bottom: 1.5rem;
max-width: 100%;
}
/* Add spacing between consecutive field containers */
.formdown-field-container {
margin-bottom: 0.75rem;
}
.formdown-field-container:last-child {
margin-bottom: 0;
}
label {
display: block;
margin-bottom: 0.5rem;
font-weight: 500;
color: var(--theme-text-primary, #374151);
font-size: 0.875rem;
line-height: 1.25;
}
input, textarea, select {
width: 100%;
max-width: 100%;
padding: 0.75rem;
border: 1px solid var(--theme-border, #d1d5db);
border-radius: 0.5rem;
font-size: 1rem;
font-family: inherit;
line-height: 1.5;
transition: all 0.15s ease-in-out;
background-color: var(--theme-bg-primary, #ffffff);
color: var(--theme-text-primary, #1f2937);
}
input:focus, textarea:focus, select:focus {
outline: none;
border-color: var(--theme-accent, #3b82f6);
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
background-color: var(--theme-bg-primary, #ffffff);
}
input:hover, textarea:hover, select:hover {
border-color: var(--theme-text-secondary, #9ca3af);
}
input[type="radio"], input[type="checkbox"] {
width: auto;
max-width: none;
margin-right: 0.5rem;
margin-bottom: 0;
}
textarea {
min-height: 6rem;
resize: vertical;
}
select {
cursor: pointer;
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e");
background-position: right 0.5rem center;
background-repeat: no-repeat;
background-size: 1.5em 1.5em;
padding-right: 2.5rem;
}
fieldset {
border: 1px solid var(--theme-border, #d1d5db);
border-radius: 0.5rem;
padding: 1.25rem;
margin: 0 0 1.5rem 0;
max-width: 100%;
background-color: var(--theme-bg-primary, #ffffff);
}
legend {
font-weight: 600;
color: var(--theme-text-primary, #374151);
padding: 0 0.75rem;
font-size: 0.875rem;
}
fieldset label {
display: flex;
align-items: center;
margin-bottom: 0.75rem;
font-weight: normal;
font-size: 0.875rem;
} /* Enhanced inline formdown-field elements with contentEditable */
formdown-field,
[contenteditable="true"]:not(textarea) {
display: inline;
min-width: 60px;
max-width: 200px;
padding: 0.125rem 0.25rem;
border: 1px solid transparent;
background-color: var(--theme-bg-secondary, rgba(239, 246, 255, 0.6));
border-radius: 0.125rem;
font-style: normal;
color: inherit;
font-size: inherit;
line-height: inherit;
font-family: inherit;
font-weight: inherit;
cursor: text;
outline: none;
transition: all 0.15s ease-in-out;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
vertical-align: baseline;
box-decoration-break: clone;
}
[contenteditable="true"]:not(textarea):hover {
background-color: var(--theme-bg-secondary, rgba(219, 234, 254, 0.8));
border-color: var(--theme-border, rgba(147, 197, 253, 0.5));
}
[contenteditable="true"]:not(textarea):focus {
background-color: var(--theme-bg-primary, rgba(255, 255, 255, 0.9));
border-color: var(--theme-accent, #3b82f6);
box-shadow: 0 0 0 1px rgba(59, 130, 246, 0.2);
color: var(--theme-accent, #1e40af);
}
[contenteditable="true"]:not(textarea):empty::before {
content: attr(data-placeholder);
color: var(--theme-text-secondary, #94a3b8);
font-style: italic;
opacity: 0.7;
}
/* Enhanced typography for markdown content */
h1, h2, h3, h4, h5, h6 {
margin-top: 0;
margin-bottom: 1rem;
color: var(--theme-text-primary, #1f2937);
font-weight: 600;
line-height: 1.25;
}
h1 {
font-size: 2.25rem;
font-weight: 700;
}
h2 {
font-size: 1.875rem;
font-weight: 600;
}
h3 {
font-size: 1.5rem;
font-weight: 600;
}
h4 {
font-size: 1.25rem;
font-weight: 600;
}
h5 {
font-size: 1.125rem;
font-weight: 600;
}
h6 {
font-size: 1rem;
font-weight: 600;
}
p {
margin-bottom: 1rem;
line-height: 1.7;
color: var(--theme-text-secondary, #4b5563);
}
/* Responsive design */
@media (max-width: 768px) {
:host {
font-size: 0.875rem;
}
input, textarea, select {
padding: 0.625rem;
font-size: 0.875rem;
}
h1 { font-size: 1.875rem; }
h2 { font-size: 1.5rem; }
h3 { font-size: 1.25rem; }
}
.error {
color: var(--theme-error, #dc2626);
font-size: 0.875rem;
margin-top: 0.5rem;
display: block;
}
/* Field validation styles */
.field-error {
border-color: var(--theme-error, #dc2626) ;
box-shadow: 0 0 0 1px rgba(220, 38, 38, 0.1) ;
}
.field-error:focus {
border-color: var(--theme-error, #dc2626) ;
box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.1) ;
}
.validation-error-message {
color: var(--theme-error, #dc2626);
font-size: 0.75rem;
margin-top: 0.25rem;
display: block;
font-weight: 500;
}
/* Success state */
.field-valid {
border-color: #10b981 ;
box-shadow: 0 0 0 1px rgba(16, 185, 129, 0.1) ;
}
.submit-button {
background-color: #3b82f6;
color: white;
padding: 0.75rem 1.5rem;
border: none;
border-radius: 0.5rem;
font-size: 1rem;
font-weight: 500;
cursor: pointer;
transition: all 0.15s ease-in-out;
margin-top: 1.5rem;
width: auto;
max-width: 100%;
}
.submit-button:hover {
background-color: #2563eb;
transform: translateY(-1px);
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
.submit-button:disabled {
background-color: #9ca3af;
cursor: not-allowed;
transform: none;
box-shadow: none;
}
.submit-button:active {
transform: translateY(0);
}
/* Ensure content doesn't overflow */
#content-container {
max-width: 100%;
overflow-wrap: break-word;
word-wrap: break-word;
} /* Radio and checkbox groups */
.radio-group, .checkbox-group {
display: flex;
gap: 0.75rem;
flex-wrap: wrap;
}
/* Inline layout (default) */
.radio-group.inline, .checkbox-group.inline {
flex-direction: row;
align-items: center;
}
/* Vertical layout */
.radio-group.vertical, .checkbox-group.vertical {
flex-direction: column;
align-items: flex-start;
}
.formdown-option-label {
display: flex;
align-items: center;
margin-bottom: 0;
font-weight: normal;
cursor: pointer;
font-size: 0.875rem;
white-space: nowrap;
}
.formdown-option-label input {
margin-right: 0.5rem;
margin-bottom: 0;
}
.formdown-option-label span {
user-select: none;
}
/* Legacy support for old structure */
.radio-group label, .checkbox-group label {
display: flex;
align-items: center;
margin-bottom: 0;
font-weight: normal;
cursor: pointer;
}/* Better spacing for form elements */
.formdown-form > * + * {
margin-top: 1rem;
}
`,f([m()],d.FormdownUI.prototype,"content",2),f([m({type:Boolean,attribute:"select-on-focus"})],d.FormdownUI.prototype,"selectOnFocus",2),f([m({attribute:"form-id"})],d.FormdownUI.prototype,"formId",2),f([m({type:Boolean,attribute:"show-submit-button"})],d.FormdownUI.prototype,"showSubmitButton",2),f([m({attribute:"submit-text"})],d.FormdownUI.prototype,"submitText",2),f([m({type:Object})],d.FormdownUI.prototype,"data",1),d.FormdownUI=f([P("formdown-ui")],d.FormdownUI);const Y=Object.freeze(Object.defineProperty({__proto__:null,get FormdownUI(){return d.FormdownUI}},Symbol.toStringTag,{value:"Module"})),G=(n,t={})=>{const e=document.createElement("formdown-ui");return t.content&&(e.content=t.content),t.formId&&(e.formId=t.formId),t.showSubmitButton!==void 0&&(e.showSubmitButton=t.showSubmitButton),t.submitText&&(e.submitText=t.submitText),n.appendChild(e),e},Q=()=>{customElements.get("formdown-ui")||Promise.resolve().then(()=>Y)};d.UIExtensionSupport=E,d.createFormdownUI=G,d.registerFormdownUI=Q,d.uiExtensionSupport=A,Object.defineProperty(d,Symbol.toStringTag,{value:"Module"})});