@memberjunction/ng-base-forms 5.10.1 → 5.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/container/record-form-container.component.js +2 -2
- package/dist/lib/explorer-entity-data-grid.component.d.ts.map +1 -1
- package/dist/lib/explorer-entity-data-grid.component.js +12 -19
- package/dist/lib/explorer-entity-data-grid.component.js.map +1 -1
- package/dist/lib/field/form-field.component.d.ts.map +1 -1
- package/dist/lib/field/form-field.component.js +7 -2
- package/dist/lib/field/form-field.component.js.map +1 -1
- package/dist/lib/isa-related-panel/isa-related-card.component.js +2 -2
- package/dist/lib/isa-related-panel/isa-related-panel.component.js +2 -2
- package/dist/lib/panel/collapsible-panel.component.js +2 -2
- package/dist/lib/section-manager/section-manager.component.js +2 -2
- package/dist/lib/toolbar/form-toolbar.component.js +2 -2
- package/package.json +8 -8
|
@@ -531,11 +531,11 @@ export class MjRecordFormContainerComponent {
|
|
|
531
531
|
i0.ɵɵconditional(ctx.ShowListManagement && ctx.EffectiveRecord ? 10 : -1);
|
|
532
532
|
i0.ɵɵadvance();
|
|
533
533
|
i0.ɵɵproperty("Sections", ctx.SectionManagerItems)("SectionOrder", ctx.SectionManagerOrder)("Visible", ctx.ShowSectionManager);
|
|
534
|
-
} }, dependencies: [i1.RecordChangesComponent, i2.ListManagementDialogComponent, i3.MjFormToolbarComponent, i4.MjSectionManagerComponent, i5.MjIsaRelatedPanelComponent], styles: ["/* ============================================\n RECORD FORM CONTAINER\n Top-level wrapper: toolbar + scrollable content\n ============================================ */\nmj-record-form-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n position: relative;\n overflow: hidden;\n}\n\n/* ViewEncapsulation.None fallback \u2014 ensure the element itself constrains overflow */\nmj-record-form-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n position: relative;\n overflow: hidden;\n}\n\n/* ============================================\n SCROLL AREA (full-width so mouse wheel works anywhere)\n ============================================ */\n.mj-forms-scroll-area {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n background:
|
|
534
|
+
} }, dependencies: [i1.RecordChangesComponent, i2.ListManagementDialogComponent, i3.MjFormToolbarComponent, i4.MjSectionManagerComponent, i5.MjIsaRelatedPanelComponent], styles: ["/* ============================================\n RECORD FORM CONTAINER \u2014 uses global --mj-* design tokens\n Top-level wrapper: toolbar + scrollable content\n ============================================ */\nmj-record-form-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n position: relative;\n overflow: hidden;\n}\n\n/* ViewEncapsulation.None fallback \u2014 ensure the element itself constrains overflow */\nmj-record-form-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n position: relative;\n overflow: hidden;\n}\n\n/* ============================================\n SCROLL AREA (full-width so mouse wheel works anywhere)\n ============================================ */\n.mj-forms-scroll-area {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n background: var(--mj-bg-page);\n}\n\n/* ============================================\n PANELS CONTAINER (centered content within scroll area)\n ============================================ */\n.mj-forms-panels-container {\n padding: 24px 32px 48px;\n max-width: 920px;\n margin: 0 auto;\n width: 100%;\n box-sizing: border-box;\n}\n\n/* Widen max-width when ISA side panel is present */\n.mj-forms-panels--has-isa-panel {\n max-width: 1240px;\n}\n\n.mj-forms-panels--full-width {\n max-width: none;\n padding-left: 24px;\n padding-right: 24px;\n}\n\n/* Flex row layout: form panels + optional ISA side panel */\n.mj-forms-layout-row {\n display: flex;\n gap: 20px;\n align-items: flex-start;\n}\n\n/* All panels in a single flex container \u2014 CSS order drives sequencing */\n.mj-forms-all-panels {\n display: flex;\n flex-direction: column;\n gap: 16px;\n flex: 1;\n min-width: 0;\n}\n\n/* Hide related entity panels in edit mode (variant host class on mj-collapsible-panel) */\n.mj-forms-panels--edit-mode .mj-panel--related-entity {\n display: none;\n}\n\n/* ============================================\n EMPTY SEARCH STATE\n ============================================ */\n.mj-forms-empty-search-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 80px 24px;\n text-align: center;\n min-height: 400px;\n}\n\n.mj-forms-empty-search-icon {\n width: 80px;\n height: 80px;\n border-radius: var(--mj-radius-full);\n background: var(--mj-bg-surface-sunken);\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 24px;\n}\n\n.mj-forms-empty-search-icon i {\n font-size: 32px;\n color: var(--mj-text-muted);\n}\n\n.mj-forms-empty-search-title {\n font-size: var(--mj-text-xl);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n margin: 0 0 12px 0;\n}\n\n.mj-forms-empty-search-message {\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n line-height: 1.6;\n max-width: 400px;\n margin: 0;\n}\n\n.mj-forms-empty-search-message strong {\n color: var(--mj-text-primary);\n font-weight: var(--mj-font-semibold);\n}\n\n.mj-forms-empty-search-link {\n color: var(--mj-brand-primary);\n text-decoration: none;\n font-weight: var(--mj-font-medium);\n}\n\n.mj-forms-empty-search-link:hover {\n text-decoration: underline;\n}\n\n/* ============================================\n RESPONSIVE\n ============================================ */\n@media (max-width: 768px) {\n .mj-forms-panels-container {\n padding: 16px 12px 32px;\n }\n}\n"], encapsulation: 2, changeDetection: 0 });
|
|
535
535
|
}
|
|
536
536
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MjRecordFormContainerComponent, [{
|
|
537
537
|
type: Component,
|
|
538
|
-
args: [{ standalone: false, selector: 'mj-record-form-container', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<!-- ============================================\n BEFORE-TOOLBAR SLOT\n ============================================ -->\n<ng-content select=\"[before-toolbar]\"></ng-content>\n\n<!-- ============================================\n TOOLBAR (bridges FormComponent state \u2192 toolbar inputs)\n ============================================ -->\n<mj-form-toolbar\n [Record]=\"EffectiveRecord\"\n [EditMode]=\"EffectiveEditMode\"\n [UserCanEdit]=\"EffectiveUserCanEdit\"\n [UserCanDelete]=\"EffectiveUserCanDelete\"\n [IsFavorite]=\"EffectiveIsFavorite\"\n [FavoriteInitDone]=\"EffectiveFavoriteInitDone\"\n [IsDirty]=\"EffectiveIsDirty\"\n [DirtyFieldNames]=\"EffectiveDirtyFieldNames\"\n [ListCount]=\"ListCount\"\n [EntityInfo]=\"EffectiveEntityInfo\"\n [Config]=\"ToolbarConfig\"\n [IsSaving]=\"EffectiveIsSaving\"\n [VisibleSectionCount]=\"VisibleSectionCount\"\n [TotalSectionCount]=\"TotalSectionCount\"\n [ExpandedSectionCount]=\"ExpandedSectionCount\"\n [SearchFilter]=\"EffectiveSearchFilter\"\n [ShowEmptyFields]=\"EffectiveShowEmptyFields\"\n [WidthMode]=\"EffectiveWidthMode\"\n [HasCustomSectionOrder]=\"EffectiveHasCustomSectionOrder\"\n (Navigate)=\"OnNavigate($event)\"\n (EditModeChange)=\"OnEditModeChange($event)\"\n (BeforeSave)=\"BeforeSave.emit($event)\"\n (SaveRequested)=\"OnSaveRequested()\"\n (BeforeCancel)=\"BeforeCancel.emit($event)\"\n (CancelRequested)=\"OnCancelRequested()\"\n (BeforeDelete)=\"BeforeDelete.emit($event)\"\n (DeleteRequested)=\"OnDeleteRequested()\"\n (FavoriteToggled)=\"OnFavoriteToggled()\"\n (BeforeHistoryView)=\"BeforeHistoryView.emit($event)\"\n (HistoryRequested)=\"OnHistoryRequested()\"\n (BeforeListManagement)=\"BeforeListManagement.emit($event)\"\n (ListManagementRequested)=\"OnListManagementRequested()\"\n (ShowChangesRequested)=\"OnShowChangesRequested()\"\n (CustomButtonClick)=\"CustomButtonClick.emit($event)\"\n (FilterChange)=\"OnFilterChange($event)\"\n (ExpandAllRequested)=\"OnExpandAll()\"\n (CollapseAllRequested)=\"OnCollapseAll()\"\n (ShowEmptyFieldsChange)=\"OnShowEmptyFieldsChange($event)\"\n (WidthModeChange)=\"OnWidthModeChange($event)\"\n (ResetSectionOrderRequested)=\"OnResetSectionOrder()\"\n (ManageSectionsRequested)=\"OnManageSections()\">\n</mj-form-toolbar>\n\n<!-- ============================================\n SCROLL AREA (full-width so mouse wheel works anywhere)\n ============================================ -->\n<div class=\"mj-forms-scroll-area\">\n <div class=\"mj-forms-panels-container\"\n [class.mj-forms-panels--full-width]=\"EffectiveWidthMode === 'full-width'\"\n [class.mj-forms-panels--edit-mode]=\"EffectiveEditMode\"\n [class.mj-forms-panels--has-isa-panel]=\"HasIsaRelatedItems\">\n <!-- Flex row: form panels on left, ISA side panel on right -->\n <div class=\"mj-forms-layout-row\">\n <!-- All panels in a single flex container \u2014 CSS order drives sequencing -->\n <div class=\"mj-forms-all-panels\">\n <ng-content></ng-content>\n\n <!-- Empty state when no sections match search -->\n @if (EffectiveSearchFilter && VisibleSectionCount === 0) {\n <div class=\"mj-forms-empty-search-state\">\n <div class=\"mj-forms-empty-search-icon\">\n <i class=\"fa-solid fa-magnifying-glass\"></i>\n </div>\n <h3 class=\"mj-forms-empty-search-title\">No sections found</h3>\n <p class=\"mj-forms-empty-search-message\">\n No sections match \"<strong>{{ EffectiveSearchFilter }}</strong>\".\n <br>Try a different search term or <a href=\"#\" (click)=\"OnFilterChange(''); $event.preventDefault()\" class=\"mj-forms-empty-search-link\">clear the search</a>.\n </p>\n </div>\n }\n </div>\n\n <!-- IS-A Related Records Side Panel -->\n <mj-isa-related-panel\n [Record]=\"EffectiveRecord\"\n [EditMode]=\"EffectiveEditMode\"\n [Collapsed]=\"EffectiveWidthMode === 'full-width'\"\n (Navigate)=\"OnNavigate($event)\">\n </mj-isa-related-panel>\n </div>\n </div>\n</div>\n\n<!-- ============================================\n RECORD CHANGES DRAWER (shown when history button clicked)\n ============================================ -->\n@if (ShowRecordChanges && EffectiveRecord) {\n <mj-record-changes\n [record]=\"EffectiveRecord\"\n (dialogClosed)=\"OnRecordChangesClosed()\">\n </mj-record-changes>\n}\n\n<!-- ============================================\n LIST MANAGEMENT DIALOG (shown when lists button clicked)\n ============================================ -->\n@if (ShowListManagement && EffectiveRecord) {\n <mj-list-management-dialog\n [visible]=\"ShowListManagement\"\n [config]=\"{\n mode: 'manage',\n entityId: EffectiveRecord.EntityInfo.ID,\n entityName: EffectiveRecord.EntityInfo.Name,\n recordIds: [EffectiveRecord.PrimaryKey.Values()[0]],\n allowCreate: true\n }\"\n (complete)=\"OnListManagementClosed()\"\n (cancel)=\"OnListManagementClosed()\">\n </mj-list-management-dialog>\n}\n\n<!-- ============================================\n SECTION MANAGER DRAWER (shown when manage-sections button clicked)\n ============================================ -->\n<mj-section-manager\n [Sections]=\"SectionManagerItems\"\n [SectionOrder]=\"SectionManagerOrder\"\n [Visible]=\"ShowSectionManager\"\n (SectionOrderChange)=\"OnSectionOrderChange($event)\"\n (ResetRequested)=\"OnSectionManagerReset()\"\n (Closed)=\"OnSectionManagerClosed()\">\n</mj-section-manager>\n", styles: ["/* ============================================\n RECORD FORM CONTAINER\n Top-level wrapper: toolbar + scrollable content\n ============================================ */\nmj-record-form-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n position: relative;\n overflow: hidden;\n}\n\n/* ViewEncapsulation.None fallback \u2014 ensure the element itself constrains overflow */\nmj-record-form-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n position: relative;\n overflow: hidden;\n}\n\n/* ============================================\n SCROLL AREA (full-width so mouse wheel works anywhere)\n ============================================ */\n.mj-forms-scroll-area {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n background:
|
|
538
|
+
args: [{ standalone: false, selector: 'mj-record-form-container', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<!-- ============================================\n BEFORE-TOOLBAR SLOT\n ============================================ -->\n<ng-content select=\"[before-toolbar]\"></ng-content>\n\n<!-- ============================================\n TOOLBAR (bridges FormComponent state \u2192 toolbar inputs)\n ============================================ -->\n<mj-form-toolbar\n [Record]=\"EffectiveRecord\"\n [EditMode]=\"EffectiveEditMode\"\n [UserCanEdit]=\"EffectiveUserCanEdit\"\n [UserCanDelete]=\"EffectiveUserCanDelete\"\n [IsFavorite]=\"EffectiveIsFavorite\"\n [FavoriteInitDone]=\"EffectiveFavoriteInitDone\"\n [IsDirty]=\"EffectiveIsDirty\"\n [DirtyFieldNames]=\"EffectiveDirtyFieldNames\"\n [ListCount]=\"ListCount\"\n [EntityInfo]=\"EffectiveEntityInfo\"\n [Config]=\"ToolbarConfig\"\n [IsSaving]=\"EffectiveIsSaving\"\n [VisibleSectionCount]=\"VisibleSectionCount\"\n [TotalSectionCount]=\"TotalSectionCount\"\n [ExpandedSectionCount]=\"ExpandedSectionCount\"\n [SearchFilter]=\"EffectiveSearchFilter\"\n [ShowEmptyFields]=\"EffectiveShowEmptyFields\"\n [WidthMode]=\"EffectiveWidthMode\"\n [HasCustomSectionOrder]=\"EffectiveHasCustomSectionOrder\"\n (Navigate)=\"OnNavigate($event)\"\n (EditModeChange)=\"OnEditModeChange($event)\"\n (BeforeSave)=\"BeforeSave.emit($event)\"\n (SaveRequested)=\"OnSaveRequested()\"\n (BeforeCancel)=\"BeforeCancel.emit($event)\"\n (CancelRequested)=\"OnCancelRequested()\"\n (BeforeDelete)=\"BeforeDelete.emit($event)\"\n (DeleteRequested)=\"OnDeleteRequested()\"\n (FavoriteToggled)=\"OnFavoriteToggled()\"\n (BeforeHistoryView)=\"BeforeHistoryView.emit($event)\"\n (HistoryRequested)=\"OnHistoryRequested()\"\n (BeforeListManagement)=\"BeforeListManagement.emit($event)\"\n (ListManagementRequested)=\"OnListManagementRequested()\"\n (ShowChangesRequested)=\"OnShowChangesRequested()\"\n (CustomButtonClick)=\"CustomButtonClick.emit($event)\"\n (FilterChange)=\"OnFilterChange($event)\"\n (ExpandAllRequested)=\"OnExpandAll()\"\n (CollapseAllRequested)=\"OnCollapseAll()\"\n (ShowEmptyFieldsChange)=\"OnShowEmptyFieldsChange($event)\"\n (WidthModeChange)=\"OnWidthModeChange($event)\"\n (ResetSectionOrderRequested)=\"OnResetSectionOrder()\"\n (ManageSectionsRequested)=\"OnManageSections()\">\n</mj-form-toolbar>\n\n<!-- ============================================\n SCROLL AREA (full-width so mouse wheel works anywhere)\n ============================================ -->\n<div class=\"mj-forms-scroll-area\">\n <div class=\"mj-forms-panels-container\"\n [class.mj-forms-panels--full-width]=\"EffectiveWidthMode === 'full-width'\"\n [class.mj-forms-panels--edit-mode]=\"EffectiveEditMode\"\n [class.mj-forms-panels--has-isa-panel]=\"HasIsaRelatedItems\">\n <!-- Flex row: form panels on left, ISA side panel on right -->\n <div class=\"mj-forms-layout-row\">\n <!-- All panels in a single flex container \u2014 CSS order drives sequencing -->\n <div class=\"mj-forms-all-panels\">\n <ng-content></ng-content>\n\n <!-- Empty state when no sections match search -->\n @if (EffectiveSearchFilter && VisibleSectionCount === 0) {\n <div class=\"mj-forms-empty-search-state\">\n <div class=\"mj-forms-empty-search-icon\">\n <i class=\"fa-solid fa-magnifying-glass\"></i>\n </div>\n <h3 class=\"mj-forms-empty-search-title\">No sections found</h3>\n <p class=\"mj-forms-empty-search-message\">\n No sections match \"<strong>{{ EffectiveSearchFilter }}</strong>\".\n <br>Try a different search term or <a href=\"#\" (click)=\"OnFilterChange(''); $event.preventDefault()\" class=\"mj-forms-empty-search-link\">clear the search</a>.\n </p>\n </div>\n }\n </div>\n\n <!-- IS-A Related Records Side Panel -->\n <mj-isa-related-panel\n [Record]=\"EffectiveRecord\"\n [EditMode]=\"EffectiveEditMode\"\n [Collapsed]=\"EffectiveWidthMode === 'full-width'\"\n (Navigate)=\"OnNavigate($event)\">\n </mj-isa-related-panel>\n </div>\n </div>\n</div>\n\n<!-- ============================================\n RECORD CHANGES DRAWER (shown when history button clicked)\n ============================================ -->\n@if (ShowRecordChanges && EffectiveRecord) {\n <mj-record-changes\n [record]=\"EffectiveRecord\"\n (dialogClosed)=\"OnRecordChangesClosed()\">\n </mj-record-changes>\n}\n\n<!-- ============================================\n LIST MANAGEMENT DIALOG (shown when lists button clicked)\n ============================================ -->\n@if (ShowListManagement && EffectiveRecord) {\n <mj-list-management-dialog\n [visible]=\"ShowListManagement\"\n [config]=\"{\n mode: 'manage',\n entityId: EffectiveRecord.EntityInfo.ID,\n entityName: EffectiveRecord.EntityInfo.Name,\n recordIds: [EffectiveRecord.PrimaryKey.Values()[0]],\n allowCreate: true\n }\"\n (complete)=\"OnListManagementClosed()\"\n (cancel)=\"OnListManagementClosed()\">\n </mj-list-management-dialog>\n}\n\n<!-- ============================================\n SECTION MANAGER DRAWER (shown when manage-sections button clicked)\n ============================================ -->\n<mj-section-manager\n [Sections]=\"SectionManagerItems\"\n [SectionOrder]=\"SectionManagerOrder\"\n [Visible]=\"ShowSectionManager\"\n (SectionOrderChange)=\"OnSectionOrderChange($event)\"\n (ResetRequested)=\"OnSectionManagerReset()\"\n (Closed)=\"OnSectionManagerClosed()\">\n</mj-section-manager>\n", styles: ["/* ============================================\n RECORD FORM CONTAINER \u2014 uses global --mj-* design tokens\n Top-level wrapper: toolbar + scrollable content\n ============================================ */\nmj-record-form-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n position: relative;\n overflow: hidden;\n}\n\n/* ViewEncapsulation.None fallback \u2014 ensure the element itself constrains overflow */\nmj-record-form-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n position: relative;\n overflow: hidden;\n}\n\n/* ============================================\n SCROLL AREA (full-width so mouse wheel works anywhere)\n ============================================ */\n.mj-forms-scroll-area {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n background: var(--mj-bg-page);\n}\n\n/* ============================================\n PANELS CONTAINER (centered content within scroll area)\n ============================================ */\n.mj-forms-panels-container {\n padding: 24px 32px 48px;\n max-width: 920px;\n margin: 0 auto;\n width: 100%;\n box-sizing: border-box;\n}\n\n/* Widen max-width when ISA side panel is present */\n.mj-forms-panels--has-isa-panel {\n max-width: 1240px;\n}\n\n.mj-forms-panels--full-width {\n max-width: none;\n padding-left: 24px;\n padding-right: 24px;\n}\n\n/* Flex row layout: form panels + optional ISA side panel */\n.mj-forms-layout-row {\n display: flex;\n gap: 20px;\n align-items: flex-start;\n}\n\n/* All panels in a single flex container \u2014 CSS order drives sequencing */\n.mj-forms-all-panels {\n display: flex;\n flex-direction: column;\n gap: 16px;\n flex: 1;\n min-width: 0;\n}\n\n/* Hide related entity panels in edit mode (variant host class on mj-collapsible-panel) */\n.mj-forms-panels--edit-mode .mj-panel--related-entity {\n display: none;\n}\n\n/* ============================================\n EMPTY SEARCH STATE\n ============================================ */\n.mj-forms-empty-search-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 80px 24px;\n text-align: center;\n min-height: 400px;\n}\n\n.mj-forms-empty-search-icon {\n width: 80px;\n height: 80px;\n border-radius: var(--mj-radius-full);\n background: var(--mj-bg-surface-sunken);\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 24px;\n}\n\n.mj-forms-empty-search-icon i {\n font-size: 32px;\n color: var(--mj-text-muted);\n}\n\n.mj-forms-empty-search-title {\n font-size: var(--mj-text-xl);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n margin: 0 0 12px 0;\n}\n\n.mj-forms-empty-search-message {\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n line-height: 1.6;\n max-width: 400px;\n margin: 0;\n}\n\n.mj-forms-empty-search-message strong {\n color: var(--mj-text-primary);\n font-weight: var(--mj-font-semibold);\n}\n\n.mj-forms-empty-search-link {\n color: var(--mj-brand-primary);\n text-decoration: none;\n font-weight: var(--mj-font-medium);\n}\n\n.mj-forms-empty-search-link:hover {\n text-decoration: underline;\n}\n\n/* ============================================\n RESPONSIVE\n ============================================ */\n@media (max-width: 768px) {\n .mj-forms-panels-container {\n padding: 16px 12px 32px;\n }\n}\n"] }]
|
|
539
539
|
}], null, { Record: [{
|
|
540
540
|
type: Input
|
|
541
541
|
}], FormComponent: [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"explorer-entity-data-grid.component.d.ts","sourceRoot":"","sources":["../../src/lib/explorer-entity-data-grid.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,YAAY,EAAa,MAAM,eAAe,CAAC;AAClF,OAAO,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"explorer-entity-data-grid.component.d.ts","sourceRoot":"","sources":["../../src/lib/explorer-entity-data-grid.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,YAAY,EAAa,MAAM,eAAe,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EACH,uBAAuB,EACvB,4BAA4B,EAC5B,sBAAsB,EACtB,sBAAsB,EACtB,iBAAiB,EACjB,iBAAiB,EAEpB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;;AAEhE;;;;;GAKG;AACH,qBA0Ba,+BAA+B;IAChB,SAAS,EAAG,uBAAuB,CAAC;IAGnD,MAAM,EAAE,aAAa,GAAG,IAAI,CAAQ;IACpC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAM;IAC9C,SAAS,EAAE,OAAO,CAAQ;IAC1B,WAAW,EAAE,OAAO,CAAQ;IAC5B,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,aAAa,CAAU;IACjD,aAAa,EAAE,iBAAiB,CAAM;IACtC,aAAa,EAAE,iBAAiB,CAAY;IAErD;;;OAGG;IACM,qBAAqB,EAAE,OAAO,CAAQ;IAGrC,mBAAmB,6CAAoD;IACvE,aAAa,uCAA8C;IAC3D,aAAa,uCAA8C;IAErE,6EAA6E;IACnE,QAAQ,oCAA2C;IAE7D,gBAAgB,CAAC,KAAK,EAAE,4BAA4B,GAAG,IAAI;IAoB3D,UAAU,CAAC,KAAK,EAAE,sBAAsB,GAAG,IAAI;IAK/C,UAAU,CAAC,KAAK,EAAE,sBAAsB,GAAG,IAAI;yCAnDtC,+BAA+B;2CAA/B,+BAA+B;CAuD3C"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Component, Input, Output, EventEmitter, ViewChild } from '@angular/core';
|
|
2
|
-
import {
|
|
2
|
+
import { buildCompositeKey } from '@memberjunction/ng-entity-viewer';
|
|
3
3
|
import * as i0 from "@angular/core";
|
|
4
4
|
import * as i1 from "@memberjunction/ng-entity-viewer";
|
|
5
5
|
const _c0 = ["innerGrid"];
|
|
@@ -35,23 +35,16 @@ export class ExplorerEntityDataGridComponent {
|
|
|
35
35
|
this.AfterRowDoubleClick.emit(event);
|
|
36
36
|
// Emit navigation event if enabled
|
|
37
37
|
if (this.NavigateOnDoubleClick && event.row) {
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
if (!
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
pkey.LoadFromSimpleObject(pkeyVals);
|
|
49
|
-
this.Navigate.emit({
|
|
50
|
-
Kind: 'record',
|
|
51
|
-
EntityName: entityName,
|
|
52
|
-
PrimaryKey: pkey
|
|
53
|
-
});
|
|
54
|
-
}
|
|
38
|
+
// Use the inner grid's resolved EntityInfo - works for both ViewID and EntityName params
|
|
39
|
+
const entityInfo = this.innerGrid?.EntityInfo;
|
|
40
|
+
if (!entityInfo)
|
|
41
|
+
return;
|
|
42
|
+
const pkey = buildCompositeKey(event.row, entityInfo);
|
|
43
|
+
this.Navigate.emit({
|
|
44
|
+
Kind: 'record',
|
|
45
|
+
EntityName: entityInfo.Name,
|
|
46
|
+
PrimaryKey: pkey
|
|
47
|
+
});
|
|
55
48
|
}
|
|
56
49
|
}
|
|
57
50
|
onRowClick(event) {
|
|
@@ -122,5 +115,5 @@ export class ExplorerEntityDataGridComponent {
|
|
|
122
115
|
}], Navigate: [{
|
|
123
116
|
type: Output
|
|
124
117
|
}] }); })();
|
|
125
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ExplorerEntityDataGridComponent, { className: "ExplorerEntityDataGridComponent", filePath: "src/lib/explorer-entity-data-grid.component.ts", lineNumber:
|
|
118
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ExplorerEntityDataGridComponent, { className: "ExplorerEntityDataGridComponent", filePath: "src/lib/explorer-entity-data-grid.component.ts", lineNumber: 46 }); })();
|
|
126
119
|
//# sourceMappingURL=explorer-entity-data-grid.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"explorer-entity-data-grid.component.js","sourceRoot":"","sources":["../../src/lib/explorer-entity-data-grid.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"explorer-entity-data-grid.component.js","sourceRoot":"","sources":["../../src/lib/explorer-entity-data-grid.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAElF,OAAO,EAOH,iBAAiB,EACpB,MAAM,kCAAkC,CAAC;;;;AAG1C;;;;;GAKG;AA2BH,MAAM,OAAO,+BAA+B;IAChB,SAAS,CAA2B;IAE5D,mDAAmD;IAC1C,MAAM,GAAyB,IAAI,CAAC;IACpC,eAAe,GAA4B,EAAE,CAAC;IAC9C,SAAS,GAAY,IAAI,CAAC;IAC1B,WAAW,GAAY,IAAI,CAAC;IAC5B,MAAM,GAAoC,MAAM,CAAC;IACjD,aAAa,GAAsB,EAAE,CAAC;IACtC,aAAa,GAAsB,QAAQ,CAAC;IAErD;;;OAGG;IACM,qBAAqB,GAAY,IAAI,CAAC;IAE/C,6CAA6C;IACnC,mBAAmB,GAAG,IAAI,YAAY,EAAgC,CAAC;IACvE,aAAa,GAAG,IAAI,YAAY,EAA0B,CAAC;IAC3D,aAAa,GAAG,IAAI,YAAY,EAA0B,CAAC;IAErE,6EAA6E;IACnE,QAAQ,GAAG,IAAI,YAAY,EAAuB,CAAC;IAE7D,gBAAgB,CAAC,KAAmC;QAChD,sCAAsC;QACtC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAErC,mCAAmC;QACnC,IAAI,IAAI,CAAC,qBAAqB,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;YAC1C,yFAAyF;YACzF,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC;YAC9C,IAAI,CAAC,UAAU;gBAAE,OAAO;YAExB,MAAM,IAAI,GAAG,iBAAiB,CAAC,KAAK,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;YAEtD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;gBACf,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE,UAAU,CAAC,IAAI;gBAC3B,UAAU,EAAE,IAAI;aACnB,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAED,UAAU,CAAC,KAA6B;QACpC,sCAAsC;QACtC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;IAED,UAAU,CAAC,KAA6B;QACpC,sCAAsC;QACtC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;yHAtDQ,+BAA+B;6DAA/B,+BAA+B;;;;;;;YAtBpC,iDAWyC;YAArC,AADA,AADA,iMAAuB,4BAAwB,KAAC,wKAC/B,sBAAkB,KAAC,wKACnB,sBAAkB,KAAC;YACxC,iBAAsB;;YAJlB,AADA,AADA,AADA,AADA,AADA,AADA,mCAAiB,wCACkB,4BACZ,gCACI,sBACV,oCACc,oCACA;;;iFAc9B,+BAA+B;cA1B3C,SAAS;6BACI,KAAK,YACL,8BAA8B,YAC9B;;;;;;;;;;;;;;KAcT;;kBAUA,SAAS;mBAAC,WAAW;;kBAGrB,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBAML,KAAK;;kBAGL,MAAM;;kBACN,MAAM;;kBACN,MAAM;;kBAGN,MAAM;;kFAxBE,+BAA+B","sourcesContent":["import { Component, Input, Output, EventEmitter, ViewChild } from '@angular/core';\nimport { RunViewParams } from '@memberjunction/core';\nimport {\n EntityDataGridComponent,\n AfterRowDoubleClickEventArgs,\n AfterRowClickEventArgs,\n AfterDataLoadEventArgs,\n GridToolbarConfig,\n GridSelectionMode,\n buildCompositeKey\n} from '@memberjunction/ng-entity-viewer';\nimport { FormNavigationEvent } from './types/navigation-events';\n\n/**\n * Wrapper for EntityDataGridComponent that emits navigation events on row double-click.\n * The host application subscribes to Navigate events and maps them to its routing system.\n *\n * This component is used by CodeGen for related entity grids in forms.\n */\n@Component({\n standalone: false,\n selector: 'mj-explorer-entity-data-grid',\n template: `\n <mj-entity-data-grid\n #innerGrid\n [Params]=\"Params\"\n [NewRecordValues]=\"NewRecordValues\"\n [AllowLoad]=\"AllowLoad\"\n [ShowToolbar]=\"ShowToolbar\"\n [Height]=\"Height\"\n [ToolbarConfig]=\"ToolbarConfig\"\n [SelectionMode]=\"SelectionMode\"\n (AfterRowDoubleClick)=\"onRowDoubleClick($event)\"\n (AfterRowClick)=\"onRowClick($event)\"\n (AfterDataLoad)=\"onDataLoad($event)\">\n </mj-entity-data-grid>\n `,\n styles: [`\n :host {\n display: block;\n height: 100%;\n width: 100%;\n }\n `]\n})\nexport class ExplorerEntityDataGridComponent {\n @ViewChild('innerGrid') innerGrid!: EntityDataGridComponent;\n\n // Pass-through inputs from EntityDataGridComponent\n @Input() Params: RunViewParams | null = null;\n @Input() NewRecordValues: Record<string, unknown> = {};\n @Input() AllowLoad: boolean = true;\n @Input() ShowToolbar: boolean = true;\n @Input() Height: number | 'auto' | 'fit-content' = 'auto';\n @Input() ToolbarConfig: GridToolbarConfig = {};\n @Input() SelectionMode: GridSelectionMode = 'single';\n\n /**\n * When true, double-clicking a row emits a Navigate event.\n * Defaults to true.\n */\n @Input() NavigateOnDoubleClick: boolean = true;\n\n // Re-emit events for consumers who need them\n @Output() AfterRowDoubleClick = new EventEmitter<AfterRowDoubleClickEventArgs>();\n @Output() AfterRowClick = new EventEmitter<AfterRowClickEventArgs>();\n @Output() AfterDataLoad = new EventEmitter<AfterDataLoadEventArgs>();\n\n /** Emitted when a row is double-clicked and NavigateOnDoubleClick is true */\n @Output() Navigate = new EventEmitter<FormNavigationEvent>();\n\n onRowDoubleClick(event: AfterRowDoubleClickEventArgs): void {\n // Re-emit the event for any consumers\n this.AfterRowDoubleClick.emit(event);\n\n // Emit navigation event if enabled\n if (this.NavigateOnDoubleClick && event.row) {\n // Use the inner grid's resolved EntityInfo - works for both ViewID and EntityName params\n const entityInfo = this.innerGrid?.EntityInfo;\n if (!entityInfo) return;\n\n const pkey = buildCompositeKey(event.row, entityInfo);\n\n this.Navigate.emit({\n Kind: 'record',\n EntityName: entityInfo.Name,\n PrimaryKey: pkey\n });\n }\n }\n\n onRowClick(event: AfterRowClickEventArgs): void {\n // Re-emit the event for any consumers\n this.AfterRowClick.emit(event);\n }\n\n onDataLoad(event: AfterDataLoadEventArgs): void {\n // Re-emit the event for any consumers\n this.AfterDataLoad.emit(event);\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-field.component.d.ts","sourceRoot":"","sources":["../../../src/lib/field/form-field.component.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"form-field.component.d.ts","sourceRoot":"","sources":["../../../src/lib/field/form-field.component.ts"],"names":[],"mappings":"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"}
|
|
@@ -643,6 +643,11 @@ export class MjFormFieldComponent {
|
|
|
643
643
|
get FKDisplayName() {
|
|
644
644
|
if (!this.Record || !this.HasRelatedEntity)
|
|
645
645
|
return null;
|
|
646
|
+
// If the FK value itself is null/empty, there's nothing to display
|
|
647
|
+
// (the joined name field may still hold a stale cached value from the view)
|
|
648
|
+
const fkValue = this.Value;
|
|
649
|
+
if (fkValue == null || fkValue === '')
|
|
650
|
+
return null;
|
|
646
651
|
// Fast path: name field is joined into our record's view
|
|
647
652
|
const nameFieldMap = this.FieldInfo?.RelatedEntityNameFieldMap;
|
|
648
653
|
if (nameFieldMap) {
|
|
@@ -1166,11 +1171,11 @@ export class MjFormFieldComponent {
|
|
|
1166
1171
|
i0.ɵɵconditionalCreate(0, MjFormFieldComponent_Conditional_0_Template, 2, 2);
|
|
1167
1172
|
} if (rf & 2) {
|
|
1168
1173
|
i0.ɵɵconditional(ctx.Record && (ctx.Record.IsSaved || !ctx.IsFieldReadOnly) ? 0 : -1);
|
|
1169
|
-
} }, dependencies: [i1.NgStyle], styles: ["\n\n\n\n[_nghost-%COMP%] {\n --mj-accent: #667eea;\n --mj-accent-light: rgba(102, 126, 234, 0.08);\n --mj-text-primary: #1f2937;\n --mj-text-secondary: #4b5563;\n --mj-text-muted: #9ca3af;\n --mj-border: #e5e7eb;\n --mj-error: #ef4444;\n --mj-warning: #f59e0b;\n --mj-card-bg: #ffffff;\n --mj-forms-field-label-width: 200px;\n --mj-forms-field-gap: 12px;\n --mj-transition: 200ms;\n\n display: contents;\n}\n\n.mj-forms-field[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: var(--mj-forms-field-label-width) 1fr;\n gap: var(--mj-forms-field-gap);\n align-items: baseline;\n padding: 8px 0;\n transition: all var(--mj-transition) ease;\n}\n\n\n\n.mj-forms-field--editing[_ngcontent-%COMP%]:hover {\n background: var(--mj-accent-light);\n border-radius: 6px;\n margin: 0 -8px;\n padding: 8px 8px;\n}\n\n\n\n\n\n.mj-forms-field-label[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n padding-top: 2px;\n word-break: break-word;\n}\n\n\n\n\n\n.mj-forms-field-control[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n}\n\n.mj-forms-field-control[_ngcontent-%COMP%] > *[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n\n\n\n\n.mj-forms-field--dirty[_ngcontent-%COMP%] .mj-forms-field-label[_ngcontent-%COMP%]::after {\n content: '';\n display: inline-block;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--mj-warning);\n margin-left: 6px;\n vertical-align: middle;\n}\n\n\n\n\n\n.mj-forms-field--required-empty[_ngcontent-%COMP%] .mj-forms-field-input[_ngcontent-%COMP%] {\n border-bottom-color: var(--mj-error);\n}\n\n.mj-forms-field--required-empty[_ngcontent-%COMP%] .mj-forms-field-input[_ngcontent-%COMP%]:focus {\n background: #fef2f2;\n border-bottom-color: var(--mj-error);\n}\n\n.mj-forms-field--required-empty[_ngcontent-%COMP%] .mj-custom-select-trigger[_ngcontent-%COMP%] {\n border-bottom-color: var(--mj-error);\n}\n\n.mj-forms-field--required-empty[_ngcontent-%COMP%] .mj-fk-search[_ngcontent-%COMP%] .mj-forms-field-input[_ngcontent-%COMP%] {\n border-bottom-color: var(--mj-error);\n}\n\n\n\n\n\n.mj-forms-field-value[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-primary);\n min-height: 24px;\n display: flex;\n align-items: center;\n overflow-wrap: break-word;\n word-break: break-word;\n}\n\n.mj-forms-field-value--long[_ngcontent-%COMP%] {\n white-space: pre-line;\n max-height: 300px;\n overflow: auto;\n}\n\n\n\n.mj-forms-field--readonly[_ngcontent-%COMP%] {\n opacity: 0.7;\n}\n\n.mj-forms-field--readonly[_ngcontent-%COMP%] .mj-forms-field-value[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n}\n\n\n\n\n\n.mj-forms-field-link[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-accent);\n cursor: pointer;\n font-weight: 400;\n font-size: 14px;\n transition: color var(--mj-transition);\n text-decoration: none;\n}\n\n.mj-forms-field-link[_ngcontent-%COMP%]:hover {\n color: #5a6fd6;\n}\n\n.mj-forms-field-link-icon[_ngcontent-%COMP%] {\n font-size: 11px;\n opacity: 0;\n transition: opacity var(--mj-transition);\n}\n\n.mj-forms-field-link[_ngcontent-%COMP%]:hover .mj-forms-field-link-icon[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n\n\n.mj-forms-field-link--fk[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 400;\n}\n\n\n\n\n\n.mj-forms-field-input[_ngcontent-%COMP%] {\n font-size: 14px;\n font-family: inherit;\n color: var(--mj-text-primary);\n background: transparent;\n border: none;\n border-bottom: 1.5px solid var(--mj-border);\n padding: 4px 0;\n width: 100%;\n outline: none;\n transition: border-color var(--mj-transition) ease,\n background var(--mj-transition) ease;\n}\n\n.mj-forms-field-input[_ngcontent-%COMP%]:focus {\n border-bottom-color: var(--mj-accent);\n background: var(--mj-accent-light);\n border-radius: 4px 4px 0 0;\n padding: 4px 6px;\n}\n\n.mj-forms-field-input[_ngcontent-%COMP%]::placeholder {\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n\n\n.mj-forms-field-input--textarea[_ngcontent-%COMP%] {\n resize: vertical;\n min-height: 60px;\n border: 1.5px solid var(--mj-border);\n border-radius: 6px;\n padding: 8px 10px;\n background: white;\n font-family: inherit;\n}\n\n.mj-forms-field-input--textarea[_ngcontent-%COMP%]:focus {\n border-color: var(--mj-accent);\n box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);\n background: white;\n padding: 8px 10px;\n border-radius: 6px;\n}\n\n\n\n.mj-forms-field-input--number[_ngcontent-%COMP%] {\n max-width: 200px;\n}\n\n\n\n.mj-forms-field-input--date[_ngcontent-%COMP%] {\n max-width: 220px;\n}\n\n\n\n\n\n.mj-forms-field-checkbox[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.mj-forms-field-checkbox[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n appearance: none;\n width: 18px;\n height: 18px;\n border: 2px solid var(--mj-border);\n border-radius: 4px;\n cursor: pointer;\n position: relative;\n transition: all var(--mj-transition) ease;\n flex-shrink: 0;\n}\n\n.mj-forms-field-checkbox[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%]:checked {\n background: var(--mj-accent);\n border-color: var(--mj-accent);\n}\n\n.mj-forms-field-checkbox[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%]:checked::after {\n content: '';\n position: absolute;\n left: 5px;\n top: 1px;\n width: 5px;\n height: 9px;\n border: solid white;\n border-width: 0 2px 2px 0;\n transform: rotate(45deg);\n}\n\n.mj-forms-field-checkbox[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: default;\n}\n\n\n\n\n\n.mj-custom-select-trigger[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n font-size: 14px;\n font-family: inherit;\n color: var(--mj-text-primary);\n background: transparent;\n border: none;\n border-bottom: 1.5px solid var(--mj-border);\n padding: 4px 0;\n width: 100%;\n cursor: pointer;\n outline: none;\n transition: border-color var(--mj-transition) ease,\n background var(--mj-transition) ease;\n}\n\n.mj-custom-select-trigger[_ngcontent-%COMP%]:focus {\n border-bottom-color: var(--mj-accent);\n background: var(--mj-accent-light);\n border-radius: 4px 4px 0 0;\n padding: 4px 6px;\n}\n\n.mj-custom-select-value[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mj-custom-select-value--placeholder[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n.mj-custom-select-chevron[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n transition: transform var(--mj-transition) ease;\n flex-shrink: 0;\n margin-left: 8px;\n}\n\n.mj-custom-select-chevron--open[_ngcontent-%COMP%] {\n transform: rotate(180deg);\n}\n\n\n\n\n\n.mj-fk-search[_ngcontent-%COMP%] {\n position: relative;\n display: flex;\n align-items: center;\n width: 100%;\n}\n\n.mj-fk-search[_ngcontent-%COMP%] .mj-forms-field-input[_ngcontent-%COMP%] {\n padding-right: 28px;\n}\n\n.mj-fk-search-icon[_ngcontent-%COMP%] {\n position: absolute;\n right: 4px;\n color: var(--mj-text-muted);\n font-size: 12px;\n pointer-events: none;\n}\n\n.mj-fk-clear[_ngcontent-%COMP%] {\n position: absolute;\n right: 2px;\n background: none;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n font-size: 11px;\n padding: 4px 6px;\n line-height: 1;\n border-radius: 3px;\n transition: all var(--mj-transition);\n}\n\n.mj-fk-clear[_ngcontent-%COMP%]:hover {\n color: var(--mj-error);\n background: rgba(239, 68, 68, 0.08);\n}\n\n\n\n.mj-fk-search--matched[_ngcontent-%COMP%] .mj-forms-field-input[_ngcontent-%COMP%] {\n border-bottom: 2px solid var(--mj-accent);\n}\n\n\n\n\n\n.mj-fk-dropdown[_ngcontent-%COMP%] {\n background: var(--mj-card-bg);\n border: 1px solid var(--mj-border);\n border-radius: 8px;\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);\n max-height: 240px;\n overflow-y: auto;\n padding: 4px;\n animation: _ngcontent-%COMP%_mj-dropdown-in 150ms ease;\n}\n\n.mj-fk-dropdown--above[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_mj-dropdown-in-above 150ms ease;\n}\n\n.mj-fk-option[_ngcontent-%COMP%] {\n padding: 10px 14px;\n font-size: 14px;\n color: var(--mj-text-primary);\n cursor: pointer;\n transition: background var(--mj-transition);\n border-radius: 6px;\n}\n\n.mj-fk-option[_ngcontent-%COMP%]:hover {\n background: var(--mj-accent-light);\n}\n\n.mj-fk-option--selected[_ngcontent-%COMP%] {\n background: var(--mj-accent-light);\n font-weight: 600;\n color: var(--mj-accent);\n}\n\n.mj-fk-option--selected[_ngcontent-%COMP%]:hover {\n background: rgba(102, 126, 234, 0.15);\n}\n\n@keyframes _ngcontent-%COMP%_mj-dropdown-in {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n@keyframes _ngcontent-%COMP%_mj-dropdown-in-above {\n from { opacity: 0; transform: translateY(4px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n\n\n\n\n.mj-forms-field-label[_ngcontent-%COMP%] [_ngcontent-%COMP%]:global(.mj-forms-search-highlight) {\n background-color: #fef08a;\n color: #854d0e;\n padding: 0;\n border-radius: 2px;\n font-weight: 700;\n box-shadow: 0 0 0 2px #fef08a;\n}\n\n\n\n\n\n.mj-forms-field--has-error[_ngcontent-%COMP%] .mj-forms-field-input[_ngcontent-%COMP%] {\n border-bottom-color: var(--mj-error);\n border-bottom-width: 2px;\n}\n\n.mj-forms-field--has-error[_ngcontent-%COMP%] .mj-forms-field-input[_ngcontent-%COMP%]:focus {\n background: #fef2f2;\n border-bottom-color: var(--mj-error);\n}\n\n.mj-forms-field--has-error[_ngcontent-%COMP%] .mj-forms-field-input--textarea[_ngcontent-%COMP%] {\n border-color: var(--mj-error);\n}\n\n.mj-forms-field--has-error[_ngcontent-%COMP%] .mj-forms-field-input--textarea[_ngcontent-%COMP%]:focus {\n border-color: var(--mj-error);\n box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.08);\n}\n\n.mj-forms-field--has-error[_ngcontent-%COMP%] .mj-custom-select-trigger[_ngcontent-%COMP%] {\n border-bottom-color: var(--mj-error);\n border-bottom-width: 2px;\n}\n\n.mj-forms-field--has-error[_ngcontent-%COMP%] .mj-fk-search[_ngcontent-%COMP%] .mj-forms-field-input[_ngcontent-%COMP%] {\n border-bottom-color: var(--mj-error);\n border-bottom-width: 2px;\n}\n\n\n\n\n\n.mj-forms-field--has-warning[_ngcontent-%COMP%] .mj-forms-field-input[_ngcontent-%COMP%] {\n border-bottom-color: var(--mj-warning);\n border-bottom-width: 2px;\n}\n\n.mj-forms-field--has-warning[_ngcontent-%COMP%] .mj-forms-field-input[_ngcontent-%COMP%]:focus {\n background: #fffbeb;\n border-bottom-color: var(--mj-warning);\n}\n\n.mj-forms-field--has-warning[_ngcontent-%COMP%] .mj-forms-field-input--textarea[_ngcontent-%COMP%] {\n border-color: var(--mj-warning);\n}\n\n.mj-forms-field--has-warning[_ngcontent-%COMP%] .mj-forms-field-input--textarea[_ngcontent-%COMP%]:focus {\n border-color: var(--mj-warning);\n box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.08);\n}\n\n.mj-forms-field--has-warning[_ngcontent-%COMP%] .mj-custom-select-trigger[_ngcontent-%COMP%] {\n border-bottom-color: var(--mj-warning);\n border-bottom-width: 2px;\n}\n\n.mj-forms-field--has-warning[_ngcontent-%COMP%] .mj-fk-search[_ngcontent-%COMP%] .mj-forms-field-input[_ngcontent-%COMP%] {\n border-bottom-color: var(--mj-warning);\n border-bottom-width: 2px;\n}\n\n\n\n\n\n.mj-forms-field-validation[_ngcontent-%COMP%] {\n grid-column: 2;\n display: flex;\n flex-direction: column;\n gap: 2px;\n margin-top: -2px;\n overflow: hidden;\n animation: _ngcontent-%COMP%_mj-validation-slide-in 200ms ease-out;\n}\n\n.mj-forms-field-validation-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 6px;\n font-size: 12px;\n line-height: 1.4;\n padding: 3px 0 1px;\n}\n\n.mj-forms-field-validation-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n\n\n.mj-forms-field-validation--error[_ngcontent-%COMP%] .mj-forms-field-validation-item[_ngcontent-%COMP%] {\n color: var(--mj-error);\n}\n\n.mj-forms-field-validation--error[_ngcontent-%COMP%] .mj-forms-field-validation-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-error);\n}\n\n\n\n.mj-forms-field-validation--warning[_ngcontent-%COMP%] .mj-forms-field-validation-item[_ngcontent-%COMP%] {\n color: #b45309;\n}\n\n.mj-forms-field-validation--warning[_ngcontent-%COMP%] .mj-forms-field-validation-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-warning);\n}\n\n@keyframes _ngcontent-%COMP%_mj-validation-slide-in {\n from {\n opacity: 0;\n max-height: 0;\n transform: translateY(-4px);\n }\n to {\n opacity: 1;\n max-height: 100px;\n transform: translateY(0);\n }\n}\n\n\n\n\n\n@media (max-width: 640px) {\n .mj-forms-field[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n gap: 4px;\n }\n\n .mj-forms-field-label[_ngcontent-%COMP%] {\n font-size: 12px;\n }\n\n .mj-forms-field-validation[_ngcontent-%COMP%] {\n grid-column: 1;\n }\n}"], changeDetection: 0 });
|
|
1174
|
+
} }, dependencies: [i1.NgStyle], styles: ["\n\n\n\n[_nghost-%COMP%] {\n --mj-forms-field-label-width: 200px;\n --mj-forms-field-gap: 12px;\n\n display: contents;\n}\n\n.mj-forms-field[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: var(--mj-forms-field-label-width) 1fr;\n gap: var(--mj-forms-field-gap);\n align-items: baseline;\n padding: 8px 0;\n transition: all var(--mj-transition-base) ease;\n}\n\n\n\n.mj-forms-field--editing[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n border-radius: 6px;\n margin: 0 -8px;\n padding: 8px 8px;\n}\n\n\n\n\n\n.mj-forms-field-label[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n padding-top: 2px;\n word-break: break-word;\n}\n\n\n\n\n\n.mj-forms-field-control[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n}\n\n.mj-forms-field-control[_ngcontent-%COMP%] > *[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n\n\n\n\n.mj-forms-field--dirty[_ngcontent-%COMP%] .mj-forms-field-label[_ngcontent-%COMP%]::after {\n content: '';\n display: inline-block;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--mj-status-warning);\n margin-left: 6px;\n vertical-align: middle;\n}\n\n\n\n\n\n.mj-forms-field--required-empty[_ngcontent-%COMP%] .mj-forms-field-input[_ngcontent-%COMP%] {\n border-bottom-color: var(--mj-status-error);\n}\n\n.mj-forms-field--required-empty[_ngcontent-%COMP%] .mj-forms-field-input[_ngcontent-%COMP%]:focus {\n background: color-mix(in srgb, var(--mj-status-error) 5%, var(--mj-bg-surface));\n border-bottom-color: var(--mj-status-error);\n}\n\n.mj-forms-field--required-empty[_ngcontent-%COMP%] .mj-custom-select-trigger[_ngcontent-%COMP%] {\n border-bottom-color: var(--mj-status-error);\n}\n\n.mj-forms-field--required-empty[_ngcontent-%COMP%] .mj-fk-search[_ngcontent-%COMP%] .mj-forms-field-input[_ngcontent-%COMP%] {\n border-bottom-color: var(--mj-status-error);\n}\n\n\n\n\n\n.mj-forms-field-value[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-primary);\n min-height: 24px;\n display: flex;\n align-items: center;\n overflow-wrap: break-word;\n word-break: break-word;\n}\n\n.mj-forms-field-value--long[_ngcontent-%COMP%] {\n white-space: pre-line;\n max-height: 300px;\n overflow: auto;\n}\n\n\n\n.mj-forms-field--readonly[_ngcontent-%COMP%] {\n opacity: 0.7;\n}\n\n.mj-forms-field--readonly[_ngcontent-%COMP%] .mj-forms-field-value[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n}\n\n\n\n\n\n.mj-forms-field-link[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-brand-primary);\n cursor: pointer;\n font-weight: 400;\n font-size: 14px;\n transition: color var(--mj-transition-base);\n text-decoration: none;\n}\n\n.mj-forms-field-link[_ngcontent-%COMP%]:hover {\n color: var(--mj-brand-primary-hover);\n}\n\n.mj-forms-field-link-icon[_ngcontent-%COMP%] {\n font-size: 11px;\n opacity: 0;\n transition: opacity var(--mj-transition-base);\n}\n\n.mj-forms-field-link[_ngcontent-%COMP%]:hover .mj-forms-field-link-icon[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n\n\n.mj-forms-field-link--fk[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 400;\n}\n\n\n\n\n\n.mj-forms-field-input[_ngcontent-%COMP%] {\n font-size: 14px;\n font-family: inherit;\n color: var(--mj-text-primary);\n background: transparent;\n border: none;\n border-bottom: 1.5px solid var(--mj-border-default);\n padding: 4px 0;\n width: 100%;\n outline: none;\n transition: border-color var(--mj-transition-base) ease,\n background var(--mj-transition-base) ease;\n}\n\n.mj-forms-field-input[_ngcontent-%COMP%]:focus {\n border-bottom-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n border-radius: 4px 4px 0 0;\n padding: 4px 6px;\n}\n\n.mj-forms-field-input[_ngcontent-%COMP%]::placeholder {\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n\n\n.mj-forms-field-input--textarea[_ngcontent-%COMP%] {\n resize: vertical;\n min-height: 60px;\n border: 1.5px solid var(--mj-border-default);\n border-radius: 6px;\n padding: 8px 10px;\n background: var(--mj-bg-surface);\n font-family: inherit;\n}\n\n.mj-forms-field-input--textarea[_ngcontent-%COMP%]:focus {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n background: var(--mj-bg-surface);\n padding: 8px 10px;\n border-radius: 6px;\n}\n\n\n\n.mj-forms-field-input--number[_ngcontent-%COMP%] {\n max-width: 200px;\n}\n\n\n\n.mj-forms-field-input--date[_ngcontent-%COMP%] {\n max-width: 220px;\n}\n\n\n\n\n\n.mj-forms-field-checkbox[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.mj-forms-field-checkbox[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n appearance: none;\n width: 18px;\n height: 18px;\n border: 2px solid var(--mj-border-default);\n border-radius: 4px;\n cursor: pointer;\n position: relative;\n transition: all var(--mj-transition-base) ease;\n flex-shrink: 0;\n}\n\n.mj-forms-field-checkbox[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%]:checked {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.mj-forms-field-checkbox[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%]:checked::after {\n content: '';\n position: absolute;\n left: 5px;\n top: 1px;\n width: 5px;\n height: 9px;\n border: solid var(--mj-text-inverse);\n border-width: 0 2px 2px 0;\n transform: rotate(45deg);\n}\n\n.mj-forms-field-checkbox[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: default;\n}\n\n\n\n\n\n.mj-custom-select-trigger[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n font-size: 14px;\n font-family: inherit;\n color: var(--mj-text-primary);\n background: transparent;\n border: none;\n border-bottom: 1.5px solid var(--mj-border-default);\n padding: 4px 0;\n width: 100%;\n cursor: pointer;\n outline: none;\n transition: border-color var(--mj-transition-base) ease,\n background var(--mj-transition-base) ease;\n}\n\n.mj-custom-select-trigger[_ngcontent-%COMP%]:focus {\n border-bottom-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n border-radius: 4px 4px 0 0;\n padding: 4px 6px;\n}\n\n.mj-custom-select-value[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mj-custom-select-value--placeholder[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n.mj-custom-select-chevron[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n transition: transform var(--mj-transition-base) ease;\n flex-shrink: 0;\n margin-left: 8px;\n}\n\n.mj-custom-select-chevron--open[_ngcontent-%COMP%] {\n transform: rotate(180deg);\n}\n\n\n\n\n\n.mj-fk-search[_ngcontent-%COMP%] {\n position: relative;\n display: flex;\n align-items: center;\n width: 100%;\n}\n\n.mj-fk-search[_ngcontent-%COMP%] .mj-forms-field-input[_ngcontent-%COMP%] {\n padding-right: 28px;\n}\n\n.mj-fk-search-icon[_ngcontent-%COMP%] {\n position: absolute;\n right: 4px;\n color: var(--mj-text-muted);\n font-size: 12px;\n pointer-events: none;\n}\n\n.mj-fk-clear[_ngcontent-%COMP%] {\n position: absolute;\n right: 2px;\n background: none;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n font-size: 11px;\n padding: 4px 6px;\n line-height: 1;\n border-radius: 3px;\n transition: all var(--mj-transition-base);\n}\n\n.mj-fk-clear[_ngcontent-%COMP%]:hover {\n color: var(--mj-status-error);\n background: color-mix(in srgb, var(--mj-status-error) 8%, transparent);\n}\n\n\n\n.mj-fk-search--matched[_ngcontent-%COMP%] .mj-forms-field-input[_ngcontent-%COMP%] {\n border-bottom: 2px solid var(--mj-brand-primary);\n}\n\n\n\n\n\n.mj-fk-dropdown[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n box-shadow: var(--mj-shadow-lg);\n max-height: 240px;\n overflow-y: auto;\n padding: 4px;\n animation: _ngcontent-%COMP%_mj-dropdown-in 150ms ease;\n}\n\n.mj-fk-dropdown--above[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_mj-dropdown-in-above 150ms ease;\n}\n\n.mj-fk-option[_ngcontent-%COMP%] {\n padding: 10px 14px;\n font-size: 14px;\n color: var(--mj-text-primary);\n cursor: pointer;\n transition: background var(--mj-transition-base);\n border-radius: 6px;\n}\n\n.mj-fk-option[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n}\n\n.mj-fk-option--selected[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n font-weight: 600;\n color: var(--mj-brand-primary);\n}\n\n.mj-fk-option--selected[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n@keyframes _ngcontent-%COMP%_mj-dropdown-in {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n@keyframes _ngcontent-%COMP%_mj-dropdown-in-above {\n from { opacity: 0; transform: translateY(4px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n\n\n\n\n.mj-forms-field-label[_ngcontent-%COMP%] [_ngcontent-%COMP%]:global(.mj-forms-search-highlight) {\n background-color: var(--mj-color-warning-200, #fef08a);\n color: var(--mj-color-warning-800, #854d0e);\n padding: 0;\n border-radius: 2px;\n font-weight: 700;\n box-shadow: 0 0 0 2px var(--mj-color-warning-200, #fef08a);\n}\n\n\n\n\n\n.mj-forms-field--has-error[_ngcontent-%COMP%] .mj-forms-field-input[_ngcontent-%COMP%] {\n border-bottom-color: var(--mj-status-error);\n border-bottom-width: 2px;\n}\n\n.mj-forms-field--has-error[_ngcontent-%COMP%] .mj-forms-field-input[_ngcontent-%COMP%]:focus {\n background: color-mix(in srgb, var(--mj-status-error) 5%, var(--mj-bg-surface));\n border-bottom-color: var(--mj-status-error);\n}\n\n.mj-forms-field--has-error[_ngcontent-%COMP%] .mj-forms-field-input--textarea[_ngcontent-%COMP%] {\n border-color: var(--mj-status-error);\n}\n\n.mj-forms-field--has-error[_ngcontent-%COMP%] .mj-forms-field-input--textarea[_ngcontent-%COMP%]:focus {\n border-color: var(--mj-status-error);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-error) 8%, transparent);\n}\n\n.mj-forms-field--has-error[_ngcontent-%COMP%] .mj-custom-select-trigger[_ngcontent-%COMP%] {\n border-bottom-color: var(--mj-status-error);\n border-bottom-width: 2px;\n}\n\n.mj-forms-field--has-error[_ngcontent-%COMP%] .mj-fk-search[_ngcontent-%COMP%] .mj-forms-field-input[_ngcontent-%COMP%] {\n border-bottom-color: var(--mj-status-error);\n border-bottom-width: 2px;\n}\n\n\n\n\n\n.mj-forms-field--has-warning[_ngcontent-%COMP%] .mj-forms-field-input[_ngcontent-%COMP%] {\n border-bottom-color: var(--mj-status-warning);\n border-bottom-width: 2px;\n}\n\n.mj-forms-field--has-warning[_ngcontent-%COMP%] .mj-forms-field-input[_ngcontent-%COMP%]:focus {\n background: color-mix(in srgb, var(--mj-status-warning) 5%, var(--mj-bg-surface));\n border-bottom-color: var(--mj-status-warning);\n}\n\n.mj-forms-field--has-warning[_ngcontent-%COMP%] .mj-forms-field-input--textarea[_ngcontent-%COMP%] {\n border-color: var(--mj-status-warning);\n}\n\n.mj-forms-field--has-warning[_ngcontent-%COMP%] .mj-forms-field-input--textarea[_ngcontent-%COMP%]:focus {\n border-color: var(--mj-status-warning);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-warning) 8%, transparent);\n}\n\n.mj-forms-field--has-warning[_ngcontent-%COMP%] .mj-custom-select-trigger[_ngcontent-%COMP%] {\n border-bottom-color: var(--mj-status-warning);\n border-bottom-width: 2px;\n}\n\n.mj-forms-field--has-warning[_ngcontent-%COMP%] .mj-fk-search[_ngcontent-%COMP%] .mj-forms-field-input[_ngcontent-%COMP%] {\n border-bottom-color: var(--mj-status-warning);\n border-bottom-width: 2px;\n}\n\n\n\n\n\n.mj-forms-field-validation[_ngcontent-%COMP%] {\n grid-column: 2;\n display: flex;\n flex-direction: column;\n gap: 2px;\n margin-top: -2px;\n overflow: hidden;\n animation: _ngcontent-%COMP%_mj-validation-slide-in 200ms ease-out;\n}\n\n.mj-forms-field-validation-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 6px;\n font-size: 12px;\n line-height: 1.4;\n padding: 3px 0 1px;\n}\n\n.mj-forms-field-validation-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n\n\n.mj-forms-field-validation--error[_ngcontent-%COMP%] .mj-forms-field-validation-item[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.mj-forms-field-validation--error[_ngcontent-%COMP%] .mj-forms-field-validation-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n\n\n.mj-forms-field-validation--warning[_ngcontent-%COMP%] .mj-forms-field-validation-item[_ngcontent-%COMP%] {\n color: var(--mj-color-warning-700);\n}\n\n.mj-forms-field-validation--warning[_ngcontent-%COMP%] .mj-forms-field-validation-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n}\n\n@keyframes _ngcontent-%COMP%_mj-validation-slide-in {\n from {\n opacity: 0;\n max-height: 0;\n transform: translateY(-4px);\n }\n to {\n opacity: 1;\n max-height: 100px;\n transform: translateY(0);\n }\n}\n\n\n\n\n\n@media (max-width: 640px) {\n .mj-forms-field[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n gap: 4px;\n }\n\n .mj-forms-field-label[_ngcontent-%COMP%] {\n font-size: 12px;\n }\n\n .mj-forms-field-validation[_ngcontent-%COMP%] {\n grid-column: 1;\n }\n}"], changeDetection: 0 });
|
|
1170
1175
|
}
|
|
1171
1176
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MjFormFieldComponent, [{
|
|
1172
1177
|
type: Component,
|
|
1173
|
-
args: [{ standalone: false, selector: 'mj-form-field', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (Record && (Record.IsSaved || !IsFieldReadOnly)) {\n <!-- READ-ONLY MODE -->\n @if ((!EditMode || IsFieldReadOnly) && !ShouldHideField) {\n <div class=\"mj-forms-field\" [class.mj-forms-field--readonly]=\"EditMode && IsFieldReadOnly\" [class.mj-forms-field--dirty]=\"IsDirty\">\n @if (ShowLabel) {\n <label class=\"mj-forms-field-label\" [innerHTML]=\"HighlightedDisplayName\"></label>\n }\n <div class=\"mj-forms-field-control\">\n <!-- FK fields with a mapped name field: show the name as a hyperlink -->\n @if (IsFKWithNameField) {\n <span class=\"mj-forms-field-value\">\n <a class=\"mj-forms-field-link mj-forms-field-link--fk\" (click)=\"OnRecordLinkClick($event)\" title=\"View related record\">\n {{ FKDisplayName }}\n </a>\n </span>\n }\n @else {\n @switch (LinkType) {\n @case ('Email') {\n <span class=\"mj-forms-field-value\">\n <a class=\"mj-forms-field-link\" (click)=\"OnEmailLinkClick($event)\" title=\"Send email\">\n {{ FormatValue() }}\n <i class=\"fa-solid fa-envelope mj-forms-field-link-icon\"></i>\n </a>\n </span>\n }\n @case ('URL') {\n <span class=\"mj-forms-field-value\">\n <a class=\"mj-forms-field-link\" (click)=\"OnUrlLinkClick($event)\" title=\"Open link\">\n {{ FormatValue() }}\n <i class=\"fa-solid fa-arrow-up-right-from-square mj-forms-field-link-icon\"></i>\n </a>\n </span>\n }\n @case ('Record') {\n <span class=\"mj-forms-field-value\">\n <a class=\"mj-forms-field-link\" (click)=\"OnRecordLinkClick($event)\" title=\"View related record\">\n {{ FormatValue() }}\n <i class=\"fa-solid fa-arrow-up-right-from-square mj-forms-field-link-icon\"></i>\n </a>\n </span>\n }\n @default {\n @if (Type === 'checkbox') {\n <span class=\"mj-forms-field-value\">\n <div class=\"mj-forms-field-checkbox\">\n <input type=\"checkbox\" [checked]=\"!!Value\" disabled>\n </div>\n </span>\n }\n @else if (IsLongText) {\n <span class=\"mj-forms-field-value mj-forms-field-value--long\">{{ FormatValue() }}</span>\n }\n @else {\n <span class=\"mj-forms-field-value\">{{ FormatValue() }}</span>\n }\n }\n }\n }\n </div>\n </div>\n }\n\n <!-- EDIT MODE -->\n @if (EditMode && !IsFieldReadOnly) {\n <div class=\"mj-forms-field mj-forms-field--editing\" [class.mj-forms-field--dirty]=\"IsDirty\" [class.mj-forms-field--required-empty]=\"IsRequiredEmpty\" [class.mj-forms-field--has-error]=\"ShowErrors\" [class.mj-forms-field--has-warning]=\"ShowWarnings\">\n @if (ShowLabel) {\n <label class=\"mj-forms-field-label\" [innerHTML]=\"HighlightedDisplayName\"></label>\n }\n <div class=\"mj-forms-field-control\">\n <!-- Foreign Key fields get custom search autocomplete -->\n @if (HasRelatedEntity) {\n <div class=\"mj-fk-search\" [class.mj-fk-search--matched]=\"FKIsMatched\">\n <input type=\"text\"\n class=\"mj-forms-field-input\"\n [value]=\"FKSearchText\"\n (input)=\"OnFKInput($event)\"\n (focus)=\"OnFKFocus($event)\"\n (blur)=\"OnFKBlur()\"\n placeholder=\"Search...\">\n @if (FKSearchText) {\n <button class=\"mj-fk-clear\" (mousedown)=\"OnFKClearClick($event)\" title=\"Clear\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n } @else {\n <i class=\"fa-solid fa-magnifying-glass mj-fk-search-icon\"></i>\n }\n @if (ShowFKDropdown && FKSuggestions.length > 0) {\n <div class=\"mj-fk-dropdown\" [ngStyle]=\"DropdownPositionStyle\" [class.mj-fk-dropdown--above]=\"OpenAbove\">\n @for (suggestion of FKSuggestions; track suggestion.PrimaryKeyValue) {\n <div class=\"mj-fk-option\" (mousedown)=\"OnFKSelectItem(suggestion, $event)\">\n {{ suggestion.DisplayName }}\n </div>\n }\n </div>\n }\n </div>\n }\n @else {\n @switch (Type) {\n @case ('textbox') {\n <input type=\"text\"\n class=\"mj-forms-field-input\"\n [value]=\"FormatValue()\"\n (input)=\"OnInputChange($event)\">\n }\n @case ('textarea') {\n <textarea\n class=\"mj-forms-field-input mj-forms-field-input--textarea\"\n [value]=\"FormatValue()\"\n (input)=\"OnInputChange($event)\"></textarea>\n }\n @case ('number') {\n <input type=\"number\"\n class=\"mj-forms-field-input mj-forms-field-input--number\"\n [value]=\"Value\"\n (change)=\"OnNumberChange($event)\">\n }\n @case ('datepicker') {\n <input type=\"date\"\n class=\"mj-forms-field-input mj-forms-field-input--date\"\n [value]=\"DateInputValue\"\n (change)=\"OnDateChange($event)\">\n }\n @case ('checkbox') {\n <div class=\"mj-forms-field-checkbox\">\n <input type=\"checkbox\"\n [checked]=\"!!Value\"\n (change)=\"OnCheckboxChange($event)\">\n </div>\n }\n @case ('select') {\n <div class=\"mj-custom-select-trigger\"\n tabindex=\"0\"\n (click)=\"OnSelectTriggerClick($event)\"\n (blur)=\"OnSelectTriggerBlur()\">\n <span class=\"mj-custom-select-value\" [class.mj-custom-select-value--placeholder]=\"!FormatValue()\">\n {{ FormatValue() || '-- Select --' }}\n </span>\n <i class=\"fa-solid fa-chevron-down mj-custom-select-chevron\" [class.mj-custom-select-chevron--open]=\"ShowSelectDropdown\"></i>\n </div>\n @if (ShowSelectDropdown && PossibleValues.length > 0) {\n <div class=\"mj-fk-dropdown\" [ngStyle]=\"DropdownPositionStyle\" [class.mj-fk-dropdown--above]=\"OpenAbove\">\n @for (option of PossibleValues; track option) {\n <div class=\"mj-fk-option\" [class.mj-fk-option--selected]=\"FormatValue() === option\" (mousedown)=\"OnSelectOptionClick(option, $event)\">\n {{ option }}\n </div>\n }\n </div>\n }\n }\n @case ('autocomplete') {\n <div class=\"mj-fk-search\">\n <input type=\"text\"\n class=\"mj-forms-field-input\"\n [value]=\"FormatValue()\"\n (input)=\"OnValueListInput($event)\"\n (focus)=\"OnValueListFocus($event)\"\n (blur)=\"OnValueListBlur()\"\n placeholder=\"Type to search...\">\n <i class=\"fa-solid fa-magnifying-glass mj-fk-search-icon\"></i>\n @if (ShowValueListDropdown && FilteredPossibleValues.length > 0) {\n <div class=\"mj-fk-dropdown\" [ngStyle]=\"DropdownPositionStyle\" [class.mj-fk-dropdown--above]=\"OpenAbove\">\n @for (option of FilteredPossibleValues; track option) {\n <div class=\"mj-fk-option\" (mousedown)=\"OnValueListSelect(option, $event)\">\n {{ option }}\n </div>\n }\n </div>\n }\n </div>\n }\n @default {\n <input type=\"text\"\n class=\"mj-forms-field-input\"\n [value]=\"FormatValue()\"\n (change)=\"OnInputChange($event)\">\n }\n }\n }\n </div>\n <!-- Inline validation messages -->\n @if (DisplayErrors.length > 0) {\n <div class=\"mj-forms-field-validation mj-forms-field-validation--error\">\n @for (error of DisplayErrors; track error.Message) {\n <div class=\"mj-forms-field-validation-item\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n <span>{{ error.Message }}</span>\n </div>\n }\n </div>\n }\n @if (DisplayWarnings.length > 0) {\n <div class=\"mj-forms-field-validation mj-forms-field-validation--warning\">\n @for (warning of DisplayWarnings; track warning.Message) {\n <div class=\"mj-forms-field-validation-item\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n <span>{{ warning.Message }}</span>\n </div>\n }\n </div>\n }\n </div>\n }\n}\n", styles: ["/* ============================================\n FORM FIELD - Shared styles for read and edit\n ============================================ */\n:host {\n --mj-accent: #667eea;\n --mj-accent-light: rgba(102, 126, 234, 0.08);\n --mj-text-primary: #1f2937;\n --mj-text-secondary: #4b5563;\n --mj-text-muted: #9ca3af;\n --mj-border: #e5e7eb;\n --mj-error: #ef4444;\n --mj-warning: #f59e0b;\n --mj-card-bg: #ffffff;\n --mj-forms-field-label-width: 200px;\n --mj-forms-field-gap: 12px;\n --mj-transition: 200ms;\n\n display: contents;\n}\n\n.mj-forms-field {\n display: grid;\n grid-template-columns: var(--mj-forms-field-label-width) 1fr;\n gap: var(--mj-forms-field-gap);\n align-items: baseline;\n padding: 8px 0;\n transition: all var(--mj-transition) ease;\n}\n\n/* Subtle row hover in edit mode */\n.mj-forms-field--editing:hover {\n background: var(--mj-accent-light);\n border-radius: 6px;\n margin: 0 -8px;\n padding: 8px 8px;\n}\n\n/* ============================================\n LABEL\n ============================================ */\n.mj-forms-field-label {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n padding-top: 2px;\n word-break: break-word;\n}\n\n/* ============================================\n FIELD CONTROL WRAPPER (value + dirty dot)\n ============================================ */\n.mj-forms-field-control {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n}\n\n.mj-forms-field-control > * {\n flex: 1;\n min-width: 0;\n}\n\n/* ============================================\n DIRTY INDICATOR (solid amber dot after label)\n ============================================ */\n.mj-forms-field--dirty .mj-forms-field-label::after {\n content: '';\n display: inline-block;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--mj-warning);\n margin-left: 6px;\n vertical-align: middle;\n}\n\n/* ============================================\n REQUIRED FIELD - red underline when empty\n ============================================ */\n.mj-forms-field--required-empty .mj-forms-field-input {\n border-bottom-color: var(--mj-error);\n}\n\n.mj-forms-field--required-empty .mj-forms-field-input:focus {\n background: #fef2f2;\n border-bottom-color: var(--mj-error);\n}\n\n.mj-forms-field--required-empty .mj-custom-select-trigger {\n border-bottom-color: var(--mj-error);\n}\n\n.mj-forms-field--required-empty .mj-fk-search .mj-forms-field-input {\n border-bottom-color: var(--mj-error);\n}\n\n/* ============================================\n READ-ONLY VALUE\n ============================================ */\n.mj-forms-field-value {\n font-size: 14px;\n color: var(--mj-text-primary);\n min-height: 24px;\n display: flex;\n align-items: center;\n overflow-wrap: break-word;\n word-break: break-word;\n}\n\n.mj-forms-field-value--long {\n white-space: pre-line;\n max-height: 300px;\n overflow: auto;\n}\n\n/* Read-only fields in edit mode */\n.mj-forms-field--readonly {\n opacity: 0.7;\n}\n\n.mj-forms-field--readonly .mj-forms-field-value {\n color: var(--mj-text-secondary);\n}\n\n/* ============================================\n LINKS (FK, email, URL)\n ============================================ */\n.mj-forms-field-link {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-accent);\n cursor: pointer;\n font-weight: 400;\n font-size: 14px;\n transition: color var(--mj-transition);\n text-decoration: none;\n}\n\n.mj-forms-field-link:hover {\n color: #5a6fd6;\n}\n\n.mj-forms-field-link-icon {\n font-size: 11px;\n opacity: 0;\n transition: opacity var(--mj-transition);\n}\n\n.mj-forms-field-link:hover .mj-forms-field-link-icon {\n opacity: 1;\n}\n\n/* FK fields showing entity name instead of raw ID */\n.mj-forms-field-link--fk {\n font-size: 14px;\n font-weight: 400;\n}\n\n/* ============================================\n EDIT MODE INPUTS - Clean underline style\n ============================================ */\n.mj-forms-field-input {\n font-size: 14px;\n font-family: inherit;\n color: var(--mj-text-primary);\n background: transparent;\n border: none;\n border-bottom: 1.5px solid var(--mj-border);\n padding: 4px 0;\n width: 100%;\n outline: none;\n transition: border-color var(--mj-transition) ease,\n background var(--mj-transition) ease;\n}\n\n.mj-forms-field-input:focus {\n border-bottom-color: var(--mj-accent);\n background: var(--mj-accent-light);\n border-radius: 4px 4px 0 0;\n padding: 4px 6px;\n}\n\n.mj-forms-field-input::placeholder {\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n/* Textarea variant */\n.mj-forms-field-input--textarea {\n resize: vertical;\n min-height: 60px;\n border: 1.5px solid var(--mj-border);\n border-radius: 6px;\n padding: 8px 10px;\n background: white;\n font-family: inherit;\n}\n\n.mj-forms-field-input--textarea:focus {\n border-color: var(--mj-accent);\n box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);\n background: white;\n padding: 8px 10px;\n border-radius: 6px;\n}\n\n/* Number input - narrower */\n.mj-forms-field-input--number {\n max-width: 200px;\n}\n\n/* Date input - narrower */\n.mj-forms-field-input--date {\n max-width: 220px;\n}\n\n/* ============================================\n CHECKBOX (custom styled)\n ============================================ */\n.mj-forms-field-checkbox {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.mj-forms-field-checkbox input[type=\"checkbox\"] {\n appearance: none;\n width: 18px;\n height: 18px;\n border: 2px solid var(--mj-border);\n border-radius: 4px;\n cursor: pointer;\n position: relative;\n transition: all var(--mj-transition) ease;\n flex-shrink: 0;\n}\n\n.mj-forms-field-checkbox input[type=\"checkbox\"]:checked {\n background: var(--mj-accent);\n border-color: var(--mj-accent);\n}\n\n.mj-forms-field-checkbox input[type=\"checkbox\"]:checked::after {\n content: '';\n position: absolute;\n left: 5px;\n top: 1px;\n width: 5px;\n height: 9px;\n border: solid white;\n border-width: 0 2px 2px 0;\n transform: rotate(45deg);\n}\n\n.mj-forms-field-checkbox input[type=\"checkbox\"]:disabled {\n opacity: 0.5;\n cursor: default;\n}\n\n/* ============================================\n CUSTOM SELECT DROPDOWN (replaces native <select>)\n ============================================ */\n.mj-custom-select-trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n font-size: 14px;\n font-family: inherit;\n color: var(--mj-text-primary);\n background: transparent;\n border: none;\n border-bottom: 1.5px solid var(--mj-border);\n padding: 4px 0;\n width: 100%;\n cursor: pointer;\n outline: none;\n transition: border-color var(--mj-transition) ease,\n background var(--mj-transition) ease;\n}\n\n.mj-custom-select-trigger:focus {\n border-bottom-color: var(--mj-accent);\n background: var(--mj-accent-light);\n border-radius: 4px 4px 0 0;\n padding: 4px 6px;\n}\n\n.mj-custom-select-value {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mj-custom-select-value--placeholder {\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n.mj-custom-select-chevron {\n font-size: 11px;\n color: var(--mj-text-muted);\n transition: transform var(--mj-transition) ease;\n flex-shrink: 0;\n margin-left: 8px;\n}\n\n.mj-custom-select-chevron--open {\n transform: rotate(180deg);\n}\n\n/* ============================================\n FK SEARCH (custom autocomplete)\n ============================================ */\n.mj-fk-search {\n position: relative;\n display: flex;\n align-items: center;\n width: 100%;\n}\n\n.mj-fk-search .mj-forms-field-input {\n padding-right: 28px;\n}\n\n.mj-fk-search-icon {\n position: absolute;\n right: 4px;\n color: var(--mj-text-muted);\n font-size: 12px;\n pointer-events: none;\n}\n\n.mj-fk-clear {\n position: absolute;\n right: 2px;\n background: none;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n font-size: 11px;\n padding: 4px 6px;\n line-height: 1;\n border-radius: 3px;\n transition: all var(--mj-transition);\n}\n\n.mj-fk-clear:hover {\n color: var(--mj-error);\n background: rgba(239, 68, 68, 0.08);\n}\n\n/* Matched state: solid accent underline */\n.mj-fk-search--matched .mj-forms-field-input {\n border-bottom: 2px solid var(--mj-accent);\n}\n\n/* ============================================\n FLOATING DROPDOWN PANEL (position: fixed via ngStyle)\n ============================================ */\n.mj-fk-dropdown {\n background: var(--mj-card-bg);\n border: 1px solid var(--mj-border);\n border-radius: 8px;\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);\n max-height: 240px;\n overflow-y: auto;\n padding: 4px;\n animation: mj-dropdown-in 150ms ease;\n}\n\n.mj-fk-dropdown--above {\n animation: mj-dropdown-in-above 150ms ease;\n}\n\n.mj-fk-option {\n padding: 10px 14px;\n font-size: 14px;\n color: var(--mj-text-primary);\n cursor: pointer;\n transition: background var(--mj-transition);\n border-radius: 6px;\n}\n\n.mj-fk-option:hover {\n background: var(--mj-accent-light);\n}\n\n.mj-fk-option--selected {\n background: var(--mj-accent-light);\n font-weight: 600;\n color: var(--mj-accent);\n}\n\n.mj-fk-option--selected:hover {\n background: rgba(102, 126, 234, 0.15);\n}\n\n@keyframes mj-dropdown-in {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n@keyframes mj-dropdown-in-above {\n from { opacity: 0; transform: translateY(4px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n/* ============================================\n SEARCH HIGHLIGHTING\n ============================================ */\n.mj-forms-field-label :global(.mj-forms-search-highlight) {\n background-color: #fef08a;\n color: #854d0e;\n padding: 0;\n border-radius: 2px;\n font-weight: 700;\n box-shadow: 0 0 0 2px #fef08a;\n}\n\n/* ============================================\n VALIDATION ERROR STATE\n ============================================ */\n.mj-forms-field--has-error .mj-forms-field-input {\n border-bottom-color: var(--mj-error);\n border-bottom-width: 2px;\n}\n\n.mj-forms-field--has-error .mj-forms-field-input:focus {\n background: #fef2f2;\n border-bottom-color: var(--mj-error);\n}\n\n.mj-forms-field--has-error .mj-forms-field-input--textarea {\n border-color: var(--mj-error);\n}\n\n.mj-forms-field--has-error .mj-forms-field-input--textarea:focus {\n border-color: var(--mj-error);\n box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.08);\n}\n\n.mj-forms-field--has-error .mj-custom-select-trigger {\n border-bottom-color: var(--mj-error);\n border-bottom-width: 2px;\n}\n\n.mj-forms-field--has-error .mj-fk-search .mj-forms-field-input {\n border-bottom-color: var(--mj-error);\n border-bottom-width: 2px;\n}\n\n/* ============================================\n VALIDATION WARNING STATE\n ============================================ */\n.mj-forms-field--has-warning .mj-forms-field-input {\n border-bottom-color: var(--mj-warning);\n border-bottom-width: 2px;\n}\n\n.mj-forms-field--has-warning .mj-forms-field-input:focus {\n background: #fffbeb;\n border-bottom-color: var(--mj-warning);\n}\n\n.mj-forms-field--has-warning .mj-forms-field-input--textarea {\n border-color: var(--mj-warning);\n}\n\n.mj-forms-field--has-warning .mj-forms-field-input--textarea:focus {\n border-color: var(--mj-warning);\n box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.08);\n}\n\n.mj-forms-field--has-warning .mj-custom-select-trigger {\n border-bottom-color: var(--mj-warning);\n border-bottom-width: 2px;\n}\n\n.mj-forms-field--has-warning .mj-fk-search .mj-forms-field-input {\n border-bottom-color: var(--mj-warning);\n border-bottom-width: 2px;\n}\n\n/* ============================================\n VALIDATION MESSAGE AREA\n ============================================ */\n.mj-forms-field-validation {\n grid-column: 2;\n display: flex;\n flex-direction: column;\n gap: 2px;\n margin-top: -2px;\n overflow: hidden;\n animation: mj-validation-slide-in 200ms ease-out;\n}\n\n.mj-forms-field-validation-item {\n display: flex;\n align-items: flex-start;\n gap: 6px;\n font-size: 12px;\n line-height: 1.4;\n padding: 3px 0 1px;\n}\n\n.mj-forms-field-validation-item i {\n font-size: 11px;\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n/* Error message colors */\n.mj-forms-field-validation--error .mj-forms-field-validation-item {\n color: var(--mj-error);\n}\n\n.mj-forms-field-validation--error .mj-forms-field-validation-item i {\n color: var(--mj-error);\n}\n\n/* Warning message colors */\n.mj-forms-field-validation--warning .mj-forms-field-validation-item {\n color: #b45309;\n}\n\n.mj-forms-field-validation--warning .mj-forms-field-validation-item i {\n color: var(--mj-warning);\n}\n\n@keyframes mj-validation-slide-in {\n from {\n opacity: 0;\n max-height: 0;\n transform: translateY(-4px);\n }\n to {\n opacity: 1;\n max-height: 100px;\n transform: translateY(0);\n }\n}\n\n/* ============================================\n RESPONSIVE\n ============================================ */\n@media (max-width: 640px) {\n .mj-forms-field {\n grid-template-columns: 1fr;\n gap: 4px;\n }\n\n .mj-forms-field-label {\n font-size: 12px;\n }\n\n .mj-forms-field-validation {\n grid-column: 1;\n }\n}\n"] }]
|
|
1178
|
+
args: [{ standalone: false, selector: 'mj-form-field', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (Record && (Record.IsSaved || !IsFieldReadOnly)) {\n <!-- READ-ONLY MODE -->\n @if ((!EditMode || IsFieldReadOnly) && !ShouldHideField) {\n <div class=\"mj-forms-field\" [class.mj-forms-field--readonly]=\"EditMode && IsFieldReadOnly\" [class.mj-forms-field--dirty]=\"IsDirty\">\n @if (ShowLabel) {\n <label class=\"mj-forms-field-label\" [innerHTML]=\"HighlightedDisplayName\"></label>\n }\n <div class=\"mj-forms-field-control\">\n <!-- FK fields with a mapped name field: show the name as a hyperlink -->\n @if (IsFKWithNameField) {\n <span class=\"mj-forms-field-value\">\n <a class=\"mj-forms-field-link mj-forms-field-link--fk\" (click)=\"OnRecordLinkClick($event)\" title=\"View related record\">\n {{ FKDisplayName }}\n </a>\n </span>\n }\n @else {\n @switch (LinkType) {\n @case ('Email') {\n <span class=\"mj-forms-field-value\">\n <a class=\"mj-forms-field-link\" (click)=\"OnEmailLinkClick($event)\" title=\"Send email\">\n {{ FormatValue() }}\n <i class=\"fa-solid fa-envelope mj-forms-field-link-icon\"></i>\n </a>\n </span>\n }\n @case ('URL') {\n <span class=\"mj-forms-field-value\">\n <a class=\"mj-forms-field-link\" (click)=\"OnUrlLinkClick($event)\" title=\"Open link\">\n {{ FormatValue() }}\n <i class=\"fa-solid fa-arrow-up-right-from-square mj-forms-field-link-icon\"></i>\n </a>\n </span>\n }\n @case ('Record') {\n <span class=\"mj-forms-field-value\">\n <a class=\"mj-forms-field-link\" (click)=\"OnRecordLinkClick($event)\" title=\"View related record\">\n {{ FormatValue() }}\n <i class=\"fa-solid fa-arrow-up-right-from-square mj-forms-field-link-icon\"></i>\n </a>\n </span>\n }\n @default {\n @if (Type === 'checkbox') {\n <span class=\"mj-forms-field-value\">\n <div class=\"mj-forms-field-checkbox\">\n <input type=\"checkbox\" [checked]=\"!!Value\" disabled>\n </div>\n </span>\n }\n @else if (IsLongText) {\n <span class=\"mj-forms-field-value mj-forms-field-value--long\">{{ FormatValue() }}</span>\n }\n @else {\n <span class=\"mj-forms-field-value\">{{ FormatValue() }}</span>\n }\n }\n }\n }\n </div>\n </div>\n }\n\n <!-- EDIT MODE -->\n @if (EditMode && !IsFieldReadOnly) {\n <div class=\"mj-forms-field mj-forms-field--editing\" [class.mj-forms-field--dirty]=\"IsDirty\" [class.mj-forms-field--required-empty]=\"IsRequiredEmpty\" [class.mj-forms-field--has-error]=\"ShowErrors\" [class.mj-forms-field--has-warning]=\"ShowWarnings\">\n @if (ShowLabel) {\n <label class=\"mj-forms-field-label\" [innerHTML]=\"HighlightedDisplayName\"></label>\n }\n <div class=\"mj-forms-field-control\">\n <!-- Foreign Key fields get custom search autocomplete -->\n @if (HasRelatedEntity) {\n <div class=\"mj-fk-search\" [class.mj-fk-search--matched]=\"FKIsMatched\">\n <input type=\"text\"\n class=\"mj-forms-field-input\"\n [value]=\"FKSearchText\"\n (input)=\"OnFKInput($event)\"\n (focus)=\"OnFKFocus($event)\"\n (blur)=\"OnFKBlur()\"\n placeholder=\"Search...\">\n @if (FKSearchText) {\n <button class=\"mj-fk-clear\" (mousedown)=\"OnFKClearClick($event)\" title=\"Clear\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n } @else {\n <i class=\"fa-solid fa-magnifying-glass mj-fk-search-icon\"></i>\n }\n @if (ShowFKDropdown && FKSuggestions.length > 0) {\n <div class=\"mj-fk-dropdown\" [ngStyle]=\"DropdownPositionStyle\" [class.mj-fk-dropdown--above]=\"OpenAbove\">\n @for (suggestion of FKSuggestions; track suggestion.PrimaryKeyValue) {\n <div class=\"mj-fk-option\" (mousedown)=\"OnFKSelectItem(suggestion, $event)\">\n {{ suggestion.DisplayName }}\n </div>\n }\n </div>\n }\n </div>\n }\n @else {\n @switch (Type) {\n @case ('textbox') {\n <input type=\"text\"\n class=\"mj-forms-field-input\"\n [value]=\"FormatValue()\"\n (input)=\"OnInputChange($event)\">\n }\n @case ('textarea') {\n <textarea\n class=\"mj-forms-field-input mj-forms-field-input--textarea\"\n [value]=\"FormatValue()\"\n (input)=\"OnInputChange($event)\"></textarea>\n }\n @case ('number') {\n <input type=\"number\"\n class=\"mj-forms-field-input mj-forms-field-input--number\"\n [value]=\"Value\"\n (change)=\"OnNumberChange($event)\">\n }\n @case ('datepicker') {\n <input type=\"date\"\n class=\"mj-forms-field-input mj-forms-field-input--date\"\n [value]=\"DateInputValue\"\n (change)=\"OnDateChange($event)\">\n }\n @case ('checkbox') {\n <div class=\"mj-forms-field-checkbox\">\n <input type=\"checkbox\"\n [checked]=\"!!Value\"\n (change)=\"OnCheckboxChange($event)\">\n </div>\n }\n @case ('select') {\n <div class=\"mj-custom-select-trigger\"\n tabindex=\"0\"\n (click)=\"OnSelectTriggerClick($event)\"\n (blur)=\"OnSelectTriggerBlur()\">\n <span class=\"mj-custom-select-value\" [class.mj-custom-select-value--placeholder]=\"!FormatValue()\">\n {{ FormatValue() || '-- Select --' }}\n </span>\n <i class=\"fa-solid fa-chevron-down mj-custom-select-chevron\" [class.mj-custom-select-chevron--open]=\"ShowSelectDropdown\"></i>\n </div>\n @if (ShowSelectDropdown && PossibleValues.length > 0) {\n <div class=\"mj-fk-dropdown\" [ngStyle]=\"DropdownPositionStyle\" [class.mj-fk-dropdown--above]=\"OpenAbove\">\n @for (option of PossibleValues; track option) {\n <div class=\"mj-fk-option\" [class.mj-fk-option--selected]=\"FormatValue() === option\" (mousedown)=\"OnSelectOptionClick(option, $event)\">\n {{ option }}\n </div>\n }\n </div>\n }\n }\n @case ('autocomplete') {\n <div class=\"mj-fk-search\">\n <input type=\"text\"\n class=\"mj-forms-field-input\"\n [value]=\"FormatValue()\"\n (input)=\"OnValueListInput($event)\"\n (focus)=\"OnValueListFocus($event)\"\n (blur)=\"OnValueListBlur()\"\n placeholder=\"Type to search...\">\n <i class=\"fa-solid fa-magnifying-glass mj-fk-search-icon\"></i>\n @if (ShowValueListDropdown && FilteredPossibleValues.length > 0) {\n <div class=\"mj-fk-dropdown\" [ngStyle]=\"DropdownPositionStyle\" [class.mj-fk-dropdown--above]=\"OpenAbove\">\n @for (option of FilteredPossibleValues; track option) {\n <div class=\"mj-fk-option\" (mousedown)=\"OnValueListSelect(option, $event)\">\n {{ option }}\n </div>\n }\n </div>\n }\n </div>\n }\n @default {\n <input type=\"text\"\n class=\"mj-forms-field-input\"\n [value]=\"FormatValue()\"\n (change)=\"OnInputChange($event)\">\n }\n }\n }\n </div>\n <!-- Inline validation messages -->\n @if (DisplayErrors.length > 0) {\n <div class=\"mj-forms-field-validation mj-forms-field-validation--error\">\n @for (error of DisplayErrors; track error.Message) {\n <div class=\"mj-forms-field-validation-item\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n <span>{{ error.Message }}</span>\n </div>\n }\n </div>\n }\n @if (DisplayWarnings.length > 0) {\n <div class=\"mj-forms-field-validation mj-forms-field-validation--warning\">\n @for (warning of DisplayWarnings; track warning.Message) {\n <div class=\"mj-forms-field-validation-item\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n <span>{{ warning.Message }}</span>\n </div>\n }\n </div>\n }\n </div>\n }\n}\n", styles: ["/* ============================================\n FORM FIELD - Shared styles for read and edit\n ============================================ */\n:host {\n --mj-forms-field-label-width: 200px;\n --mj-forms-field-gap: 12px;\n\n display: contents;\n}\n\n.mj-forms-field {\n display: grid;\n grid-template-columns: var(--mj-forms-field-label-width) 1fr;\n gap: var(--mj-forms-field-gap);\n align-items: baseline;\n padding: 8px 0;\n transition: all var(--mj-transition-base) ease;\n}\n\n/* Subtle row hover in edit mode */\n.mj-forms-field--editing:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n border-radius: 6px;\n margin: 0 -8px;\n padding: 8px 8px;\n}\n\n/* ============================================\n LABEL\n ============================================ */\n.mj-forms-field-label {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n padding-top: 2px;\n word-break: break-word;\n}\n\n/* ============================================\n FIELD CONTROL WRAPPER (value + dirty dot)\n ============================================ */\n.mj-forms-field-control {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n}\n\n.mj-forms-field-control > * {\n flex: 1;\n min-width: 0;\n}\n\n/* ============================================\n DIRTY INDICATOR (solid amber dot after label)\n ============================================ */\n.mj-forms-field--dirty .mj-forms-field-label::after {\n content: '';\n display: inline-block;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--mj-status-warning);\n margin-left: 6px;\n vertical-align: middle;\n}\n\n/* ============================================\n REQUIRED FIELD - red underline when empty\n ============================================ */\n.mj-forms-field--required-empty .mj-forms-field-input {\n border-bottom-color: var(--mj-status-error);\n}\n\n.mj-forms-field--required-empty .mj-forms-field-input:focus {\n background: color-mix(in srgb, var(--mj-status-error) 5%, var(--mj-bg-surface));\n border-bottom-color: var(--mj-status-error);\n}\n\n.mj-forms-field--required-empty .mj-custom-select-trigger {\n border-bottom-color: var(--mj-status-error);\n}\n\n.mj-forms-field--required-empty .mj-fk-search .mj-forms-field-input {\n border-bottom-color: var(--mj-status-error);\n}\n\n/* ============================================\n READ-ONLY VALUE\n ============================================ */\n.mj-forms-field-value {\n font-size: 14px;\n color: var(--mj-text-primary);\n min-height: 24px;\n display: flex;\n align-items: center;\n overflow-wrap: break-word;\n word-break: break-word;\n}\n\n.mj-forms-field-value--long {\n white-space: pre-line;\n max-height: 300px;\n overflow: auto;\n}\n\n/* Read-only fields in edit mode */\n.mj-forms-field--readonly {\n opacity: 0.7;\n}\n\n.mj-forms-field--readonly .mj-forms-field-value {\n color: var(--mj-text-secondary);\n}\n\n/* ============================================\n LINKS (FK, email, URL)\n ============================================ */\n.mj-forms-field-link {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-brand-primary);\n cursor: pointer;\n font-weight: 400;\n font-size: 14px;\n transition: color var(--mj-transition-base);\n text-decoration: none;\n}\n\n.mj-forms-field-link:hover {\n color: var(--mj-brand-primary-hover);\n}\n\n.mj-forms-field-link-icon {\n font-size: 11px;\n opacity: 0;\n transition: opacity var(--mj-transition-base);\n}\n\n.mj-forms-field-link:hover .mj-forms-field-link-icon {\n opacity: 1;\n}\n\n/* FK fields showing entity name instead of raw ID */\n.mj-forms-field-link--fk {\n font-size: 14px;\n font-weight: 400;\n}\n\n/* ============================================\n EDIT MODE INPUTS - Clean underline style\n ============================================ */\n.mj-forms-field-input {\n font-size: 14px;\n font-family: inherit;\n color: var(--mj-text-primary);\n background: transparent;\n border: none;\n border-bottom: 1.5px solid var(--mj-border-default);\n padding: 4px 0;\n width: 100%;\n outline: none;\n transition: border-color var(--mj-transition-base) ease,\n background var(--mj-transition-base) ease;\n}\n\n.mj-forms-field-input:focus {\n border-bottom-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n border-radius: 4px 4px 0 0;\n padding: 4px 6px;\n}\n\n.mj-forms-field-input::placeholder {\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n/* Textarea variant */\n.mj-forms-field-input--textarea {\n resize: vertical;\n min-height: 60px;\n border: 1.5px solid var(--mj-border-default);\n border-radius: 6px;\n padding: 8px 10px;\n background: var(--mj-bg-surface);\n font-family: inherit;\n}\n\n.mj-forms-field-input--textarea:focus {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n background: var(--mj-bg-surface);\n padding: 8px 10px;\n border-radius: 6px;\n}\n\n/* Number input - narrower */\n.mj-forms-field-input--number {\n max-width: 200px;\n}\n\n/* Date input - narrower */\n.mj-forms-field-input--date {\n max-width: 220px;\n}\n\n/* ============================================\n CHECKBOX (custom styled)\n ============================================ */\n.mj-forms-field-checkbox {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.mj-forms-field-checkbox input[type=\"checkbox\"] {\n appearance: none;\n width: 18px;\n height: 18px;\n border: 2px solid var(--mj-border-default);\n border-radius: 4px;\n cursor: pointer;\n position: relative;\n transition: all var(--mj-transition-base) ease;\n flex-shrink: 0;\n}\n\n.mj-forms-field-checkbox input[type=\"checkbox\"]:checked {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.mj-forms-field-checkbox input[type=\"checkbox\"]:checked::after {\n content: '';\n position: absolute;\n left: 5px;\n top: 1px;\n width: 5px;\n height: 9px;\n border: solid var(--mj-text-inverse);\n border-width: 0 2px 2px 0;\n transform: rotate(45deg);\n}\n\n.mj-forms-field-checkbox input[type=\"checkbox\"]:disabled {\n opacity: 0.5;\n cursor: default;\n}\n\n/* ============================================\n CUSTOM SELECT DROPDOWN (replaces native <select>)\n ============================================ */\n.mj-custom-select-trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n font-size: 14px;\n font-family: inherit;\n color: var(--mj-text-primary);\n background: transparent;\n border: none;\n border-bottom: 1.5px solid var(--mj-border-default);\n padding: 4px 0;\n width: 100%;\n cursor: pointer;\n outline: none;\n transition: border-color var(--mj-transition-base) ease,\n background var(--mj-transition-base) ease;\n}\n\n.mj-custom-select-trigger:focus {\n border-bottom-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n border-radius: 4px 4px 0 0;\n padding: 4px 6px;\n}\n\n.mj-custom-select-value {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mj-custom-select-value--placeholder {\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n.mj-custom-select-chevron {\n font-size: 11px;\n color: var(--mj-text-muted);\n transition: transform var(--mj-transition-base) ease;\n flex-shrink: 0;\n margin-left: 8px;\n}\n\n.mj-custom-select-chevron--open {\n transform: rotate(180deg);\n}\n\n/* ============================================\n FK SEARCH (custom autocomplete)\n ============================================ */\n.mj-fk-search {\n position: relative;\n display: flex;\n align-items: center;\n width: 100%;\n}\n\n.mj-fk-search .mj-forms-field-input {\n padding-right: 28px;\n}\n\n.mj-fk-search-icon {\n position: absolute;\n right: 4px;\n color: var(--mj-text-muted);\n font-size: 12px;\n pointer-events: none;\n}\n\n.mj-fk-clear {\n position: absolute;\n right: 2px;\n background: none;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n font-size: 11px;\n padding: 4px 6px;\n line-height: 1;\n border-radius: 3px;\n transition: all var(--mj-transition-base);\n}\n\n.mj-fk-clear:hover {\n color: var(--mj-status-error);\n background: color-mix(in srgb, var(--mj-status-error) 8%, transparent);\n}\n\n/* Matched state: solid accent underline */\n.mj-fk-search--matched .mj-forms-field-input {\n border-bottom: 2px solid var(--mj-brand-primary);\n}\n\n/* ============================================\n FLOATING DROPDOWN PANEL (position: fixed via ngStyle)\n ============================================ */\n.mj-fk-dropdown {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n box-shadow: var(--mj-shadow-lg);\n max-height: 240px;\n overflow-y: auto;\n padding: 4px;\n animation: mj-dropdown-in 150ms ease;\n}\n\n.mj-fk-dropdown--above {\n animation: mj-dropdown-in-above 150ms ease;\n}\n\n.mj-fk-option {\n padding: 10px 14px;\n font-size: 14px;\n color: var(--mj-text-primary);\n cursor: pointer;\n transition: background var(--mj-transition-base);\n border-radius: 6px;\n}\n\n.mj-fk-option:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n}\n\n.mj-fk-option--selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n font-weight: 600;\n color: var(--mj-brand-primary);\n}\n\n.mj-fk-option--selected:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n@keyframes mj-dropdown-in {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n@keyframes mj-dropdown-in-above {\n from { opacity: 0; transform: translateY(4px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n/* ============================================\n SEARCH HIGHLIGHTING\n ============================================ */\n.mj-forms-field-label :global(.mj-forms-search-highlight) {\n background-color: var(--mj-color-warning-200, #fef08a);\n color: var(--mj-color-warning-800, #854d0e);\n padding: 0;\n border-radius: 2px;\n font-weight: 700;\n box-shadow: 0 0 0 2px var(--mj-color-warning-200, #fef08a);\n}\n\n/* ============================================\n VALIDATION ERROR STATE\n ============================================ */\n.mj-forms-field--has-error .mj-forms-field-input {\n border-bottom-color: var(--mj-status-error);\n border-bottom-width: 2px;\n}\n\n.mj-forms-field--has-error .mj-forms-field-input:focus {\n background: color-mix(in srgb, var(--mj-status-error) 5%, var(--mj-bg-surface));\n border-bottom-color: var(--mj-status-error);\n}\n\n.mj-forms-field--has-error .mj-forms-field-input--textarea {\n border-color: var(--mj-status-error);\n}\n\n.mj-forms-field--has-error .mj-forms-field-input--textarea:focus {\n border-color: var(--mj-status-error);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-error) 8%, transparent);\n}\n\n.mj-forms-field--has-error .mj-custom-select-trigger {\n border-bottom-color: var(--mj-status-error);\n border-bottom-width: 2px;\n}\n\n.mj-forms-field--has-error .mj-fk-search .mj-forms-field-input {\n border-bottom-color: var(--mj-status-error);\n border-bottom-width: 2px;\n}\n\n/* ============================================\n VALIDATION WARNING STATE\n ============================================ */\n.mj-forms-field--has-warning .mj-forms-field-input {\n border-bottom-color: var(--mj-status-warning);\n border-bottom-width: 2px;\n}\n\n.mj-forms-field--has-warning .mj-forms-field-input:focus {\n background: color-mix(in srgb, var(--mj-status-warning) 5%, var(--mj-bg-surface));\n border-bottom-color: var(--mj-status-warning);\n}\n\n.mj-forms-field--has-warning .mj-forms-field-input--textarea {\n border-color: var(--mj-status-warning);\n}\n\n.mj-forms-field--has-warning .mj-forms-field-input--textarea:focus {\n border-color: var(--mj-status-warning);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-warning) 8%, transparent);\n}\n\n.mj-forms-field--has-warning .mj-custom-select-trigger {\n border-bottom-color: var(--mj-status-warning);\n border-bottom-width: 2px;\n}\n\n.mj-forms-field--has-warning .mj-fk-search .mj-forms-field-input {\n border-bottom-color: var(--mj-status-warning);\n border-bottom-width: 2px;\n}\n\n/* ============================================\n VALIDATION MESSAGE AREA\n ============================================ */\n.mj-forms-field-validation {\n grid-column: 2;\n display: flex;\n flex-direction: column;\n gap: 2px;\n margin-top: -2px;\n overflow: hidden;\n animation: mj-validation-slide-in 200ms ease-out;\n}\n\n.mj-forms-field-validation-item {\n display: flex;\n align-items: flex-start;\n gap: 6px;\n font-size: 12px;\n line-height: 1.4;\n padding: 3px 0 1px;\n}\n\n.mj-forms-field-validation-item i {\n font-size: 11px;\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n/* Error message colors */\n.mj-forms-field-validation--error .mj-forms-field-validation-item {\n color: var(--mj-status-error);\n}\n\n.mj-forms-field-validation--error .mj-forms-field-validation-item i {\n color: var(--mj-status-error);\n}\n\n/* Warning message colors */\n.mj-forms-field-validation--warning .mj-forms-field-validation-item {\n color: var(--mj-color-warning-700);\n}\n\n.mj-forms-field-validation--warning .mj-forms-field-validation-item i {\n color: var(--mj-status-warning);\n}\n\n@keyframes mj-validation-slide-in {\n from {\n opacity: 0;\n max-height: 0;\n transform: translateY(-4px);\n }\n to {\n opacity: 1;\n max-height: 100px;\n transform: translateY(0);\n }\n}\n\n/* ============================================\n RESPONSIVE\n ============================================ */\n@media (max-width: 640px) {\n .mj-forms-field {\n grid-template-columns: 1fr;\n gap: 4px;\n }\n\n .mj-forms-field-label {\n font-size: 12px;\n }\n\n .mj-forms-field-validation {\n grid-column: 1;\n }\n}\n"] }]
|
|
1174
1179
|
}], null, { Record: [{
|
|
1175
1180
|
type: Input
|
|
1176
1181
|
}], EditMode: [{
|