@nuralyui/form 0.1.3 → 0.1.4
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/bundle.js +78 -6
- package/package.json +1 -1
package/bundle.js
CHANGED
|
@@ -1,26 +1,98 @@
|
|
|
1
|
-
import{css as t,LitElement as i,html as
|
|
1
|
+
import{css as t,LitElement as i,html as s}from"lit";import{property as e,state as n,customElement as r}from"lit/decorators.js";import{NuralyUIBaseMixin as o}from"@nuralyui/common/mixins";
|
|
2
2
|
/**
|
|
3
3
|
* @license
|
|
4
4
|
* Copyright 2023 Nuraly, Laabidi Aymen
|
|
5
5
|
* SPDX-License-Identifier: MIT
|
|
6
|
-
*/const a=t
|
|
6
|
+
*/const a=t`
|
|
7
|
+
:host {
|
|
8
|
+
display: block;
|
|
9
|
+
width: 100%;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
:host([disabled]) {
|
|
13
|
+
opacity: 0.6;
|
|
14
|
+
pointer-events: none;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.form-wrapper {
|
|
18
|
+
width: 100%;
|
|
19
|
+
display: flex;
|
|
20
|
+
flex-direction: column;
|
|
21
|
+
gap: var(--nuraly-form-gap, 16px);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.form-wrapper[disabled] {
|
|
25
|
+
opacity: 0.6;
|
|
26
|
+
pointer-events: none;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* Form validation states */
|
|
30
|
+
:host([data-validation-state="pristine"]) {
|
|
31
|
+
border-left: 3px solid transparent;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
:host([data-validation-state="valid"]) {
|
|
35
|
+
border-left: 3px solid #52c41a;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
:host([data-validation-state="invalid"]) {
|
|
39
|
+
border-left: 3px solid #ff4d4f;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
:host([data-validation-state="pending"]) {
|
|
43
|
+
border-left: 3px solid #1890ff;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* Form submission states */
|
|
47
|
+
:host([data-submission-state="submitting"]) {
|
|
48
|
+
opacity: 0.8;
|
|
49
|
+
pointer-events: none;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
:host([data-submission-state="success"]) {
|
|
53
|
+
border-left: 3px solid #52c41a;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
:host([data-submission-state="error"]) {
|
|
57
|
+
border-left: 3px solid #ff4d4f;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* Responsive design */
|
|
61
|
+
@media (max-width: 768px) {
|
|
62
|
+
.form-wrapper {
|
|
63
|
+
gap: var(--nuraly-form-gap-mobile, 12px);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
`
|
|
7
67
|
/**
|
|
8
68
|
* @license
|
|
9
69
|
* Copyright 2023 Nuraly, Laabidi Aymen
|
|
10
70
|
* SPDX-License-Identifier: MIT
|
|
11
|
-
*/;var d,
|
|
71
|
+
*/;var d,l;!function(t){t.Pristine="pristine",t.Pending="pending",t.Valid="valid",t.Invalid="invalid",t.Submitted="submitted"}(d||(d={})),function(t){t.Idle="idle",t.Submitting="submitting",t.Success="success",t.Error="error"}(l||(l={}));const h={VALIDATION_CHANGED:"nr-form-validation-changed",FIELD_CHANGED:"nr-form-field-changed",SUBMIT_ATTEMPT:"nr-form-submit-attempt",SUBMIT_SUCCESS:"nr-form-submit-success",SUBMIT_ERROR:"nr-form-submit-error",RESET:"nr-form-reset"};
|
|
12
72
|
/**
|
|
13
73
|
* @license
|
|
14
74
|
* Copyright 2023 Nuraly, Laabidi Aymen
|
|
15
75
|
* SPDX-License-Identifier: MIT
|
|
16
|
-
*/var u=function(t,i,e
|
|
76
|
+
*/var u=function(t,i,s,e){return new(s||(s=Promise))((function(n,r){function o(t){try{d(e.next(t))}catch(t){r(t)}}function a(t){try{d(e.throw(t))}catch(t){r(t)}}function d(t){var i;t.done?n(t.value):(i=t.value,i instanceof s?i:new s((function(t){t(i)}))).then(o,a)}d((e=e.apply(t,i||[])).next())}))};class c{constructor(t){this.host=t,this.fields=new Map,this.validationState=d.Pristine,this.validationPromise=null}registerField(t){var i;const s=t.name||t.getAttribute("name")||`field-${Date.now()}`,e={element:t,name:s,value:t.value,isValid:t.getValidationStatus().isValid,validationMessage:t.validationMessage||"",required:null!==(i=t.required)&&void 0!==i&&i,touched:!1,dirty:!1};this.fields.set(s,e),this.addFieldListeners(t,s)}unregisterField(t){const i=this.fields.get(t);i&&(this.removeFieldListeners(i.element),this.fields.delete(t))}addFieldListeners(t,i){t.addEventListener("nr-validation",(t=>this.handleFieldValidation(i,t)))}removeFieldListeners(t){}handleFieldValidation(t,i){const s=this.fields.get(t);if(s){if(i&&i.detail)s.isValid=i.detail.isValid||!1,s.validationMessage=i.detail.validationMessage||"";else{const t=s.element.getValidationStatus();s.isValid=t.isValid,s.validationMessage=s.element.validationMessage||""}this.updateFormValidationState()}}updateFormValidationState(){const t=this.getInvalidFields(),i=0===t.length;this.validationState=i?d.Valid:d.Invalid;const s={isValid:i,invalidFields:t,validationErrors:this.buildValidationErrors(),summary:i?"Form is valid":`${t.length} field(s) have errors`};this.dispatchValidationEvent(s)}buildValidationErrors(){const t={};for(const[i,s]of this.fields)!s.isValid&&s.validationMessage&&(t[i]=s.validationMessage);return t}validateForm(){return this.validationPromise||(this.validationState=d.Pending,this.validationPromise=this.performValidation()),this.validationPromise}performValidation(){return u(this,void 0,void 0,(function*(){const t=[],i={};for(const[s,e]of this.fields){const n=e.element.getValidationStatus().isValid;e.isValid=n,e.validationMessage=e.element.validationMessage||"",n||(t.push(e),i[s]=e.validationMessage)}const s=0===t.length;this.validationState=s?d.Valid:d.Invalid;const e={isValid:s,invalidFields:t,validationErrors:i,summary:s?"Form is valid":`${t.length} field(s) have errors`};return this.dispatchValidationEvent(e),this.validationPromise=null,e}))}getValidationState(){return this.validationState}getFields(){return Array.from(this.fields.values())}getInvalidFields(){return Array.from(this.fields.values()).filter((t=>!t.isValid))}isValid(){return this.validationState===d.Valid&&Array.from(this.fields.values()).every((t=>t.isValid))}focusFirstInvalidField(){const t=Array.from(this.fields.values()).find((t=>!t.isValid));return!(!t||"function"!=typeof t.element.focus)&&(t.element.focus(),!0)}reset(){for(const t of this.fields.values())"clearValidation"in t.element&&"function"==typeof t.element.clearValidation&&t.element.clearValidation(),"value"in t.element&&(t.element.value=""),t.touched=!1,t.dirty=!1,t.isValid=!0,t.validationMessage="";this.validationState=d.Pristine,this.dispatchResetEvent()}dispatchValidationEvent(t){var i,s;null===(s=(i=this.host).dispatchCustomEvent)||void 0===s||s.call(i,h.VALIDATION_CHANGED,{validationResult:t})}dispatchResetEvent(){var t,i;null===(i=(t=this.host).dispatchCustomEvent)||void 0===i||i.call(t,h.RESET,{})}}
|
|
17
77
|
/**
|
|
18
78
|
* @license
|
|
19
79
|
* Copyright 2023 Nuraly, Laabidi Aymen
|
|
20
80
|
* SPDX-License-Identifier: MIT
|
|
21
|
-
*/var v=function(t,i,e
|
|
81
|
+
*/var v=function(t,i,s,e){return new(s||(s=Promise))((function(n,r){function o(t){try{d(e.next(t))}catch(t){r(t)}}function a(t){try{d(e.throw(t))}catch(t){r(t)}}function d(t){var i;t.done?n(t.value):(i=t.value,i instanceof s?i:new s((function(t){t(i)}))).then(o,a)}d((e=e.apply(t,i||[])).next())}))};class m{constructor(t){this.host=t,this.submissionState=l.Idle,this.lastSubmissionData=null}getSubmissionState(){return this.submissionState}isSubmitting(){return this.submissionState===l.Submitting}collectFormData(){const t=new FormData,i={},s={};return this.getFormFields().forEach((e=>{const n=e.name||e.getAttribute("name");if(!n)return;const r=e.value;null!=r&&t.append(n,String(r)),i[n]=r,s[n]={element:e,value:r,name:n,type:e.tagName.toLowerCase(),required:e.required||!1,disabled:e.disabled||!1}})),{formData:t,jsonData:i,fields:s}}submitForm(t){return v(this,void 0,void 0,(function*(){if(this.isSubmitting())throw new Error("Form is already submitting");try{this.setSubmissionState(l.Submitting);const i=this.host.validationController;if(i){const t=yield i.validateForm();if(!t.isValid)throw i.focusFirstInvalidField(),this.dispatchSubmitAttemptEvent(t),new Error(`Form validation failed: ${t.summary}`)}const s=this.collectFormData();return t&&(Object.assign(s.jsonData,t),Object.entries(t).forEach((([t,i])=>{s.formData.append(t,String(i))}))),this.lastSubmissionData=s,this.dispatchSubmitSuccessEvent(s),this.setSubmissionState(l.Success),s}catch(t){throw this.setSubmissionState(l.Error),this.dispatchSubmitErrorEvent(t),t}}))}resetSubmission(){this.submissionState=l.Idle,this.lastSubmissionData=null}getLastSubmissionData(){return this.lastSubmissionData}getFormFields(){var t;const i=this.host,s=[],e=["nr-input","nr-select","nr-radio","nr-checkbox","nr-textarea","nr-timepicker","nr-datepicker","input","select","textarea"];e.forEach((t=>{i.querySelectorAll(t).forEach((t=>{(t.name||t.getAttribute("name"))&&s.push(t)}))}));return((null===(t=i.shadowRoot)||void 0===t?void 0:t.querySelectorAll("slot"))||[]).forEach((t=>{t.assignedElements({flatten:!0}).forEach((t=>{e.forEach((i=>{if(t.matches&&t.matches(i)){const i=t;(i.name||i.getAttribute("name"))&&s.push(i)}t.querySelectorAll(i).forEach((t=>{const i=t;(i.name||i.getAttribute("name"))&&s.push(i)}))}))}))})),s}setSubmissionState(t){var i,s;this.submissionState=t,null===(s=(i=this.host).requestUpdate)||void 0===s||s.call(i)}dispatchSubmitAttemptEvent(t){var i,s;null===(s=(i=this.host).dispatchCustomEvent)||void 0===s||s.call(i,h.SUBMIT_ATTEMPT,{validationResult:t})}dispatchSubmitSuccessEvent(t){var i,s;null===(s=(i=this.host).dispatchCustomEvent)||void 0===s||s.call(i,h.SUBMIT_SUCCESS,{formData:t})}dispatchSubmitErrorEvent(t){var i,s;null===(s=(i=this.host).dispatchCustomEvent)||void 0===s||s.call(i,h.SUBMIT_ERROR,{error:t})}}
|
|
22
82
|
/**
|
|
23
83
|
* @license
|
|
24
84
|
* Copyright 2023 Nuraly, Laabidi Aymen
|
|
25
85
|
* SPDX-License-Identifier: MIT
|
|
26
|
-
*/var f=function(t,i,e
|
|
86
|
+
*/var f=function(t,i,s,e){for(var n,r=arguments.length,o=r<3?i:null===e?e=Object.getOwnPropertyDescriptor(i,s):e,a=t.length-1;a>=0;a--)(n=t[a])&&(o=(r<3?n(o):r>3?n(i,s,o):n(i,s))||o);return r>3&&o&&Object.defineProperty(i,s,o),o},p=function(t,i,s,e){return new(s||(s=Promise))((function(n,r){function o(t){try{d(e.next(t))}catch(t){r(t)}}function a(t){try{d(e.throw(t))}catch(t){r(t)}}function d(t){var i;t.done?n(t.value):(i=t.value,i instanceof s?i:new s((function(t){t(i)}))).then(o,a)}d((e=e.apply(t,i||[])).next())}))};let b=class extends(o(i)){constructor(){super(...arguments),this.config={validateOnChange:!1,validateOnBlur:!0,showErrorsImmediately:!1,preventInvalidSubmission:!0,resetOnSuccess:!1,validationDelay:300},this.validateOnChange=!1,this.validateOnBlur=!0,this.preventInvalidSubmission=!0,this.resetOnSuccess=!1,this.method="POST",this.enctype="multipart/form-data",this.disabled=!1,this._validationState=d.Pristine,this._submissionState=l.Idle,this.validationController=new c(this),this.submissionController=new m(this),this.handleValidationChanged=t=>{const i=t.detail.validationResult;i&&(this._validationState=i.isValid?d.Valid:d.Invalid)}}get validationState(){return this._validationState}get submissionState(){return this._submissionState}connectedCallback(){super.connectedCallback(),this.setupFormObserver()}disconnectedCallback(){super.disconnectedCallback(),this.cleanupFormObserver()}willUpdate(t){super.willUpdate(t),(t.has("validateOnChange")||t.has("validateOnBlur")||t.has("preventInvalidSubmission")||t.has("resetOnSuccess"))&&(this.config=Object.assign(Object.assign({},this.config),{validateOnChange:this.validateOnChange,validateOnBlur:this.validateOnBlur,preventInvalidSubmission:this.preventInvalidSubmission,resetOnSuccess:this.resetOnSuccess}))}firstUpdated(){this.registerExistingFields(),this.setupFormEvents()}setupFormObserver(){const t=new MutationObserver((t=>{t.forEach((t=>{t.addedNodes.forEach((t=>{t.nodeType===Node.ELEMENT_NODE&&this.registerFieldsInElement(t)}))}))}));t.observe(this,{childList:!0,subtree:!0}),this._formObserver=t}cleanupFormObserver(){const t=this._formObserver;t&&t.disconnect()}registerExistingFields(){this.registerFieldsInElement(this)}registerFieldsInElement(t){["nr-input","nr-select","nr-radio","nr-checkbox","nr-textarea","nr-timepicker","nr-datepicker"].forEach((i=>{t.querySelectorAll(i).forEach((t=>{t.getAttribute("name")&&this.validationController.registerField(t)}))}))}setupFormEvents(){this.addEventListener("submit",this.handleFormSubmit),this.addEventListener("reset",this.handleFormReset),this.addEventListener(h.VALIDATION_CHANGED,this.handleValidationChanged)}handleFormSubmit(t){return p(this,void 0,void 0,(function*(){if(t.preventDefault(),!this.disabled)try{const t=yield this.submissionController.submitForm();this.resetOnSuccess&&this.reset(),this.action&&this.performNativeSubmission(t.formData)}catch(t){console.error("Form submission failed:",t)}}))}handleFormReset(t){t.preventDefault(),this.reset()}performNativeSubmission(t){const i=document.createElement("form");i.action=this.action,i.method=this.method,i.enctype=this.enctype,this.target&&(i.target=this.target);for(const[s,e]of t.entries()){const t=document.createElement("input");t.type="hidden",t.name=s,t.value=e,i.appendChild(t)}document.body.appendChild(i),i.submit(),document.body.removeChild(i)}validate(){return p(this,void 0,void 0,(function*(){return(yield this.validationController.validateForm()).isValid}))}submit(t){return p(this,void 0,void 0,(function*(){yield this.submissionController.submitForm(t)}))}reset(){this.validationController.reset(),this.submissionController.resetSubmission(),this._validationState=d.Pristine,this._submissionState=l.Idle}get isValid(){return this.validationController.isValid()}get isSubmitting(){return this.submissionController.isSubmitting()}getFormData(){return this.submissionController.collectFormData()}getInvalidFields(){return this.validationController.getInvalidFields()}getFieldsValue(t){const i=this.getFormData().jsonData;if(t&&t.length>0){const s={};return t.forEach((t=>{t in i&&(s[t]=i[t])})),s}return i}getFieldValue(t){return this.getFieldsValue()[t]}setFieldsValue(t){Object.entries(t).forEach((([t,i])=>{this.setFieldValue(t,i)}))}setFieldValue(t,i){const s=this.validationController.getFields().find((i=>i.name===t));s&&s.element&&(s.element.value=i,s.value=i,s.element.dispatchEvent(new Event("change",{bubbles:!0})))}validateFields(t){return p(this,void 0,void 0,(function*(){const i=yield this.validationController.validateForm();if(t&&t.length>0){const s={};if(t.forEach((t=>{i.validationErrors[t]&&(s[t]=i.validationErrors[t])})),Object.keys(s).length>0)throw new Error(JSON.stringify(s));return this.getFieldsValue(t)}if(!i.isValid)throw new Error(JSON.stringify(i.validationErrors));return this.getFieldsValue()}))}resetFields(t){if(!t||0===t.length)return void this.reset();const i=this.validationController.getFields();t.forEach((t=>{const s=i.find((i=>i.name===t));s&&s.element&&(s.element.value="",s.value="",s.touched=!1,s.dirty=!1,s.isValid=!0,s.validationMessage="",s.element.dispatchEvent(new Event("change",{bubbles:!0})))}))}getFieldError(t){const i=this.validationController.getFields().find((i=>i.name===t));return i&&!i.isValid?i.validationMessage:null}getFieldsError(t){const i=this.validationController.getFields(),s={};return(t?i.filter((i=>t.includes(i.name))):i).forEach((t=>{s[t.name]=t.isValid?null:t.validationMessage})),s}isFieldTouched(t){const i=this.validationController.getFields().find((i=>i.name===t));return!!i&&i.touched}isFieldsTouched(t){const i=this.validationController.getFields();return(t?i.filter((i=>t.includes(i.name))):i).some((t=>t.touched))}isFieldDirty(t){const i=this.validationController.getFields().find((i=>i.name===t));return!!i&&i.dirty}isFieldsDirty(t){const i=this.validationController.getFields();return(t?i.filter((i=>t.includes(i.name))):i).some((t=>t.dirty))}getFieldInstance(t){const i=this.validationController.getFields().find((i=>i.name===t));return i?i.element:null}scrollToField(t){if(t){const i=this.getFieldInstance(t);return!!i&&(i.scrollIntoView({behavior:"smooth",block:"center"}),"function"==typeof i.focus&&i.focus(),!0)}return this.validationController.focusFirstInvalidField()}finish(){return p(this,void 0,void 0,(function*(){try{const t=yield this.validateFields();return yield this.submit(),t}catch(t){throw this.scrollToField(),t}}))}getFieldsWithErrors(){return this.validationController.getFields().filter((t=>!t.isValid)).map((t=>t.name))}hasErrors(){return this.getFieldsWithErrors().length>0}getFormState(){const t=this.validationController.getFields();return{isValid:this.isValid,isSubmitting:this.isSubmitting,hasErrors:this.hasErrors(),errorCount:this.getFieldsWithErrors().length,fieldCount:t.length,touchedFields:t.filter((t=>t.touched)).map((t=>t.name)),dirtyFields:t.filter((t=>t.dirty)).map((t=>t.name)),invalidFields:this.getFieldsWithErrors()}}setLoading(t){this.disabled=t,this.requestUpdate()}render(){return s`
|
|
87
|
+
<form
|
|
88
|
+
action="${this.action||""}"
|
|
89
|
+
method="${this.method.toLowerCase()}"
|
|
90
|
+
enctype="${this.enctype}"
|
|
91
|
+
target="${this.target||""}"
|
|
92
|
+
class="form-wrapper"
|
|
93
|
+
data-disabled="${this.disabled}"
|
|
94
|
+
novalidate
|
|
95
|
+
>
|
|
96
|
+
<slot></slot>
|
|
97
|
+
</form>
|
|
98
|
+
`}};b.styles=a,f([e({type:Object})],b.prototype,"config",void 0),f([e({type:Boolean,attribute:"validate-on-change"})],b.prototype,"validateOnChange",void 0),f([e({type:Boolean,attribute:"validate-on-blur"})],b.prototype,"validateOnBlur",void 0),f([e({type:Boolean,attribute:"prevent-invalid-submission"})],b.prototype,"preventInvalidSubmission",void 0),f([e({type:Boolean,attribute:"reset-on-success"})],b.prototype,"resetOnSuccess",void 0),f([e({type:String})],b.prototype,"action",void 0),f([e({type:String})],b.prototype,"method",void 0),f([e({type:String,attribute:"enctype"})],b.prototype,"enctype",void 0),f([e({type:String})],b.prototype,"target",void 0),f([e({type:Boolean,reflect:!0})],b.prototype,"disabled",void 0),f([n()],b.prototype,"_validationState",void 0),f([n()],b.prototype,"_submissionState",void 0),b=f([r("nr-form")],b);export{h as FORM_EVENTS,m as FormSubmissionController,l as FormSubmissionState,c as FormValidationController,d as FormValidationState,b as NrFormElement};
|
package/package.json
CHANGED