ngx-form-designer 0.0.28 → 0.0.30
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/fesm2022/ngx-form-designer.mjs +361 -1046
- package/fesm2022/ngx-form-designer.mjs.map +1 -1
- package/lib/data/data-provider.d.ts +1 -0
- package/lib/form-core/form-engine-runtime-flags.d.ts +3 -0
- package/lib/form-designer/layout-canvas.component.d.ts +7 -0
- package/lib/form-designer/widget-inspector.component.d.ts +1 -1
- package/lib/ui/safe.pipe.d.ts +8 -0
- package/lib/widgets/field-widgets/select/select-widget.component.d.ts +7 -0
- package/package.json +1 -1
- package/lib/form-renderer/form-viewer/form-viewer-readonly.component.d.ts +0 -57
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, InjectionToken, NgModule, inject, signal, computed, EventEmitter, DestroyRef, Injector, afterNextRender, ViewContainerRef, Input, ViewChild, Output, Inject, ChangeDetectionStrategy, Component, effect, ElementRef, NgZone, input, output, HostListener, ContentChildren, untracked, ChangeDetectorRef } from '@angular/core';
|
|
2
|
+
import { Injectable, InjectionToken, NgModule, inject, signal, computed, EventEmitter, DestroyRef, Injector, afterNextRender, ViewContainerRef, Input, ViewChild, Output, Inject, ChangeDetectionStrategy, Component, effect, ElementRef, NgZone, input, output, HostListener, ContentChildren, untracked, ChangeDetectorRef, Pipe } from '@angular/core';
|
|
3
3
|
import { BehaviorSubject, Subject, merge, of, filter, map, debounceTime as debounceTime$1, skip, firstValueFrom } from 'rxjs';
|
|
4
4
|
import { v4 } from 'uuid';
|
|
5
5
|
import * as i1 from '@angular/common';
|
|
@@ -13,11 +13,12 @@ import { LucideAngularModule } from 'lucide-angular';
|
|
|
13
13
|
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
|
|
14
14
|
import * as i5 from 'angular-resizable-element';
|
|
15
15
|
import { ResizableModule } from 'angular-resizable-element';
|
|
16
|
-
import { Router, NavigationEnd } from '@angular/router';
|
|
17
16
|
import loader from '@monaco-editor/loader';
|
|
17
|
+
import { Router, NavigationEnd } from '@angular/router';
|
|
18
18
|
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
|
|
19
19
|
import { NgSelectComponent } from '@ng-select/ng-select';
|
|
20
20
|
import Quill from 'quill';
|
|
21
|
+
import { DomSanitizer } from '@angular/platform-browser';
|
|
21
22
|
import { HttpClient, provideHttpClient } from '@angular/common/http';
|
|
22
23
|
|
|
23
24
|
const CURRENT_SCHEMA_VERSION = '1.0.0';
|
|
@@ -794,6 +795,16 @@ function hasWrapperSurfaceStyles(style) {
|
|
|
794
795
|
|
|
795
796
|
const WIDGET_EDITOR_CONTEXT = new InjectionToken('WIDGET_EDITOR_CONTEXT');
|
|
796
797
|
|
|
798
|
+
const SUPPRESS_API_CALLS_FLAG = '__fdSuppressApiCalls';
|
|
799
|
+
function setEngineApiCallsSuppressed(engine, suppressed) {
|
|
800
|
+
engine[SUPPRESS_API_CALLS_FLAG] = suppressed;
|
|
801
|
+
}
|
|
802
|
+
function areEngineApiCallsSuppressed(engine) {
|
|
803
|
+
if (!engine)
|
|
804
|
+
return false;
|
|
805
|
+
return engine[SUPPRESS_API_CALLS_FLAG] === true;
|
|
806
|
+
}
|
|
807
|
+
|
|
797
808
|
const SCOPED_NODE_SEPARATOR = '::scope::';
|
|
798
809
|
function composeScopedNodeId(scopePath, nodeId) {
|
|
799
810
|
if (scopePath.length === 0)
|
|
@@ -2559,7 +2570,7 @@ class LayoutNodeComponent {
|
|
|
2559
2570
|
shouldUpdate = true;
|
|
2560
2571
|
}
|
|
2561
2572
|
if (readOnlyModeChange && !readOnlyModeChange.firstChange) {
|
|
2562
|
-
// Swap engine proxy for preview
|
|
2573
|
+
// Swap engine proxy for preview runtime flags
|
|
2563
2574
|
shouldUpdate = true;
|
|
2564
2575
|
}
|
|
2565
2576
|
if (shouldUpdate) {
|
|
@@ -2847,8 +2858,8 @@ class LayoutNodeComponent {
|
|
|
2847
2858
|
if (mode === 'design') {
|
|
2848
2859
|
proxy.isFieldVisible = () => true;
|
|
2849
2860
|
}
|
|
2850
|
-
|
|
2851
|
-
proxy
|
|
2861
|
+
if (mode === 'preview') {
|
|
2862
|
+
setEngineApiCallsSuppressed(proxy, true);
|
|
2852
2863
|
}
|
|
2853
2864
|
this.renderEngineProxy = proxy;
|
|
2854
2865
|
this.renderEngineSource = this.engine;
|
|
@@ -4219,7 +4230,9 @@ class JsonFormRendererComponent {
|
|
|
4219
4230
|
if (!this.engine || this.mode === 'design') {
|
|
4220
4231
|
return;
|
|
4221
4232
|
}
|
|
4222
|
-
const apiExecutor = this.
|
|
4233
|
+
const apiExecutor = this.mode === 'preview'
|
|
4234
|
+
? undefined
|
|
4235
|
+
: this.resolveEventApiExecutor();
|
|
4223
4236
|
this.runner = new FormEventRunner(this.engine, {
|
|
4224
4237
|
logger: this.eventLogger,
|
|
4225
4238
|
apiExecutor,
|
|
@@ -4712,7 +4725,7 @@ class JsonFormRendererComponent {
|
|
|
4712
4725
|
</ng-container>
|
|
4713
4726
|
<ng-template #loading>Loading form...</ng-template>
|
|
4714
4727
|
</div>
|
|
4715
|
-
`, isInline: true, styles: [".form-renderer-container{width:100%;height:100vh
|
|
4728
|
+
`, isInline: true, styles: [".form-renderer-container{width:100%;height:100vh}.form-renderer-container.is-design{padding-top:2.25rem;height:auto;overflow:visible}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: LayoutNodeComponent, selector: "app-layout-node", inputs: ["node", "engine", "fields", "designMode", "readOnlyMode", "scopePath", "device", "breakpoint", "connectedDropLists"], outputs: ["nodeDrop", "nodeSelect"] }] });
|
|
4716
4729
|
}
|
|
4717
4730
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: JsonFormRendererComponent, decorators: [{
|
|
4718
4731
|
type: Component,
|
|
@@ -4737,7 +4750,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
4737
4750
|
</ng-container>
|
|
4738
4751
|
<ng-template #loading>Loading form...</ng-template>
|
|
4739
4752
|
</div>
|
|
4740
|
-
`, styles: [".form-renderer-container{width:100%;height:100vh
|
|
4753
|
+
`, styles: [".form-renderer-container{width:100%;height:100vh}.form-renderer-container.is-design{padding-top:2.25rem;height:auto;overflow:visible}\n"] }]
|
|
4741
4754
|
}], ctorParameters: () => [{ type: DesignerStateService }], propDecorators: { schema: [{
|
|
4742
4755
|
type: Input
|
|
4743
4756
|
}], initialValues: [{
|
|
@@ -4953,876 +4966,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
4953
4966
|
type: Input
|
|
4954
4967
|
}] } });
|
|
4955
4968
|
|
|
4956
|
-
class FormViewerReadonlyComponent {
|
|
4957
|
-
schema;
|
|
4958
|
-
values = {};
|
|
4959
|
-
breakpoint = 'xl';
|
|
4960
|
-
asRow(node) {
|
|
4961
|
-
return node;
|
|
4962
|
-
}
|
|
4963
|
-
asCol(node) {
|
|
4964
|
-
return node;
|
|
4965
|
-
}
|
|
4966
|
-
asWidget(node) {
|
|
4967
|
-
return node;
|
|
4968
|
-
}
|
|
4969
|
-
getField(fieldId) {
|
|
4970
|
-
return this.schema?.fields.find(field => field.id === fieldId);
|
|
4971
|
-
}
|
|
4972
|
-
getFieldLabel(field) {
|
|
4973
|
-
return field.label?.trim() || field.name;
|
|
4974
|
-
}
|
|
4975
|
-
getFieldValue(field) {
|
|
4976
|
-
return this.values[field.name] ?? field.defaultValue ?? null;
|
|
4977
|
-
}
|
|
4978
|
-
getHeadingText(field) {
|
|
4979
|
-
return field.label?.trim() || field.name;
|
|
4980
|
-
}
|
|
4981
|
-
getRichTextContent(field) {
|
|
4982
|
-
const text = field['text'];
|
|
4983
|
-
return typeof text === 'string' ? text : '';
|
|
4984
|
-
}
|
|
4985
|
-
getHeadingLevel(field) {
|
|
4986
|
-
const level = field['level'];
|
|
4987
|
-
return typeof level === 'string' && /^h[1-6]$/.test(level) ? level : 'h2';
|
|
4988
|
-
}
|
|
4989
|
-
getParagraphText(field) {
|
|
4990
|
-
const text = field['text'];
|
|
4991
|
-
if (typeof text === 'string' && text.trim()) {
|
|
4992
|
-
return text;
|
|
4993
|
-
}
|
|
4994
|
-
return field.label?.trim() || '';
|
|
4995
|
-
}
|
|
4996
|
-
getNodeStyle(node) {
|
|
4997
|
-
const style = normalizeStyle(node.style);
|
|
4998
|
-
if (!style['width'])
|
|
4999
|
-
style['width'] = '100%';
|
|
5000
|
-
if (!style['height'])
|
|
5001
|
-
style['height'] = 'auto';
|
|
5002
|
-
return style;
|
|
5003
|
-
}
|
|
5004
|
-
getFieldStyle(field) {
|
|
5005
|
-
return normalizeStyle(field.style);
|
|
5006
|
-
}
|
|
5007
|
-
getColClasses(node) {
|
|
5008
|
-
if (node.type !== 'col')
|
|
5009
|
-
return '';
|
|
5010
|
-
const span = this.getEffectiveSpan(node.responsive || { xs: 12 });
|
|
5011
|
-
return this.getSpanClass(span);
|
|
5012
|
-
}
|
|
5013
|
-
formatFieldValue(field, value) {
|
|
5014
|
-
if (field.type === 'select' || field.type === 'radio' || field.type === 'search' || field.type === 'tree-select') {
|
|
5015
|
-
return this.formatScalarValue(this.resolveOptionLabel(field, value));
|
|
5016
|
-
}
|
|
5017
|
-
if (field.type === 'date') {
|
|
5018
|
-
return this.formatDateValue(value);
|
|
5019
|
-
}
|
|
5020
|
-
if (field.type === 'time') {
|
|
5021
|
-
return this.formatTimeValue(value);
|
|
5022
|
-
}
|
|
5023
|
-
if (field.type === 'datetime-local') {
|
|
5024
|
-
return this.formatDateTimeValue(value);
|
|
5025
|
-
}
|
|
5026
|
-
return this.formatScalarValue(value, field);
|
|
5027
|
-
}
|
|
5028
|
-
formatScalarValue(value, field) {
|
|
5029
|
-
if (Array.isArray(value)) {
|
|
5030
|
-
const scalarItems = value
|
|
5031
|
-
.map(item => this.formatScalarValue(item))
|
|
5032
|
-
.filter(item => item !== 'No value provided');
|
|
5033
|
-
return scalarItems.length ? scalarItems.join(', ') : this.getEmptyValueLabel(field);
|
|
5034
|
-
}
|
|
5035
|
-
if (value == null || value === '') {
|
|
5036
|
-
return this.getEmptyValueLabel(field);
|
|
5037
|
-
}
|
|
5038
|
-
if (typeof value === 'boolean') {
|
|
5039
|
-
return value ? 'Yes' : 'No';
|
|
5040
|
-
}
|
|
5041
|
-
if (typeof value === 'object') {
|
|
5042
|
-
return JSON.stringify(value, null, 2);
|
|
5043
|
-
}
|
|
5044
|
-
return String(value);
|
|
5045
|
-
}
|
|
5046
|
-
getDisplayList(field, value) {
|
|
5047
|
-
if (!Array.isArray(value))
|
|
5048
|
-
return [];
|
|
5049
|
-
return value
|
|
5050
|
-
.map(item => this.resolveOptionLabel(field, item))
|
|
5051
|
-
.map(item => this.formatScalarValue(item))
|
|
5052
|
-
.filter(item => item !== 'No value provided');
|
|
5053
|
-
}
|
|
5054
|
-
getUploadedFiles(value) {
|
|
5055
|
-
if (!value)
|
|
5056
|
-
return [];
|
|
5057
|
-
if (Array.isArray(value)) {
|
|
5058
|
-
return value.filter(item => this.isUploadedFileRef(item));
|
|
5059
|
-
}
|
|
5060
|
-
return this.isUploadedFileRef(value) ? [value] : [];
|
|
5061
|
-
}
|
|
5062
|
-
getImageSource(field, value) {
|
|
5063
|
-
if (typeof value === 'string' && value.trim()) {
|
|
5064
|
-
return value;
|
|
5065
|
-
}
|
|
5066
|
-
const imageSrc = field['imageSrc'];
|
|
5067
|
-
if (typeof imageSrc === 'string' && imageSrc.trim()) {
|
|
5068
|
-
return imageSrc;
|
|
5069
|
-
}
|
|
5070
|
-
const staticValue = field.dataConfig?.staticValue;
|
|
5071
|
-
return typeof staticValue === 'string' && staticValue.trim() ? staticValue : null;
|
|
5072
|
-
}
|
|
5073
|
-
getRepeatableItems(value) {
|
|
5074
|
-
if (!Array.isArray(value))
|
|
5075
|
-
return [];
|
|
5076
|
-
return value.filter(item => this.isRecord(item));
|
|
5077
|
-
}
|
|
5078
|
-
getRepeatableFields(field) {
|
|
5079
|
-
return field.repeatable?.itemSchema?.fields ?? [];
|
|
5080
|
-
}
|
|
5081
|
-
getRepeatableItemTitle(field, index) {
|
|
5082
|
-
const itemLabel = field.repeatable?.itemLabel?.trim() || 'Item';
|
|
5083
|
-
return `${itemLabel} ${index + 1}`;
|
|
5084
|
-
}
|
|
5085
|
-
getNestedFieldValue(item, nestedField) {
|
|
5086
|
-
return item[nestedField.name] ?? nestedField.defaultValue ?? null;
|
|
5087
|
-
}
|
|
5088
|
-
getTableRows(value) {
|
|
5089
|
-
if (!Array.isArray(value))
|
|
5090
|
-
return [];
|
|
5091
|
-
return value.filter(item => this.isRecord(item));
|
|
5092
|
-
}
|
|
5093
|
-
getTableColumns(field, value) {
|
|
5094
|
-
const configuredColumns = Array.isArray(field['columns']) ? field['columns'] : [];
|
|
5095
|
-
const normalizedConfigured = configuredColumns
|
|
5096
|
-
.filter(column => this.isRecord(column) && typeof column['key'] === 'string')
|
|
5097
|
-
.map(column => ({
|
|
5098
|
-
key: String(column['key']),
|
|
5099
|
-
label: typeof column['label'] === 'string' && column['label'].trim()
|
|
5100
|
-
? String(column['label'])
|
|
5101
|
-
: String(column['key'])
|
|
5102
|
-
}));
|
|
5103
|
-
if (normalizedConfigured.length) {
|
|
5104
|
-
return normalizedConfigured;
|
|
5105
|
-
}
|
|
5106
|
-
const [firstRow] = this.getTableRows(value);
|
|
5107
|
-
if (!firstRow)
|
|
5108
|
-
return [];
|
|
5109
|
-
return Object.keys(firstRow).map(key => ({ key, label: key }));
|
|
5110
|
-
}
|
|
5111
|
-
readPathValue(value, path) {
|
|
5112
|
-
if (!path)
|
|
5113
|
-
return value;
|
|
5114
|
-
return path
|
|
5115
|
-
.split('.')
|
|
5116
|
-
.reduce((current, segment) => (this.isRecord(current) ? current[segment] : undefined), value);
|
|
5117
|
-
}
|
|
5118
|
-
isTruthy(value) {
|
|
5119
|
-
return !!value;
|
|
5120
|
-
}
|
|
5121
|
-
getEmptyValueLabel(field) {
|
|
5122
|
-
return field?.type === 'file' ? 'No files uploaded' : 'No value provided';
|
|
5123
|
-
}
|
|
5124
|
-
formatFileSize(size) {
|
|
5125
|
-
if (size >= 1024 * 1024) {
|
|
5126
|
-
return `${(size / (1024 * 1024)).toFixed(1)} MB`;
|
|
5127
|
-
}
|
|
5128
|
-
if (size >= 1024) {
|
|
5129
|
-
return `${(size / 1024).toFixed(1)} KB`;
|
|
5130
|
-
}
|
|
5131
|
-
return `${size} B`;
|
|
5132
|
-
}
|
|
5133
|
-
trackByNodeId(_, node) {
|
|
5134
|
-
return node.id;
|
|
5135
|
-
}
|
|
5136
|
-
trackByIndex(index) {
|
|
5137
|
-
return index;
|
|
5138
|
-
}
|
|
5139
|
-
trackByFieldId(_, field) {
|
|
5140
|
-
return field.id;
|
|
5141
|
-
}
|
|
5142
|
-
trackByTableColumn(_, column) {
|
|
5143
|
-
return column.key;
|
|
5144
|
-
}
|
|
5145
|
-
trackByUploadedFile(_, file) {
|
|
5146
|
-
return `${file.id ?? ''}-${file.name ?? ''}-${file.url ?? ''}`;
|
|
5147
|
-
}
|
|
5148
|
-
getEffectiveSpan(responsive) {
|
|
5149
|
-
const breakpoints = ['xs', 'sm', 'md', 'lg', 'xl', '2xl'];
|
|
5150
|
-
const currentIndex = breakpoints.indexOf(this.breakpoint);
|
|
5151
|
-
if (currentIndex === -1)
|
|
5152
|
-
return responsive.xs || 12;
|
|
5153
|
-
for (let index = currentIndex; index >= 0; index -= 1) {
|
|
5154
|
-
const key = breakpoints[index];
|
|
5155
|
-
if (responsive[key] != null) {
|
|
5156
|
-
return responsive[key];
|
|
5157
|
-
}
|
|
5158
|
-
}
|
|
5159
|
-
return 12;
|
|
5160
|
-
}
|
|
5161
|
-
getSpanClass(span) {
|
|
5162
|
-
if (span === 12)
|
|
5163
|
-
return 'w-full';
|
|
5164
|
-
const map = {
|
|
5165
|
-
1: 'w-1/12',
|
|
5166
|
-
2: 'w-2/12',
|
|
5167
|
-
3: 'w-3/12',
|
|
5168
|
-
4: 'w-4/12',
|
|
5169
|
-
5: 'w-5/12',
|
|
5170
|
-
6: 'w-6/12',
|
|
5171
|
-
7: 'w-7/12',
|
|
5172
|
-
8: 'w-8/12',
|
|
5173
|
-
9: 'w-9/12',
|
|
5174
|
-
10: 'w-10/12',
|
|
5175
|
-
11: 'w-11/12'
|
|
5176
|
-
};
|
|
5177
|
-
return map[span] || 'w-full';
|
|
5178
|
-
}
|
|
5179
|
-
resolveOptionLabel(field, value) {
|
|
5180
|
-
const options = this.getFieldOptions(field);
|
|
5181
|
-
const matched = options.find(option => this.optionMatches(option, value));
|
|
5182
|
-
return matched?.label ?? value;
|
|
5183
|
-
}
|
|
5184
|
-
getFieldOptions(field) {
|
|
5185
|
-
return field.dataConfig?.staticOptions ?? field.staticOptions ?? [];
|
|
5186
|
-
}
|
|
5187
|
-
optionMatches(option, value) {
|
|
5188
|
-
return option.value === value || String(option.value) === String(value);
|
|
5189
|
-
}
|
|
5190
|
-
formatDateValue(value) {
|
|
5191
|
-
if (typeof value !== 'string' || !value.trim()) {
|
|
5192
|
-
return this.getEmptyValueLabel();
|
|
5193
|
-
}
|
|
5194
|
-
const date = new Date(`${value}T00:00:00`);
|
|
5195
|
-
return Number.isNaN(date.getTime()) ? value : date.toLocaleDateString('en-GB');
|
|
5196
|
-
}
|
|
5197
|
-
formatTimeValue(value) {
|
|
5198
|
-
if (typeof value !== 'string' || !value.trim()) {
|
|
5199
|
-
return this.getEmptyValueLabel();
|
|
5200
|
-
}
|
|
5201
|
-
const [hours, minutes] = value.split(':');
|
|
5202
|
-
if (!hours || !minutes)
|
|
5203
|
-
return value;
|
|
5204
|
-
const date = new Date();
|
|
5205
|
-
date.setHours(Number(hours), Number(minutes), 0, 0);
|
|
5206
|
-
return Number.isNaN(date.getTime())
|
|
5207
|
-
? value
|
|
5208
|
-
: date.toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit' });
|
|
5209
|
-
}
|
|
5210
|
-
formatDateTimeValue(value) {
|
|
5211
|
-
if (typeof value !== 'string' || !value.trim()) {
|
|
5212
|
-
return this.getEmptyValueLabel();
|
|
5213
|
-
}
|
|
5214
|
-
const date = new Date(value);
|
|
5215
|
-
return Number.isNaN(date.getTime())
|
|
5216
|
-
? value
|
|
5217
|
-
: date.toLocaleString('en-GB', {
|
|
5218
|
-
year: 'numeric',
|
|
5219
|
-
month: 'short',
|
|
5220
|
-
day: 'numeric',
|
|
5221
|
-
hour: '2-digit',
|
|
5222
|
-
minute: '2-digit'
|
|
5223
|
-
});
|
|
5224
|
-
}
|
|
5225
|
-
isRecord(value) {
|
|
5226
|
-
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
5227
|
-
}
|
|
5228
|
-
isUploadedFileRef(value) {
|
|
5229
|
-
if (!this.isRecord(value))
|
|
5230
|
-
return false;
|
|
5231
|
-
return typeof value['name'] === 'string'
|
|
5232
|
-
|| typeof value['url'] === 'string'
|
|
5233
|
-
|| typeof value['id'] === 'string';
|
|
5234
|
-
}
|
|
5235
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FormViewerReadonlyComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5236
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: FormViewerReadonlyComponent, isStandalone: true, selector: "app-form-viewer-readonly", inputs: { schema: "schema", values: "values", breakpoint: "breakpoint" }, ngImport: i0, template: `
|
|
5237
|
-
<div class="space-y-4" data-fd="form-viewer-readonly">
|
|
5238
|
-
<ng-container *ngIf="schema.layout as layout">
|
|
5239
|
-
<ng-container
|
|
5240
|
-
*ngTemplateOutlet="renderNode; context: { $implicit: layout }">
|
|
5241
|
-
</ng-container>
|
|
5242
|
-
</ng-container>
|
|
5243
|
-
</div>
|
|
5244
|
-
|
|
5245
|
-
<ng-template #renderNode let-node>
|
|
5246
|
-
<ng-container [ngSwitch]="node.type">
|
|
5247
|
-
<div
|
|
5248
|
-
*ngSwitchCase="'row'"
|
|
5249
|
-
class="flex flex-wrap"
|
|
5250
|
-
data-fd="form-viewer-row"
|
|
5251
|
-
[style]="getNodeStyle(node)">
|
|
5252
|
-
<ng-container *ngFor="let child of asRow(node).children; trackBy: trackByNodeId">
|
|
5253
|
-
<ng-container
|
|
5254
|
-
*ngTemplateOutlet="renderNode; context: { $implicit: child }">
|
|
5255
|
-
</ng-container>
|
|
5256
|
-
</ng-container>
|
|
5257
|
-
</div>
|
|
5258
|
-
|
|
5259
|
-
<div
|
|
5260
|
-
*ngSwitchCase="'col'"
|
|
5261
|
-
class="min-h-[1px] space-y-4"
|
|
5262
|
-
data-fd="form-viewer-column"
|
|
5263
|
-
[class]="getColClasses(node)"
|
|
5264
|
-
[style]="getNodeStyle(node)">
|
|
5265
|
-
<ng-container *ngFor="let child of asCol(node).children; trackBy: trackByNodeId">
|
|
5266
|
-
<ng-container
|
|
5267
|
-
*ngTemplateOutlet="renderNode; context: { $implicit: child }">
|
|
5268
|
-
</ng-container>
|
|
5269
|
-
</ng-container>
|
|
5270
|
-
</div>
|
|
5271
|
-
|
|
5272
|
-
<ng-container *ngSwitchCase="'widget'">
|
|
5273
|
-
<ng-container *ngIf="getField(asWidget(node).refId) as field">
|
|
5274
|
-
<div class="w-full"
|
|
5275
|
-
data-fd="form-viewer-widget"
|
|
5276
|
-
[attr.data-fd-field-name]="field.name"
|
|
5277
|
-
[attr.data-fd-field-type]="field.type"
|
|
5278
|
-
[style]="getNodeStyle(node)">
|
|
5279
|
-
<ng-container [ngSwitch]="field.type">
|
|
5280
|
-
<div *ngSwitchCase="'heading'"
|
|
5281
|
-
data-fd="form-viewer-heading"
|
|
5282
|
-
[attr.data-fd-field-name]="field.name"
|
|
5283
|
-
[attr.data-fd-field-type]="field.type"
|
|
5284
|
-
[style]="getFieldStyle(field)">
|
|
5285
|
-
<h1
|
|
5286
|
-
*ngIf="getHeadingLevel(field) === 'h1'"
|
|
5287
|
-
class="text-4xl font-semibold tracking-tight text-slate-950">
|
|
5288
|
-
{{ getHeadingText(field) }}
|
|
5289
|
-
</h1>
|
|
5290
|
-
<h2
|
|
5291
|
-
*ngIf="getHeadingLevel(field) === 'h2'"
|
|
5292
|
-
class="text-3xl font-semibold tracking-tight text-slate-950">
|
|
5293
|
-
{{ getHeadingText(field) }}
|
|
5294
|
-
</h2>
|
|
5295
|
-
<h3
|
|
5296
|
-
*ngIf="getHeadingLevel(field) === 'h3'"
|
|
5297
|
-
class="text-2xl font-semibold tracking-tight text-slate-950">
|
|
5298
|
-
{{ getHeadingText(field) }}
|
|
5299
|
-
</h3>
|
|
5300
|
-
<h4
|
|
5301
|
-
*ngIf="getHeadingLevel(field) === 'h4'"
|
|
5302
|
-
class="text-xl font-semibold tracking-tight text-slate-950">
|
|
5303
|
-
{{ getHeadingText(field) }}
|
|
5304
|
-
</h4>
|
|
5305
|
-
<h5
|
|
5306
|
-
*ngIf="getHeadingLevel(field) === 'h5'"
|
|
5307
|
-
class="text-lg font-semibold tracking-tight text-slate-950">
|
|
5308
|
-
{{ getHeadingText(field) }}
|
|
5309
|
-
</h5>
|
|
5310
|
-
<h6
|
|
5311
|
-
*ngIf="getHeadingLevel(field) === 'h6'"
|
|
5312
|
-
class="text-base font-semibold tracking-tight text-slate-950">
|
|
5313
|
-
{{ getHeadingText(field) }}
|
|
5314
|
-
</h6>
|
|
5315
|
-
</div>
|
|
5316
|
-
|
|
5317
|
-
<p
|
|
5318
|
-
*ngSwitchCase="'paragraph'"
|
|
5319
|
-
data-fd="form-viewer-paragraph"
|
|
5320
|
-
[attr.data-fd-field-name]="field.name"
|
|
5321
|
-
[attr.data-fd-field-type]="field.type"
|
|
5322
|
-
class="whitespace-pre-wrap text-sm leading-6 text-slate-700"
|
|
5323
|
-
[style]="getFieldStyle(field)">
|
|
5324
|
-
{{ getParagraphText(field) }}
|
|
5325
|
-
</p>
|
|
5326
|
-
|
|
5327
|
-
<div
|
|
5328
|
-
*ngSwitchCase="'rich-text'"
|
|
5329
|
-
data-fd="form-viewer-rich-text"
|
|
5330
|
-
[attr.data-fd-field-name]="field.name"
|
|
5331
|
-
[attr.data-fd-field-type]="field.type"
|
|
5332
|
-
class="whitespace-pre-wrap text-sm leading-6 text-slate-700"
|
|
5333
|
-
[style]="getFieldStyle(field)"
|
|
5334
|
-
[innerHTML]="getRichTextContent(field)"></div>
|
|
5335
|
-
|
|
5336
|
-
<div *ngSwitchCase="'cta-button'"
|
|
5337
|
-
data-fd="form-viewer-button"
|
|
5338
|
-
[attr.data-fd-field-name]="field.name"
|
|
5339
|
-
[attr.data-fd-field-type]="field.type"
|
|
5340
|
-
[style]="getFieldStyle(field)">
|
|
5341
|
-
<button
|
|
5342
|
-
type="button"
|
|
5343
|
-
disabled
|
|
5344
|
-
class="inline-flex cursor-default items-center justify-center rounded-lg border border-slate-300 bg-slate-100 px-4 py-2 text-sm font-medium text-slate-700 shadow-sm">
|
|
5345
|
-
{{ field.label || 'Action' }}
|
|
5346
|
-
</button>
|
|
5347
|
-
</div>
|
|
5348
|
-
|
|
5349
|
-
<div *ngSwitchDefault
|
|
5350
|
-
data-fd="form-viewer-field-card"
|
|
5351
|
-
[attr.data-fd-field-name]="field.name"
|
|
5352
|
-
[attr.data-fd-field-type]="field.type"
|
|
5353
|
-
class="rounded-xl border border-slate-200 bg-white px-4 py-3 shadow-sm"
|
|
5354
|
-
[style]="getFieldStyle(field)">
|
|
5355
|
-
<div class="mb-3 flex items-start justify-between gap-3" *ngIf="field.helpText || field.html5?.required">
|
|
5356
|
-
<div *ngIf="field.helpText">
|
|
5357
|
-
<p data-fd="form-viewer-field-help" class="text-xs text-slate-500">
|
|
5358
|
-
{{ field.helpText }}
|
|
5359
|
-
</p>
|
|
5360
|
-
</div>
|
|
5361
|
-
<span
|
|
5362
|
-
*ngIf="field.html5?.required"
|
|
5363
|
-
class="rounded-full bg-rose-50 px-2 py-1 text-[11px] font-medium text-rose-600">
|
|
5364
|
-
Required
|
|
5365
|
-
</span>
|
|
5366
|
-
</div>
|
|
5367
|
-
|
|
5368
|
-
<ng-container [ngSwitch]="field.type">
|
|
5369
|
-
<div *ngSwitchCase="'checkbox'"
|
|
5370
|
-
data-fd="form-viewer-field-value"
|
|
5371
|
-
class="inline-flex items-center rounded-full px-3 py-1 text-sm font-medium"
|
|
5372
|
-
[class.bg-emerald-50]="isTruthy(getFieldValue(field))"
|
|
5373
|
-
[class.text-emerald-700]="isTruthy(getFieldValue(field))"
|
|
5374
|
-
[class.bg-slate-100]="!isTruthy(getFieldValue(field))"
|
|
5375
|
-
[class.text-slate-600]="!isTruthy(getFieldValue(field))">
|
|
5376
|
-
{{ isTruthy(getFieldValue(field)) ? 'Checked' : 'Not checked' }}
|
|
5377
|
-
</div>
|
|
5378
|
-
|
|
5379
|
-
<div *ngSwitchCase="'multiselect'" data-fd="form-viewer-chip-list" class="flex flex-wrap gap-2">
|
|
5380
|
-
<span
|
|
5381
|
-
*ngFor="let item of getDisplayList(field, getFieldValue(field)); trackBy: trackByIndex"
|
|
5382
|
-
data-fd="form-viewer-chip"
|
|
5383
|
-
class="rounded-full bg-slate-100 px-3 py-1 text-sm text-slate-700">
|
|
5384
|
-
{{ item }}
|
|
5385
|
-
</span>
|
|
5386
|
-
<span *ngIf="!getDisplayList(field, getFieldValue(field)).length" data-fd="form-viewer-field-value-empty" class="text-sm text-slate-400">
|
|
5387
|
-
{{ getEmptyValueLabel(field) }}
|
|
5388
|
-
</span>
|
|
5389
|
-
</div>
|
|
5390
|
-
|
|
5391
|
-
<div *ngSwitchCase="'checkbox-group'" data-fd="form-viewer-chip-list" class="flex flex-wrap gap-2">
|
|
5392
|
-
<span
|
|
5393
|
-
*ngFor="let item of getDisplayList(field, getFieldValue(field)); trackBy: trackByIndex"
|
|
5394
|
-
data-fd="form-viewer-chip"
|
|
5395
|
-
class="rounded-full bg-slate-100 px-3 py-1 text-sm text-slate-700">
|
|
5396
|
-
{{ item }}
|
|
5397
|
-
</span>
|
|
5398
|
-
<span *ngIf="!getDisplayList(field, getFieldValue(field)).length" data-fd="form-viewer-field-value-empty" class="text-sm text-slate-400">
|
|
5399
|
-
{{ getEmptyValueLabel(field) }}
|
|
5400
|
-
</span>
|
|
5401
|
-
</div>
|
|
5402
|
-
|
|
5403
|
-
<div *ngSwitchCase="'file'" data-fd="form-viewer-file-list" class="space-y-2">
|
|
5404
|
-
<ng-container *ngIf="getUploadedFiles(getFieldValue(field)).length; else emptyFileState">
|
|
5405
|
-
<div
|
|
5406
|
-
*ngFor="let file of getUploadedFiles(getFieldValue(field)); trackBy: trackByUploadedFile"
|
|
5407
|
-
data-fd="form-viewer-file-item"
|
|
5408
|
-
class="flex items-center justify-between gap-3 rounded-lg border border-slate-200 bg-slate-50 px-3 py-2">
|
|
5409
|
-
<div class="min-w-0">
|
|
5410
|
-
<a
|
|
5411
|
-
*ngIf="file.url; else fileNameText"
|
|
5412
|
-
data-fd="form-viewer-file-link"
|
|
5413
|
-
[href]="file.url"
|
|
5414
|
-
target="_blank"
|
|
5415
|
-
rel="noopener noreferrer"
|
|
5416
|
-
class="block truncate text-sm font-medium text-sky-700 underline">
|
|
5417
|
-
{{ file.name || file.id || 'Uploaded file' }}
|
|
5418
|
-
</a>
|
|
5419
|
-
<ng-template #fileNameText>
|
|
5420
|
-
<div data-fd="form-viewer-file-name" class="truncate text-sm font-medium text-slate-900">
|
|
5421
|
-
{{ file.name || file.id || 'Uploaded file' }}
|
|
5422
|
-
</div>
|
|
5423
|
-
</ng-template>
|
|
5424
|
-
<div *ngIf="file.type" data-fd="form-viewer-file-type" class="text-xs text-slate-500">{{ file.type }}</div>
|
|
5425
|
-
</div>
|
|
5426
|
-
<div *ngIf="file.size != null" data-fd="form-viewer-file-size" class="text-xs text-slate-500">
|
|
5427
|
-
{{ formatFileSize(file.size) }}
|
|
5428
|
-
</div>
|
|
5429
|
-
</div>
|
|
5430
|
-
</ng-container>
|
|
5431
|
-
<ng-template #emptyFileState>
|
|
5432
|
-
<span data-fd="form-viewer-field-value-empty" class="text-sm text-slate-400">{{ getEmptyValueLabel(field) }}</span>
|
|
5433
|
-
</ng-template>
|
|
5434
|
-
</div>
|
|
5435
|
-
|
|
5436
|
-
<div *ngSwitchCase="'image'" data-fd="form-viewer-image" class="space-y-3">
|
|
5437
|
-
<ng-container *ngIf="getImageSource(field, getFieldValue(field)) as imageSrc; else emptyImageState">
|
|
5438
|
-
<img
|
|
5439
|
-
data-fd="form-viewer-image-element"
|
|
5440
|
-
[src]="imageSrc"
|
|
5441
|
-
[alt]="field.label || field.name"
|
|
5442
|
-
class="max-h-64 rounded-lg border border-slate-200 object-contain">
|
|
5443
|
-
</ng-container>
|
|
5444
|
-
<ng-template #emptyImageState>
|
|
5445
|
-
<span data-fd="form-viewer-field-value-empty" class="text-sm text-slate-400">{{ getEmptyValueLabel(field) }}</span>
|
|
5446
|
-
</ng-template>
|
|
5447
|
-
</div>
|
|
5448
|
-
|
|
5449
|
-
<div *ngSwitchCase="'repeatable-group'" data-fd="form-viewer-repeatable-group" class="space-y-3">
|
|
5450
|
-
<ng-container *ngIf="getRepeatableItems(getFieldValue(field)).length; else emptyRepeatableState">
|
|
5451
|
-
<section
|
|
5452
|
-
*ngFor="let item of getRepeatableItems(getFieldValue(field)); let index = index; trackBy: trackByIndex"
|
|
5453
|
-
data-fd="form-viewer-repeatable-item"
|
|
5454
|
-
class="rounded-lg border border-slate-200 bg-slate-50 px-3 py-3">
|
|
5455
|
-
<div data-fd="form-viewer-repeatable-item-title" class="mb-3 text-xs font-semibold uppercase tracking-wide text-slate-500">
|
|
5456
|
-
{{ getRepeatableItemTitle(field, index) }}
|
|
5457
|
-
</div>
|
|
5458
|
-
<dl class="grid gap-3 sm:grid-cols-2">
|
|
5459
|
-
<div
|
|
5460
|
-
*ngFor="let nestedField of getRepeatableFields(field); trackBy: trackByFieldId"
|
|
5461
|
-
data-fd="form-viewer-repeatable-field"
|
|
5462
|
-
class="rounded-md border border-slate-200 bg-white px-3 py-2">
|
|
5463
|
-
<dt data-fd="form-viewer-repeatable-field-label" class="text-xs font-medium uppercase tracking-wide text-slate-500">
|
|
5464
|
-
{{ getFieldLabel(nestedField) }}
|
|
5465
|
-
</dt>
|
|
5466
|
-
<dd data-fd="form-viewer-repeatable-field-value" class="mt-1 whitespace-pre-wrap text-sm text-slate-900">
|
|
5467
|
-
{{ formatScalarValue(getNestedFieldValue(item, nestedField)) }}
|
|
5468
|
-
</dd>
|
|
5469
|
-
</div>
|
|
5470
|
-
</dl>
|
|
5471
|
-
</section>
|
|
5472
|
-
</ng-container>
|
|
5473
|
-
<ng-template #emptyRepeatableState>
|
|
5474
|
-
<span data-fd="form-viewer-field-value-empty" class="text-sm text-slate-400">{{ getEmptyValueLabel(field) }}</span>
|
|
5475
|
-
</ng-template>
|
|
5476
|
-
</div>
|
|
5477
|
-
|
|
5478
|
-
<div *ngSwitchCase="'table'" data-fd="form-viewer-table-wrapper" class="overflow-x-auto rounded-lg border border-slate-200">
|
|
5479
|
-
<table data-fd="form-viewer-table" class="min-w-full divide-y divide-slate-200 text-sm">
|
|
5480
|
-
<thead data-fd="form-viewer-table-head" class="bg-slate-50">
|
|
5481
|
-
<tr>
|
|
5482
|
-
<th
|
|
5483
|
-
*ngFor="let column of getTableColumns(field, getFieldValue(field)); trackBy: trackByTableColumn"
|
|
5484
|
-
data-fd="form-viewer-table-header"
|
|
5485
|
-
class="px-3 py-2 text-left font-semibold text-slate-600">
|
|
5486
|
-
{{ column.label }}
|
|
5487
|
-
</th>
|
|
5488
|
-
</tr>
|
|
5489
|
-
</thead>
|
|
5490
|
-
<tbody data-fd="form-viewer-table-body" class="divide-y divide-slate-200 bg-white">
|
|
5491
|
-
<tr *ngFor="let row of getTableRows(getFieldValue(field)); trackBy: trackByIndex" data-fd="form-viewer-table-row">
|
|
5492
|
-
<td
|
|
5493
|
-
*ngFor="let column of getTableColumns(field, getFieldValue(field)); trackBy: trackByTableColumn"
|
|
5494
|
-
data-fd="form-viewer-table-cell"
|
|
5495
|
-
class="px-3 py-2 align-top text-slate-700">
|
|
5496
|
-
{{ formatScalarValue(readPathValue(row, column.key)) }}
|
|
5497
|
-
</td>
|
|
5498
|
-
</tr>
|
|
5499
|
-
<tr *ngIf="!getTableRows(getFieldValue(field)).length" data-fd="form-viewer-table-empty-row">
|
|
5500
|
-
<td data-fd="form-viewer-table-empty"
|
|
5501
|
-
class="px-3 py-3 text-slate-400"
|
|
5502
|
-
[attr.colspan]="getTableColumns(field, getFieldValue(field)).length || 1">
|
|
5503
|
-
{{ getEmptyValueLabel(field) }}
|
|
5504
|
-
</td>
|
|
5505
|
-
</tr>
|
|
5506
|
-
</tbody>
|
|
5507
|
-
</table>
|
|
5508
|
-
</div>
|
|
5509
|
-
|
|
5510
|
-
<div *ngSwitchDefault data-fd="form-viewer-field-value" class="whitespace-pre-wrap text-sm leading-6 text-slate-900">
|
|
5511
|
-
{{ formatFieldValue(field, getFieldValue(field)) }}
|
|
5512
|
-
</div>
|
|
5513
|
-
</ng-container>
|
|
5514
|
-
</div>
|
|
5515
|
-
</ng-container>
|
|
5516
|
-
</div>
|
|
5517
|
-
</ng-container>
|
|
5518
|
-
</ng-container>
|
|
5519
|
-
</ng-container>
|
|
5520
|
-
</ng-template>
|
|
5521
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1.NgSwitchDefault, selector: "[ngSwitchDefault]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
5522
|
-
}
|
|
5523
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FormViewerReadonlyComponent, decorators: [{
|
|
5524
|
-
type: Component,
|
|
5525
|
-
args: [{
|
|
5526
|
-
selector: 'app-form-viewer-readonly',
|
|
5527
|
-
standalone: true,
|
|
5528
|
-
imports: [CommonModule],
|
|
5529
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
5530
|
-
template: `
|
|
5531
|
-
<div class="space-y-4" data-fd="form-viewer-readonly">
|
|
5532
|
-
<ng-container *ngIf="schema.layout as layout">
|
|
5533
|
-
<ng-container
|
|
5534
|
-
*ngTemplateOutlet="renderNode; context: { $implicit: layout }">
|
|
5535
|
-
</ng-container>
|
|
5536
|
-
</ng-container>
|
|
5537
|
-
</div>
|
|
5538
|
-
|
|
5539
|
-
<ng-template #renderNode let-node>
|
|
5540
|
-
<ng-container [ngSwitch]="node.type">
|
|
5541
|
-
<div
|
|
5542
|
-
*ngSwitchCase="'row'"
|
|
5543
|
-
class="flex flex-wrap"
|
|
5544
|
-
data-fd="form-viewer-row"
|
|
5545
|
-
[style]="getNodeStyle(node)">
|
|
5546
|
-
<ng-container *ngFor="let child of asRow(node).children; trackBy: trackByNodeId">
|
|
5547
|
-
<ng-container
|
|
5548
|
-
*ngTemplateOutlet="renderNode; context: { $implicit: child }">
|
|
5549
|
-
</ng-container>
|
|
5550
|
-
</ng-container>
|
|
5551
|
-
</div>
|
|
5552
|
-
|
|
5553
|
-
<div
|
|
5554
|
-
*ngSwitchCase="'col'"
|
|
5555
|
-
class="min-h-[1px] space-y-4"
|
|
5556
|
-
data-fd="form-viewer-column"
|
|
5557
|
-
[class]="getColClasses(node)"
|
|
5558
|
-
[style]="getNodeStyle(node)">
|
|
5559
|
-
<ng-container *ngFor="let child of asCol(node).children; trackBy: trackByNodeId">
|
|
5560
|
-
<ng-container
|
|
5561
|
-
*ngTemplateOutlet="renderNode; context: { $implicit: child }">
|
|
5562
|
-
</ng-container>
|
|
5563
|
-
</ng-container>
|
|
5564
|
-
</div>
|
|
5565
|
-
|
|
5566
|
-
<ng-container *ngSwitchCase="'widget'">
|
|
5567
|
-
<ng-container *ngIf="getField(asWidget(node).refId) as field">
|
|
5568
|
-
<div class="w-full"
|
|
5569
|
-
data-fd="form-viewer-widget"
|
|
5570
|
-
[attr.data-fd-field-name]="field.name"
|
|
5571
|
-
[attr.data-fd-field-type]="field.type"
|
|
5572
|
-
[style]="getNodeStyle(node)">
|
|
5573
|
-
<ng-container [ngSwitch]="field.type">
|
|
5574
|
-
<div *ngSwitchCase="'heading'"
|
|
5575
|
-
data-fd="form-viewer-heading"
|
|
5576
|
-
[attr.data-fd-field-name]="field.name"
|
|
5577
|
-
[attr.data-fd-field-type]="field.type"
|
|
5578
|
-
[style]="getFieldStyle(field)">
|
|
5579
|
-
<h1
|
|
5580
|
-
*ngIf="getHeadingLevel(field) === 'h1'"
|
|
5581
|
-
class="text-4xl font-semibold tracking-tight text-slate-950">
|
|
5582
|
-
{{ getHeadingText(field) }}
|
|
5583
|
-
</h1>
|
|
5584
|
-
<h2
|
|
5585
|
-
*ngIf="getHeadingLevel(field) === 'h2'"
|
|
5586
|
-
class="text-3xl font-semibold tracking-tight text-slate-950">
|
|
5587
|
-
{{ getHeadingText(field) }}
|
|
5588
|
-
</h2>
|
|
5589
|
-
<h3
|
|
5590
|
-
*ngIf="getHeadingLevel(field) === 'h3'"
|
|
5591
|
-
class="text-2xl font-semibold tracking-tight text-slate-950">
|
|
5592
|
-
{{ getHeadingText(field) }}
|
|
5593
|
-
</h3>
|
|
5594
|
-
<h4
|
|
5595
|
-
*ngIf="getHeadingLevel(field) === 'h4'"
|
|
5596
|
-
class="text-xl font-semibold tracking-tight text-slate-950">
|
|
5597
|
-
{{ getHeadingText(field) }}
|
|
5598
|
-
</h4>
|
|
5599
|
-
<h5
|
|
5600
|
-
*ngIf="getHeadingLevel(field) === 'h5'"
|
|
5601
|
-
class="text-lg font-semibold tracking-tight text-slate-950">
|
|
5602
|
-
{{ getHeadingText(field) }}
|
|
5603
|
-
</h5>
|
|
5604
|
-
<h6
|
|
5605
|
-
*ngIf="getHeadingLevel(field) === 'h6'"
|
|
5606
|
-
class="text-base font-semibold tracking-tight text-slate-950">
|
|
5607
|
-
{{ getHeadingText(field) }}
|
|
5608
|
-
</h6>
|
|
5609
|
-
</div>
|
|
5610
|
-
|
|
5611
|
-
<p
|
|
5612
|
-
*ngSwitchCase="'paragraph'"
|
|
5613
|
-
data-fd="form-viewer-paragraph"
|
|
5614
|
-
[attr.data-fd-field-name]="field.name"
|
|
5615
|
-
[attr.data-fd-field-type]="field.type"
|
|
5616
|
-
class="whitespace-pre-wrap text-sm leading-6 text-slate-700"
|
|
5617
|
-
[style]="getFieldStyle(field)">
|
|
5618
|
-
{{ getParagraphText(field) }}
|
|
5619
|
-
</p>
|
|
5620
|
-
|
|
5621
|
-
<div
|
|
5622
|
-
*ngSwitchCase="'rich-text'"
|
|
5623
|
-
data-fd="form-viewer-rich-text"
|
|
5624
|
-
[attr.data-fd-field-name]="field.name"
|
|
5625
|
-
[attr.data-fd-field-type]="field.type"
|
|
5626
|
-
class="whitespace-pre-wrap text-sm leading-6 text-slate-700"
|
|
5627
|
-
[style]="getFieldStyle(field)"
|
|
5628
|
-
[innerHTML]="getRichTextContent(field)"></div>
|
|
5629
|
-
|
|
5630
|
-
<div *ngSwitchCase="'cta-button'"
|
|
5631
|
-
data-fd="form-viewer-button"
|
|
5632
|
-
[attr.data-fd-field-name]="field.name"
|
|
5633
|
-
[attr.data-fd-field-type]="field.type"
|
|
5634
|
-
[style]="getFieldStyle(field)">
|
|
5635
|
-
<button
|
|
5636
|
-
type="button"
|
|
5637
|
-
disabled
|
|
5638
|
-
class="inline-flex cursor-default items-center justify-center rounded-lg border border-slate-300 bg-slate-100 px-4 py-2 text-sm font-medium text-slate-700 shadow-sm">
|
|
5639
|
-
{{ field.label || 'Action' }}
|
|
5640
|
-
</button>
|
|
5641
|
-
</div>
|
|
5642
|
-
|
|
5643
|
-
<div *ngSwitchDefault
|
|
5644
|
-
data-fd="form-viewer-field-card"
|
|
5645
|
-
[attr.data-fd-field-name]="field.name"
|
|
5646
|
-
[attr.data-fd-field-type]="field.type"
|
|
5647
|
-
class="rounded-xl border border-slate-200 bg-white px-4 py-3 shadow-sm"
|
|
5648
|
-
[style]="getFieldStyle(field)">
|
|
5649
|
-
<div class="mb-3 flex items-start justify-between gap-3" *ngIf="field.helpText || field.html5?.required">
|
|
5650
|
-
<div *ngIf="field.helpText">
|
|
5651
|
-
<p data-fd="form-viewer-field-help" class="text-xs text-slate-500">
|
|
5652
|
-
{{ field.helpText }}
|
|
5653
|
-
</p>
|
|
5654
|
-
</div>
|
|
5655
|
-
<span
|
|
5656
|
-
*ngIf="field.html5?.required"
|
|
5657
|
-
class="rounded-full bg-rose-50 px-2 py-1 text-[11px] font-medium text-rose-600">
|
|
5658
|
-
Required
|
|
5659
|
-
</span>
|
|
5660
|
-
</div>
|
|
5661
|
-
|
|
5662
|
-
<ng-container [ngSwitch]="field.type">
|
|
5663
|
-
<div *ngSwitchCase="'checkbox'"
|
|
5664
|
-
data-fd="form-viewer-field-value"
|
|
5665
|
-
class="inline-flex items-center rounded-full px-3 py-1 text-sm font-medium"
|
|
5666
|
-
[class.bg-emerald-50]="isTruthy(getFieldValue(field))"
|
|
5667
|
-
[class.text-emerald-700]="isTruthy(getFieldValue(field))"
|
|
5668
|
-
[class.bg-slate-100]="!isTruthy(getFieldValue(field))"
|
|
5669
|
-
[class.text-slate-600]="!isTruthy(getFieldValue(field))">
|
|
5670
|
-
{{ isTruthy(getFieldValue(field)) ? 'Checked' : 'Not checked' }}
|
|
5671
|
-
</div>
|
|
5672
|
-
|
|
5673
|
-
<div *ngSwitchCase="'multiselect'" data-fd="form-viewer-chip-list" class="flex flex-wrap gap-2">
|
|
5674
|
-
<span
|
|
5675
|
-
*ngFor="let item of getDisplayList(field, getFieldValue(field)); trackBy: trackByIndex"
|
|
5676
|
-
data-fd="form-viewer-chip"
|
|
5677
|
-
class="rounded-full bg-slate-100 px-3 py-1 text-sm text-slate-700">
|
|
5678
|
-
{{ item }}
|
|
5679
|
-
</span>
|
|
5680
|
-
<span *ngIf="!getDisplayList(field, getFieldValue(field)).length" data-fd="form-viewer-field-value-empty" class="text-sm text-slate-400">
|
|
5681
|
-
{{ getEmptyValueLabel(field) }}
|
|
5682
|
-
</span>
|
|
5683
|
-
</div>
|
|
5684
|
-
|
|
5685
|
-
<div *ngSwitchCase="'checkbox-group'" data-fd="form-viewer-chip-list" class="flex flex-wrap gap-2">
|
|
5686
|
-
<span
|
|
5687
|
-
*ngFor="let item of getDisplayList(field, getFieldValue(field)); trackBy: trackByIndex"
|
|
5688
|
-
data-fd="form-viewer-chip"
|
|
5689
|
-
class="rounded-full bg-slate-100 px-3 py-1 text-sm text-slate-700">
|
|
5690
|
-
{{ item }}
|
|
5691
|
-
</span>
|
|
5692
|
-
<span *ngIf="!getDisplayList(field, getFieldValue(field)).length" data-fd="form-viewer-field-value-empty" class="text-sm text-slate-400">
|
|
5693
|
-
{{ getEmptyValueLabel(field) }}
|
|
5694
|
-
</span>
|
|
5695
|
-
</div>
|
|
5696
|
-
|
|
5697
|
-
<div *ngSwitchCase="'file'" data-fd="form-viewer-file-list" class="space-y-2">
|
|
5698
|
-
<ng-container *ngIf="getUploadedFiles(getFieldValue(field)).length; else emptyFileState">
|
|
5699
|
-
<div
|
|
5700
|
-
*ngFor="let file of getUploadedFiles(getFieldValue(field)); trackBy: trackByUploadedFile"
|
|
5701
|
-
data-fd="form-viewer-file-item"
|
|
5702
|
-
class="flex items-center justify-between gap-3 rounded-lg border border-slate-200 bg-slate-50 px-3 py-2">
|
|
5703
|
-
<div class="min-w-0">
|
|
5704
|
-
<a
|
|
5705
|
-
*ngIf="file.url; else fileNameText"
|
|
5706
|
-
data-fd="form-viewer-file-link"
|
|
5707
|
-
[href]="file.url"
|
|
5708
|
-
target="_blank"
|
|
5709
|
-
rel="noopener noreferrer"
|
|
5710
|
-
class="block truncate text-sm font-medium text-sky-700 underline">
|
|
5711
|
-
{{ file.name || file.id || 'Uploaded file' }}
|
|
5712
|
-
</a>
|
|
5713
|
-
<ng-template #fileNameText>
|
|
5714
|
-
<div data-fd="form-viewer-file-name" class="truncate text-sm font-medium text-slate-900">
|
|
5715
|
-
{{ file.name || file.id || 'Uploaded file' }}
|
|
5716
|
-
</div>
|
|
5717
|
-
</ng-template>
|
|
5718
|
-
<div *ngIf="file.type" data-fd="form-viewer-file-type" class="text-xs text-slate-500">{{ file.type }}</div>
|
|
5719
|
-
</div>
|
|
5720
|
-
<div *ngIf="file.size != null" data-fd="form-viewer-file-size" class="text-xs text-slate-500">
|
|
5721
|
-
{{ formatFileSize(file.size) }}
|
|
5722
|
-
</div>
|
|
5723
|
-
</div>
|
|
5724
|
-
</ng-container>
|
|
5725
|
-
<ng-template #emptyFileState>
|
|
5726
|
-
<span data-fd="form-viewer-field-value-empty" class="text-sm text-slate-400">{{ getEmptyValueLabel(field) }}</span>
|
|
5727
|
-
</ng-template>
|
|
5728
|
-
</div>
|
|
5729
|
-
|
|
5730
|
-
<div *ngSwitchCase="'image'" data-fd="form-viewer-image" class="space-y-3">
|
|
5731
|
-
<ng-container *ngIf="getImageSource(field, getFieldValue(field)) as imageSrc; else emptyImageState">
|
|
5732
|
-
<img
|
|
5733
|
-
data-fd="form-viewer-image-element"
|
|
5734
|
-
[src]="imageSrc"
|
|
5735
|
-
[alt]="field.label || field.name"
|
|
5736
|
-
class="max-h-64 rounded-lg border border-slate-200 object-contain">
|
|
5737
|
-
</ng-container>
|
|
5738
|
-
<ng-template #emptyImageState>
|
|
5739
|
-
<span data-fd="form-viewer-field-value-empty" class="text-sm text-slate-400">{{ getEmptyValueLabel(field) }}</span>
|
|
5740
|
-
</ng-template>
|
|
5741
|
-
</div>
|
|
5742
|
-
|
|
5743
|
-
<div *ngSwitchCase="'repeatable-group'" data-fd="form-viewer-repeatable-group" class="space-y-3">
|
|
5744
|
-
<ng-container *ngIf="getRepeatableItems(getFieldValue(field)).length; else emptyRepeatableState">
|
|
5745
|
-
<section
|
|
5746
|
-
*ngFor="let item of getRepeatableItems(getFieldValue(field)); let index = index; trackBy: trackByIndex"
|
|
5747
|
-
data-fd="form-viewer-repeatable-item"
|
|
5748
|
-
class="rounded-lg border border-slate-200 bg-slate-50 px-3 py-3">
|
|
5749
|
-
<div data-fd="form-viewer-repeatable-item-title" class="mb-3 text-xs font-semibold uppercase tracking-wide text-slate-500">
|
|
5750
|
-
{{ getRepeatableItemTitle(field, index) }}
|
|
5751
|
-
</div>
|
|
5752
|
-
<dl class="grid gap-3 sm:grid-cols-2">
|
|
5753
|
-
<div
|
|
5754
|
-
*ngFor="let nestedField of getRepeatableFields(field); trackBy: trackByFieldId"
|
|
5755
|
-
data-fd="form-viewer-repeatable-field"
|
|
5756
|
-
class="rounded-md border border-slate-200 bg-white px-3 py-2">
|
|
5757
|
-
<dt data-fd="form-viewer-repeatable-field-label" class="text-xs font-medium uppercase tracking-wide text-slate-500">
|
|
5758
|
-
{{ getFieldLabel(nestedField) }}
|
|
5759
|
-
</dt>
|
|
5760
|
-
<dd data-fd="form-viewer-repeatable-field-value" class="mt-1 whitespace-pre-wrap text-sm text-slate-900">
|
|
5761
|
-
{{ formatScalarValue(getNestedFieldValue(item, nestedField)) }}
|
|
5762
|
-
</dd>
|
|
5763
|
-
</div>
|
|
5764
|
-
</dl>
|
|
5765
|
-
</section>
|
|
5766
|
-
</ng-container>
|
|
5767
|
-
<ng-template #emptyRepeatableState>
|
|
5768
|
-
<span data-fd="form-viewer-field-value-empty" class="text-sm text-slate-400">{{ getEmptyValueLabel(field) }}</span>
|
|
5769
|
-
</ng-template>
|
|
5770
|
-
</div>
|
|
5771
|
-
|
|
5772
|
-
<div *ngSwitchCase="'table'" data-fd="form-viewer-table-wrapper" class="overflow-x-auto rounded-lg border border-slate-200">
|
|
5773
|
-
<table data-fd="form-viewer-table" class="min-w-full divide-y divide-slate-200 text-sm">
|
|
5774
|
-
<thead data-fd="form-viewer-table-head" class="bg-slate-50">
|
|
5775
|
-
<tr>
|
|
5776
|
-
<th
|
|
5777
|
-
*ngFor="let column of getTableColumns(field, getFieldValue(field)); trackBy: trackByTableColumn"
|
|
5778
|
-
data-fd="form-viewer-table-header"
|
|
5779
|
-
class="px-3 py-2 text-left font-semibold text-slate-600">
|
|
5780
|
-
{{ column.label }}
|
|
5781
|
-
</th>
|
|
5782
|
-
</tr>
|
|
5783
|
-
</thead>
|
|
5784
|
-
<tbody data-fd="form-viewer-table-body" class="divide-y divide-slate-200 bg-white">
|
|
5785
|
-
<tr *ngFor="let row of getTableRows(getFieldValue(field)); trackBy: trackByIndex" data-fd="form-viewer-table-row">
|
|
5786
|
-
<td
|
|
5787
|
-
*ngFor="let column of getTableColumns(field, getFieldValue(field)); trackBy: trackByTableColumn"
|
|
5788
|
-
data-fd="form-viewer-table-cell"
|
|
5789
|
-
class="px-3 py-2 align-top text-slate-700">
|
|
5790
|
-
{{ formatScalarValue(readPathValue(row, column.key)) }}
|
|
5791
|
-
</td>
|
|
5792
|
-
</tr>
|
|
5793
|
-
<tr *ngIf="!getTableRows(getFieldValue(field)).length" data-fd="form-viewer-table-empty-row">
|
|
5794
|
-
<td data-fd="form-viewer-table-empty"
|
|
5795
|
-
class="px-3 py-3 text-slate-400"
|
|
5796
|
-
[attr.colspan]="getTableColumns(field, getFieldValue(field)).length || 1">
|
|
5797
|
-
{{ getEmptyValueLabel(field) }}
|
|
5798
|
-
</td>
|
|
5799
|
-
</tr>
|
|
5800
|
-
</tbody>
|
|
5801
|
-
</table>
|
|
5802
|
-
</div>
|
|
5803
|
-
|
|
5804
|
-
<div *ngSwitchDefault data-fd="form-viewer-field-value" class="whitespace-pre-wrap text-sm leading-6 text-slate-900">
|
|
5805
|
-
{{ formatFieldValue(field, getFieldValue(field)) }}
|
|
5806
|
-
</div>
|
|
5807
|
-
</ng-container>
|
|
5808
|
-
</div>
|
|
5809
|
-
</ng-container>
|
|
5810
|
-
</div>
|
|
5811
|
-
</ng-container>
|
|
5812
|
-
</ng-container>
|
|
5813
|
-
</ng-container>
|
|
5814
|
-
</ng-template>
|
|
5815
|
-
`
|
|
5816
|
-
}]
|
|
5817
|
-
}], propDecorators: { schema: [{
|
|
5818
|
-
type: Input,
|
|
5819
|
-
args: [{ required: true }]
|
|
5820
|
-
}], values: [{
|
|
5821
|
-
type: Input
|
|
5822
|
-
}], breakpoint: [{
|
|
5823
|
-
type: Input
|
|
5824
|
-
}] } });
|
|
5825
|
-
|
|
5826
4969
|
class FormViewerComponent {
|
|
5827
4970
|
schema;
|
|
5828
4971
|
set data(value) {
|
|
@@ -5993,34 +5136,25 @@ class FormViewerComponent {
|
|
|
5993
5136
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: FormViewerComponent, isStandalone: true, selector: "app-form-viewer", inputs: { schema: "schema", data: "data", options: "options", viewOnly: "viewOnly", eventApis: "eventApis", eventApiExecutor: "eventApiExecutor", fieldDataAccessMap: "fieldDataAccessMap", fieldDataAccessApi: "fieldDataAccessApi", formContentId: "formContentId", formContentVersion: "formContentVersion" }, outputs: { formDataChange: "formDataChange", formValidationChange: "formValidationChange", uploadedFilesChange: "uploadedFilesChange", submit: "submit" }, viewQueries: [{ propertyName: "renderer", first: true, predicate: JsonFormRendererComponent, descendants: true }], ngImport: i0, template: `
|
|
5994
5137
|
<div class="form-viewer-container flex flex-col h-full"
|
|
5995
5138
|
data-fd="form-viewer"
|
|
5996
|
-
[attr.data-fd-mode]="viewOnly ? '
|
|
5997
|
-
<div class="flex-1 min-h-0
|
|
5998
|
-
<app-form-
|
|
5999
|
-
*ngIf="viewOnly; else liveRenderer"
|
|
5139
|
+
[attr.data-fd-mode]="viewOnly ? 'preview' : 'live'">
|
|
5140
|
+
<div class="flex-1 min-h-0" data-fd="form-viewer-surface">
|
|
5141
|
+
<app-json-form-renderer
|
|
6000
5142
|
[schema]="schema"
|
|
6001
|
-
[
|
|
6002
|
-
[
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
|
|
6009
|
-
|
|
6010
|
-
|
|
6011
|
-
|
|
6012
|
-
|
|
6013
|
-
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
[formContentId]="formContentId"
|
|
6017
|
-
[formContentVersion]="formContentVersion"
|
|
6018
|
-
(valueChange)="onValueChange($event)"
|
|
6019
|
-
(validationChange)="onValidationChange($event)"
|
|
6020
|
-
(uploadedFilesChange)="onUploadedFilesChange($event)"
|
|
6021
|
-
(formSubmit)="onRendererSubmit($event)">
|
|
6022
|
-
</app-json-form-renderer>
|
|
6023
|
-
</ng-template>
|
|
5143
|
+
[initialValues]="normalizedInitialValues"
|
|
5144
|
+
[mode]="viewOnly ? 'preview' : 'live'"
|
|
5145
|
+
[breakpoint]="breakpoint()"
|
|
5146
|
+
[uploadOnSubmit]="true"
|
|
5147
|
+
[eventApis]="eventApis"
|
|
5148
|
+
[eventApiExecutor]="eventApiExecutor"
|
|
5149
|
+
[fieldDataAccessMap]="fieldDataAccessMap"
|
|
5150
|
+
[fieldDataAccessApi]="fieldDataAccessApi"
|
|
5151
|
+
[formContentId]="formContentId"
|
|
5152
|
+
[formContentVersion]="formContentVersion"
|
|
5153
|
+
(valueChange)="onValueChange($event)"
|
|
5154
|
+
(validationChange)="onValidationChange($event)"
|
|
5155
|
+
(uploadedFilesChange)="onUploadedFilesChange($event)"
|
|
5156
|
+
(formSubmit)="onRendererSubmit($event)">
|
|
5157
|
+
</app-json-form-renderer>
|
|
6024
5158
|
</div>
|
|
6025
5159
|
|
|
6026
5160
|
<div *ngIf="!viewOnly && options.showSubmitButton"
|
|
@@ -6035,41 +5169,32 @@ class FormViewerComponent {
|
|
|
6035
5169
|
</button>
|
|
6036
5170
|
</div>
|
|
6037
5171
|
</div>
|
|
6038
|
-
`, isInline: true, styles: [":host{display:block;height:100%;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: JsonFormRendererComponent, selector: "app-json-form-renderer", inputs: ["schema", "initialValues", "mode", "device", "breakpoint", "eventLogger", "eventApis", "eventApiExecutor", "uploadOnSubmit", "fieldDataAccessMap", "fieldDataAccessApi", "formContentId", "formContentVersion"], outputs: ["valueChange", "groupedValueChange", "combinedValueChange", "validationChange", "uploadedFilesChange", "formSubmit"] }
|
|
5172
|
+
`, isInline: true, styles: [":host{display:block;height:100%;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: JsonFormRendererComponent, selector: "app-json-form-renderer", inputs: ["schema", "initialValues", "mode", "device", "breakpoint", "eventLogger", "eventApis", "eventApiExecutor", "uploadOnSubmit", "fieldDataAccessMap", "fieldDataAccessApi", "formContentId", "formContentVersion"], outputs: ["valueChange", "groupedValueChange", "combinedValueChange", "validationChange", "uploadedFilesChange", "formSubmit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
6039
5173
|
}
|
|
6040
5174
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FormViewerComponent, decorators: [{
|
|
6041
5175
|
type: Component,
|
|
6042
|
-
args: [{ selector: 'app-form-viewer', standalone: true, imports: [CommonModule, JsonFormRendererComponent
|
|
5176
|
+
args: [{ selector: 'app-form-viewer', standalone: true, imports: [CommonModule, JsonFormRendererComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
6043
5177
|
<div class="form-viewer-container flex flex-col h-full"
|
|
6044
5178
|
data-fd="form-viewer"
|
|
6045
|
-
[attr.data-fd-mode]="viewOnly ? '
|
|
6046
|
-
<div class="flex-1 min-h-0
|
|
6047
|
-
<app-form-
|
|
6048
|
-
*ngIf="viewOnly; else liveRenderer"
|
|
5179
|
+
[attr.data-fd-mode]="viewOnly ? 'preview' : 'live'">
|
|
5180
|
+
<div class="flex-1 min-h-0" data-fd="form-viewer-surface">
|
|
5181
|
+
<app-json-form-renderer
|
|
6049
5182
|
[schema]="schema"
|
|
6050
|
-
[
|
|
6051
|
-
[
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
6064
|
-
|
|
6065
|
-
[formContentId]="formContentId"
|
|
6066
|
-
[formContentVersion]="formContentVersion"
|
|
6067
|
-
(valueChange)="onValueChange($event)"
|
|
6068
|
-
(validationChange)="onValidationChange($event)"
|
|
6069
|
-
(uploadedFilesChange)="onUploadedFilesChange($event)"
|
|
6070
|
-
(formSubmit)="onRendererSubmit($event)">
|
|
6071
|
-
</app-json-form-renderer>
|
|
6072
|
-
</ng-template>
|
|
5183
|
+
[initialValues]="normalizedInitialValues"
|
|
5184
|
+
[mode]="viewOnly ? 'preview' : 'live'"
|
|
5185
|
+
[breakpoint]="breakpoint()"
|
|
5186
|
+
[uploadOnSubmit]="true"
|
|
5187
|
+
[eventApis]="eventApis"
|
|
5188
|
+
[eventApiExecutor]="eventApiExecutor"
|
|
5189
|
+
[fieldDataAccessMap]="fieldDataAccessMap"
|
|
5190
|
+
[fieldDataAccessApi]="fieldDataAccessApi"
|
|
5191
|
+
[formContentId]="formContentId"
|
|
5192
|
+
[formContentVersion]="formContentVersion"
|
|
5193
|
+
(valueChange)="onValueChange($event)"
|
|
5194
|
+
(validationChange)="onValidationChange($event)"
|
|
5195
|
+
(uploadedFilesChange)="onUploadedFilesChange($event)"
|
|
5196
|
+
(formSubmit)="onRendererSubmit($event)">
|
|
5197
|
+
</app-json-form-renderer>
|
|
6073
5198
|
</div>
|
|
6074
5199
|
|
|
6075
5200
|
<div *ngIf="!viewOnly && options.showSubmitButton"
|
|
@@ -7322,6 +6447,101 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
7322
6447
|
args: [WIDGET_DEFINITIONS]
|
|
7323
6448
|
}] }, { type: DesignerStateService }] });
|
|
7324
6449
|
|
|
6450
|
+
class MonacoEditorComponent {
|
|
6451
|
+
value = input('');
|
|
6452
|
+
language = input('html');
|
|
6453
|
+
theme = input('vs');
|
|
6454
|
+
readOnly = input(false);
|
|
6455
|
+
minimap = input(false);
|
|
6456
|
+
options = input(null);
|
|
6457
|
+
valueChange = output();
|
|
6458
|
+
containerRef;
|
|
6459
|
+
static configured = false;
|
|
6460
|
+
monaco;
|
|
6461
|
+
editor;
|
|
6462
|
+
suppressChange = false;
|
|
6463
|
+
subscriptions = [];
|
|
6464
|
+
resizeObserver;
|
|
6465
|
+
editorReady = signal(false);
|
|
6466
|
+
syncInputs = effect(() => {
|
|
6467
|
+
if (!this.editorReady())
|
|
6468
|
+
return;
|
|
6469
|
+
if (!this.editor || !this.monaco)
|
|
6470
|
+
return;
|
|
6471
|
+
const nextValue = this.value();
|
|
6472
|
+
if (this.editor.getValue() !== nextValue) {
|
|
6473
|
+
this.suppressChange = true;
|
|
6474
|
+
this.editor.setValue(nextValue ?? '');
|
|
6475
|
+
this.suppressChange = false;
|
|
6476
|
+
}
|
|
6477
|
+
const model = this.editor.getModel();
|
|
6478
|
+
if (model) {
|
|
6479
|
+
this.monaco.editor.setModelLanguage(model, this.language());
|
|
6480
|
+
}
|
|
6481
|
+
this.monaco.editor.setTheme(this.theme());
|
|
6482
|
+
const options = this.options() ?? {};
|
|
6483
|
+
this.editor.updateOptions({
|
|
6484
|
+
...options,
|
|
6485
|
+
readOnly: this.readOnly(),
|
|
6486
|
+
minimap: { enabled: this.minimap() }
|
|
6487
|
+
});
|
|
6488
|
+
});
|
|
6489
|
+
async ngAfterViewInit() {
|
|
6490
|
+
if (!MonacoEditorComponent.configured) {
|
|
6491
|
+
loader.config({
|
|
6492
|
+
paths: { vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.45.0/min/vs' }
|
|
6493
|
+
});
|
|
6494
|
+
MonacoEditorComponent.configured = true;
|
|
6495
|
+
}
|
|
6496
|
+
this.monaco = (await loader.init());
|
|
6497
|
+
this.editor = this.monaco.editor.create(this.containerRef.nativeElement, {
|
|
6498
|
+
value: this.value() ?? '',
|
|
6499
|
+
language: this.language(),
|
|
6500
|
+
theme: this.theme(),
|
|
6501
|
+
readOnly: this.readOnly(),
|
|
6502
|
+
minimap: { enabled: this.minimap() },
|
|
6503
|
+
automaticLayout: false,
|
|
6504
|
+
...(this.options() ?? {})
|
|
6505
|
+
});
|
|
6506
|
+
const model = this.editor.getModel();
|
|
6507
|
+
if (model && this.language()) {
|
|
6508
|
+
this.monaco.editor.setModelLanguage(model, this.language());
|
|
6509
|
+
}
|
|
6510
|
+
this.subscriptions.push(this.editor.onDidChangeModelContent(() => {
|
|
6511
|
+
if (this.suppressChange)
|
|
6512
|
+
return;
|
|
6513
|
+
this.valueChange.emit(this.editor?.getValue() ?? '');
|
|
6514
|
+
}));
|
|
6515
|
+
if (typeof ResizeObserver !== 'undefined') {
|
|
6516
|
+
this.resizeObserver = new ResizeObserver(() => this.editor?.layout());
|
|
6517
|
+
this.resizeObserver.observe(this.containerRef.nativeElement);
|
|
6518
|
+
}
|
|
6519
|
+
this.editorReady.set(true);
|
|
6520
|
+
}
|
|
6521
|
+
ngOnDestroy() {
|
|
6522
|
+
this.resizeObserver?.disconnect();
|
|
6523
|
+
this.subscriptions.forEach(subscription => subscription.dispose());
|
|
6524
|
+
this.subscriptions = [];
|
|
6525
|
+
this.editor?.dispose();
|
|
6526
|
+
this.editor = undefined;
|
|
6527
|
+
}
|
|
6528
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: MonacoEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6529
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.17", type: MonacoEditorComponent, isStandalone: true, selector: "app-monaco-editor", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, language: { classPropertyName: "language", publicName: "language", isSignal: true, isRequired: false, transformFunction: null }, theme: { classPropertyName: "theme", publicName: "theme", isSignal: true, isRequired: false, transformFunction: null }, readOnly: { classPropertyName: "readOnly", publicName: "readOnly", isSignal: true, isRequired: false, transformFunction: null }, minimap: { classPropertyName: "minimap", publicName: "minimap", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, host: { classAttribute: "block h-full w-full" }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true, static: true }], ngImport: i0, template: `<div class="h-full w-full" #container></div>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
6530
|
+
}
|
|
6531
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: MonacoEditorComponent, decorators: [{
|
|
6532
|
+
type: Component,
|
|
6533
|
+
args: [{
|
|
6534
|
+
selector: 'app-monaco-editor',
|
|
6535
|
+
standalone: true,
|
|
6536
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
6537
|
+
template: `<div class="h-full w-full" #container></div>`,
|
|
6538
|
+
host: { class: 'block h-full w-full' }
|
|
6539
|
+
}]
|
|
6540
|
+
}], propDecorators: { containerRef: [{
|
|
6541
|
+
type: ViewChild,
|
|
6542
|
+
args: ['container', { static: true }]
|
|
6543
|
+
}] } });
|
|
6544
|
+
|
|
7325
6545
|
const DEFAULT_PAGE_STYLE = {
|
|
7326
6546
|
paddingTop: 32,
|
|
7327
6547
|
paddingRight: 32,
|
|
@@ -7347,6 +6567,15 @@ class LayoutCanvasComponent {
|
|
|
7347
6567
|
get device() { return this.state.activeDevice(); } // 'mobile' | 'desktop' for basic passing
|
|
7348
6568
|
get breakpoint() { return this.state.activeBreakpoint(); }
|
|
7349
6569
|
zoom = signal(1);
|
|
6570
|
+
showLiveSchemaEditor = signal(false);
|
|
6571
|
+
liveSchemaEditorText = signal('');
|
|
6572
|
+
liveSchemaEditorError = signal('');
|
|
6573
|
+
liveSchemaEditorOptions = {
|
|
6574
|
+
fontSize: 12,
|
|
6575
|
+
lineNumbersMinChars: 3,
|
|
6576
|
+
wordWrap: 'on',
|
|
6577
|
+
scrollBeyondLastLine: false
|
|
6578
|
+
};
|
|
7350
6579
|
pageBaseSize = signal({ width: 0, height: 0 });
|
|
7351
6580
|
minZoom = 0.25;
|
|
7352
6581
|
maxZoom = 3;
|
|
@@ -7504,6 +6733,34 @@ class LayoutCanvasComponent {
|
|
|
7504
6733
|
}
|
|
7505
6734
|
this.state.isPreviewMode.set(true);
|
|
7506
6735
|
}
|
|
6736
|
+
toggleLiveSchemaEditor() {
|
|
6737
|
+
if (this.showLiveSchemaEditor()) {
|
|
6738
|
+
this.closeLiveSchemaEditor();
|
|
6739
|
+
return;
|
|
6740
|
+
}
|
|
6741
|
+
this.liveSchemaEditorText.set(serializeSchema(this.state.schema()));
|
|
6742
|
+
this.liveSchemaEditorError.set('');
|
|
6743
|
+
this.showLiveSchemaEditor.set(true);
|
|
6744
|
+
}
|
|
6745
|
+
closeLiveSchemaEditor() {
|
|
6746
|
+
this.showLiveSchemaEditor.set(false);
|
|
6747
|
+
}
|
|
6748
|
+
onLiveSchemaEditorTextChange(nextText) {
|
|
6749
|
+
this.liveSchemaEditorText.set(nextText);
|
|
6750
|
+
if (this.state.isReadOnly()) {
|
|
6751
|
+
this.liveSchemaEditorError.set('');
|
|
6752
|
+
return;
|
|
6753
|
+
}
|
|
6754
|
+
try {
|
|
6755
|
+
const parsedSchema = parseSchema(nextText);
|
|
6756
|
+
this.state.updateSchema(parsedSchema);
|
|
6757
|
+
this.state.selectNode(null);
|
|
6758
|
+
this.liveSchemaEditorError.set('');
|
|
6759
|
+
}
|
|
6760
|
+
catch {
|
|
6761
|
+
this.liveSchemaEditorError.set('Invalid JSON schema. Changes are not applied until the JSON is valid.');
|
|
6762
|
+
}
|
|
6763
|
+
}
|
|
7507
6764
|
getCanvasWidth() {
|
|
7508
6765
|
const bp = this.breakpoint;
|
|
7509
6766
|
switch (bp) {
|
|
@@ -7785,6 +7042,12 @@ class LayoutCanvasComponent {
|
|
|
7785
7042
|
<span class="text-[12px] leading-none">Preview</span>
|
|
7786
7043
|
</button>
|
|
7787
7044
|
|
|
7045
|
+
<button class="inline-flex h-7 w-7 items-center justify-center rounded-[4px] border border-transparent transition-colors hover:border-border-default hover:bg-slate-50"
|
|
7046
|
+
(click)="toggleLiveSchemaEditor(); $event.stopPropagation()"
|
|
7047
|
+
title="Live JSON schema editor"
|
|
7048
|
+
aria-label="Live JSON schema editor">
|
|
7049
|
+
<lucide-icon name="braces" class="w-3.5 h-3.5"></lucide-icon>
|
|
7050
|
+
</button>
|
|
7788
7051
|
<button class="inline-flex h-7 w-7 items-center justify-center rounded-[4px] border border-transparent transition-colors hover:border-border-default hover:bg-slate-50"
|
|
7789
7052
|
(click)="exportJson(); $event.stopPropagation()" title="Export JSON">
|
|
7790
7053
|
<lucide-icon name="download" class="w-3.5 h-3.5"></lucide-icon>
|
|
@@ -7891,15 +7154,53 @@ class LayoutCanvasComponent {
|
|
|
7891
7154
|
<lucide-icon *ngIf="!last" name="chevron-right" class="w-3 h-3 text-ink-600"></lucide-icon>
|
|
7892
7155
|
</ng-container>
|
|
7893
7156
|
</div>
|
|
7157
|
+
|
|
7158
|
+
<div *ngIf="showLiveSchemaEditor()"
|
|
7159
|
+
data-testid="live-schema-editor-panel"
|
|
7160
|
+
class="absolute inset-0 z-[70] flex items-center justify-center bg-black/20 p-4 backdrop-blur-[1px]"
|
|
7161
|
+
(click)="closeLiveSchemaEditor()">
|
|
7162
|
+
<section class="h-full w-full max-w-5xl overflow-hidden rounded-[6px] border border-border-default bg-surface-default shadow-popover"
|
|
7163
|
+
(click)="$event.stopPropagation()">
|
|
7164
|
+
<header class="flex items-center justify-between border-b border-border-default px-4 py-2.5">
|
|
7165
|
+
<div class="flex flex-col">
|
|
7166
|
+
<h3 class="text-[13px] font-semibold text-text-strong">Live JSON Schema Editor</h3>
|
|
7167
|
+
<p class="text-[11px] text-text-primary/80">Changes apply instantly when JSON is valid.</p>
|
|
7168
|
+
</div>
|
|
7169
|
+
<button type="button"
|
|
7170
|
+
class="inline-flex h-8 w-8 items-center justify-center rounded-[4px] border border-border-default text-text-primary transition-colors hover:bg-slate-50"
|
|
7171
|
+
aria-label="Close live schema editor"
|
|
7172
|
+
(click)="closeLiveSchemaEditor()">
|
|
7173
|
+
<lucide-icon name="x" class="h-4 w-4"></lucide-icon>
|
|
7174
|
+
</button>
|
|
7175
|
+
</header>
|
|
7176
|
+
|
|
7177
|
+
<div *ngIf="liveSchemaEditorError()"
|
|
7178
|
+
class="border-b border-red-200 bg-red-50 px-4 py-2 text-[11px] text-red-700">
|
|
7179
|
+
{{ liveSchemaEditorError() }}
|
|
7180
|
+
</div>
|
|
7181
|
+
|
|
7182
|
+
<div class="h-[calc(100%-56px)] min-h-0">
|
|
7183
|
+
<app-monaco-editor
|
|
7184
|
+
class="h-full"
|
|
7185
|
+
[value]="liveSchemaEditorText()"
|
|
7186
|
+
language="json"
|
|
7187
|
+
theme="vs"
|
|
7188
|
+
[readOnly]="state.isReadOnly()"
|
|
7189
|
+
[options]="liveSchemaEditorOptions"
|
|
7190
|
+
(valueChange)="onLiveSchemaEditorTextChange($event)">
|
|
7191
|
+
</app-monaco-editor>
|
|
7192
|
+
</div>
|
|
7193
|
+
</section>
|
|
7194
|
+
</div>
|
|
7894
7195
|
</div>
|
|
7895
7196
|
|
|
7896
7197
|
<!-- Hidden file input for import -->
|
|
7897
7198
|
<input type="file" #fileInput accept=".json" (change)="onFileSelected($event)" style="display: none;">
|
|
7898
|
-
`, isInline: true, styles: [".canvas-grid{background-image:radial-gradient(rgba(148,163,184,.35) 1px,transparent 1px);background-size:18px 18px}.custom-scrollbar::-webkit-scrollbar{width:6px;height:6px}.custom-scrollbar::-webkit-scrollbar-track{background:transparent}.custom-scrollbar::-webkit-scrollbar-thumb{background:transparent;border-radius:10px}.custom-scrollbar:hover::-webkit-scrollbar-thumb{background:#00000026}.custom-scrollbar{scrollbar-width:thin;scrollbar-color:transparent transparent}.custom-scrollbar:hover{scrollbar-color:rgba(0,0,0,.15) transparent}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: JsonFormRendererComponent, selector: "app-json-form-renderer", inputs: ["schema", "initialValues", "mode", "device", "breakpoint", "eventLogger", "eventApis", "eventApiExecutor", "uploadOnSubmit", "fieldDataAccessMap", "fieldDataAccessApi", "formContentId", "formContentVersion"], outputs: ["valueChange", "groupedValueChange", "combinedValueChange", "validationChange", "uploadedFilesChange", "formSubmit"] }, { kind: "ngmodule", type: UiIconModule }, { kind: "component", type: i3$1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }] });
|
|
7199
|
+
`, isInline: true, styles: [".canvas-grid{background-image:radial-gradient(rgba(148,163,184,.35) 1px,transparent 1px);background-size:18px 18px}.custom-scrollbar::-webkit-scrollbar{width:6px;height:6px}.custom-scrollbar::-webkit-scrollbar-track{background:transparent}.custom-scrollbar::-webkit-scrollbar-thumb{background:transparent;border-radius:10px}.custom-scrollbar:hover::-webkit-scrollbar-thumb{background:#00000026}.custom-scrollbar{scrollbar-width:thin;scrollbar-color:transparent transparent}.custom-scrollbar:hover{scrollbar-color:rgba(0,0,0,.15) transparent}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: JsonFormRendererComponent, selector: "app-json-form-renderer", inputs: ["schema", "initialValues", "mode", "device", "breakpoint", "eventLogger", "eventApis", "eventApiExecutor", "uploadOnSubmit", "fieldDataAccessMap", "fieldDataAccessApi", "formContentId", "formContentVersion"], outputs: ["valueChange", "groupedValueChange", "combinedValueChange", "validationChange", "uploadedFilesChange", "formSubmit"] }, { kind: "ngmodule", type: UiIconModule }, { kind: "component", type: i3$1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }, { kind: "component", type: MonacoEditorComponent, selector: "app-monaco-editor", inputs: ["value", "language", "theme", "readOnly", "minimap", "options"], outputs: ["valueChange"] }] });
|
|
7899
7200
|
}
|
|
7900
7201
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: LayoutCanvasComponent, decorators: [{
|
|
7901
7202
|
type: Component,
|
|
7902
|
-
args: [{ selector: 'app-layout-canvas', standalone: true, imports: [CommonModule, JsonFormRendererComponent, UiIconModule], template: `
|
|
7203
|
+
args: [{ selector: 'app-layout-canvas', standalone: true, imports: [CommonModule, JsonFormRendererComponent, UiIconModule, MonacoEditorComponent], template: `
|
|
7903
7204
|
<div #root class="h-full w-full relative font-sans">
|
|
7904
7205
|
<!-- Floating Toolbar (fixed to canvas viewport; unaffected by pan/zoom) -->
|
|
7905
7206
|
<div class="absolute top-4 left-1/2 -translate-x-1/2 z-40">
|
|
@@ -7974,6 +7275,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
7974
7275
|
<span class="text-[12px] leading-none">Preview</span>
|
|
7975
7276
|
</button>
|
|
7976
7277
|
|
|
7278
|
+
<button class="inline-flex h-7 w-7 items-center justify-center rounded-[4px] border border-transparent transition-colors hover:border-border-default hover:bg-slate-50"
|
|
7279
|
+
(click)="toggleLiveSchemaEditor(); $event.stopPropagation()"
|
|
7280
|
+
title="Live JSON schema editor"
|
|
7281
|
+
aria-label="Live JSON schema editor">
|
|
7282
|
+
<lucide-icon name="braces" class="w-3.5 h-3.5"></lucide-icon>
|
|
7283
|
+
</button>
|
|
7977
7284
|
<button class="inline-flex h-7 w-7 items-center justify-center rounded-[4px] border border-transparent transition-colors hover:border-border-default hover:bg-slate-50"
|
|
7978
7285
|
(click)="exportJson(); $event.stopPropagation()" title="Export JSON">
|
|
7979
7286
|
<lucide-icon name="download" class="w-3.5 h-3.5"></lucide-icon>
|
|
@@ -8080,6 +7387,44 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
8080
7387
|
<lucide-icon *ngIf="!last" name="chevron-right" class="w-3 h-3 text-ink-600"></lucide-icon>
|
|
8081
7388
|
</ng-container>
|
|
8082
7389
|
</div>
|
|
7390
|
+
|
|
7391
|
+
<div *ngIf="showLiveSchemaEditor()"
|
|
7392
|
+
data-testid="live-schema-editor-panel"
|
|
7393
|
+
class="absolute inset-0 z-[70] flex items-center justify-center bg-black/20 p-4 backdrop-blur-[1px]"
|
|
7394
|
+
(click)="closeLiveSchemaEditor()">
|
|
7395
|
+
<section class="h-full w-full max-w-5xl overflow-hidden rounded-[6px] border border-border-default bg-surface-default shadow-popover"
|
|
7396
|
+
(click)="$event.stopPropagation()">
|
|
7397
|
+
<header class="flex items-center justify-between border-b border-border-default px-4 py-2.5">
|
|
7398
|
+
<div class="flex flex-col">
|
|
7399
|
+
<h3 class="text-[13px] font-semibold text-text-strong">Live JSON Schema Editor</h3>
|
|
7400
|
+
<p class="text-[11px] text-text-primary/80">Changes apply instantly when JSON is valid.</p>
|
|
7401
|
+
</div>
|
|
7402
|
+
<button type="button"
|
|
7403
|
+
class="inline-flex h-8 w-8 items-center justify-center rounded-[4px] border border-border-default text-text-primary transition-colors hover:bg-slate-50"
|
|
7404
|
+
aria-label="Close live schema editor"
|
|
7405
|
+
(click)="closeLiveSchemaEditor()">
|
|
7406
|
+
<lucide-icon name="x" class="h-4 w-4"></lucide-icon>
|
|
7407
|
+
</button>
|
|
7408
|
+
</header>
|
|
7409
|
+
|
|
7410
|
+
<div *ngIf="liveSchemaEditorError()"
|
|
7411
|
+
class="border-b border-red-200 bg-red-50 px-4 py-2 text-[11px] text-red-700">
|
|
7412
|
+
{{ liveSchemaEditorError() }}
|
|
7413
|
+
</div>
|
|
7414
|
+
|
|
7415
|
+
<div class="h-[calc(100%-56px)] min-h-0">
|
|
7416
|
+
<app-monaco-editor
|
|
7417
|
+
class="h-full"
|
|
7418
|
+
[value]="liveSchemaEditorText()"
|
|
7419
|
+
language="json"
|
|
7420
|
+
theme="vs"
|
|
7421
|
+
[readOnly]="state.isReadOnly()"
|
|
7422
|
+
[options]="liveSchemaEditorOptions"
|
|
7423
|
+
(valueChange)="onLiveSchemaEditorTextChange($event)">
|
|
7424
|
+
</app-monaco-editor>
|
|
7425
|
+
</div>
|
|
7426
|
+
</section>
|
|
7427
|
+
</div>
|
|
8083
7428
|
</div>
|
|
8084
7429
|
|
|
8085
7430
|
<!-- Hidden file input for import -->
|
|
@@ -25973,101 +25318,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
25973
25318
|
args: ['projectFileInput']
|
|
25974
25319
|
}] } });
|
|
25975
25320
|
|
|
25976
|
-
class MonacoEditorComponent {
|
|
25977
|
-
value = input('');
|
|
25978
|
-
language = input('html');
|
|
25979
|
-
theme = input('vs');
|
|
25980
|
-
readOnly = input(false);
|
|
25981
|
-
minimap = input(false);
|
|
25982
|
-
options = input(null);
|
|
25983
|
-
valueChange = output();
|
|
25984
|
-
containerRef;
|
|
25985
|
-
static configured = false;
|
|
25986
|
-
monaco;
|
|
25987
|
-
editor;
|
|
25988
|
-
suppressChange = false;
|
|
25989
|
-
subscriptions = [];
|
|
25990
|
-
resizeObserver;
|
|
25991
|
-
editorReady = signal(false);
|
|
25992
|
-
syncInputs = effect(() => {
|
|
25993
|
-
if (!this.editorReady())
|
|
25994
|
-
return;
|
|
25995
|
-
if (!this.editor || !this.monaco)
|
|
25996
|
-
return;
|
|
25997
|
-
const nextValue = this.value();
|
|
25998
|
-
if (this.editor.getValue() !== nextValue) {
|
|
25999
|
-
this.suppressChange = true;
|
|
26000
|
-
this.editor.setValue(nextValue ?? '');
|
|
26001
|
-
this.suppressChange = false;
|
|
26002
|
-
}
|
|
26003
|
-
const model = this.editor.getModel();
|
|
26004
|
-
if (model) {
|
|
26005
|
-
this.monaco.editor.setModelLanguage(model, this.language());
|
|
26006
|
-
}
|
|
26007
|
-
this.monaco.editor.setTheme(this.theme());
|
|
26008
|
-
const options = this.options() ?? {};
|
|
26009
|
-
this.editor.updateOptions({
|
|
26010
|
-
...options,
|
|
26011
|
-
readOnly: this.readOnly(),
|
|
26012
|
-
minimap: { enabled: this.minimap() }
|
|
26013
|
-
});
|
|
26014
|
-
});
|
|
26015
|
-
async ngAfterViewInit() {
|
|
26016
|
-
if (!MonacoEditorComponent.configured) {
|
|
26017
|
-
loader.config({
|
|
26018
|
-
paths: { vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.45.0/min/vs' }
|
|
26019
|
-
});
|
|
26020
|
-
MonacoEditorComponent.configured = true;
|
|
26021
|
-
}
|
|
26022
|
-
this.monaco = (await loader.init());
|
|
26023
|
-
this.editor = this.monaco.editor.create(this.containerRef.nativeElement, {
|
|
26024
|
-
value: this.value() ?? '',
|
|
26025
|
-
language: this.language(),
|
|
26026
|
-
theme: this.theme(),
|
|
26027
|
-
readOnly: this.readOnly(),
|
|
26028
|
-
minimap: { enabled: this.minimap() },
|
|
26029
|
-
automaticLayout: false,
|
|
26030
|
-
...(this.options() ?? {})
|
|
26031
|
-
});
|
|
26032
|
-
const model = this.editor.getModel();
|
|
26033
|
-
if (model && this.language()) {
|
|
26034
|
-
this.monaco.editor.setModelLanguage(model, this.language());
|
|
26035
|
-
}
|
|
26036
|
-
this.subscriptions.push(this.editor.onDidChangeModelContent(() => {
|
|
26037
|
-
if (this.suppressChange)
|
|
26038
|
-
return;
|
|
26039
|
-
this.valueChange.emit(this.editor?.getValue() ?? '');
|
|
26040
|
-
}));
|
|
26041
|
-
if (typeof ResizeObserver !== 'undefined') {
|
|
26042
|
-
this.resizeObserver = new ResizeObserver(() => this.editor?.layout());
|
|
26043
|
-
this.resizeObserver.observe(this.containerRef.nativeElement);
|
|
26044
|
-
}
|
|
26045
|
-
this.editorReady.set(true);
|
|
26046
|
-
}
|
|
26047
|
-
ngOnDestroy() {
|
|
26048
|
-
this.resizeObserver?.disconnect();
|
|
26049
|
-
this.subscriptions.forEach(subscription => subscription.dispose());
|
|
26050
|
-
this.subscriptions = [];
|
|
26051
|
-
this.editor?.dispose();
|
|
26052
|
-
this.editor = undefined;
|
|
26053
|
-
}
|
|
26054
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: MonacoEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
26055
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.17", type: MonacoEditorComponent, isStandalone: true, selector: "app-monaco-editor", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, language: { classPropertyName: "language", publicName: "language", isSignal: true, isRequired: false, transformFunction: null }, theme: { classPropertyName: "theme", publicName: "theme", isSignal: true, isRequired: false, transformFunction: null }, readOnly: { classPropertyName: "readOnly", publicName: "readOnly", isSignal: true, isRequired: false, transformFunction: null }, minimap: { classPropertyName: "minimap", publicName: "minimap", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, host: { classAttribute: "block h-full w-full" }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true, static: true }], ngImport: i0, template: `<div class="h-full w-full" #container></div>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
26056
|
-
}
|
|
26057
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: MonacoEditorComponent, decorators: [{
|
|
26058
|
-
type: Component,
|
|
26059
|
-
args: [{
|
|
26060
|
-
selector: 'app-monaco-editor',
|
|
26061
|
-
standalone: true,
|
|
26062
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
26063
|
-
template: `<div class="h-full w-full" #container></div>`,
|
|
26064
|
-
host: { class: 'block h-full w-full' }
|
|
26065
|
-
}]
|
|
26066
|
-
}], propDecorators: { containerRef: [{
|
|
26067
|
-
type: ViewChild,
|
|
26068
|
-
args: ['container', { static: true }]
|
|
26069
|
-
}] } });
|
|
26070
|
-
|
|
26071
25321
|
/// <reference path="../../json-editor.d.ts" />
|
|
26072
25322
|
const FD_JSON_EDITOR_ICONLIB = 'fdlucide';
|
|
26073
25323
|
function ensureFdIconLib(jsonEditorCtor) {
|
|
@@ -28084,6 +27334,9 @@ class DefaultDataProvider extends DataProvider {
|
|
|
28084
27334
|
return super.queryOptions(field, { ...query, term: query.term || '' }, engine);
|
|
28085
27335
|
}
|
|
28086
27336
|
if (cfg.type === 'source' || cfg.type === 'global' || cfg.type === 'api') {
|
|
27337
|
+
if (this.shouldSuppressRemoteAccess(cfg, engine)) {
|
|
27338
|
+
return [];
|
|
27339
|
+
}
|
|
28087
27340
|
if (!cfg.datasourceId)
|
|
28088
27341
|
return [];
|
|
28089
27342
|
const filters = this.resolveFilters(cfg, engine);
|
|
@@ -28135,6 +27388,9 @@ class DefaultDataProvider extends DataProvider {
|
|
|
28135
27388
|
// Determine if source-backed
|
|
28136
27389
|
const isSource = cfg.type === 'source' || cfg.type === 'global' || (cfg.type === 'api' && !!cfg.datasourceId);
|
|
28137
27390
|
if (isSource && cfg.datasourceId) {
|
|
27391
|
+
if (this.shouldSuppressRemoteAccess(cfg, engine)) {
|
|
27392
|
+
return { rows: [], total: 0 };
|
|
27393
|
+
}
|
|
28138
27394
|
// Build DataSourceQuery
|
|
28139
27395
|
const term = query.term ?? '';
|
|
28140
27396
|
const search = term ? { term, columns: cfg.searchColumns } : undefined;
|
|
@@ -28213,6 +27469,9 @@ class DefaultDataProvider extends DataProvider {
|
|
|
28213
27469
|
case 'source':
|
|
28214
27470
|
case 'global':
|
|
28215
27471
|
case 'api': // Aliasing API to source if datasourceId present
|
|
27472
|
+
if (this.shouldSuppressRemoteAccess(cfg, engine)) {
|
|
27473
|
+
return [];
|
|
27474
|
+
}
|
|
28216
27475
|
if (cfg.datasourceId) {
|
|
28217
27476
|
return this.getGlobalRows(cfg);
|
|
28218
27477
|
}
|
|
@@ -28371,8 +27630,16 @@ class DefaultDataProvider extends DataProvider {
|
|
|
28371
27630
|
async getRuntimeOptions(field, engine) {
|
|
28372
27631
|
if (!engine)
|
|
28373
27632
|
return undefined;
|
|
27633
|
+
if (areEngineApiCallsSuppressed(engine))
|
|
27634
|
+
return undefined;
|
|
28374
27635
|
return this.runtimeFieldDataAccessRegistry.getOptions(field, engine);
|
|
28375
27636
|
}
|
|
27637
|
+
shouldSuppressRemoteAccess(cfg, engine) {
|
|
27638
|
+
if (!engine || !areEngineApiCallsSuppressed(engine)) {
|
|
27639
|
+
return false;
|
|
27640
|
+
}
|
|
27641
|
+
return cfg.type === 'source' || cfg.type === 'global' || cfg.type === 'api';
|
|
27642
|
+
}
|
|
28376
27643
|
shouldUseLocalResolution(cfg) {
|
|
28377
27644
|
if (cfg.rowsPath || cfg.labelPath || cfg.valuePath || cfg.rowSelectionMode || cfg.selectionFieldId || cfg.selectionMatchPath || cfg.childRowsPath) {
|
|
28378
27645
|
return true;
|
|
@@ -29440,6 +28707,11 @@ class SelectWidgetComponent {
|
|
|
29440
28707
|
runtimeManagedField = false;
|
|
29441
28708
|
runtimeOptionsLoaded = false;
|
|
29442
28709
|
dependencyValueSnapshot = new Map();
|
|
28710
|
+
cachedStyleSource;
|
|
28711
|
+
cachedWrapperStyles = { width: '100%' };
|
|
28712
|
+
cachedControlCssVars = this.toCssVarMap({});
|
|
28713
|
+
cachedInputLabel = '';
|
|
28714
|
+
cachedInputAttributes = { 'aria-label': 'Select field' };
|
|
29443
28715
|
destroyRef = inject(DestroyRef);
|
|
29444
28716
|
cdr = inject(ChangeDetectorRef);
|
|
29445
28717
|
dataProvider = inject(DATA_PROVIDER, { optional: true }) || inject(DefaultDataProvider);
|
|
@@ -29562,9 +28834,8 @@ class SelectWidgetComponent {
|
|
|
29562
28834
|
return this.toSafeNonNegativeInt(this.config['searchMinChars'], 0);
|
|
29563
28835
|
}
|
|
29564
28836
|
getInputAttributes() {
|
|
29565
|
-
|
|
29566
|
-
|
|
29567
|
-
};
|
|
28837
|
+
this.syncTemplateBindingCaches();
|
|
28838
|
+
return this.cachedInputAttributes;
|
|
29568
28839
|
}
|
|
29569
28840
|
pillLabel() {
|
|
29570
28841
|
return String(this.config['pillLabel'] ?? '').trim();
|
|
@@ -29578,16 +28849,22 @@ class SelectWidgetComponent {
|
|
|
29578
28849
|
showNativeLabel() {
|
|
29579
28850
|
return this.config?.showLabel !== false && this.nativeLabel().length > 0;
|
|
29580
28851
|
}
|
|
28852
|
+
getCompositeClass() {
|
|
28853
|
+
return this.showNativeLabel()
|
|
28854
|
+
? 'relative fd-select-composite mt-[0.5em]'
|
|
28855
|
+
: 'relative fd-select-composite';
|
|
28856
|
+
}
|
|
29581
28857
|
getWrapperStyles() {
|
|
29582
|
-
|
|
29583
|
-
return
|
|
28858
|
+
this.syncTemplateBindingCaches();
|
|
28859
|
+
return this.cachedWrapperStyles;
|
|
29584
28860
|
}
|
|
29585
28861
|
getControlCssVars() {
|
|
29586
|
-
|
|
29587
|
-
return this.
|
|
28862
|
+
this.syncTemplateBindingCaches();
|
|
28863
|
+
return this.cachedControlCssVars;
|
|
29588
28864
|
}
|
|
29589
28865
|
getPillStyles() {
|
|
29590
|
-
|
|
28866
|
+
this.syncTemplateBindingCaches();
|
|
28867
|
+
return this.cachedControlCssVars;
|
|
29591
28868
|
}
|
|
29592
28869
|
get visible() {
|
|
29593
28870
|
return this.engine ? this.engine.isFieldVisible(this.config.id) : true;
|
|
@@ -29871,6 +29148,20 @@ class SelectWidgetComponent {
|
|
|
29871
29148
|
getAccessibleLabel() {
|
|
29872
29149
|
return this.config?.label?.trim() || this.config?.name || this.config?.placeholder || 'Select field';
|
|
29873
29150
|
}
|
|
29151
|
+
syncTemplateBindingCaches() {
|
|
29152
|
+
const styleSource = this.config?.style;
|
|
29153
|
+
if (this.cachedStyleSource !== styleSource) {
|
|
29154
|
+
const { wrapperStyles, controlStyles } = splitControlSurfaceStyles(this.config.style, SELECT_CONTROL_STYLE_KEYS);
|
|
29155
|
+
this.cachedWrapperStyles = mergeAndNormalize({ width: '100%' }, wrapperStyles);
|
|
29156
|
+
this.cachedControlCssVars = this.toCssVarMap(controlStyles);
|
|
29157
|
+
this.cachedStyleSource = styleSource;
|
|
29158
|
+
}
|
|
29159
|
+
const accessibleLabel = this.getAccessibleLabel();
|
|
29160
|
+
if (this.cachedInputLabel !== accessibleLabel) {
|
|
29161
|
+
this.cachedInputLabel = accessibleLabel;
|
|
29162
|
+
this.cachedInputAttributes = { 'aria-label': accessibleLabel };
|
|
29163
|
+
}
|
|
29164
|
+
}
|
|
29874
29165
|
toSafeNonNegativeInt(value, fallback) {
|
|
29875
29166
|
if (typeof value === 'number' && Number.isFinite(value) && value >= 0) {
|
|
29876
29167
|
return Math.floor(value);
|
|
@@ -29890,7 +29181,7 @@ class SelectWidgetComponent {
|
|
|
29890
29181
|
[ngStyle]="getWrapperStyles()"
|
|
29891
29182
|
data-fd="field"
|
|
29892
29183
|
[attr.data-fd-field-type]="config.type">
|
|
29893
|
-
<div class="
|
|
29184
|
+
<div [class]="getCompositeClass()" [class.fd-select-composite--with-pill]="hasPillLabel()">
|
|
29894
29185
|
@if (showNativeLabel()) {
|
|
29895
29186
|
<label
|
|
29896
29187
|
[for]="fieldId"
|
|
@@ -29960,7 +29251,7 @@ class SelectWidgetComponent {
|
|
|
29960
29251
|
<p [id]="helpTextId" [class]="fieldHelpClass" data-fd="field-help">{{ config.helpText }}</p>
|
|
29961
29252
|
}
|
|
29962
29253
|
</div>
|
|
29963
|
-
`, isInline: true, styles: [":host ::ng-deep ng-select.fd-select{display:block;min-height:0;color:var(--fd-select-text-color, #1C2431)}.fd-select-composite{display:flex;width:100%;min-width:0}:host ::ng-deep ng-select.fd-select .ng-select-container{height:var(--fd-select-height, 100%);min-height:var(--fd-select-min-height, 20px);border-style:var(--fd-select-border-style, solid);border-width:var(--fd-select-border-width, 1.5px);border-color:var(--fd-select-border-color, #3F8CFF);border-top-style:var(--fd-select-border-top-style, var(--fd-select-border-style, solid));border-right-style:var(--fd-select-border-right-style, var(--fd-select-border-style, solid));border-bottom-style:var(--fd-select-border-bottom-style, var(--fd-select-border-style, solid));border-left-style:var(--fd-select-border-left-style, var(--fd-select-border-style, solid));border-top-width:var(--fd-select-border-top-width, var(--fd-select-border-width, 1.5px));border-right-width:var(--fd-select-border-right-width, var(--fd-select-border-width, 1.5px));border-bottom-width:var(--fd-select-border-bottom-width, var(--fd-select-border-width, 1.5px));border-left-width:var(--fd-select-border-left-width, var(--fd-select-border-width, 1.5px));border-top-color:var(--fd-select-border-top-color, var(--fd-select-border-color, #3F8CFF));border-right-color:var(--fd-select-border-right-color, var(--fd-select-border-color, #3F8CFF));border-bottom-color:var(--fd-select-border-bottom-color, var(--fd-select-border-color, #3F8CFF));border-left-color:var(--fd-select-border-left-color, var(--fd-select-border-color, #3F8CFF));border-radius:var(--fd-select-border-radius, 4px);border-top-left-radius:var(--fd-select-border-top-left-radius, var(--fd-select-border-radius, 4px));border-top-right-radius:var(--fd-select-border-top-right-radius, var(--fd-select-border-radius, 4px));border-bottom-right-radius:var(--fd-select-border-bottom-right-radius, var(--fd-select-border-radius, 4px));border-bottom-left-radius:var(--fd-select-border-bottom-left-radius, var(--fd-select-border-radius, 4px));background:var(--fd-select-background-color, #FFFFFF);box-shadow:var(--fd-select-box-shadow, none);transition:border-color .2s ease,box-shadow .2s ease}:host ::ng-deep ng-select.fd-select:hover .ng-select-container{border-color:var(--fd-select-hover-border-color, var(--fd-select-border-color, #3F8CFF))}:host ::ng-deep ng-select.fd-select.fd-select--with-pill .ng-select-container{border-top-right-radius:0;border-bottom-right-radius:0;border-right-width:0}:host ::ng-deep ng-select.fd-select.ng-select-focused:not(.ng-select-opened) .ng-select-container,:host ::ng-deep ng-select.fd-select.ng-select-opened .ng-select-container{border-width:var(--fd-select-interactive-border-width, var(--fd-select-border-width, 1.5px));border-color:var(--fd-select-interactive-border-color, #7FB2FF)}:host ::ng-deep ng-select.fd-select[data-fd-field-state=invalid] .ng-select-container{border-width:var(--fd-select-invalid-border-width, var(--fd-select-border-width, 1.5px));border-color:var(--fd-select-invalid-border-color, #EF4444)}:host ::ng-deep ng-select.fd-select .ng-value-container{align-items:center;min-height:100%;padding-top:var(--fd-select-padding-top, 2px);padding-right:var(--fd-select-padding-right, 12px);padding-bottom:var(--fd-select-padding-bottom, 2px);padding-left:var(--fd-select-padding-left, 12px);gap:4px}:host ::ng-deep ng-select.fd-select .ng-placeholder,:host ::ng-deep ng-select.fd-select .ng-value-label,:host ::ng-deep ng-select.fd-select .ng-input>input{font-family:inherit;color:var(--fd-select-text-color, #1C2431);font-size:var(--fd-select-font-size, 14px);font-weight:var(--fd-select-font-weight, 400);line-height:var(--fd-select-line-height, 20px)}:host ::ng-deep ng-select.fd-select .ng-placeholder{color:#1c243166}:host ::ng-deep ng-select.fd-select .ng-select-container.ng-has-value .ng-placeholder{display:none}:host ::ng-deep ng-select.fd-select .ng-arrow-wrapper{padding-right:var(--fd-select-arrow-padding-right, 12px)}:host ::ng-deep ng-select.fd-select.fd-select--with-pill .ng-arrow-wrapper,:host ::ng-deep ng-select.fd-select.fd-select--with-pill .ng-clear-wrapper{display:none}:host ::ng-deep ng-select.fd-select .ng-arrow{border-color:var(--fd-select-icon-color, rgba(28, 36, 49, .6)) transparent transparent}:host ::ng-deep ng-select.fd-select .ng-clear-wrapper{color:var(--fd-select-icon-color, rgba(28, 36, 49, .6))}:host ::ng-deep .ng-dropdown-panel{border:1px solid #E6EAF0;border-radius:8px;background:#fff;box-shadow:0 10px 30px #0000001f}:host ::ng-deep .ng-dropdown-panel .ng-option{padding:10px 14px;font-size:14px;line-height:20px;background:#fff;color:#1c2431}:host ::ng-deep .ng-dropdown-panel .ng-option.ng-option-marked{background:#7fb2ff14;color:#1c2431}:host ::ng-deep .ng-dropdown-panel .ng-option.ng-option-selected{background:#7fb2ff24;color:#1c2431}.fd-select-pill{display:inline-flex;align-items:center;gap:8px;height:var(--fd-select-height, 100%);min-height:var(--fd-select-min-height, 20px);padding:0 12px;border-style:var(--fd-select-border-style, solid);border-width:var(--fd-select-border-width, 1px);border-color:var(--fd-select-border-color, #3F8CFF);border-left-width:var(--fd-select-border-left-width, 1px);border-left-style:var(--fd-select-border-left-style, solid);border-left-color:var(--fd-select-border-left-color, var(--fd-select-border-color, #3F8CFF));border-top-right-radius:var(--fd-select-border-top-right-radius, var(--fd-select-border-radius, 4px));border-bottom-right-radius:var(--fd-select-border-bottom-right-radius, var(--fd-select-border-radius, 4px));border-top-left-radius:0;border-bottom-left-radius:0;background:var(--fd-select-background-color, #FFFFFF);color:var(--fd-select-text-color, #1C2431);font-size:var(--fd-select-font-size, 14px);font-weight:var(--fd-select-font-weight, 400);line-height:var(--fd-select-line-height, 20px);box-shadow:var(--fd-select-box-shadow, none);white-space:nowrap;cursor:pointer}.fd-select-pill:disabled{cursor:default;opacity:.7}.fd-select-pill__arrow{width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;border-top:5px solid var(--fd-select-icon-color, rgba(28, 36, 49, .6))}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.
|
|
29254
|
+
`, isInline: true, styles: [":host ::ng-deep ng-select.fd-select{display:block;min-height:0;color:var(--fd-select-text-color, #1C2431)}.fd-select-composite{display:flex;width:100%;min-width:0}:host ::ng-deep ng-select.fd-select .ng-select-container{height:var(--fd-select-height, 100%);min-height:var(--fd-select-min-height, 20px);border-style:var(--fd-select-border-style, solid);border-width:var(--fd-select-border-width, 1.5px);border-color:var(--fd-select-border-color, #3F8CFF);border-top-style:var(--fd-select-border-top-style, var(--fd-select-border-style, solid));border-right-style:var(--fd-select-border-right-style, var(--fd-select-border-style, solid));border-bottom-style:var(--fd-select-border-bottom-style, var(--fd-select-border-style, solid));border-left-style:var(--fd-select-border-left-style, var(--fd-select-border-style, solid));border-top-width:var(--fd-select-border-top-width, var(--fd-select-border-width, 1.5px));border-right-width:var(--fd-select-border-right-width, var(--fd-select-border-width, 1.5px));border-bottom-width:var(--fd-select-border-bottom-width, var(--fd-select-border-width, 1.5px));border-left-width:var(--fd-select-border-left-width, var(--fd-select-border-width, 1.5px));border-top-color:var(--fd-select-border-top-color, var(--fd-select-border-color, #3F8CFF));border-right-color:var(--fd-select-border-right-color, var(--fd-select-border-color, #3F8CFF));border-bottom-color:var(--fd-select-border-bottom-color, var(--fd-select-border-color, #3F8CFF));border-left-color:var(--fd-select-border-left-color, var(--fd-select-border-color, #3F8CFF));border-radius:var(--fd-select-border-radius, 4px);border-top-left-radius:var(--fd-select-border-top-left-radius, var(--fd-select-border-radius, 4px));border-top-right-radius:var(--fd-select-border-top-right-radius, var(--fd-select-border-radius, 4px));border-bottom-right-radius:var(--fd-select-border-bottom-right-radius, var(--fd-select-border-radius, 4px));border-bottom-left-radius:var(--fd-select-border-bottom-left-radius, var(--fd-select-border-radius, 4px));background:var(--fd-select-background-color, #FFFFFF);box-shadow:var(--fd-select-box-shadow, none);transition:border-color .2s ease,box-shadow .2s ease}:host ::ng-deep ng-select.fd-select:hover .ng-select-container{border-color:var(--fd-select-hover-border-color, var(--fd-select-border-color, #3F8CFF))}:host ::ng-deep ng-select.fd-select.fd-select--with-pill .ng-select-container{border-top-right-radius:0;border-bottom-right-radius:0;border-right-width:0}:host ::ng-deep ng-select.fd-select.ng-select-focused:not(.ng-select-opened) .ng-select-container,:host ::ng-deep ng-select.fd-select.ng-select-opened .ng-select-container{border-width:var(--fd-select-interactive-border-width, var(--fd-select-border-width, 1.5px));border-color:var(--fd-select-interactive-border-color, #7FB2FF)}:host ::ng-deep ng-select.fd-select[data-fd-field-state=invalid] .ng-select-container{border-width:var(--fd-select-invalid-border-width, var(--fd-select-border-width, 1.5px));border-color:var(--fd-select-invalid-border-color, #EF4444)}:host ::ng-deep ng-select.fd-select .ng-value-container{align-items:center;min-height:100%;padding-top:var(--fd-select-padding-top, 2px);padding-right:var(--fd-select-padding-right, 12px);padding-bottom:var(--fd-select-padding-bottom, 2px);padding-left:var(--fd-select-padding-left, 12px);gap:4px}:host ::ng-deep ng-select.fd-select .ng-placeholder,:host ::ng-deep ng-select.fd-select .ng-value-label,:host ::ng-deep ng-select.fd-select .ng-input>input{font-family:inherit;color:var(--fd-select-text-color, #1C2431);font-size:var(--fd-select-font-size, 14px);font-weight:var(--fd-select-font-weight, 400);line-height:var(--fd-select-line-height, 20px)}:host ::ng-deep ng-select.fd-select .ng-placeholder{color:#1c243166}:host ::ng-deep ng-select.fd-select .ng-select-container.ng-has-value .ng-placeholder{display:none}:host ::ng-deep ng-select.fd-select .ng-arrow-wrapper{padding-right:var(--fd-select-arrow-padding-right, 12px)}:host ::ng-deep ng-select.fd-select.fd-select--with-pill .ng-arrow-wrapper,:host ::ng-deep ng-select.fd-select.fd-select--with-pill .ng-clear-wrapper{display:none}:host ::ng-deep ng-select.fd-select .ng-arrow{border-color:var(--fd-select-icon-color, rgba(28, 36, 49, .6)) transparent transparent}:host ::ng-deep ng-select.fd-select .ng-clear-wrapper{color:var(--fd-select-icon-color, rgba(28, 36, 49, .6))}:host ::ng-deep .ng-dropdown-panel{border:1px solid #E6EAF0;border-radius:8px;background:#fff;box-shadow:0 10px 30px #0000001f}:host ::ng-deep .ng-dropdown-panel .ng-option{padding:10px 14px;font-size:14px;line-height:20px;background:#fff;color:#1c2431}:host ::ng-deep .ng-dropdown-panel .ng-option.ng-option-marked{background:#7fb2ff14;color:#1c2431}:host ::ng-deep .ng-dropdown-panel .ng-option.ng-option-selected{background:#7fb2ff24;color:#1c2431}.fd-select-pill{display:inline-flex;align-items:center;gap:8px;height:var(--fd-select-height, 100%);min-height:var(--fd-select-min-height, 20px);padding:0 12px;border-style:var(--fd-select-border-style, solid);border-width:var(--fd-select-border-width, 1px);border-color:var(--fd-select-border-color, #3F8CFF);border-left-width:var(--fd-select-border-left-width, 1px);border-left-style:var(--fd-select-border-left-style, solid);border-left-color:var(--fd-select-border-left-color, var(--fd-select-border-color, #3F8CFF));border-top-right-radius:var(--fd-select-border-top-right-radius, var(--fd-select-border-radius, 4px));border-bottom-right-radius:var(--fd-select-border-bottom-right-radius, var(--fd-select-border-radius, 4px));border-top-left-radius:0;border-bottom-left-radius:0;background:var(--fd-select-background-color, #FFFFFF);color:var(--fd-select-text-color, #1C2431);font-size:var(--fd-select-font-size, 14px);font-weight:var(--fd-select-font-weight, 400);line-height:var(--fd-select-line-height, 20px);box-shadow:var(--fd-select-box-shadow, none);white-space:nowrap;cursor:pointer}.fd-select-pill:disabled{cursor:default;opacity:.7}.fd-select-pill__arrow{width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;border-top:5px solid var(--fd-select-icon-color, rgba(28, 36, 49, .6))}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: NgSelectComponent, selector: "ng-select", inputs: ["bindLabel", "bindValue", "ariaLabel", "markFirst", "placeholder", "fixedPlaceholder", "notFoundText", "typeToSearchText", "preventToggleOnRightClick", "addTagText", "loadingText", "clearAllText", "appearance", "dropdownPosition", "appendTo", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "ngClass", "typeahead", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd", "deselectOnClick", "keyDownFn"], outputs: ["blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"] }] });
|
|
29964
29255
|
}
|
|
29965
29256
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SelectWidgetComponent, decorators: [{
|
|
29966
29257
|
type: Component,
|
|
@@ -29970,7 +29261,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
29970
29261
|
[ngStyle]="getWrapperStyles()"
|
|
29971
29262
|
data-fd="field"
|
|
29972
29263
|
[attr.data-fd-field-type]="config.type">
|
|
29973
|
-
<div class="
|
|
29264
|
+
<div [class]="getCompositeClass()" [class.fd-select-composite--with-pill]="hasPillLabel()">
|
|
29974
29265
|
@if (showNativeLabel()) {
|
|
29975
29266
|
<label
|
|
29976
29267
|
[for]="fieldId"
|
|
@@ -32538,6 +31829,30 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
32538
31829
|
args: ['editor', { static: true }]
|
|
32539
31830
|
}] } });
|
|
32540
31831
|
|
|
31832
|
+
class SafePipe {
|
|
31833
|
+
// Use inject() for modern Angular
|
|
31834
|
+
sanitizer = inject(DomSanitizer);
|
|
31835
|
+
transform(value, type) {
|
|
31836
|
+
switch (type) {
|
|
31837
|
+
case 'html': return this.sanitizer.bypassSecurityTrustHtml(value);
|
|
31838
|
+
case 'style': return this.sanitizer.bypassSecurityTrustStyle(value);
|
|
31839
|
+
case 'script': return this.sanitizer.bypassSecurityTrustScript(value);
|
|
31840
|
+
case 'url': return this.sanitizer.bypassSecurityTrustUrl(value);
|
|
31841
|
+
case 'resourceUrl': return this.sanitizer.bypassSecurityTrustResourceUrl(value);
|
|
31842
|
+
default: return value;
|
|
31843
|
+
}
|
|
31844
|
+
}
|
|
31845
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SafePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
31846
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.17", ngImport: i0, type: SafePipe, isStandalone: true, name: "safe" });
|
|
31847
|
+
}
|
|
31848
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SafePipe, decorators: [{
|
|
31849
|
+
type: Pipe,
|
|
31850
|
+
args: [{
|
|
31851
|
+
name: 'safe',
|
|
31852
|
+
standalone: true
|
|
31853
|
+
}]
|
|
31854
|
+
}] });
|
|
31855
|
+
|
|
32541
31856
|
class RichTextWidgetComponent {
|
|
32542
31857
|
editor = inject(WIDGET_EDITOR_CONTEXT, { optional: true });
|
|
32543
31858
|
destroyRef = inject(DestroyRef);
|
|
@@ -32670,13 +31985,13 @@ class RichTextWidgetComponent {
|
|
|
32670
31985
|
[class]="'rich-text-widget ' + contentClass()"
|
|
32671
31986
|
data-fd="text-content"
|
|
32672
31987
|
[ngStyle]="editorStyles()"
|
|
32673
|
-
[innerHTML]="contentHtml()"></div>
|
|
31988
|
+
[innerHTML]="contentHtml() | safe:'html'"></div>
|
|
32674
31989
|
</ng-template>
|
|
32675
|
-
`, isInline: true, styles: [":host ::ng-deep .rich-text-widget ol{list-style-type:var(--fd-ordered-list-style, decimal);margin-left:1.25rem;padding-left:.5rem}:host ::ng-deep .rich-text-widget ul{margin-left:1.25rem;padding-left:.5rem;list-style-type:disc}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: InlineQuillEditorComponent, selector: "app-inline-quill-editor", inputs: ["html", "placeholder", "readOnly", "autoFocus", "containerClass", "editorClass", "editorStyle"], outputs: ["htmlChange", "editorBlur", "editorFocus"] }] });
|
|
31990
|
+
`, isInline: true, styles: [":host ::ng-deep .rich-text-widget ol{list-style-type:var(--fd-ordered-list-style, decimal);margin-left:1.25rem;padding-left:.5rem}:host ::ng-deep .rich-text-widget ul{margin-left:1.25rem;padding-left:.5rem;list-style-type:disc}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: InlineQuillEditorComponent, selector: "app-inline-quill-editor", inputs: ["html", "placeholder", "readOnly", "autoFocus", "containerClass", "editorClass", "editorStyle"], outputs: ["htmlChange", "editorBlur", "editorFocus"] }, { kind: "pipe", type: SafePipe, name: "safe" }] });
|
|
32676
31991
|
}
|
|
32677
31992
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: RichTextWidgetComponent, decorators: [{
|
|
32678
31993
|
type: Component,
|
|
32679
|
-
args: [{ selector: 'app-rich-text-widget', standalone: true, imports: [CommonModule, InlineQuillEditorComponent], template: `
|
|
31994
|
+
args: [{ selector: 'app-rich-text-widget', standalone: true, imports: [CommonModule, InlineQuillEditorComponent, SafePipe], template: `
|
|
32680
31995
|
<ng-container *ngIf="isDesignMode(); else staticContent">
|
|
32681
31996
|
<app-inline-quill-editor
|
|
32682
31997
|
[html]="contentHtml()"
|
|
@@ -32694,7 +32009,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
32694
32009
|
[class]="'rich-text-widget ' + contentClass()"
|
|
32695
32010
|
data-fd="text-content"
|
|
32696
32011
|
[ngStyle]="editorStyles()"
|
|
32697
|
-
[innerHTML]="contentHtml()"></div>
|
|
32012
|
+
[innerHTML]="contentHtml() | safe:'html'"></div>
|
|
32698
32013
|
</ng-template>
|
|
32699
32014
|
`, styles: [":host ::ng-deep .rich-text-widget ol{list-style-type:var(--fd-ordered-list-style, decimal);margin-left:1.25rem;padding-left:.5rem}:host ::ng-deep .rich-text-widget ul{margin-left:1.25rem;padding-left:.5rem;list-style-type:disc}\n"] }]
|
|
32700
32015
|
}], propDecorators: { config: [{
|