ngx-dynamic-entity 1.5.0 → 1.7.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.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, makeEnvironmentProviders, inject, Injectable, signal, Input, ChangeDetectionStrategy, Component, DestroyRef, Injector, isDevMode, ViewContainerRef, ViewChild, forwardRef,
|
|
2
|
+
import { InjectionToken, makeEnvironmentProviders, inject, Injectable, signal, Input, ChangeDetectionStrategy, Component, ChangeDetectorRef, DestroyRef, Injector, isDevMode, ViewContainerRef, ViewChild, forwardRef, Optional, Inject, EventEmitter, computed, HostListener, ViewChildren, Output, ElementRef, afterNextRender } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/forms';
|
|
4
4
|
import { ReactiveFormsModule, Validators, FormBuilder, FormArray, FormGroup } from '@angular/forms';
|
|
5
5
|
import { resolveLabel, formatDisplayValue, normalizeLookupValues, lookupValuesToOptions, valuesMatch, getOptionStoredValue, resolveOptionLabel, resolveOptionValue, buildReferenceCacheKey, normalizeReferenceOptions, entityKeyFromCacheKey, applyCascadeFilter, resolveEffectiveMask, shouldMaskField, findTab, fileRefName, evaluateFormRules, filterRulesForTab, evaluateFieldVisibility, normalizeConfigOptions, migrateRecord, getTabData, getValueByPath, setTabData, setValueByPath, normalizeArrayStructures, ambiguousFieldIds, parseFieldRef, toRefToken, collectFieldScopes, fieldRefFor, refOf, getTabPath, applyAutoPatch, applyPatchOnTrue } from '@dynamic-entity/core';
|
|
@@ -152,6 +152,25 @@ const SYSTEM_DEFAULT_CAN_EDIT = new InjectionToken('SYSTEM_DEFAULT_CAN_EDIT');
|
|
|
152
152
|
* Enables cross-entity field referencing (`isReferenced`, `referencedEntityKey`, `referencedFieldId`, `hasDrift`).
|
|
153
153
|
*/
|
|
154
154
|
const CONFIG_SOURCE = new InjectionToken('CONFIG_SOURCE');
|
|
155
|
+
/**
|
|
156
|
+
* Turns the markdown a `markdown` field stores into HTML for display.
|
|
157
|
+
*
|
|
158
|
+
* Optional, and deliberately not bundled: these packages declare no runtime dependencies
|
|
159
|
+
* beyond `tslib`, and a markdown parser is a large one to force on every consumer. Without
|
|
160
|
+
* a renderer the field still works — it stores and shows the source text, with line breaks
|
|
161
|
+
* preserved and nothing interpreted.
|
|
162
|
+
*
|
|
163
|
+
* The returned HTML is bound through `[innerHTML]`, so Angular's sanitizer strips scripts
|
|
164
|
+
* and event handlers before it reaches the DOM. That is a backstop, not a licence: a
|
|
165
|
+
* renderer should still be configured to escape raw HTML in its input, because sanitizing
|
|
166
|
+
* removes the dangerous parts silently rather than telling the author their content was
|
|
167
|
+
* altered.
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* import { marked } from 'marked';
|
|
171
|
+
* { provide: MARKDOWN_RENDERER, useValue: (src: string) => marked.parse(src) as string }
|
|
172
|
+
*/
|
|
173
|
+
const MARKDOWN_RENDERER = new InjectionToken('MARKDOWN_RENDERER');
|
|
155
174
|
|
|
156
175
|
/**
|
|
157
176
|
* Provider function for ngx-dynamic-entity.
|
|
@@ -426,6 +445,233 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
426
445
|
type: Input
|
|
427
446
|
}] } });
|
|
428
447
|
|
|
448
|
+
/**
|
|
449
|
+
* Markdown field: a long-form input that stores **markdown source**, never HTML.
|
|
450
|
+
*
|
|
451
|
+
* Storing the source rather than rendered HTML is the whole design. The record stays plain
|
|
452
|
+
* text — diffable, portable, safe to log, and impossible to turn into stored XSS by writing
|
|
453
|
+
* it into a database. Rendering happens at display time and only when a consumer asks for
|
|
454
|
+
* it, via `MARKDOWN_RENDERER`.
|
|
455
|
+
*
|
|
456
|
+
* Without a renderer this degrades to exactly what `textarea` does, plus preserved line
|
|
457
|
+
* breaks: the source is shown as text with nothing interpreted. That is the default because
|
|
458
|
+
* these packages declare no runtime dependencies beyond `tslib`, and a markdown parser is a
|
|
459
|
+
* large thing to force on a consumer who wanted a form library.
|
|
460
|
+
*
|
|
461
|
+
* With a renderer, its HTML is bound through `[innerHTML]`, which Angular sanitizes — see
|
|
462
|
+
* the token's own note on why that is a backstop rather than a licence.
|
|
463
|
+
*/
|
|
464
|
+
class MarkdownFieldComponent {
|
|
465
|
+
field;
|
|
466
|
+
control;
|
|
467
|
+
language = 'en';
|
|
468
|
+
readonly = false;
|
|
469
|
+
masked = false;
|
|
470
|
+
/** Optional — the field is fully usable without one. */
|
|
471
|
+
render = inject(MARKDOWN_RENDERER, { optional: true });
|
|
472
|
+
cdr = inject(ChangeDetectorRef);
|
|
473
|
+
destroyRef = inject(DestroyRef);
|
|
474
|
+
previewing = signal(false, ...(ngDevMode ? [{ debugName: "previewing" }] : /* istanbul ignore next */ []));
|
|
475
|
+
valueSub;
|
|
476
|
+
/**
|
|
477
|
+
* Re-render when the value changes from outside this component.
|
|
478
|
+
*
|
|
479
|
+
* `rendered()` reads `control.value`, which under OnPush is neither an input nor a
|
|
480
|
+
* template event: typing in the textarea updates through `formControl`, but a host
|
|
481
|
+
* calling `patchValue`, a rule, or an `autoPatch` mapping does not mark this component
|
|
482
|
+
* dirty. The preview and the read-only view would keep showing the previous document
|
|
483
|
+
* while the record already held a different one.
|
|
484
|
+
*/
|
|
485
|
+
ngOnChanges(changes) {
|
|
486
|
+
if (!changes['control'])
|
|
487
|
+
return;
|
|
488
|
+
this.valueSub?.unsubscribe();
|
|
489
|
+
this.valueSub = this.control?.valueChanges?.subscribe(() => this.cdr.markForCheck());
|
|
490
|
+
if (this.valueSub)
|
|
491
|
+
this.destroyRef.onDestroy(() => this.valueSub?.unsubscribe());
|
|
492
|
+
}
|
|
493
|
+
/** A Preview tab that can only ever show the source back is worse than no tab. */
|
|
494
|
+
get canPreview() {
|
|
495
|
+
return !!this.render;
|
|
496
|
+
}
|
|
497
|
+
get label() {
|
|
498
|
+
return resolveLabel(this.field?.label, this.language);
|
|
499
|
+
}
|
|
500
|
+
get placeholder() {
|
|
501
|
+
return resolveLabel(this.field?.placeholder, this.language);
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Rendered HTML, or null when there is no renderer or nothing to render.
|
|
505
|
+
*
|
|
506
|
+
* A renderer is consumer code and may throw on input it does not like. Letting that
|
|
507
|
+
* escape would take down the whole form over one malformed field, so it falls back to the
|
|
508
|
+
* source text — which is what the field would have shown with no renderer at all.
|
|
509
|
+
*/
|
|
510
|
+
rendered() {
|
|
511
|
+
const source = this.control?.value;
|
|
512
|
+
if (!this.render || typeof source !== 'string' || source === '')
|
|
513
|
+
return null;
|
|
514
|
+
try {
|
|
515
|
+
return this.render(source);
|
|
516
|
+
}
|
|
517
|
+
catch {
|
|
518
|
+
return null;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: MarkdownFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
522
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: MarkdownFieldComponent, isStandalone: true, selector: "ngx-markdown-field", inputs: { field: "field", control: "control", language: "language", readonly: "readonly", masked: "masked" }, usesOnChanges: true, ngImport: i0, template: `
|
|
523
|
+
<div
|
|
524
|
+
class="ngx-field ngx-field--markdown"
|
|
525
|
+
[attr.data-testid]="'field-' + field.id"
|
|
526
|
+
[attr.data-field-type]="field.type"
|
|
527
|
+
[class.ngx-field--readonly]="readonly"
|
|
528
|
+
[class.ngx-field--masked]="masked"
|
|
529
|
+
>
|
|
530
|
+
<label class="ngx-field__label" [attr.for]="field.id">{{ label }}</label>
|
|
531
|
+
|
|
532
|
+
@if (masked) {
|
|
533
|
+
<span class="ngx-field__value ngx-field__value--masked" [attr.data-testid]="'field-' + field.id + '-masked'">XXXXXXXXX</span>
|
|
534
|
+
} @else if (readonly) {
|
|
535
|
+
@if (rendered(); as html) {
|
|
536
|
+
<div class="ngx-field__value ngx-field__markdown" [attr.data-testid]="'field-' + field.id + '-value'" [innerHTML]="html"></div>
|
|
537
|
+
} @else {
|
|
538
|
+
<!-- No renderer: the source is the display. The stylesheet keeps its line
|
|
539
|
+
breaks with white-space: pre-wrap, and interpolation escapes it. -->
|
|
540
|
+
<span class="ngx-field__value ngx-field__markdown--source" [attr.data-testid]="'field-' + field.id + '-value'">{{ control.value }}</span>
|
|
541
|
+
}
|
|
542
|
+
} @else {
|
|
543
|
+
<div class="ngx-field__markdown-editor">
|
|
544
|
+
@if (canPreview) {
|
|
545
|
+
<div class="ngx-field__markdown-tabs" role="group" [attr.aria-label]="label + ' editor mode'">
|
|
546
|
+
<button
|
|
547
|
+
type="button"
|
|
548
|
+
class="ngx-field__markdown-tab"
|
|
549
|
+
[attr.data-testid]="'field-' + field.id + '-write'"
|
|
550
|
+
[attr.aria-pressed]="!previewing()"
|
|
551
|
+
(click)="previewing.set(false)"
|
|
552
|
+
>
|
|
553
|
+
Write
|
|
554
|
+
</button>
|
|
555
|
+
<button
|
|
556
|
+
type="button"
|
|
557
|
+
class="ngx-field__markdown-tab"
|
|
558
|
+
[attr.data-testid]="'field-' + field.id + '-preview'"
|
|
559
|
+
[attr.aria-pressed]="previewing()"
|
|
560
|
+
(click)="previewing.set(true)"
|
|
561
|
+
>
|
|
562
|
+
Preview
|
|
563
|
+
</button>
|
|
564
|
+
</div>
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
@if (previewing()) {
|
|
568
|
+
<div class="ngx-field__markdown ngx-field__markdown--preview" [attr.data-testid]="'field-' + field.id + '-preview-body'" [innerHTML]="rendered()"></div>
|
|
569
|
+
} @else {
|
|
570
|
+
<textarea
|
|
571
|
+
[id]="field.id"
|
|
572
|
+
class="ngx-field__input ngx-field__input--markdown"
|
|
573
|
+
[attr.data-testid]="'field-' + field.id + '-input'"
|
|
574
|
+
[formControl]="$any(control)"
|
|
575
|
+
[placeholder]="placeholder"
|
|
576
|
+
[attr.disabled]="field.disabled ? true : null"
|
|
577
|
+
rows="6"
|
|
578
|
+
></textarea>
|
|
579
|
+
}
|
|
580
|
+
</div>
|
|
581
|
+
|
|
582
|
+
@if (control.invalid && control.touched) {
|
|
583
|
+
<span class="ngx-field__error" [attr.data-testid]="'field-' + field.id + '-error'">This field has an error</span>
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
</div>
|
|
587
|
+
`, isInline: true, 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
588
|
+
}
|
|
589
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: MarkdownFieldComponent, decorators: [{
|
|
590
|
+
type: Component,
|
|
591
|
+
args: [{
|
|
592
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
593
|
+
selector: 'ngx-markdown-field',
|
|
594
|
+
standalone: true,
|
|
595
|
+
imports: [ReactiveFormsModule],
|
|
596
|
+
template: `
|
|
597
|
+
<div
|
|
598
|
+
class="ngx-field ngx-field--markdown"
|
|
599
|
+
[attr.data-testid]="'field-' + field.id"
|
|
600
|
+
[attr.data-field-type]="field.type"
|
|
601
|
+
[class.ngx-field--readonly]="readonly"
|
|
602
|
+
[class.ngx-field--masked]="masked"
|
|
603
|
+
>
|
|
604
|
+
<label class="ngx-field__label" [attr.for]="field.id">{{ label }}</label>
|
|
605
|
+
|
|
606
|
+
@if (masked) {
|
|
607
|
+
<span class="ngx-field__value ngx-field__value--masked" [attr.data-testid]="'field-' + field.id + '-masked'">XXXXXXXXX</span>
|
|
608
|
+
} @else if (readonly) {
|
|
609
|
+
@if (rendered(); as html) {
|
|
610
|
+
<div class="ngx-field__value ngx-field__markdown" [attr.data-testid]="'field-' + field.id + '-value'" [innerHTML]="html"></div>
|
|
611
|
+
} @else {
|
|
612
|
+
<!-- No renderer: the source is the display. The stylesheet keeps its line
|
|
613
|
+
breaks with white-space: pre-wrap, and interpolation escapes it. -->
|
|
614
|
+
<span class="ngx-field__value ngx-field__markdown--source" [attr.data-testid]="'field-' + field.id + '-value'">{{ control.value }}</span>
|
|
615
|
+
}
|
|
616
|
+
} @else {
|
|
617
|
+
<div class="ngx-field__markdown-editor">
|
|
618
|
+
@if (canPreview) {
|
|
619
|
+
<div class="ngx-field__markdown-tabs" role="group" [attr.aria-label]="label + ' editor mode'">
|
|
620
|
+
<button
|
|
621
|
+
type="button"
|
|
622
|
+
class="ngx-field__markdown-tab"
|
|
623
|
+
[attr.data-testid]="'field-' + field.id + '-write'"
|
|
624
|
+
[attr.aria-pressed]="!previewing()"
|
|
625
|
+
(click)="previewing.set(false)"
|
|
626
|
+
>
|
|
627
|
+
Write
|
|
628
|
+
</button>
|
|
629
|
+
<button
|
|
630
|
+
type="button"
|
|
631
|
+
class="ngx-field__markdown-tab"
|
|
632
|
+
[attr.data-testid]="'field-' + field.id + '-preview'"
|
|
633
|
+
[attr.aria-pressed]="previewing()"
|
|
634
|
+
(click)="previewing.set(true)"
|
|
635
|
+
>
|
|
636
|
+
Preview
|
|
637
|
+
</button>
|
|
638
|
+
</div>
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
@if (previewing()) {
|
|
642
|
+
<div class="ngx-field__markdown ngx-field__markdown--preview" [attr.data-testid]="'field-' + field.id + '-preview-body'" [innerHTML]="rendered()"></div>
|
|
643
|
+
} @else {
|
|
644
|
+
<textarea
|
|
645
|
+
[id]="field.id"
|
|
646
|
+
class="ngx-field__input ngx-field__input--markdown"
|
|
647
|
+
[attr.data-testid]="'field-' + field.id + '-input'"
|
|
648
|
+
[formControl]="$any(control)"
|
|
649
|
+
[placeholder]="placeholder"
|
|
650
|
+
[attr.disabled]="field.disabled ? true : null"
|
|
651
|
+
rows="6"
|
|
652
|
+
></textarea>
|
|
653
|
+
}
|
|
654
|
+
</div>
|
|
655
|
+
|
|
656
|
+
@if (control.invalid && control.touched) {
|
|
657
|
+
<span class="ngx-field__error" [attr.data-testid]="'field-' + field.id + '-error'">This field has an error</span>
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
</div>
|
|
661
|
+
`,
|
|
662
|
+
}]
|
|
663
|
+
}], propDecorators: { field: [{
|
|
664
|
+
type: Input
|
|
665
|
+
}], control: [{
|
|
666
|
+
type: Input
|
|
667
|
+
}], language: [{
|
|
668
|
+
type: Input
|
|
669
|
+
}], readonly: [{
|
|
670
|
+
type: Input
|
|
671
|
+
}], masked: [{
|
|
672
|
+
type: Input
|
|
673
|
+
}] } });
|
|
674
|
+
|
|
429
675
|
class NumberFieldComponent {
|
|
430
676
|
messages = inject(ValidationMessagesService);
|
|
431
677
|
field;
|
|
@@ -3694,6 +3940,7 @@ function builtInFieldTypes() {
|
|
|
3694
3940
|
return {
|
|
3695
3941
|
text: TextFieldComponent,
|
|
3696
3942
|
textarea: TextareaFieldComponent,
|
|
3943
|
+
markdown: MarkdownFieldComponent,
|
|
3697
3944
|
number: NumberFieldComponent,
|
|
3698
3945
|
currency: CurrencyFieldComponent,
|
|
3699
3946
|
email: EmailFieldComponent,
|
|
@@ -4140,12 +4387,19 @@ class DynamicFormComponent {
|
|
|
4140
4387
|
*/
|
|
4141
4388
|
isFieldReadonly(field) {
|
|
4142
4389
|
return (this.readonly ||
|
|
4390
|
+
// `permissions.edit` gated the Save button and nothing else, so a role without edit
|
|
4391
|
+
// rights received a fully editable form: it could type into every field, and only
|
|
4392
|
+
// discovered the record was not theirs to change when no Save button appeared. The
|
|
4393
|
+
// permission means the record may not be edited, so the fields say so.
|
|
4394
|
+
!this.permissions.canEdit ||
|
|
4143
4395
|
!!field.readonly ||
|
|
4144
4396
|
this.readOnlyFields.includes(field.id) ||
|
|
4145
4397
|
this.isFieldLocked(field));
|
|
4146
4398
|
}
|
|
4147
4399
|
toggleFieldLock(field) {
|
|
4148
|
-
|
|
4400
|
+
// Unlocking is an edit. Without the permission check a viewer could open the lock on a
|
|
4401
|
+
// critical field, which is the one control that exists to make editing deliberate.
|
|
4402
|
+
if (!field.criticalField || this.readonly || !this.permissions.canEdit)
|
|
4149
4403
|
return;
|
|
4150
4404
|
const next = new Set(this.unlockedFields());
|
|
4151
4405
|
if (next.has(field.id))
|
|
@@ -4854,6 +5108,7 @@ class DynamicRecordFormComponent {
|
|
|
4854
5108
|
sectionSave = new EventEmitter();
|
|
4855
5109
|
dynamicFormComp;
|
|
4856
5110
|
rulesEvaluation = inject(RulesEvaluationService);
|
|
5111
|
+
rbacService = inject(RbacService);
|
|
4857
5112
|
host = inject(ElementRef);
|
|
4858
5113
|
injector = inject(Injector);
|
|
4859
5114
|
currentData = signal({}, ...(ngDevMode ? [{ debugName: "currentData" }] : /* istanbul ignore next */ []));
|
|
@@ -4883,9 +5138,21 @@ class DynamicRecordFormComponent {
|
|
|
4883
5138
|
dismissInfoBanner(fieldId) {
|
|
4884
5139
|
this.dismissed.set(new Set(this.dismissed()).add(fieldId));
|
|
4885
5140
|
}
|
|
5141
|
+
/**
|
|
5142
|
+
* Whether the current roles may edit this record.
|
|
5143
|
+
*
|
|
5144
|
+
* `userRoles` was declared as an input here and then read by nothing at all — this
|
|
5145
|
+
* component computed no permissions of any kind, so the record view was fully editable
|
|
5146
|
+
* for every role while the plain form at least hid its Save button. Cached on the same
|
|
5147
|
+
* terms as the sibling component: it depends only on `config` and `userRoles`.
|
|
5148
|
+
*/
|
|
5149
|
+
permissionsCache = null;
|
|
5150
|
+
get permissions() {
|
|
5151
|
+
return (this.permissionsCache ??= this.rbacService.getPermissions(this.config, this.userRoles));
|
|
5152
|
+
}
|
|
4886
5153
|
/** True when nothing in the record may be edited. */
|
|
4887
5154
|
get recordReadOnly() {
|
|
4888
|
-
return this.readonly || this.isReadOnly;
|
|
5155
|
+
return this.readonly || this.isReadOnly || !this.permissions.canEdit;
|
|
4889
5156
|
}
|
|
4890
5157
|
// ─── Inline array-row editing ───────────────────────────────────────────────
|
|
4891
5158
|
/**
|
|
@@ -5097,6 +5364,11 @@ class DynamicRecordFormComponent {
|
|
|
5097
5364
|
* after the first keystroke.
|
|
5098
5365
|
*/
|
|
5099
5366
|
ngOnChanges(changes) {
|
|
5367
|
+
// Permissions depend on these two and nothing else; a stale cache would keep a record
|
|
5368
|
+
// editable after a role switch.
|
|
5369
|
+
if (changes['config'] || changes['userRoles']) {
|
|
5370
|
+
this.permissionsCache = null;
|
|
5371
|
+
}
|
|
5100
5372
|
if (changes['initialData'] || changes['config']) {
|
|
5101
5373
|
this.originalBaseline.set({ ...(this.initialData ?? {}) });
|
|
5102
5374
|
this.currentData.set({ ...(this.initialData ?? {}) });
|
|
@@ -5346,5 +5618,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
5346
5618
|
* Generated bundle index. Do not edit.
|
|
5347
5619
|
*/
|
|
5348
5620
|
|
|
5349
|
-
export { ASYNC_VALIDATOR_REGISTRY, ArrayFieldComponent, BooleanFieldComponent, COMMON_MODULES_REGISTRY, CONFIG_SOURCE, CascadeDataService, CheckboxFieldComponent, ConfigSourceService, CurrencyFieldComponent, DEFAULT_VALIDATION_MESSAGES, DateFieldComponent, DateTimeFieldComponent, DropdownFieldComponent, DynamicFieldComponent, DynamicFormComponent, DynamicRecordFormComponent, ENTITY_REF_CACHE_STORE, ENTITY_REF_REGISTRY, EmailFieldComponent, EntityRefFieldComponent, EntityRefRegistryService, EntityRefSelectionService, EntityReferenceService, FIELD_TYPE_REGISTRY, FIELD_TYPE_SETS, FieldRegistryService, FileFieldComponent, GroupFieldComponent, HOOK_REGISTRY, HookRegistryService, ImageFieldComponent, InMemoryEntityRefCacheStore, LOOKUP_REGISTRY, LookupRegistryService, MASKED_ROLES, MonthYearFieldComponent, MultiSelectFieldComponent, NumberFieldComponent, PasswordFieldComponent, RECORD_MIGRATIONS, RadioFieldComponent, RbacService, RulesEvaluationService, SYSTEM_DEFAULT_CAN_EDIT, TextFieldComponent, TextareaFieldComponent, TimeFieldComponent, UPLOAD_HANDLER, VALIDATION_MESSAGES, VALIDATOR_REGISTRY, ValidationMessagesService, ValidatorRegistryService, builtInFieldTypes, provideBuiltInFieldTypes, provideFieldTypes, provideNgxDynamicEntity, refreshChoiceOptions };
|
|
5621
|
+
export { ASYNC_VALIDATOR_REGISTRY, ArrayFieldComponent, BooleanFieldComponent, COMMON_MODULES_REGISTRY, CONFIG_SOURCE, CascadeDataService, CheckboxFieldComponent, ConfigSourceService, CurrencyFieldComponent, DEFAULT_VALIDATION_MESSAGES, DateFieldComponent, DateTimeFieldComponent, DropdownFieldComponent, DynamicFieldComponent, DynamicFormComponent, DynamicRecordFormComponent, ENTITY_REF_CACHE_STORE, ENTITY_REF_REGISTRY, EmailFieldComponent, EntityRefFieldComponent, EntityRefRegistryService, EntityRefSelectionService, EntityReferenceService, FIELD_TYPE_REGISTRY, FIELD_TYPE_SETS, FieldRegistryService, FileFieldComponent, GroupFieldComponent, HOOK_REGISTRY, HookRegistryService, ImageFieldComponent, InMemoryEntityRefCacheStore, LOOKUP_REGISTRY, LookupRegistryService, MARKDOWN_RENDERER, MASKED_ROLES, MarkdownFieldComponent, MonthYearFieldComponent, MultiSelectFieldComponent, NumberFieldComponent, PasswordFieldComponent, RECORD_MIGRATIONS, RadioFieldComponent, RbacService, RulesEvaluationService, SYSTEM_DEFAULT_CAN_EDIT, TextFieldComponent, TextareaFieldComponent, TimeFieldComponent, UPLOAD_HANDLER, VALIDATION_MESSAGES, VALIDATOR_REGISTRY, ValidationMessagesService, ValidatorRegistryService, builtInFieldTypes, provideBuiltInFieldTypes, provideFieldTypes, provideNgxDynamicEntity, refreshChoiceOptions };
|
|
5350
5622
|
//# sourceMappingURL=ngx-dynamic-entity.mjs.map
|