@ngstarter-ui/components 21.0.47 → 21.0.48

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.
@@ -4368,11 +4368,11 @@
4368
4368
  "FormBuilderSchema shape: { title?: string; fields?: FormBuilderField[]; layout?: FormBuilderLayoutItem[]; sections: FormBuilderSection[] }.",
4369
4369
  "Root-level fields live in schema.fields and can be placed outside sections. Sections live in schema.sections and contain section.fields. The optional schema.layout array controls top-level canvas order with items like { kind: \"field\" | \"section\", id }.",
4370
4370
  "FormBuilderSection shape: { id: string; title: string; description?: string; collapsed?: boolean; fields: FormBuilderField[] }.",
4371
- "FormBuilderField shape: { id: string; name: string; type: string; kind?: \"field\" | \"layout\" | \"static\"; label: string; placeholder?: string; hint?: string; defaultValue?: any; width?: 1..12; multiple?: boolean; clearable?: boolean; required?: boolean; disabled?: boolean; readonly?: boolean; options?: FormBuilderOption[]; validation?: FormBuilderValidationRule[]; visibility?: { form?: boolean; email?: boolean; pdf?: boolean; condition?: string }; settings?: Record<string, any>; children?: FormBuilderField[] }.",
4371
+ "FormBuilderField shape: { id: string; name: string; type: string; kind?: \"field\" | \"layout\" | \"static\"; label: string; placeholder?: string; hint?: string; defaultValue?: any; width?: 1..12; multiple?: boolean; clearable?: boolean; required?: boolean; disabled?: boolean; readonly?: boolean; options?: FormBuilderOption[]; validation?: FormBuilderValidationRule[]; settings?: Record<string, any>; children?: FormBuilderField[] }.",
4372
4372
  "Layout blocks are represented as fields with kind: \"layout\". The built-in group block uses type: \"group\", width: 12, and children: FormBuilderField[]. Section is a top-level FormBuilderSection, not a child field, and should not be nested inside another section/group.",
4373
4373
  "Static blocks are represented as fields with kind: \"static\". The built-in spacer block uses type: \"spacer\", width: 12, and settings.height with one of 8, 16, 24, 32, 48, or 64.",
4374
4374
  "Use width as a 12-column span. Default fields are 12 columns unless a narrower width is set. Nested children in group are sorted and rendered inside that group container.",
4375
- "Option fields use options entries { label: string; value: any; selected?: boolean }. For select, multiple controls array values; clearable enables the clear action. For radio, settings.orientation is \"vertical\" by default and can be \"horizontal\". Date and time fields include type: \"date\" for a single date, type: \"time\" for HH:mm time values, and type: \"date-range\" for a DateRange-like value with start/end dates. Upload fields use type: \"upload\", multiple for File[] values, and settings.accept for comma-separated MIME types such as \"*/*\" or \"image/*,application/pdf\". Upload handling can be provided with [uploadCallback] on ngs-form-builder/ngs-form-renderer or globally through provideFormBuilder({ uploadCallback }). The callback receives { field, control, event, files, fileList, multiple } and may return sync/async value stored in the form control.",
4375
+ "Option fields use options entries { label: string; value: any; selected?: boolean }. For select, multiple controls array values; clearable enables the clear action. For radio, settings.orientation is \"vertical\" by default and can be \"horizontal\". Hidden fields use type: \"hidden\" and render as native <input type=\"hidden\"> controls included in raw form values. Date and time fields include type: \"date\" for a single date, type: \"time\" for HH:mm time values, and type: \"date-range\" for a DateRange-like value with start/end dates. Upload fields use type: \"upload\", multiple for File[] values, and settings.accept for comma-separated MIME types such as \"*/*\" or \"image/*,application/pdf\". Upload handling can be provided with [uploadCallback] on ngs-form-builder/ngs-form-renderer or globally through provideFormBuilder({ uploadCallback }). The callback receives { field, control, event, files, fileList, multiple } and may return sync/async value stored in the form control.",
4376
4376
  "Use <ngs-form-renderer> from @ngstarter-ui/components/form-builder to render a saved FormBuilderSchema as a runtime form. The Angular class export is FormBuilderRenderer.",
4377
4377
  "Register custom placeholders through provideFormBuilder({ fields/items/settings }) using formBuilderField(), formBuilderItem(), and formBuilderSettings(). Custom field definitions can provide defaults, renderer, settings, validators, acceptsChildren, group, icon, and kind."
4378
4378
  ],
@@ -4458,7 +4458,6 @@
4458
4458
  "FormBuilderUploadCallback",
4459
4459
  "FormBuilderUploadContext",
4460
4460
  "FormBuilderValidationRule",
4461
- "FormBuilderVisibility",
4462
4461
  "provideFormBuilder",
4463
4462
  "provideFormBuilderField",
4464
4463
  "provideFormBuilderFields",
@@ -198,6 +198,20 @@ const OPTIONS_SETTINGS_SCHEMA = {
198
198
  }
199
199
  ]
200
200
  };
201
+ const HIDDEN_SETTINGS_SCHEMA = {
202
+ sections: [
203
+ {
204
+ id: 'hidden-settings',
205
+ title: 'Hidden field',
206
+ fields: [
207
+ { id: 'hidden-label', name: 'label', type: 'text', label: 'Label' },
208
+ { id: 'hidden-name', name: 'name', type: 'text', label: 'Field ID' },
209
+ { id: 'hidden-default-value', name: 'defaultValue', type: 'text', label: 'Value' },
210
+ { id: 'hidden-disabled', name: 'disabled', type: 'toggle', label: 'Disabled', defaultValue: false }
211
+ ]
212
+ }
213
+ ]
214
+ };
201
215
  const DEFAULT_FORM_BUILDER_FIELDS = [
202
216
  {
203
217
  type: 'text',
@@ -239,6 +253,21 @@ const DEFAULT_FORM_BUILDER_FIELDS = [
239
253
  },
240
254
  validators: field => field.required ? [Validators.required, Validators.email] : [Validators.email]
241
255
  },
256
+ {
257
+ type: 'hidden',
258
+ label: 'Hidden',
259
+ group: 'Basic',
260
+ icon: 'fluent:eye-off-24-regular',
261
+ description: 'Native hidden input included in submitted form values.',
262
+ defaults: {
263
+ label: 'Hidden field',
264
+ defaultValue: ''
265
+ },
266
+ settings: {
267
+ extends: 'none',
268
+ schema: HIDDEN_SETTINGS_SCHEMA
269
+ }
270
+ },
242
271
  {
243
272
  type: 'textarea',
244
273
  label: 'Textarea',
@@ -755,9 +784,9 @@ class FormBuilderFieldHost {
755
784
  return String(value);
756
785
  }
757
786
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: FormBuilderFieldHost, deps: [], target: i0.ɵɵFactoryTarget.Component });
758
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: FormBuilderFieldHost, isStandalone: true, selector: "ngs-form-builder-field-host", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: true, transformFunction: null }, definitions: { classPropertyName: "definitions", publicName: "definitions", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, editableCanvas: { classPropertyName: "editableCanvas", publicName: "editableCanvas", isSignal: true, isRequired: false, transformFunction: null }, uploadCallback: { classPropertyName: "uploadCallback", publicName: "uploadCallback", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.is-custom": "customLoaded()", "class.is-width-1": "!editableCanvas() && field().width === 1", "class.is-width-2": "!editableCanvas() && field().width === 2", "class.is-width-3": "!editableCanvas() && field().width === 3", "class.is-width-4": "!editableCanvas() && field().width === 4", "class.is-width-5": "!editableCanvas() && field().width === 5", "class.is-width-6": "!editableCanvas() && field().width === 6", "class.is-width-7": "!editableCanvas() && field().width === 7", "class.is-width-8": "!editableCanvas() && field().width === 8", "class.is-width-9": "!editableCanvas() && field().width === 9", "class.is-width-10": "!editableCanvas() && field().width === 10", "class.is-width-11": "!editableCanvas() && field().width === 11", "class.is-width-12": "!editableCanvas() && (field().width ?? 12) === 12" }, classAttribute: "ngs-form-builder-field-host" }, providers: [
787
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: FormBuilderFieldHost, isStandalone: true, selector: "ngs-form-builder-field-host", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: true, transformFunction: null }, definitions: { classPropertyName: "definitions", publicName: "definitions", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, editableCanvas: { classPropertyName: "editableCanvas", publicName: "editableCanvas", isSignal: true, isRequired: false, transformFunction: null }, uploadCallback: { classPropertyName: "uploadCallback", publicName: "uploadCallback", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.is-custom": "customLoaded()", "class.is-width-1": "!editableCanvas() && field().width === 1", "class.is-width-2": "!editableCanvas() && field().width === 2", "class.is-width-3": "!editableCanvas() && field().width === 3", "class.is-width-4": "!editableCanvas() && field().width === 4", "class.is-width-5": "!editableCanvas() && field().width === 5", "class.is-width-6": "!editableCanvas() && field().width === 6", "class.is-width-7": "!editableCanvas() && field().width === 7", "class.is-width-8": "!editableCanvas() && field().width === 8", "class.is-width-9": "!editableCanvas() && field().width === 9", "class.is-width-10": "!editableCanvas() && field().width === 10", "class.is-width-11": "!editableCanvas() && field().width === 11", "class.is-width-12": "!editableCanvas() && (field().width ?? 12) === 12", "class.is-hidden-field": "!editableCanvas() && field().type === \"hidden\"" }, classAttribute: "ngs-form-builder-field-host" }, providers: [
759
788
  provideNativeDateAdapter()
760
- ], viewQueries: [{ propertyName: "anchor", first: true, predicate: ["anchor"], descendants: true, read: ViewContainerRef, isSignal: true }], exportAs: ["ngsFormBuilderFieldHost"], ngImport: i0, template: "<ng-container #anchor/>\n\n@if (!customLoaded()) {\n @switch (field().type) {\n @case ('textarea') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <textarea ngsInput\n rows=\"3\"\n [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [readonly]=\"readonly() || field().readonly\"></textarea>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('select') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <ngs-select [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [multiple]=\"field().multiple ?? false\"\n [clearable]=\"field().clearable ?? false\">\n @for (option of field().options ?? []; track option.value) {\n <ngs-option [value]=\"option.value\">{{ option.label }}</ngs-option>\n }\n </ngs-select>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('radio') {\n <div class=\"ngs-form-builder-choice-field\">\n <span class=\"ngs-form-builder-choice-label\">{{ field().label }}</span>\n <ngs-radio-group [formControl]=\"control()\"\n [name]=\"field().name\"\n [orientation]=\"radioOrientation()\">\n @for (option of field().options ?? []; track option.value) {\n <ngs-radio-button [value]=\"option.value\">{{ option.label }}</ngs-radio-button>\n }\n </ngs-radio-group>\n @if (field().hint) {\n <span class=\"ngs-form-builder-choice-hint\">{{ field().hint }}</span>\n }\n </div>\n }\n\n @case ('checkbox') {\n <div class=\"ngs-form-builder-check-field\">\n <ngs-checkbox [formControl]=\"control()\">\n {{ field().label }}\n </ngs-checkbox>\n @if (field().hint) {\n <span>{{ field().hint }}</span>\n }\n </div>\n }\n\n @case ('toggle') {\n <div class=\"ngs-form-builder-check-field\">\n <ngs-slide-toggle [formControl]=\"control()\">\n {{ field().label }}\n </ngs-slide-toggle>\n @if (field().hint) {\n <span>{{ field().hint }}</span>\n }\n </div>\n }\n\n @case ('date') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <input ngsInput\n [ngsDatepicker]=\"picker\"\n [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [readonly]=\"readonly() || field().readonly\">\n <ngs-datepicker-toggle ngsIconButtonSuffix [for]=\"picker\"/>\n <ngs-datepicker #picker/>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('time') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <input ngsInput\n [ngsTimepicker]=\"timePicker\"\n [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [readonly]=\"readonly() || field().readonly\">\n <ngs-timepicker-toggle ngsIconButtonSuffix [for]=\"timePicker\"/>\n <ngs-timepicker #timePicker/>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('date-range') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <ngs-date-range-input #rangeInput [rangePicker]=\"rangePicker\">\n <input ngsStartDate\n [value]=\"dateRangeStartValue()\"\n [placeholder]=\"field().placeholder || 'Start date'\"\n [readonly]=\"readonly() || field().readonly\"\n [disabled]=\"dateRangeDisabled()\"\n (input)=\"onDateRangeChanged(rangeInput)\">\n <input ngsEndDate\n [value]=\"dateRangeEndValue()\"\n placeholder=\"End date\"\n [readonly]=\"readonly() || field().readonly\"\n [disabled]=\"dateRangeDisabled()\"\n (input)=\"onDateRangeChanged(rangeInput)\">\n </ngs-date-range-input>\n <ngs-datepicker-toggle ngsIconButtonSuffix [for]=\"rangePicker\"/>\n <ngs-date-range-picker #rangePicker/>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('upload') {\n <div class=\"ngs-form-builder-upload-field\"\n [class.is-disabled]=\"uploadDisabled()\">\n <span class=\"ngs-form-builder-choice-label\">{{ field().label }}</span>\n <ngs-upload-area ngsUploadTrigger\n [accept]=\"uploadAccept()\"\n [multiple]=\"field().multiple ?? false\"\n (fileSelected)=\"onUploadFilesSelected($event)\">\n <ngs-icon name=\"fluent:arrow-upload-24-regular\" ngsUploadAreaIcon/>\n <ng-container ngsUploadAreaMainState>\n {{ uploadSelectedText() }}\n </ng-container>\n <ng-container ngsUploadAreaDropState>\n Drop files here\n </ng-container>\n <ng-container ngsUploadAreaInvalidState>\n Invalid file type\n </ng-container>\n </ngs-upload-area>\n @if (field().hint) {\n <span class=\"ngs-form-builder-choice-hint\">{{ field().hint }}</span>\n }\n </div>\n }\n\n @case ('spacer') {\n <div class=\"ngs-form-builder-spacer\"\n [class.is-height-8]=\"spacerHeight() === 8\"\n [class.is-height-16]=\"spacerHeight() === 16\"\n [class.is-height-24]=\"spacerHeight() === 24\"\n [class.is-height-32]=\"spacerHeight() === 32\"\n [class.is-height-48]=\"spacerHeight() === 48\"\n [class.is-height-64]=\"spacerHeight() === 64\"\n aria-hidden=\"true\"></div>\n }\n\n @case ('timezone-select') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <ngs-timezone-select [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [required]=\"field().required ?? false\"/>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('currency') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <input ngsInput\n type=\"number\"\n inputmode=\"decimal\"\n [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [readonly]=\"readonly() || field().readonly\">\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('currency-select') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <ngs-currency-select [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [required]=\"field().required ?? false\"/>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('country-select') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <ngs-country-select [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [clearable]=\"field().clearable ?? false\"\n [required]=\"field().required ?? false\"/>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @default {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <input ngsInput\n [type]=\"textInputType()\"\n [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [readonly]=\"readonly() || field().readonly\">\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n }\n}\n", styles: [":host{display:block;min-width:0}:host.is-width-1{grid-column:span 1}:host.is-width-2{grid-column:span 2}:host.is-width-3{grid-column:span 3}:host.is-width-4{grid-column:span 4}:host.is-width-5{grid-column:span 5}:host.is-width-6{grid-column:span 6}:host.is-width-7{grid-column:span 7}:host.is-width-8{grid-column:span 8}:host.is-width-9{grid-column:span 9}:host.is-width-10{grid-column:span 10}:host.is-width-11{grid-column:span 11}:host.is-width-12{grid-column:span 12}:host .ngs-form-builder-check-field{display:flex;min-height:calc(var(--spacing, .25rem) * 11);flex-direction:column;justify-content:center;gap:calc(var(--spacing, .25rem) * 1)}:host .ngs-form-builder-check-field span{color:var(--ngs-color-on-surface-variant);font-size:var(--ngs-font-size-xs)}:host .ngs-form-builder-choice-field{display:flex;min-height:calc(var(--spacing, .25rem) * 11);flex-direction:column;gap:calc(var(--spacing, .25rem) * 2)}:host .ngs-form-builder-upload-field{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 2)}:host .ngs-form-builder-upload-field.is-disabled{pointer-events:none;opacity:.7}:host .ngs-form-builder-upload-field ngs-upload-area{--ngs-upload-area-padding: calc(var(--spacing, .25rem) * 6);--ngs-upload-area-border-radius: var(--ngs-field-radius)}:host .ngs-form-builder-choice-label{color:var(--ngs-color-on-surface);font-size:var(--ngs-font-size-sm);font-weight:500}:host .ngs-form-builder-choice-hint{color:var(--ngs-color-on-surface-variant);font-size:var(--ngs-font-size-xs)}:host .ngs-form-builder-spacer{min-height:calc(var(--spacing, .25rem) * 6)}:host .ngs-form-builder-spacer.is-height-8{min-height:calc(var(--spacing, .25rem) * 2)}:host .ngs-form-builder-spacer.is-height-16{min-height:calc(var(--spacing, .25rem) * 4)}:host .ngs-form-builder-spacer.is-height-24{min-height:calc(var(--spacing, .25rem) * 6)}:host .ngs-form-builder-spacer.is-height-32{min-height:calc(var(--spacing, .25rem) * 8)}:host .ngs-form-builder-spacer.is-height-48{min-height:calc(var(--spacing, .25rem) * 12)}:host .ngs-form-builder-spacer.is-height-64{min-height:calc(var(--spacing, .25rem) * 16)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: Datepicker, selector: "ngs-datepicker", inputs: ["startAt", "calendarHeaderComponent", "quickPresets", "showQuickPresets"], exportAs: ["ngsDatepicker"] }, { kind: "directive", type: DatepickerInput, selector: "input[ngsDatepicker]", inputs: ["ngsDatepicker"], exportAs: ["ngsDatepickerInput"] }, { kind: "component", type: DatepickerToggle, selector: "ngs-datepicker-toggle", inputs: ["for"], exportAs: ["ngsDatepickerToggle"] }, { kind: "component", type: DateRangeInput, selector: "ngs-date-range-input", inputs: ["rangePicker", "separator"], exportAs: ["ngsDateRangeInput"] }, { kind: "component", type: DateRangePicker, selector: "ngs-date-range-picker", inputs: ["startAt", "calendarHeaderComponent", "quickPresets", "showQuickPresets", "calendarCount", "extended"], exportAs: ["ngsDateRangePicker"] }, { kind: "directive", type: StartDate, selector: "input[ngsStartDate]" }, { kind: "directive", type: EndDate, selector: "input[ngsEndDate]" }, { kind: "component", type: FormField, selector: "ngs-form-field", inputs: ["subscriptHiddenIfEmpty", "sameHeightAsButton"], exportAs: ["ngsFormField"] }, { kind: "component", type: Hint, selector: "ngs-hint", inputs: ["align"], exportAs: ["ngsHint"] }, { kind: "directive", type: IconButtonSuffix, selector: "[ngsIconButtonSuffix]" }, { kind: "component", type: Label, selector: "ngs-label" }, { kind: "directive", type: Input, selector: "input[ngsInput], textarea[ngsInput]", inputs: ["id", "placeholder", "required", "disabled", "readonly", "errorStateMatcher"], exportAs: ["ngsInput"] }, { kind: "component", type: Select, selector: "ngs-select", inputs: ["id", "placeholder", "disabled", "required", "multiple", "hideCheckIcon", "clearable", "aria-label", "tabIndex", "aria-describedby", "value"], outputs: ["selectionChange", "opened", "closed", "valueChange"], exportAs: ["ngsSelect"] }, { kind: "component", type: Option, selector: "ngs-option", inputs: ["value", "data", "disabled", "selected"], outputs: ["onSelectionChange"], exportAs: ["ngsOption"] }, { kind: "component", type: Checkbox, selector: "ngs-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["checkedChange", "disabledChange", "indeterminateChange", "change"], exportAs: ["ngsCheckbox"] }, { kind: "component", type: SlideToggle, selector: "ngs-slide-toggle", inputs: ["id", "name", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "disabled", "disableRipple", "tabIndex", "hideIcon", "color", "checked"], outputs: ["disabledChange", "checkedChange", "change", "toggleChange"], exportAs: ["ngsSlideToggle"] }, { kind: "component", type: RadioButton, selector: "ngs-radio-button", inputs: ["id", "value", "name", "checked", "disabled"], outputs: ["checkedChange", "change"] }, { kind: "component", type: RadioGroup, selector: "ngs-radio-group", inputs: ["disabled", "name", "orientation", "value"], outputs: ["disabledChange", "valueChange", "change"], exportAs: ["ngsRadioGroup"] }, { kind: "component", type: CountrySelect, selector: "ngs-country-select", inputs: ["searchTerm", "value", "id", "placeholder", "required", "disabled", "multiple", "hideCheckIcon", "clearable", "aria-label", "tabIndex", "aria-describedby", "showCountryCode"], outputs: ["searchTermChange", "valueChange", "requiredChange", "disabledChange", "opened", "closed", "selectionChange"], exportAs: ["ngsCountrySelect"] }, { kind: "component", type: CurrencySelect, selector: "ngs-currency-select", inputs: ["searchTerm", "placeholder", "required", "disabled", "showCountryName"], outputs: ["searchTermChange", "requiredChange", "disabledChange", "opened", "closed"], exportAs: ["ngsCurrencySelect"] }, { kind: "component", type: TimezoneSelect, selector: "ngs-timezone-select", inputs: ["aria-describedby", "locale", "placeholder", "required", "disabled", "value", "searchTerm"], outputs: ["valueChange", "searchTermChange", "opened", "closed"], exportAs: ["ngsTimezoneSelect"] }, { kind: "component", type: Timepicker, selector: "ngs-timepicker", inputs: ["disabled", "interval"], outputs: ["opened", "closed"], exportAs: ["ngsTimepicker"] }, { kind: "directive", type: TimepickerInput, selector: "input[ngsTimepicker]", inputs: ["disabled", "max", "min", "openOnClick", "ngsTimepicker"] }, { kind: "component", type: TimepickerToggle, selector: "ngs-timepicker-toggle", inputs: ["for", "disabled"], exportAs: ["ngsTimepickerToggle"] }, { kind: "component", type: Icon, selector: "ngs-icon", inputs: ["name"], exportAs: ["ngsIcon"] }, { kind: "component", type: UploadArea, selector: "ngs-upload-area", inputs: ["accept", "allowHover", "multiple"], outputs: ["fileSelected"], exportAs: ["ngsUploadArea"] }, { kind: "directive", type: UploadAreaIconDirective, selector: "[ngsUploadAreaIcon]" }, { kind: "directive", type: UploadAreaMainStateDirective, selector: "[ngsUploadAreaMainState]" }, { kind: "directive", type: UploadAreaDropStateDirective, selector: "[ngsUploadAreaDropState]" }, { kind: "directive", type: UploadAreaInvalidStateDirective, selector: "[ngsUploadAreaInvalidState]" }, { kind: "directive", type: UploadTriggerDirective, selector: "[ngsUploadTrigger]", inputs: ["accept", "multiple"], outputs: ["fileSelected"], exportAs: ["ngsUploadTrigger"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
789
+ ], viewQueries: [{ propertyName: "anchor", first: true, predicate: ["anchor"], descendants: true, read: ViewContainerRef, isSignal: true }], exportAs: ["ngsFormBuilderFieldHost"], ngImport: i0, template: "<ng-container #anchor/>\n\n@if (!customLoaded()) {\n @switch (field().type) {\n @case ('textarea') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <textarea ngsInput\n rows=\"3\"\n [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [readonly]=\"readonly() || field().readonly\"></textarea>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('hidden') {\n <input type=\"hidden\" [formControl]=\"control()\">\n }\n\n @case ('select') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <ngs-select [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [multiple]=\"field().multiple ?? false\"\n [clearable]=\"field().clearable ?? false\">\n @for (option of field().options ?? []; track option.value) {\n <ngs-option [value]=\"option.value\">{{ option.label }}</ngs-option>\n }\n </ngs-select>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('radio') {\n <div class=\"ngs-form-builder-choice-field\">\n <span class=\"ngs-form-builder-choice-label\">{{ field().label }}</span>\n <ngs-radio-group [formControl]=\"control()\"\n [name]=\"field().name\"\n [orientation]=\"radioOrientation()\">\n @for (option of field().options ?? []; track option.value) {\n <ngs-radio-button [value]=\"option.value\">{{ option.label }}</ngs-radio-button>\n }\n </ngs-radio-group>\n @if (field().hint) {\n <span class=\"ngs-form-builder-choice-hint\">{{ field().hint }}</span>\n }\n </div>\n }\n\n @case ('checkbox') {\n <div class=\"ngs-form-builder-check-field\">\n <ngs-checkbox [formControl]=\"control()\">\n {{ field().label }}\n </ngs-checkbox>\n @if (field().hint) {\n <span>{{ field().hint }}</span>\n }\n </div>\n }\n\n @case ('toggle') {\n <div class=\"ngs-form-builder-check-field\">\n <ngs-slide-toggle [formControl]=\"control()\">\n {{ field().label }}\n </ngs-slide-toggle>\n @if (field().hint) {\n <span>{{ field().hint }}</span>\n }\n </div>\n }\n\n @case ('date') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <input ngsInput\n [ngsDatepicker]=\"picker\"\n [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [readonly]=\"readonly() || field().readonly\">\n <ngs-datepicker-toggle ngsIconButtonSuffix [for]=\"picker\"/>\n <ngs-datepicker #picker/>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('time') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <input ngsInput\n [ngsTimepicker]=\"timePicker\"\n [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [readonly]=\"readonly() || field().readonly\">\n <ngs-timepicker-toggle ngsIconButtonSuffix [for]=\"timePicker\"/>\n <ngs-timepicker #timePicker/>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('date-range') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <ngs-date-range-input #rangeInput [rangePicker]=\"rangePicker\">\n <input ngsStartDate\n [value]=\"dateRangeStartValue()\"\n [placeholder]=\"field().placeholder || 'Start date'\"\n [readonly]=\"readonly() || field().readonly\"\n [disabled]=\"dateRangeDisabled()\"\n (input)=\"onDateRangeChanged(rangeInput)\">\n <input ngsEndDate\n [value]=\"dateRangeEndValue()\"\n placeholder=\"End date\"\n [readonly]=\"readonly() || field().readonly\"\n [disabled]=\"dateRangeDisabled()\"\n (input)=\"onDateRangeChanged(rangeInput)\">\n </ngs-date-range-input>\n <ngs-datepicker-toggle ngsIconButtonSuffix [for]=\"rangePicker\"/>\n <ngs-date-range-picker #rangePicker/>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('upload') {\n <div class=\"ngs-form-builder-upload-field\"\n [class.is-disabled]=\"uploadDisabled()\">\n <span class=\"ngs-form-builder-choice-label\">{{ field().label }}</span>\n <ngs-upload-area ngsUploadTrigger\n [accept]=\"uploadAccept()\"\n [multiple]=\"field().multiple ?? false\"\n (fileSelected)=\"onUploadFilesSelected($event)\">\n <ngs-icon name=\"fluent:arrow-upload-24-regular\" ngsUploadAreaIcon/>\n <ng-container ngsUploadAreaMainState>\n {{ uploadSelectedText() }}\n </ng-container>\n <ng-container ngsUploadAreaDropState>\n Drop files here\n </ng-container>\n <ng-container ngsUploadAreaInvalidState>\n Invalid file type\n </ng-container>\n </ngs-upload-area>\n @if (field().hint) {\n <span class=\"ngs-form-builder-choice-hint\">{{ field().hint }}</span>\n }\n </div>\n }\n\n @case ('spacer') {\n <div class=\"ngs-form-builder-spacer\"\n [class.is-height-8]=\"spacerHeight() === 8\"\n [class.is-height-16]=\"spacerHeight() === 16\"\n [class.is-height-24]=\"spacerHeight() === 24\"\n [class.is-height-32]=\"spacerHeight() === 32\"\n [class.is-height-48]=\"spacerHeight() === 48\"\n [class.is-height-64]=\"spacerHeight() === 64\"\n aria-hidden=\"true\"></div>\n }\n\n @case ('timezone-select') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <ngs-timezone-select [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [required]=\"field().required ?? false\"/>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('currency') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <input ngsInput\n type=\"number\"\n inputmode=\"decimal\"\n [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [readonly]=\"readonly() || field().readonly\">\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('currency-select') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <ngs-currency-select [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [required]=\"field().required ?? false\"/>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('country-select') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <ngs-country-select [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [clearable]=\"field().clearable ?? false\"\n [required]=\"field().required ?? false\"/>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @default {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <input ngsInput\n [type]=\"textInputType()\"\n [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [readonly]=\"readonly() || field().readonly\">\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n }\n}\n", styles: [":host{display:block;min-width:0}:host.is-hidden-field{display:none}:host.is-width-1{grid-column:span 1}:host.is-width-2{grid-column:span 2}:host.is-width-3{grid-column:span 3}:host.is-width-4{grid-column:span 4}:host.is-width-5{grid-column:span 5}:host.is-width-6{grid-column:span 6}:host.is-width-7{grid-column:span 7}:host.is-width-8{grid-column:span 8}:host.is-width-9{grid-column:span 9}:host.is-width-10{grid-column:span 10}:host.is-width-11{grid-column:span 11}:host.is-width-12{grid-column:span 12}:host .ngs-form-builder-check-field{display:flex;min-height:calc(var(--spacing, .25rem) * 11);flex-direction:column;justify-content:center;gap:calc(var(--spacing, .25rem) * 1)}:host .ngs-form-builder-check-field span{color:var(--ngs-color-on-surface-variant);font-size:var(--ngs-font-size-xs)}:host .ngs-form-builder-choice-field{display:flex;min-height:calc(var(--spacing, .25rem) * 11);flex-direction:column;gap:calc(var(--spacing, .25rem) * 2)}:host .ngs-form-builder-upload-field{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 2)}:host .ngs-form-builder-upload-field.is-disabled{pointer-events:none;opacity:.7}:host .ngs-form-builder-upload-field ngs-upload-area{--ngs-upload-area-padding: calc(var(--spacing, .25rem) * 6);--ngs-upload-area-border-radius: var(--ngs-field-radius)}:host .ngs-form-builder-choice-label{color:var(--ngs-color-on-surface);font-size:var(--ngs-font-size-sm);font-weight:500}:host .ngs-form-builder-choice-hint{color:var(--ngs-color-on-surface-variant);font-size:var(--ngs-font-size-xs)}:host .ngs-form-builder-spacer{min-height:calc(var(--spacing, .25rem) * 6)}:host .ngs-form-builder-spacer.is-height-8{min-height:calc(var(--spacing, .25rem) * 2)}:host .ngs-form-builder-spacer.is-height-16{min-height:calc(var(--spacing, .25rem) * 4)}:host .ngs-form-builder-spacer.is-height-24{min-height:calc(var(--spacing, .25rem) * 6)}:host .ngs-form-builder-spacer.is-height-32{min-height:calc(var(--spacing, .25rem) * 8)}:host .ngs-form-builder-spacer.is-height-48{min-height:calc(var(--spacing, .25rem) * 12)}:host .ngs-form-builder-spacer.is-height-64{min-height:calc(var(--spacing, .25rem) * 16)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: Datepicker, selector: "ngs-datepicker", inputs: ["startAt", "calendarHeaderComponent", "quickPresets", "showQuickPresets"], exportAs: ["ngsDatepicker"] }, { kind: "directive", type: DatepickerInput, selector: "input[ngsDatepicker]", inputs: ["ngsDatepicker"], exportAs: ["ngsDatepickerInput"] }, { kind: "component", type: DatepickerToggle, selector: "ngs-datepicker-toggle", inputs: ["for"], exportAs: ["ngsDatepickerToggle"] }, { kind: "component", type: DateRangeInput, selector: "ngs-date-range-input", inputs: ["rangePicker", "separator"], exportAs: ["ngsDateRangeInput"] }, { kind: "component", type: DateRangePicker, selector: "ngs-date-range-picker", inputs: ["startAt", "calendarHeaderComponent", "quickPresets", "showQuickPresets", "calendarCount", "extended"], exportAs: ["ngsDateRangePicker"] }, { kind: "directive", type: StartDate, selector: "input[ngsStartDate]" }, { kind: "directive", type: EndDate, selector: "input[ngsEndDate]" }, { kind: "component", type: FormField, selector: "ngs-form-field", inputs: ["subscriptHiddenIfEmpty", "sameHeightAsButton"], exportAs: ["ngsFormField"] }, { kind: "component", type: Hint, selector: "ngs-hint", inputs: ["align"], exportAs: ["ngsHint"] }, { kind: "directive", type: IconButtonSuffix, selector: "[ngsIconButtonSuffix]" }, { kind: "component", type: Label, selector: "ngs-label" }, { kind: "directive", type: Input, selector: "input[ngsInput], textarea[ngsInput]", inputs: ["id", "placeholder", "required", "disabled", "readonly", "errorStateMatcher"], exportAs: ["ngsInput"] }, { kind: "component", type: Select, selector: "ngs-select", inputs: ["id", "placeholder", "disabled", "required", "multiple", "hideCheckIcon", "clearable", "aria-label", "tabIndex", "aria-describedby", "value"], outputs: ["selectionChange", "opened", "closed", "valueChange"], exportAs: ["ngsSelect"] }, { kind: "component", type: Option, selector: "ngs-option", inputs: ["value", "data", "disabled", "selected"], outputs: ["onSelectionChange"], exportAs: ["ngsOption"] }, { kind: "component", type: Checkbox, selector: "ngs-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["checkedChange", "disabledChange", "indeterminateChange", "change"], exportAs: ["ngsCheckbox"] }, { kind: "component", type: SlideToggle, selector: "ngs-slide-toggle", inputs: ["id", "name", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "disabled", "disableRipple", "tabIndex", "hideIcon", "color", "checked"], outputs: ["disabledChange", "checkedChange", "change", "toggleChange"], exportAs: ["ngsSlideToggle"] }, { kind: "component", type: RadioButton, selector: "ngs-radio-button", inputs: ["id", "value", "name", "checked", "disabled"], outputs: ["checkedChange", "change"] }, { kind: "component", type: RadioGroup, selector: "ngs-radio-group", inputs: ["disabled", "name", "orientation", "value"], outputs: ["disabledChange", "valueChange", "change"], exportAs: ["ngsRadioGroup"] }, { kind: "component", type: CountrySelect, selector: "ngs-country-select", inputs: ["searchTerm", "value", "id", "placeholder", "required", "disabled", "multiple", "hideCheckIcon", "clearable", "aria-label", "tabIndex", "aria-describedby", "showCountryCode"], outputs: ["searchTermChange", "valueChange", "requiredChange", "disabledChange", "opened", "closed", "selectionChange"], exportAs: ["ngsCountrySelect"] }, { kind: "component", type: CurrencySelect, selector: "ngs-currency-select", inputs: ["searchTerm", "placeholder", "required", "disabled", "showCountryName"], outputs: ["searchTermChange", "requiredChange", "disabledChange", "opened", "closed"], exportAs: ["ngsCurrencySelect"] }, { kind: "component", type: TimezoneSelect, selector: "ngs-timezone-select", inputs: ["aria-describedby", "locale", "placeholder", "required", "disabled", "value", "searchTerm"], outputs: ["valueChange", "searchTermChange", "opened", "closed"], exportAs: ["ngsTimezoneSelect"] }, { kind: "component", type: Timepicker, selector: "ngs-timepicker", inputs: ["disabled", "interval"], outputs: ["opened", "closed"], exportAs: ["ngsTimepicker"] }, { kind: "directive", type: TimepickerInput, selector: "input[ngsTimepicker]", inputs: ["disabled", "max", "min", "openOnClick", "ngsTimepicker"] }, { kind: "component", type: TimepickerToggle, selector: "ngs-timepicker-toggle", inputs: ["for", "disabled"], exportAs: ["ngsTimepickerToggle"] }, { kind: "component", type: Icon, selector: "ngs-icon", inputs: ["name"], exportAs: ["ngsIcon"] }, { kind: "component", type: UploadArea, selector: "ngs-upload-area", inputs: ["accept", "allowHover", "multiple"], outputs: ["fileSelected"], exportAs: ["ngsUploadArea"] }, { kind: "directive", type: UploadAreaIconDirective, selector: "[ngsUploadAreaIcon]" }, { kind: "directive", type: UploadAreaMainStateDirective, selector: "[ngsUploadAreaMainState]" }, { kind: "directive", type: UploadAreaDropStateDirective, selector: "[ngsUploadAreaDropState]" }, { kind: "directive", type: UploadAreaInvalidStateDirective, selector: "[ngsUploadAreaInvalidState]" }, { kind: "directive", type: UploadTriggerDirective, selector: "[ngsUploadTrigger]", inputs: ["accept", "multiple"], outputs: ["fileSelected"], exportAs: ["ngsUploadTrigger"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
761
790
  }
762
791
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: FormBuilderFieldHost, decorators: [{
763
792
  type: Component,
@@ -810,8 +839,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
810
839
  '[class.is-width-9]': '!editableCanvas() && field().width === 9',
811
840
  '[class.is-width-10]': '!editableCanvas() && field().width === 10',
812
841
  '[class.is-width-11]': '!editableCanvas() && field().width === 11',
813
- '[class.is-width-12]': '!editableCanvas() && (field().width ?? 12) === 12'
814
- }, template: "<ng-container #anchor/>\n\n@if (!customLoaded()) {\n @switch (field().type) {\n @case ('textarea') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <textarea ngsInput\n rows=\"3\"\n [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [readonly]=\"readonly() || field().readonly\"></textarea>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('select') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <ngs-select [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [multiple]=\"field().multiple ?? false\"\n [clearable]=\"field().clearable ?? false\">\n @for (option of field().options ?? []; track option.value) {\n <ngs-option [value]=\"option.value\">{{ option.label }}</ngs-option>\n }\n </ngs-select>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('radio') {\n <div class=\"ngs-form-builder-choice-field\">\n <span class=\"ngs-form-builder-choice-label\">{{ field().label }}</span>\n <ngs-radio-group [formControl]=\"control()\"\n [name]=\"field().name\"\n [orientation]=\"radioOrientation()\">\n @for (option of field().options ?? []; track option.value) {\n <ngs-radio-button [value]=\"option.value\">{{ option.label }}</ngs-radio-button>\n }\n </ngs-radio-group>\n @if (field().hint) {\n <span class=\"ngs-form-builder-choice-hint\">{{ field().hint }}</span>\n }\n </div>\n }\n\n @case ('checkbox') {\n <div class=\"ngs-form-builder-check-field\">\n <ngs-checkbox [formControl]=\"control()\">\n {{ field().label }}\n </ngs-checkbox>\n @if (field().hint) {\n <span>{{ field().hint }}</span>\n }\n </div>\n }\n\n @case ('toggle') {\n <div class=\"ngs-form-builder-check-field\">\n <ngs-slide-toggle [formControl]=\"control()\">\n {{ field().label }}\n </ngs-slide-toggle>\n @if (field().hint) {\n <span>{{ field().hint }}</span>\n }\n </div>\n }\n\n @case ('date') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <input ngsInput\n [ngsDatepicker]=\"picker\"\n [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [readonly]=\"readonly() || field().readonly\">\n <ngs-datepicker-toggle ngsIconButtonSuffix [for]=\"picker\"/>\n <ngs-datepicker #picker/>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('time') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <input ngsInput\n [ngsTimepicker]=\"timePicker\"\n [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [readonly]=\"readonly() || field().readonly\">\n <ngs-timepicker-toggle ngsIconButtonSuffix [for]=\"timePicker\"/>\n <ngs-timepicker #timePicker/>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('date-range') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <ngs-date-range-input #rangeInput [rangePicker]=\"rangePicker\">\n <input ngsStartDate\n [value]=\"dateRangeStartValue()\"\n [placeholder]=\"field().placeholder || 'Start date'\"\n [readonly]=\"readonly() || field().readonly\"\n [disabled]=\"dateRangeDisabled()\"\n (input)=\"onDateRangeChanged(rangeInput)\">\n <input ngsEndDate\n [value]=\"dateRangeEndValue()\"\n placeholder=\"End date\"\n [readonly]=\"readonly() || field().readonly\"\n [disabled]=\"dateRangeDisabled()\"\n (input)=\"onDateRangeChanged(rangeInput)\">\n </ngs-date-range-input>\n <ngs-datepicker-toggle ngsIconButtonSuffix [for]=\"rangePicker\"/>\n <ngs-date-range-picker #rangePicker/>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('upload') {\n <div class=\"ngs-form-builder-upload-field\"\n [class.is-disabled]=\"uploadDisabled()\">\n <span class=\"ngs-form-builder-choice-label\">{{ field().label }}</span>\n <ngs-upload-area ngsUploadTrigger\n [accept]=\"uploadAccept()\"\n [multiple]=\"field().multiple ?? false\"\n (fileSelected)=\"onUploadFilesSelected($event)\">\n <ngs-icon name=\"fluent:arrow-upload-24-regular\" ngsUploadAreaIcon/>\n <ng-container ngsUploadAreaMainState>\n {{ uploadSelectedText() }}\n </ng-container>\n <ng-container ngsUploadAreaDropState>\n Drop files here\n </ng-container>\n <ng-container ngsUploadAreaInvalidState>\n Invalid file type\n </ng-container>\n </ngs-upload-area>\n @if (field().hint) {\n <span class=\"ngs-form-builder-choice-hint\">{{ field().hint }}</span>\n }\n </div>\n }\n\n @case ('spacer') {\n <div class=\"ngs-form-builder-spacer\"\n [class.is-height-8]=\"spacerHeight() === 8\"\n [class.is-height-16]=\"spacerHeight() === 16\"\n [class.is-height-24]=\"spacerHeight() === 24\"\n [class.is-height-32]=\"spacerHeight() === 32\"\n [class.is-height-48]=\"spacerHeight() === 48\"\n [class.is-height-64]=\"spacerHeight() === 64\"\n aria-hidden=\"true\"></div>\n }\n\n @case ('timezone-select') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <ngs-timezone-select [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [required]=\"field().required ?? false\"/>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('currency') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <input ngsInput\n type=\"number\"\n inputmode=\"decimal\"\n [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [readonly]=\"readonly() || field().readonly\">\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('currency-select') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <ngs-currency-select [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [required]=\"field().required ?? false\"/>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('country-select') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <ngs-country-select [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [clearable]=\"field().clearable ?? false\"\n [required]=\"field().required ?? false\"/>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @default {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <input ngsInput\n [type]=\"textInputType()\"\n [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [readonly]=\"readonly() || field().readonly\">\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n }\n}\n", styles: [":host{display:block;min-width:0}:host.is-width-1{grid-column:span 1}:host.is-width-2{grid-column:span 2}:host.is-width-3{grid-column:span 3}:host.is-width-4{grid-column:span 4}:host.is-width-5{grid-column:span 5}:host.is-width-6{grid-column:span 6}:host.is-width-7{grid-column:span 7}:host.is-width-8{grid-column:span 8}:host.is-width-9{grid-column:span 9}:host.is-width-10{grid-column:span 10}:host.is-width-11{grid-column:span 11}:host.is-width-12{grid-column:span 12}:host .ngs-form-builder-check-field{display:flex;min-height:calc(var(--spacing, .25rem) * 11);flex-direction:column;justify-content:center;gap:calc(var(--spacing, .25rem) * 1)}:host .ngs-form-builder-check-field span{color:var(--ngs-color-on-surface-variant);font-size:var(--ngs-font-size-xs)}:host .ngs-form-builder-choice-field{display:flex;min-height:calc(var(--spacing, .25rem) * 11);flex-direction:column;gap:calc(var(--spacing, .25rem) * 2)}:host .ngs-form-builder-upload-field{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 2)}:host .ngs-form-builder-upload-field.is-disabled{pointer-events:none;opacity:.7}:host .ngs-form-builder-upload-field ngs-upload-area{--ngs-upload-area-padding: calc(var(--spacing, .25rem) * 6);--ngs-upload-area-border-radius: var(--ngs-field-radius)}:host .ngs-form-builder-choice-label{color:var(--ngs-color-on-surface);font-size:var(--ngs-font-size-sm);font-weight:500}:host .ngs-form-builder-choice-hint{color:var(--ngs-color-on-surface-variant);font-size:var(--ngs-font-size-xs)}:host .ngs-form-builder-spacer{min-height:calc(var(--spacing, .25rem) * 6)}:host .ngs-form-builder-spacer.is-height-8{min-height:calc(var(--spacing, .25rem) * 2)}:host .ngs-form-builder-spacer.is-height-16{min-height:calc(var(--spacing, .25rem) * 4)}:host .ngs-form-builder-spacer.is-height-24{min-height:calc(var(--spacing, .25rem) * 6)}:host .ngs-form-builder-spacer.is-height-32{min-height:calc(var(--spacing, .25rem) * 8)}:host .ngs-form-builder-spacer.is-height-48{min-height:calc(var(--spacing, .25rem) * 12)}:host .ngs-form-builder-spacer.is-height-64{min-height:calc(var(--spacing, .25rem) * 16)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
842
+ '[class.is-width-12]': '!editableCanvas() && (field().width ?? 12) === 12',
843
+ '[class.is-hidden-field]': '!editableCanvas() && field().type === "hidden"'
844
+ }, template: "<ng-container #anchor/>\n\n@if (!customLoaded()) {\n @switch (field().type) {\n @case ('textarea') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <textarea ngsInput\n rows=\"3\"\n [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [readonly]=\"readonly() || field().readonly\"></textarea>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('hidden') {\n <input type=\"hidden\" [formControl]=\"control()\">\n }\n\n @case ('select') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <ngs-select [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [multiple]=\"field().multiple ?? false\"\n [clearable]=\"field().clearable ?? false\">\n @for (option of field().options ?? []; track option.value) {\n <ngs-option [value]=\"option.value\">{{ option.label }}</ngs-option>\n }\n </ngs-select>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('radio') {\n <div class=\"ngs-form-builder-choice-field\">\n <span class=\"ngs-form-builder-choice-label\">{{ field().label }}</span>\n <ngs-radio-group [formControl]=\"control()\"\n [name]=\"field().name\"\n [orientation]=\"radioOrientation()\">\n @for (option of field().options ?? []; track option.value) {\n <ngs-radio-button [value]=\"option.value\">{{ option.label }}</ngs-radio-button>\n }\n </ngs-radio-group>\n @if (field().hint) {\n <span class=\"ngs-form-builder-choice-hint\">{{ field().hint }}</span>\n }\n </div>\n }\n\n @case ('checkbox') {\n <div class=\"ngs-form-builder-check-field\">\n <ngs-checkbox [formControl]=\"control()\">\n {{ field().label }}\n </ngs-checkbox>\n @if (field().hint) {\n <span>{{ field().hint }}</span>\n }\n </div>\n }\n\n @case ('toggle') {\n <div class=\"ngs-form-builder-check-field\">\n <ngs-slide-toggle [formControl]=\"control()\">\n {{ field().label }}\n </ngs-slide-toggle>\n @if (field().hint) {\n <span>{{ field().hint }}</span>\n }\n </div>\n }\n\n @case ('date') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <input ngsInput\n [ngsDatepicker]=\"picker\"\n [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [readonly]=\"readonly() || field().readonly\">\n <ngs-datepicker-toggle ngsIconButtonSuffix [for]=\"picker\"/>\n <ngs-datepicker #picker/>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('time') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <input ngsInput\n [ngsTimepicker]=\"timePicker\"\n [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [readonly]=\"readonly() || field().readonly\">\n <ngs-timepicker-toggle ngsIconButtonSuffix [for]=\"timePicker\"/>\n <ngs-timepicker #timePicker/>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('date-range') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <ngs-date-range-input #rangeInput [rangePicker]=\"rangePicker\">\n <input ngsStartDate\n [value]=\"dateRangeStartValue()\"\n [placeholder]=\"field().placeholder || 'Start date'\"\n [readonly]=\"readonly() || field().readonly\"\n [disabled]=\"dateRangeDisabled()\"\n (input)=\"onDateRangeChanged(rangeInput)\">\n <input ngsEndDate\n [value]=\"dateRangeEndValue()\"\n placeholder=\"End date\"\n [readonly]=\"readonly() || field().readonly\"\n [disabled]=\"dateRangeDisabled()\"\n (input)=\"onDateRangeChanged(rangeInput)\">\n </ngs-date-range-input>\n <ngs-datepicker-toggle ngsIconButtonSuffix [for]=\"rangePicker\"/>\n <ngs-date-range-picker #rangePicker/>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('upload') {\n <div class=\"ngs-form-builder-upload-field\"\n [class.is-disabled]=\"uploadDisabled()\">\n <span class=\"ngs-form-builder-choice-label\">{{ field().label }}</span>\n <ngs-upload-area ngsUploadTrigger\n [accept]=\"uploadAccept()\"\n [multiple]=\"field().multiple ?? false\"\n (fileSelected)=\"onUploadFilesSelected($event)\">\n <ngs-icon name=\"fluent:arrow-upload-24-regular\" ngsUploadAreaIcon/>\n <ng-container ngsUploadAreaMainState>\n {{ uploadSelectedText() }}\n </ng-container>\n <ng-container ngsUploadAreaDropState>\n Drop files here\n </ng-container>\n <ng-container ngsUploadAreaInvalidState>\n Invalid file type\n </ng-container>\n </ngs-upload-area>\n @if (field().hint) {\n <span class=\"ngs-form-builder-choice-hint\">{{ field().hint }}</span>\n }\n </div>\n }\n\n @case ('spacer') {\n <div class=\"ngs-form-builder-spacer\"\n [class.is-height-8]=\"spacerHeight() === 8\"\n [class.is-height-16]=\"spacerHeight() === 16\"\n [class.is-height-24]=\"spacerHeight() === 24\"\n [class.is-height-32]=\"spacerHeight() === 32\"\n [class.is-height-48]=\"spacerHeight() === 48\"\n [class.is-height-64]=\"spacerHeight() === 64\"\n aria-hidden=\"true\"></div>\n }\n\n @case ('timezone-select') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <ngs-timezone-select [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [required]=\"field().required ?? false\"/>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('currency') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <input ngsInput\n type=\"number\"\n inputmode=\"decimal\"\n [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [readonly]=\"readonly() || field().readonly\">\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('currency-select') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <ngs-currency-select [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [required]=\"field().required ?? false\"/>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @case ('country-select') {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <ngs-country-select [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [clearable]=\"field().clearable ?? false\"\n [required]=\"field().required ?? false\"/>\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n\n @default {\n <ngs-form-field>\n <ngs-label>{{ field().label }}</ngs-label>\n <input ngsInput\n [type]=\"textInputType()\"\n [formControl]=\"control()\"\n [placeholder]=\"field().placeholder || ''\"\n [readonly]=\"readonly() || field().readonly\">\n @if (field().hint) {\n <ngs-hint>{{ field().hint }}</ngs-hint>\n }\n </ngs-form-field>\n }\n }\n}\n", styles: [":host{display:block;min-width:0}:host.is-hidden-field{display:none}:host.is-width-1{grid-column:span 1}:host.is-width-2{grid-column:span 2}:host.is-width-3{grid-column:span 3}:host.is-width-4{grid-column:span 4}:host.is-width-5{grid-column:span 5}:host.is-width-6{grid-column:span 6}:host.is-width-7{grid-column:span 7}:host.is-width-8{grid-column:span 8}:host.is-width-9{grid-column:span 9}:host.is-width-10{grid-column:span 10}:host.is-width-11{grid-column:span 11}:host.is-width-12{grid-column:span 12}:host .ngs-form-builder-check-field{display:flex;min-height:calc(var(--spacing, .25rem) * 11);flex-direction:column;justify-content:center;gap:calc(var(--spacing, .25rem) * 1)}:host .ngs-form-builder-check-field span{color:var(--ngs-color-on-surface-variant);font-size:var(--ngs-font-size-xs)}:host .ngs-form-builder-choice-field{display:flex;min-height:calc(var(--spacing, .25rem) * 11);flex-direction:column;gap:calc(var(--spacing, .25rem) * 2)}:host .ngs-form-builder-upload-field{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 2)}:host .ngs-form-builder-upload-field.is-disabled{pointer-events:none;opacity:.7}:host .ngs-form-builder-upload-field ngs-upload-area{--ngs-upload-area-padding: calc(var(--spacing, .25rem) * 6);--ngs-upload-area-border-radius: var(--ngs-field-radius)}:host .ngs-form-builder-choice-label{color:var(--ngs-color-on-surface);font-size:var(--ngs-font-size-sm);font-weight:500}:host .ngs-form-builder-choice-hint{color:var(--ngs-color-on-surface-variant);font-size:var(--ngs-font-size-xs)}:host .ngs-form-builder-spacer{min-height:calc(var(--spacing, .25rem) * 6)}:host .ngs-form-builder-spacer.is-height-8{min-height:calc(var(--spacing, .25rem) * 2)}:host .ngs-form-builder-spacer.is-height-16{min-height:calc(var(--spacing, .25rem) * 4)}:host .ngs-form-builder-spacer.is-height-24{min-height:calc(var(--spacing, .25rem) * 6)}:host .ngs-form-builder-spacer.is-height-32{min-height:calc(var(--spacing, .25rem) * 8)}:host .ngs-form-builder-spacer.is-height-48{min-height:calc(var(--spacing, .25rem) * 12)}:host .ngs-form-builder-spacer.is-height-64{min-height:calc(var(--spacing, .25rem) * 16)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
815
845
  }], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], control: [{ type: i0.Input, args: [{ isSignal: true, alias: "control", required: true }] }], definitions: [{ type: i0.Input, args: [{ isSignal: true, alias: "definitions", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], editableCanvas: [{ type: i0.Input, args: [{ isSignal: true, alias: "editableCanvas", required: false }] }], uploadCallback: [{ type: i0.Input, args: [{ isSignal: true, alias: "uploadCallback", required: false }] }], anchor: [{ type: i0.ViewChild, args: ['anchor', { ...{ read: ViewContainerRef }, isSignal: true }] }] } });
816
846
 
817
847
  class FormBuilderRenderer {
@@ -848,23 +878,7 @@ class FormBuilderRenderer {
848
878
  }
849
879
  return definitions;
850
880
  }, []), ...(ngDevMode ? [{ debugName: "definitions" }] : /* istanbul ignore next */ []));
851
- visibleCanvasItems = computed(() => this.resolveCanvasItems(this.schema())
852
- .map(item => {
853
- if (item.field) {
854
- return {
855
- ...item,
856
- field: this.visibleFields([item.field])[0]
857
- };
858
- }
859
- return {
860
- ...item,
861
- section: {
862
- ...item.section,
863
- fields: this.visibleFields(item.section.fields)
864
- }
865
- };
866
- })
867
- .filter(item => !!item.field || !!item.section?.fields.length), ...(ngDevMode ? [{ debugName: "visibleCanvasItems" }] : /* istanbul ignore next */ []));
881
+ visibleCanvasItems = computed(() => this.resolveCanvasItems(this.schema()).filter(item => !!item.field || !!item.section?.fields.length), ...(ngDevMode ? [{ debugName: "visibleCanvasItems" }] : /* istanbul ignore next */ []));
868
882
  formGroup = computed(() => this.createFormGroup(), ...(ngDevMode ? [{ debugName: "formGroup" }] : /* istanbul ignore next */ []));
869
883
  constructor() {
870
884
  effect(onCleanup => {
@@ -901,7 +915,7 @@ class FormBuilderRenderer {
901
915
  field.type === 'grid';
902
916
  }
903
917
  visibleChildren(field) {
904
- return this.visibleFields(field.children ?? []);
918
+ return field.children ?? [];
905
919
  }
906
920
  isRepeaterField(field) {
907
921
  return field.type === 'repeater';
@@ -1007,14 +1021,6 @@ class FormBuilderRenderer {
1007
1021
  }
1008
1022
  return new FormGroup(controls);
1009
1023
  }
1010
- visibleFields(fields) {
1011
- return fields
1012
- .filter(field => field.visibility?.form !== false)
1013
- .map(field => ({
1014
- ...field,
1015
- children: field.children ? this.visibleFields(field.children) : undefined
1016
- }));
1017
- }
1018
1024
  fieldInitialValue(field) {
1019
1025
  if (field.defaultValue !== undefined) {
1020
1026
  return field.defaultValue;
@@ -2128,11 +2134,6 @@ class FormBuilder {
2128
2134
  kind,
2129
2135
  label: baseLabel,
2130
2136
  width: definition.defaults?.width ?? this.defaultWidth(definition.type),
2131
- visibility: {
2132
- form: true,
2133
- email: true,
2134
- pdf: true
2135
- },
2136
2137
  ...definition.defaults
2137
2138
  };
2138
2139
  if (field.defaultValue === undefined) {
@@ -2687,7 +2688,6 @@ function cloneField(field) {
2687
2688
  ...field,
2688
2689
  options: field.options?.map(option => ({ ...option })),
2689
2690
  validation: field.validation?.map(rule => ({ ...rule })),
2690
- visibility: field.visibility ? { ...field.visibility } : undefined,
2691
2691
  settings: field.settings ? { ...field.settings } : undefined,
2692
2692
  children: field.children?.map(cloneField)
2693
2693
  };