@memberjunction/ng-dashboard-viewer 5.24.0 → 5.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/config-panels/artifact-config-panel.component.js +2 -2
- package/dist/lib/config-panels/query-config-panel.component.js +2 -2
- package/dist/lib/config-panels/view-config-panel.component.d.ts +2 -1
- package/dist/lib/config-panels/view-config-panel.component.d.ts.map +1 -1
- package/dist/lib/config-panels/view-config-panel.component.js +100 -32
- package/dist/lib/config-panels/view-config-panel.component.js.map +1 -1
- package/dist/lib/config-panels/weburl-config-panel.component.js +2 -2
- package/dist/lib/parts/view-part.component.d.ts +2 -0
- package/dist/lib/parts/view-part.component.d.ts.map +1 -1
- package/dist/lib/parts/view-part.component.js +7 -4
- package/dist/lib/parts/view-part.component.js.map +1 -1
- package/package.json +10 -9
|
@@ -272,7 +272,7 @@ let WebURLConfigPanelComponent = class WebURLConfigPanelComponent extends BaseCo
|
|
|
272
272
|
i0.ɵɵtwoWayProperty("ngModel", ctx.allowFullscreen);
|
|
273
273
|
i0.ɵɵadvance(8);
|
|
274
274
|
i0.ɵɵtwoWayProperty("ngModel", ctx.refreshOnResize);
|
|
275
|
-
} }, dependencies: [i1.DefaultValueAccessor, i1.CheckboxControlValueAccessor, i1.RadioControlValueAccessor, i1.NgControlStatus, i1.NgModel], styles: ["\n\n\n\n\n\n\n\n\n\n.config-panel[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 24px;\n padding: 8px 0;\n}\n\n\n\n\n\n\n.form-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.form-group[_ngcontent-%COMP%] > label[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.form-group[_ngcontent-%COMP%] > label[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 14px;\n width: 16px;\n}\n\n.form-group[_ngcontent-%COMP%] > label[_ngcontent-%COMP%] .required[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n\n\n\n\n\n.form-input[_ngcontent-%COMP%] {\n padding: 14px 16px;\n border: 2px solid var(--mj-border-default);\n border-radius: 10px;\n font-size: 15px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n transition: all 0.2s ease;\n width: 100%;\n box-sizing: border-box;\n}\n\n.form-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 4px color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n}\n\n.form-input[_ngcontent-%COMP%]::placeholder {\n color: var(--mj-text-disabled);\n}\n\n.form-input.error[_ngcontent-%COMP%] {\n border-color: var(--mj-status-error);\n}\n\n.form-input.error[_ngcontent-%COMP%]:focus {\n box-shadow: 0 0 0 4px color-mix(in srgb, var(--mj-status-error) 12%, transparent);\n}\n\n.input-with-action[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n.input-with-action[_ngcontent-%COMP%] .form-input[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.input-action-btn[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 2px solid var(--mj-border-default);\n border-radius: 10px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n}\n\n.input-action-btn[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n\n\n\n\n\n.form-hint[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-muted);\n line-height: 1.4;\n}\n\n.form-error[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-status-error);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.form-error[_ngcontent-%COMP%]::before {\n content: '\\f071';\n font-family: 'Font Awesome 6 Free';\n font-weight: 900;\n font-size: 12px;\n}\n\n\n\n\n\n\n.radio-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.radio-option[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n border: 2px solid color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n background: var(--mj-bg-surface);\n}\n\n.radio-option[_ngcontent-%COMP%]:hover {\n border-color: color-mix(in srgb, var(--mj-brand-primary) 30%, var(--mj-bg-surface));\n background: var(--mj-bg-surface-card);\n}\n\n.radio-option.selected[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.radio-option[_ngcontent-%COMP%] input[type=\"radio\"][_ngcontent-%COMP%] {\n display: none;\n}\n\n.radio-mark[_ngcontent-%COMP%] {\n width: 20px;\n height: 20px;\n border: 2px solid var(--mj-border-strong);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: all 0.2s ease;\n}\n\n.radio-option.selected[_ngcontent-%COMP%] .radio-mark[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n}\n\n.radio-option.selected[_ngcontent-%COMP%] .radio-mark[_ngcontent-%COMP%]::after {\n content: '';\n width: 10px;\n height: 10px;\n background: var(--mj-brand-primary);\n border-radius: 50%;\n}\n\n.radio-content[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.radio-label[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.radio-badge[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 600;\n padding: 3px 8px;\n border-radius: 4px;\n text-transform: uppercase;\n}\n\n.radio-badge.recommended[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 10%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.radio-badge.secure[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.radio-badge.warning[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 10%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n\n\n\n\n\n.checkbox-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.checkbox-option[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 14px 16px;\n border: 2px solid color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n background: var(--mj-bg-surface);\n}\n\n.checkbox-option[_ngcontent-%COMP%]:hover {\n border-color: color-mix(in srgb, var(--mj-brand-primary) 30%, var(--mj-bg-surface));\n background: var(--mj-bg-surface-card);\n}\n\n.checkbox-option[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n display: none;\n}\n\n.checkbox-mark[_ngcontent-%COMP%] {\n width: 22px;\n height: 22px;\n border: 2px solid var(--mj-border-strong);\n border-radius: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: all 0.2s ease;\n margin-top: 2px;\n}\n\n.checkbox-option[_ngcontent-%COMP%] input[_ngcontent-%COMP%]:checked + .checkbox-mark[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.checkbox-option[_ngcontent-%COMP%] input[_ngcontent-%COMP%]:checked + .checkbox-mark[_ngcontent-%COMP%]::after {\n content: '\\f00c';\n font-family: 'Font Awesome 6 Free';\n font-weight: 900;\n font-size: 12px;\n color: var(--mj-text-inverse);\n}\n\n.checkbox-content[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.checkbox-label[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.checkbox-desc[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n\n\n\n\n\n.form-select[_ngcontent-%COMP%] {\n padding: 14px 40px 14px 16px;\n border: 2px solid var(--mj-border-default);\n border-radius: 10px;\n font-size: 15px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n transition: all 0.2s ease;\n width: 100%;\n box-sizing: border-box;\n cursor: pointer;\n appearance: none;\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 8L1 3h10z'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 16px center;\n}\n\n.form-select[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 4px color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n}\n\n\n\n\n\n\n.config-panel--compact[_ngcontent-%COMP%] {\n gap: 16px;\n}\n\n.config-panel--compact[_ngcontent-%COMP%] .form-group[_ngcontent-%COMP%] {\n gap: 8px;\n}\n\n.config-panel--compact[_ngcontent-%COMP%] .form-input[_ngcontent-%COMP%] {\n padding: 10px 14px;\n font-size: 14px;\n}\n\n.config-panel--compact[_ngcontent-%COMP%] .form-select[_ngcontent-%COMP%] {\n padding: 10px 36px 10px 14px;\n font-size: 14px;\n}\n\n\n\n\n\n\n.optional-tag[_ngcontent-%COMP%] {\n font-weight: 400;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n\n\n\n\n\n.form-hint--selected[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n.form-hint--selected[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n\n\n\n\n\n.collapsible-section[_ngcontent-%COMP%] {\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-radius: 10px;\n overflow: hidden;\n}\n\n.collapsible-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n padding: 12px 16px;\n border: none;\n background: var(--mj-bg-page);\n cursor: pointer;\n transition: background 0.2s ease;\n}\n\n.collapsible-header[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.collapsible-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.collapsible-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 14px;\n}\n\n.collapsible-chevron[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 12px;\n transition: transform 0.2s ease;\n}\n\n.collapsible-content[_ngcontent-%COMP%] {\n padding: 16px;\n border-top: 1px solid color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n\n\n\n\n\n.radio-group--horizontal[_ngcontent-%COMP%] {\n flex-direction: row;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.radio-option--compact[_ngcontent-%COMP%] {\n padding: 10px 14px;\n flex: 1;\n min-width: 100px;\n}\n\n.radio-option--compact[_ngcontent-%COMP%] .radio-label[_ngcontent-%COMP%] {\n font-size: 13px;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.radio-option--compact[_ngcontent-%COMP%] .radio-label[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 12px;\n}\n\n.radio-option--compact[_ngcontent-%COMP%] .radio-mark[_ngcontent-%COMP%] {\n width: 16px;\n height: 16px;\n}\n\n.radio-option--compact.selected[_ngcontent-%COMP%] .radio-mark[_ngcontent-%COMP%]::after {\n width: 8px;\n height: 8px;\n}\n\n\n\n\n\n\n.checkbox-group--compact[_ngcontent-%COMP%] {\n gap: 4px;\n}\n\n.checkbox-option--compact[_ngcontent-%COMP%] {\n padding: 10px 14px;\n}\n\n.checkbox-option--compact[_ngcontent-%COMP%] .checkbox-mark[_ngcontent-%COMP%] {\n width: 18px;\n height: 18px;\n margin-top: 0;\n}\n\n.checkbox-option--compact[_ngcontent-%COMP%] .checkbox-label[_ngcontent-%COMP%] {\n font-size: 13px;\n}\n\n\n\n\n\n\nmj-tree-dropdown.error[_ngcontent-%COMP%] {\n --dropdown-border-color: var(--mj-status-error);\n}\n\nmj-tree-dropdown.error[_ngcontent-%COMP%]:focus-within {\n --dropdown-border-focus: var(--mj-status-error);\n}"] });
|
|
275
|
+
} }, dependencies: [i1.DefaultValueAccessor, i1.CheckboxControlValueAccessor, i1.RadioControlValueAccessor, i1.NgControlStatus, i1.NgModel], styles: ["\n\n\n\n\n\n\n\n\n\n.config-panel[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 24px;\n padding: 8px 0;\n}\n\n\n\n\n\n\n.form-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.form-group[_ngcontent-%COMP%] > label[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.form-group[_ngcontent-%COMP%] > label[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 14px;\n width: 16px;\n}\n\n.form-group[_ngcontent-%COMP%] > label[_ngcontent-%COMP%] .required[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n\n\n\n\n\n.form-input[_ngcontent-%COMP%] {\n padding: 14px 16px;\n border: 2px solid var(--mj-border-default);\n border-radius: 10px;\n font-size: 15px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n transition: all 0.2s ease;\n width: 100%;\n box-sizing: border-box;\n}\n\n.form-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 4px color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n}\n\n.form-input[_ngcontent-%COMP%]::placeholder {\n color: var(--mj-text-disabled);\n}\n\n.form-input.error[_ngcontent-%COMP%] {\n border-color: var(--mj-status-error);\n}\n\n.form-input.error[_ngcontent-%COMP%]:focus {\n box-shadow: 0 0 0 4px color-mix(in srgb, var(--mj-status-error) 12%, transparent);\n}\n\n.input-with-action[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n.input-with-action[_ngcontent-%COMP%] .form-input[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.input-action-btn[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 2px solid var(--mj-border-default);\n border-radius: 10px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n}\n\n.input-action-btn[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n\n\n\n\n\n.form-hint[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-muted);\n line-height: 1.4;\n}\n\n.form-error[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-status-error);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.form-error[_ngcontent-%COMP%]::before {\n content: '\\f071';\n font-family: 'Font Awesome 6 Free';\n font-weight: 900;\n font-size: 12px;\n}\n\n\n\n\n\n\n.radio-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.radio-option[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n border: 2px solid color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n background: var(--mj-bg-surface);\n}\n\n.radio-option[_ngcontent-%COMP%]:hover {\n border-color: color-mix(in srgb, var(--mj-brand-primary) 30%, var(--mj-bg-surface));\n background: var(--mj-bg-surface-card);\n}\n\n.radio-option.selected[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.radio-option[_ngcontent-%COMP%] input[type=\"radio\"][_ngcontent-%COMP%] {\n display: none;\n}\n\n.radio-mark[_ngcontent-%COMP%] {\n width: 20px;\n height: 20px;\n border: 2px solid var(--mj-border-strong);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: all 0.2s ease;\n}\n\n.radio-option.selected[_ngcontent-%COMP%] .radio-mark[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n}\n\n.radio-option.selected[_ngcontent-%COMP%] .radio-mark[_ngcontent-%COMP%]::after {\n content: '';\n width: 10px;\n height: 10px;\n background: var(--mj-brand-primary);\n border-radius: 50%;\n}\n\n.radio-content[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.radio-label[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.radio-badge[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 600;\n padding: 3px 8px;\n border-radius: 4px;\n text-transform: uppercase;\n}\n\n.radio-badge.recommended[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 10%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.radio-badge.secure[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.radio-badge.warning[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 10%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n\n\n\n\n\n.checkbox-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.checkbox-option[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 14px 16px;\n border: 2px solid color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n background: var(--mj-bg-surface);\n}\n\n.checkbox-option[_ngcontent-%COMP%]:hover {\n border-color: color-mix(in srgb, var(--mj-brand-primary) 30%, var(--mj-bg-surface));\n background: var(--mj-bg-surface-card);\n}\n\n.checkbox-option[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n display: none;\n}\n\n.checkbox-mark[_ngcontent-%COMP%] {\n width: 22px;\n height: 22px;\n border: 2px solid var(--mj-border-strong);\n border-radius: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: all 0.2s ease;\n margin-top: 2px;\n}\n\n.checkbox-option[_ngcontent-%COMP%] input[_ngcontent-%COMP%]:checked + .checkbox-mark[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.checkbox-option[_ngcontent-%COMP%] input[_ngcontent-%COMP%]:checked + .checkbox-mark[_ngcontent-%COMP%]::after {\n content: '\\f00c';\n font-family: 'Font Awesome 6 Free';\n font-weight: 900;\n font-size: 12px;\n color: var(--mj-text-inverse);\n}\n\n.checkbox-content[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.checkbox-label[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.checkbox-desc[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n\n\n\n\n\n.form-select[_ngcontent-%COMP%] {\n padding: 14px 40px 14px 16px;\n border: 2px solid var(--mj-border-default);\n border-radius: 10px;\n font-size: 15px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n transition: all 0.2s ease;\n width: 100%;\n box-sizing: border-box;\n cursor: pointer;\n appearance: none;\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 8L1 3h10z'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 16px center;\n}\n\n.form-select[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 4px color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n}\n\n\n\n\n\n\n.config-panel--compact[_ngcontent-%COMP%] {\n gap: 16px;\n}\n\n.config-panel--compact[_ngcontent-%COMP%] .form-group[_ngcontent-%COMP%] {\n gap: 8px;\n}\n\n.config-panel--compact[_ngcontent-%COMP%] .form-input[_ngcontent-%COMP%] {\n padding: 10px 14px;\n font-size: 14px;\n}\n\n.config-panel--compact[_ngcontent-%COMP%] .form-select[_ngcontent-%COMP%] {\n padding: 10px 36px 10px 14px;\n font-size: 14px;\n}\n\n\n\n\n\n\n.optional-tag[_ngcontent-%COMP%] {\n font-weight: 400;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n\n\n\n\n\n.form-hint--selected[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n.form-hint--selected[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n\n\n\n\n\n.collapsible-section[_ngcontent-%COMP%] {\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-radius: 10px;\n overflow: hidden;\n}\n\n.collapsible-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n padding: 12px 16px;\n border: none;\n background: var(--mj-bg-page);\n cursor: pointer;\n transition: background 0.2s ease;\n}\n\n.collapsible-header[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.collapsible-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.collapsible-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 14px;\n}\n\n.collapsible-chevron[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 12px;\n transition: transform 0.2s ease;\n}\n\n.collapsible-content[_ngcontent-%COMP%] {\n padding: 16px;\n border-top: 1px solid color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n\n\n\n\n\n.radio-group--horizontal[_ngcontent-%COMP%] {\n flex-direction: row;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.radio-option--compact[_ngcontent-%COMP%] {\n padding: 10px 14px;\n flex: 1;\n min-width: 120px;\n}\n\n.radio-option--compact[_ngcontent-%COMP%] .radio-label[_ngcontent-%COMP%] {\n font-size: 13px;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.radio-option--compact[_ngcontent-%COMP%] .radio-label[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 12px;\n}\n\n.radio-option--compact[_ngcontent-%COMP%] .radio-mark[_ngcontent-%COMP%] {\n width: 16px;\n height: 16px;\n}\n\n.radio-option--compact.selected[_ngcontent-%COMP%] .radio-mark[_ngcontent-%COMP%]::after {\n width: 8px;\n height: 8px;\n}\n\n\n\n\n\n\n.checkbox-group--compact[_ngcontent-%COMP%] {\n gap: 4px;\n}\n\n.checkbox-option--compact[_ngcontent-%COMP%] {\n padding: 10px 14px;\n}\n\n.checkbox-option--compact[_ngcontent-%COMP%] .checkbox-mark[_ngcontent-%COMP%] {\n width: 18px;\n height: 18px;\n margin-top: 0;\n}\n\n.checkbox-option--compact[_ngcontent-%COMP%] .checkbox-label[_ngcontent-%COMP%] {\n font-size: 13px;\n}\n\n\n\n\n\n\nmj-tree-dropdown.error[_ngcontent-%COMP%] {\n --dropdown-border-color: var(--mj-status-error);\n}\n\nmj-tree-dropdown.error[_ngcontent-%COMP%]:focus-within {\n --dropdown-border-focus: var(--mj-status-error);\n}"] });
|
|
276
276
|
};
|
|
277
277
|
WebURLConfigPanelComponent = __decorate([
|
|
278
278
|
RegisterClass(BaseConfigPanel, 'WebURLPanelConfigDialog')
|
|
@@ -280,7 +280,7 @@ WebURLConfigPanelComponent = __decorate([
|
|
|
280
280
|
export { WebURLConfigPanelComponent };
|
|
281
281
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(WebURLConfigPanelComponent, [{
|
|
282
282
|
type: Component,
|
|
283
|
-
args: [{ standalone: false, selector: 'mj-weburl-config-panel', template: "<!-- WebURL Config Panel - Form content only, no dialog chrome -->\n<div class=\"config-panel\">\n <!-- Title -->\n <div class=\"form-group\">\n <label for=\"partTitle\">\n <i class=\"fa-solid fa-heading\"></i>\n Part Title\n </label>\n <input\n type=\"text\"\n id=\"partTitle\"\n [(ngModel)]=\"title\"\n (input)=\"onTitleChange()\"\n placeholder=\"Enter a title for this part\"\n class=\"form-input\">\n </div>\n\n <!-- URL -->\n <div class=\"form-group\">\n <label for=\"webUrl\">\n <i class=\"fa-solid fa-link\"></i>\n URL\n <span class=\"required\">*</span>\n </label>\n <div class=\"input-with-action\">\n <input\n type=\"url\"\n id=\"webUrl\"\n [(ngModel)]=\"url\"\n (input)=\"onUrlChange()\"\n placeholder=\"https://example.com\"\n class=\"form-input\"\n [class.error]=\"urlError\">\n @if (showUrlPreview) {\n <button\n class=\"input-action-btn\"\n (click)=\"previewUrl()\"\n title=\"Preview in new tab\">\n <i class=\"fa-solid fa-external-link\"></i>\n </button>\n }\n </div>\n @if (urlError) {\n <span class=\"form-error\">{{ urlError }}</span>\n }\n @if (!urlError) {\n <span class=\"form-hint\">\n Enter the full URL including https://\n </span>\n }\n </div>\n\n <!-- Security Mode -->\n <div class=\"form-group\">\n <label>\n <i class=\"fa-solid fa-shield-halved\"></i>\n Security Mode\n </label>\n <div class=\"radio-group\">\n <label class=\"radio-option\" [class.selected]=\"sandboxMode === 'standard'\">\n <input\n type=\"radio\"\n name=\"sandboxMode\"\n value=\"standard\"\n [(ngModel)]=\"sandboxMode\"\n (change)=\"onSandboxModeChange()\">\n <span class=\"radio-mark\"></span>\n <span class=\"radio-content\">\n <span class=\"radio-label\">Standard</span>\n <span class=\"radio-badge recommended\">Recommended</span>\n </span>\n </label>\n <label class=\"radio-option\" [class.selected]=\"sandboxMode === 'strict'\">\n <input\n type=\"radio\"\n name=\"sandboxMode\"\n value=\"strict\"\n [(ngModel)]=\"sandboxMode\"\n (change)=\"onSandboxModeChange()\">\n <span class=\"radio-mark\"></span>\n <span class=\"radio-content\">\n <span class=\"radio-label\">Strict</span>\n <span class=\"radio-badge secure\">Most Secure</span>\n </span>\n </label>\n <label class=\"radio-option\" [class.selected]=\"sandboxMode === 'permissive'\">\n <input\n type=\"radio\"\n name=\"sandboxMode\"\n value=\"permissive\"\n [(ngModel)]=\"sandboxMode\"\n (change)=\"onSandboxModeChange()\">\n <span class=\"radio-mark\"></span>\n <span class=\"radio-content\">\n <span class=\"radio-label\">Permissive</span>\n <span class=\"radio-badge warning\">Least Secure</span>\n </span>\n </label>\n </div>\n <span class=\"form-hint\">{{ getSandboxModeDescription() }}</span>\n </div>\n\n <!-- Options -->\n <div class=\"form-group\">\n <label>\n <i class=\"fa-solid fa-sliders\"></i>\n Options\n </label>\n <div class=\"checkbox-group\">\n <label class=\"checkbox-option\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"allowFullscreen\"\n (change)=\"onOptionChange()\">\n <span class=\"checkbox-mark\"></span>\n <span class=\"checkbox-content\">\n <span class=\"checkbox-label\">Allow Fullscreen</span>\n <span class=\"checkbox-desc\">Enable fullscreen mode for the embedded content</span>\n </span>\n </label>\n <label class=\"checkbox-option\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"refreshOnResize\"\n (change)=\"onOptionChange()\">\n <span class=\"checkbox-mark\"></span>\n <span class=\"checkbox-content\">\n <span class=\"checkbox-label\">Refresh on Resize</span>\n <span class=\"checkbox-desc\">Reload the page when the part is resized</span>\n </span>\n </label>\n </div>\n </div>\n</div>\n", styles: ["/**\n * Shared styles for Config Panels (form content only, no dialog chrome)\n */\n\n/* ========================================\n Panel Container\n ======================================== */\n\n.config-panel {\n display: flex;\n flex-direction: column;\n gap: 24px;\n padding: 8px 0;\n}\n\n/* ========================================\n Form Groups\n ======================================== */\n\n.form-group {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.form-group > label {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.form-group > label i {\n color: var(--mj-brand-primary);\n font-size: 14px;\n width: 16px;\n}\n\n.form-group > label .required {\n color: var(--mj-status-error);\n}\n\n/* ========================================\n Form Inputs\n ======================================== */\n\n.form-input {\n padding: 14px 16px;\n border: 2px solid var(--mj-border-default);\n border-radius: 10px;\n font-size: 15px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n transition: all 0.2s ease;\n width: 100%;\n box-sizing: border-box;\n}\n\n.form-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 4px color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n}\n\n.form-input::placeholder {\n color: var(--mj-text-disabled);\n}\n\n.form-input.error {\n border-color: var(--mj-status-error);\n}\n\n.form-input.error:focus {\n box-shadow: 0 0 0 4px color-mix(in srgb, var(--mj-status-error) 12%, transparent);\n}\n\n.input-with-action {\n display: flex;\n gap: 8px;\n}\n\n.input-with-action .form-input {\n flex: 1;\n}\n\n.input-action-btn {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 2px solid var(--mj-border-default);\n border-radius: 10px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n}\n\n.input-action-btn:hover {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n/* ========================================\n Form Hints & Errors\n ======================================== */\n\n.form-hint {\n font-size: 13px;\n color: var(--mj-text-muted);\n line-height: 1.4;\n}\n\n.form-error {\n font-size: 13px;\n color: var(--mj-status-error);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.form-error::before {\n content: '\\f071';\n font-family: 'Font Awesome 6 Free';\n font-weight: 900;\n font-size: 12px;\n}\n\n/* ========================================\n Radio Group\n ======================================== */\n\n.radio-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.radio-option {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n border: 2px solid color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n background: var(--mj-bg-surface);\n}\n\n.radio-option:hover {\n border-color: color-mix(in srgb, var(--mj-brand-primary) 30%, var(--mj-bg-surface));\n background: var(--mj-bg-surface-card);\n}\n\n.radio-option.selected {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.radio-option input[type=\"radio\"] {\n display: none;\n}\n\n.radio-mark {\n width: 20px;\n height: 20px;\n border: 2px solid var(--mj-border-strong);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: all 0.2s ease;\n}\n\n.radio-option.selected .radio-mark {\n border-color: var(--mj-brand-primary);\n}\n\n.radio-option.selected .radio-mark::after {\n content: '';\n width: 10px;\n height: 10px;\n background: var(--mj-brand-primary);\n border-radius: 50%;\n}\n\n.radio-content {\n flex: 1;\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.radio-label {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.radio-badge {\n font-size: 11px;\n font-weight: 600;\n padding: 3px 8px;\n border-radius: 4px;\n text-transform: uppercase;\n}\n\n.radio-badge.recommended {\n background: color-mix(in srgb, var(--mj-status-success) 10%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.radio-badge.secure {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.radio-badge.warning {\n background: color-mix(in srgb, var(--mj-status-warning) 10%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n/* ========================================\n Checkbox Group\n ======================================== */\n\n.checkbox-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.checkbox-option {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 14px 16px;\n border: 2px solid color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n background: var(--mj-bg-surface);\n}\n\n.checkbox-option:hover {\n border-color: color-mix(in srgb, var(--mj-brand-primary) 30%, var(--mj-bg-surface));\n background: var(--mj-bg-surface-card);\n}\n\n.checkbox-option input[type=\"checkbox\"] {\n display: none;\n}\n\n.checkbox-mark {\n width: 22px;\n height: 22px;\n border: 2px solid var(--mj-border-strong);\n border-radius: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: all 0.2s ease;\n margin-top: 2px;\n}\n\n.checkbox-option input:checked + .checkbox-mark {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.checkbox-option input:checked + .checkbox-mark::after {\n content: '\\f00c';\n font-family: 'Font Awesome 6 Free';\n font-weight: 900;\n font-size: 12px;\n color: var(--mj-text-inverse);\n}\n\n.checkbox-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.checkbox-label {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.checkbox-desc {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n/* ========================================\n Select/Dropdown\n ======================================== */\n\n.form-select {\n padding: 14px 40px 14px 16px;\n border: 2px solid var(--mj-border-default);\n border-radius: 10px;\n font-size: 15px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n transition: all 0.2s ease;\n width: 100%;\n box-sizing: border-box;\n cursor: pointer;\n appearance: none;\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 8L1 3h10z'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 16px center;\n}\n\n.form-select:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 4px color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n}\n\n/* ========================================\n Compact Panel Variant\n ======================================== */\n\n.config-panel--compact {\n gap: 16px;\n}\n\n.config-panel--compact .form-group {\n gap: 8px;\n}\n\n.config-panel--compact .form-input {\n padding: 10px 14px;\n font-size: 14px;\n}\n\n.config-panel--compact .form-select {\n padding: 10px 36px 10px 14px;\n font-size: 14px;\n}\n\n/* ========================================\n Optional Tag\n ======================================== */\n\n.optional-tag {\n font-weight: 400;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n/* ========================================\n Selected Hint (Success State)\n ======================================== */\n\n.form-hint--selected {\n color: var(--mj-status-success);\n}\n\n.form-hint--selected i {\n color: var(--mj-status-success);\n}\n\n/* ========================================\n Collapsible Section\n ======================================== */\n\n.collapsible-section {\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-radius: 10px;\n overflow: hidden;\n}\n\n.collapsible-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n padding: 12px 16px;\n border: none;\n background: var(--mj-bg-page);\n cursor: pointer;\n transition: background 0.2s ease;\n}\n\n.collapsible-header:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.collapsible-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.collapsible-title i {\n color: var(--mj-brand-primary);\n font-size: 14px;\n}\n\n.collapsible-chevron {\n color: var(--mj-text-muted);\n font-size: 12px;\n transition: transform 0.2s ease;\n}\n\n.collapsible-content {\n padding: 16px;\n border-top: 1px solid color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n/* ========================================\n Horizontal Radio Group\n ======================================== */\n\n.radio-group--horizontal {\n flex-direction: row;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.radio-option--compact {\n padding: 10px 14px;\n flex: 1;\n min-width: 100px;\n}\n\n.radio-option--compact .radio-label {\n font-size: 13px;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.radio-option--compact .radio-label i {\n color: var(--mj-brand-primary);\n font-size: 12px;\n}\n\n.radio-option--compact .radio-mark {\n width: 16px;\n height: 16px;\n}\n\n.radio-option--compact.selected .radio-mark::after {\n width: 8px;\n height: 8px;\n}\n\n/* ========================================\n Compact Checkbox Group\n ======================================== */\n\n.checkbox-group--compact {\n gap: 4px;\n}\n\n.checkbox-option--compact {\n padding: 10px 14px;\n}\n\n.checkbox-option--compact .checkbox-mark {\n width: 18px;\n height: 18px;\n margin-top: 0;\n}\n\n.checkbox-option--compact .checkbox-label {\n font-size: 13px;\n}\n\n/* ========================================\n Tree Dropdown Error State\n ======================================== */\n\nmj-tree-dropdown.error {\n --dropdown-border-color: var(--mj-status-error);\n}\n\nmj-tree-dropdown.error:focus-within {\n --dropdown-border-focus: var(--mj-status-error);\n}\n"] }]
|
|
283
|
+
args: [{ standalone: false, selector: 'mj-weburl-config-panel', template: "<!-- WebURL Config Panel - Form content only, no dialog chrome -->\n<div class=\"config-panel\">\n <!-- Title -->\n <div class=\"form-group\">\n <label for=\"partTitle\">\n <i class=\"fa-solid fa-heading\"></i>\n Part Title\n </label>\n <input\n type=\"text\"\n id=\"partTitle\"\n [(ngModel)]=\"title\"\n (input)=\"onTitleChange()\"\n placeholder=\"Enter a title for this part\"\n class=\"form-input\">\n </div>\n\n <!-- URL -->\n <div class=\"form-group\">\n <label for=\"webUrl\">\n <i class=\"fa-solid fa-link\"></i>\n URL\n <span class=\"required\">*</span>\n </label>\n <div class=\"input-with-action\">\n <input\n type=\"url\"\n id=\"webUrl\"\n [(ngModel)]=\"url\"\n (input)=\"onUrlChange()\"\n placeholder=\"https://example.com\"\n class=\"form-input\"\n [class.error]=\"urlError\">\n @if (showUrlPreview) {\n <button\n class=\"input-action-btn\"\n (click)=\"previewUrl()\"\n title=\"Preview in new tab\">\n <i class=\"fa-solid fa-external-link\"></i>\n </button>\n }\n </div>\n @if (urlError) {\n <span class=\"form-error\">{{ urlError }}</span>\n }\n @if (!urlError) {\n <span class=\"form-hint\">\n Enter the full URL including https://\n </span>\n }\n </div>\n\n <!-- Security Mode -->\n <div class=\"form-group\">\n <label>\n <i class=\"fa-solid fa-shield-halved\"></i>\n Security Mode\n </label>\n <div class=\"radio-group\">\n <label class=\"radio-option\" [class.selected]=\"sandboxMode === 'standard'\">\n <input\n type=\"radio\"\n name=\"sandboxMode\"\n value=\"standard\"\n [(ngModel)]=\"sandboxMode\"\n (change)=\"onSandboxModeChange()\">\n <span class=\"radio-mark\"></span>\n <span class=\"radio-content\">\n <span class=\"radio-label\">Standard</span>\n <span class=\"radio-badge recommended\">Recommended</span>\n </span>\n </label>\n <label class=\"radio-option\" [class.selected]=\"sandboxMode === 'strict'\">\n <input\n type=\"radio\"\n name=\"sandboxMode\"\n value=\"strict\"\n [(ngModel)]=\"sandboxMode\"\n (change)=\"onSandboxModeChange()\">\n <span class=\"radio-mark\"></span>\n <span class=\"radio-content\">\n <span class=\"radio-label\">Strict</span>\n <span class=\"radio-badge secure\">Most Secure</span>\n </span>\n </label>\n <label class=\"radio-option\" [class.selected]=\"sandboxMode === 'permissive'\">\n <input\n type=\"radio\"\n name=\"sandboxMode\"\n value=\"permissive\"\n [(ngModel)]=\"sandboxMode\"\n (change)=\"onSandboxModeChange()\">\n <span class=\"radio-mark\"></span>\n <span class=\"radio-content\">\n <span class=\"radio-label\">Permissive</span>\n <span class=\"radio-badge warning\">Least Secure</span>\n </span>\n </label>\n </div>\n <span class=\"form-hint\">{{ getSandboxModeDescription() }}</span>\n </div>\n\n <!-- Options -->\n <div class=\"form-group\">\n <label>\n <i class=\"fa-solid fa-sliders\"></i>\n Options\n </label>\n <div class=\"checkbox-group\">\n <label class=\"checkbox-option\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"allowFullscreen\"\n (change)=\"onOptionChange()\">\n <span class=\"checkbox-mark\"></span>\n <span class=\"checkbox-content\">\n <span class=\"checkbox-label\">Allow Fullscreen</span>\n <span class=\"checkbox-desc\">Enable fullscreen mode for the embedded content</span>\n </span>\n </label>\n <label class=\"checkbox-option\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"refreshOnResize\"\n (change)=\"onOptionChange()\">\n <span class=\"checkbox-mark\"></span>\n <span class=\"checkbox-content\">\n <span class=\"checkbox-label\">Refresh on Resize</span>\n <span class=\"checkbox-desc\">Reload the page when the part is resized</span>\n </span>\n </label>\n </div>\n </div>\n</div>\n", styles: ["/**\n * Shared styles for Config Panels (form content only, no dialog chrome)\n */\n\n/* ========================================\n Panel Container\n ======================================== */\n\n.config-panel {\n display: flex;\n flex-direction: column;\n gap: 24px;\n padding: 8px 0;\n}\n\n/* ========================================\n Form Groups\n ======================================== */\n\n.form-group {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.form-group > label {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.form-group > label i {\n color: var(--mj-brand-primary);\n font-size: 14px;\n width: 16px;\n}\n\n.form-group > label .required {\n color: var(--mj-status-error);\n}\n\n/* ========================================\n Form Inputs\n ======================================== */\n\n.form-input {\n padding: 14px 16px;\n border: 2px solid var(--mj-border-default);\n border-radius: 10px;\n font-size: 15px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n transition: all 0.2s ease;\n width: 100%;\n box-sizing: border-box;\n}\n\n.form-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 4px color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n}\n\n.form-input::placeholder {\n color: var(--mj-text-disabled);\n}\n\n.form-input.error {\n border-color: var(--mj-status-error);\n}\n\n.form-input.error:focus {\n box-shadow: 0 0 0 4px color-mix(in srgb, var(--mj-status-error) 12%, transparent);\n}\n\n.input-with-action {\n display: flex;\n gap: 8px;\n}\n\n.input-with-action .form-input {\n flex: 1;\n}\n\n.input-action-btn {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 2px solid var(--mj-border-default);\n border-radius: 10px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n}\n\n.input-action-btn:hover {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n/* ========================================\n Form Hints & Errors\n ======================================== */\n\n.form-hint {\n font-size: 13px;\n color: var(--mj-text-muted);\n line-height: 1.4;\n}\n\n.form-error {\n font-size: 13px;\n color: var(--mj-status-error);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.form-error::before {\n content: '\\f071';\n font-family: 'Font Awesome 6 Free';\n font-weight: 900;\n font-size: 12px;\n}\n\n/* ========================================\n Radio Group\n ======================================== */\n\n.radio-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.radio-option {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n border: 2px solid color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n background: var(--mj-bg-surface);\n}\n\n.radio-option:hover {\n border-color: color-mix(in srgb, var(--mj-brand-primary) 30%, var(--mj-bg-surface));\n background: var(--mj-bg-surface-card);\n}\n\n.radio-option.selected {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.radio-option input[type=\"radio\"] {\n display: none;\n}\n\n.radio-mark {\n width: 20px;\n height: 20px;\n border: 2px solid var(--mj-border-strong);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: all 0.2s ease;\n}\n\n.radio-option.selected .radio-mark {\n border-color: var(--mj-brand-primary);\n}\n\n.radio-option.selected .radio-mark::after {\n content: '';\n width: 10px;\n height: 10px;\n background: var(--mj-brand-primary);\n border-radius: 50%;\n}\n\n.radio-content {\n flex: 1;\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.radio-label {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.radio-badge {\n font-size: 11px;\n font-weight: 600;\n padding: 3px 8px;\n border-radius: 4px;\n text-transform: uppercase;\n}\n\n.radio-badge.recommended {\n background: color-mix(in srgb, var(--mj-status-success) 10%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.radio-badge.secure {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.radio-badge.warning {\n background: color-mix(in srgb, var(--mj-status-warning) 10%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n/* ========================================\n Checkbox Group\n ======================================== */\n\n.checkbox-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.checkbox-option {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 14px 16px;\n border: 2px solid color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n background: var(--mj-bg-surface);\n}\n\n.checkbox-option:hover {\n border-color: color-mix(in srgb, var(--mj-brand-primary) 30%, var(--mj-bg-surface));\n background: var(--mj-bg-surface-card);\n}\n\n.checkbox-option input[type=\"checkbox\"] {\n display: none;\n}\n\n.checkbox-mark {\n width: 22px;\n height: 22px;\n border: 2px solid var(--mj-border-strong);\n border-radius: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: all 0.2s ease;\n margin-top: 2px;\n}\n\n.checkbox-option input:checked + .checkbox-mark {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.checkbox-option input:checked + .checkbox-mark::after {\n content: '\\f00c';\n font-family: 'Font Awesome 6 Free';\n font-weight: 900;\n font-size: 12px;\n color: var(--mj-text-inverse);\n}\n\n.checkbox-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.checkbox-label {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.checkbox-desc {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n/* ========================================\n Select/Dropdown\n ======================================== */\n\n.form-select {\n padding: 14px 40px 14px 16px;\n border: 2px solid var(--mj-border-default);\n border-radius: 10px;\n font-size: 15px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n transition: all 0.2s ease;\n width: 100%;\n box-sizing: border-box;\n cursor: pointer;\n appearance: none;\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 8L1 3h10z'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 16px center;\n}\n\n.form-select:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 4px color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n}\n\n/* ========================================\n Compact Panel Variant\n ======================================== */\n\n.config-panel--compact {\n gap: 16px;\n}\n\n.config-panel--compact .form-group {\n gap: 8px;\n}\n\n.config-panel--compact .form-input {\n padding: 10px 14px;\n font-size: 14px;\n}\n\n.config-panel--compact .form-select {\n padding: 10px 36px 10px 14px;\n font-size: 14px;\n}\n\n/* ========================================\n Optional Tag\n ======================================== */\n\n.optional-tag {\n font-weight: 400;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n/* ========================================\n Selected Hint (Success State)\n ======================================== */\n\n.form-hint--selected {\n color: var(--mj-status-success);\n}\n\n.form-hint--selected i {\n color: var(--mj-status-success);\n}\n\n/* ========================================\n Collapsible Section\n ======================================== */\n\n.collapsible-section {\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-radius: 10px;\n overflow: hidden;\n}\n\n.collapsible-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n padding: 12px 16px;\n border: none;\n background: var(--mj-bg-page);\n cursor: pointer;\n transition: background 0.2s ease;\n}\n\n.collapsible-header:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.collapsible-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.collapsible-title i {\n color: var(--mj-brand-primary);\n font-size: 14px;\n}\n\n.collapsible-chevron {\n color: var(--mj-text-muted);\n font-size: 12px;\n transition: transform 0.2s ease;\n}\n\n.collapsible-content {\n padding: 16px;\n border-top: 1px solid color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n/* ========================================\n Horizontal Radio Group\n ======================================== */\n\n.radio-group--horizontal {\n flex-direction: row;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.radio-option--compact {\n padding: 10px 14px;\n flex: 1;\n min-width: 120px;\n}\n\n.radio-option--compact .radio-label {\n font-size: 13px;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.radio-option--compact .radio-label i {\n color: var(--mj-brand-primary);\n font-size: 12px;\n}\n\n.radio-option--compact .radio-mark {\n width: 16px;\n height: 16px;\n}\n\n.radio-option--compact.selected .radio-mark::after {\n width: 8px;\n height: 8px;\n}\n\n/* ========================================\n Compact Checkbox Group\n ======================================== */\n\n.checkbox-group--compact {\n gap: 4px;\n}\n\n.checkbox-option--compact {\n padding: 10px 14px;\n}\n\n.checkbox-option--compact .checkbox-mark {\n width: 18px;\n height: 18px;\n margin-top: 0;\n}\n\n.checkbox-option--compact .checkbox-label {\n font-size: 13px;\n}\n\n/* ========================================\n Tree Dropdown Error State\n ======================================== */\n\nmj-tree-dropdown.error {\n --dropdown-border-color: var(--mj-status-error);\n}\n\nmj-tree-dropdown.error:focus-within {\n --dropdown-border-focus: var(--mj-status-error);\n}\n"] }]
|
|
284
284
|
}], () => [{ type: i0.ChangeDetectorRef }], null); })();
|
|
285
285
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(WebURLConfigPanelComponent, { className: "WebURLConfigPanelComponent", filePath: "src/lib/config-panels/weburl-config-panel.component.ts", lineNumber: 17 }); })();
|
|
286
286
|
//# sourceMappingURL=weburl-config-panel.component.js.map
|
|
@@ -3,6 +3,7 @@ import { BaseDashboardPart } from './base-dashboard-part';
|
|
|
3
3
|
import { EntityInfo } from '@memberjunction/core';
|
|
4
4
|
import { MJUserViewEntityExtended } from '@memberjunction/core-entities';
|
|
5
5
|
import { EntityViewMode, RecordSelectedEvent, RecordOpenedEvent } from '@memberjunction/ng-entity-viewer';
|
|
6
|
+
import { MapRenderMode } from '@memberjunction/ng-map-view';
|
|
6
7
|
import * as i0 from "@angular/core";
|
|
7
8
|
/**
|
|
8
9
|
* Runtime renderer for View dashboard parts.
|
|
@@ -13,6 +14,7 @@ export declare class ViewPartComponent extends BaseDashboardPart implements Afte
|
|
|
13
14
|
viewEntity: MJUserViewEntityExtended | null;
|
|
14
15
|
entityInfo: EntityInfo | null;
|
|
15
16
|
viewMode: EntityViewMode;
|
|
17
|
+
mapRenderMode: MapRenderMode;
|
|
16
18
|
selectionMode: 'single' | 'multiple';
|
|
17
19
|
constructor(cdr: ChangeDetectorRef);
|
|
18
20
|
ngAfterViewInit(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view-part.component.d.ts","sourceRoot":"","sources":["../../../src/lib/parts/view-part.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,iBAAiB,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAEvF,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,OAAO,EAAY,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;;
|
|
1
|
+
{"version":3,"file":"view-part.component.d.ts","sourceRoot":"","sources":["../../../src/lib/parts/view-part.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,iBAAiB,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAEvF,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,OAAO,EAAY,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAC1G,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;;AAE5D;;;GAGG;AACH,qBAoGa,iBAAkB,SAAQ,iBAAkB,YAAW,aAAa,EAAE,SAAS;IACjF,OAAO,UAAS;IAChB,UAAU,EAAE,wBAAwB,GAAG,IAAI,CAAQ;IACnD,UAAU,EAAE,UAAU,GAAG,IAAI,CAAQ;IACrC,QAAQ,EAAE,cAAc,CAAU;IAClC,aAAa,EAAE,aAAa,CAAW;IACvC,aAAa,EAAE,QAAQ,GAAG,UAAU,CAAY;gBAE3C,GAAG,EAAE,iBAAiB;IAIlC,eAAe,IAAI,IAAI;IAMV,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAgElC,gBAAgB,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI;IASlD,cAAc,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI;cAmBlC,OAAO,IAAI,IAAI;yCA9GzB,iBAAiB;2CAAjB,iBAAiB;CAmH7B"}
|
|
@@ -47,7 +47,7 @@ function ViewPartComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
|
47
47
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
48
48
|
i0.ɵɵproperty("entity", ctx_r0.entityInfo)("viewEntity", ctx_r0.viewEntity);
|
|
49
49
|
i0.ɵɵtwoWayProperty("viewMode", ctx_r0.viewMode);
|
|
50
|
-
i0.ɵɵproperty("gridSelectionMode", ctx_r0.selectionMode)("showGridToolbar", false);
|
|
50
|
+
i0.ɵɵproperty("mapRenderMode", ctx_r0.mapRenderMode)("gridSelectionMode", ctx_r0.selectionMode)("showGridToolbar", false);
|
|
51
51
|
} }
|
|
52
52
|
/**
|
|
53
53
|
* Runtime renderer for View dashboard parts.
|
|
@@ -58,6 +58,7 @@ let ViewPartComponent = class ViewPartComponent extends BaseDashboardPart {
|
|
|
58
58
|
viewEntity = null;
|
|
59
59
|
entityInfo = null;
|
|
60
60
|
viewMode = 'grid';
|
|
61
|
+
mapRenderMode = 'point';
|
|
61
62
|
selectionMode = 'single';
|
|
62
63
|
constructor(cdr) {
|
|
63
64
|
super(cdr);
|
|
@@ -81,6 +82,7 @@ let ViewPartComponent = class ViewPartComponent extends BaseDashboardPart {
|
|
|
81
82
|
const md = new Metadata();
|
|
82
83
|
// Set view mode from config
|
|
83
84
|
this.viewMode = config?.['displayMode'] || 'grid';
|
|
85
|
+
this.mapRenderMode = config?.['mapRenderMode'] || 'point';
|
|
84
86
|
this.selectionMode = config?.['selectionMode'] === 'multiple' ? 'multiple' : 'single';
|
|
85
87
|
if (viewId) {
|
|
86
88
|
// Load saved view by ID
|
|
@@ -148,12 +150,12 @@ let ViewPartComponent = class ViewPartComponent extends BaseDashboardPart {
|
|
|
148
150
|
this.entityInfo = null;
|
|
149
151
|
}
|
|
150
152
|
static ɵfac = function ViewPartComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ViewPartComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
|
|
151
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ViewPartComponent, selectors: [["mj-view-part"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 5, vars: 8, consts: [[1, "view-part"], [1, "loading-state"], [1, "error-state"], [1, "empty-state"], [3, "entity", "viewEntity", "viewMode", "gridSelectionMode", "showGridToolbar"], ["text", "Loading view..."], [1, "fa-solid", "fa-exclamation-triangle"], [1, "fa-solid", "fa-table"], [3, "viewModeChange", "recordSelected", "recordOpened", "entity", "viewEntity", "viewMode", "gridSelectionMode", "showGridToolbar"]], template: function ViewPartComponent_Template(rf, ctx) { if (rf & 1) {
|
|
153
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ViewPartComponent, selectors: [["mj-view-part"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 5, vars: 8, consts: [[1, "view-part"], [1, "loading-state"], [1, "error-state"], [1, "empty-state"], [3, "entity", "viewEntity", "viewMode", "mapRenderMode", "gridSelectionMode", "showGridToolbar"], ["text", "Loading view..."], [1, "fa-solid", "fa-exclamation-triangle"], [1, "fa-solid", "fa-table"], [3, "viewModeChange", "recordSelected", "recordOpened", "entity", "viewEntity", "viewMode", "mapRenderMode", "gridSelectionMode", "showGridToolbar"]], template: function ViewPartComponent_Template(rf, ctx) { if (rf & 1) {
|
|
152
154
|
i0.ɵɵelementStart(0, "div", 0);
|
|
153
155
|
i0.ɵɵconditionalCreate(1, ViewPartComponent_Conditional_1_Template, 2, 0, "div", 1);
|
|
154
156
|
i0.ɵɵconditionalCreate(2, ViewPartComponent_Conditional_2_Template, 4, 1, "div", 2);
|
|
155
157
|
i0.ɵɵconditionalCreate(3, ViewPartComponent_Conditional_3_Template, 6, 0, "div", 3);
|
|
156
|
-
i0.ɵɵconditionalCreate(4, ViewPartComponent_Conditional_4_Template, 1,
|
|
158
|
+
i0.ɵɵconditionalCreate(4, ViewPartComponent_Conditional_4_Template, 1, 6, "mj-entity-viewer", 4);
|
|
157
159
|
i0.ɵɵelementEnd();
|
|
158
160
|
} if (rf & 2) {
|
|
159
161
|
i0.ɵɵclassProp("loading", ctx.IsLoading)("error", ctx.ErrorMessage);
|
|
@@ -205,6 +207,7 @@ export { ViewPartComponent };
|
|
|
205
207
|
[entity]="entityInfo"
|
|
206
208
|
[viewEntity]="viewEntity"
|
|
207
209
|
[(viewMode)]="viewMode"
|
|
210
|
+
[mapRenderMode]="mapRenderMode"
|
|
208
211
|
[gridSelectionMode]="selectionMode"
|
|
209
212
|
[showGridToolbar]="false"
|
|
210
213
|
(recordSelected)="onRecordSelected($event)"
|
|
@@ -214,5 +217,5 @@ export { ViewPartComponent };
|
|
|
214
217
|
</div>
|
|
215
218
|
`, styles: ["\n :host {\n display: block;\n width: 100%;\n height: 100%;\n }\n\n .view-part {\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface);\n }\n\n .loading-state,\n .error-state,\n .empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n color: var(--mj-text-secondary);\n text-align: center;\n padding: 24px;\n }\n\n .error-state i,\n .empty-state i {\n font-size: 48px;\n color: var(--mj-text-muted);\n margin-bottom: 16px;\n }\n\n .error-state i {\n color: var(--mj-status-error);\n }\n\n .empty-state h4 {\n margin: 0 0 8px 0;\n color: var(--mj-text-primary);\n }\n\n .empty-state p {\n margin: 0;\n font-size: 13px;\n }\n\n mj-entity-viewer {\n flex: 1;\n min-height: 0;\n }\n "] }]
|
|
216
219
|
}], () => [{ type: i0.ChangeDetectorRef }], null); })();
|
|
217
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ViewPartComponent, { className: "ViewPartComponent", filePath: "src/lib/parts/view-part.component.ts", lineNumber:
|
|
220
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ViewPartComponent, { className: "ViewPartComponent", filePath: "src/lib/parts/view-part.component.ts", lineNumber: 114 }); })();
|
|
218
221
|
//# sourceMappingURL=view-part.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view-part.component.js","sourceRoot":"","sources":["../../../src/lib/parts/view-part.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, ChangeDetectorRef, AfterViewInit, OnDestroy } from '@angular/core';\nimport { RegisterClass, UUIDsEqual } from '@memberjunction/global';\nimport { BaseDashboardPart } from './base-dashboard-part';\nimport { PanelConfig } from '../models/dashboard-types';\nimport { Metadata, EntityInfo } from '@memberjunction/core';\nimport { MJUserViewEntityExtended } from '@memberjunction/core-entities';\nimport { EntityViewMode, RecordSelectedEvent, RecordOpenedEvent } from '@memberjunction/ng-entity-viewer';\n\n/**\n * Runtime renderer for View dashboard parts.\n * Displays entity data using mj-entity-viewer with grid, cards, or timeline layout.\n */\n@RegisterClass(BaseDashboardPart, 'ViewPanelRenderer')\n@Component({\n standalone: false,\n selector: 'mj-view-part',\n template: `\n <div class=\"view-part\" [class.loading]=\"IsLoading\" [class.error]=\"ErrorMessage\">\n <!-- Loading state -->\n @if (IsLoading) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading view...\"></mj-loading>\n </div>\n }\n \n <!-- Error state -->\n @if (ErrorMessage && !IsLoading) {\n <div class=\"error-state\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <span>{{ ErrorMessage }}</span>\n </div>\n }\n \n <!-- No view configured -->\n @if (!IsLoading && !ErrorMessage && !hasView) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-table\"></i>\n <h4>No View Selected</h4>\n <p>Click the configure button to select a view for this part.</p>\n </div>\n }\n \n <!-- Entity Viewer -->\n @if (!IsLoading && !ErrorMessage && hasView && entityInfo) {\n <mj-entity-viewer\n [entity]=\"entityInfo\"\n [viewEntity]=\"viewEntity\"\n [(viewMode)]=\"viewMode\"\n [gridSelectionMode]=\"selectionMode\"\n [showGridToolbar]=\"false\"\n (recordSelected)=\"onRecordSelected($event)\"\n (recordOpened)=\"onRecordOpened($event)\">\n </mj-entity-viewer>\n }\n </div>\n `,\n styles: [`\n :host {\n display: block;\n width: 100%;\n height: 100%;\n }\n\n .view-part {\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface);\n }\n\n .loading-state,\n .error-state,\n .empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n color: var(--mj-text-secondary);\n text-align: center;\n padding: 24px;\n }\n\n .error-state i,\n .empty-state i {\n font-size: 48px;\n color: var(--mj-text-muted);\n margin-bottom: 16px;\n }\n\n .error-state i {\n color: var(--mj-status-error);\n }\n\n .empty-state h4 {\n margin: 0 0 8px 0;\n color: var(--mj-text-primary);\n }\n\n .empty-state p {\n margin: 0;\n font-size: 13px;\n }\n\n mj-entity-viewer {\n flex: 1;\n min-height: 0;\n }\n `]\n})\nexport class ViewPartComponent extends BaseDashboardPart implements AfterViewInit, OnDestroy {\n public hasView = false;\n public viewEntity: MJUserViewEntityExtended | null = null;\n public entityInfo: EntityInfo | null = null;\n public viewMode: EntityViewMode = 'grid';\n public selectionMode: 'single' | 'multiple' = 'single';\n\n constructor(cdr: ChangeDetectorRef) {\n super(cdr);\n }\n\n ngAfterViewInit(): void {\n if (this.Panel) {\n this.loadContent();\n }\n }\n\n public async loadContent(): Promise<void> {\n const config = this.getConfig<PanelConfig>();\n const viewId = config?.['viewId'] as string | undefined;\n const entityName = config?.['entityName'] as string | undefined;\n\n if (!viewId && !entityName) {\n this.hasView = false;\n this.cdr.detectChanges();\n return;\n }\n\n this.setLoading(true);\n\n try {\n const md = new Metadata();\n\n // Set view mode from config\n this.viewMode = (config?.['displayMode'] as EntityViewMode) || 'grid';\n this.selectionMode = config?.['selectionMode'] === 'multiple' ? 'multiple' : 'single';\n\n if (viewId) {\n // Load saved view by ID\n const viewEntity = await md.GetEntityObject<MJUserViewEntityExtended>('MJ: User Views');\n const loaded = await viewEntity.Load(viewId);\n this.viewEntity = viewEntity; // IMPORTANT - only set this.viewEntity AFTER we have it loaded in the above\n\n if (!loaded) {\n throw new Error('View not found');\n }\n\n // Get entity info from the view - prefer ViewEntityInfo if available (set by MJUserViewEntityExtended.Load)\n // Fall back to looking up by Entity name (virtual field) or EntityID\n if (viewEntity.ViewEntityInfo) {\n this.entityInfo = viewEntity.ViewEntityInfo;\n } else if (viewEntity.Entity) {\n this.entityInfo = md.Entities.find(e => e.Name === viewEntity!.Entity) || null;\n } else if (viewEntity.EntityID) {\n // Last resort: look up by EntityID\n this.entityInfo = md.Entities.find(e => UUIDsEqual(e.ID, viewEntity!.EntityID)) || null;\n }\n\n if (!this.entityInfo) {\n throw new Error(`Could not determine entity for view \"${this.viewEntity.Name}\" (ID: ${viewId})`);\n }\n } else if (entityName) {\n // Create dynamic view for entity (no saved view)\n this.entityInfo = md.Entities.find(e => e.Name === entityName) || null;\n\n if (!this.entityInfo) {\n throw new Error(`Entity \"${entityName}\" not found`);\n }\n\n // No viewEntity means the entity-viewer will show all records\n this.viewEntity = null;\n }\n\n this.hasView = true;\n this.setLoading(false);\n } catch (error) {\n this.setError(error instanceof Error ? error.message : 'Failed to load view');\n }\n }\n\n public onRecordSelected(event: RecordSelectedEvent): void {\n // Emit data change event with selected record\n this.emitDataChanged({\n type: 'record-selected',\n record: event.record,\n primaryKey: event.record?.PrimaryKey\n });\n }\n\n public onRecordOpened(event: RecordOpenedEvent): void {\n // Emit data change event for record open (for any listeners that need it)\n this.emitDataChanged({\n type: 'record-opened',\n record: event.record,\n primaryKey: event.record?.PrimaryKey\n });\n\n // Request navigation to open the record\n if (event.entity && event.compositeKey) {\n this.RequestOpenEntityRecord(\n event.entity.Name,\n event.compositeKey.ToURLSegment(),\n 'view',\n false\n );\n }\n }\n\n protected override cleanup(): void {\n // EntityViewer handles its own cleanup\n this.viewEntity = null;\n this.entityInfo = null;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"view-part.component.js","sourceRoot":"","sources":["../../../src/lib/parts/view-part.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, ChangeDetectorRef, AfterViewInit, OnDestroy } from '@angular/core';\nimport { RegisterClass, UUIDsEqual } from '@memberjunction/global';\nimport { BaseDashboardPart } from './base-dashboard-part';\nimport { PanelConfig } from '../models/dashboard-types';\nimport { Metadata, EntityInfo } from '@memberjunction/core';\nimport { MJUserViewEntityExtended } from '@memberjunction/core-entities';\nimport { EntityViewMode, RecordSelectedEvent, RecordOpenedEvent } from '@memberjunction/ng-entity-viewer';\nimport { MapRenderMode } from '@memberjunction/ng-map-view';\n\n/**\n * Runtime renderer for View dashboard parts.\n * Displays entity data using mj-entity-viewer with grid, cards, or timeline layout.\n */\n@RegisterClass(BaseDashboardPart, 'ViewPanelRenderer')\n@Component({\n standalone: false,\n selector: 'mj-view-part',\n template: `\n <div class=\"view-part\" [class.loading]=\"IsLoading\" [class.error]=\"ErrorMessage\">\n <!-- Loading state -->\n @if (IsLoading) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading view...\"></mj-loading>\n </div>\n }\n \n <!-- Error state -->\n @if (ErrorMessage && !IsLoading) {\n <div class=\"error-state\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <span>{{ ErrorMessage }}</span>\n </div>\n }\n \n <!-- No view configured -->\n @if (!IsLoading && !ErrorMessage && !hasView) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-table\"></i>\n <h4>No View Selected</h4>\n <p>Click the configure button to select a view for this part.</p>\n </div>\n }\n \n <!-- Entity Viewer -->\n @if (!IsLoading && !ErrorMessage && hasView && entityInfo) {\n <mj-entity-viewer\n [entity]=\"entityInfo\"\n [viewEntity]=\"viewEntity\"\n [(viewMode)]=\"viewMode\"\n [mapRenderMode]=\"mapRenderMode\"\n [gridSelectionMode]=\"selectionMode\"\n [showGridToolbar]=\"false\"\n (recordSelected)=\"onRecordSelected($event)\"\n (recordOpened)=\"onRecordOpened($event)\">\n </mj-entity-viewer>\n }\n </div>\n `,\n styles: [`\n :host {\n display: block;\n width: 100%;\n height: 100%;\n }\n\n .view-part {\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface);\n }\n\n .loading-state,\n .error-state,\n .empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n color: var(--mj-text-secondary);\n text-align: center;\n padding: 24px;\n }\n\n .error-state i,\n .empty-state i {\n font-size: 48px;\n color: var(--mj-text-muted);\n margin-bottom: 16px;\n }\n\n .error-state i {\n color: var(--mj-status-error);\n }\n\n .empty-state h4 {\n margin: 0 0 8px 0;\n color: var(--mj-text-primary);\n }\n\n .empty-state p {\n margin: 0;\n font-size: 13px;\n }\n\n mj-entity-viewer {\n flex: 1;\n min-height: 0;\n }\n `]\n})\nexport class ViewPartComponent extends BaseDashboardPart implements AfterViewInit, OnDestroy {\n public hasView = false;\n public viewEntity: MJUserViewEntityExtended | null = null;\n public entityInfo: EntityInfo | null = null;\n public viewMode: EntityViewMode = 'grid';\n public mapRenderMode: MapRenderMode = 'point';\n public selectionMode: 'single' | 'multiple' = 'single';\n\n constructor(cdr: ChangeDetectorRef) {\n super(cdr);\n }\n\n ngAfterViewInit(): void {\n if (this.Panel) {\n this.loadContent();\n }\n }\n\n public async loadContent(): Promise<void> {\n const config = this.getConfig<PanelConfig>();\n const viewId = config?.['viewId'] as string | undefined;\n const entityName = config?.['entityName'] as string | undefined;\n\n if (!viewId && !entityName) {\n this.hasView = false;\n this.cdr.detectChanges();\n return;\n }\n\n this.setLoading(true);\n\n try {\n const md = new Metadata();\n\n // Set view mode from config\n this.viewMode = (config?.['displayMode'] as EntityViewMode) || 'grid';\n this.mapRenderMode = (config?.['mapRenderMode'] as MapRenderMode) || 'point';\n this.selectionMode = config?.['selectionMode'] === 'multiple' ? 'multiple' : 'single';\n\n if (viewId) {\n // Load saved view by ID\n const viewEntity = await md.GetEntityObject<MJUserViewEntityExtended>('MJ: User Views');\n const loaded = await viewEntity.Load(viewId);\n this.viewEntity = viewEntity; // IMPORTANT - only set this.viewEntity AFTER we have it loaded in the above\n\n if (!loaded) {\n throw new Error('View not found');\n }\n\n // Get entity info from the view - prefer ViewEntityInfo if available (set by MJUserViewEntityExtended.Load)\n // Fall back to looking up by Entity name (virtual field) or EntityID\n if (viewEntity.ViewEntityInfo) {\n this.entityInfo = viewEntity.ViewEntityInfo;\n } else if (viewEntity.Entity) {\n this.entityInfo = md.Entities.find(e => e.Name === viewEntity!.Entity) || null;\n } else if (viewEntity.EntityID) {\n // Last resort: look up by EntityID\n this.entityInfo = md.Entities.find(e => UUIDsEqual(e.ID, viewEntity!.EntityID)) || null;\n }\n\n if (!this.entityInfo) {\n throw new Error(`Could not determine entity for view \"${this.viewEntity.Name}\" (ID: ${viewId})`);\n }\n } else if (entityName) {\n // Create dynamic view for entity (no saved view)\n this.entityInfo = md.Entities.find(e => e.Name === entityName) || null;\n\n if (!this.entityInfo) {\n throw new Error(`Entity \"${entityName}\" not found`);\n }\n\n // No viewEntity means the entity-viewer will show all records\n this.viewEntity = null;\n }\n\n this.hasView = true;\n this.setLoading(false);\n } catch (error) {\n this.setError(error instanceof Error ? error.message : 'Failed to load view');\n }\n }\n\n public onRecordSelected(event: RecordSelectedEvent): void {\n // Emit data change event with selected record\n this.emitDataChanged({\n type: 'record-selected',\n record: event.record,\n primaryKey: event.record?.PrimaryKey\n });\n }\n\n public onRecordOpened(event: RecordOpenedEvent): void {\n // Emit data change event for record open (for any listeners that need it)\n this.emitDataChanged({\n type: 'record-opened',\n record: event.record,\n primaryKey: event.record?.PrimaryKey\n });\n\n // Request navigation to open the record\n if (event.entity && event.compositeKey) {\n this.RequestOpenEntityRecord(\n event.entity.Name,\n event.compositeKey.ToURLSegment(),\n 'view',\n false\n );\n }\n }\n\n protected override cleanup(): void {\n // EntityViewer handles its own cleanup\n this.viewEntity = null;\n this.entityInfo = null;\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-dashboard-viewer",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.26.0",
|
|
4
4
|
"description": "MemberJunction: Angular components for metadata-driven dashboards with Golden Layout panels, supporting views, queries, artifacts, and custom content",
|
|
5
5
|
"main": "./dist/public-api.js",
|
|
6
6
|
"typings": "./dist/public-api.d.ts",
|
|
@@ -37,14 +37,15 @@
|
|
|
37
37
|
"golden-layout": "^2.6.0"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@memberjunction/core
|
|
41
|
-
"@memberjunction/
|
|
42
|
-
"@memberjunction/
|
|
43
|
-
"@memberjunction/ng-
|
|
44
|
-
"@memberjunction/ng-entity-viewer": "5.
|
|
45
|
-
"@memberjunction/ng-
|
|
46
|
-
"@memberjunction/ng-query-viewer": "5.
|
|
47
|
-
"@memberjunction/ng-
|
|
40
|
+
"@memberjunction/core": "5.26.0",
|
|
41
|
+
"@memberjunction/core-entities": "5.26.0",
|
|
42
|
+
"@memberjunction/global": "5.26.0",
|
|
43
|
+
"@memberjunction/ng-artifacts": "5.26.0",
|
|
44
|
+
"@memberjunction/ng-entity-viewer": "5.26.0",
|
|
45
|
+
"@memberjunction/ng-map-view": "5.26.0",
|
|
46
|
+
"@memberjunction/ng-query-viewer": "5.26.0",
|
|
47
|
+
"@memberjunction/ng-shared-generic": "5.26.0",
|
|
48
|
+
"@memberjunction/ng-trees": "5.26.0",
|
|
48
49
|
"rxjs": "^7.8.2",
|
|
49
50
|
"tslib": "^2.8.1"
|
|
50
51
|
},
|