@memberjunction/ng-forms 5.41.0 → 5.42.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.
|
@@ -241,7 +241,7 @@ export class DynamicFormComponent {
|
|
|
241
241
|
this.FormGroup = new FormGroup(controls);
|
|
242
242
|
}
|
|
243
243
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DynamicFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
244
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: DynamicFormComponent, isStandalone: false, selector: "mj-dynamic-form", inputs: { FormDefinition: "FormDefinition", Disabled: "Disabled", Visible: "Visible" }, outputs: { FormSubmitted: "FormSubmitted" }, ngImport: i0, template: "@if (IsVisible) {\n <div class=\"dynamic-form\">\n <!-- Simple Choice Mode (single question, no title, buttongroup/radio) -->\n @if (IsSimpleChoice) {\n <div class=\"simple-choice-buttons\">\n @for (option of GetOptions(FormDefinition.questions[0]); track TrackByValue($index, option)) {\n <button\n mjButton\n [variant]=\"IsSimpleChoiceSelected(option.value) ? 'primary' : 'secondary'\"\n [disabled]=\"Disabled\"\n (click)=\"OnSimpleChoiceClick(option.value)\"\n class=\"choice-button\"\n [class.selected]=\"IsSimpleChoiceSelected(option.value)\"\n >\n <span>\n @if (IsSimpleChoiceSelected(option.value)) {\n <i class=\"fa-solid fa-check\" aria-hidden=\"true\"></i>\n } @else if (HasIcon(option)) {\n <i class=\"fa {{ option.icon }}\" aria-hidden=\"true\"></i>\n }\n {{ option.label }}\n </span>\n </button>\n }\n </div>\n }\n <!-- Full Form Mode (complex forms) -->\n @if (!IsSimpleChoice) {\n <form [formGroup]=\"FormGroup\" (ngSubmit)=\"OnSubmit()\" class=\"response-form\">\n <!-- Form Title -->\n @if (FormDefinition.title) {\n <h3 class=\"form-title\">{{ FormDefinition.title }}</h3>\n }\n <!-- Form Description -->\n @if (FormDefinition.description) {\n <p class=\"form-description\">{{ FormDefinition.description }}</p>\n }\n <!-- Questions (excludes footer choice question) -->\n @if (MainQuestions.length > 0) {\n <div class=\"form-questions\">\n @for (question of MainQuestions; track TrackByQuestionId($index, question)) {\n <mj-dynamic-form-field\n [Question]=\"question\"\n [Control]=\"GetControl(question.id)\"\n [formControlName]=\"question.id\"\n ></mj-dynamic-form-field>\n }\n </div>\n }\n <!-- Footer Actions -->\n <div class=\"form-actions\">\n <!-- Footer Choice Buttons (replaces Submit when present) -->\n @if (FooterChoiceQuestion) {\n @for (option of GetOptions(FooterChoiceQuestion); track TrackByValue($index, option)) {\n <button\n mjButton\n type=\"button\"\n [variant]=\"IsFooterChoiceSelected(option.value) ? 'primary' : 'secondary'\"\n [disabled]=\"Disabled\"\n (click)=\"OnFooterChoiceClick(option.value)\"\n class=\"footer-choice-button\"\n [class.selected]=\"IsFooterChoiceSelected(option.value)\"\n >\n <span>\n @if (IsFooterChoiceSelected(option.value)) {\n <i class=\"fa-solid fa-check\" aria-hidden=\"true\"></i>\n } @else if (HasIcon(option)) {\n <i class=\"fa {{ option.icon }}\" aria-hidden=\"true\"></i>\n }\n {{ option.label }}\n </span>\n </button>\n }\n }\n <!-- Standard Submit Button (when no footer choice) -->\n @if (ShowSubmitButton) {\n <button\n mjButton\n type=\"submit\"\n variant=\"primary\"\n [disabled]=\"Disabled || IsSubmitting || FormGroup.invalid\"\n class=\"submit-button\"\n >\n @if (!IsSubmitting) {\n <span>\n <i class=\"fa fa-check\" aria-hidden=\"true\"></i>\n {{ SubmitLabel }}\n </span>\n }\n @if (IsSubmitting) {\n <span>\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Submitting...\n </span>\n }\n </button>\n }\n </div>\n </form>\n }\n </div>\n}\n", styles: [".dynamic-form {\n margin-top: 16px;\n display: block;\n width: fit-content;\n max-width: 600px;\n}\n\n/* Simple Choice Mode */\n.simple-choice-buttons {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 12px;\n}\n\n.choice-button {\n padding: 8px 16px;\n font-size: 14px;\n}\n\n.choice-button i,\n.choice-button i.fa-solid {\n margin-right: 6px;\n}\n\n.choice-button.selected {\n box-shadow: 0 0 0 2px var(--mj-brand-primary);\n}\n\n/* Full Form Mode */\n.response-form {\n background: color-mix(in srgb, var(--mj-brand-primary) 3%, transparent);\n border: 2px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n border-radius: 12px;\n padding: 0;\n margin-top: 12px;\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n overflow: hidden;\n}\n\n.form-title {\n margin: 0;\n padding: 12px 16px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-inverse);\n background: var(--mj-brand-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.form-title::before {\n content: \"\\f044\";\n font-family: \"Font Awesome 6 Free\";\n font-weight: 900;\n font-size: 13px;\n opacity: 0.95;\n}\n\n.form-description {\n margin: 0;\n padding: 12px 16px;\n font-size: 13px;\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n border-bottom: 1px solid color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n font-style: italic;\n}\n\n.form-questions {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n}\n\n.form-actions {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n justify-content: flex-start;\n padding: 12px 16px;\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n border-top: 1px solid color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.submit-button {\n min-width: 120px;\n}\n\n/* Footer choice buttons - horizontal on desktop with text wrapping */\n.footer-choice-button {\n min-width: 120px;\n max-width: 100%;\n white-space: normal;\n text-align: left;\n line-height: 1.3;\n padding: 10px 16px;\n}\n\n.footer-choice-button i.fa,\n.footer-choice-button i.fa-solid {\n margin-right: 6px;\n flex-shrink: 0;\n}\n\n.footer-choice-button.selected {\n box-shadow: 0 0 0 2px var(--mj-brand-primary);\n}\n\n.submit-button i.fa {\n margin-right: 6px;\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n .dynamic-form {\n margin-top: 12px;\n }\n\n .response-form {\n border-radius: 10px;\n }\n\n .form-questions {\n padding: 12px;\n }\n\n .form-actions {\n padding: 10px 12px;\n }\n\n .simple-choice-buttons {\n gap: 8px;\n }\n\n .choice-button {\n padding: 10px 14px;\n font-size: 13px;\n }\n}\n\n@media (max-width: 480px) {\n .dynamic-form {\n margin-top: 10px;\n width: 100%;\n max-width: 100%;\n }\n\n .response-form {\n border-radius: 8px;\n border-width: 1.5px;\n }\n\n .form-title {\n font-size: 13px;\n padding: 10px 12px;\n }\n\n .form-description {\n font-size: 12px;\n padding: 10px 12px;\n }\n\n .form-questions {\n padding: 10px;\n }\n\n .form-actions {\n padding: 8px 10px;\n flex-direction: column;\n }\n\n .choice-button {\n width: 100%;\n min-height: 44px;\n padding: 12px 16px;\n font-size: 14px;\n }\n\n .footer-choice-button {\n width: 100%;\n min-height: 44px;\n font-size: 14px;\n }\n\n .submit-button {\n width: 100%;\n min-height: 44px;\n font-size: 13px;\n }\n}\n"], dependencies: [{ kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2.MJButtonDirective, selector: "button[mjButton], a[mjButton]", inputs: ["variant", "size", "toggleable", "selected"], outputs: ["selectedChange"] }, { kind: "component", type: i3.DynamicFormFieldComponent, selector: "mj-dynamic-form-field", inputs: ["Question", "Control"] }] });
|
|
244
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: DynamicFormComponent, isStandalone: false, selector: "mj-dynamic-form", inputs: { FormDefinition: "FormDefinition", Disabled: "Disabled", Visible: "Visible" }, outputs: { FormSubmitted: "FormSubmitted" }, ngImport: i0, template: "@if (IsVisible) {\n <div class=\"dynamic-form\">\n <!-- Simple Choice Mode (single question, no title, buttongroup/radio) -->\n @if (IsSimpleChoice) {\n <div class=\"simple-choice-buttons\">\n @for (option of GetOptions(FormDefinition.questions[0]); track TrackByValue($index, option)) {\n <button\n mjButton\n [variant]=\"IsSimpleChoiceSelected(option.value) ? 'primary' : 'secondary'\"\n [disabled]=\"Disabled\"\n (click)=\"OnSimpleChoiceClick(option.value)\"\n class=\"choice-button\"\n [class.selected]=\"IsSimpleChoiceSelected(option.value)\"\n >\n <span>\n @if (IsSimpleChoiceSelected(option.value)) {\n <i class=\"fa-solid fa-check\" aria-hidden=\"true\"></i>\n } @else if (HasIcon(option)) {\n <i class=\"fa {{ option.icon }}\" aria-hidden=\"true\"></i>\n }\n {{ option.label }}\n </span>\n </button>\n }\n </div>\n }\n <!-- Full Form Mode (complex forms) -->\n @if (!IsSimpleChoice) {\n <form [formGroup]=\"FormGroup\" (ngSubmit)=\"OnSubmit()\" class=\"response-form\">\n <!-- Form Title -->\n @if (FormDefinition.title) {\n <h3 class=\"form-title\">{{ FormDefinition.title }}</h3>\n }\n <!-- Form Description -->\n @if (FormDefinition.description) {\n <p class=\"form-description\">{{ FormDefinition.description }}</p>\n }\n <!-- Questions (excludes footer choice question) -->\n @if (MainQuestions.length > 0) {\n <div class=\"form-questions\">\n @for (question of MainQuestions; track TrackByQuestionId($index, question)) {\n <mj-dynamic-form-field\n [Question]=\"question\"\n [Control]=\"GetControl(question.id)\"\n [formControlName]=\"question.id\"\n ></mj-dynamic-form-field>\n }\n </div>\n }\n <!-- Footer Actions -->\n <div class=\"form-actions\">\n <!-- Footer Choice Buttons (replaces Submit when present) -->\n @if (FooterChoiceQuestion) {\n @for (option of GetOptions(FooterChoiceQuestion); track TrackByValue($index, option)) {\n <button\n mjButton\n type=\"button\"\n [variant]=\"IsFooterChoiceSelected(option.value) ? 'primary' : 'secondary'\"\n [disabled]=\"Disabled\"\n (click)=\"OnFooterChoiceClick(option.value)\"\n class=\"footer-choice-button\"\n [class.selected]=\"IsFooterChoiceSelected(option.value)\"\n >\n <span>\n @if (IsFooterChoiceSelected(option.value)) {\n <i class=\"fa-solid fa-check\" aria-hidden=\"true\"></i>\n } @else if (HasIcon(option)) {\n <i class=\"fa {{ option.icon }}\" aria-hidden=\"true\"></i>\n }\n {{ option.label }}\n </span>\n </button>\n }\n }\n <!-- Standard Submit Button (when no footer choice) -->\n @if (ShowSubmitButton) {\n <button\n mjButton\n type=\"submit\"\n variant=\"primary\"\n [disabled]=\"Disabled || IsSubmitting || FormGroup.invalid\"\n class=\"submit-button\"\n >\n @if (!IsSubmitting) {\n <span>\n <i class=\"fa fa-check\" aria-hidden=\"true\"></i>\n {{ SubmitLabel }}\n </span>\n }\n @if (IsSubmitting) {\n <span>\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Submitting...\n </span>\n }\n </button>\n }\n </div>\n </form>\n }\n </div>\n}\n", styles: [".dynamic-form {\n margin-top: 16px;\n display: block;\n width: fit-content;\n max-width: 600px;\n}\n\n/* Simple Choice Mode */\n.simple-choice-buttons {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 12px;\n}\n\n.choice-button {\n padding: 8px 16px;\n font-size: 14px;\n}\n\n.choice-button i,\n.choice-button i.fa-solid {\n margin-right: 6px;\n}\n\n.choice-button.selected {\n box-shadow: 0 0 0 2px var(--mj-brand-primary);\n}\n\n/* Full Form Mode */\n.response-form {\n background: color-mix(in srgb, var(--mj-brand-primary) 3%, transparent);\n border: 2px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n border-radius: 12px;\n padding: 0;\n margin-top: 12px;\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n overflow: hidden;\n}\n\n.form-title {\n margin: 0;\n padding: 12px 16px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-inverse);\n background: var(--mj-brand-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.form-title::before {\n content: \"\\f044\";\n font-family: \"Font Awesome 6 Free\";\n font-weight: 900;\n font-size: 13px;\n opacity: 0.95;\n}\n\n.form-description {\n margin: 0;\n padding: 12px 16px;\n font-size: 13px;\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n border-bottom: 1px solid color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n font-style: italic;\n}\n\n.form-questions {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n}\n\n.form-actions {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n justify-content: flex-start;\n padding: 12px 16px;\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n border-top: 1px solid color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.submit-button {\n min-width: 120px;\n}\n\n/* Footer choice buttons - horizontal on desktop with text wrapping */\n.footer-choice-button {\n min-width: 120px;\n max-width: 100%;\n white-space: normal;\n text-align: left;\n line-height: 1.3;\n padding: 10px 16px;\n}\n\n.footer-choice-button i.fa,\n.footer-choice-button i.fa-solid {\n margin-right: 6px;\n flex-shrink: 0;\n}\n\n.footer-choice-button.selected {\n box-shadow: 0 0 0 2px var(--mj-brand-primary);\n}\n\n.submit-button i.fa {\n margin-right: 6px;\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n .dynamic-form {\n margin-top: 12px;\n }\n\n .response-form {\n border-radius: 10px;\n }\n\n .form-questions {\n padding: 12px;\n }\n\n .form-actions {\n padding: 10px 12px;\n }\n\n .simple-choice-buttons {\n gap: 8px;\n }\n\n .choice-button {\n padding: 10px 14px;\n font-size: 13px;\n }\n}\n\n@media (max-width: 480px) {\n .dynamic-form {\n margin-top: 10px;\n width: 100%;\n max-width: 100%;\n }\n\n .response-form {\n border-radius: 8px;\n border-width: 1.5px;\n }\n\n .form-title {\n font-size: 13px;\n padding: 10px 12px;\n }\n\n .form-description {\n font-size: 12px;\n padding: 10px 12px;\n }\n\n .form-questions {\n padding: 10px;\n }\n\n .form-actions {\n padding: 8px 10px;\n flex-direction: column;\n }\n\n .choice-button {\n width: 100%;\n min-height: 44px;\n padding: 12px 16px;\n font-size: 14px;\n }\n\n .footer-choice-button {\n width: 100%;\n min-height: 44px;\n font-size: 14px;\n }\n\n .submit-button {\n width: 100%;\n min-height: 44px;\n font-size: 13px;\n }\n}\n"], dependencies: [{ kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2.MJButtonDirective, selector: "button[mjButton], a[mjButton]", inputs: ["variant", "size", "toggleable", "selected", "ariaLabel"], outputs: ["selectedChange"] }, { kind: "component", type: i3.DynamicFormFieldComponent, selector: "mj-dynamic-form-field", inputs: ["Question", "Control"] }] });
|
|
245
245
|
}
|
|
246
246
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DynamicFormComponent, decorators: [{
|
|
247
247
|
type: Component,
|
|
@@ -219,7 +219,7 @@ export class DynamicFormFieldComponent {
|
|
|
219
219
|
useExisting: forwardRef(() => DynamicFormFieldComponent),
|
|
220
220
|
multi: true
|
|
221
221
|
}
|
|
222
|
-
], ngImport: i0, template: "<div class=\"form-question\" [class.required]=\"Question.required\">\n <!-- Label -->\n @if (Question.label) {\n <label class=\"question-label\">\n {{ Question.label }}\n @if (Question.required) {\n <span class=\"required-indicator\">*</span>\n }\n </label>\n }\n\n <!-- Help Text -->\n @if (Question.helpText) {\n <div class=\"help-text\">\n {{ Question.helpText }}\n </div>\n }\n\n <!-- Input Container with width class -->\n <div class=\"input-container\" [ngClass]=\"WidthClass\">\n\n <!-- Text Input -->\n @if (QuestionType === 'text') {\n <input\n type=\"text\"\n class=\"mj-input question-input\"\n [value]=\"$any(Value) || ''\"\n [placeholder]=\"Placeholder\"\n [disabled]=\"Disabled\"\n (input)=\"OnValueChange($any($event.target).value)\"\n />\n }\n\n <!-- Email Input -->\n @if (QuestionType === 'email') {\n <input\n type=\"email\"\n class=\"mj-input question-input\"\n [value]=\"$any(Value) || ''\"\n [placeholder]=\"Placeholder\"\n [disabled]=\"Disabled\"\n (input)=\"OnValueChange($any($event.target).value)\"\n />\n }\n\n <!-- Textarea -->\n @if (QuestionType === 'textarea') {\n <textarea\n class=\"mj-textarea question-textarea\"\n [value]=\"$any(Value) || ''\"\n [placeholder]=\"Placeholder\"\n [disabled]=\"Disabled\"\n (input)=\"OnValueChange($any($event.target).value)\"\n rows=\"5\"\n ></textarea>\n }\n\n <!-- Number Input -->\n @if (QuestionType === 'number') {\n <mj-numeric-input\n [ngModel]=\"$any(Value)\"\n [ngModelOptions]=\"{standalone: true}\"\n [Min]=\"Min || 0\"\n [Max]=\"Max || 999999999\"\n [Step]=\"Step || 1\"\n [Disabled]=\"Disabled\"\n (ngModelChange)=\"OnValueChange($any($event))\"\n class=\"question-input\"\n ></mj-numeric-input>\n }\n\n <!-- Currency Input -->\n @if (QuestionType === 'currency') {\n <mj-numeric-input\n [ngModel]=\"$any(Value)\"\n [ngModelOptions]=\"{standalone: true}\"\n [Min]=\"Min || 0\"\n [Max]=\"Max || 999999999\"\n [Step]=\"Step || 0.01\"\n [Decimals]=\"2\"\n [Disabled]=\"Disabled\"\n (ngModelChange)=\"OnValueChange($any($event))\"\n class=\"question-input\"\n ></mj-numeric-input>\n }\n\n <!-- Date Picker -->\n @if (QuestionType === 'date') {\n <mj-datepicker\n [ngModel]=\"$any(Value)\"\n [ngModelOptions]=\"{standalone: true}\"\n [Disabled]=\"Disabled\"\n (ValueChange)=\"OnValueChange($any($event))\"\n class=\"question-input\"\n ></mj-datepicker>\n }\n\n <!-- DateTime Picker -->\n @if (QuestionType === 'datetime') {\n <input\n type=\"datetime-local\"\n class=\"mj-input question-input\"\n [value]=\"$any(Value)\"\n [disabled]=\"Disabled\"\n (change)=\"OnValueChange($any($event.target).value)\"\n />\n }\n\n <!-- Button Group -->\n @if (QuestionType === 'buttongroup') {\n <div class=\"mj-buttongroup question-buttongroup\">\n @for (option of Options; track TrackByValue($index, option)) {\n <button\n mjButton\n [toggleable]=\"true\"\n [selected]=\"Value === option.value\"\n [disabled]=\"Disabled\"\n (click)=\"OnValueChange(option.value)\"\n class=\"buttongroup-option\"\n >\n @if (option.icon) {\n <i class=\"fa {{ option.icon }}\" aria-hidden=\"true\"></i>\n }\n {{ option.label }}\n </button>\n }\n </div>\n }\n\n <!-- Radio Buttons -->\n @if (QuestionType === 'radio') {\n <div class=\"question-radio-group\">\n @for (option of Options; track TrackByValue($index, option)) {\n <div class=\"radio-option\">\n <input\n type=\"radio\"\n class=\"mj-radio\"\n [name]=\"Question.id\"\n [value]=\"option.value\"\n [checked]=\"Value === option.value\"\n [disabled]=\"Disabled\"\n (change)=\"OnValueChange(option.value)\"\n [id]=\"Question.id + '_' + option.value\"\n />\n <label [for]=\"Question.id + '_' + option.value\" class=\"radio-label\">\n @if (option.icon) {\n <i class=\"fa {{ option.icon }}\" aria-hidden=\"true\"></i>\n }\n {{ option.label }}\n </label>\n </div>\n }\n </div>\n }\n\n <!-- Dropdown -->\n @if (QuestionType === 'dropdown') {\n <select\n [formControl]=\"Control\"\n [disabled]=\"Disabled\"\n class=\"question-dropdown\"\n >\n <option value=\"\">Select an option...</option>\n @for (option of Options; track TrackByValue($index, option)) {\n <option [value]=\"option.value\">\n {{ option.label }}\n </option>\n }\n </select>\n }\n\n <!-- Slider -->\n @if (QuestionType === 'slider') {\n <div class=\"question-slider-container\">\n <input\n type=\"range\"\n class=\"mj-slider question-slider\"\n [min]=\"GetSliderConfig().min\"\n [max]=\"GetSliderConfig().max\"\n [step]=\"GetSliderConfig().step || 1\"\n [value]=\"$any(Value) || GetSliderConfig().min\"\n [disabled]=\"Disabled\"\n (input)=\"OnValueChange(+$any($event.target).value)\"\n />\n <div class=\"slider-value\">\n {{ Value || GetSliderConfig().min }}{{ GetSliderConfig().suffix || '' }}\n </div>\n </div>\n }\n\n <!-- Date Range -->\n @if (QuestionType === 'daterange') {\n <div class=\"question-daterange\">\n <mj-datepicker\n [ngModel]=\"$any(Value)?.start\"\n [ngModelOptions]=\"{standalone: true}\"\n [Disabled]=\"Disabled\"\n (ValueChange)=\"OnDateRangeStartChange($any($event))\"\n Placeholder=\"Start Date\"\n class=\"daterange-start\"\n ></mj-datepicker>\n <span class=\"daterange-separator\">to</span>\n <mj-datepicker\n [ngModel]=\"$any(Value)?.end\"\n [ngModelOptions]=\"{standalone: true}\"\n [Disabled]=\"Disabled\"\n (ValueChange)=\"OnDateRangeEndChange($any($event))\"\n Placeholder=\"End Date\"\n class=\"daterange-end\"\n ></mj-datepicker>\n </div>\n }\n\n <!-- Time Picker -->\n @if (QuestionType === 'time') {\n <input\n type=\"time\"\n class=\"mj-input question-input\"\n [value]=\"$any(Value)\"\n [disabled]=\"Disabled\"\n (change)=\"OnValueChange($any($event.target).value)\"\n />\n }\n\n <!-- Checkboxes -->\n @if (QuestionType === 'checkbox') {\n <div class=\"question-checkbox-group\">\n @for (option of Options; track TrackByValue($index, option)) {\n <div class=\"checkbox-option\">\n <input\n type=\"checkbox\"\n class=\"mj-checkbox\"\n [checked]=\"IsChecked(option)\"\n [disabled]=\"Disabled\"\n (change)=\"ToggleCheckbox(option)\"\n [id]=\"Question.id + '_' + option.value\"\n />\n <label [for]=\"Question.id + '_' + option.value\" class=\"checkbox-label\">\n @if (option.icon) {\n <i class=\"fa {{ option.icon }}\" aria-hidden=\"true\"></i>\n }\n {{ option.label }}\n </label>\n </div>\n }\n </div>\n }\n </div><!-- end input-container -->\n\n <!-- Validation Error -->\n @if (Control.invalid && Control.touched) {\n <div class=\"validation-error\">\n @if (Control.errors?.['required']) {\n <span>This field is required</span>\n }\n @if (Control.errors?.['email']) {\n <span>Please enter a valid email address</span>\n }\n @if (Control.errors?.['min']) {\n <span>Value must be at least {{ Min }}</span>\n }\n @if (Control.errors?.['max']) {\n <span>Value must be at most {{ Max }}</span>\n }\n </div>\n }\n</div>\n", styles: [".form-question {\n margin-bottom: 16px;\n}\n\n.question-label {\n display: block;\n font-weight: 500;\n margin-bottom: 6px;\n color: var(--mj-text-primary);\n font-size: 14px;\n}\n\n.required-indicator {\n color: var(--mj-status-error);\n margin-left: 2px;\n}\n\n.help-text {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-bottom: 8px;\n font-style: italic;\n}\n\n/* Default widths - controlled by input-container width classes */\n.question-input,\n.question-textarea,\n.question-dropdown {\n width: 100%;\n max-width: 100%;\n}\n\n.question-dropdown {\n padding: 8px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n font-size: 14px;\n font-family: inherit;\n background-color: var(--mj-bg-surface);\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23666' d='M6 9L1 4h10z'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 8px center;\n background-size: 12px;\n padding-right: 32px;\n cursor: pointer;\n transition: border-color 0.2s ease, box-shadow 0.2s ease;\n appearance: none;\n -webkit-appearance: none;\n -moz-appearance: none;\n color: var(--mj-text-primary);\n}\n\n.question-dropdown:hover {\n border-color: var(--mj-border-strong);\n}\n\n.question-dropdown:focus {\n outline: none;\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}\n\n.question-dropdown:disabled {\n background-color: var(--mj-bg-surface-sunken);\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n.question-textarea {\n resize: vertical;\n min-height: 100px;\n}\n\n.question-buttongroup {\n display: flex;\n flex-wrap: nowrap;\n gap: 8px;\n overflow-x: auto;\n overflow-y: hidden;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: thin;\n scrollbar-color: color-mix(in srgb, var(--mj-brand-primary) 30%, transparent) transparent;\n}\n\n.question-buttongroup::-webkit-scrollbar {\n height: 6px;\n}\n\n.question-buttongroup::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.question-buttongroup::-webkit-scrollbar-thumb {\n background: color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n border-radius: 3px;\n}\n\n.question-buttongroup::-webkit-scrollbar-thumb:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 50%, transparent);\n}\n\n.buttongroup-option {\n flex: 0 0 auto;\n white-space: nowrap;\n}\n\n.buttongroup-option i {\n margin-right: 6px;\n}\n\n.question-radio-group,\n.question-checkbox-group {\n display: flex;\n flex-wrap: wrap;\n gap: 12px 16px;\n}\n\n.radio-option,\n.checkbox-option {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 120px;\n flex: 0 0 auto;\n}\n\n.radio-label,\n.checkbox-label {\n cursor: pointer;\n user-select: none;\n margin: 0;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.radio-label i,\n.checkbox-label i {\n color: var(--mj-text-secondary);\n}\n\n.validation-error {\n color: var(--mj-status-error);\n font-size: 12px;\n margin-top: 4px;\n}\n\n/* Required field styling */\n.form-question.required .question-label {\n font-weight: 600;\n}\n\n/* Slider styling */\n.question-slider-container {\n width: 100%;\n}\n\n.question-slider {\n width: 100%;\n margin-bottom: 8px;\n}\n\n.slider-value {\n text-align: center;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-brand-primary);\n padding: 4px 0;\n}\n\n/* Date range styling */\n.question-daterange {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.daterange-start,\n.daterange-end {\n flex: 1;\n min-width: 150px;\n}\n\n.daterange-separator {\n font-weight: 500;\n color: var(--mj-text-secondary);\n white-space: nowrap;\n}\n\n/* Mobile adjustments for date range */\n@media (max-width: 480px) {\n .question-daterange {\n flex-direction: column;\n align-items: stretch;\n }\n\n .daterange-separator {\n text-align: center;\n padding: 4px 0;\n }\n}\n\n/* ===== Semantic Width Classes ===== */\n/* Controls field width based on expected content length */\n\n.input-container {\n display: block;\n}\n\n/* Narrow fields - for numbers, dates, times, short codes */\n.input-container.width-narrow {\n max-width: 200px;\n}\n\n.input-container.width-narrow .question-input,\n.input-container.width-narrow .question-dropdown {\n width: 100%;\n}\n\n/* Medium fields - for names, cities, phone numbers (DEFAULT) */\n.input-container.width-medium {\n max-width: 450px;\n}\n\n.input-container.width-medium .question-input,\n.input-container.width-medium .question-dropdown {\n width: 100%;\n}\n\n/* Wide fields - for emails, URLs, long text */\n.input-container.width-wide {\n max-width: 100%;\n}\n\n.input-container.width-wide .question-input,\n.input-container.width-wide .question-dropdown {\n width: 100%;\n}\n\n/* Full width - for textarea, search fields */\n.input-container.width-full {\n max-width: 100%;\n}\n\n.input-container.width-full .question-input,\n.input-container.width-full .question-textarea,\n.input-container.width-full .question-dropdown {\n width: 100%;\n}\n\n/* Auto-width - for dropdowns, radio, checkbox (sizes to content) */\n.input-container.width-auto {\n max-width: 350px;\n min-width: 150px;\n width: auto;\n}\n\n.input-container.width-auto .question-dropdown {\n width: 100%;\n}\n\n/* Responsive adjustments for smaller screens */\n@media (max-width: 600px) {\n .input-container.width-narrow,\n .input-container.width-medium,\n .input-container.width-wide,\n .input-container.width-auto {\n max-width: 100%;\n }\n}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.MJButtonDirective, selector: "button[mjButton], a[mjButton]", inputs: ["variant", "size", "toggleable", "selected"], outputs: ["selectedChange"] }, { kind: "component", type: i3.MJNumericInputComponent, selector: "mj-numeric-input", inputs: ["Min", "Max", "Step", "Format", "Decimals", "Disabled", "Placeholder"] }, { kind: "component", type: i3.MJDatepickerComponent, selector: "mj-datepicker", inputs: ["Min", "Max", "Format", "Placeholder", "Disabled"], outputs: ["ValueChange"] }] });
|
|
222
|
+
], ngImport: i0, template: "<div class=\"form-question\" [class.required]=\"Question.required\">\n <!-- Label -->\n @if (Question.label) {\n <label class=\"question-label\">\n {{ Question.label }}\n @if (Question.required) {\n <span class=\"required-indicator\">*</span>\n }\n </label>\n }\n\n <!-- Help Text -->\n @if (Question.helpText) {\n <div class=\"help-text\">\n {{ Question.helpText }}\n </div>\n }\n\n <!-- Input Container with width class -->\n <div class=\"input-container\" [ngClass]=\"WidthClass\">\n\n <!-- Text Input -->\n @if (QuestionType === 'text') {\n <input\n type=\"text\"\n class=\"mj-input question-input\"\n [value]=\"$any(Value) || ''\"\n [placeholder]=\"Placeholder\"\n [disabled]=\"Disabled\"\n (input)=\"OnValueChange($any($event.target).value)\"\n />\n }\n\n <!-- Email Input -->\n @if (QuestionType === 'email') {\n <input\n type=\"email\"\n class=\"mj-input question-input\"\n [value]=\"$any(Value) || ''\"\n [placeholder]=\"Placeholder\"\n [disabled]=\"Disabled\"\n (input)=\"OnValueChange($any($event.target).value)\"\n />\n }\n\n <!-- Textarea -->\n @if (QuestionType === 'textarea') {\n <textarea\n class=\"mj-textarea question-textarea\"\n [value]=\"$any(Value) || ''\"\n [placeholder]=\"Placeholder\"\n [disabled]=\"Disabled\"\n (input)=\"OnValueChange($any($event.target).value)\"\n rows=\"5\"\n ></textarea>\n }\n\n <!-- Number Input -->\n @if (QuestionType === 'number') {\n <mj-numeric-input\n [ngModel]=\"$any(Value)\"\n [ngModelOptions]=\"{standalone: true}\"\n [Min]=\"Min || 0\"\n [Max]=\"Max || 999999999\"\n [Step]=\"Step || 1\"\n [Disabled]=\"Disabled\"\n (ngModelChange)=\"OnValueChange($any($event))\"\n class=\"question-input\"\n ></mj-numeric-input>\n }\n\n <!-- Currency Input -->\n @if (QuestionType === 'currency') {\n <mj-numeric-input\n [ngModel]=\"$any(Value)\"\n [ngModelOptions]=\"{standalone: true}\"\n [Min]=\"Min || 0\"\n [Max]=\"Max || 999999999\"\n [Step]=\"Step || 0.01\"\n [Decimals]=\"2\"\n [Disabled]=\"Disabled\"\n (ngModelChange)=\"OnValueChange($any($event))\"\n class=\"question-input\"\n ></mj-numeric-input>\n }\n\n <!-- Date Picker -->\n @if (QuestionType === 'date') {\n <mj-datepicker\n [ngModel]=\"$any(Value)\"\n [ngModelOptions]=\"{standalone: true}\"\n [Disabled]=\"Disabled\"\n (ValueChange)=\"OnValueChange($any($event))\"\n class=\"question-input\"\n ></mj-datepicker>\n }\n\n <!-- DateTime Picker -->\n @if (QuestionType === 'datetime') {\n <input\n type=\"datetime-local\"\n class=\"mj-input question-input\"\n [value]=\"$any(Value)\"\n [disabled]=\"Disabled\"\n (change)=\"OnValueChange($any($event.target).value)\"\n />\n }\n\n <!-- Button Group -->\n @if (QuestionType === 'buttongroup') {\n <div class=\"mj-buttongroup question-buttongroup\">\n @for (option of Options; track TrackByValue($index, option)) {\n <button\n mjButton\n [toggleable]=\"true\"\n [selected]=\"Value === option.value\"\n [disabled]=\"Disabled\"\n (click)=\"OnValueChange(option.value)\"\n class=\"buttongroup-option\"\n >\n @if (option.icon) {\n <i class=\"fa {{ option.icon }}\" aria-hidden=\"true\"></i>\n }\n {{ option.label }}\n </button>\n }\n </div>\n }\n\n <!-- Radio Buttons -->\n @if (QuestionType === 'radio') {\n <div class=\"question-radio-group\">\n @for (option of Options; track TrackByValue($index, option)) {\n <div class=\"radio-option\">\n <input\n type=\"radio\"\n class=\"mj-radio\"\n [name]=\"Question.id\"\n [value]=\"option.value\"\n [checked]=\"Value === option.value\"\n [disabled]=\"Disabled\"\n (change)=\"OnValueChange(option.value)\"\n [id]=\"Question.id + '_' + option.value\"\n />\n <label [for]=\"Question.id + '_' + option.value\" class=\"radio-label\">\n @if (option.icon) {\n <i class=\"fa {{ option.icon }}\" aria-hidden=\"true\"></i>\n }\n {{ option.label }}\n </label>\n </div>\n }\n </div>\n }\n\n <!-- Dropdown -->\n @if (QuestionType === 'dropdown') {\n <select\n [formControl]=\"Control\"\n [disabled]=\"Disabled\"\n class=\"question-dropdown\"\n >\n <option value=\"\">Select an option...</option>\n @for (option of Options; track TrackByValue($index, option)) {\n <option [value]=\"option.value\">\n {{ option.label }}\n </option>\n }\n </select>\n }\n\n <!-- Slider -->\n @if (QuestionType === 'slider') {\n <div class=\"question-slider-container\">\n <input\n type=\"range\"\n class=\"mj-slider question-slider\"\n [min]=\"GetSliderConfig().min\"\n [max]=\"GetSliderConfig().max\"\n [step]=\"GetSliderConfig().step || 1\"\n [value]=\"$any(Value) || GetSliderConfig().min\"\n [disabled]=\"Disabled\"\n (input)=\"OnValueChange(+$any($event.target).value)\"\n />\n <div class=\"slider-value\">\n {{ Value || GetSliderConfig().min }}{{ GetSliderConfig().suffix || '' }}\n </div>\n </div>\n }\n\n <!-- Date Range -->\n @if (QuestionType === 'daterange') {\n <div class=\"question-daterange\">\n <mj-datepicker\n [ngModel]=\"$any(Value)?.start\"\n [ngModelOptions]=\"{standalone: true}\"\n [Disabled]=\"Disabled\"\n (ValueChange)=\"OnDateRangeStartChange($any($event))\"\n Placeholder=\"Start Date\"\n class=\"daterange-start\"\n ></mj-datepicker>\n <span class=\"daterange-separator\">to</span>\n <mj-datepicker\n [ngModel]=\"$any(Value)?.end\"\n [ngModelOptions]=\"{standalone: true}\"\n [Disabled]=\"Disabled\"\n (ValueChange)=\"OnDateRangeEndChange($any($event))\"\n Placeholder=\"End Date\"\n class=\"daterange-end\"\n ></mj-datepicker>\n </div>\n }\n\n <!-- Time Picker -->\n @if (QuestionType === 'time') {\n <input\n type=\"time\"\n class=\"mj-input question-input\"\n [value]=\"$any(Value)\"\n [disabled]=\"Disabled\"\n (change)=\"OnValueChange($any($event.target).value)\"\n />\n }\n\n <!-- Checkboxes -->\n @if (QuestionType === 'checkbox') {\n <div class=\"question-checkbox-group\">\n @for (option of Options; track TrackByValue($index, option)) {\n <div class=\"checkbox-option\">\n <input\n type=\"checkbox\"\n class=\"mj-checkbox\"\n [checked]=\"IsChecked(option)\"\n [disabled]=\"Disabled\"\n (change)=\"ToggleCheckbox(option)\"\n [id]=\"Question.id + '_' + option.value\"\n />\n <label [for]=\"Question.id + '_' + option.value\" class=\"checkbox-label\">\n @if (option.icon) {\n <i class=\"fa {{ option.icon }}\" aria-hidden=\"true\"></i>\n }\n {{ option.label }}\n </label>\n </div>\n }\n </div>\n }\n </div><!-- end input-container -->\n\n <!-- Validation Error -->\n @if (Control.invalid && Control.touched) {\n <div class=\"validation-error\">\n @if (Control.errors?.['required']) {\n <span>This field is required</span>\n }\n @if (Control.errors?.['email']) {\n <span>Please enter a valid email address</span>\n }\n @if (Control.errors?.['min']) {\n <span>Value must be at least {{ Min }}</span>\n }\n @if (Control.errors?.['max']) {\n <span>Value must be at most {{ Max }}</span>\n }\n </div>\n }\n</div>\n", styles: [".form-question {\n margin-bottom: 16px;\n}\n\n.question-label {\n display: block;\n font-weight: 500;\n margin-bottom: 6px;\n color: var(--mj-text-primary);\n font-size: 14px;\n}\n\n.required-indicator {\n color: var(--mj-status-error);\n margin-left: 2px;\n}\n\n.help-text {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-bottom: 8px;\n font-style: italic;\n}\n\n/* Default widths - controlled by input-container width classes */\n.question-input,\n.question-textarea,\n.question-dropdown {\n width: 100%;\n max-width: 100%;\n}\n\n.question-dropdown {\n padding: 8px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n font-size: 14px;\n font-family: inherit;\n background-color: var(--mj-bg-surface);\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23666' d='M6 9L1 4h10z'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 8px center;\n background-size: 12px;\n padding-right: 32px;\n cursor: pointer;\n transition: border-color 0.2s ease, box-shadow 0.2s ease;\n appearance: none;\n -webkit-appearance: none;\n -moz-appearance: none;\n color: var(--mj-text-primary);\n}\n\n.question-dropdown:hover {\n border-color: var(--mj-border-strong);\n}\n\n.question-dropdown:focus {\n outline: none;\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}\n\n.question-dropdown:disabled {\n background-color: var(--mj-bg-surface-sunken);\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n.question-textarea {\n resize: vertical;\n min-height: 100px;\n}\n\n.question-buttongroup {\n display: flex;\n flex-wrap: nowrap;\n gap: 8px;\n overflow-x: auto;\n overflow-y: hidden;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: thin;\n scrollbar-color: color-mix(in srgb, var(--mj-brand-primary) 30%, transparent) transparent;\n}\n\n.question-buttongroup::-webkit-scrollbar {\n height: 6px;\n}\n\n.question-buttongroup::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.question-buttongroup::-webkit-scrollbar-thumb {\n background: color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n border-radius: 3px;\n}\n\n.question-buttongroup::-webkit-scrollbar-thumb:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 50%, transparent);\n}\n\n.buttongroup-option {\n flex: 0 0 auto;\n white-space: nowrap;\n}\n\n.buttongroup-option i {\n margin-right: 6px;\n}\n\n.question-radio-group,\n.question-checkbox-group {\n display: flex;\n flex-wrap: wrap;\n gap: 12px 16px;\n}\n\n.radio-option,\n.checkbox-option {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 120px;\n flex: 0 0 auto;\n}\n\n.radio-label,\n.checkbox-label {\n cursor: pointer;\n user-select: none;\n margin: 0;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.radio-label i,\n.checkbox-label i {\n color: var(--mj-text-secondary);\n}\n\n.validation-error {\n color: var(--mj-status-error);\n font-size: 12px;\n margin-top: 4px;\n}\n\n/* Required field styling */\n.form-question.required .question-label {\n font-weight: 600;\n}\n\n/* Slider styling */\n.question-slider-container {\n width: 100%;\n}\n\n.question-slider {\n width: 100%;\n margin-bottom: 8px;\n}\n\n.slider-value {\n text-align: center;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-brand-primary);\n padding: 4px 0;\n}\n\n/* Date range styling */\n.question-daterange {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.daterange-start,\n.daterange-end {\n flex: 1;\n min-width: 150px;\n}\n\n.daterange-separator {\n font-weight: 500;\n color: var(--mj-text-secondary);\n white-space: nowrap;\n}\n\n/* Mobile adjustments for date range */\n@media (max-width: 480px) {\n .question-daterange {\n flex-direction: column;\n align-items: stretch;\n }\n\n .daterange-separator {\n text-align: center;\n padding: 4px 0;\n }\n}\n\n/* ===== Semantic Width Classes ===== */\n/* Controls field width based on expected content length */\n\n.input-container {\n display: block;\n}\n\n/* Narrow fields - for numbers, dates, times, short codes */\n.input-container.width-narrow {\n max-width: 200px;\n}\n\n.input-container.width-narrow .question-input,\n.input-container.width-narrow .question-dropdown {\n width: 100%;\n}\n\n/* Medium fields - for names, cities, phone numbers (DEFAULT) */\n.input-container.width-medium {\n max-width: 450px;\n}\n\n.input-container.width-medium .question-input,\n.input-container.width-medium .question-dropdown {\n width: 100%;\n}\n\n/* Wide fields - for emails, URLs, long text */\n.input-container.width-wide {\n max-width: 100%;\n}\n\n.input-container.width-wide .question-input,\n.input-container.width-wide .question-dropdown {\n width: 100%;\n}\n\n/* Full width - for textarea, search fields */\n.input-container.width-full {\n max-width: 100%;\n}\n\n.input-container.width-full .question-input,\n.input-container.width-full .question-textarea,\n.input-container.width-full .question-dropdown {\n width: 100%;\n}\n\n/* Auto-width - for dropdowns, radio, checkbox (sizes to content) */\n.input-container.width-auto {\n max-width: 350px;\n min-width: 150px;\n width: auto;\n}\n\n.input-container.width-auto .question-dropdown {\n width: 100%;\n}\n\n/* Responsive adjustments for smaller screens */\n@media (max-width: 600px) {\n .input-container.width-narrow,\n .input-container.width-medium,\n .input-container.width-wide,\n .input-container.width-auto {\n max-width: 100%;\n }\n}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.MJButtonDirective, selector: "button[mjButton], a[mjButton]", inputs: ["variant", "size", "toggleable", "selected", "ariaLabel"], outputs: ["selectedChange"] }, { kind: "component", type: i3.MJNumericInputComponent, selector: "mj-numeric-input", inputs: ["Min", "Max", "Step", "Format", "Decimals", "Disabled", "Placeholder"] }, { kind: "component", type: i3.MJDatepickerComponent, selector: "mj-datepicker", inputs: ["Min", "Max", "Format", "Placeholder", "Disabled"], outputs: ["ValueChange"] }] });
|
|
223
223
|
}
|
|
224
224
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DynamicFormFieldComponent, decorators: [{
|
|
225
225
|
type: Component,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-forms",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.42.0",
|
|
4
4
|
"description": "MemberJunction: Generic dynamic form rendering from JSON schemas. Renders structured forms with 14+ field types (text, textarea, number, currency, date, daterange, time, checkbox, radio, dropdown, buttongroup, slider, email) with built-in validation, responsive layout, and intelligent field sizing.",
|
|
5
5
|
"main": "./dist/public-api.js",
|
|
6
6
|
"typings": "./dist/public-api.d.ts",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"@angular/forms": "21.1.3"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@memberjunction/ai-core-plus": "5.
|
|
37
|
-
"@memberjunction/ng-ui-components": "5.
|
|
36
|
+
"@memberjunction/ai-core-plus": "5.42.0",
|
|
37
|
+
"@memberjunction/ng-ui-components": "5.42.0",
|
|
38
38
|
"tslib": "^2.8.1"
|
|
39
39
|
},
|
|
40
40
|
"sideEffects": false,
|