@memberjunction/ng-base-forms 5.7.0 → 5.9.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.
@@ -1166,11 +1166,11 @@ export class MjFormFieldComponent {
1166
1166
  i0.ɵɵconditionalCreate(0, MjFormFieldComponent_Conditional_0_Template, 2, 2);
1167
1167
  } if (rf & 2) {
1168
1168
  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: 500;\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 });
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 });
1170
1170
  }
1171
1171
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MjFormFieldComponent, [{
1172
1172
  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: 500;\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"] }]
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"] }]
1174
1174
  }], null, { Record: [{
1175
1175
  type: Input
1176
1176
  }], EditMode: [{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-base-forms",
3
- "version": "5.7.0",
3
+ "version": "5.9.0",
4
4
  "description": "MemberJunction: Generic Angular form components for rendering and editing entity records. Provides configurable toolbar, modern form fields (PrimeNG unstyled), collapsible panels with IS-A inheritance support, and event-driven navigation. Zero Explorer dependencies - usable in any Angular application.",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -36,13 +36,13 @@
36
36
  "primeng": "21.1.1"
37
37
  },
38
38
  "dependencies": {
39
- "@memberjunction/core": "5.7.0",
40
- "@memberjunction/core-entities": "5.7.0",
41
- "@memberjunction/global": "5.7.0",
42
- "@memberjunction/ng-base-types": "5.7.0",
43
- "@memberjunction/ng-list-management": "5.7.0",
44
- "@memberjunction/ng-record-changes": "5.7.0",
45
- "@memberjunction/ng-entity-viewer": "5.7.0",
39
+ "@memberjunction/core": "5.9.0",
40
+ "@memberjunction/core-entities": "5.9.0",
41
+ "@memberjunction/global": "5.9.0",
42
+ "@memberjunction/ng-base-types": "5.9.0",
43
+ "@memberjunction/ng-list-management": "5.9.0",
44
+ "@memberjunction/ng-record-changes": "5.9.0",
45
+ "@memberjunction/ng-entity-viewer": "5.9.0",
46
46
  "rxjs": "^7.8.2",
47
47
  "tslib": "^2.8.1"
48
48
  },