@a.nemreen/dga-dynamic-form 0.1.9 → 0.2.0
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
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Schema-driven dynamic forms for Angular, rendered with [`@a.nemreen/dga-ui`](https://www.npmjs.com/package/@a.nemreen/dga-ui) controls.
|
|
4
4
|
|
|
5
|
-
**Version 0.
|
|
5
|
+
**Version 0.2.0** — wizard card chrome, Back / Save as draft actions, and selectable option cards.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -176,12 +176,14 @@ When both `password` and `confirmPassword` fields exist, `passwordMismatch` vali
|
|
|
176
176
|
| `consentBaseUrl` | `string?` | — | CMS base for `consentServiceName` fields → GET `{base}/consents/{name}`. |
|
|
177
177
|
| `wizard` | `DgaWizardConfig?` | — | Multi-step mode (see below). |
|
|
178
178
|
|
|
179
|
-
`DgaFormLabel` is a map of locale code → string (
|
|
179
|
+
`DgaFormLabel` is a map of locale code → string. `en` and `ar` are required; extra keys match `provideDgaLocales` (e.g. `{ en, ar, ur }`). Resolution: exact locale → `en` → `ar` → first non-empty value.
|
|
180
180
|
|
|
181
181
|
---
|
|
182
182
|
|
|
183
183
|
## Wizard (`config.wizard`)
|
|
184
184
|
|
|
185
|
+
When `enabled`, the form renders DGA chrome: a numbered stepper with a compact radial step counter, the current step in a card (title, description, optional badge), **Back** (outline, start), **Save as draft** (ghost), and **Next** / **Submit** (primary, end). Reloading restores a local draft behind an info banner when `enableLocalStorageSave` is on.
|
|
186
|
+
|
|
185
187
|
| Key | Type | Default | Description |
|
|
186
188
|
|-----|------|---------|-------------|
|
|
187
189
|
| `enabled` | `boolean` | — | Turn on stepper UI. |
|
|
@@ -262,7 +264,9 @@ HTTP adapter maps `Id/Title`, `Code/Name`, and `{UserName,Email,DisplayName}` sh
|
|
|
262
264
|
| `monthPicker` | date | Month-only mode. |
|
|
263
265
|
| `maxChips` | chips | Max chip count validator. |
|
|
264
266
|
| `allowDuplicates` | chips | Allow duplicate chip values. |
|
|
267
|
+
| `countries` | phone | Extra dial codes after KSA (`+966`). `{ code, label?, name?: { en, ar } }`. Duplicate codes are skipped. Saudi mobile rules still apply to `+966`; other codes only require digits. |
|
|
265
268
|
| `alwaysOpen` | select | `openMode="always"` on `dga-select`. |
|
|
269
|
+
| `optionsLayout` | radio, checkbox | `'stack'` (default), `'grid'`, or `'cards'` (selectable DGA option cards). |
|
|
266
270
|
| `consentServiceName` | checkbox | Fetch label from CMS (`consentBaseUrl`). |
|
|
267
271
|
| `excludeFromDraft` / `sensitive` | any | Strip from localStorage drafts. |
|
|
268
272
|
|
|
@@ -306,7 +310,7 @@ Supports `pattern`, `minLength`, `maxLength`, `min`, `max`, `minDate`, `maxDate`
|
|
|
306
310
|
|
|
307
311
|
### Exported utilities
|
|
308
312
|
|
|
309
|
-
`dgaBuildFormGroup`, `dgaIsFieldVisible`, `dgaIsRequiredWhen`, `dgaApplyCrossFieldValidators`, `dgaSaudiMobileValidator`, `dgaPasswordMatchValidator`, `dgaAssertSafeHttpUrl`, `createHttpLookupAdapter`, `createHttpSubmitAdapter`.
|
|
313
|
+
`dgaBuildFormGroup`, `dgaIsFieldVisible`, `dgaIsRequiredWhen`, `dgaApplyCrossFieldValidators`, `dgaSaudiMobileValidator`, `dgaPhoneFieldValidator`, `dgaPasswordMatchValidator`, `dgaAssertSafeHttpUrl`, `createHttpLookupAdapter`, `createHttpSubmitAdapter`.
|
|
310
314
|
|
|
311
315
|
## License
|
|
312
316
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import*as l from"@angular/core";import{InjectionToken as x,inject as c,Injectable as Y,isDevMode as ze,makeEnvironmentProviders as Be,input as u,booleanAttribute as J,signal as m,computed as p,output as g,ChangeDetectionStrategy as V,Component as R,DestroyRef as Q,effect as k,untracked as q}from"@angular/core";import{NgComponentOutlet as X}from"@angular/common";import*as h from"@angular/forms";import{Validators as b,ReactiveFormsModule as O,FormsModule as Z,FormBuilder as _e}from"@angular/forms";import{switchMap as ee,catchError as $e,map as Ue,startWith as Ge}from"rxjs/operators";import{takeUntilDestroyed as T}from"@angular/core/rxjs-interop";import{DgaToastService as je,DgaButton as A,DgaIcon as te,dgaProvideValueAccessor as ae,DgaField as ie,DgaInput as ne,DgaSelect as oe,DgaCheckbox as re,DgaRadio as le,DgaPhoneInput as se,DgaChipInput as de,DgaSwitch as ue,DgaUpload as ce,DgaNumberInput as pe,DgaOtp as fe,DgaStepper as me}from"@a.nemreen/dga-ui";import{of as D,throwError as ge,startWith as Ke,catchError as We}from"rxjs";import{HttpClient as I,HttpHeaders as He}from"@angular/common/http";import{DgaDatePicker as he}from"@a.nemreen/dga-ui/date-picker";const z=new x("DGA_LOOKUP_ADAPTER"),E=new x("DGA_SUBMIT_ADAPTER"),B=new x("DGA_FORM_TOAST_ADAPTER"),_=new x("DGA_CAPTCHA_ADAPTER"),$=new x("DGA_HTTP_SECURITY"),U=new x("DGA_FORM_I18N_ADAPTER"),be=new x("DGA_DYNAMIC_FORM_FIELD_REGISTRY"),ve=[["StartDate","EndDate"],["UseCaseStartDate","UseCaseEndDate"],["startDate","endDate"]];function ye(i){return e=>e.value&&i.value!==e.value?{passwordMismatch:!0}:null}function Ye(i){return e=>{if(!e.value||!i.value)return null;const t=new Date(e.value),a=new Date(i.value),n=new Date(a);return n.setDate(n.getDate()+1),t>=n?null:{endDateAfterStartDate:!0}}}function xe(i){const e=(i.value??"").toString().trim();if(!e)return null;let t=e;return e.startsWith("+966")?t=e.slice(4):e.startsWith("966")&&(t=e.slice(3)),/^\d+$/.test(t)?t.startsWith("0")?t.length===10?null:{invalidLength:!0}:t.startsWith("5")?t.length===9?null:{invalidLength:!0}:{invalidPrefix:!0}:{invalidFormat:!0}}function Je(i){return e=>{if(!e.value)return null;const t=new Date(e.value),a=new Date(i);return t>=a?null:{minDate:!0}}}function Qe(i){return e=>{if(!e.value)return null;const t=new Date(e.value),a=new Date(i);return t<=a?null:{maxDate:!0}}}function Xe(i){const e=i.value;return Array.isArray(e)&&e.some(a=>a&&typeof a=="object"&&a.status==="uploading")?{uploadInProgress:!0}:null}function De(i,e){const t=i.get("password"),a=i.get("confirmPassword");t&&a&&(a.addValidators(ye(t)),a.updateValueAndValidity({emitEvent:!1}));for(const[n,o]of ve){const r=i.get(n),s=i.get(o);if(!r||!s)continue;s.addValidators(Ye(r));const d=e.find(S=>S.name===o),f=S=>{if(d?.validation){if(S){const qe=new Date(S),P=new Date(qe);P.setDate(P.getDate()+1),d.validation.minDate=P.toISOString().split("T")[0]}else delete d.validation.minDate;s.updateValueAndValidity({emitEvent:!1})}};f(r.value),r.valueChanges.subscribe(S=>f(S))}}const we=["checkbox","multiselect","chips","file","multifile","multifilestaged"],Ze=["toggle"];function Se(i){return i.value!==void 0?i.value:we.includes(i.type)?[]:Ze.includes(i.type)?!1:""}function G(i,e){const t=[],a=i.validation;(e||i.required||a?.required)&&(we.includes(i.type)?t.push(et):i.type==="toggle"?t.push(b.requiredTrue):t.push(b.required)),(i.type==="email"||a?.pattern==="email")&&t.push(b.email);const n=a?.minLength;n!=null&&t.push(b.minLength(n));const o=a?.maxLength??i.maxLength;if(o!=null&&t.push(b.maxLength(o)),a?.pattern&&a.pattern!=="email"){const r=a.pattern;if(typeof r=="string"&&r.length>0&&r.length<=200)try{t.push(b.pattern(r))}catch{}}return a?.min!=null&&t.push(b.min(a.min)),a?.max!=null&&t.push(b.max(a.max)),i.maxChips!=null&&i.type==="chips"&&t.push(tt(i.maxChips)),i.type==="phone"&&t.push(xe),i.type==="multifilestaged"&&t.push(Xe),a?.minDate&&t.push(Je(a.minDate)),a?.maxDate&&t.push(Qe(a.maxDate)),t}function et(i){const e=i.value;return Array.isArray(e)&&e.length>0?null:{required:!0}}function tt(i){return e=>{const t=e.value;return Array.isArray(t)&&t.length>i?{maxChips:{max:i,actual:t.length}}:null}}function Ie(i,e,t=!0){const a=!!e.disabled;return i.control({value:Se(e),disabled:a},{validators:G(e,t&&!e.requiredWhen)})}function Ce(i,e){const t={};for(const a of e){if(a.hidden&&a.type==="hidden"){t[a.name]=i.control(a.value??"");continue}t[a.name]=Ie(i,a)}return i.group(t)}function Le(i,e){return e?.length?e.flatMap(t=>t.fields):i}function Fe(i,e,t){i.setValidators(G(e,t)),i.updateValueAndValidity({emitEvent:!1})}function j(i,e){return Array.isArray(i)?i.some(t=>t==e):i==e}function at(i){return i.label?.en??""}function it(i){return i.label?.ar??""}function M(i,e,t,a){return ke(a?.(i)??{name:i,type:"select",label:{en:"",ar:""}},e,t?.(i))}function nt(i,e,t,a,n){if(!i.showOnTitleEn&&!i.showOnTitleAr||t==null||t==="")return!1;const o=M(e,t,a,n);if(!o)return!1;const r=i.showOnTitleEn?at(o)===i.showOnTitleEn:!0,s=i.showOnTitleAr?it(o)===i.showOnTitleAr:!0;return r&&s}function Ne(i,e,t,a){if(!i.extraField)return!0;const n=i.extraFieldTrigger||i.dependsOn;if(!n)return!1;const o=e[n];return M(n,o,t,a)?.requiresTextInput===!0}function ke(i,e,t){return i?[...t??[],...i.options??[],...i.groupedOptions?.flatMap(n=>n.options)??[]].find(n=>n.value==e):void 0}function K(i,e,t,a){if(i.hidden&&i.type!=="hidden"||i.type==="hidden")return!1;if(!i.dependsOn&&!i.extraField)return!0;const n=i.dependsOn??i.extraFieldTrigger;if(!n)return Ne(i,e,t,a);const o=e[n];if(i.showOnValues?.length&&!i.showOnValues.some(r=>j(o,r))||(i.showOnTitleEn||i.showOnTitleAr)&&!nt(i,n,o,t,a))return!1;if(i.showWhenOptionProperty){const r=M(n,o,t,a),s=i.showWhenOptionProperty.property;if(!r||r[s]!==i.showWhenOptionProperty.value)return!1}return!(i.extraField&&!Ne(i,e,t,a)||i.dependsOn&&!i.showOnValues?.length&&!i.showWhenOptionProperty&&!i.showOnTitleEn&&!i.showOnTitleAr&&!i.extraField&&(o==null||o===""||Array.isArray(o)&&o.length===0))}function W(i,e,t,a){const n=i.requiredWhen;if(!n)return!!i.required;const o=e[n.field];if(n.optionProperty!=null){const r=M(n.field,o,t,a);return!!r&&r[n.optionProperty]===n.optionPropertyValue}return n.values?.length?n.values.some(r=>j(o,r)):n.value!==void 0?j(o,n.value):o!=null&&o!==""}const ot=new Set(["otp","file"]),Oe=/password|passwd|secret|token|otp|national.?id|ssn|pin$/i;class C{submitAdapter=c(E,{optional:!0});captcha=c(_,{optional:!0});buildPayload(e,t,a){const n=new Set(a.filter(r=>r.excludeFromPayload).map(r=>r.name));let o={};for(const[r,s]of Object.entries(t)){if(n.has(r))continue;const d=e.fieldMapping?.[r]??r;o[d]=s}return e.payloadTransformer?e.payloadTransformer(o):o}hasFileValues(e){return Object.values(e).some(t=>t instanceof File||Array.isArray(t)&&t.some(a=>a instanceof File||a?.file instanceof File))}toFormData(e){const t=new FormData;for(const[a,n]of Object.entries(e))if(n!=null)if(n instanceof File)t.append(a,n);else if(Array.isArray(n))for(const o of n)o instanceof File?t.append(a,o):o?.file instanceof File?t.append(a,o.file,o.name):t.append(a,typeof o=="string"?o:JSON.stringify(o));else typeof n=="object"?t.append(a,JSON.stringify(n)):t.append(a,String(n));return t}submitForm(e,t,a){if(!e.endpoint||!this.submitAdapter)return D(t);const n=this.buildPayload(e,t,a),o=n instanceof FormData?n:this.hasFileValues(n)?this.toFormData(n):n,r={};return e.idempotencyKey&&(r["Idempotency-Key"]=e.idempotencyKey),(this.captcha?.getToken("submit")??D(null)).pipe(ee(d=>(d&&(r["X-Recaptcha-Token"]=d),D({endpoint:e.endpoint,method:e.method??"POST",body:o,headers:r})))).pipe(ee(d=>this.submitAdapter.submit(d)),$e(d=>{throw d}))}saveDraft(e,t,a=[]){if(typeof localStorage>"u")return;const n=new Map(a.map(r=>[r.name,r])),o={};for(const[r,s]of Object.entries(t)){const d=n.get(r);d&&this.isDraftBlocked(d)||!d&&Oe.test(r)||s instanceof File||(o[r]=s)}localStorage.setItem(this.storageKey(e),JSON.stringify(o))}loadDraft(e){if(typeof localStorage>"u")return null;const t=localStorage.getItem(this.storageKey(e));if(!t)return null;try{return JSON.parse(t)}catch{return null}}clearDraft(e){typeof localStorage>"u"||localStorage.removeItem(this.storageKey(e))}isDraftBlocked(e){return e.excludeFromDraft||e.sensitive||e.excludeFromPayload||ot.has(e.type)?!0:Oe.test(e.name)}storageKey(e){return`dga-dynamic-form:${e}`}static ɵfac=l.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"22.0.7",ngImport:l,type:C,deps:[],target:l.ɵɵFactoryTarget.Injectable});static ɵprov=l.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"22.0.7",ngImport:l,type:C,providedIn:"root"})}l.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"22.0.7",ngImport:l,type:C,decorators:[{type:Y,args:[{providedIn:"root"}]}]});function v(i,e,t=""){if(!i)return t;const a=i[e];return a||(i.en?i.en:i.ar?i.ar:Object.values(i).find(o=>!!o)||t)}function Te(){return typeof document>"u"?"ar":(document.documentElement.lang||"ar").toLowerCase().split("-")[0]||"ar"}class L{extras=c(be,{optional:!0});map=new Map;constructor(){for(const e of this.extras??[])this.register(e)}register(e){this.map.set(e.type,e.component)}get(e){return this.map.get(e)??null}hasCustom(e){return this.map.has(e)}isBuiltIn(e){return rt.has(e)}static ɵfac=l.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"22.0.7",ngImport:l,type:L,deps:[],target:l.ɵɵFactoryTarget.Injectable});static ɵprov=l.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"22.0.7",ngImport:l,type:L,providedIn:"root"})}l.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"22.0.7",ngImport:l,type:L,decorators:[{type:Y,args:[{providedIn:"root"}]}],ctorParameters:()=>[]});const rt=new Set(["text","email","textarea","select","multiselect","checkbox","radio","phone","file","multifile","multifilestaged","date","chips","toggle","hidden","number","otp","password"]),Ae={resolveLabel(i,e){return v(i,e)}},Ee={getToken:()=>D(null)},Me={lookup:()=>D([])},lt=new Set(["__proto__","constructor","prototype"]);function F(i,e){const t=i.trim();if(!t)throw new Error("DGA dynamic form: empty HTTP URL");if(t.startsWith("/")&&!t.startsWith("//"))return t.replace(/\/$/,"")||"/";let a;try{a=new URL(t)}catch{throw new Error(`DGA dynamic form: invalid HTTP URL "${i}"`)}if(a.protocol!=="http:"&&a.protocol!=="https:")throw new Error(`DGA dynamic form: blocked URL protocol "${a.protocol}"`);if(e?.length&&!e.some(o=>{try{return new URL(o).origin===a.origin}catch{return o===a.origin}}))throw new Error(`DGA dynamic form: origin not allowlisted "${a.origin}"`);return a.toString().replace(/\/$/,"")}function Pe(i=c(I),e={}){return{lookup(t){try{const n=`${F(t.domain,e.allowedOrigins)}/lookup/${encodeURIComponent(t.name)}`,o={};if(t.parentId!=null&&t.parentId!==""&&(o.parentId=String(t.parentId)),t.search){const r=t.searchParamName||"q";o[r]=t.search}return i.get(n,{params:o}).pipe(Ue(r=>Array.isArray(r)?r.map(st):[]))}catch(a){return ge(()=>a)}}}}function st(i){const e=i??{},t=e.DisplayName??e.UserName??e.Email,a=e.value??e.id??e.Id??e.Code??t??"",n=String(e.labelEn??e.titleEn??e.en??e.TitleEn??e.Name??e.name??t??a),o=String(e.labelAr??e.titleAr??e.ar??e.TitleAr??e.NameAr??e.nameAr??n),r={value:a,label:{en:n,ar:o}};for(const[s,d]of Object.entries(e))lt.has(s)||s==="value"||s==="label"||s==="id"||s==="Id"||s==="labelEn"||s==="titleEn"||s==="en"||s==="TitleEn"||s==="labelAr"||s==="titleAr"||s==="ar"||s==="TitleAr"||(r[s]=d);return e.disabled!=null&&(r.disabled=!!e.disabled),e.requiresTextInput!=null&&(r.requiresTextInput=!!e.requiresTextInput),e.description&&typeof e.description=="object"&&(r.description=e.description),r}function Ve(i=c(I),e={}){return{submit(t){try{const a=F(t.endpoint,e.allowedOrigins),n=new He(t.headers??{}),o=t.method.toUpperCase();return o==="GET"?i.get(a,{headers:n}):o==="DELETE"?i.delete(a,{headers:n,body:t.body}):o==="PUT"?i.put(a,t.body,{headers:n}):o==="PATCH"?i.patch(a,t.body,{headers:n}):i.post(a,t.body,{headers:n})}catch(a){return ge(()=>a)}}}}function Re(i=c(je)){return{show(e){i.show({title:e.title,message:e.message,variant:e.variant??"info"})}}}function dt(i={}){const e=i.httpLookup??!1,t=i.httpSubmit??!0,a=i.dgaToast??!0,n=i.requireAllowedOrigins??!1,o={allowedOrigins:i.allowedOrigins};if(n&&(e||t)&&!i.allowedOrigins?.length)throw new Error("DGA dynamic form: provideDgaDynamicForm({ allowedOrigins: [...] }) is required when requireAllowedOrigins is true. ");return ze()&&(e||t)&&!i.allowedOrigins?.length&&console.warn("[dga-dynamic-form] HTTP adapters enabled without allowedOrigins. Absolute schema URLs can reach any https host — set allowedOrigins (and requireAllowedOrigins: true) for CMS schemas."),Be([{provide:$,useValue:o},{provide:U,useValue:Ae},{provide:_,useValue:Ee},{provide:z,useFactory:()=>e?Pe(c(I),o):Me},{provide:E,useFactory:()=>t?Ve(c(I),o):{submit:()=>D(null)}},{provide:B,useFactory:()=>a?Re():{show:()=>{}}}])}function ut(i,e,t=""){return v(i,e,t)}class y{accept=u("",...ngDevMode?[{debugName:"accept"}]:[]);maxFileSize=u(0,...ngDevMode?[{debugName:"maxFileSize"}]:[]);maxFiles=u(0,...ngDevMode?[{debugName:"maxFiles"}]:[]);uploadEndpoint=u("",...ngDevMode?[{debugName:"uploadEndpoint"}]:[]);deleteEndpoint=u("",...ngDevMode?[{debugName:"deleteEndpoint"}]:[]);deleteMethod=u("DELETE",...ngDevMode?[{debugName:"deleteMethod"}]:[]);hint=u("Drag files here or browse",...ngDevMode?[{debugName:"hint"}]:[]);browseLabel=u("Choose files",...ngDevMode?[{debugName:"browseLabel"}]:[]);removeLabel=u("Remove",...ngDevMode?[{debugName:"removeLabel"}]:[]);downloadLabel=u("Download",...ngDevMode?[{debugName:"downloadLabel"}]:[]);uploadingLabel=u("Uploading…",...ngDevMode?[{debugName:"uploadingLabel"}]:[]);errorLabel=u("Upload failed",...ngDevMode?[{debugName:"errorLabel"}]:[]);disabledInput=u(!1,{...ngDevMode?{debugName:"disabledInput"}:{},alias:"disabled",transform:J});cvaDisabled=m(!1,...ngDevMode?[{debugName:"cvaDisabled"}]:[]);disabled=p(()=>this.disabledInput()||this.cvaDisabled(),...ngDevMode?[{debugName:"disabled"}]:[]);fileDownload=g();http=c(I);httpSecurity=c($,{optional:!0});files=m([],...ngDevMode?[{debugName:"files"}]:[]);dragging=m(!1,...ngDevMode?[{debugName:"dragging"}]:[]);onChange=()=>{};onTouched=()=>{};atLimit=p(()=>{const e=this.maxFiles();return e>0&&this.files().length>=e},...ngDevMode?[{debugName:"atLimit"}]:[]);onDragOver(e){e.preventDefault(),!this.disabled()&&!this.atLimit()&&this.dragging.set(!0)}onDrop(e){if(e.preventDefault(),this.dragging.set(!1),this.disabled()||this.atLimit())return;const t=e.dataTransfer?.files;t?.length&&this.addFiles(Array.from(t))}onPick(e){const t=e.target;t.files?.length&&this.addFiles(Array.from(t.files)),t.value=""}remove(e){if(e.status==="uploading")return;const t=this.isExisting(e),a=this.deleteEndpoint();if(!t&&a&&e.fileId){const n=a.includes(":id")?a.replace(":id",encodeURIComponent(e.fileId)):a.includes(":fileId")?a.replace(":fileId",encodeURIComponent(e.fileId)):a;try{const o=F(n,this.httpSecurity?.allowedOrigins);this.deleteMethod()==="POST"?this.http.post(o,{FileName:e.fileName}).subscribe({complete:()=>this.commit(this.files().filter(r=>r!==e))}):this.http.delete(o).subscribe({complete:()=>this.commit(this.files().filter(r=>r!==e))});return}catch{}}this.commit(this.files().filter(n=>n!==e))}onDownload(e){this.isExisting(e)&&this.fileDownload.emit({Id:Number(e.fileId),FileName:e.fileName,ContentType:""})}isExisting(e){return e.listKey?.startsWith("existing-")??!1}addFiles(e){const t=this.maxFileSize(),a=this.maxFiles();let n=a>0?a-this.files().length:e.length;if(!(n<=0))for(const o of e.slice(0,n))t>0&&o.size>t||this.uploadOne(o)}uploadOne(e){const t=`new-${e.name}-${Date.now()}-${Math.random().toString(36).slice(2,7)}`,a={fileId:"",fileName:e.name,sizeBytes:e.size,status:"uploading",listKey:t},n=[...this.files(),a];this.files.set(n),this.onChange(n);const o=this.uploadEndpoint();if(!o){a.status="success",a.fileId=t,this.commit([...this.files()]);return}try{const r=F(o,this.httpSecurity?.allowedOrigins),s=new FormData;s.append("file",e),this.http.post(r,s).subscribe({next:d=>{a.status="success",a.fileId=d.fileId??t,d.fileName&&(a.fileName=d.fileName),this.commit([...this.files()])},error:d=>{a.status="error",a.errorMessage=d?.message??this.errorLabel(),this.commit([...this.files()])}})}catch(r){a.status="error",a.errorMessage=r?.message??this.errorLabel(),this.commit([...this.files()])}}commit(e){this.files.set(e),this.onChange(e),this.onTouched()}writeValue(e){const a=(Array.isArray(e)?e:[]).map(n=>{if("Id"in n&&"FileName"in n){const o=n;return{fileId:String(o.Id),fileName:o.FileName,status:"success",listKey:`existing-${o.Id}`}}return n});this.files.set(a)}registerOnChange(e){this.onChange=e}registerOnTouched(e){this.onTouched=e}setDisabledState(e){this.cvaDisabled.set(e)}static ɵfac=l.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"22.0.7",ngImport:l,type:y,deps:[],target:l.ɵɵFactoryTarget.Component});static ɵcmp=l.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"22.0.7",type:y,isStandalone:!0,selector:"dga-dynamic-form-staged-upload",inputs:{accept:{classPropertyName:"accept",publicName:"accept",isSignal:!0,isRequired:!1,transformFunction:null},maxFileSize:{classPropertyName:"maxFileSize",publicName:"maxFileSize",isSignal:!0,isRequired:!1,transformFunction:null},maxFiles:{classPropertyName:"maxFiles",publicName:"maxFiles",isSignal:!0,isRequired:!1,transformFunction:null},uploadEndpoint:{classPropertyName:"uploadEndpoint",publicName:"uploadEndpoint",isSignal:!0,isRequired:!1,transformFunction:null},deleteEndpoint:{classPropertyName:"deleteEndpoint",publicName:"deleteEndpoint",isSignal:!0,isRequired:!1,transformFunction:null},deleteMethod:{classPropertyName:"deleteMethod",publicName:"deleteMethod",isSignal:!0,isRequired:!1,transformFunction:null},hint:{classPropertyName:"hint",publicName:"hint",isSignal:!0,isRequired:!1,transformFunction:null},browseLabel:{classPropertyName:"browseLabel",publicName:"browseLabel",isSignal:!0,isRequired:!1,transformFunction:null},removeLabel:{classPropertyName:"removeLabel",publicName:"removeLabel",isSignal:!0,isRequired:!1,transformFunction:null},downloadLabel:{classPropertyName:"downloadLabel",publicName:"downloadLabel",isSignal:!0,isRequired:!1,transformFunction:null},uploadingLabel:{classPropertyName:"uploadingLabel",publicName:"uploadingLabel",isSignal:!0,isRequired:!1,transformFunction:null},errorLabel:{classPropertyName:"errorLabel",publicName:"errorLabel",isSignal:!0,isRequired:!1,transformFunction:null},disabledInput:{classPropertyName:"disabledInput",publicName:"disabled",isSignal:!0,isRequired:!1,transformFunction:null}},outputs:{fileDownload:"fileDownload"},host:{classAttribute:"block w-full"},providers:[ae(y)],ngImport:l,template:`
|
|
1
|
+
import*as l from"@angular/core";import{InjectionToken as x,inject as p,Injectable as X,isDevMode as je,makeEnvironmentProviders as We,input as c,booleanAttribute as Z,signal as f,computed as u,output as h,ChangeDetectionStrategy as R,Component as V,DestroyRef as ee,effect as N,untracked as q}from"@angular/core";import{NgComponentOutlet as te,NgTemplateOutlet as ae}from"@angular/common";import*as b from"@angular/forms";import{Validators as v,ReactiveFormsModule as O,FormsModule as ie,FormBuilder as Ke}from"@angular/forms";import{switchMap as ne,catchError as He,map as Ye,startWith as Je}from"rxjs/operators";import{takeUntilDestroyed as A}from"@angular/core/rxjs-interop";import{DgaToastService as Qe,DgaButton as E,DgaIcon as C,dgaProvideValueAccessor as oe,DgaField as re,DgaInput as le,DgaSelect as se,DgaCheckbox as de,DgaRadio as ce,DgaPhoneInput as ue,DgaChipInput as pe,DgaSwitch as fe,DgaUpload as me,DgaNumberInput as ge,DgaOtp as he,DgaAlert as be,DgaBadge as ve,DgaCard as ye,DgaProgress as xe,DgaStepper as De}from"@a.nemreen/dga-ui";import{of as D,throwError as we,startWith as Xe,catchError as Ze}from"rxjs";import{HttpClient as L,HttpHeaders as et}from"@angular/common/http";import{DgaDatePicker as Se}from"@a.nemreen/dga-ui/date-picker";const B=new x("DGA_LOOKUP_ADAPTER"),M=new x("DGA_SUBMIT_ADAPTER"),$=new x("DGA_FORM_TOAST_ADAPTER"),_=new x("DGA_CAPTCHA_ADAPTER"),U=new x("DGA_HTTP_SECURITY"),G=new x("DGA_FORM_I18N_ADAPTER"),Ce=new x("DGA_DYNAMIC_FORM_FIELD_REGISTRY"),Le=[["StartDate","EndDate"],["UseCaseStartDate","UseCaseEndDate"],["startDate","endDate"]];function Ie(i){return e=>e.value&&i.value!==e.value?{passwordMismatch:!0}:null}function tt(i){return e=>{if(!e.value||!i.value)return null;const t=new Date(e.value),a=new Date(i.value),n=new Date(a);return n.setDate(n.getDate()+1),t>=n?null:{endDateAfterStartDate:!0}}}function at(i){const e=(i??"").trim();if(e)return e.startsWith("+")?e:`+${e}`}function ke(i){const e=[...new Set((i??[]).map(t=>at(t?.code)).filter(t=>!!t&&t!=="+966"))].sort((t,a)=>a.length-t.length);return t=>{const a=(t.value??"").toString().trim();if(!a||!e.length)return j(t);const n=e.find(r=>a.startsWith(r));if(!n)return j(t);const o=a.slice(n.length).replace(/\s+/g,"");return o?/^\d+$/.test(o)?null:{invalidFormat:!0}:null}}function j(i){const e=(i.value??"").toString().trim();if(!e)return null;let t=e;return e.startsWith("+966")?t=e.slice(4):e.startsWith("966")&&(t=e.slice(3)),/^\d+$/.test(t)?t.startsWith("0")?t.length===10?null:{invalidLength:!0}:t.startsWith("5")?t.length===9?null:{invalidLength:!0}:{invalidPrefix:!0}:{invalidFormat:!0}}function it(i){return e=>{if(!e.value)return null;const t=new Date(e.value),a=new Date(i);return t>=a?null:{minDate:!0}}}function nt(i){return e=>{if(!e.value)return null;const t=new Date(e.value),a=new Date(i);return t<=a?null:{maxDate:!0}}}function ot(i){const e=i.value;return Array.isArray(e)&&e.some(a=>a&&typeof a=="object"&&a.status==="uploading")?{uploadInProgress:!0}:null}function Te(i,e){const t=i.get("password"),a=i.get("confirmPassword");t&&a&&(a.addValidators(Ie(t)),a.updateValueAndValidity({emitEvent:!1}));for(const[n,o]of Le){const r=i.get(n),s=i.get(o);if(!r||!s)continue;s.addValidators(tt(r));const d=e.find(S=>S.name===o),g=S=>{if(d?.validation){if(S){const Ge=new Date(S),z=new Date(Ge);z.setDate(z.getDate()+1),d.validation.minDate=z.toISOString().split("T")[0]}else delete d.validation.minDate;s.updateValueAndValidity({emitEvent:!1})}};g(r.value),r.valueChanges.subscribe(S=>g(S))}}const Fe=["checkbox","multiselect","chips","file","multifile","multifilestaged"],rt=["toggle"];function Ne(i){return i.value!==void 0?i.value:Fe.includes(i.type)?[]:rt.includes(i.type)?!1:""}function W(i,e){const t=[],a=i.validation;(e||i.required||a?.required)&&(Fe.includes(i.type)?t.push(lt):i.type==="toggle"?t.push(v.requiredTrue):t.push(v.required)),(i.type==="email"||a?.pattern==="email")&&t.push(v.email);const n=a?.minLength;n!=null&&t.push(v.minLength(n));const o=a?.maxLength??i.maxLength;if(o!=null&&t.push(v.maxLength(o)),a?.pattern&&a.pattern!=="email"){const r=a.pattern;if(typeof r=="string"&&r.length>0&&r.length<=200)try{t.push(v.pattern(r))}catch{}}return a?.min!=null&&t.push(v.min(a.min)),a?.max!=null&&t.push(v.max(a.max)),i.maxChips!=null&&i.type==="chips"&&t.push(st(i.maxChips)),i.type==="phone"&&t.push(ke(i.countries)),i.type==="multifilestaged"&&t.push(ot),a?.minDate&&t.push(it(a.minDate)),a?.maxDate&&t.push(nt(a.maxDate)),t}function lt(i){const e=i.value;return Array.isArray(e)&&e.length>0?null:{required:!0}}function st(i){return e=>{const t=e.value;return Array.isArray(t)&&t.length>i?{maxChips:{max:i,actual:t.length}}:null}}function Oe(i,e,t=!0){const a=!!e.disabled;return i.control({value:Ne(e),disabled:a},{validators:W(e,t&&!e.requiredWhen)})}function Ae(i,e){const t={};for(const a of e){if(a.hidden&&a.type==="hidden"){t[a.name]=i.control(a.value??"");continue}t[a.name]=Oe(i,a)}return i.group(t)}function Ee(i,e){return e?.length?e.flatMap(t=>t.fields):i}function K(i,e,t){i.setValidators(W(e,t)),i.updateValueAndValidity({emitEvent:!1})}function H(i,e){return Array.isArray(i)?i.some(t=>t==e):i==e}function dt(i){return i.label?.en??""}function ct(i){return i.label?.ar??""}function P(i,e,t,a){return Pe(a?.(i)??{name:i,type:"select",label:{en:"",ar:""}},e,t?.(i))}function ut(i,e,t,a,n){if(!i.showOnTitleEn&&!i.showOnTitleAr||t==null||t==="")return!1;const o=P(e,t,a,n);if(!o)return!1;const r=i.showOnTitleEn?dt(o)===i.showOnTitleEn:!0,s=i.showOnTitleAr?ct(o)===i.showOnTitleAr:!0;return r&&s}function Me(i,e,t,a){if(!i.extraField)return!0;const n=i.extraFieldTrigger||i.dependsOn;if(!n)return!1;const o=e[n];return P(n,o,t,a)?.requiresTextInput===!0}function Pe(i,e,t){return i?[...t??[],...i.options??[],...i.groupedOptions?.flatMap(n=>n.options)??[]].find(n=>n.value==e):void 0}function Y(i,e,t,a){if(i.hidden&&i.type!=="hidden"||i.type==="hidden")return!1;if(!i.dependsOn&&!i.extraField)return!0;const n=i.dependsOn??i.extraFieldTrigger;if(!n)return Me(i,e,t,a);const o=e[n];if(i.showOnValues?.length&&!i.showOnValues.some(r=>H(o,r))||(i.showOnTitleEn||i.showOnTitleAr)&&!ut(i,n,o,t,a))return!1;if(i.showWhenOptionProperty){const r=P(n,o,t,a),s=i.showWhenOptionProperty.property;if(!r||r[s]!==i.showWhenOptionProperty.value)return!1}return!(i.extraField&&!Me(i,e,t,a)||i.dependsOn&&!i.showOnValues?.length&&!i.showWhenOptionProperty&&!i.showOnTitleEn&&!i.showOnTitleAr&&!i.extraField&&(o==null||o===""||Array.isArray(o)&&o.length===0))}function J(i,e,t,a){const n=i.requiredWhen;if(!n)return!!i.required;const o=e[n.field];if(n.optionProperty!=null){const r=P(n.field,o,t,a);return!!r&&r[n.optionProperty]===n.optionPropertyValue}return n.values?.length?n.values.some(r=>H(o,r)):n.value!==void 0?H(o,n.value):o!=null&&o!==""}const pt=new Set(["otp","file"]),ze=/password|passwd|secret|token|otp|national.?id|ssn|pin$/i;class I{submitAdapter=p(M,{optional:!0});captcha=p(_,{optional:!0});buildPayload(e,t,a){const n=new Set(a.filter(r=>r.excludeFromPayload).map(r=>r.name));let o={};for(const[r,s]of Object.entries(t)){if(n.has(r))continue;const d=e.fieldMapping?.[r]??r;o[d]=s}return e.payloadTransformer?e.payloadTransformer(o):o}hasFileValues(e){return Object.values(e).some(t=>t instanceof File||Array.isArray(t)&&t.some(a=>a instanceof File||a?.file instanceof File))}toFormData(e){const t=new FormData;for(const[a,n]of Object.entries(e))if(n!=null)if(n instanceof File)t.append(a,n);else if(Array.isArray(n))for(const o of n)o instanceof File?t.append(a,o):o?.file instanceof File?t.append(a,o.file,o.name):t.append(a,typeof o=="string"?o:JSON.stringify(o));else typeof n=="object"?t.append(a,JSON.stringify(n)):t.append(a,String(n));return t}submitForm(e,t,a){if(!e.endpoint||!this.submitAdapter)return D(t);const n=this.buildPayload(e,t,a),o=n instanceof FormData?n:this.hasFileValues(n)?this.toFormData(n):n,r={};return e.idempotencyKey&&(r["Idempotency-Key"]=e.idempotencyKey),(this.captcha?.getToken("submit")??D(null)).pipe(ne(d=>(d&&(r["X-Recaptcha-Token"]=d),D({endpoint:e.endpoint,method:e.method??"POST",body:o,headers:r})))).pipe(ne(d=>this.submitAdapter.submit(d)),He(d=>{throw d}))}saveDraft(e,t,a=[]){if(typeof localStorage>"u")return;const n=new Map(a.map(r=>[r.name,r])),o={};for(const[r,s]of Object.entries(t)){const d=n.get(r);d&&this.isDraftBlocked(d)||!d&&ze.test(r)||s instanceof File||(o[r]=s)}localStorage.setItem(this.storageKey(e),JSON.stringify(o))}loadDraft(e){if(typeof localStorage>"u")return null;const t=localStorage.getItem(this.storageKey(e));if(!t)return null;try{return JSON.parse(t)}catch{return null}}clearDraft(e){typeof localStorage>"u"||localStorage.removeItem(this.storageKey(e))}isDraftBlocked(e){return e.excludeFromDraft||e.sensitive||e.excludeFromPayload||pt.has(e.type)?!0:ze.test(e.name)}storageKey(e){return`dga-dynamic-form:${e}`}static ɵfac=l.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"22.1.5",ngImport:l,type:I,deps:[],target:l.ɵɵFactoryTarget.Injectable});static ɵprov=l.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"22.1.5",ngImport:l,type:I,providedIn:"root"})}l.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"22.1.5",ngImport:l,type:I,decorators:[{type:X,args:[{providedIn:"root"}]}]});function m(i,e,t=""){if(!i)return t;const a=i[e];return a||(i.en?i.en:i.ar?i.ar:Object.values(i).find(o=>!!o)||t)}function Re(){return typeof document>"u"?"ar":(document.documentElement.lang||"ar").toLowerCase().split("-")[0]||"ar"}class k{extras=p(Ce,{optional:!0});map=new Map;constructor(){for(const e of this.extras??[])this.register(e)}register(e){this.map.set(e.type,e.component)}get(e){return this.map.get(e)??null}hasCustom(e){return this.map.has(e)}isBuiltIn(e){return ft.has(e)}static ɵfac=l.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"22.1.5",ngImport:l,type:k,deps:[],target:l.ɵɵFactoryTarget.Injectable});static ɵprov=l.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"22.1.5",ngImport:l,type:k,providedIn:"root"})}l.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"22.1.5",ngImport:l,type:k,decorators:[{type:X,args:[{providedIn:"root"}]}],ctorParameters:()=>[]});const ft=new Set(["text","email","textarea","select","multiselect","checkbox","radio","phone","file","multifile","multifilestaged","date","chips","toggle","hidden","number","otp","password"]),Ve={resolveLabel(i,e){return m(i,e)}},qe={getToken:()=>D(null)},Be={lookup:()=>D([])},mt=new Set(["__proto__","constructor","prototype"]);function T(i,e){const t=i.trim();if(!t)throw new Error("DGA dynamic form: empty HTTP URL");if(t.startsWith("/")&&!t.startsWith("//"))return t.replace(/\/$/,"")||"/";let a;try{a=new URL(t)}catch{throw new Error(`DGA dynamic form: invalid HTTP URL "${i}"`)}if(a.protocol!=="http:"&&a.protocol!=="https:")throw new Error(`DGA dynamic form: blocked URL protocol "${a.protocol}"`);if(e?.length&&!e.some(o=>{try{return new URL(o).origin===a.origin}catch{return o===a.origin}}))throw new Error(`DGA dynamic form: origin not allowlisted "${a.origin}"`);return a.toString().replace(/\/$/,"")}function $e(i=p(L),e={}){return{lookup(t){try{const n=`${T(t.domain,e.allowedOrigins)}/lookup/${encodeURIComponent(t.name)}`,o={};if(t.parentId!=null&&t.parentId!==""&&(o.parentId=String(t.parentId)),t.search){const r=t.searchParamName||"q";o[r]=t.search}return i.get(n,{params:o}).pipe(Ye(r=>Array.isArray(r)?r.map(gt):[]))}catch(a){return we(()=>a)}}}}function gt(i){const e=i??{},t=e.DisplayName??e.UserName??e.Email,a=e.value??e.id??e.Id??e.Code??t??"",n=String(e.labelEn??e.titleEn??e.en??e.TitleEn??e.Name??e.name??t??a),o=String(e.labelAr??e.titleAr??e.ar??e.TitleAr??e.NameAr??e.nameAr??n),r={value:a,label:{en:n,ar:o}};for(const[s,d]of Object.entries(e))mt.has(s)||s==="value"||s==="label"||s==="id"||s==="Id"||s==="labelEn"||s==="titleEn"||s==="en"||s==="TitleEn"||s==="labelAr"||s==="titleAr"||s==="ar"||s==="TitleAr"||(r[s]=d);return e.disabled!=null&&(r.disabled=!!e.disabled),e.requiresTextInput!=null&&(r.requiresTextInput=!!e.requiresTextInput),e.description&&typeof e.description=="object"&&(r.description=e.description),r}function _e(i=p(L),e={}){return{submit(t){try{const a=T(t.endpoint,e.allowedOrigins),n=new et(t.headers??{}),o=t.method.toUpperCase();return o==="GET"?i.get(a,{headers:n}):o==="DELETE"?i.delete(a,{headers:n,body:t.body}):o==="PUT"?i.put(a,t.body,{headers:n}):o==="PATCH"?i.patch(a,t.body,{headers:n}):i.post(a,t.body,{headers:n})}catch(a){return we(()=>a)}}}}function Ue(i=p(Qe)){return{show(e){i.show({title:e.title,message:e.message,variant:e.variant??"info"})}}}function ht(i={}){const e=i.httpLookup??!1,t=i.httpSubmit??!0,a=i.dgaToast??!0,n=i.requireAllowedOrigins??!1,o={allowedOrigins:i.allowedOrigins};if(n&&(e||t)&&!i.allowedOrigins?.length)throw new Error("DGA dynamic form: provideDgaDynamicForm({ allowedOrigins: [...] }) is required when requireAllowedOrigins is true. ");return je()&&(e||t)&&!i.allowedOrigins?.length&&console.warn("[dga-dynamic-form] HTTP adapters enabled without allowedOrigins. Absolute schema URLs can reach any https host — set allowedOrigins (and requireAllowedOrigins: true) for CMS schemas."),We([{provide:U,useValue:o},{provide:G,useValue:Ve},{provide:_,useValue:qe},{provide:B,useFactory:()=>e?$e(p(L),o):Be},{provide:M,useFactory:()=>t?_e(p(L),o):{submit:()=>D(null)}},{provide:$,useFactory:()=>a?Ue():{show:()=>{}}}])}function bt(i,e,t=""){return m(i,e,t)}class y{accept=c("",...ngDevMode?[{debugName:"accept"}]:[]);maxFileSize=c(0,...ngDevMode?[{debugName:"maxFileSize"}]:[]);maxFiles=c(0,...ngDevMode?[{debugName:"maxFiles"}]:[]);uploadEndpoint=c("",...ngDevMode?[{debugName:"uploadEndpoint"}]:[]);deleteEndpoint=c("",...ngDevMode?[{debugName:"deleteEndpoint"}]:[]);deleteMethod=c("DELETE",...ngDevMode?[{debugName:"deleteMethod"}]:[]);hint=c("Drag files here or browse",...ngDevMode?[{debugName:"hint"}]:[]);browseLabel=c("Choose files",...ngDevMode?[{debugName:"browseLabel"}]:[]);removeLabel=c("Remove",...ngDevMode?[{debugName:"removeLabel"}]:[]);downloadLabel=c("Download",...ngDevMode?[{debugName:"downloadLabel"}]:[]);uploadingLabel=c("Uploading…",...ngDevMode?[{debugName:"uploadingLabel"}]:[]);errorLabel=c("Upload failed",...ngDevMode?[{debugName:"errorLabel"}]:[]);disabledInput=c(!1,{...ngDevMode?{debugName:"disabledInput"}:{},alias:"disabled",transform:Z});cvaDisabled=f(!1,...ngDevMode?[{debugName:"cvaDisabled"}]:[]);disabled=u(()=>this.disabledInput()||this.cvaDisabled(),...ngDevMode?[{debugName:"disabled"}]:[]);fileDownload=h();http=p(L);httpSecurity=p(U,{optional:!0});files=f([],...ngDevMode?[{debugName:"files"}]:[]);dragging=f(!1,...ngDevMode?[{debugName:"dragging"}]:[]);onChange=()=>{};onTouched=()=>{};atLimit=u(()=>{const e=this.maxFiles();return e>0&&this.files().length>=e},...ngDevMode?[{debugName:"atLimit"}]:[]);onDragOver(e){e.preventDefault(),!this.disabled()&&!this.atLimit()&&this.dragging.set(!0)}onDrop(e){if(e.preventDefault(),this.dragging.set(!1),this.disabled()||this.atLimit())return;const t=e.dataTransfer?.files;t?.length&&this.addFiles(Array.from(t))}onPick(e){const t=e.target;t.files?.length&&this.addFiles(Array.from(t.files)),t.value=""}remove(e){if(e.status==="uploading")return;const t=this.isExisting(e),a=this.deleteEndpoint();if(!t&&a&&e.fileId){const n=a.includes(":id")?a.replace(":id",encodeURIComponent(e.fileId)):a.includes(":fileId")?a.replace(":fileId",encodeURIComponent(e.fileId)):a;try{const o=T(n,this.httpSecurity?.allowedOrigins);this.deleteMethod()==="POST"?this.http.post(o,{FileName:e.fileName}).subscribe({complete:()=>this.commit(this.files().filter(r=>r!==e))}):this.http.delete(o).subscribe({complete:()=>this.commit(this.files().filter(r=>r!==e))});return}catch{}}this.commit(this.files().filter(n=>n!==e))}onDownload(e){this.isExisting(e)&&this.fileDownload.emit({Id:Number(e.fileId),FileName:e.fileName,ContentType:""})}isExisting(e){return e.listKey?.startsWith("existing-")??!1}addFiles(e){const t=this.maxFileSize(),a=this.maxFiles();let n=a>0?a-this.files().length:e.length;if(!(n<=0))for(const o of e.slice(0,n))t>0&&o.size>t||this.uploadOne(o)}uploadOne(e){const t=`new-${e.name}-${Date.now()}-${Math.random().toString(36).slice(2,7)}`,a={fileId:"",fileName:e.name,sizeBytes:e.size,status:"uploading",listKey:t},n=[...this.files(),a];this.files.set(n),this.onChange(n);const o=this.uploadEndpoint();if(!o){a.status="success",a.fileId=t,this.commit([...this.files()]);return}try{const r=T(o,this.httpSecurity?.allowedOrigins),s=new FormData;s.append("file",e),this.http.post(r,s).subscribe({next:d=>{a.status="success",a.fileId=d.fileId??t,d.fileName&&(a.fileName=d.fileName),this.commit([...this.files()])},error:d=>{a.status="error",a.errorMessage=d?.message??this.errorLabel(),this.commit([...this.files()])}})}catch(r){a.status="error",a.errorMessage=r?.message??this.errorLabel(),this.commit([...this.files()])}}commit(e){this.files.set(e),this.onChange(e),this.onTouched()}writeValue(e){const a=(Array.isArray(e)?e:[]).map(n=>{if("Id"in n&&"FileName"in n){const o=n;return{fileId:String(o.Id),fileName:o.FileName,status:"success",listKey:`existing-${o.Id}`}}return n});this.files.set(a)}registerOnChange(e){this.onChange=e}registerOnTouched(e){this.onTouched=e}setDisabledState(e){this.cvaDisabled.set(e)}static ɵfac=l.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"22.1.5",ngImport:l,type:y,deps:[],target:l.ɵɵFactoryTarget.Component});static ɵcmp=l.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"22.1.5",type:y,isStandalone:!0,selector:"dga-dynamic-form-staged-upload",inputs:{accept:{classPropertyName:"accept",publicName:"accept",isSignal:!0,isRequired:!1,transformFunction:null},maxFileSize:{classPropertyName:"maxFileSize",publicName:"maxFileSize",isSignal:!0,isRequired:!1,transformFunction:null},maxFiles:{classPropertyName:"maxFiles",publicName:"maxFiles",isSignal:!0,isRequired:!1,transformFunction:null},uploadEndpoint:{classPropertyName:"uploadEndpoint",publicName:"uploadEndpoint",isSignal:!0,isRequired:!1,transformFunction:null},deleteEndpoint:{classPropertyName:"deleteEndpoint",publicName:"deleteEndpoint",isSignal:!0,isRequired:!1,transformFunction:null},deleteMethod:{classPropertyName:"deleteMethod",publicName:"deleteMethod",isSignal:!0,isRequired:!1,transformFunction:null},hint:{classPropertyName:"hint",publicName:"hint",isSignal:!0,isRequired:!1,transformFunction:null},browseLabel:{classPropertyName:"browseLabel",publicName:"browseLabel",isSignal:!0,isRequired:!1,transformFunction:null},removeLabel:{classPropertyName:"removeLabel",publicName:"removeLabel",isSignal:!0,isRequired:!1,transformFunction:null},downloadLabel:{classPropertyName:"downloadLabel",publicName:"downloadLabel",isSignal:!0,isRequired:!1,transformFunction:null},uploadingLabel:{classPropertyName:"uploadingLabel",publicName:"uploadingLabel",isSignal:!0,isRequired:!1,transformFunction:null},errorLabel:{classPropertyName:"errorLabel",publicName:"errorLabel",isSignal:!0,isRequired:!1,transformFunction:null},disabledInput:{classPropertyName:"disabledInput",publicName:"disabled",isSignal:!0,isRequired:!1,transformFunction:null}},outputs:{fileDownload:"fileDownload"},host:{classAttribute:"block w-full"},providers:[oe(y)],ngImport:l,template:`
|
|
2
2
|
<div class="flex flex-col gap-md">
|
|
3
3
|
<div
|
|
4
4
|
class="flex flex-col items-center justify-center gap-md rounded-lg border border-dashed border-border
|
|
@@ -76,7 +76,7 @@ import*as l from"@angular/core";import{InjectionToken as x,inject as c,Injectabl
|
|
|
76
76
|
</ul>
|
|
77
77
|
}
|
|
78
78
|
</div>
|
|
79
|
-
`,isInline:!0,dependencies:[{kind:"directive",type:
|
|
79
|
+
`,isInline:!0,dependencies:[{kind:"directive",type:E,selector:"button[dgaButton], a[dgaButton]",inputs:["variant","size","iconOnly","cooldownMs","loading","dgaButtonClass"]},{kind:"component",type:C,selector:"dga-icon",inputs:["name","glyph","size","tone","label"]}],changeDetection:l.ChangeDetectionStrategy.OnPush})}l.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"22.1.5",ngImport:l,type:y,decorators:[{type:V,args:[{selector:"dga-dynamic-form-staged-upload",standalone:!0,imports:[E,C],template:`
|
|
80
80
|
<div class="flex flex-col gap-md">
|
|
81
81
|
<div
|
|
82
82
|
class="flex flex-col items-center justify-center gap-md rounded-lg border border-dashed border-border
|
|
@@ -154,7 +154,7 @@ import*as l from"@angular/core";import{InjectionToken as x,inject as c,Injectabl
|
|
|
154
154
|
</ul>
|
|
155
155
|
}
|
|
156
156
|
</div>
|
|
157
|
-
`,changeDetection:
|
|
157
|
+
`,changeDetection:R.OnPush,host:{class:"block w-full"},providers:[oe(y)]}]}],propDecorators:{accept:[{type:l.Input,args:[{isSignal:!0,alias:"accept",required:!1}]}],maxFileSize:[{type:l.Input,args:[{isSignal:!0,alias:"maxFileSize",required:!1}]}],maxFiles:[{type:l.Input,args:[{isSignal:!0,alias:"maxFiles",required:!1}]}],uploadEndpoint:[{type:l.Input,args:[{isSignal:!0,alias:"uploadEndpoint",required:!1}]}],deleteEndpoint:[{type:l.Input,args:[{isSignal:!0,alias:"deleteEndpoint",required:!1}]}],deleteMethod:[{type:l.Input,args:[{isSignal:!0,alias:"deleteMethod",required:!1}]}],hint:[{type:l.Input,args:[{isSignal:!0,alias:"hint",required:!1}]}],browseLabel:[{type:l.Input,args:[{isSignal:!0,alias:"browseLabel",required:!1}]}],removeLabel:[{type:l.Input,args:[{isSignal:!0,alias:"removeLabel",required:!1}]}],downloadLabel:[{type:l.Input,args:[{isSignal:!0,alias:"downloadLabel",required:!1}]}],uploadingLabel:[{type:l.Input,args:[{isSignal:!0,alias:"uploadingLabel",required:!1}]}],errorLabel:[{type:l.Input,args:[{isSignal:!0,alias:"errorLabel",required:!1}]}],disabledInput:[{type:l.Input,args:[{isSignal:!0,alias:"disabled",required:!1}]}],fileDownload:[{type:l.Output,args:["fileDownload"]}]}});class w{field=c.required(...ngDevMode?[{debugName:"field"}]:[]);form=c.required(...ngDevMode?[{debugName:"form"}]:[]);locale=c("ar",...ngDevMode?[{debugName:"locale"}]:[]);required=c(!1,{...ngDevMode?{debugName:"required"}:{},transform:Z});error=c("",...ngDevMode?[{debugName:"error"}]:[]);runtimeOptions=c([],...ngDevMode?[{debugName:"runtimeOptions"}]:[]);consentBaseUrl=c(...ngDevMode?[void 0,{debugName:"consentBaseUrl"}]:[]);optionsLoaded=h();fileDownload=h();lookup=p(B,{optional:!0});http=p(L,{optional:!0});destroyRef=p(ee);loadedOptions=f([],...ngDevMode?[{debugName:"loadedOptions"}]:[]);controlId=`dga-df-${Math.random().toString(36).slice(2,9)}`;get control(){return this.form().controls[this.field().name]}labelText=u(()=>m(this.field().label,this.locale()),...ngDevMode?[{debugName:"labelText"}]:[]);hintText=u(()=>m(this.field().hint,this.locale()),...ngDevMode?[{debugName:"hintText"}]:[]);placeholderText=u(()=>m(this.field().placeholder,this.locale()),...ngDevMode?[{debugName:"placeholderText"}]:[]);phoneCountries=u(()=>(this.field().countries??[]).flatMap(e=>{const t=(e.code??"").trim();if(!t)return[];const a=t.startsWith("+")?t:`+${t}`;return[{code:a,label:(e.label??"").trim()||a,name:e.name}]}),...ngDevMode?[{debugName:"phoneCountries"}]:[]);resolvedOptions=u(()=>{const e=this.runtimeOptions();if(e.length)return e;const t=this.loadedOptions();if(t.length)return t;const a=this.field();return a.options?.length?a.options:a.groupedOptions?.flatMap(n=>n.options)??[]},...ngDevMode?[{debugName:"resolvedOptions"}]:[]);optionGroups=u(()=>{const e=this.runtimeOptions();if(e.length)return[{label:"",options:e}];const t=this.loadedOptions();if(t.length)return[{label:"",options:t}];const a=this.field();return a.groupedOptions?.length&&!a.options?.length?a.groupedOptions.map(n=>({label:m(n.groupLabel,this.locale()),options:n.options})):[{label:"",options:a.options??[]}]},...ngDevMode?[{debugName:"optionGroups"}]:[]);selectOptions=u(()=>this.resolvedOptions().map(e=>({value:String(e.value),label:this.optionLabel(e),disabled:!!e.disabled})),...ngDevMode?[{debugName:"selectOptions"}]:[]);ngOnInit(){const e=this.field();if(this.mapExistingFileValue(),e.consentServiceName&&this.consentBaseUrl()&&this.http&&this.fetchConsent(e),e.lookupDomain&&e.lookupName&&this.lookup){if(e.dependsOn&&e.useParentId!==!1){const t=this.form().get(e.dependsOn);if(t){t.valueChanges.pipe(Xe(t.value),A(this.destroyRef)).subscribe(a=>this.fetchLookup(e,a));return}}e.searchLookup||this.fetchLookup(e)}}mapExistingFileValue(){const e=this.field();if(e.type!=="file"&&e.type!=="multifile")return;const t=this.control.value;if(!Array.isArray(t)||!t.length)return;const a=t[0];if(!a||!("Id"in a)||!("FileName"in a))return;const n=t.map(o=>({id:String(o.Id),name:o.FileName,size:0}));this.control.setValue(n,{emitEvent:!1})}fetchConsent(e){const a=`${this.consentBaseUrl().replace(/\/$/,"")}/consents/${encodeURIComponent(e.consentServiceName)}`;this.http.get(a).pipe(Ze(()=>D(null)),A(this.destroyRef)).subscribe(n=>{if(!n?.Content)return;const o={en:n.Content.En||n.Content.Ar||"",ar:n.Content.Ar||n.Content.En||""};if(e.type==="checkbox"){const r=e.options?.length?[...e.options]:[{value:!0,label:{en:"",ar:""}}];r[0]={...r[0],label:o},this.loadedOptions.set(r),this.optionsLoaded.emit({name:e.name,options:r})}})}fetchLookup(e,t,a){if(!this.lookup||!e.lookupDomain||!e.lookupName)return;const n=e.minSearchLength??(e.searchLookup?3:0);a!=null&&a.length<n||this.lookup.lookup({domain:e.lookupDomain,name:e.lookupName,parentId:e.useParentId!==!1&&t!=null&&t!==""?t:void 0,search:a||void 0,searchParamName:e.searchParamName}).pipe(A(this.destroyRef)).subscribe(o=>{const r=this.applyLookupFilter(o);this.loadedOptions.set(r),this.optionsLoaded.emit({name:e.name,options:r})})}optionLabel(e){return m(e.label,this.locale())}optionDescription(e){return e.description?m(e.description,this.locale()):""}isCardsLayout(){return this.field().optionsLayout==="cards"}optionsContainerClass(){const e=this.field().optionsLayout;return e==="cards"?"grid grid-cols-1 gap-md sm:grid-cols-2":e==="grid"?"flex flex-wrap gap-lg":"flex flex-col gap-md"}choiceLabelClass(e){return this.isCardsLayout()?["flex min-h-7xl cursor-pointer items-start gap-lg rounded-lg border border-border bg-elevated p-xl text-start shadow-xs","transition-[border-color,box-shadow,background-color] hover:border-border-primary-light hover:shadow-sm","has-[:checked]:border-border-primary has-[:checked]:bg-primary-faint has-[:checked]:shadow-sm has-[:checked]:ring-2 has-[:checked]:ring-primary/20","has-[:focus-visible]:outline has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-focus",e.disabled||this.field().disabled?"pointer-events-none opacity-50":""].filter(Boolean).join(" "):"inline-flex max-w-full items-start gap-sm text-body-sm text-fg"}isPasswordField(){const e=this.field().name;return e==="password"||e==="confirmPassword"}isChecked(e){const t=this.control?.value;return Array.isArray(t)&&t.some(a=>a==e)}toggleCheckbox(e,t){const a=Array.isArray(this.control.value)?[...this.control.value]:[],n=t?a.some(o=>o==e)?a:[...a,e]:a.filter(o=>o!=e);this.control.setValue(n),this.control.markAsDirty()}onSelectSearchQuery(e){const t=this.field();t.searchLookup&&this.fetchLookup(t,this.form().get(t.dependsOn??"")?.value,e)}onStagedFileDownload(e){this.fileDownload.emit(e)}onRestrict(e){const t=this.field().inputRestriction;if(!t)return;const a=e.target;let n=a.value;t==="numbers"&&(n=n.replace(/\D+/g,"")),t==="english"&&(n=n.replace(/[^a-zA-Z0-9\s.,\-_/]/g,"")),t==="arabic"&&(n=n.replace(/[^\u0600-\u06FF0-9\s.,\-_/]/g,"")),n!==a.value&&(a.value=n,this.control.setValue(n))}applyLookupFilter(e){const t=this.field().lookupFilter;return t?e.filter(a=>a[t.property]===t.value):e}static ɵfac=l.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"22.1.5",ngImport:l,type:w,deps:[],target:l.ɵɵFactoryTarget.Component});static ɵcmp=l.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"22.1.5",type:w,isStandalone:!0,selector:"dga-dynamic-form-field",inputs:{field:{classPropertyName:"field",publicName:"field",isSignal:!0,isRequired:!0,transformFunction:null},form:{classPropertyName:"form",publicName:"form",isSignal:!0,isRequired:!0,transformFunction:null},locale:{classPropertyName:"locale",publicName:"locale",isSignal:!0,isRequired:!1,transformFunction:null},required:{classPropertyName:"required",publicName:"required",isSignal:!0,isRequired:!1,transformFunction:null},error:{classPropertyName:"error",publicName:"error",isSignal:!0,isRequired:!1,transformFunction:null},runtimeOptions:{classPropertyName:"runtimeOptions",publicName:"runtimeOptions",isSignal:!0,isRequired:!1,transformFunction:null},consentBaseUrl:{classPropertyName:"consentBaseUrl",publicName:"consentBaseUrl",isSignal:!0,isRequired:!1,transformFunction:null}},outputs:{optionsLoaded:"optionsLoaded",fileDownload:"fileDownload"},host:{properties:{"class.hidden":'field().type === "hidden"'},classAttribute:"block w-full"},ngImport:l,template:`
|
|
158
158
|
@if (field().type !== 'hidden') {
|
|
159
159
|
<dga-field
|
|
160
160
|
[label]="labelText()"
|
|
@@ -208,6 +208,7 @@ import*as l from"@angular/core";import{InjectionToken as x,inject as c,Injectabl
|
|
|
208
208
|
[required]="required()"
|
|
209
209
|
[controlId]="controlId"
|
|
210
210
|
[locale]="locale()"
|
|
211
|
+
[countries]="phoneCountries()"
|
|
211
212
|
/>
|
|
212
213
|
}
|
|
213
214
|
@case ('date') {
|
|
@@ -298,44 +299,77 @@ import*as l from"@angular/core";import{InjectionToken as x,inject as c,Injectabl
|
|
|
298
299
|
/>
|
|
299
300
|
}
|
|
300
301
|
@case ('radio') {
|
|
301
|
-
<div
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
302
|
+
<div class="flex flex-col gap-lg" role="radiogroup" [attr.aria-labelledby]="controlId">
|
|
303
|
+
@for (group of optionGroups(); track $index) {
|
|
304
|
+
@if (group.label) {
|
|
305
|
+
<p class="m-0 text-label-sm font-medium text-muted">{{ group.label }}</p>
|
|
306
|
+
}
|
|
307
|
+
<div [class]="optionsContainerClass()">
|
|
308
|
+
@for (opt of group.options; track opt.value) {
|
|
309
|
+
<label [class]="choiceLabelClass(opt)">
|
|
310
|
+
<input
|
|
311
|
+
type="radio"
|
|
312
|
+
dgaRadio
|
|
313
|
+
class="peer mt-xxs"
|
|
314
|
+
[name]="field().name"
|
|
315
|
+
[value]="opt.value"
|
|
316
|
+
[formControl]="control"
|
|
317
|
+
[disabled]="!!opt.disabled || !!field().disabled"
|
|
318
|
+
[dgaInvalid]="!!error()"
|
|
319
|
+
/>
|
|
320
|
+
<span class="flex min-w-0 flex-col gap-xxs">
|
|
321
|
+
<span class="text-body-sm font-medium text-fg">{{ optionLabel(opt) }}</span>
|
|
322
|
+
@if (optionDescription(opt); as desc) {
|
|
323
|
+
<span class="text-body-xs text-muted">{{ desc }}</span>
|
|
324
|
+
}
|
|
325
|
+
</span>
|
|
326
|
+
@if (isCardsLayout()) {
|
|
327
|
+
<span
|
|
328
|
+
class="ms-auto hidden shrink-0 text-fg-primary peer-checked:inline-flex"
|
|
329
|
+
>
|
|
330
|
+
<dga-icon name="checkCircle" size="sm" tone="primary" />
|
|
331
|
+
</span>
|
|
332
|
+
}
|
|
333
|
+
</label>
|
|
334
|
+
}
|
|
335
|
+
</div>
|
|
319
336
|
}
|
|
320
337
|
</div>
|
|
321
338
|
}
|
|
322
339
|
@case ('checkbox') {
|
|
323
|
-
<div
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
<
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
340
|
+
<div class="flex flex-col gap-lg">
|
|
341
|
+
@for (group of optionGroups(); track $index) {
|
|
342
|
+
@if (group.label) {
|
|
343
|
+
<p class="m-0 text-label-sm font-medium text-muted">{{ group.label }}</p>
|
|
344
|
+
}
|
|
345
|
+
<div [class]="optionsContainerClass()">
|
|
346
|
+
@for (opt of group.options; track opt.value) {
|
|
347
|
+
<label [class]="choiceLabelClass(opt)">
|
|
348
|
+
<input
|
|
349
|
+
type="checkbox"
|
|
350
|
+
dgaCheckbox
|
|
351
|
+
class="peer mt-xxs"
|
|
352
|
+
[checked]="isChecked(opt.value)"
|
|
353
|
+
[disabled]="!!opt.disabled || !!field().disabled"
|
|
354
|
+
[dgaInvalid]="!!error()"
|
|
355
|
+
(change)="toggleCheckbox(opt.value, $any($event.target).checked)"
|
|
356
|
+
/>
|
|
357
|
+
<span class="flex min-w-0 flex-col gap-xxs">
|
|
358
|
+
<span class="text-body-sm font-medium text-fg">{{ optionLabel(opt) }}</span>
|
|
359
|
+
@if (optionDescription(opt); as desc) {
|
|
360
|
+
<span class="text-body-xs text-muted">{{ desc }}</span>
|
|
361
|
+
}
|
|
362
|
+
</span>
|
|
363
|
+
@if (isCardsLayout()) {
|
|
364
|
+
<span
|
|
365
|
+
class="ms-auto hidden shrink-0 text-fg-primary peer-checked:inline-flex"
|
|
366
|
+
>
|
|
367
|
+
<dga-icon name="checkCircle" size="sm" tone="primary" />
|
|
368
|
+
</span>
|
|
369
|
+
}
|
|
370
|
+
</label>
|
|
371
|
+
}
|
|
372
|
+
</div>
|
|
339
373
|
}
|
|
340
374
|
</div>
|
|
341
375
|
}
|
|
@@ -368,7 +402,7 @@ import*as l from"@angular/core";import{InjectionToken as x,inject as c,Injectabl
|
|
|
368
402
|
}
|
|
369
403
|
</dga-field>
|
|
370
404
|
}
|
|
371
|
-
`,isInline:!0,dependencies:[{kind:"ngmodule",type:O},{kind:"directive",type:
|
|
405
|
+
`,isInline:!0,dependencies:[{kind:"ngmodule",type:O},{kind:"directive",type:b.DefaultValueAccessor,selector:"input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]"},{kind:"directive",type:b.RadioControlValueAccessor,selector:"input[type=radio]:not([ngNoCva])[formControlName],input[type=radio]:not([ngNoCva])[formControl],input[type=radio]:not([ngNoCva])[ngModel]",inputs:["name","formControlName","value"]},{kind:"directive",type:b.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:b.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:b.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"ngmodule",type:ie},{kind:"component",type:re,selector:"dga-field",inputs:["label","labelHint","hint","error","status","statusMessage","controlId","required"]},{kind:"directive",type:le,selector:"input[dgaInput], textarea[dgaInput]",inputs:["size","dgaInvalid","status"]},{kind:"component",type:se,selector:"dga-select",inputs:["options","value","multiple","searchable","openMode","clearable","size","status","placeholder","label","removeLabel","clearLabel","emptyLabel","disabled","dgaInvalid"],outputs:["valueChange","searchChange"]},{kind:"directive",type:de,selector:'input[type="checkbox"][dgaCheckbox]',inputs:["size","dgaInvalid"]},{kind:"directive",type:ce,selector:'input[type="radio"][dgaRadio]',inputs:["size","dgaInvalid"]},{kind:"component",type:ue,selector:"dga-phone-input",inputs:["countries","locale","countryCode","nationalNumber","controlId","name","placeholder","autocomplete","codeLabel","disabled","required","invalid","value"],outputs:["countryCodeChange","nationalNumberChange","valueChange"]},{kind:"component",type:Se,selector:"dga-date-picker",inputs:["value","startValue","endValue","calendar","range","format","mode","locale","minDate","maxDate","yearBefore","yearAfter","placeholder","controlId","name","size","disabled","required","clearable","editable","dgaInvalid","status","rangeSeparator","todayLabel","clearLabel","closeLabel","saveLabel","ariaLabel"],outputs:["startValueChange","endValueChange","valueChange","rangeChange"]},{kind:"component",type:pe,selector:"dga-chip-input",inputs:["value","placeholder","label","removeLabel","disabled","allowDuplicates","dgaInvalid","status"],outputs:["valueChange"]},{kind:"component",type:fe,selector:"dga-switch",inputs:["checked","size","label","disabled"],outputs:["checkedChange","changed"]},{kind:"component",type:me,selector:"dga-upload",inputs:["files","accept","multiple","appearance","hint","browseLabel","removeLabel","disabled","maxSize","maxFiles","dragging"],outputs:["filesChange","rejected","draggingChange"]},{kind:"component",type:ge,selector:"dga-number-input",inputs:["value","min","max","step","size","label","controlId","name","incrementLabel","decrementLabel","disabled","dgaInvalid","status"],outputs:["valueChange"]},{kind:"component",type:he,selector:"dga-otp",inputs:["length","value","label","alphanumeric","disabled","dgaInvalid"],outputs:["valueChange","completed"]},{kind:"component",type:C,selector:"dga-icon",inputs:["name","glyph","size","tone","label"]},{kind:"component",type:y,selector:"dga-dynamic-form-staged-upload",inputs:["accept","maxFileSize","maxFiles","uploadEndpoint","deleteEndpoint","deleteMethod","hint","browseLabel","removeLabel","downloadLabel","uploadingLabel","errorLabel","disabled"],outputs:["fileDownload"]}],changeDetection:l.ChangeDetectionStrategy.OnPush})}l.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"22.1.5",ngImport:l,type:w,decorators:[{type:V,args:[{selector:"dga-dynamic-form-field",standalone:!0,imports:[O,ie,re,le,se,de,ce,ue,Se,pe,fe,me,ge,he,C,y],template:`
|
|
372
406
|
@if (field().type !== 'hidden') {
|
|
373
407
|
<dga-field
|
|
374
408
|
[label]="labelText()"
|
|
@@ -422,6 +456,7 @@ import*as l from"@angular/core";import{InjectionToken as x,inject as c,Injectabl
|
|
|
422
456
|
[required]="required()"
|
|
423
457
|
[controlId]="controlId"
|
|
424
458
|
[locale]="locale()"
|
|
459
|
+
[countries]="phoneCountries()"
|
|
425
460
|
/>
|
|
426
461
|
}
|
|
427
462
|
@case ('date') {
|
|
@@ -512,44 +547,77 @@ import*as l from"@angular/core";import{InjectionToken as x,inject as c,Injectabl
|
|
|
512
547
|
/>
|
|
513
548
|
}
|
|
514
549
|
@case ('radio') {
|
|
515
|
-
<div
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
550
|
+
<div class="flex flex-col gap-lg" role="radiogroup" [attr.aria-labelledby]="controlId">
|
|
551
|
+
@for (group of optionGroups(); track $index) {
|
|
552
|
+
@if (group.label) {
|
|
553
|
+
<p class="m-0 text-label-sm font-medium text-muted">{{ group.label }}</p>
|
|
554
|
+
}
|
|
555
|
+
<div [class]="optionsContainerClass()">
|
|
556
|
+
@for (opt of group.options; track opt.value) {
|
|
557
|
+
<label [class]="choiceLabelClass(opt)">
|
|
558
|
+
<input
|
|
559
|
+
type="radio"
|
|
560
|
+
dgaRadio
|
|
561
|
+
class="peer mt-xxs"
|
|
562
|
+
[name]="field().name"
|
|
563
|
+
[value]="opt.value"
|
|
564
|
+
[formControl]="control"
|
|
565
|
+
[disabled]="!!opt.disabled || !!field().disabled"
|
|
566
|
+
[dgaInvalid]="!!error()"
|
|
567
|
+
/>
|
|
568
|
+
<span class="flex min-w-0 flex-col gap-xxs">
|
|
569
|
+
<span class="text-body-sm font-medium text-fg">{{ optionLabel(opt) }}</span>
|
|
570
|
+
@if (optionDescription(opt); as desc) {
|
|
571
|
+
<span class="text-body-xs text-muted">{{ desc }}</span>
|
|
572
|
+
}
|
|
573
|
+
</span>
|
|
574
|
+
@if (isCardsLayout()) {
|
|
575
|
+
<span
|
|
576
|
+
class="ms-auto hidden shrink-0 text-fg-primary peer-checked:inline-flex"
|
|
577
|
+
>
|
|
578
|
+
<dga-icon name="checkCircle" size="sm" tone="primary" />
|
|
579
|
+
</span>
|
|
580
|
+
}
|
|
581
|
+
</label>
|
|
582
|
+
}
|
|
583
|
+
</div>
|
|
533
584
|
}
|
|
534
585
|
</div>
|
|
535
586
|
}
|
|
536
587
|
@case ('checkbox') {
|
|
537
|
-
<div
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
<
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
588
|
+
<div class="flex flex-col gap-lg">
|
|
589
|
+
@for (group of optionGroups(); track $index) {
|
|
590
|
+
@if (group.label) {
|
|
591
|
+
<p class="m-0 text-label-sm font-medium text-muted">{{ group.label }}</p>
|
|
592
|
+
}
|
|
593
|
+
<div [class]="optionsContainerClass()">
|
|
594
|
+
@for (opt of group.options; track opt.value) {
|
|
595
|
+
<label [class]="choiceLabelClass(opt)">
|
|
596
|
+
<input
|
|
597
|
+
type="checkbox"
|
|
598
|
+
dgaCheckbox
|
|
599
|
+
class="peer mt-xxs"
|
|
600
|
+
[checked]="isChecked(opt.value)"
|
|
601
|
+
[disabled]="!!opt.disabled || !!field().disabled"
|
|
602
|
+
[dgaInvalid]="!!error()"
|
|
603
|
+
(change)="toggleCheckbox(opt.value, $any($event.target).checked)"
|
|
604
|
+
/>
|
|
605
|
+
<span class="flex min-w-0 flex-col gap-xxs">
|
|
606
|
+
<span class="text-body-sm font-medium text-fg">{{ optionLabel(opt) }}</span>
|
|
607
|
+
@if (optionDescription(opt); as desc) {
|
|
608
|
+
<span class="text-body-xs text-muted">{{ desc }}</span>
|
|
609
|
+
}
|
|
610
|
+
</span>
|
|
611
|
+
@if (isCardsLayout()) {
|
|
612
|
+
<span
|
|
613
|
+
class="ms-auto hidden shrink-0 text-fg-primary peer-checked:inline-flex"
|
|
614
|
+
>
|
|
615
|
+
<dga-icon name="checkCircle" size="sm" tone="primary" />
|
|
616
|
+
</span>
|
|
617
|
+
}
|
|
618
|
+
</label>
|
|
619
|
+
}
|
|
620
|
+
</div>
|
|
553
621
|
}
|
|
554
622
|
</div>
|
|
555
623
|
}
|
|
@@ -582,21 +650,107 @@ import*as l from"@angular/core";import{InjectionToken as x,inject as c,Injectabl
|
|
|
582
650
|
}
|
|
583
651
|
</dga-field>
|
|
584
652
|
}
|
|
585
|
-
`,changeDetection:V.OnPush,host:{class:"block w-full","[class.hidden]":'field().type === "hidden"'}}]}],propDecorators:{field:[{type:l.Input,args:[{isSignal:!0,alias:"field",required:!0}]}],form:[{type:l.Input,args:[{isSignal:!0,alias:"form",required:!0}]}],locale:[{type:l.Input,args:[{isSignal:!0,alias:"locale",required:!1}]}],required:[{type:l.Input,args:[{isSignal:!0,alias:"required",required:!1}]}],error:[{type:l.Input,args:[{isSignal:!0,alias:"error",required:!1}]}],runtimeOptions:[{type:l.Input,args:[{isSignal:!0,alias:"runtimeOptions",required:!1}]}],consentBaseUrl:[{type:l.Input,args:[{isSignal:!0,alias:"consentBaseUrl",required:!1}]}],optionsLoaded:[{type:l.Output,args:["optionsLoaded"]}],fileDownload:[{type:l.Output,args:["fileDownload"]}]}});const ct={1:"col-span-1",2:"col-span-2",3:"col-span-3",4:"col-span-4",5:"col-span-5",6:"col-span-6",7:"col-span-7",8:"col-span-8",9:"col-span-9",10:"col-span-10",11:"col-span-11",12:"col-span-12"},pt={1:"md:col-span-1",2:"md:col-span-2",3:"md:col-span-3",4:"md:col-span-4",5:"md:col-span-5",6:"md:col-span-6",7:"md:col-span-7",8:"md:col-span-8",9:"md:col-span-9",10:"md:col-span-10",11:"md:col-span-11",12:"md:col-span-12"},ft={1:"lg:col-span-1",2:"lg:col-span-2",3:"lg:col-span-3",4:"lg:col-span-4",5:"lg:col-span-5",6:"lg:col-span-6",7:"lg:col-span-7",8:"lg:col-span-8",9:"lg:col-span-9",10:"lg:col-span-10",11:"lg:col-span-11",12:"lg:col-span-12"};function H(i){return Number.isFinite(i)?Math.min(12,Math.max(1,Math.round(i))):12}class N{config=u.required(...ngDevMode?[{debugName:"config"}]:[]);localeInput=u(null,{...ngDevMode?{debugName:"localeInput"}:{},alias:"locale"});formSubmitted=g();formError=g();clearButtonClick=g();draftSaved=g();fileDownload=g();fb=c(_e);formService=c(C);submitAdapter=c(E,{optional:!0});toast=c(B,{optional:!0});i18n=c(U,{optional:!0});destroyRef=c(Q);registry=c(L);form;formSignature="";valueChangesSub=null;activeStep=m(0,...ngDevMode?[{debugName:"activeStep"}]:[]);submitting=m(!1,...ngDevMode?[{debugName:"submitting"}]:[]);optionsMap=m({},...ngDevMode?[{debugName:"optionsMap"}]:[]);formValues=m({},...ngDevMode?[{debugName:"formValues"}]:[]);locale=p(()=>this.localeInput()??Te(),...ngDevMode?[{debugName:"locale"}]:[]);wizardEnabled=p(()=>!!this.config().wizard?.enabled&&!!this.config().wizard?.steps?.length,...ngDevMode?[{debugName:"wizardEnabled"}]:[]);allFields=p(()=>Le(this.config().fields,this.config().wizard?.steps),...ngDevMode?[{debugName:"allFields"}]:[]);currentStepFields=p(()=>this.wizardEnabled()?this.config().wizard.steps[this.activeStep()]?.fields??[]:this.config().fields,...ngDevMode?[{debugName:"currentStepFields"}]:[]);visibleFields=p(()=>{const e=this.formValues(),t=this.optionsMap(),a=this.allFields(),n=o=>a.find(r=>r.name===o);return this.currentStepFields().filter(o=>K(o,e,r=>t[r],n))},...ngDevMode?[{debugName:"visibleFields"}]:[]);stepperSteps=p(()=>{const e=this.config().wizard?.steps??[],t=this.activeStep(),a=!!this.config().wizard?.allowSkipSteps;return e.map((n,o)=>({label:this.labelOf(n.title),description:n.description?this.labelOf(n.description):void 0,disabled:!a&&o>t}))},...ngDevMode?[{debugName:"stepperSteps"}]:[]);descriptionText=p(()=>this.labelOf(this.config().description),...ngDevMode?[{debugName:"descriptionText"}]:[]);constructor(){this.form=this.fb.group({}),this.destroyRef.onDestroy(()=>this.valueChangesSub?.unsubscribe()),k(()=>{const e=this.allFields(),t=e.map(n=>`${n.name}:${n.type}`).join("|"),a=this.config();q(()=>{if(t===this.formSignature)return;const n=Object.keys(this.form.controls).length?this.form.getRawValue():null,o=this.formSignature==="";this.formSignature=t;const r=Ce(this.fb,e);if(n)r.patchValue(n,{emitEvent:!1});else if(o&&a.formId&&a.enableLocalStorageSave){const f=this.formService.loadDraft(a.formId);f&&r.patchValue(f,{emitEvent:!1})}this.form=r,De(r,e);const s=r.get("password"),d=r.get("confirmPassword");s&&d&&s.valueChanges.pipe(T(this.destroyRef)).subscribe(()=>d.updateValueAndValidity({emitEvent:!1})),o||this.activeStep.set(0),this.formValues.set(r.getRawValue()),this.valueChangesSub?.unsubscribe(),this.valueChangesSub=r.valueChanges.pipe(Ge(r.getRawValue())).subscribe(f=>this.formValues.set(f))})}),k(()=>{const e=this.formValues(),t=this.optionsMap();if(this.form)for(const a of this.allFields()){const n=this.form.get(a.name);if(!n||!a.requiredWhen)continue;const o=this.allFields(),s=W(a,e,d=>t[d],d=>o.find(f=>f.name===d));Fe(n,a,s)}}),k(()=>{const e=this.allFields();q(()=>{if(!this.form)return;const t={};for(const a of e)a.value!==void 0&&(t[a.name]=a.value);Object.keys(t).length&&this.form.patchValue(t,{emitEvent:!1})})}),k(()=>{const e=this.activeStep(),t=this.config().wizard;q(()=>{!t?.steps?.[e]?.initialData||!this.form||this.form.patchValue(t.steps[e].initialData,{emitEvent:!1})})})}labelOf(e){return e?this.i18n?this.i18n.resolveLabel(e,this.locale()):v(e,this.locale()):""}submitLabel(){const e=this.config();return this.wizardEnabled()?this.labelOf(e.wizard?.submitButtonText??e.submitButtonLabel)||(this.locale()==="en"?"Submit":"إرسال"):this.labelOf(e.submitButtonLabel)||(this.locale()==="en"?"Submit":"إرسال")}nextLabel(){return this.labelOf(this.config().wizard?.nextButtonText)||(this.locale()==="en"?"Next":"التالي")}previousLabel(){return this.labelOf(this.config().wizard?.previousButtonText)||(this.locale()==="en"?"Previous":"السابق")}clearLabel(){return this.labelOf(this.config().clearButtonLabel)}saveLabel(){return this.labelOf(this.config().saveButtonLabel??this.config().wizard?.saveButtonText)||(this.locale()==="en"?"Save":"حفظ")}showSave(){const e=this.config();return!!(e.enableLocalStorageSave||e.wizard?.showSaveButton)}isLastStep(){return this.wizardEnabled()?this.activeStep()>=this.config().wizard.steps.length-1:!0}isRequired(e){const t=this.allFields(),a=n=>t.find(o=>o.name===n);return W(e,this.formValues(),n=>this.optionsMap()[n],a)}fieldError(e){const t=this.form?.get(e.name);if(!t||!(t.touched||t.dirty)||!t.errors)return"";const a=t.errors,n=e.validation?.errorMessages,o=this.locale(),r=s=>n?.[s]?this.labelOf(n[s]):"";return a.required?r("required")||(o==="en"?"Required":"مطلوب"):a.email?r("email")||(o==="en"?"Invalid email":"بريد غير صالح"):a.minlength?r("minLength")||(o==="en"?"Too short":"قصير جداً"):a.maxlength?r("maxLength")||(o==="en"?"Too long":"طويل جداً"):a.pattern?r("pattern")||(o==="en"?"Invalid format":"صيغة غير صالحة"):a.maxChips?r("maxChips")||(o==="en"?"Too many items":"عدد العناصر كبير"):a.invalidFormat?r("invalidFormat")||(o==="en"?"Invalid format":"صيغة غير صالحة"):a.invalidPrefix?r("invalidPrefix")||(o==="en"?"Invalid prefix":"بادئة غير صالحة"):a.invalidLength?r("invalidLength")||(o==="en"?"Invalid length":"طول غير صالح"):a.passwordMismatch?r("passwordMismatch")||(o==="en"?"Passwords do not match":"كلمات المرور غير متطابقة"):a.endDateAfterStartDate?r("endDateAfterStartDate")||(o==="en"?"End date must be after start date":"تاريخ النهاية يجب أن يكون بعد تاريخ البداية"):a.uploadInProgress?r("uploadInProgress")||(o==="en"?"Upload in progress":"جاري رفع الملفات"):a.maxFiles?r("maxFiles")||(o==="en"?"Too many files":"عدد الملفات كبير"):a.minDate?r("minDate")||(o==="en"?"Date is too early":"التاريخ مبكر جداً"):a.maxDate?r("maxDate")||(o==="en"?"Date is too late":"التاريخ متأخر جداً"):o==="en"?"Invalid":"غير صالح"}columnClass(e){const t=e.columns,a=H(t?.sm??t?.md??12),n=H(t?.md??a),o=H(t?.lg??n);return["w-full",ct[a],pt[n],ft[o]].join(" ")}customComponent(e){return this.registry.hasCustom(e.type)?this.registry.get(e.type):null}customInputs(e){return{field:e,form:this.form,locale:this.locale(),required:this.isRequired(e),error:this.fieldError(e)}}onOptionsLoaded(e){this.optionsMap.update(t=>({...t,[e.name]:e.options}))}previousStep(){this.activeStep()>0&&this.activeStep.update(e=>e-1)}canActivateStep=(e,t)=>{if(e<=t)return!0;const a=this.config().wizard;return!a?.allowSkipSteps&&e>t+1?!1:a?.validateOnStepChange===!1?!0:(this.markStepTouched(),this.stepValid())};nextStep(){this.config().wizard?.validateOnStepChange!==!1&&(this.markStepTouched(),!this.stepValid())||this.isLastStep()||(this.activeStep.update(t=>t+1),this.skipEmptyStepsForward())}skipEmptyStepsForward(){const e=this.config().wizard;if(e?.steps)for(;this.activeStep()<e.steps.length-1&&this.visibleFields().length===0;)this.activeStep.update(t=>t+1)}onClear(){this.form.reset();for(const t of this.allFields()){const a=this.form.get(t.name);a&&a.setValue(t.value!==void 0?t.value:["checkbox","multiselect","chips","file","multifile","multifilestaged"].includes(t.type)?[]:t.type==="toggle"?!1:"")}this.activeStep.set(0);const e=this.config().formId;e&&this.formService.clearDraft(e),this.clearButtonClick.emit()}onSaveDraft(){const e=this.form.getRawValue(),t=this.config(),a=t.formId;a&&this.formService.saveDraft(a,e,this.allFields());const n=t.wizard;if(n?.autoSave&&n.saveEndpoint&&this.submitAdapter){const o=this.formService.buildPayload(t,e,this.allFields());this.submitAdapter.submit({endpoint:n.saveEndpoint,method:n.saveMethod??"POST",body:o}).subscribe({error:r=>this.formError.emit(r)})}this.draftSaved.emit(e),this.toast?.show({variant:"success",message:this.locale()==="en"?"Draft saved":"تم حفظ المسودة"})}onSubmit(){if(this.wizardEnabled()&&!this.isLastStep()){this.nextStep();return}if(this.markVisibleTouched(),!this.visibleValid()){this.toast?.show({variant:"error",message:this.locale()==="en"?"Please fix the highlighted fields":"يرجى تصحيح الحقول المحددة"});return}const e=this.config(),t=this.form.getRawValue(),a=new Set(this.collectVisibleFieldNames()),n={};for(const o of this.allFields())!a.has(o.name)&&o.type!=="hidden"||(n[o.name]=t[o.name]);if(e.emitOnly||!e.endpoint){this.formSubmitted.emit(n),this.toast?.show({variant:"success",message:this.labelOf(e.successMessage)||(this.locale()==="en"?"Submitted":"تم الإرسال")});return}this.submitting.set(!0),this.formService.submitForm(e,n,this.allFields()).subscribe({next:o=>{this.submitting.set(!1),this.formSubmitted.emit(o),e.formId&&this.formService.clearDraft(e.formId),this.toast?.show({variant:"success",message:this.labelOf(e.successMessage)||(this.locale()==="en"?"Submitted successfully":"تم الإرسال بنجاح")})},error:o=>{this.submitting.set(!1),this.formError.emit(o),this.toast?.show({variant:"error",message:this.labelOf(e.errorMessage)||(this.locale()==="en"?"Submission failed":"فشل الإرسال")})}})}patchFormValues(e){this.form.patchValue(e)}getForm(){return this.form}markStepTouched(){for(const e of this.visibleFields())this.form.get(e.name)?.markAsTouched()}markVisibleTouched(){for(const e of this.collectVisibleFieldNames())this.form.get(e)?.markAsTouched()}stepValid(){return this.config().wizard?.steps[this.activeStep()]?.optional?!0:this.visibleFields().every(t=>{const a=this.form.get(t.name);return!a||a.disabled||a.valid})}visibleValid(){return this.collectVisibleFieldNames().every(e=>{const t=this.form.get(e);return!t||t.disabled||t.valid})}collectVisibleFieldNames(){const e=this.formValues(),t=this.optionsMap(),a=this.wizardEnabled()?this.allFields():this.config().fields,n=o=>a.find(r=>r.name===o);return a.filter(o=>o.type==="hidden"||K(o,e,r=>t[r],n)).map(o=>o.name)}static ɵfac=l.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"22.0.7",ngImport:l,type:N,deps:[],target:l.ɵɵFactoryTarget.Component});static ɵcmp=l.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"22.0.7",type:N,isStandalone:!0,selector:"dga-dynamic-form",inputs:{config:{classPropertyName:"config",publicName:"config",isSignal:!0,isRequired:!0,transformFunction:null},localeInput:{classPropertyName:"localeInput",publicName:"locale",isSignal:!0,isRequired:!1,transformFunction:null}},outputs:{formSubmitted:"formSubmitted",formError:"formError",clearButtonClick:"clearButtonClick",draftSaved:"draftSaved",fileDownload:"fileDownload"},host:{classAttribute:"block w-full"},ngImport:l,template:`
|
|
586
|
-
<form
|
|
653
|
+
`,changeDetection:R.OnPush,host:{class:"block w-full","[class.hidden]":'field().type === "hidden"'}}]}],propDecorators:{field:[{type:l.Input,args:[{isSignal:!0,alias:"field",required:!0}]}],form:[{type:l.Input,args:[{isSignal:!0,alias:"form",required:!0}]}],locale:[{type:l.Input,args:[{isSignal:!0,alias:"locale",required:!1}]}],required:[{type:l.Input,args:[{isSignal:!0,alias:"required",required:!1}]}],error:[{type:l.Input,args:[{isSignal:!0,alias:"error",required:!1}]}],runtimeOptions:[{type:l.Input,args:[{isSignal:!0,alias:"runtimeOptions",required:!1}]}],consentBaseUrl:[{type:l.Input,args:[{isSignal:!0,alias:"consentBaseUrl",required:!1}]}],optionsLoaded:[{type:l.Output,args:["optionsLoaded"]}],fileDownload:[{type:l.Output,args:["fileDownload"]}]}});const vt={1:"col-span-1",2:"col-span-2",3:"col-span-3",4:"col-span-4",5:"col-span-5",6:"col-span-6",7:"col-span-7",8:"col-span-8",9:"col-span-9",10:"col-span-10",11:"col-span-11",12:"col-span-12"},yt={1:"md:col-span-1",2:"md:col-span-2",3:"md:col-span-3",4:"md:col-span-4",5:"md:col-span-5",6:"md:col-span-6",7:"md:col-span-7",8:"md:col-span-8",9:"md:col-span-9",10:"md:col-span-10",11:"md:col-span-11",12:"md:col-span-12"},xt={1:"lg:col-span-1",2:"lg:col-span-2",3:"lg:col-span-3",4:"lg:col-span-4",5:"lg:col-span-5",6:"lg:col-span-6",7:"lg:col-span-7",8:"lg:col-span-8",9:"lg:col-span-9",10:"lg:col-span-10",11:"lg:col-span-11",12:"lg:col-span-12"};function Q(i){return Number.isFinite(i)?Math.min(12,Math.max(1,Math.round(i))):12}class F{config=c.required(...ngDevMode?[{debugName:"config"}]:[]);localeInput=c(null,{...ngDevMode?{debugName:"localeInput"}:{},alias:"locale"});formSubmitted=h();formError=h();clearButtonClick=h();draftSaved=h();fileDownload=h();fb=p(Ke);formService=p(I);submitAdapter=p(M,{optional:!0});toast=p($,{optional:!0});i18n=p(G,{optional:!0});destroyRef=p(ee);registry=p(k);form;formSignature="";valueChangesSub=null;activeStep=f(0,...ngDevMode?[{debugName:"activeStep"}]:[]);submitting=f(!1,...ngDevMode?[{debugName:"submitting"}]:[]);draftRestored=f(!1,...ngDevMode?[{debugName:"draftRestored"}]:[]);draftJustSaved=f(!1,...ngDevMode?[{debugName:"draftJustSaved"}]:[]);optionsMap=f({},...ngDevMode?[{debugName:"optionsMap"}]:[]);formValues=f({},...ngDevMode?[{debugName:"formValues"}]:[]);draftSavedTimer=null;locale=u(()=>this.localeInput()??Re(),...ngDevMode?[{debugName:"locale"}]:[]);wizardEnabled=u(()=>!!this.config().wizard?.enabled&&!!this.config().wizard?.steps?.length,...ngDevMode?[{debugName:"wizardEnabled"}]:[]);allFields=u(()=>Ee(this.config().fields,this.config().wizard?.steps),...ngDevMode?[{debugName:"allFields"}]:[]);currentStepFields=u(()=>this.wizardEnabled()?this.config().wizard.steps[this.activeStep()]?.fields??[]:this.config().fields,...ngDevMode?[{debugName:"currentStepFields"}]:[]);visibleFields=u(()=>{const e=this.formValues(),t=this.optionsMap(),a=this.allFields(),n=o=>a.find(r=>r.name===o);return this.currentStepFields().filter(o=>Y(o,e,r=>t[r],n))},...ngDevMode?[{debugName:"visibleFields"}]:[]);stepperSteps=u(()=>{const e=this.config().wizard?.steps??[],t=this.activeStep(),a=!!this.config().wizard?.allowSkipSteps;return e.map((n,o)=>({label:this.labelOf(n.title),disabled:!a&&o>t}))},...ngDevMode?[{debugName:"stepperSteps"}]:[]);descriptionText=u(()=>this.labelOf(this.config().description),...ngDevMode?[{debugName:"descriptionText"}]:[]);currentStep=u(()=>this.wizardEnabled()?this.config().wizard?.steps[this.activeStep()]:void 0,...ngDevMode?[{debugName:"currentStep"}]:[]);currentStepTitle=u(()=>this.labelOf(this.currentStep()?.title),...ngDevMode?[{debugName:"currentStepTitle"}]:[]);currentStepDescription=u(()=>this.labelOf(this.currentStep()?.description),...ngDevMode?[{debugName:"currentStepDescription"}]:[]);currentStepOptional=u(()=>!!this.currentStep()?.optional,...ngDevMode?[{debugName:"currentStepOptional"}]:[]);stepCount=u(()=>this.config().wizard?.steps.length??0,...ngDevMode?[{debugName:"stepCount"}]:[]);stepPercent=u(()=>{const e=this.stepCount();return e?Math.round((this.activeStep()+1)/e*100):0},...ngDevMode?[{debugName:"stepPercent"}]:[]);stepFraction(){return`${this.activeStep()+1}/${this.stepCount()}`}constructor(){this.form=this.fb.group({}),this.destroyRef.onDestroy(()=>{this.valueChangesSub?.unsubscribe(),this.draftSavedTimer&&clearTimeout(this.draftSavedTimer)}),N(()=>{const e=this.allFields(),t=e.map(n=>`${n.name}:${n.type}`).join("|"),a=this.config();q(()=>{if(t===this.formSignature)return;const n=Object.keys(this.form.controls).length?this.form.getRawValue():null,o=this.formSignature==="";this.formSignature=t;const r=Ae(this.fb,e);if(n)r.patchValue(n,{emitEvent:!1});else if(o&&a.formId&&a.enableLocalStorageSave){const g=this.formService.loadDraft(a.formId);g&&(r.patchValue(g,{emitEvent:!1}),this.draftRestored.set(!0))}this.form=r,Te(r,e);const s=r.get("password"),d=r.get("confirmPassword");s&&d&&s.valueChanges.pipe(A(this.destroyRef)).subscribe(()=>d.updateValueAndValidity({emitEvent:!1})),o||this.activeStep.set(0),this.formValues.set(r.getRawValue()),this.valueChangesSub?.unsubscribe(),this.valueChangesSub=r.valueChanges.pipe(Je(r.getRawValue())).subscribe(g=>this.formValues.set(g))})}),N(()=>{const e=this.formValues(),t=this.optionsMap();if(this.form)for(const a of this.allFields()){const n=this.form.get(a.name);if(n)if(a.requiredWhen){const o=this.allFields(),s=J(a,e,d=>t[d],d=>o.find(g=>g.name===d));K(n,a,s)}else a.type==="phone"&&K(n,a,!!(a.required||a.validation?.required))}}),N(()=>{const e=this.allFields();q(()=>{if(!this.form)return;const t={};for(const a of e)a.value!==void 0&&(t[a.name]=a.value);Object.keys(t).length&&this.form.patchValue(t,{emitEvent:!1})})}),N(()=>{const e=this.activeStep(),t=this.config().wizard;q(()=>{!t?.steps?.[e]?.initialData||!this.form||this.form.patchValue(t.steps[e].initialData,{emitEvent:!1})})})}labelOf(e){return e?this.i18n?this.i18n.resolveLabel(e,this.locale()):m(e,this.locale()):""}submitLabel(){const e=this.config();return this.wizardEnabled()?this.labelOf(e.wizard?.submitButtonText??e.submitButtonLabel)||(this.locale()==="en"?"Submit":"إرسال"):this.labelOf(e.submitButtonLabel)||(this.locale()==="en"?"Submit":"إرسال")}nextLabel(){return this.labelOf(this.config().wizard?.nextButtonText)||(this.locale()==="en"?"Next":"التالي")}previousLabel(){return this.labelOf(this.config().wizard?.previousButtonText)||(this.locale()==="en"?"Back":"رجوع")}clearLabel(){return this.labelOf(this.config().clearButtonLabel)}saveLabel(){return this.labelOf(this.config().saveButtonLabel??this.config().wizard?.saveButtonText)||(this.locale()==="en"?"Save as draft":"حفظ كمسودة")}draftSavedLabel(){return this.locale()==="en"?"Draft saved":"تم حفظ المسودة"}draftRestoredTitle(){return this.locale()==="en"?"Draft restored":"تم استعادة المسودة"}draftRestoredBody(){return this.locale()==="en"?"Your previous answers were loaded. You can continue or discard the draft.":"تم تحميل إجاباتك السابقة. يمكنك المتابعة أو حذف المسودة."}discardDraftLabel(){return this.locale()==="en"?"Discard draft":"حذف المسودة"}optionalBadgeLabel(){return this.locale()==="en"?"Optional":"اختياري"}stepProgressLabel(){const e=this.stepCount(),t=this.activeStep()+1;return this.locale()==="en"?`Step ${t} of ${e}`:`الخطوة ${t} من ${e}`}showSave(){const e=this.config();return!!(e.enableLocalStorageSave||e.wizard?.showSaveButton)}isLastStep(){return this.wizardEnabled()?this.activeStep()>=this.config().wizard.steps.length-1:!0}isRequired(e){const t=this.allFields(),a=n=>t.find(o=>o.name===n);return J(e,this.formValues(),n=>this.optionsMap()[n],a)}fieldError(e){const t=this.form?.get(e.name);if(!t||!(t.touched||t.dirty)||!t.errors)return"";const a=t.errors,n=e.validation?.errorMessages,o=this.locale(),r=s=>n?.[s]?this.labelOf(n[s]):"";return a.required?r("required")||(o==="en"?"Required":"مطلوب"):a.email?r("email")||(o==="en"?"Invalid email":"بريد غير صالح"):a.minlength?r("minLength")||(o==="en"?"Too short":"قصير جداً"):a.maxlength?r("maxLength")||(o==="en"?"Too long":"طويل جداً"):a.pattern?r("pattern")||(o==="en"?"Invalid format":"صيغة غير صالحة"):a.maxChips?r("maxChips")||(o==="en"?"Too many items":"عدد العناصر كبير"):a.invalidFormat?r("invalidFormat")||(o==="en"?"Invalid format":"صيغة غير صالحة"):a.invalidPrefix?r("invalidPrefix")||(o==="en"?"Invalid prefix":"بادئة غير صالحة"):a.invalidLength?r("invalidLength")||(o==="en"?"Invalid length":"طول غير صالح"):a.passwordMismatch?r("passwordMismatch")||(o==="en"?"Passwords do not match":"كلمات المرور غير متطابقة"):a.endDateAfterStartDate?r("endDateAfterStartDate")||(o==="en"?"End date must be after start date":"تاريخ النهاية يجب أن يكون بعد تاريخ البداية"):a.uploadInProgress?r("uploadInProgress")||(o==="en"?"Upload in progress":"جاري رفع الملفات"):a.maxFiles?r("maxFiles")||(o==="en"?"Too many files":"عدد الملفات كبير"):a.minDate?r("minDate")||(o==="en"?"Date is too early":"التاريخ مبكر جداً"):a.maxDate?r("maxDate")||(o==="en"?"Date is too late":"التاريخ متأخر جداً"):o==="en"?"Invalid":"غير صالح"}columnClass(e){const t=e.columns,a=Q(t?.sm??t?.md??12),n=Q(t?.md??a),o=Q(t?.lg??n);return["w-full",vt[a],yt[n],xt[o]].join(" ")}customComponent(e){return this.registry.hasCustom(e.type)?this.registry.get(e.type):null}customInputs(e){return{field:e,form:this.form,locale:this.locale(),required:this.isRequired(e),error:this.fieldError(e)}}onOptionsLoaded(e){this.optionsMap.update(t=>({...t,[e.name]:e.options}))}previousStep(){this.activeStep()>0&&this.activeStep.update(e=>e-1)}canActivateStep=(e,t)=>{if(e<=t)return!0;const a=this.config().wizard;return!a?.allowSkipSteps&&e>t+1?!1:a?.validateOnStepChange===!1?!0:(this.markStepTouched(),this.stepValid())};nextStep(){this.config().wizard?.validateOnStepChange!==!1&&(this.markStepTouched(),!this.stepValid())||this.isLastStep()||(this.activeStep.update(t=>t+1),this.skipEmptyStepsForward())}skipEmptyStepsForward(){const e=this.config().wizard;if(e?.steps)for(;this.activeStep()<e.steps.length-1&&this.visibleFields().length===0;)this.activeStep.update(t=>t+1)}onClear(){this.form.reset();for(const t of this.allFields()){const a=this.form.get(t.name);a&&a.setValue(t.value!==void 0?t.value:["checkbox","multiselect","chips","file","multifile","multifilestaged"].includes(t.type)?[]:t.type==="toggle"?!1:"")}this.activeStep.set(0),this.draftRestored.set(!1),this.draftJustSaved.set(!1);const e=this.config().formId;e&&this.formService.clearDraft(e),this.clearButtonClick.emit()}onSaveDraft(){const e=this.form.getRawValue(),t=this.config(),a=t.formId;a&&this.formService.saveDraft(a,e,this.allFields());const n=t.wizard;if(n?.autoSave&&n.saveEndpoint&&this.submitAdapter){const o=this.formService.buildPayload(t,e,this.allFields());this.submitAdapter.submit({endpoint:n.saveEndpoint,method:n.saveMethod??"POST",body:o}).subscribe({error:r=>this.formError.emit(r)})}this.draftSaved.emit(e),this.draftRestored.set(!1),this.draftJustSaved.set(!0),this.draftSavedTimer&&clearTimeout(this.draftSavedTimer),this.draftSavedTimer=setTimeout(()=>this.draftJustSaved.set(!1),2500),this.toast?.show({variant:"success",message:this.locale()==="en"?"Draft saved":"تم حفظ المسودة"})}dismissDraftBanner(){this.draftRestored.set(!1)}onDiscardDraft(){this.draftRestored.set(!1),this.onClear()}onSubmit(){if(this.wizardEnabled()&&!this.isLastStep()){this.nextStep();return}if(this.markVisibleTouched(),!this.visibleValid()){this.toast?.show({variant:"error",message:this.locale()==="en"?"Please fix the highlighted fields":"يرجى تصحيح الحقول المحددة"});return}const e=this.config(),t=this.form.getRawValue(),a=new Set(this.collectVisibleFieldNames()),n={};for(const o of this.allFields())!a.has(o.name)&&o.type!=="hidden"||(n[o.name]=t[o.name]);if(e.emitOnly||!e.endpoint){this.formSubmitted.emit(n),this.toast?.show({variant:"success",message:this.labelOf(e.successMessage)||(this.locale()==="en"?"Submitted":"تم الإرسال")});return}this.submitting.set(!0),this.formService.submitForm(e,n,this.allFields()).subscribe({next:o=>{this.submitting.set(!1),this.formSubmitted.emit(o),e.formId&&this.formService.clearDraft(e.formId),this.toast?.show({variant:"success",message:this.labelOf(e.successMessage)||(this.locale()==="en"?"Submitted successfully":"تم الإرسال بنجاح")})},error:o=>{this.submitting.set(!1),this.formError.emit(o),this.toast?.show({variant:"error",message:this.labelOf(e.errorMessage)||(this.locale()==="en"?"Submission failed":"فشل الإرسال")})}})}patchFormValues(e){this.form.patchValue(e)}getForm(){return this.form}markStepTouched(){for(const e of this.visibleFields())this.form.get(e.name)?.markAsTouched()}markVisibleTouched(){for(const e of this.collectVisibleFieldNames())this.form.get(e)?.markAsTouched()}stepValid(){return this.config().wizard?.steps[this.activeStep()]?.optional?!0:this.visibleFields().every(t=>{const a=this.form.get(t.name);return!a||a.disabled||a.valid})}visibleValid(){return this.collectVisibleFieldNames().every(e=>{const t=this.form.get(e);return!t||t.disabled||t.valid})}collectVisibleFieldNames(){const e=this.formValues(),t=this.optionsMap(),a=this.wizardEnabled()?this.allFields():this.config().fields,n=o=>a.find(r=>r.name===o);return a.filter(o=>o.type==="hidden"||Y(o,e,r=>t[r],n)).map(o=>o.name)}static ɵfac=l.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"22.1.5",ngImport:l,type:F,deps:[],target:l.ɵɵFactoryTarget.Component});static ɵcmp=l.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"22.1.5",type:F,isStandalone:!0,selector:"dga-dynamic-form",inputs:{config:{classPropertyName:"config",publicName:"config",isSignal:!0,isRequired:!0,transformFunction:null},localeInput:{classPropertyName:"localeInput",publicName:"locale",isSignal:!0,isRequired:!1,transformFunction:null}},outputs:{formSubmitted:"formSubmitted",formError:"formError",clearButtonClick:"clearButtonClick",draftSaved:"draftSaved",fileDownload:"fileDownload"},host:{classAttribute:"block w-full"},ngImport:l,template:`
|
|
654
|
+
<form
|
|
655
|
+
class="flex w-full flex-col"
|
|
656
|
+
[class.gap-2xl]="wizardEnabled()"
|
|
657
|
+
[class.gap-3xl]="!wizardEnabled()"
|
|
658
|
+
[formGroup]="form"
|
|
659
|
+
(ngSubmit)="onSubmit()"
|
|
660
|
+
>
|
|
587
661
|
@if (descriptionText()) {
|
|
588
662
|
<p class="text-body-md text-paragraph">{{ descriptionText() }}</p>
|
|
589
663
|
}
|
|
590
664
|
|
|
591
665
|
@if (wizardEnabled()) {
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
666
|
+
@if (draftRestored()) {
|
|
667
|
+
<dga-alert
|
|
668
|
+
variant="info"
|
|
669
|
+
display="inline"
|
|
670
|
+
color
|
|
671
|
+
[title]="draftRestoredTitle()"
|
|
672
|
+
[closeLabel]="locale() === 'en' ? 'Dismiss' : 'إغلاق'"
|
|
673
|
+
dismissible
|
|
674
|
+
(dismissed)="dismissDraftBanner()"
|
|
675
|
+
>
|
|
676
|
+
{{ draftRestoredBody() }}
|
|
677
|
+
<button
|
|
678
|
+
dgaAlertActions
|
|
679
|
+
dgaButton
|
|
680
|
+
type="button"
|
|
681
|
+
variant="ghost"
|
|
682
|
+
size="sm"
|
|
683
|
+
(click)="onDiscardDraft()"
|
|
684
|
+
>
|
|
685
|
+
{{ discardDraftLabel() }}
|
|
686
|
+
</button>
|
|
687
|
+
</dga-alert>
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
<dga-card appearance="outline" padding="lg">
|
|
691
|
+
<div class="flex flex-col gap-2xl">
|
|
692
|
+
<div
|
|
693
|
+
class="flex items-center gap-xl rounded-lg bg-sunken px-xl py-lg"
|
|
694
|
+
>
|
|
695
|
+
<dga-stepper
|
|
696
|
+
class="min-w-0 flex-1"
|
|
697
|
+
[steps]="stepperSteps()"
|
|
698
|
+
[(active)]="activeStep"
|
|
699
|
+
[beforeActiveChange]="canActivateStep"
|
|
700
|
+
[label]="stepProgressLabel()"
|
|
701
|
+
/>
|
|
702
|
+
<div
|
|
703
|
+
class="flex shrink-0 items-center justify-center rounded-full bg-card p-sm shadow-xs"
|
|
704
|
+
>
|
|
705
|
+
<dga-progress
|
|
706
|
+
appearance="radial"
|
|
707
|
+
size="md"
|
|
708
|
+
[value]="stepPercent()"
|
|
709
|
+
[valueText]="stepFraction()"
|
|
710
|
+
[label]="stepProgressLabel()"
|
|
711
|
+
/>
|
|
712
|
+
</div>
|
|
713
|
+
</div>
|
|
714
|
+
|
|
715
|
+
<div class="flex flex-col gap-xl">
|
|
716
|
+
<div class="flex flex-wrap items-start justify-between gap-md">
|
|
717
|
+
<div class="min-w-0 flex-1">
|
|
718
|
+
@if (currentStepTitle()) {
|
|
719
|
+
<h3 class="m-0 text-display-xs font-semibold text-display">
|
|
720
|
+
{{ currentStepTitle() }}
|
|
721
|
+
</h3>
|
|
722
|
+
}
|
|
723
|
+
@if (currentStepDescription()) {
|
|
724
|
+
<p class="m-0 mt-sm text-body-sm text-muted">
|
|
725
|
+
{{ currentStepDescription() }}
|
|
726
|
+
</p>
|
|
727
|
+
}
|
|
728
|
+
</div>
|
|
729
|
+
@if (currentStepOptional()) {
|
|
730
|
+
<dga-badge variant="neutral" size="sm">
|
|
731
|
+
{{ optionalBadgeLabel() }}
|
|
732
|
+
</dga-badge>
|
|
733
|
+
}
|
|
734
|
+
</div>
|
|
735
|
+
<ng-container *ngTemplateOutlet="fieldsTpl" />
|
|
736
|
+
</div>
|
|
737
|
+
</div>
|
|
738
|
+
<div
|
|
739
|
+
dgaCardActions
|
|
740
|
+
class="flex w-full flex-col gap-lg rounded-md bg-sunken px-xl py-lg sm:flex-row sm:items-center"
|
|
741
|
+
>
|
|
742
|
+
<ng-container *ngTemplateOutlet="actionsTpl" />
|
|
743
|
+
</div>
|
|
744
|
+
</dga-card>
|
|
745
|
+
} @else {
|
|
746
|
+
<ng-container *ngTemplateOutlet="fieldsTpl" />
|
|
747
|
+
<div class="flex w-full flex-col gap-lg sm:flex-row sm:items-center">
|
|
748
|
+
<ng-container *ngTemplateOutlet="actionsTpl" />
|
|
749
|
+
</div>
|
|
598
750
|
}
|
|
751
|
+
</form>
|
|
599
752
|
|
|
753
|
+
<ng-template #fieldsTpl>
|
|
600
754
|
<div class="grid grid-cols-12 gap-xl">
|
|
601
755
|
@for (field of visibleFields(); track field.name) {
|
|
602
756
|
<div [class]="columnClass(field)">
|
|
@@ -618,29 +772,22 @@ import*as l from"@angular/core";import{InjectionToken as x,inject as c,Injectabl
|
|
|
618
772
|
</div>
|
|
619
773
|
}
|
|
620
774
|
</div>
|
|
775
|
+
</ng-template>
|
|
621
776
|
|
|
777
|
+
<ng-template #actionsTpl>
|
|
622
778
|
<div class="flex flex-wrap items-center gap-md">
|
|
623
|
-
@if (wizardEnabled()
|
|
779
|
+
@if (wizardEnabled()) {
|
|
624
780
|
<button
|
|
625
781
|
dgaButton
|
|
626
782
|
type="button"
|
|
627
|
-
variant="
|
|
783
|
+
variant="outlineMuted"
|
|
784
|
+
[disabled]="activeStep() === 0"
|
|
628
785
|
(click)="previousStep()"
|
|
629
786
|
>
|
|
787
|
+
<dga-icon name="arrowPrev" size="sm" />
|
|
630
788
|
{{ previousLabel() }}
|
|
631
789
|
</button>
|
|
632
790
|
}
|
|
633
|
-
|
|
634
|
-
@if (wizardEnabled() && !isLastStep()) {
|
|
635
|
-
<button dgaButton type="button" (click)="nextStep()">
|
|
636
|
-
{{ nextLabel() }}
|
|
637
|
-
</button>
|
|
638
|
-
} @else {
|
|
639
|
-
<button dgaButton type="submit" [disabled]="submitting()">
|
|
640
|
-
{{ submitLabel() }}
|
|
641
|
-
</button>
|
|
642
|
-
}
|
|
643
|
-
|
|
644
791
|
@if (config().clearButtonLabel) {
|
|
645
792
|
<button
|
|
646
793
|
dgaButton
|
|
@@ -651,34 +798,133 @@ import*as l from"@angular/core";import{InjectionToken as x,inject as c,Injectabl
|
|
|
651
798
|
{{ clearLabel() }}
|
|
652
799
|
</button>
|
|
653
800
|
}
|
|
801
|
+
</div>
|
|
654
802
|
|
|
803
|
+
<div class="flex flex-wrap items-center gap-md sm:ms-auto">
|
|
655
804
|
@if (showSave()) {
|
|
656
805
|
<button
|
|
657
806
|
dgaButton
|
|
658
807
|
type="button"
|
|
659
|
-
variant="
|
|
808
|
+
variant="ghost"
|
|
660
809
|
(click)="onSaveDraft()"
|
|
661
810
|
>
|
|
662
|
-
|
|
811
|
+
<dga-icon [name]="draftJustSaved() ? 'check' : 'folder'" size="sm" />
|
|
812
|
+
{{ draftJustSaved() ? draftSavedLabel() : saveLabel() }}
|
|
813
|
+
</button>
|
|
814
|
+
}
|
|
815
|
+
@if (wizardEnabled() && !isLastStep()) {
|
|
816
|
+
<button dgaButton type="button" (click)="nextStep()">
|
|
817
|
+
{{ nextLabel() }}
|
|
818
|
+
<dga-icon name="arrowNext" size="sm" />
|
|
819
|
+
</button>
|
|
820
|
+
} @else {
|
|
821
|
+
<button dgaButton type="submit" [disabled]="submitting()" [loading]="submitting()">
|
|
822
|
+
{{ submitLabel() }}
|
|
663
823
|
</button>
|
|
664
824
|
}
|
|
665
825
|
</div>
|
|
666
|
-
</
|
|
667
|
-
`,isInline:!0,dependencies:[{kind:"ngmodule",type:O},{kind:"directive",type:
|
|
668
|
-
<form
|
|
826
|
+
</ng-template>
|
|
827
|
+
`,isInline:!0,dependencies:[{kind:"ngmodule",type:O},{kind:"directive",type:b.ɵNgNoValidate,selector:"form:not([ngNoForm]):not([ngNativeValidate])"},{kind:"directive",type:b.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:b.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"component",type:w,selector:"dga-dynamic-form-field",inputs:["field","form","locale","required","error","runtimeOptions","consentBaseUrl"],outputs:["optionsLoaded","fileDownload"]},{kind:"component",type:be,selector:"dga-alert",inputs:["variant","title","shadow","color","display","dismissible","closeLabel"],outputs:["dismissed"]},{kind:"component",type:ve,selector:"dga-badge",inputs:["variant","size"]},{kind:"directive",type:E,selector:"button[dgaButton], a[dgaButton]",inputs:["variant","size","iconOnly","cooldownMs","loading","dgaButtonClass"]},{kind:"component",type:ye,selector:"dga-card",inputs:["appearance","padding","border","shadow","title","description","titleTruncate","descriptionClamp","icon","iconSize","iconAppearance","badges","badgeSize","primaryLabel","primaryHref","primaryVariant","secondaryLabel","secondaryHref","secondaryVariant","actionSize","actionsAlign","interactive"],outputs:["primaryClick","secondaryClick"]},{kind:"component",type:C,selector:"dga-icon",inputs:["name","glyph","size","tone","label"]},{kind:"component",type:xe,selector:"dga-progress",inputs:["value","size","tone","appearance","showValue","valueText","label"]},{kind:"component",type:De,selector:"dga-stepper",inputs:["steps","active","label","beforeActiveChange"],outputs:["activeChange"]},{kind:"directive",type:te,selector:"[ngComponentOutlet]",inputs:["ngComponentOutlet","ngComponentOutletInputs","ngComponentOutletInjector","ngComponentOutletEnvironmentInjector","ngComponentOutletContent","ngComponentOutletNgModule"],exportAs:["ngComponentOutlet"]},{kind:"directive",type:ae,selector:"[ngTemplateOutlet]",inputs:["ngTemplateOutletContext","ngTemplateOutlet","ngTemplateOutletInjector"]}],changeDetection:l.ChangeDetectionStrategy.OnPush})}l.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"22.1.5",ngImport:l,type:F,decorators:[{type:V,args:[{selector:"dga-dynamic-form",standalone:!0,imports:[O,w,be,ve,E,ye,C,xe,De,te,ae],template:`
|
|
828
|
+
<form
|
|
829
|
+
class="flex w-full flex-col"
|
|
830
|
+
[class.gap-2xl]="wizardEnabled()"
|
|
831
|
+
[class.gap-3xl]="!wizardEnabled()"
|
|
832
|
+
[formGroup]="form"
|
|
833
|
+
(ngSubmit)="onSubmit()"
|
|
834
|
+
>
|
|
669
835
|
@if (descriptionText()) {
|
|
670
836
|
<p class="text-body-md text-paragraph">{{ descriptionText() }}</p>
|
|
671
837
|
}
|
|
672
838
|
|
|
673
839
|
@if (wizardEnabled()) {
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
840
|
+
@if (draftRestored()) {
|
|
841
|
+
<dga-alert
|
|
842
|
+
variant="info"
|
|
843
|
+
display="inline"
|
|
844
|
+
color
|
|
845
|
+
[title]="draftRestoredTitle()"
|
|
846
|
+
[closeLabel]="locale() === 'en' ? 'Dismiss' : 'إغلاق'"
|
|
847
|
+
dismissible
|
|
848
|
+
(dismissed)="dismissDraftBanner()"
|
|
849
|
+
>
|
|
850
|
+
{{ draftRestoredBody() }}
|
|
851
|
+
<button
|
|
852
|
+
dgaAlertActions
|
|
853
|
+
dgaButton
|
|
854
|
+
type="button"
|
|
855
|
+
variant="ghost"
|
|
856
|
+
size="sm"
|
|
857
|
+
(click)="onDiscardDraft()"
|
|
858
|
+
>
|
|
859
|
+
{{ discardDraftLabel() }}
|
|
860
|
+
</button>
|
|
861
|
+
</dga-alert>
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
<dga-card appearance="outline" padding="lg">
|
|
865
|
+
<div class="flex flex-col gap-2xl">
|
|
866
|
+
<div
|
|
867
|
+
class="flex items-center gap-xl rounded-lg bg-sunken px-xl py-lg"
|
|
868
|
+
>
|
|
869
|
+
<dga-stepper
|
|
870
|
+
class="min-w-0 flex-1"
|
|
871
|
+
[steps]="stepperSteps()"
|
|
872
|
+
[(active)]="activeStep"
|
|
873
|
+
[beforeActiveChange]="canActivateStep"
|
|
874
|
+
[label]="stepProgressLabel()"
|
|
875
|
+
/>
|
|
876
|
+
<div
|
|
877
|
+
class="flex shrink-0 items-center justify-center rounded-full bg-card p-sm shadow-xs"
|
|
878
|
+
>
|
|
879
|
+
<dga-progress
|
|
880
|
+
appearance="radial"
|
|
881
|
+
size="md"
|
|
882
|
+
[value]="stepPercent()"
|
|
883
|
+
[valueText]="stepFraction()"
|
|
884
|
+
[label]="stepProgressLabel()"
|
|
885
|
+
/>
|
|
886
|
+
</div>
|
|
887
|
+
</div>
|
|
888
|
+
|
|
889
|
+
<div class="flex flex-col gap-xl">
|
|
890
|
+
<div class="flex flex-wrap items-start justify-between gap-md">
|
|
891
|
+
<div class="min-w-0 flex-1">
|
|
892
|
+
@if (currentStepTitle()) {
|
|
893
|
+
<h3 class="m-0 text-display-xs font-semibold text-display">
|
|
894
|
+
{{ currentStepTitle() }}
|
|
895
|
+
</h3>
|
|
896
|
+
}
|
|
897
|
+
@if (currentStepDescription()) {
|
|
898
|
+
<p class="m-0 mt-sm text-body-sm text-muted">
|
|
899
|
+
{{ currentStepDescription() }}
|
|
900
|
+
</p>
|
|
901
|
+
}
|
|
902
|
+
</div>
|
|
903
|
+
@if (currentStepOptional()) {
|
|
904
|
+
<dga-badge variant="neutral" size="sm">
|
|
905
|
+
{{ optionalBadgeLabel() }}
|
|
906
|
+
</dga-badge>
|
|
907
|
+
}
|
|
908
|
+
</div>
|
|
909
|
+
<ng-container *ngTemplateOutlet="fieldsTpl" />
|
|
910
|
+
</div>
|
|
911
|
+
</div>
|
|
912
|
+
<div
|
|
913
|
+
dgaCardActions
|
|
914
|
+
class="flex w-full flex-col gap-lg rounded-md bg-sunken px-xl py-lg sm:flex-row sm:items-center"
|
|
915
|
+
>
|
|
916
|
+
<ng-container *ngTemplateOutlet="actionsTpl" />
|
|
917
|
+
</div>
|
|
918
|
+
</dga-card>
|
|
919
|
+
} @else {
|
|
920
|
+
<ng-container *ngTemplateOutlet="fieldsTpl" />
|
|
921
|
+
<div class="flex w-full flex-col gap-lg sm:flex-row sm:items-center">
|
|
922
|
+
<ng-container *ngTemplateOutlet="actionsTpl" />
|
|
923
|
+
</div>
|
|
680
924
|
}
|
|
925
|
+
</form>
|
|
681
926
|
|
|
927
|
+
<ng-template #fieldsTpl>
|
|
682
928
|
<div class="grid grid-cols-12 gap-xl">
|
|
683
929
|
@for (field of visibleFields(); track field.name) {
|
|
684
930
|
<div [class]="columnClass(field)">
|
|
@@ -700,29 +946,22 @@ import*as l from"@angular/core";import{InjectionToken as x,inject as c,Injectabl
|
|
|
700
946
|
</div>
|
|
701
947
|
}
|
|
702
948
|
</div>
|
|
949
|
+
</ng-template>
|
|
703
950
|
|
|
951
|
+
<ng-template #actionsTpl>
|
|
704
952
|
<div class="flex flex-wrap items-center gap-md">
|
|
705
|
-
@if (wizardEnabled()
|
|
953
|
+
@if (wizardEnabled()) {
|
|
706
954
|
<button
|
|
707
955
|
dgaButton
|
|
708
956
|
type="button"
|
|
709
|
-
variant="
|
|
957
|
+
variant="outlineMuted"
|
|
958
|
+
[disabled]="activeStep() === 0"
|
|
710
959
|
(click)="previousStep()"
|
|
711
960
|
>
|
|
961
|
+
<dga-icon name="arrowPrev" size="sm" />
|
|
712
962
|
{{ previousLabel() }}
|
|
713
963
|
</button>
|
|
714
964
|
}
|
|
715
|
-
|
|
716
|
-
@if (wizardEnabled() && !isLastStep()) {
|
|
717
|
-
<button dgaButton type="button" (click)="nextStep()">
|
|
718
|
-
{{ nextLabel() }}
|
|
719
|
-
</button>
|
|
720
|
-
} @else {
|
|
721
|
-
<button dgaButton type="submit" [disabled]="submitting()">
|
|
722
|
-
{{ submitLabel() }}
|
|
723
|
-
</button>
|
|
724
|
-
}
|
|
725
|
-
|
|
726
965
|
@if (config().clearButtonLabel) {
|
|
727
966
|
<button
|
|
728
967
|
dgaButton
|
|
@@ -733,17 +972,30 @@ import*as l from"@angular/core";import{InjectionToken as x,inject as c,Injectabl
|
|
|
733
972
|
{{ clearLabel() }}
|
|
734
973
|
</button>
|
|
735
974
|
}
|
|
975
|
+
</div>
|
|
736
976
|
|
|
977
|
+
<div class="flex flex-wrap items-center gap-md sm:ms-auto">
|
|
737
978
|
@if (showSave()) {
|
|
738
979
|
<button
|
|
739
980
|
dgaButton
|
|
740
981
|
type="button"
|
|
741
|
-
variant="
|
|
982
|
+
variant="ghost"
|
|
742
983
|
(click)="onSaveDraft()"
|
|
743
984
|
>
|
|
744
|
-
|
|
985
|
+
<dga-icon [name]="draftJustSaved() ? 'check' : 'folder'" size="sm" />
|
|
986
|
+
{{ draftJustSaved() ? draftSavedLabel() : saveLabel() }}
|
|
987
|
+
</button>
|
|
988
|
+
}
|
|
989
|
+
@if (wizardEnabled() && !isLastStep()) {
|
|
990
|
+
<button dgaButton type="button" (click)="nextStep()">
|
|
991
|
+
{{ nextLabel() }}
|
|
992
|
+
<dga-icon name="arrowNext" size="sm" />
|
|
993
|
+
</button>
|
|
994
|
+
} @else {
|
|
995
|
+
<button dgaButton type="submit" [disabled]="submitting()" [loading]="submitting()">
|
|
996
|
+
{{ submitLabel() }}
|
|
745
997
|
</button>
|
|
746
998
|
}
|
|
747
999
|
</div>
|
|
748
|
-
</
|
|
749
|
-
`,changeDetection:
|
|
1000
|
+
</ng-template>
|
|
1001
|
+
`,changeDetection:R.OnPush,host:{class:"block w-full"}}]}],ctorParameters:()=>[],propDecorators:{config:[{type:l.Input,args:[{isSignal:!0,alias:"config",required:!0}]}],localeInput:[{type:l.Input,args:[{isSignal:!0,alias:"locale",required:!1}]}],formSubmitted:[{type:l.Output,args:["formSubmitted"]}],formError:[{type:l.Output,args:["formError"]}],clearButtonClick:[{type:l.Output,args:["clearButtonClick"]}],draftSaved:[{type:l.Output,args:["draftSaved"]}],fileDownload:[{type:l.Output,args:["fileDownload"]}]}});export{_ as DGA_CAPTCHA_ADAPTER,Le as DGA_DATE_RANGE_PAIRS,Ce as DGA_DYNAMIC_FORM_FIELD_REGISTRY,G as DGA_FORM_I18N_ADAPTER,$ as DGA_FORM_TOAST_ADAPTER,U as DGA_HTTP_SECURITY,B as DGA_LOOKUP_ADAPTER,M as DGA_SUBMIT_ADAPTER,F as DgaDynamicForm,w as DgaDynamicFormField,k as DgaDynamicFormFieldRegistry,I as DgaDynamicFormService,Ue as createDgaToastAdapter,$e as createHttpLookupAdapter,_e as createHttpSubmitAdapter,Ve as defaultFormI18nAdapter,Te as dgaApplyCrossFieldValidators,T as dgaAssertSafeHttpUrl,Ae as dgaBuildFormGroup,W as dgaBuildValidators,Ee as dgaCollectFields,Oe as dgaCreateControl,Ne as dgaDefaultValueForField,Re as dgaDetectLocale,Pe as dgaFindSelectedOption,Y as dgaIsFieldVisible,J as dgaIsRequiredWhen,Ie as dgaPasswordMatchValidator,ke as dgaPhoneFieldValidator,m as dgaResolveLabel,j as dgaSaudiMobileValidator,K as dgaSetControlValidators,Be as emptyLookupAdapter,qe as noopCaptchaAdapter,ht as provideDgaDynamicForm,bt as resolveFormLabel};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@a.nemreen/dga-dynamic-form",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Schema-driven Angular dynamic forms — 18 field types, wizard, cross-field validators (password, Saudi phone, date range), staged uploads, lookup, reCAPTCHA v3, and conditional visibility. Built on @a.nemreen/dga-ui.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import * as _a_nemreen_dga_dynamic_form from '@a.nemreen/dga-dynamic-form';
|
|
1
2
|
import * as _angular_core from '@angular/core';
|
|
2
3
|
import { InjectionToken, Type, OnInit, EnvironmentProviders } from '@angular/core';
|
|
3
4
|
import { FormGroup, FormControl, FormBuilder, ValidatorFn, AbstractControl, ValidationErrors } from '@angular/forms';
|
|
4
|
-
import { DgaStep, DgaSelectOption, DgaToastService } from '@a.nemreen/dga-ui';
|
|
5
|
+
import { DgaStep, DgaPhoneCountry, DgaSelectOption, DgaToastService } from '@a.nemreen/dga-ui';
|
|
5
6
|
import { Observable } from 'rxjs';
|
|
6
7
|
import { HttpClient } from '@angular/common/http';
|
|
7
8
|
|
|
@@ -44,6 +45,15 @@ interface DgaStagedFileRef {
|
|
|
44
45
|
listKey?: string;
|
|
45
46
|
}
|
|
46
47
|
type DgaInputRestriction = 'numbers' | 'english' | 'arabic';
|
|
48
|
+
/** Extra dial code for `type: 'phone'` (KSA `+966` is always first). */
|
|
49
|
+
interface DgaFormPhoneCountry {
|
|
50
|
+
/** Dial code including `+`, e.g. `+971`. */
|
|
51
|
+
code: string;
|
|
52
|
+
/** Short prefix-select label. Defaults to `code`. */
|
|
53
|
+
label?: string;
|
|
54
|
+
/** Searchable country name. */
|
|
55
|
+
name?: DgaFormLabel;
|
|
56
|
+
}
|
|
47
57
|
type DgaHttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
48
58
|
interface DgaFormField {
|
|
49
59
|
name: string;
|
|
@@ -101,11 +111,20 @@ interface DgaFormField {
|
|
|
101
111
|
monthPicker?: boolean;
|
|
102
112
|
maxChips?: number;
|
|
103
113
|
allowDuplicates?: boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Extra dial codes for `type: 'phone'`.
|
|
116
|
+
* KSA (`+966`) is always first; duplicate codes are skipped.
|
|
117
|
+
*/
|
|
118
|
+
countries?: DgaFormPhoneCountry[];
|
|
104
119
|
disabled?: boolean;
|
|
105
120
|
readonly?: boolean;
|
|
106
121
|
value?: unknown;
|
|
107
122
|
columns?: DgaFormFieldColumns;
|
|
108
|
-
|
|
123
|
+
/**
|
|
124
|
+
* Radio / checkbox arrangement.
|
|
125
|
+
* `cards` renders each option as a selectable DGA card (title + description).
|
|
126
|
+
*/
|
|
127
|
+
optionsLayout?: 'stack' | 'grid' | 'cards';
|
|
109
128
|
excludeFromPayload?: boolean;
|
|
110
129
|
/**
|
|
111
130
|
* When true, the field value is never written to draft storage.
|
|
@@ -284,8 +303,11 @@ declare class DgaDynamicForm {
|
|
|
284
303
|
private valueChangesSub;
|
|
285
304
|
readonly activeStep: _angular_core.WritableSignal<number>;
|
|
286
305
|
readonly submitting: _angular_core.WritableSignal<boolean>;
|
|
306
|
+
readonly draftRestored: _angular_core.WritableSignal<boolean>;
|
|
307
|
+
readonly draftJustSaved: _angular_core.WritableSignal<boolean>;
|
|
287
308
|
readonly optionsMap: _angular_core.WritableSignal<Record<string, DgaFormFieldOption[]>>;
|
|
288
309
|
private readonly formValues;
|
|
310
|
+
private draftSavedTimer;
|
|
289
311
|
readonly locale: _angular_core.Signal<string>;
|
|
290
312
|
readonly wizardEnabled: _angular_core.Signal<boolean>;
|
|
291
313
|
readonly allFields: _angular_core.Signal<DgaFormField[]>;
|
|
@@ -293,6 +315,13 @@ declare class DgaDynamicForm {
|
|
|
293
315
|
readonly visibleFields: _angular_core.Signal<DgaFormField[]>;
|
|
294
316
|
readonly stepperSteps: _angular_core.Signal<DgaStep[]>;
|
|
295
317
|
readonly descriptionText: _angular_core.Signal<string>;
|
|
318
|
+
readonly currentStep: _angular_core.Signal<_a_nemreen_dga_dynamic_form.DgaFormStep | undefined>;
|
|
319
|
+
readonly currentStepTitle: _angular_core.Signal<string>;
|
|
320
|
+
readonly currentStepDescription: _angular_core.Signal<string>;
|
|
321
|
+
readonly currentStepOptional: _angular_core.Signal<boolean>;
|
|
322
|
+
readonly stepCount: _angular_core.Signal<number>;
|
|
323
|
+
readonly stepPercent: _angular_core.Signal<number>;
|
|
324
|
+
stepFraction(): string;
|
|
296
325
|
constructor();
|
|
297
326
|
labelOf(label: DgaFormLabel | undefined): string;
|
|
298
327
|
submitLabel(): string;
|
|
@@ -300,6 +329,12 @@ declare class DgaDynamicForm {
|
|
|
300
329
|
previousLabel(): string;
|
|
301
330
|
clearLabel(): string;
|
|
302
331
|
saveLabel(): string;
|
|
332
|
+
draftSavedLabel(): string;
|
|
333
|
+
draftRestoredTitle(): string;
|
|
334
|
+
draftRestoredBody(): string;
|
|
335
|
+
discardDraftLabel(): string;
|
|
336
|
+
optionalBadgeLabel(): string;
|
|
337
|
+
stepProgressLabel(): string;
|
|
303
338
|
showSave(): boolean;
|
|
304
339
|
isLastStep(): boolean;
|
|
305
340
|
isRequired(field: DgaFormField): boolean;
|
|
@@ -318,6 +353,8 @@ declare class DgaDynamicForm {
|
|
|
318
353
|
private skipEmptyStepsForward;
|
|
319
354
|
onClear(): void;
|
|
320
355
|
onSaveDraft(): void;
|
|
356
|
+
dismissDraftBanner(): void;
|
|
357
|
+
onDiscardDraft(): void;
|
|
321
358
|
onSubmit(): void;
|
|
322
359
|
/** Imperative helpers for host apps. */
|
|
323
360
|
patchFormValues(values: Record<string, unknown>): void;
|
|
@@ -353,13 +390,23 @@ declare class DgaDynamicFormField implements OnInit {
|
|
|
353
390
|
readonly labelText: _angular_core.Signal<string>;
|
|
354
391
|
readonly hintText: _angular_core.Signal<string>;
|
|
355
392
|
readonly placeholderText: _angular_core.Signal<string>;
|
|
393
|
+
/** Extra dial codes after KSA; empty/invalid entries are dropped. */
|
|
394
|
+
readonly phoneCountries: _angular_core.Signal<DgaPhoneCountry[]>;
|
|
356
395
|
readonly resolvedOptions: _angular_core.Signal<DgaFormFieldOption[]>;
|
|
396
|
+
readonly optionGroups: _angular_core.Signal<{
|
|
397
|
+
label: string;
|
|
398
|
+
options: DgaFormFieldOption[];
|
|
399
|
+
}[]>;
|
|
357
400
|
readonly selectOptions: _angular_core.Signal<DgaSelectOption[]>;
|
|
358
401
|
ngOnInit(): void;
|
|
359
402
|
private mapExistingFileValue;
|
|
360
403
|
private fetchConsent;
|
|
361
404
|
private fetchLookup;
|
|
362
405
|
optionLabel(opt: DgaFormFieldOption): string;
|
|
406
|
+
optionDescription(opt: DgaFormFieldOption): string;
|
|
407
|
+
isCardsLayout(): boolean;
|
|
408
|
+
optionsContainerClass(): string;
|
|
409
|
+
choiceLabelClass(opt: DgaFormFieldOption): string;
|
|
363
410
|
isPasswordField(): boolean;
|
|
364
411
|
isChecked(value: unknown): boolean;
|
|
365
412
|
toggleCheckbox(value: unknown, checked: boolean): void;
|
|
@@ -413,6 +460,13 @@ declare function dgaIsRequiredWhen(field: DgaFormField, values: Record<string, u
|
|
|
413
460
|
/** Known start/end date field pairs used by cross-field validators. */
|
|
414
461
|
declare const DGA_DATE_RANGE_PAIRS: ReadonlyArray<[string, string]>;
|
|
415
462
|
declare function dgaPasswordMatchValidator(passwordControl: AbstractControl): ValidatorFn;
|
|
463
|
+
/**
|
|
464
|
+
* Phone validator used by `type: phone`.
|
|
465
|
+
* KSA numbers keep Saudi mobile rules; extra `countries` codes only require digits.
|
|
466
|
+
*/
|
|
467
|
+
declare function dgaPhoneFieldValidator(extraCountries?: ReadonlyArray<{
|
|
468
|
+
code?: string;
|
|
469
|
+
} | null | undefined>): ValidatorFn;
|
|
416
470
|
/**
|
|
417
471
|
* Saudi mobile validation for type: phone fields.
|
|
418
472
|
* Accepts E.164 (+966…) or national digits (0xxxxxxxx or 5xxxxxxxx).
|
|
@@ -468,5 +522,5 @@ type LocalizedMap = Partial<Record<string, string>>;
|
|
|
468
522
|
declare function dgaResolveLabel(label: LocalizedMap | DgaFormLabel | undefined, locale: DgaFormLocale, fallback?: string): string;
|
|
469
523
|
declare function dgaDetectLocale(): DgaFormLocale;
|
|
470
524
|
|
|
471
|
-
export { DGA_CAPTCHA_ADAPTER, DGA_DATE_RANGE_PAIRS, DGA_DYNAMIC_FORM_FIELD_REGISTRY, DGA_FORM_I18N_ADAPTER, DGA_FORM_TOAST_ADAPTER, DGA_HTTP_SECURITY, DGA_LOOKUP_ADAPTER, DGA_SUBMIT_ADAPTER, DgaDynamicForm, DgaDynamicFormField, DgaDynamicFormFieldRegistry, DgaDynamicFormService, createDgaToastAdapter, createHttpLookupAdapter, createHttpSubmitAdapter, defaultFormI18nAdapter, dgaApplyCrossFieldValidators, dgaAssertSafeHttpUrl, dgaBuildFormGroup, dgaBuildValidators, dgaCollectFields, dgaCreateControl, dgaDefaultValueForField, dgaDetectLocale, dgaFindSelectedOption, dgaIsFieldVisible, dgaIsRequiredWhen, dgaPasswordMatchValidator, dgaResolveLabel, dgaSaudiMobileValidator, dgaSetControlValidators, emptyLookupAdapter, noopCaptchaAdapter, provideDgaDynamicForm, resolveFormLabel };
|
|
472
|
-
export type { DgaCaptchaAdapter, DgaDynamicFieldHostContext, DgaDynamicFieldRenderer, DgaDynamicFormConfig, DgaDynamicFormPayloadTransformer, DgaExistingAttachment, DgaFormField, DgaFormFieldColumns, DgaFormFieldOption, DgaFormFieldType, DgaFormI18nAdapter, DgaFormLabel, DgaFormLocale, DgaFormStep, DgaFormToastAdapter, DgaHttpAdapterSecurityOptions, DgaHttpMethod, DgaHttpSecurityOptions, DgaInputRestriction, DgaLookupAdapter, DgaLookupRequest, DgaStagedFileRef, DgaSubmitAdapter, DgaSubmitRequest, DgaToastVariant, DgaWizardConfig, ProvideDgaDynamicFormOptions };
|
|
525
|
+
export { DGA_CAPTCHA_ADAPTER, DGA_DATE_RANGE_PAIRS, DGA_DYNAMIC_FORM_FIELD_REGISTRY, DGA_FORM_I18N_ADAPTER, DGA_FORM_TOAST_ADAPTER, DGA_HTTP_SECURITY, DGA_LOOKUP_ADAPTER, DGA_SUBMIT_ADAPTER, DgaDynamicForm, DgaDynamicFormField, DgaDynamicFormFieldRegistry, DgaDynamicFormService, createDgaToastAdapter, createHttpLookupAdapter, createHttpSubmitAdapter, defaultFormI18nAdapter, dgaApplyCrossFieldValidators, dgaAssertSafeHttpUrl, dgaBuildFormGroup, dgaBuildValidators, dgaCollectFields, dgaCreateControl, dgaDefaultValueForField, dgaDetectLocale, dgaFindSelectedOption, dgaIsFieldVisible, dgaIsRequiredWhen, dgaPasswordMatchValidator, dgaPhoneFieldValidator, dgaResolveLabel, dgaSaudiMobileValidator, dgaSetControlValidators, emptyLookupAdapter, noopCaptchaAdapter, provideDgaDynamicForm, resolveFormLabel };
|
|
526
|
+
export type { DgaCaptchaAdapter, DgaDynamicFieldHostContext, DgaDynamicFieldRenderer, DgaDynamicFormConfig, DgaDynamicFormPayloadTransformer, DgaExistingAttachment, DgaFormField, DgaFormFieldColumns, DgaFormFieldOption, DgaFormFieldType, DgaFormI18nAdapter, DgaFormLabel, DgaFormLocale, DgaFormPhoneCountry, DgaFormStep, DgaFormToastAdapter, DgaHttpAdapterSecurityOptions, DgaHttpMethod, DgaHttpSecurityOptions, DgaInputRestriction, DgaLookupAdapter, DgaLookupRequest, DgaStagedFileRef, DgaSubmitAdapter, DgaSubmitRequest, DgaToastVariant, DgaWizardConfig, ProvideDgaDynamicFormOptions };
|