@yourself.create/ngx-form-designer 0.0.7 → 0.0.8
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/uch-web-ngx-form-designer.mjs +320 -75
- package/fesm2022/uch-web-ngx-form-designer.mjs.map +1 -1
- package/lib/data/data-provider.d.ts +3 -0
- package/lib/form-designer/data-panel/data-panel.component.d.ts +5 -1
- package/lib/form-designer/designer-state.service.d.ts +1 -1
- package/lib/form-designer/form-preview.component.d.ts +2 -2
- package/lib/form-designer/layout-canvas.component.d.ts +2 -2
- package/lib/form-designer/rules-editor/rules-panel/rules-panel.component.d.ts +1 -0
- package/lib/form-designer/widget-inspector.component.d.ts +1 -1
- package/lib/form-renderer/json-form-renderer.component.d.ts +4 -2
- package/lib/website/website-preview-shell.component.d.ts +1 -1
- package/lib/widgets/field-widgets/text-field/text-field.component.d.ts +8 -0
- package/package.json +1 -1
|
@@ -5257,7 +5257,7 @@ class JsonFormRendererComponent {
|
|
|
5257
5257
|
this.runtimeFieldDataAccessRegistry.unregister(this.engine);
|
|
5258
5258
|
}
|
|
5259
5259
|
async emitValuePayload(values) {
|
|
5260
|
-
const fieldValueMap = await this.buildFieldValueMap(values);
|
|
5260
|
+
const fieldValueMap = await this.buildFieldValueMap(values, { normalizeFileFieldsForSubmit: true });
|
|
5261
5261
|
const groupedValues = this.buildGroupedValues(fieldValueMap);
|
|
5262
5262
|
const combinedValues = this.buildCombinedValues(fieldValueMap);
|
|
5263
5263
|
this.valueChange.emit(fieldValueMap);
|
|
@@ -5419,16 +5419,10 @@ class JsonFormRendererComponent {
|
|
|
5419
5419
|
this.validationChange.emit(validation);
|
|
5420
5420
|
// Notify all widgets to show errors if any
|
|
5421
5421
|
this.engine?.submit();
|
|
5422
|
-
const preUploadFieldValueMap = this.uploadOnSubmit
|
|
5423
|
-
? await this.buildFieldValueMap(this.engine?.getValues() ?? {}, { normalizeFileFieldsForSubmit: true })
|
|
5424
|
-
: undefined;
|
|
5425
5422
|
const uploadedFiles = this.uploadOnSubmit ? await this.uploadPendingFiles() : {};
|
|
5426
5423
|
this.uploadedFilesChange.emit(uploadedFiles);
|
|
5427
5424
|
const values = this.engine?.getValues() ?? {};
|
|
5428
|
-
const
|
|
5429
|
-
const submitValues = preUploadFieldValueMap
|
|
5430
|
-
? this.mergeFileMetadata(fieldValueMap, preUploadFieldValueMap)
|
|
5431
|
-
: fieldValueMap;
|
|
5425
|
+
const submitValues = await this.buildFieldValueMap(values, { normalizeFileFieldsForSubmit: true });
|
|
5432
5426
|
this.formSubmit.emit({
|
|
5433
5427
|
values: submitValues,
|
|
5434
5428
|
groupedValues: this.buildGroupedValues(submitValues),
|
|
@@ -5689,13 +5683,14 @@ class JsonFormRendererComponent {
|
|
|
5689
5683
|
continue;
|
|
5690
5684
|
}
|
|
5691
5685
|
if (field.type === 'file') {
|
|
5686
|
+
const normalizeFileFieldsForSubmit = options.normalizeFileFieldsForSubmit === true;
|
|
5692
5687
|
const fileValue = {
|
|
5693
5688
|
fieldName: field.name,
|
|
5694
|
-
fieldValue:
|
|
5695
|
-
? this.
|
|
5689
|
+
fieldValue: normalizeFileFieldsForSubmit
|
|
5690
|
+
? await this.buildFileSubmitValueEntries(rawValue)
|
|
5696
5691
|
: rawValue,
|
|
5697
|
-
...(
|
|
5698
|
-
...(await this.buildFileFieldMetadata(rawValue))
|
|
5692
|
+
...(normalizeFileFieldsForSubmit ? { fieldType: field.type } : {}),
|
|
5693
|
+
...(!normalizeFileFieldsForSubmit ? await this.buildFileFieldMetadata(rawValue) : {})
|
|
5699
5694
|
};
|
|
5700
5695
|
mapped[field.id] = fileValue;
|
|
5701
5696
|
continue;
|
|
@@ -5782,7 +5777,12 @@ class JsonFormRendererComponent {
|
|
|
5782
5777
|
return undefined;
|
|
5783
5778
|
return values.length === 1 ? values[0] : values;
|
|
5784
5779
|
}
|
|
5785
|
-
|
|
5780
|
+
async buildFileSubmitValueEntries(value) {
|
|
5781
|
+
const rawEntries = this.normalizeFileFieldEntries(value);
|
|
5782
|
+
const normalizedEntries = await Promise.all(rawEntries.map(entry => this.normalizeSingleFileFieldEntry(entry)));
|
|
5783
|
+
return normalizedEntries.filter((entry) => entry !== null);
|
|
5784
|
+
}
|
|
5785
|
+
normalizeFileFieldEntries(value) {
|
|
5786
5786
|
if (this.isFileList(value)) {
|
|
5787
5787
|
return Array.from(value);
|
|
5788
5788
|
}
|
|
@@ -5794,6 +5794,23 @@ class JsonFormRendererComponent {
|
|
|
5794
5794
|
}
|
|
5795
5795
|
return [value];
|
|
5796
5796
|
}
|
|
5797
|
+
async normalizeSingleFileFieldEntry(value) {
|
|
5798
|
+
if (this.isFile(value)) {
|
|
5799
|
+
return this.buildPendingSubmitFileValue(value);
|
|
5800
|
+
}
|
|
5801
|
+
if (this.isUploadedFileRef(value)) {
|
|
5802
|
+
return { ...value };
|
|
5803
|
+
}
|
|
5804
|
+
return null;
|
|
5805
|
+
}
|
|
5806
|
+
async buildPendingSubmitFileValue(file) {
|
|
5807
|
+
return {
|
|
5808
|
+
name: file.name || undefined,
|
|
5809
|
+
size: Number.isFinite(file.size) ? file.size : undefined,
|
|
5810
|
+
type: file.type || undefined,
|
|
5811
|
+
data: await this.readFileBase64(file)
|
|
5812
|
+
};
|
|
5813
|
+
}
|
|
5797
5814
|
getUploadedFileRefs(value) {
|
|
5798
5815
|
if (this.isUploadedFileRef(value))
|
|
5799
5816
|
return [value];
|
|
@@ -5808,26 +5825,6 @@ class JsonFormRendererComponent {
|
|
|
5808
5825
|
: undefined;
|
|
5809
5826
|
return fieldLabel === undefined ? {} : { fieldLabel };
|
|
5810
5827
|
}
|
|
5811
|
-
mergeFileMetadata(target, source) {
|
|
5812
|
-
const merged = { ...target };
|
|
5813
|
-
for (const fieldId of Object.keys(source)) {
|
|
5814
|
-
const sourceValue = source[fieldId];
|
|
5815
|
-
const targetValue = merged[fieldId];
|
|
5816
|
-
if (!sourceValue || !targetValue)
|
|
5817
|
-
continue;
|
|
5818
|
-
if (sourceValue.fileType === undefined && sourceValue.data === undefined)
|
|
5819
|
-
continue;
|
|
5820
|
-
const nextValue = { ...targetValue };
|
|
5821
|
-
if (sourceValue.fileType !== undefined) {
|
|
5822
|
-
nextValue.fileType = sourceValue.fileType;
|
|
5823
|
-
}
|
|
5824
|
-
if (sourceValue.data !== undefined) {
|
|
5825
|
-
nextValue.data = sourceValue.data;
|
|
5826
|
-
}
|
|
5827
|
-
merged[fieldId] = nextValue;
|
|
5828
|
-
}
|
|
5829
|
-
return merged;
|
|
5830
|
-
}
|
|
5831
5828
|
buildGroupedValues(values) {
|
|
5832
5829
|
const grouped = {};
|
|
5833
5830
|
const schema = this.engine?.getSchema();
|
|
@@ -15891,8 +15888,33 @@ class DataPanelComponent {
|
|
|
15891
15888
|
showOptionMappingControls() {
|
|
15892
15889
|
return this.sourceType === 'source' && this.widgetType !== 'table' && this.usesOptionMapping();
|
|
15893
15890
|
}
|
|
15894
|
-
|
|
15895
|
-
|
|
15891
|
+
showDisplayFormattingControls() {
|
|
15892
|
+
if (this.widgetType === 'select' && this.usesOptionMapping()) {
|
|
15893
|
+
return true;
|
|
15894
|
+
}
|
|
15895
|
+
return this.sourceType === 'source'
|
|
15896
|
+
&& this.bindingShape === 'scalar'
|
|
15897
|
+
&& (this.widgetType === 'text' || this.widgetType === 'number');
|
|
15898
|
+
}
|
|
15899
|
+
supportsNumericDisplayFormatting() {
|
|
15900
|
+
return this.widgetType === 'select' || this.widgetType === 'number';
|
|
15901
|
+
}
|
|
15902
|
+
displayFormattingTitle() {
|
|
15903
|
+
return this.widgetType === 'select' ? 'Amount Display' : 'Field Display';
|
|
15904
|
+
}
|
|
15905
|
+
displayFormattingDescription() {
|
|
15906
|
+
if (this.widgetType === 'select') {
|
|
15907
|
+
return 'Format the visible dropdown label without changing the stored option value.';
|
|
15908
|
+
}
|
|
15909
|
+
if (this.widgetType === 'number') {
|
|
15910
|
+
return 'Show a fixed prefix and grouped digits in the visible field value without changing the stored number.';
|
|
15911
|
+
}
|
|
15912
|
+
return 'Show a fixed prefix beside the editable value without changing the stored field value.';
|
|
15913
|
+
}
|
|
15914
|
+
numericDisplayFormattingLabel() {
|
|
15915
|
+
return this.widgetType === 'select'
|
|
15916
|
+
? 'Show thousand separators for numeric labels'
|
|
15917
|
+
: 'Show thousand separators for numeric values';
|
|
15896
15918
|
}
|
|
15897
15919
|
showStaticOptionsEditor() {
|
|
15898
15920
|
return this.sourceType === 'static' && this.widgetType !== 'table' && this.usesOptionMapping();
|
|
@@ -15945,7 +15967,12 @@ class DataPanelComponent {
|
|
|
15945
15967
|
return sample ? collectArrayPaths(sample) : [];
|
|
15946
15968
|
}
|
|
15947
15969
|
shouldPersistOptionLabelFormatting() {
|
|
15948
|
-
|
|
15970
|
+
if (this.widgetType === 'select' && this.usesOptionMapping()) {
|
|
15971
|
+
return true;
|
|
15972
|
+
}
|
|
15973
|
+
return this.sourceType === 'source'
|
|
15974
|
+
&& this.bindingShape === 'scalar'
|
|
15975
|
+
&& (this.widgetType === 'text' || this.widgetType === 'number');
|
|
15949
15976
|
}
|
|
15950
15977
|
usesOptionMapping() {
|
|
15951
15978
|
return this.bindingShape === 'list' || this.widgetType === 'search';
|
|
@@ -16266,17 +16293,17 @@ class DataPanelComponent {
|
|
|
16266
16293
|
</div>
|
|
16267
16294
|
</div>
|
|
16268
16295
|
|
|
16269
|
-
<div class="rounded-lg border border-gray-200 bg-white p-3" *ngIf="
|
|
16270
|
-
<div class="text-xs font-semibold uppercase tracking-wide text-gray-500">
|
|
16271
|
-
<div class="mt-1 text-[11px] text-gray-500">
|
|
16296
|
+
<div class="rounded-lg border border-gray-200 bg-white p-3" *ngIf="showDisplayFormattingControls()">
|
|
16297
|
+
<div class="text-xs font-semibold uppercase tracking-wide text-gray-500">{{ displayFormattingTitle() }}</div>
|
|
16298
|
+
<div class="mt-1 text-[11px] text-gray-500">{{ displayFormattingDescription() }}</div>
|
|
16272
16299
|
|
|
16273
|
-
<label class="mt-3 flex items-center gap-2 text-sm text-gray-700">
|
|
16300
|
+
<label class="mt-3 flex items-center gap-2 text-sm text-gray-700" *ngIf="supportsNumericDisplayFormatting()">
|
|
16274
16301
|
<input
|
|
16275
16302
|
type="checkbox"
|
|
16276
16303
|
[checked]="formatNumericOptionLabels"
|
|
16277
16304
|
(change)="formatNumericOptionLabels = $any($event.target).checked; emitChange()"
|
|
16278
16305
|
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500">
|
|
16279
|
-
<span>
|
|
16306
|
+
<span>{{ numericDisplayFormattingLabel() }}</span>
|
|
16280
16307
|
</label>
|
|
16281
16308
|
|
|
16282
16309
|
<div class="mt-3 flex flex-col gap-1">
|
|
@@ -16885,17 +16912,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
16885
16912
|
</div>
|
|
16886
16913
|
</div>
|
|
16887
16914
|
|
|
16888
|
-
<div class="rounded-lg border border-gray-200 bg-white p-3" *ngIf="
|
|
16889
|
-
<div class="text-xs font-semibold uppercase tracking-wide text-gray-500">
|
|
16890
|
-
<div class="mt-1 text-[11px] text-gray-500">
|
|
16915
|
+
<div class="rounded-lg border border-gray-200 bg-white p-3" *ngIf="showDisplayFormattingControls()">
|
|
16916
|
+
<div class="text-xs font-semibold uppercase tracking-wide text-gray-500">{{ displayFormattingTitle() }}</div>
|
|
16917
|
+
<div class="mt-1 text-[11px] text-gray-500">{{ displayFormattingDescription() }}</div>
|
|
16891
16918
|
|
|
16892
|
-
<label class="mt-3 flex items-center gap-2 text-sm text-gray-700">
|
|
16919
|
+
<label class="mt-3 flex items-center gap-2 text-sm text-gray-700" *ngIf="supportsNumericDisplayFormatting()">
|
|
16893
16920
|
<input
|
|
16894
16921
|
type="checkbox"
|
|
16895
16922
|
[checked]="formatNumericOptionLabels"
|
|
16896
16923
|
(change)="formatNumericOptionLabels = $any($event.target).checked; emitChange()"
|
|
16897
16924
|
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500">
|
|
16898
|
-
<span>
|
|
16925
|
+
<span>{{ numericDisplayFormattingLabel() }}</span>
|
|
16899
16926
|
</label>
|
|
16900
16927
|
|
|
16901
16928
|
<div class="mt-3 flex flex-col gap-1">
|
|
@@ -17674,11 +17701,18 @@ class RulesPanelComponent {
|
|
|
17674
17701
|
ruleActionOptions = [
|
|
17675
17702
|
{ label: 'Visible', value: 'visible' },
|
|
17676
17703
|
{ label: 'Hidden', value: 'hidden' },
|
|
17677
|
-
{ label: 'Enabled', value: 'enable' },
|
|
17678
17704
|
{ label: 'Disabled', value: 'disable' },
|
|
17679
17705
|
{ label: 'Required', value: 'required' },
|
|
17680
17706
|
{ label: 'Optional', value: 'optional' }
|
|
17681
17707
|
];
|
|
17708
|
+
actionLabels = {
|
|
17709
|
+
visible: 'Visible',
|
|
17710
|
+
hidden: 'Hidden',
|
|
17711
|
+
enable: 'Enabled',
|
|
17712
|
+
disable: 'Disabled',
|
|
17713
|
+
required: 'Required',
|
|
17714
|
+
optional: 'Optional'
|
|
17715
|
+
};
|
|
17682
17716
|
severityOptions = [
|
|
17683
17717
|
{ label: 'Warn', value: 'warn' },
|
|
17684
17718
|
{ label: 'Error', value: 'error' }
|
|
@@ -17730,7 +17764,7 @@ class RulesPanelComponent {
|
|
|
17730
17764
|
return `${primary} / else ${this.getActionLabel(rule.elseAction)}`;
|
|
17731
17765
|
}
|
|
17732
17766
|
getActionLabel(action) {
|
|
17733
|
-
return this.
|
|
17767
|
+
return this.actionLabels[action] ?? action;
|
|
17734
17768
|
}
|
|
17735
17769
|
getActionColor(action) {
|
|
17736
17770
|
switch (action) {
|
|
@@ -17749,7 +17783,7 @@ class RulesPanelComponent {
|
|
|
17749
17783
|
<div class="flex items-center justify-between mb-2">
|
|
17750
17784
|
<div class="flex flex-col">
|
|
17751
17785
|
<span class="font-semibold text-gray-700">Rules</span>
|
|
17752
|
-
<span class="text-xs text-gray-500">Rules can override visibility,
|
|
17786
|
+
<span class="text-xs text-gray-500">Rules can override visibility, disabled, and required state set elsewhere.</span>
|
|
17753
17787
|
</div>
|
|
17754
17788
|
<button (click)="addRule()"
|
|
17755
17789
|
[disabled]="readOnly"
|
|
@@ -17871,7 +17905,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
17871
17905
|
<div class="flex items-center justify-between mb-2">
|
|
17872
17906
|
<div class="flex flex-col">
|
|
17873
17907
|
<span class="font-semibold text-gray-700">Rules</span>
|
|
17874
|
-
<span class="text-xs text-gray-500">Rules can override visibility,
|
|
17908
|
+
<span class="text-xs text-gray-500">Rules can override visibility, disabled, and required state set elsewhere.</span>
|
|
17875
17909
|
</div>
|
|
17876
17910
|
<button (click)="addRule()"
|
|
17877
17911
|
[disabled]="readOnly"
|
|
@@ -19546,34 +19580,35 @@ class FormPreviewComponent {
|
|
|
19546
19580
|
copyData() {
|
|
19547
19581
|
navigator.clipboard.writeText(JSON.stringify(this.previewData(), null, 2));
|
|
19548
19582
|
}
|
|
19549
|
-
sanitizePreviewData(value) {
|
|
19583
|
+
sanitizePreviewData(value, withinFileField = false) {
|
|
19550
19584
|
if (Array.isArray(value)) {
|
|
19551
|
-
return value.map(item => this.sanitizePreviewData(item));
|
|
19585
|
+
return value.map(item => this.sanitizePreviewData(item, withinFileField));
|
|
19552
19586
|
}
|
|
19553
19587
|
if (!this.isObjectRecord(value)) {
|
|
19554
19588
|
return value;
|
|
19555
19589
|
}
|
|
19590
|
+
const nextWithinFileField = withinFileField || this.isFileFieldRecord(value);
|
|
19556
19591
|
const sanitized = {};
|
|
19557
19592
|
for (const [key, entryValue] of Object.entries(value)) {
|
|
19558
|
-
if (key === 'data' && this.shouldHideFileData(
|
|
19593
|
+
if (key === 'data' && this.shouldHideFileData(nextWithinFileField, entryValue)) {
|
|
19559
19594
|
continue;
|
|
19560
19595
|
}
|
|
19561
|
-
sanitized[key] = this.sanitizePreviewData(entryValue);
|
|
19596
|
+
sanitized[key] = this.sanitizePreviewData(entryValue, nextWithinFileField);
|
|
19562
19597
|
}
|
|
19563
19598
|
return sanitized;
|
|
19564
19599
|
}
|
|
19565
19600
|
isObjectRecord(value) {
|
|
19566
19601
|
return !!value && typeof value === 'object';
|
|
19567
19602
|
}
|
|
19568
|
-
shouldHideFileData(
|
|
19569
|
-
if (!
|
|
19603
|
+
shouldHideFileData(withinFileField, value) {
|
|
19604
|
+
if (!withinFileField)
|
|
19570
19605
|
return false;
|
|
19571
19606
|
return this.isBytePayload(value) || this.isBase64Payload(value);
|
|
19572
19607
|
}
|
|
19573
19608
|
isFileFieldRecord(value) {
|
|
19574
19609
|
return typeof value['fieldName'] === 'string'
|
|
19575
19610
|
&& Object.hasOwn(value, 'fieldValue')
|
|
19576
|
-
&& Object.hasOwn(value, 'fileType');
|
|
19611
|
+
&& (value['fieldType'] === 'file' || Object.hasOwn(value, 'fileType'));
|
|
19577
19612
|
}
|
|
19578
19613
|
isBytePayload(value) {
|
|
19579
19614
|
if (value instanceof Uint8Array)
|
|
@@ -31774,7 +31809,20 @@ function compareSortableValues(left, right) {
|
|
|
31774
31809
|
}
|
|
31775
31810
|
return String(left ?? '').localeCompare(String(right ?? ''));
|
|
31776
31811
|
}
|
|
31812
|
+
function toDisplayText(value) {
|
|
31813
|
+
if (typeof value === 'string') {
|
|
31814
|
+
const trimmed = value.trim();
|
|
31815
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
31816
|
+
}
|
|
31817
|
+
if (typeof value === 'number' || typeof value === 'boolean') {
|
|
31818
|
+
return String(value);
|
|
31819
|
+
}
|
|
31820
|
+
return undefined;
|
|
31821
|
+
}
|
|
31777
31822
|
class DataProvider {
|
|
31823
|
+
async getValueDisplayPrefix(_field, _engine) {
|
|
31824
|
+
return '';
|
|
31825
|
+
}
|
|
31778
31826
|
// Non-abstract with default implementation for backward compatibility
|
|
31779
31827
|
async queryOptions(field, query, engine) {
|
|
31780
31828
|
const options = await this.getOptions(field, engine);
|
|
@@ -31952,17 +32000,11 @@ class DefaultDataProvider extends DataProvider {
|
|
|
31952
32000
|
return cfg.staticValue;
|
|
31953
32001
|
return currentValue !== undefined ? currentValue : field.defaultValue;
|
|
31954
32002
|
}
|
|
31955
|
-
|
|
31956
|
-
|
|
31957
|
-
rows = this.applyRowFilters(rows, cfg.filters, engine);
|
|
31958
|
-
if (!rows || rows.length === 0) {
|
|
31959
|
-
return currentValue !== undefined ? currentValue : field.defaultValue;
|
|
31960
|
-
}
|
|
31961
|
-
const selectedRow = this.selectScalarRow(rows, cfg, engine);
|
|
31962
|
-
if (cfg.rowSelectionMode === 'selected' && !selectedRow) {
|
|
32003
|
+
const context = await this.getScalarValueContext(cfg, field, engine);
|
|
32004
|
+
if (!context) {
|
|
31963
32005
|
return currentValue !== undefined ? currentValue : field.defaultValue;
|
|
31964
32006
|
}
|
|
31965
|
-
const row =
|
|
32007
|
+
const row = context.row;
|
|
31966
32008
|
const resolvedPath = cfg.valueKey;
|
|
31967
32009
|
const resolvedValue = resolvePathValue(row, resolvedPath);
|
|
31968
32010
|
if (resolvedPath && resolvedValue !== undefined) {
|
|
@@ -31973,6 +32015,27 @@ class DefaultDataProvider extends DataProvider {
|
|
|
31973
32015
|
}
|
|
31974
32016
|
return row;
|
|
31975
32017
|
}
|
|
32018
|
+
async getValueDisplayPrefix(field, engine) {
|
|
32019
|
+
const cfg = getEffectiveDataConfig(field);
|
|
32020
|
+
const prefixPath = cfg.optionLabelPrefixPath?.trim();
|
|
32021
|
+
if (!prefixPath) {
|
|
32022
|
+
return '';
|
|
32023
|
+
}
|
|
32024
|
+
const context = await this.getScalarValueContext(cfg, field, engine);
|
|
32025
|
+
if (!context) {
|
|
32026
|
+
return '';
|
|
32027
|
+
}
|
|
32028
|
+
for (const candidate of [context.row, context.parentRow, context.sourceRow]) {
|
|
32029
|
+
if (!candidate)
|
|
32030
|
+
continue;
|
|
32031
|
+
const resolved = resolvePathValue(candidate, prefixPath);
|
|
32032
|
+
const value = toDisplayText(resolved);
|
|
32033
|
+
if (value) {
|
|
32034
|
+
return value;
|
|
32035
|
+
}
|
|
32036
|
+
}
|
|
32037
|
+
return '';
|
|
32038
|
+
}
|
|
31976
32039
|
async resolveValue(field, value) {
|
|
31977
32040
|
return String(value);
|
|
31978
32041
|
}
|
|
@@ -32020,6 +32083,18 @@ class DefaultDataProvider extends DataProvider {
|
|
|
32020
32083
|
const rows = await this.getRawRows(cfg, field, engine);
|
|
32021
32084
|
return this.resolveCollectionRowContexts(rows, cfg, engine);
|
|
32022
32085
|
}
|
|
32086
|
+
async getScalarValueContext(cfg, field, engine) {
|
|
32087
|
+
const contexts = await this.getOptionRowContexts(cfg, field, engine);
|
|
32088
|
+
const filteredContexts = this.applyOptionRowFilters(contexts, cfg.filters, engine);
|
|
32089
|
+
if (filteredContexts.length === 0) {
|
|
32090
|
+
return undefined;
|
|
32091
|
+
}
|
|
32092
|
+
const selectedContext = this.selectOptionContext(filteredContexts, cfg, engine);
|
|
32093
|
+
if (cfg.rowSelectionMode === 'selected' && !selectedContext) {
|
|
32094
|
+
return undefined;
|
|
32095
|
+
}
|
|
32096
|
+
return selectedContext ?? filteredContexts[0];
|
|
32097
|
+
}
|
|
32023
32098
|
resolveCollectionRowContexts(rows, cfg, engine) {
|
|
32024
32099
|
const parentContexts = this.extractRowContexts(rows, cfg.rowsPath);
|
|
32025
32100
|
if (cfg.rowSelectionMode === 'selected' && cfg.childRowsPath) {
|
|
@@ -32240,10 +32315,8 @@ class DefaultDataProvider extends DataProvider {
|
|
|
32240
32315
|
if (!candidate)
|
|
32241
32316
|
continue;
|
|
32242
32317
|
const resolved = resolvePathValue(candidate, prefixPath);
|
|
32243
|
-
|
|
32244
|
-
|
|
32245
|
-
const value = String(resolved).trim();
|
|
32246
|
-
if (value.length > 0) {
|
|
32318
|
+
const value = toDisplayText(resolved);
|
|
32319
|
+
if (value) {
|
|
32247
32320
|
return value;
|
|
32248
32321
|
}
|
|
32249
32322
|
}
|
|
@@ -32436,6 +32509,8 @@ class TextFieldWidgetComponent {
|
|
|
32436
32509
|
dependencyValueSnapshot = new Map();
|
|
32437
32510
|
isControlFocused = false;
|
|
32438
32511
|
isControlHovered = false;
|
|
32512
|
+
displayPrefix = '';
|
|
32513
|
+
formattedNumberValue = '';
|
|
32439
32514
|
set config(value) {
|
|
32440
32515
|
const previousSignature = this.getDataConfigSignature(this._config);
|
|
32441
32516
|
this._config = value;
|
|
@@ -32450,7 +32525,10 @@ class TextFieldWidgetComponent {
|
|
|
32450
32525
|
if (this.dataProvider && this._config?.dataConfig) {
|
|
32451
32526
|
this.seedDependencySnapshotFromEngine();
|
|
32452
32527
|
void this.refreshValueFromDataSource();
|
|
32528
|
+
return;
|
|
32453
32529
|
}
|
|
32530
|
+
this.displayPrefix = '';
|
|
32531
|
+
this.syncFormattedNumberValue();
|
|
32454
32532
|
}
|
|
32455
32533
|
get config() {
|
|
32456
32534
|
return this._config;
|
|
@@ -32473,6 +32551,12 @@ class TextFieldWidgetComponent {
|
|
|
32473
32551
|
isColorField() {
|
|
32474
32552
|
return this.config?.type === 'color';
|
|
32475
32553
|
}
|
|
32554
|
+
usesFormattedNumberInput() {
|
|
32555
|
+
return this.config?.type === 'number' && this.config?.dataConfig?.formatNumericOptionLabels === true;
|
|
32556
|
+
}
|
|
32557
|
+
hasDisplayPrefix() {
|
|
32558
|
+
return !this.isTextarea() && !this.isColorField() && this.displayPrefix.trim().length > 0;
|
|
32559
|
+
}
|
|
32476
32560
|
getControlClass(multiline = false) {
|
|
32477
32561
|
return getTextControlClass({
|
|
32478
32562
|
invalid: !!this.error,
|
|
@@ -32510,6 +32594,9 @@ class TextFieldWidgetComponent {
|
|
|
32510
32594
|
if (this.dataProvider && this.config.dataConfig) {
|
|
32511
32595
|
void this.refreshValueFromDataSource();
|
|
32512
32596
|
}
|
|
32597
|
+
else {
|
|
32598
|
+
this.syncFormattedNumberValue();
|
|
32599
|
+
}
|
|
32513
32600
|
// Sync enabled state based on config + rules
|
|
32514
32601
|
this.syncEnabledState();
|
|
32515
32602
|
if (this.engine) {
|
|
@@ -32545,6 +32632,9 @@ class TextFieldWidgetComponent {
|
|
|
32545
32632
|
this.control.valueChanges
|
|
32546
32633
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
32547
32634
|
.subscribe(val => {
|
|
32635
|
+
if (this.usesFormattedNumberInput() && !this.isControlFocused) {
|
|
32636
|
+
this.syncFormattedNumberValue();
|
|
32637
|
+
}
|
|
32548
32638
|
if (this.engine) {
|
|
32549
32639
|
this.engine.setValue(this.config.name, val);
|
|
32550
32640
|
this.engine.emitUiEvent({ fieldId: this.config.id, fieldName: this.config.name, type: 'change', value: val });
|
|
@@ -32556,6 +32646,7 @@ class TextFieldWidgetComponent {
|
|
|
32556
32646
|
}
|
|
32557
32647
|
onFocus() {
|
|
32558
32648
|
this.isControlFocused = true;
|
|
32649
|
+
this.syncFormattedNumberValue();
|
|
32559
32650
|
if (this.engine)
|
|
32560
32651
|
this.engine.emitUiEvent({ fieldId: this.config.id, fieldName: this.config.name, type: 'focus' });
|
|
32561
32652
|
}
|
|
@@ -32565,6 +32656,8 @@ class TextFieldWidgetComponent {
|
|
|
32565
32656
|
}
|
|
32566
32657
|
onBlur() {
|
|
32567
32658
|
this.isControlFocused = false;
|
|
32659
|
+
this.control.markAsTouched();
|
|
32660
|
+
this.syncFormattedNumberValue();
|
|
32568
32661
|
if (this.engine) {
|
|
32569
32662
|
this.engine.emitUiEvent({ fieldId: this.config.id, fieldName: this.config.name, type: 'blur' });
|
|
32570
32663
|
if (this.control.touched) {
|
|
@@ -32612,6 +32705,15 @@ class TextFieldWidgetComponent {
|
|
|
32612
32705
|
invalid: !!this.error
|
|
32613
32706
|
}), splitControlSurfaceStyles(this.config.style).controlStyles);
|
|
32614
32707
|
}
|
|
32708
|
+
getSingleLineControlStyles() {
|
|
32709
|
+
const styles = this.getControlStyles();
|
|
32710
|
+
if (!this.hasDisplayPrefix()) {
|
|
32711
|
+
return styles;
|
|
32712
|
+
}
|
|
32713
|
+
return mergeAndNormalize(styles, {
|
|
32714
|
+
paddingLeft: `calc(20px + ${Math.max(this.displayPrefix.length, 1)}ch)`
|
|
32715
|
+
});
|
|
32716
|
+
}
|
|
32615
32717
|
hasWrapperFrame() {
|
|
32616
32718
|
return hasWrapperSurfaceStyles(this.config.style);
|
|
32617
32719
|
}
|
|
@@ -32650,9 +32752,11 @@ class TextFieldWidgetComponent {
|
|
|
32650
32752
|
return;
|
|
32651
32753
|
try {
|
|
32652
32754
|
const val = await this.dataProvider.getValue(this.config, this.engine);
|
|
32755
|
+
this.displayPrefix = await this.dataProvider.getValueDisplayPrefix(this.config, this.engine);
|
|
32653
32756
|
if (val === undefined || val === null)
|
|
32654
32757
|
return;
|
|
32655
32758
|
this.control.setValue(val, { emitEvent: false });
|
|
32759
|
+
this.syncFormattedNumberValue();
|
|
32656
32760
|
if (this.engine) {
|
|
32657
32761
|
this.engine.setValue(this.config.name, val);
|
|
32658
32762
|
}
|
|
@@ -32678,6 +32782,9 @@ class TextFieldWidgetComponent {
|
|
|
32678
32782
|
sourceKey,
|
|
32679
32783
|
String(dataConfig.valueKey ?? ''),
|
|
32680
32784
|
String(dataConfig.rowsPath ?? ''),
|
|
32785
|
+
String(dataConfig.formatNumericOptionLabels ?? ''),
|
|
32786
|
+
String(dataConfig.optionLabelPrefixPath ?? ''),
|
|
32787
|
+
String(dataConfig.optionLabelPrefixFieldId ?? ''),
|
|
32681
32788
|
String(dataConfig.rowSelectionMode ?? ''),
|
|
32682
32789
|
String(dataConfig.selectionFieldId ?? ''),
|
|
32683
32790
|
String(dataConfig.selectionMatchPath ?? ''),
|
|
@@ -32733,6 +32840,59 @@ class TextFieldWidgetComponent {
|
|
|
32733
32840
|
.filter(field => dependencyIds.has(field.id))
|
|
32734
32841
|
.map(field => field.name);
|
|
32735
32842
|
}
|
|
32843
|
+
onFormattedNumberInput(event) {
|
|
32844
|
+
const input = event.target;
|
|
32845
|
+
this.formattedNumberValue = input.value;
|
|
32846
|
+
if (this.control.pristine) {
|
|
32847
|
+
this.control.markAsDirty();
|
|
32848
|
+
}
|
|
32849
|
+
const normalized = input.value.replace(/,/g, '').trim();
|
|
32850
|
+
if (!normalized) {
|
|
32851
|
+
this.control.setValue(null);
|
|
32852
|
+
return;
|
|
32853
|
+
}
|
|
32854
|
+
const parsed = Number(normalized);
|
|
32855
|
+
this.control.setValue(Number.isFinite(parsed) ? parsed : null);
|
|
32856
|
+
}
|
|
32857
|
+
syncFormattedNumberValue() {
|
|
32858
|
+
if (!this.usesFormattedNumberInput()) {
|
|
32859
|
+
return;
|
|
32860
|
+
}
|
|
32861
|
+
const rawValue = this.control.value;
|
|
32862
|
+
if (rawValue === undefined || rawValue === null || rawValue === '') {
|
|
32863
|
+
this.formattedNumberValue = '';
|
|
32864
|
+
return;
|
|
32865
|
+
}
|
|
32866
|
+
if (typeof rawValue !== 'string' && typeof rawValue !== 'number') {
|
|
32867
|
+
this.formattedNumberValue = '';
|
|
32868
|
+
return;
|
|
32869
|
+
}
|
|
32870
|
+
const normalized = String(rawValue).replace(/,/g, '').trim();
|
|
32871
|
+
if (!normalized) {
|
|
32872
|
+
this.formattedNumberValue = '';
|
|
32873
|
+
return;
|
|
32874
|
+
}
|
|
32875
|
+
if (this.isControlFocused) {
|
|
32876
|
+
this.formattedNumberValue = normalized;
|
|
32877
|
+
return;
|
|
32878
|
+
}
|
|
32879
|
+
this.formattedNumberValue = this.formatNumericValue(normalized);
|
|
32880
|
+
}
|
|
32881
|
+
formatNumericValue(value) {
|
|
32882
|
+
if (!/^-?\d+(\.\d+)?$/.test(value)) {
|
|
32883
|
+
return value;
|
|
32884
|
+
}
|
|
32885
|
+
const numericValue = Number(value);
|
|
32886
|
+
if (!Number.isFinite(numericValue)) {
|
|
32887
|
+
return value;
|
|
32888
|
+
}
|
|
32889
|
+
const fractionPart = value.split('.')[1];
|
|
32890
|
+
return new Intl.NumberFormat(undefined, {
|
|
32891
|
+
useGrouping: true,
|
|
32892
|
+
minimumFractionDigits: fractionPart?.length ?? 0,
|
|
32893
|
+
maximumFractionDigits: fractionPart?.length ?? 0
|
|
32894
|
+
}).format(numericValue);
|
|
32895
|
+
}
|
|
32736
32896
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TextFieldWidgetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
32737
32897
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: TextFieldWidgetComponent, isStandalone: true, selector: "app-text-field-widget", inputs: { config: "config", engine: "engine", control: "control" }, ngImport: i0, template: `
|
|
32738
32898
|
<div [class]="fieldContainerClass"
|
|
@@ -32797,7 +32957,46 @@ class TextFieldWidgetComponent {
|
|
|
32797
32957
|
[cpFallbackColor]="'#000000'"
|
|
32798
32958
|
[cpDisabled]="config.readonly || !enabled"
|
|
32799
32959
|
(colorPickerChange)="onColorPickerChange($event)">
|
|
32960
|
+
} @else if (usesFormattedNumberInput()) {
|
|
32961
|
+
@if (hasDisplayPrefix()) {
|
|
32962
|
+
<span
|
|
32963
|
+
class="pointer-events-none absolute left-3 top-1/2 z-[1] -translate-y-1/2 text-sm text-slate-500"
|
|
32964
|
+
data-fd-field-prefix>
|
|
32965
|
+
{{ displayPrefix }}
|
|
32966
|
+
</span>
|
|
32967
|
+
}
|
|
32968
|
+
<input
|
|
32969
|
+
[id]="fieldId"
|
|
32970
|
+
type="text"
|
|
32971
|
+
inputmode="decimal"
|
|
32972
|
+
[placeholder]="config.placeholder || ''"
|
|
32973
|
+
[value]="formattedNumberValue"
|
|
32974
|
+
(input)="onFormattedNumberInput($event)"
|
|
32975
|
+
(click)="onClick()"
|
|
32976
|
+
(focus)="onFocus()"
|
|
32977
|
+
(blur)="onBlur()"
|
|
32978
|
+
(mouseenter)="onMouseEnter()"
|
|
32979
|
+
(mouseleave)="onMouseLeave()"
|
|
32980
|
+
[readonly]="config.readonly"
|
|
32981
|
+
[disabled]="control.disabled"
|
|
32982
|
+
[attr.aria-required]="required"
|
|
32983
|
+
[attr.aria-invalid]="!!error"
|
|
32984
|
+
[attr.aria-describedby]="getAriaDescribedBy()"
|
|
32985
|
+
[attr.aria-label]="getAccessibleLabel()"
|
|
32986
|
+
[class]="getControlClass()"
|
|
32987
|
+
[ngStyle]="getSingleLineControlStyles()"
|
|
32988
|
+
data-fd="field-control"
|
|
32989
|
+
[attr.min]="config.html5?.min"
|
|
32990
|
+
[attr.max]="config.html5?.max"
|
|
32991
|
+
[attr.step]="config.html5?.step">
|
|
32800
32992
|
} @else {
|
|
32993
|
+
@if (hasDisplayPrefix()) {
|
|
32994
|
+
<span
|
|
32995
|
+
class="pointer-events-none absolute left-3 top-1/2 z-[1] -translate-y-1/2 text-sm text-slate-500"
|
|
32996
|
+
data-fd-field-prefix>
|
|
32997
|
+
{{ displayPrefix }}
|
|
32998
|
+
</span>
|
|
32999
|
+
}
|
|
32801
33000
|
<input
|
|
32802
33001
|
[id]="fieldId"
|
|
32803
33002
|
[type]="config.type"
|
|
@@ -32814,7 +33013,7 @@ class TextFieldWidgetComponent {
|
|
|
32814
33013
|
[attr.aria-describedby]="getAriaDescribedBy()"
|
|
32815
33014
|
[attr.aria-label]="getAccessibleLabel()"
|
|
32816
33015
|
[class]="getControlClass()"
|
|
32817
|
-
[ngStyle]="
|
|
33016
|
+
[ngStyle]="getSingleLineControlStyles()"
|
|
32818
33017
|
data-fd="field-control"
|
|
32819
33018
|
[attr.min]="config.html5?.min"
|
|
32820
33019
|
[attr.max]="config.html5?.max"
|
|
@@ -32901,7 +33100,46 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
32901
33100
|
[cpFallbackColor]="'#000000'"
|
|
32902
33101
|
[cpDisabled]="config.readonly || !enabled"
|
|
32903
33102
|
(colorPickerChange)="onColorPickerChange($event)">
|
|
33103
|
+
} @else if (usesFormattedNumberInput()) {
|
|
33104
|
+
@if (hasDisplayPrefix()) {
|
|
33105
|
+
<span
|
|
33106
|
+
class="pointer-events-none absolute left-3 top-1/2 z-[1] -translate-y-1/2 text-sm text-slate-500"
|
|
33107
|
+
data-fd-field-prefix>
|
|
33108
|
+
{{ displayPrefix }}
|
|
33109
|
+
</span>
|
|
33110
|
+
}
|
|
33111
|
+
<input
|
|
33112
|
+
[id]="fieldId"
|
|
33113
|
+
type="text"
|
|
33114
|
+
inputmode="decimal"
|
|
33115
|
+
[placeholder]="config.placeholder || ''"
|
|
33116
|
+
[value]="formattedNumberValue"
|
|
33117
|
+
(input)="onFormattedNumberInput($event)"
|
|
33118
|
+
(click)="onClick()"
|
|
33119
|
+
(focus)="onFocus()"
|
|
33120
|
+
(blur)="onBlur()"
|
|
33121
|
+
(mouseenter)="onMouseEnter()"
|
|
33122
|
+
(mouseleave)="onMouseLeave()"
|
|
33123
|
+
[readonly]="config.readonly"
|
|
33124
|
+
[disabled]="control.disabled"
|
|
33125
|
+
[attr.aria-required]="required"
|
|
33126
|
+
[attr.aria-invalid]="!!error"
|
|
33127
|
+
[attr.aria-describedby]="getAriaDescribedBy()"
|
|
33128
|
+
[attr.aria-label]="getAccessibleLabel()"
|
|
33129
|
+
[class]="getControlClass()"
|
|
33130
|
+
[ngStyle]="getSingleLineControlStyles()"
|
|
33131
|
+
data-fd="field-control"
|
|
33132
|
+
[attr.min]="config.html5?.min"
|
|
33133
|
+
[attr.max]="config.html5?.max"
|
|
33134
|
+
[attr.step]="config.html5?.step">
|
|
32904
33135
|
} @else {
|
|
33136
|
+
@if (hasDisplayPrefix()) {
|
|
33137
|
+
<span
|
|
33138
|
+
class="pointer-events-none absolute left-3 top-1/2 z-[1] -translate-y-1/2 text-sm text-slate-500"
|
|
33139
|
+
data-fd-field-prefix>
|
|
33140
|
+
{{ displayPrefix }}
|
|
33141
|
+
</span>
|
|
33142
|
+
}
|
|
32905
33143
|
<input
|
|
32906
33144
|
[id]="fieldId"
|
|
32907
33145
|
[type]="config.type"
|
|
@@ -32918,7 +33156,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
32918
33156
|
[attr.aria-describedby]="getAriaDescribedBy()"
|
|
32919
33157
|
[attr.aria-label]="getAccessibleLabel()"
|
|
32920
33158
|
[class]="getControlClass()"
|
|
32921
|
-
[ngStyle]="
|
|
33159
|
+
[ngStyle]="getSingleLineControlStyles()"
|
|
32922
33160
|
data-fd="field-control"
|
|
32923
33161
|
[attr.min]="config.html5?.min"
|
|
32924
33162
|
[attr.max]="config.html5?.max"
|
|
@@ -37660,6 +37898,10 @@ function generateId$2() {
|
|
|
37660
37898
|
const COMMON_GROUP_FIELDS = [
|
|
37661
37899
|
{ key: 'groupKey', type: 'text', label: 'Group Key', placeholder: 'documents', helpText: 'Group fields into one object on submit/preview (uses the field key inside the group).' }
|
|
37662
37900
|
];
|
|
37901
|
+
const COMMON_INTERACTIVITY_FIELDS = [
|
|
37902
|
+
{ key: 'readonly', type: 'checkbox', label: 'Read Only' },
|
|
37903
|
+
{ key: 'disabled', type: 'checkbox', label: 'Disabled' }
|
|
37904
|
+
];
|
|
37663
37905
|
const COMMON_BASIC_FIELDS = [
|
|
37664
37906
|
{ key: 'name', type: 'text', label: 'Field Key (Name)' },
|
|
37665
37907
|
{ key: 'label', type: 'text', label: 'Label' },
|
|
@@ -37667,6 +37909,7 @@ const COMMON_BASIC_FIELDS = [
|
|
|
37667
37909
|
{ key: 'placeholder', type: 'text', label: 'Placeholder' },
|
|
37668
37910
|
{ key: 'helpText', type: 'text', label: 'Help Text' }, // Hint
|
|
37669
37911
|
{ key: 'tooltip', type: 'text', label: 'Tooltip' },
|
|
37912
|
+
...COMMON_INTERACTIVITY_FIELDS,
|
|
37670
37913
|
...COMMON_GROUP_FIELDS
|
|
37671
37914
|
];
|
|
37672
37915
|
const FILE_BASIC_FIELDS = [
|
|
@@ -37675,6 +37918,7 @@ const FILE_BASIC_FIELDS = [
|
|
|
37675
37918
|
{ key: 'showLabel', type: 'checkbox', label: 'Show Native Label' },
|
|
37676
37919
|
{ key: 'helpText', type: 'text', label: 'Help Text' },
|
|
37677
37920
|
{ key: 'tooltip', type: 'text', label: 'Tooltip' },
|
|
37921
|
+
...COMMON_INTERACTIVITY_FIELDS,
|
|
37678
37922
|
...COMMON_GROUP_FIELDS
|
|
37679
37923
|
];
|
|
37680
37924
|
const COMMON_APPEARANCE_FIELDS = [
|
|
@@ -37699,9 +37943,7 @@ const COMMON_APPEARANCE_FIELDS = [
|
|
|
37699
37943
|
{ label: 'Third Width (33%)', value: '33.33%' },
|
|
37700
37944
|
{ label: 'Quarter Width (25%)', value: '25%' }
|
|
37701
37945
|
]
|
|
37702
|
-
}
|
|
37703
|
-
{ key: 'readonly', type: 'checkbox', label: 'Read Only' },
|
|
37704
|
-
{ key: 'disabled', type: 'checkbox', label: 'Disabled' }
|
|
37946
|
+
}
|
|
37705
37947
|
];
|
|
37706
37948
|
const COMMON_STYLE_SECTIONS = [
|
|
37707
37949
|
STYLE_LAYOUT_SECTION,
|
|
@@ -37752,6 +37994,7 @@ const BUTTON_PROPERTIES = [
|
|
|
37752
37994
|
label: 'Style',
|
|
37753
37995
|
fields: [
|
|
37754
37996
|
{ key: 'variant', type: 'select', label: 'Variant', options: BUTTON_VARIANT_OPTIONS },
|
|
37997
|
+
...COMMON_INTERACTIVITY_FIELDS,
|
|
37755
37998
|
...COMMON_APPEARANCE_FIELDS
|
|
37756
37999
|
]
|
|
37757
38000
|
},
|
|
@@ -37770,6 +38013,7 @@ const IMAGE_BUTTON_PROPERTIES = [
|
|
|
37770
38013
|
label: 'Style',
|
|
37771
38014
|
fields: [
|
|
37772
38015
|
{ key: 'variant', type: 'select', label: 'Variant', options: BUTTON_VARIANT_OPTIONS },
|
|
38016
|
+
...COMMON_INTERACTIVITY_FIELDS,
|
|
37773
38017
|
...COMMON_APPEARANCE_FIELDS
|
|
37774
38018
|
]
|
|
37775
38019
|
},
|
|
@@ -37819,6 +38063,7 @@ const REPEATABLE_WIDGET_PROPERTIES = [
|
|
|
37819
38063
|
{ key: 'showLabel', type: 'checkbox', label: 'Show Native Label' },
|
|
37820
38064
|
{ key: 'helpText', type: 'text', label: 'Help Text' },
|
|
37821
38065
|
{ key: 'tooltip', type: 'text', label: 'Tooltip' },
|
|
38066
|
+
...COMMON_INTERACTIVITY_FIELDS,
|
|
37822
38067
|
...COMMON_GROUP_FIELDS
|
|
37823
38068
|
]
|
|
37824
38069
|
},
|