@memberjunction/ng-base-forms 6.1.0-edge.4 → 6.1.0-edge.6
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/chrome/form-chrome-rail-pref.d.ts +22 -0
- package/dist/lib/chrome/form-chrome-rail-pref.d.ts.map +1 -1
- package/dist/lib/chrome/form-chrome-rail-pref.js +29 -0
- package/dist/lib/chrome/form-chrome-rail-pref.js.map +1 -1
- package/dist/lib/chrome/form-chrome.d.ts +19 -0
- package/dist/lib/chrome/form-chrome.d.ts.map +1 -1
- package/dist/lib/chrome/form-chrome.js +26 -0
- package/dist/lib/chrome/form-chrome.js.map +1 -1
- package/dist/lib/container/record-form-container.component.d.ts +52 -2
- package/dist/lib/container/record-form-container.component.d.ts.map +1 -1
- package/dist/lib/container/record-form-container.component.js +485 -161
- package/dist/lib/container/record-form-container.component.js.map +1 -1
- package/dist/lib/explorer-entity-data-grid.component.d.ts +36 -0
- package/dist/lib/explorer-entity-data-grid.component.d.ts.map +1 -1
- package/dist/lib/explorer-entity-data-grid.component.js +112 -3
- package/dist/lib/explorer-entity-data-grid.component.js.map +1 -1
- package/dist/lib/field/form-field.component.d.ts +59 -0
- package/dist/lib/field/form-field.component.d.ts.map +1 -1
- package/dist/lib/field/form-field.component.js +710 -294
- package/dist/lib/field/form-field.component.js.map +1 -1
- package/dist/lib/overlays/base-form-overlay.d.ts.map +1 -1
- package/dist/lib/overlays/base-form-overlay.js +3 -1
- package/dist/lib/overlays/base-form-overlay.js.map +1 -1
- package/dist/lib/overlays/form-slide-in.component.js +10 -11
- package/dist/lib/overlays/form-slide-in.component.js.map +1 -1
- package/dist/lib/panel/collapsible-panel.component.d.ts +84 -3
- package/dist/lib/panel/collapsible-panel.component.d.ts.map +1 -1
- package/dist/lib/panel/collapsible-panel.component.js +253 -37
- package/dist/lib/panel/collapsible-panel.component.js.map +1 -1
- package/dist/lib/panel-slot/base-form-panel.d.ts +12 -0
- package/dist/lib/panel-slot/base-form-panel.d.ts.map +1 -1
- package/dist/lib/panel-slot/base-form-panel.js.map +1 -1
- package/dist/lib/related-grid-height.d.ts +48 -11
- package/dist/lib/related-grid-height.d.ts.map +1 -1
- package/dist/lib/related-grid-height.js +53 -12
- package/dist/lib/related-grid-height.js.map +1 -1
- package/dist/lib/section-indicators/form-section-indicator-coordinator.service.d.ts +80 -0
- package/dist/lib/section-indicators/form-section-indicator-coordinator.service.d.ts.map +1 -0
- package/dist/lib/section-indicators/form-section-indicator-coordinator.service.js +99 -0
- package/dist/lib/section-indicators/form-section-indicator-coordinator.service.js.map +1 -0
- package/dist/lib/section-indicators/form-section-indicators.d.ts +97 -0
- package/dist/lib/section-indicators/form-section-indicators.d.ts.map +1 -0
- package/dist/lib/section-indicators/form-section-indicators.js +132 -0
- package/dist/lib/section-indicators/form-section-indicators.js.map +1 -0
- package/dist/lib/section-manager/section-manager.component.js +2 -2
- package/dist/lib/section-manager/section-manager.component.js.map +1 -1
- package/dist/lib/toolbar/form-toolbar.component.js +4 -4
- package/dist/lib/toolbar/form-toolbar.component.js.map +1 -1
- package/dist/public-api.d.ts +2 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +3 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +25 -27
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collapsible-panel.component.js","sourceRoot":"","sources":["../../../src/lib/panel/collapsible-panel.component.ts","../../../src/lib/panel/collapsible-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n Component, Input, Output, EventEmitter,\n ChangeDetectionStrategy, ChangeDetectorRef, inject,\n OnChanges, SimpleChanges, OnInit, AfterContentInit, AfterViewInit, OnDestroy,\n ContentChildren, QueryList, HostBinding, HostListener, ElementRef,\n ViewChild, NgZone, ViewEncapsulation\n} from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { FormContext, PanelVariant, PanelDragStartEvent, PanelDropEvent } from '../types/form-types';\nimport { IsFormSectionHidden } from '../types/entity-form-config';\nimport { FormNavigationEvent } from '../types/navigation-events';\nimport { MjFormFieldComponent } from '../field/form-field.component';\nimport { CompositeKey } from '@memberjunction/core';\nimport { EscapeHTML, HighlightSearchMatches } from '@memberjunction/global';\nimport { FormChromeCoordinator } from '../chrome/form-chrome-coordinator.service';\n\n/**\n * Reusable collapsible panel for form sections.\n *\n * Supports three visual variants:\n * - **default**: White card with accent border (standard field sections)\n * - **related-entity**: Blue-accented card with row count badge (related entity grids)\n * - **inherited**: Purple-accented card with \"Inherited from X\" badge (IS-A parent field sections)\n *\n * Features:\n * - Expand/collapse with smooth animation\n * - Search filtering (hides non-matching panels, highlights matched names)\n * - Drag-to-reorder sections\n * - Inheritable \"Inherited from X\" badge with navigation event\n * - Row count badge for related entity sections\n *\n * @example\n * ```html\n * <mj-collapsible-panel\n * SectionKey=\"productDetails\"\n * SectionName=\"Product Details\"\n * Icon=\"fa fa-box\"\n * Variant=\"inherited\"\n * InheritedFromEntity=\"Products\"\n * [Form]=\"formComponent\"\n * [FormContext]=\"formContext\"\n * (Navigate)=\"onNavigate($event)\">\n * <mj-form-field ...></mj-form-field>\n * </mj-collapsible-panel>\n * ```\n */\n@Component({\n standalone: false,\n selector: 'mj-collapsible-panel',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None, // Required to style projected content (grids, etc.)\n templateUrl: './collapsible-panel.component.html',\n styleUrls: ['./collapsible-panel.component.css']\n})\nexport class MjCollapsiblePanelComponent implements OnInit, OnChanges, AfterContentInit, AfterViewInit, OnDestroy {\n private cdr = inject(ChangeDetectorRef);\n private elementRef = inject(ElementRef);\n private ngZone = inject(NgZone);\n private chrome = inject(FormChromeCoordinator, { optional: true });\n\n /** Unique key for state persistence */\n @Input() SectionKey = '';\n\n /** Display name shown in the panel header */\n @Input() SectionName = '';\n\n /** Font Awesome icon class for the panel header */\n @Input() Icon = 'fa fa-folder';\n\n /**\n * Reference to the parent form component for state delegation.\n * Expected to have IsSectionExpanded, SetSectionExpanded, getSectionDisplayOrder methods.\n */\n @Input() Form: unknown;\n\n /** Form-level context (search filter, showEmptyFields) */\n @Input() FormContext?: FormContext;\n\n /** Panel visual variant */\n @Input() Variant: PanelVariant = 'default';\n\n /** Row count badge for related entity sections */\n @Input() BadgeCount: number | undefined;\n\n /** Default expanded state when no persisted state exists */\n @Input() DefaultExpanded: boolean | undefined;\n\n /**\n * For 'inherited' variant: the parent entity name this section's fields come from.\n * Displayed as \"Inherited from X\" badge and used for navigation.\n */\n @Input() InheritedFromEntity = '';\n\n /**\n * For 'inherited' variant: the primary key to navigate to when clicking the badge.\n * (Shared PK in IS-A relationships.)\n */\n @Input() InheritedRecordPrimaryKey?: CompositeKey;\n\n /**\n * Container-driven hard hide. When true the panel is removed from view\n * regardless of search state — used by the record-form container to honor\n * `EntityFormConfig.showRelatedEntities` / `hiddenSectionKeys` /\n * `visibleSectionKeys`. Composes with (overrides) search visibility so all\n * existing `IsVisible`-based section counts stay correct.\n */\n @Input()\n set Hidden(value: boolean) {\n if (value !== this._hidden) {\n this._hidden = value;\n // Recompute visibility if content has initialized (FieldComponents present).\n if (this.FieldComponents) {\n this.UpdateVisibilityAndHighlighting();\n }\n }\n }\n get Hidden(): boolean {\n return this._hidden;\n }\n private _hidden = false;\n\n // ---- Deprecated camelCase aliases (backward compat) ----\n\n /** @deprecated Use [SectionKey] instead */\n @Input('sectionKey') set _deprecatedSectionKey(value: string) { this.SectionKey = value; }\n\n /** @deprecated Use [SectionName] instead */\n @Input('sectionName') set _deprecatedSectionName(value: string) { this.SectionName = value; }\n\n /** @deprecated Use [Icon] instead */\n @Input('icon') set _deprecatedIcon(value: string) { this.Icon = value; }\n\n /** @deprecated Use [Form] instead */\n @Input('form') set _deprecatedForm(value: unknown) { this.Form = value; }\n\n /** @deprecated Use [FormContext] instead */\n @Input('formContext') set _deprecatedFormContext(value: FormContext | undefined) { this.FormContext = value; }\n\n // ---- Outputs ----\n\n @Output() DragStarted = new EventEmitter<PanelDragStartEvent>();\n @Output() DragEnded = new EventEmitter<void>();\n @Output() PanelDrop = new EventEmitter<PanelDropEvent>();\n @Output() Navigate = new EventEmitter<FormNavigationEvent>();\n\n // ---- Content Children ----\n\n @ContentChildren(MjFormFieldComponent, { descendants: true }) FieldComponents!: QueryList<MjFormFieldComponent>;\n\n // ---- State ----\n\n DisplayName = '';\n FieldNames = '';\n IsVisible = true;\n\n @HostBinding('attr.data-section-key')\n get HostSectionKey(): string {\n return this.SectionKey;\n }\n\n @HostBinding('attr.data-variant')\n get HostVariant(): string {\n return this.Variant;\n }\n\n @HostBinding('attr.data-icon')\n get HostIcon(): string {\n return this.Icon;\n }\n\n @HostBinding('class')\n get HostClass(): string {\n const classes = [`mj-panel--${this.Variant}`];\n if (!this.IsVisible) classes.push('mj-search-hidden');\n if (this.IsDragging) classes.push('mj-dragging');\n if (this.IsDragOver) classes.push('mj-drag-over');\n if (this.chrome?.Spec.RelatedRoles.get(this.SectionKey) === 'Detail') {\n classes.push('mj-form-role-detail');\n }\n if (this.chrome?.HidesAccordionChrome(this.SectionKey)) {\n classes.push('mj-chrome-plain');\n }\n if (!this.hasRenderableContent()) {\n classes.push('mj-panel-empty');\n }\n return classes.join(' ');\n }\n\n @HostBinding('style.order')\n get CssOrder(): number {\n const formRef = this.Form as { getSectionDisplayOrder?: (key: string) => number };\n return formRef?.getSectionDisplayOrder ? formRef.getSectionDisplayOrder(this.SectionKey) : 0;\n }\n\n IsDragging = false;\n IsDragOver = false;\n\n // ---- Event relay ----\n\n /** Signals re-subscription when ContentChildren change */\n private fieldNavReset$ = new Subject<void>();\n private destroy$ = new Subject<void>();\n\n // ---- Panel content resize ----\n\n @ViewChild('panelContent') private panelContentRef?: ElementRef<HTMLElement>;\n private resizeObserver?: ResizeObserver;\n private resizeDebounceTimer?: ReturnType<typeof setTimeout>;\n /** ResizeObserver fires once synchronously on observe(); that initial measurement is not a user resize. */\n private resizeObserverPrimed = false;\n\n /**\n * Persisted accordion resize height for related-entity panels.\n * Related grids size themselves from row count (accordion and left-nav),\n * so a pinned pixel height — especially 0 / toolbar-only measured while\n * collapsed — would clip the grid. Only honor a user drag that is at\n * least the CSS min-height.\n */\n get PanelContentHeight(): number | undefined {\n if (this.Variant !== 'related-entity') return undefined;\n if (this.hidesAccordionChrome()) return undefined;\n const formRef = this.Form as { GetSectionPanelHeight?: (key: string) => number | undefined };\n const persisted = formRef?.GetSectionPanelHeight?.(this.SectionKey);\n if (persisted == null || persisted < 120) return undefined;\n return persisted;\n }\n\n private hidesAccordionChrome(): boolean {\n if (this.chrome?.HidesAccordionChrome(this.SectionKey)) return true;\n const el = this.elementRef.nativeElement as HTMLElement | undefined;\n return !!el?.classList.contains('mj-chrome-show');\n }\n\n /** Whether drag-to-reorder is allowed (from FormContext) */\n get ReorderAllowed(): boolean {\n return this.FormContext?.allowSectionReorder !== false;\n }\n\n /**\n * Whether this panel's header may collapse/expand. Driven by\n * `FormContext.collapsibleSections`; when false the panel renders\n * always-expanded with no toggle chevron (used by dialog/slide-in surfaces\n * that lock sections open). Undefined / true means collapsible.\n */\n get Collapsible(): boolean {\n // Selected left-nav item has no accordion chrome. More keeps collapse/expand.\n if (this.hidesAccordionChrome()) return false;\n return this.FormContext?.collapsibleSections !== false;\n }\n\n /** Whether the panel is expanded (delegates to form state; always true when not collapsible) */\n get Expanded(): boolean {\n if (!this.Collapsible) return true;\n const formRef = this.Form as { IsSectionExpanded?: (key: string, defaultExpanded?: boolean) => boolean };\n return formRef?.IsSectionExpanded ? formRef.IsSectionExpanded(this.SectionKey, this.DefaultExpanded) : true;\n }\n\n // ---- Lifecycle ----\n\n ngOnInit(): void {\n this.DisplayName = this.SectionName;\n this.chrome?.Changes.pipe(takeUntil(this.destroy$)).subscribe(() => {\n this.UpdateVisibilityAndHighlighting();\n });\n }\n\n ngAfterContentInit(): void {\n this.UpdateFieldNames();\n this.SubscribeToFieldNavigateEvents();\n this.FieldComponents.changes.subscribe(() => {\n this.UpdateFieldNames();\n this.SubscribeToFieldNavigateEvents();\n });\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['SectionName']) {\n this.DisplayName = this.SectionName;\n }\n if (changes['SectionName'] || changes['FormContext']) {\n this.UpdateVisibilityAndHighlighting();\n }\n if (changes['FormContext'] && this.FieldComponents) {\n this.FieldComponents.forEach(field => {\n field.FormContext = this.FormContext;\n });\n }\n }\n\n ngAfterViewInit(): void {\n this.SetupResizeObserver();\n }\n\n ngOnDestroy(): void {\n this.fieldNavReset$.next();\n this.fieldNavReset$.complete();\n this.destroy$.next();\n this.destroy$.complete();\n this.resizeObserver?.disconnect();\n if (this.resizeDebounceTimer) {\n clearTimeout(this.resizeDebounceTimer);\n }\n }\n\n // ---- Actions ----\n\n Toggle(): void {\n if (!this.Collapsible) return;\n const formRef = this.Form as { SetSectionExpanded?: (key: string, expanded: boolean) => void };\n if (formRef?.SetSectionExpanded) {\n formRef.SetSectionExpanded(this.SectionKey, !this.Expanded);\n this.cdr.markForCheck();\n }\n }\n\n /**\n * Navigate to the parent entity when clicking the \"Inherited from X\" badge.\n * Derives the PrimaryKey from the Form's record when InheritedRecordPrimaryKey\n * is not explicitly provided (which is the common case in generated templates).\n */\n OnInheritedBadgeClick(event: MouseEvent): void {\n event.stopPropagation();\n if (!this.InheritedFromEntity) return;\n\n const primaryKey = this.InheritedRecordPrimaryKey\n ?? (this.Form as { record?: { PrimaryKey: CompositeKey } })?.record?.PrimaryKey\n ?? new CompositeKey([]);\n\n this.Navigate.emit({\n Kind: 'entity-hierarchy',\n EntityName: this.InheritedFromEntity,\n PrimaryKey: primaryKey,\n Direction: 'parent'\n });\n }\n\n // ---- Drag and Drop ----\n\n @HostListener('dragover', ['$event'])\n OnDragOver(event: DragEvent): void {\n if (!this.ReorderAllowed) return;\n event.preventDefault();\n event.stopPropagation();\n if (event.dataTransfer?.types.includes('text/plain')) {\n this.IsDragOver = true;\n }\n }\n\n @HostListener('dragleave', ['$event'])\n OnDragLeave(event: DragEvent): void {\n if (!this.ReorderAllowed) return;\n event.preventDefault();\n this.IsDragOver = false;\n }\n\n @HostListener('drop', ['$event'])\n OnDrop(event: DragEvent): void {\n if (!this.ReorderAllowed) return;\n event.preventDefault();\n event.stopPropagation();\n this.IsDragOver = false;\n\n const sourceSectionKey = event.dataTransfer?.getData('text/plain');\n if (sourceSectionKey && sourceSectionKey !== this.SectionKey) {\n this.PanelDrop.emit({\n SourceSectionKey: sourceSectionKey,\n TargetSectionKey: this.SectionKey\n });\n this.ReorderSections(sourceSectionKey, this.SectionKey);\n }\n }\n\n OnDragStart(event: DragEvent): void {\n if (!this.ReorderAllowed) return;\n this.IsDragging = true;\n event.dataTransfer?.setData('text/plain', this.SectionKey);\n if (event.dataTransfer) {\n event.dataTransfer.effectAllowed = 'move';\n }\n this.DragStarted.emit({ SectionKey: this.SectionKey, Event: event });\n }\n\n OnDragEnd(): void {\n this.IsDragging = false;\n this.DragEnded.emit();\n }\n\n // ---- Private Methods ----\n\n private ReorderSections(sourceSectionKey: string, targetSectionKey: string): void {\n const formRef = this.Form as {\n getSectionOrder?: () => string[];\n setSectionOrder?: (order: string[]) => void;\n };\n if (!formRef?.getSectionOrder || !formRef?.setSectionOrder) return;\n\n const currentOrder = formRef.getSectionOrder();\n const sourceIndex = currentOrder.indexOf(sourceSectionKey);\n const targetIndex = currentOrder.indexOf(targetSectionKey);\n if (sourceIndex === -1 || targetIndex === -1) return;\n\n const newOrder = [...currentOrder];\n newOrder.splice(sourceIndex, 1);\n newOrder.splice(targetIndex, 0, sourceSectionKey);\n formRef.setSectionOrder(newOrder);\n this.cdr.markForCheck();\n }\n\n /**\n * Field panels whose only children are empty/hidden (e.g. leftover\n * `Details` with just unused geo columns) should not take space.\n * Custom widgets and related grids have no FieldComponents — keep them.\n */\n /**\n * Whether this panel matches a section-search term by title or field\n * name. Ignores chrome hide/show — the rail uses this to decide if the\n * *group* matches, even when another section is currently selected.\n */\n public MatchesSearch(term: string): boolean {\n const filter = (term || '').toLowerCase().trim();\n if (!filter) return true;\n if (this.SectionName.toLowerCase().includes(filter)) return true;\n if (this.SectionKey.toLowerCase().includes(filter)) return true;\n return this.FieldNames.includes(filter);\n }\n\n private hasRenderableContent(): boolean {\n if (this.Variant === 'related-entity') return true;\n if (!this.FieldComponents || this.FieldComponents.length === 0) return true;\n return this.FieldComponents.some((field) => !field.ShouldHideField);\n }\n\n private isHiddenByChrome(): boolean {\n if (!this.chrome) return false;\n if (this.Variant === 'related-entity') {\n return !this.chrome.IsRelatedSectionVisible(this.SectionKey);\n }\n return !this.chrome.IsFirstClassSectionVisible(this.SectionKey);\n }\n\n private UpdateFieldNames(): void {\n if (this.FieldComponents) {\n const names: string[] = [];\n this.FieldComponents.forEach(field => {\n if (field.DisplayName) {\n names.push(field.DisplayName.toLowerCase());\n }\n });\n this.FieldNames = names.join(' ');\n this.UpdateVisibilityAndHighlighting();\n }\n }\n\n /**\n * Subscribes to Navigate events from all child form-field components\n * and relays them through this panel's Navigate output.\n */\n private SubscribeToFieldNavigateEvents(): void {\n this.fieldNavReset$.next(); // tear down previous subscriptions\n this.FieldComponents.forEach(field => {\n field.Navigate.pipe(takeUntil(this.fieldNavReset$)).subscribe((event: FormNavigationEvent) => {\n this.Navigate.emit(event);\n });\n });\n }\n\n /**\n * Sets up a ResizeObserver on the panel content div for related-entity panels.\n * When the user drags the CSS resize handle, we persist the new height.\n */\n private SetupResizeObserver(): void {\n if (this.Variant !== 'related-entity' || !this.panelContentRef) return;\n\n const el = this.panelContentRef.nativeElement;\n // Run outside Angular zone to avoid triggering change detection on every resize frame\n this.ngZone.runOutsideAngular(() => {\n this.resizeObserver = new ResizeObserver((entries) => {\n // Skip the synchronous initial fire emitted when observe() is called — it's the\n // panel's own first measurement on load, not a user-initiated resize. Persisting\n // it would write a spurious panelHeight for every panel on form open.\n if (!this.resizeObserverPrimed) {\n this.resizeObserverPrimed = true;\n return;\n }\n // Only a height change while the panel is expanded reflects a genuine user drag of\n // the resize handle. Ignore reflows while collapsed (e.g. content settling on load).\n if (!this.Expanded) return;\n // Left-nav sizes the grid from the leftover column. Persisting that\n // computed height would write ~0 (or the toolbar) and then pin it.\n if (this.hidesAccordionChrome()) return;\n const entry = entries[0];\n if (!entry) return;\n const newHeight = Math.round(entry.contentRect.height);\n if (newHeight < 120) return;\n this.DebouncePersistHeight(newHeight);\n });\n this.resizeObserver.observe(el);\n });\n }\n\n /**\n * Debounces height persistence so we don't write to DB on every resize frame.\n */\n private DebouncePersistHeight(height: number): void {\n if (this.resizeDebounceTimer) {\n clearTimeout(this.resizeDebounceTimer);\n }\n this.resizeDebounceTimer = setTimeout(() => {\n const formRef = this.Form as { SetSectionPanelHeight?: (key: string, height: number) => void };\n formRef?.SetSectionPanelHeight?.(this.SectionKey, height);\n }, 500);\n }\n\n private UpdateVisibilityAndHighlighting(): void {\n // Hard hide takes precedence over search state. Driven by an explicit\n // `Hidden` input OR the form config's section-visibility rules carried on\n // FormContext (which also reach slot-injected BaseFormPanels, since every\n // panel receives FormContext).\n if (this._hidden || IsFormSectionHidden(this.FormContext, this.SectionKey, this.Variant) || this.isHiddenByChrome()) {\n this.IsVisible = false;\n this.DisplayName = EscapeHTML(this.SectionName);\n this.cdr.markForCheck();\n return;\n }\n\n const searchTerm = (this.FormContext?.sectionFilter || '').toLowerCase().trim();\n\n if (!searchTerm) {\n this.IsVisible = this.hasRenderableContent();\n this.DisplayName = this.SectionName;\n this.cdr.markForCheck();\n return;\n }\n\n const sectionMatches = this.SectionName.toLowerCase().includes(searchTerm);\n const fieldsMatch = this.FieldNames.includes(searchTerm);\n this.IsVisible = this.MatchesSearch(searchTerm);\n\n // DisplayName is bound to `[innerHTML]` in the template — must always be HTML-safe.\n this.DisplayName =\n this.IsVisible && sectionMatches\n ? HighlightSearchMatches(this.SectionName, searchTerm, 'mj-forms-search-highlight')\n : EscapeHTML(this.SectionName);\n\n this.cdr.markForCheck();\n }\n}\n","<div class=\"mj-forms-panel\"\n [class.mj-forms-panel--related]=\"Variant === 'related-entity'\"\n [class.mj-forms-panel--inherited]=\"Variant === 'inherited'\"\n [attr.data-section-key]=\"SectionKey\">\n\n <!-- Panel Header -->\n <div class=\"mj-forms-panel-header\"\n [class.mj-forms-panel-header--static]=\"!Collapsible\"\n [attr.role]=\"Collapsible ? 'button' : null\"\n [attr.tabindex]=\"Collapsible ? 0 : null\"\n (click)=\"Toggle()\">\n <!-- Drag Handle (hidden when reorder disabled) -->\n @if (ReorderAllowed) {\n <div class=\"mj-forms-drag-handle\"\n title=\"Drag to reorder sections\"\n draggable=\"true\"\n (dragstart)=\"OnDragStart($event)\"\n (dragend)=\"OnDragEnd()\"\n (click)=\"$event.stopPropagation()\">\n <i class=\"fa-solid fa-grip-vertical\"></i>\n </div>\n }\n\n <!-- Icon + Title -->\n <div class=\"mj-forms-panel-title-group\">\n <i [class]=\"Icon\" class=\"mj-forms-panel-icon\"></i>\n <h3 class=\"mj-forms-panel-title\">\n <span [innerHTML]=\"DisplayName\"></span>\n <!-- Row count badge for related entities -->\n @if (BadgeCount !== undefined) {\n <span class=\"mj-forms-row-count-badge\" [class.mj-forms-row-count-badge--zero]=\"BadgeCount === 0\">\n {{ BadgeCount }}\n </span>\n }\n </h3>\n </div>\n\n <!-- Inherited From badge (IS-A) -->\n @if (Variant === 'inherited' && InheritedFromEntity) {\n <a class=\"mj-forms-inherited-badge\" (click)=\"OnInheritedBadgeClick($event)\"\n [title]=\"'View parent record: ' + InheritedFromEntity\">\n <i class=\"fa-solid fa-arrow-up\"></i>\n Inherited from {{ InheritedFromEntity }}\n </a>\n }\n\n <!-- Chevron (hidden when sections are locked open) -->\n @if (Collapsible) {\n <div class=\"mj-forms-panel-chevron\">\n <i [class]=\"Expanded ? 'fa fa-chevron-up' : 'fa fa-chevron-down'\"></i>\n </div>\n }\n </div>\n\n <!-- Panel Body -->\n <div class=\"mj-forms-panel-body\" [class.mj-forms-panel-body--collapsed]=\"!Expanded\">\n <div class=\"mj-forms-panel-content\"\n #panelContent\n [style.height.px]=\"PanelContentHeight\">\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n"]}
|
|
1
|
+
{"version":3,"file":"collapsible-panel.component.js","sourceRoot":"","sources":["../../../src/lib/panel/collapsible-panel.component.ts","../../../src/lib/panel/collapsible-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n Component, Input, Output, EventEmitter,\n ChangeDetectionStrategy, ChangeDetectorRef, inject,\n OnChanges, SimpleChanges, OnInit, AfterContentInit, AfterViewInit, OnDestroy,\n ContentChildren, QueryList, HostBinding, HostListener, ElementRef,\n ViewChild, NgZone, ViewEncapsulation\n} from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { FormContext, PanelVariant, PanelDragStartEvent, PanelDropEvent } from '../types/form-types';\nimport { IsFormSectionHidden } from '../types/entity-form-config';\nimport { FormNavigationEvent } from '../types/navigation-events';\nimport { MjFormFieldComponent } from '../field/form-field.component';\nimport { CompositeKey } from '@memberjunction/core';\nimport { EscapeHTML, HighlightSearchMatches, type ValidationErrorInfo } from '@memberjunction/global';\nimport { FormChromeCoordinator } from '../chrome/form-chrome-coordinator.service';\nimport { FormSectionIndicatorCoordinator, type FormSectionIndicatorSource } from '../section-indicators/form-section-indicator-coordinator.service';\nimport {\n ClaimedCollectionErrors,\n DescribeSectionDirty,\n DescribeSectionErrors,\n DescribeSectionWarnings,\n SectionOwnsValidationSource,\n SumSectionIndicators,\n TallyValidationErrors,\n type FormSectionIndicators,\n type ParsedValidationSource,\n type SectionValidationScope,\n} from '../section-indicators/form-section-indicators';\n\n/**\n * Reusable collapsible panel for form sections.\n *\n * Supports three visual variants:\n * - **default**: White card with accent border (standard field sections)\n * - **related-entity**: Blue-accented card with row count badge (related entity grids)\n * - **inherited**: Purple-accented card with \"Inherited from X\" badge (IS-A parent field sections)\n *\n * Features:\n * - Expand/collapse with smooth animation\n * - Search filtering (hides non-matching panels, highlights matched names)\n * - Drag-to-reorder sections\n * - Inheritable \"Inherited from X\" badge with navigation event\n * - Row count badge for related entity sections\n * - Section indicators: an unsaved-changes dot and an invalid-field count derived\n * live from the projected `mj-form-field`s (plus anything a custom section\n * supplies through `[Indicators]`), published to the form's chrome rail\n * through {@link FormSectionIndicatorCoordinator}\n *\n * @example\n * ```html\n * <mj-collapsible-panel\n * SectionKey=\"productDetails\"\n * SectionName=\"Product Details\"\n * Icon=\"fa fa-box\"\n * Variant=\"inherited\"\n * InheritedFromEntity=\"Products\"\n * [Form]=\"formComponent\"\n * [FormContext]=\"formContext\"\n * (Navigate)=\"onNavigate($event)\">\n * <mj-form-field ...></mj-form-field>\n * </mj-collapsible-panel>\n * ```\n */\n@Component({\n standalone: false,\n selector: 'mj-collapsible-panel',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None, // Required to style projected content (grids, etc.)\n templateUrl: './collapsible-panel.component.html',\n styleUrls: ['./collapsible-panel.component.css']\n})\nexport class MjCollapsiblePanelComponent implements OnInit, OnChanges, AfterContentInit, AfterViewInit, OnDestroy, FormSectionIndicatorSource {\n private cdr = inject(ChangeDetectorRef);\n private elementRef = inject(ElementRef);\n private ngZone = inject(NgZone);\n private chrome = inject(FormChromeCoordinator, { optional: true });\n private indicators = inject(FormSectionIndicatorCoordinator, { optional: true });\n\n /** Unique key for state persistence */\n @Input() SectionKey = '';\n\n /**\n * Indicator counts a custom section supplies for content that is NOT rendered by\n * `mj-form-field` — a designer, an inline grid, a hand-built editor. Added to the\n * counts this panel derives from its own fields, so a section that mixes both\n * reports the union. Omit for ordinary field panels: their state is derived.\n *\n * ```html\n * <mj-collapsible-panel SectionKey=\"lines\" [Indicators]=\"{ DirtyCount: LineEditor.EditedRows, ErrorCount: LineEditor.InvalidRows }\">\n * ```\n */\n @Input() Indicators?: Partial<FormSectionIndicators> | null;\n\n /**\n * Graph-path collection names whose validation failures belong to THIS panel —\n * `ValidationSources=\"Modifications\"` claims `Modifications[2].ProvisionID`.\n *\n * Only needed when a panel hosts a child collection whose path name differs from\n * its `SectionKey`: plain field failures are joined automatically from the panel's\n * `mj-form-field` children, and a graph path whose leading segment already matches\n * the `SectionKey` is claimed without any declaration. Declared HERE, on the panel\n * that owns the collection, rather than in an app-side `fieldName -> sectionKey`\n * map that duplicates a fact the panel owns and drifts silently when a\n * `SectionKey` is renamed. Accepts a single name or a list.\n */\n @Input() ValidationSources?: string | readonly string[] | null;\n\n /** Display name shown in the panel header */\n @Input() SectionName = '';\n\n /** Font Awesome icon class for the panel header */\n @Input() Icon = 'fa fa-folder';\n\n /**\n * Reference to the parent form component for state delegation.\n * Expected to have IsSectionExpanded, SetSectionExpanded, getSectionDisplayOrder methods.\n */\n @Input() Form: unknown;\n\n /** Form-level context (search filter, showEmptyFields) */\n @Input() FormContext?: FormContext;\n\n /** Panel visual variant */\n @Input() Variant: PanelVariant = 'default';\n\n /** Row count badge for related entity sections */\n @Input() BadgeCount: number | undefined;\n\n /** Default expanded state when no persisted state exists */\n @Input() DefaultExpanded: boolean | undefined;\n\n /**\n * For 'inherited' variant: the parent entity name this section's fields come from.\n * Displayed as \"Inherited from X\" badge and used for navigation.\n */\n @Input() InheritedFromEntity = '';\n\n /**\n * For 'inherited' variant: the primary key to navigate to when clicking the badge.\n * (Shared PK in IS-A relationships.)\n */\n @Input() InheritedRecordPrimaryKey?: CompositeKey;\n\n /**\n * Container-driven hard hide. When true the panel is removed from view\n * regardless of search state — used by the record-form container to honor\n * `EntityFormConfig.showRelatedEntities` / `hiddenSectionKeys` /\n * `visibleSectionKeys`. Composes with (overrides) search visibility so all\n * existing `IsVisible`-based section counts stay correct.\n */\n @Input()\n set Hidden(value: boolean) {\n if (value !== this._hidden) {\n this._hidden = value;\n // Recompute visibility if content has initialized (FieldComponents present).\n if (this.FieldComponents) {\n this.UpdateVisibilityAndHighlighting();\n }\n }\n }\n get Hidden(): boolean {\n return this._hidden;\n }\n private _hidden = false;\n\n // ---- Deprecated camelCase aliases (backward compat) ----\n\n /** @deprecated Use [SectionKey] instead */\n @Input('sectionKey') set _deprecatedSectionKey(value: string) { this.SectionKey = value; }\n\n /** @deprecated Use [SectionName] instead */\n @Input('sectionName') set _deprecatedSectionName(value: string) { this.SectionName = value; }\n\n /** @deprecated Use [Icon] instead */\n @Input('icon') set _deprecatedIcon(value: string) { this.Icon = value; }\n\n /** @deprecated Use [Form] instead */\n @Input('form') set _deprecatedForm(value: unknown) { this.Form = value; }\n\n /** @deprecated Use [FormContext] instead */\n @Input('formContext') set _deprecatedFormContext(value: FormContext | undefined) { this.FormContext = value; }\n\n // ---- Outputs ----\n\n @Output() DragStarted = new EventEmitter<PanelDragStartEvent>();\n @Output() DragEnded = new EventEmitter<void>();\n @Output() PanelDrop = new EventEmitter<PanelDropEvent>();\n @Output() Navigate = new EventEmitter<FormNavigationEvent>();\n\n // ---- Content Children ----\n\n @ContentChildren(MjFormFieldComponent, { descendants: true }) FieldComponents!: QueryList<MjFormFieldComponent>;\n\n // ---- State ----\n\n DisplayName = '';\n FieldNames = '';\n IsVisible = true;\n\n @HostBinding('attr.data-section-key')\n get HostSectionKey(): string {\n return this.SectionKey;\n }\n\n @HostBinding('attr.data-variant')\n get HostVariant(): string {\n return this.Variant;\n }\n\n @HostBinding('attr.data-icon')\n get HostIcon(): string {\n return this.Icon;\n }\n\n /**\n * Indicator counts mirrored onto the host element, so CSS and any DOM sweep can\n * read a section's state without a component reference.\n */\n @HostBinding('attr.data-dirty-count')\n get HostDirtyCount(): number {\n return this.SectionIndicators.DirtyCount;\n }\n\n @HostBinding('attr.data-error-count')\n get HostErrorCount(): number {\n return this.SectionIndicators.ErrorCount;\n }\n\n @HostBinding('class')\n get HostClass(): string {\n const classes = [`mj-panel--${this.Variant}`];\n if (!this.IsVisible) classes.push('mj-search-hidden');\n if (this.IsDragging) classes.push('mj-dragging');\n if (this.IsDragOver) classes.push('mj-drag-over');\n const indicators = this.SectionIndicators;\n if (indicators.DirtyCount > 0) classes.push('mj-panel-dirty');\n if (indicators.ErrorCount > 0) classes.push('mj-panel-has-errors');\n else if (indicators.WarningCount > 0) classes.push('mj-panel-has-warnings');\n if (this.chrome?.Spec.RelatedRoles.get(this.SectionKey) === 'Detail') {\n classes.push('mj-form-role-detail');\n }\n if (this.chrome?.HidesAccordionChrome(this.SectionKey)) {\n classes.push('mj-chrome-plain');\n }\n if (!this.hasRenderableContent()) {\n classes.push('mj-panel-empty');\n }\n return classes.join(' ');\n }\n\n @HostBinding('style.order')\n get CssOrder(): number {\n const formRef = this.Form as { getSectionDisplayOrder?: (key: string) => number };\n return formRef?.getSectionDisplayOrder ? formRef.getSectionDisplayOrder(this.SectionKey) : 0;\n }\n\n IsDragging = false;\n IsDragOver = false;\n\n // ---- Event relay ----\n\n /** Signals re-subscription when ContentChildren change */\n private fieldNavReset$ = new Subject<void>();\n private destroy$ = new Subject<void>();\n\n // ---- Panel content resize ----\n\n @ViewChild('panelContent') private panelContentRef?: ElementRef<HTMLElement>;\n private resizeObserver?: ResizeObserver;\n private resizeDebounceTimer?: ReturnType<typeof setTimeout>;\n /** ResizeObserver fires once synchronously on observe(); that initial measurement is not a user resize. */\n private resizeObserverPrimed = false;\n\n /**\n * Persisted accordion resize height for related-entity panels.\n * Related grids size themselves from row count (accordion and left-nav),\n * so a pinned pixel height — especially 0 / toolbar-only measured while\n * collapsed — would clip the grid. Only honor a user drag that is at\n * least the CSS min-height.\n */\n get PanelContentHeight(): number | undefined {\n if (this.Variant !== 'related-entity') return undefined;\n if (this.hidesAccordionChrome()) return undefined;\n const formRef = this.Form as { GetSectionPanelHeight?: (key: string) => number | undefined };\n const persisted = formRef?.GetSectionPanelHeight?.(this.SectionKey);\n if (persisted == null || persisted < 120) return undefined;\n return persisted;\n }\n\n private hidesAccordionChrome(): boolean {\n if (this.chrome?.HidesAccordionChrome(this.SectionKey)) return true;\n const el = this.elementRef.nativeElement as HTMLElement | undefined;\n return !!el?.classList.contains('mj-chrome-show');\n }\n\n /** Whether drag-to-reorder is allowed (from FormContext) */\n get ReorderAllowed(): boolean {\n return this.FormContext?.allowSectionReorder !== false;\n }\n\n /**\n * Whether this panel's header may collapse/expand. Driven by\n * `FormContext.collapsibleSections`; when false the panel renders\n * always-expanded with no toggle chevron (used by dialog/slide-in surfaces\n * that lock sections open). Undefined / true means collapsible.\n */\n get Collapsible(): boolean {\n // Selected left-nav item has no accordion chrome. More keeps collapse/expand.\n if (this.hidesAccordionChrome()) return false;\n return this.FormContext?.collapsibleSections !== false;\n }\n\n /** Whether the panel is expanded (delegates to form state; always true when not collapsible) */\n get Expanded(): boolean {\n if (!this.Collapsible) return true;\n const formRef = this.Form as { IsSectionExpanded?: (key: string, defaultExpanded?: boolean) => boolean };\n return formRef?.IsSectionExpanded ? formRef.IsSectionExpanded(this.SectionKey, this.DefaultExpanded) : true;\n }\n\n // ---- Section indicators (unsaved-changes dot + invalid-field count) ----\n\n /**\n * Live state of this section: fields edited since the last save, fields that are\n * invalid or required-and-empty, and fields carrying warnings. Derived from the\n * projected `mj-form-field`s on every read — the same state those fields use for\n * their own amber dot and red underline, so the section can never disagree with\n * its fields — plus graph-path validation failures this section claims, plus\n * whatever a custom section supplies through `[Indicators]`.\n *\n * Read during change detection (host bindings, the header template, the rail via\n * the coordinator). Pure and cheap: one pass over the field list.\n */\n public get SectionIndicators(): FormSectionIndicators {\n return SumSectionIndicators(\n this.fieldIndicators(),\n TallyValidationErrors(this.claimedGraphErrors()),\n this.Indicators,\n );\n }\n\n public get SectionDirtyCount(): number {\n return this.SectionIndicators.DirtyCount;\n }\n\n public get SectionErrorCount(): number {\n return this.SectionIndicators.ErrorCount;\n }\n\n public get SectionWarningCount(): number {\n return this.SectionIndicators.WarningCount;\n }\n\n public get SectionDirtyTitle(): string {\n return DescribeSectionDirty(this.SectionDirtyCount);\n }\n\n public get SectionErrorTitle(): string {\n return DescribeSectionErrors(this.SectionErrorCount);\n }\n\n public get SectionWarningTitle(): string {\n return DescribeSectionWarnings(this.SectionWarningCount);\n }\n\n /** {@link FormSectionIndicatorSource} — the rail reads this through the coordinator. */\n public GetSectionIndicators(): FormSectionIndicators {\n return this.SectionIndicators;\n }\n\n /** {@link FormSectionIndicatorSource} — whether a form-level error belongs to this section. */\n public OwnsValidationSource(source: ParsedValidationSource): boolean {\n return SectionOwnsValidationSource(source, this.SectionKey, this.validationScope());\n }\n\n /** Normalized {@link ValidationSources}. */\n public get ValidationCollectionNames(): string[] {\n const raw = this.ValidationSources;\n if (!raw) return [];\n return (typeof raw === 'string' ? [raw] : [...raw]).map((n) => n.trim()).filter((n) => n.length > 0);\n }\n\n /** Field names this panel renders — the join between a plain-field error and this section. */\n private renderedFieldNames(): string[] {\n const names: string[] = [];\n this.FieldComponents?.forEach((field) => {\n if (field.FieldName) names.push(field.FieldName);\n });\n return names;\n }\n\n private validationScope(): SectionValidationScope {\n return { FieldNames: this.renderedFieldNames(), CollectionNames: this.ValidationCollectionNames };\n }\n\n /**\n * Counts of FIELDS (not messages) in each state. A field is invalid when it shows a\n * failure OR is required and empty in edit mode — exactly the two conditions that\n * paint its underline red. Warnings count only on fields with no failure, mirroring\n * `MjFormFieldComponent.ShowWarnings`.\n */\n private fieldIndicators(): FormSectionIndicators {\n let DirtyCount = 0;\n let ErrorCount = 0;\n let WarningCount = 0;\n this.FieldComponents?.forEach((field) => {\n if (field.IsDirty) DirtyCount++;\n // Only a field that renders an EDITOR can be invalid: a read-only field renders its\n // value as text and never paints an underline, so it is skipped even when\n // `IsRequiredEmpty` would say otherwise (a NOT NULL `__mj_CreatedAt` on a new record\n // is empty and read-only — the user cannot fix it, and it fills itself on save).\n if (!field.EditMode || field.IsFieldReadOnly) return;\n if (field.ShowErrors || field.IsRequiredEmpty) ErrorCount++;\n // The field paints its amber underline on EITHER of these — a stored date the input\n // cannot parse warns on its own, outside the validation pipeline.\n else if (field.ShowWarnings || field.StoredDateIsUnreadable) WarningCount++;\n });\n return { DirtyCount, ErrorCount, WarningCount };\n }\n\n /**\n * Graph-path failures (`Lines[2].Amount`) this section owns, once the form has asked\n * for validation to show. Plain field-name failures are NOT counted here — the field\n * that renders them already reports through {@link fieldIndicators}.\n */\n private claimedGraphErrors(): ValidationErrorInfo[] {\n const ctx = this.FormContext;\n if (!ctx?.showValidation || !ctx.validationErrors?.length) return [];\n return ClaimedCollectionErrors(ctx.validationErrors, this.SectionKey, this.validationScope());\n }\n\n /** (Re)declare this section with the container-scoped registry the rail reads. */\n private registerIndicatorSource(previousKey?: string): void {\n if (!this.indicators) return;\n if (previousKey && previousKey !== this.SectionKey) {\n this.indicators.Unregister(this, previousKey);\n }\n this.indicators.Register(this);\n }\n\n // ---- Lifecycle ----\n\n ngOnInit(): void {\n this.DisplayName = this.SectionName;\n this.chrome?.Changes.pipe(takeUntil(this.destroy$)).subscribe(() => {\n this.UpdateVisibilityAndHighlighting();\n });\n this.registerIndicatorSource();\n }\n\n ngAfterContentInit(): void {\n this.UpdateFieldNames();\n this.SubscribeToFieldNavigateEvents();\n this.FieldComponents.changes.subscribe(() => {\n this.UpdateFieldNames();\n this.SubscribeToFieldNavigateEvents();\n // The set of fields changed, so the section's counts (and which errors it\n // claims) may have too — let the rail re-read.\n this.indicators?.NotifyChanged();\n });\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['SectionName']) {\n this.DisplayName = this.SectionName;\n }\n if (changes['SectionKey'] && !changes['SectionKey'].firstChange) {\n this.registerIndicatorSource(changes['SectionKey'].previousValue as string | undefined);\n }\n if (changes['SectionName'] || changes['FormContext']) {\n this.UpdateVisibilityAndHighlighting();\n }\n if (changes['FormContext'] && this.FieldComponents) {\n this.FieldComponents.forEach(field => {\n field.FormContext = this.FormContext;\n });\n }\n }\n\n ngAfterViewInit(): void {\n this.SetupResizeObserver();\n }\n\n ngOnDestroy(): void {\n this.indicators?.Unregister(this);\n this.fieldNavReset$.next();\n this.fieldNavReset$.complete();\n this.destroy$.next();\n this.destroy$.complete();\n this.resizeObserver?.disconnect();\n if (this.resizeDebounceTimer) {\n clearTimeout(this.resizeDebounceTimer);\n }\n }\n\n // ---- Actions ----\n\n Toggle(): void {\n if (!this.Collapsible) return;\n const formRef = this.Form as { SetSectionExpanded?: (key: string, expanded: boolean) => void };\n if (formRef?.SetSectionExpanded) {\n formRef.SetSectionExpanded(this.SectionKey, !this.Expanded);\n this.cdr.markForCheck();\n }\n }\n\n /**\n * Navigate to the parent entity when clicking the \"Inherited from X\" badge.\n * Derives the PrimaryKey from the Form's record when InheritedRecordPrimaryKey\n * is not explicitly provided (which is the common case in generated templates).\n */\n OnInheritedBadgeClick(event: MouseEvent): void {\n event.stopPropagation();\n if (!this.InheritedFromEntity) return;\n\n const primaryKey = this.InheritedRecordPrimaryKey\n ?? (this.Form as { record?: { PrimaryKey: CompositeKey } })?.record?.PrimaryKey\n ?? new CompositeKey([]);\n\n this.Navigate.emit({\n Kind: 'entity-hierarchy',\n EntityName: this.InheritedFromEntity,\n PrimaryKey: primaryKey,\n Direction: 'parent'\n });\n }\n\n // ---- Drag and Drop ----\n\n @HostListener('dragover', ['$event'])\n OnDragOver(event: DragEvent): void {\n if (!this.ReorderAllowed) return;\n event.preventDefault();\n event.stopPropagation();\n if (event.dataTransfer?.types.includes('text/plain')) {\n this.IsDragOver = true;\n }\n }\n\n @HostListener('dragleave', ['$event'])\n OnDragLeave(event: DragEvent): void {\n if (!this.ReorderAllowed) return;\n event.preventDefault();\n this.IsDragOver = false;\n }\n\n @HostListener('drop', ['$event'])\n OnDrop(event: DragEvent): void {\n if (!this.ReorderAllowed) return;\n event.preventDefault();\n event.stopPropagation();\n this.IsDragOver = false;\n\n const sourceSectionKey = event.dataTransfer?.getData('text/plain');\n if (sourceSectionKey && sourceSectionKey !== this.SectionKey) {\n this.PanelDrop.emit({\n SourceSectionKey: sourceSectionKey,\n TargetSectionKey: this.SectionKey\n });\n this.ReorderSections(sourceSectionKey, this.SectionKey);\n }\n }\n\n OnDragStart(event: DragEvent): void {\n if (!this.ReorderAllowed) return;\n this.IsDragging = true;\n event.dataTransfer?.setData('text/plain', this.SectionKey);\n if (event.dataTransfer) {\n event.dataTransfer.effectAllowed = 'move';\n }\n this.DragStarted.emit({ SectionKey: this.SectionKey, Event: event });\n }\n\n OnDragEnd(): void {\n this.IsDragging = false;\n this.DragEnded.emit();\n }\n\n // ---- Private Methods ----\n\n private ReorderSections(sourceSectionKey: string, targetSectionKey: string): void {\n const formRef = this.Form as {\n getSectionOrder?: () => string[];\n setSectionOrder?: (order: string[]) => void;\n };\n if (!formRef?.getSectionOrder || !formRef?.setSectionOrder) return;\n\n const currentOrder = formRef.getSectionOrder();\n const sourceIndex = currentOrder.indexOf(sourceSectionKey);\n const targetIndex = currentOrder.indexOf(targetSectionKey);\n if (sourceIndex === -1 || targetIndex === -1) return;\n\n const newOrder = [...currentOrder];\n newOrder.splice(sourceIndex, 1);\n newOrder.splice(targetIndex, 0, sourceSectionKey);\n formRef.setSectionOrder(newOrder);\n this.cdr.markForCheck();\n }\n\n /**\n * Field panels whose only children are empty/hidden (e.g. leftover\n * `Details` with just unused geo columns) should not take space.\n * Custom widgets and related grids have no FieldComponents — keep them.\n */\n /**\n * Whether this panel matches a section-search term by title or field\n * name. Ignores chrome hide/show — the rail uses this to decide if the\n * *group* matches, even when another section is currently selected.\n */\n public MatchesSearch(term: string): boolean {\n const filter = (term || '').toLowerCase().trim();\n if (!filter) return true;\n if (this.SectionName.toLowerCase().includes(filter)) return true;\n if (this.SectionKey.toLowerCase().includes(filter)) return true;\n return this.FieldNames.includes(filter);\n }\n\n private hasRenderableContent(): boolean {\n if (this.Variant === 'related-entity') return true;\n if (!this.FieldComponents || this.FieldComponents.length === 0) return true;\n return this.FieldComponents.some((field) => !field.ShouldHideField);\n }\n\n private isHiddenByChrome(): boolean {\n if (!this.chrome) return false;\n if (this.Variant === 'related-entity') {\n return !this.chrome.IsRelatedSectionVisible(this.SectionKey);\n }\n return !this.chrome.IsFirstClassSectionVisible(this.SectionKey);\n }\n\n private UpdateFieldNames(): void {\n if (this.FieldComponents) {\n const names: string[] = [];\n this.FieldComponents.forEach(field => {\n if (field.DisplayName) {\n names.push(field.DisplayName.toLowerCase());\n }\n });\n this.FieldNames = names.join(' ');\n this.UpdateVisibilityAndHighlighting();\n }\n }\n\n /**\n * Subscribes to Navigate events from all child form-field components\n * and relays them through this panel's Navigate output. Also listens for\n * value edits so the section indicators (and the rail reading them) refresh\n * on the same tick as the keystroke rather than on the container's next poll.\n */\n private SubscribeToFieldNavigateEvents(): void {\n this.fieldNavReset$.next(); // tear down previous subscriptions\n this.FieldComponents.forEach(field => {\n field.Navigate.pipe(takeUntil(this.fieldNavReset$)).subscribe((event: FormNavigationEvent) => {\n this.Navigate.emit(event);\n });\n field.ValueChange.pipe(takeUntil(this.fieldNavReset$)).subscribe(() => {\n this.cdr.markForCheck();\n this.indicators?.NotifyChanged();\n });\n });\n }\n\n /**\n * Sets up a ResizeObserver on the panel content div for related-entity panels.\n * When the user drags the CSS resize handle, we persist the new height.\n */\n private SetupResizeObserver(): void {\n if (this.Variant !== 'related-entity' || !this.panelContentRef) return;\n\n const el = this.panelContentRef.nativeElement;\n // Run outside Angular zone to avoid triggering change detection on every resize frame\n this.ngZone.runOutsideAngular(() => {\n this.resizeObserver = new ResizeObserver((entries) => {\n // Skip the synchronous initial fire emitted when observe() is called — it's the\n // panel's own first measurement on load, not a user-initiated resize. Persisting\n // it would write a spurious panelHeight for every panel on form open.\n if (!this.resizeObserverPrimed) {\n this.resizeObserverPrimed = true;\n return;\n }\n // Only a height change while the panel is expanded reflects a genuine user drag of\n // the resize handle. Ignore reflows while collapsed (e.g. content settling on load).\n if (!this.Expanded) return;\n // Left-nav sizes the grid from the leftover column. Persisting that\n // computed height would write ~0 (or the toolbar) and then pin it.\n if (this.hidesAccordionChrome()) return;\n const entry = entries[0];\n if (!entry) return;\n const newHeight = Math.round(entry.contentRect.height);\n if (newHeight < 120) return;\n this.DebouncePersistHeight(newHeight);\n });\n this.resizeObserver.observe(el);\n });\n }\n\n /**\n * Debounces height persistence so we don't write to DB on every resize frame.\n */\n private DebouncePersistHeight(height: number): void {\n if (this.resizeDebounceTimer) {\n clearTimeout(this.resizeDebounceTimer);\n }\n this.resizeDebounceTimer = setTimeout(() => {\n const formRef = this.Form as { SetSectionPanelHeight?: (key: string, height: number) => void };\n formRef?.SetSectionPanelHeight?.(this.SectionKey, height);\n }, 500);\n }\n\n private UpdateVisibilityAndHighlighting(): void {\n // Hard hide takes precedence over search state. Driven by an explicit\n // `Hidden` input OR the form config's section-visibility rules carried on\n // FormContext (which also reach slot-injected BaseFormPanels, since every\n // panel receives FormContext).\n if (this._hidden || IsFormSectionHidden(this.FormContext, this.SectionKey, this.Variant) || this.isHiddenByChrome()) {\n this.IsVisible = false;\n this.DisplayName = EscapeHTML(this.SectionName);\n this.cdr.markForCheck();\n return;\n }\n\n const searchTerm = (this.FormContext?.sectionFilter || '').toLowerCase().trim();\n\n if (!searchTerm) {\n this.IsVisible = this.hasRenderableContent();\n this.DisplayName = this.SectionName;\n this.cdr.markForCheck();\n return;\n }\n\n const sectionMatches = this.SectionName.toLowerCase().includes(searchTerm);\n const fieldsMatch = this.FieldNames.includes(searchTerm);\n this.IsVisible = this.MatchesSearch(searchTerm);\n\n // DisplayName is bound to `[innerHTML]` in the template — must always be HTML-safe.\n this.DisplayName =\n this.IsVisible && sectionMatches\n ? HighlightSearchMatches(this.SectionName, searchTerm, 'mj-forms-search-highlight')\n : EscapeHTML(this.SectionName);\n\n this.cdr.markForCheck();\n }\n}\n","<div class=\"mj-forms-panel\"\n [class.mj-forms-panel--related]=\"Variant === 'related-entity'\"\n [class.mj-forms-panel--inherited]=\"Variant === 'inherited'\"\n [attr.data-section-key]=\"SectionKey\">\n\n <!-- Panel Header -->\n <div class=\"mj-forms-panel-header\"\n [class.mj-forms-panel-header--static]=\"!Collapsible\"\n [attr.role]=\"Collapsible ? 'button' : null\"\n [attr.tabindex]=\"Collapsible ? 0 : null\"\n (click)=\"Toggle()\">\n <!-- Drag Handle (hidden when reorder disabled) -->\n @if (ReorderAllowed) {\n <div class=\"mj-forms-drag-handle\"\n title=\"Drag to reorder sections\"\n draggable=\"true\"\n (dragstart)=\"OnDragStart($event)\"\n (dragend)=\"OnDragEnd()\"\n (click)=\"$event.stopPropagation()\">\n <i class=\"fa-solid fa-grip-vertical\"></i>\n </div>\n }\n\n <!-- Icon + Title -->\n <div class=\"mj-forms-panel-title-group\">\n <i [class]=\"Icon\" class=\"mj-forms-panel-icon\"></i>\n <h3 class=\"mj-forms-panel-title\">\n <span [innerHTML]=\"DisplayName\"></span>\n <!-- Section indicators: unsaved-changes dot (same idiom as an edited field's\n label dot) and invalid-field count (same colour as the field's red underline).\n Derived from the projected fields — see SectionIndicators. -->\n @if (SectionDirtyCount > 0) {\n <span class=\"mj-forms-panel-dirty\"\n role=\"img\"\n [title]=\"SectionDirtyTitle\"\n [attr.aria-label]=\"SectionDirtyTitle\"></span>\n }\n @if (SectionErrorCount > 0) {\n <span class=\"mj-forms-panel-error-badge\"\n role=\"img\"\n [title]=\"SectionErrorTitle\"\n [attr.aria-label]=\"SectionErrorTitle\">\n <i class=\"fa-solid fa-circle-exclamation\" aria-hidden=\"true\"></i>{{ SectionErrorCount }}\n </span>\n } @else if (SectionWarningCount > 0) {\n <span class=\"mj-forms-panel-warning-badge\"\n role=\"img\"\n [title]=\"SectionWarningTitle\"\n [attr.aria-label]=\"SectionWarningTitle\">\n <i class=\"fa-solid fa-triangle-exclamation\" aria-hidden=\"true\"></i>{{ SectionWarningCount }}\n </span>\n }\n <!-- Row count badge for related entities -->\n @if (BadgeCount !== undefined) {\n <span class=\"mj-forms-row-count-badge\" [class.mj-forms-row-count-badge--zero]=\"BadgeCount === 0\">\n {{ BadgeCount }}\n </span>\n }\n </h3>\n </div>\n\n <!-- Inherited From badge (IS-A) -->\n @if (Variant === 'inherited' && InheritedFromEntity) {\n <a class=\"mj-forms-inherited-badge\" (click)=\"OnInheritedBadgeClick($event)\"\n [title]=\"'View parent record: ' + InheritedFromEntity\">\n <i class=\"fa-solid fa-arrow-up\"></i>\n Inherited from {{ InheritedFromEntity }}\n </a>\n }\n\n <!-- Chevron (hidden when sections are locked open) -->\n @if (Collapsible) {\n <div class=\"mj-forms-panel-chevron\">\n <i [class]=\"Expanded ? 'fa fa-chevron-up' : 'fa fa-chevron-down'\"></i>\n </div>\n }\n </div>\n\n <!-- Panel Body -->\n <div class=\"mj-forms-panel-body\" [class.mj-forms-panel-body--collapsed]=\"!Expanded\">\n <div class=\"mj-forms-panel-content\"\n #panelContent\n [style.height.px]=\"PanelContentHeight\">\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n"]}
|
|
@@ -91,6 +91,18 @@ export interface FormPanelRegistrationMetadata extends Record<string, unknown> {
|
|
|
91
91
|
* L3 `MJ: Form Chrome Rules` still wins. `chromeGroup` still merges.
|
|
92
92
|
*/
|
|
93
93
|
inclusion?: FormInclusion;
|
|
94
|
+
/**
|
|
95
|
+
* Open a NEW (unsaved) record on this contribution instead of the first first-class group.
|
|
96
|
+
*
|
|
97
|
+
* A saved record opens where the user last was, or on the lead group. That is right for reading a
|
|
98
|
+
* record and wrong for creating one: the lead group is usually a summary, and a summary of a record
|
|
99
|
+
* with no data is a page of blanks the user has to look past to find where typing starts.
|
|
100
|
+
*
|
|
101
|
+
* Only consulted when the record is unsaved, so it cannot change how an existing record opens.
|
|
102
|
+
* If several contributions on one entity set it, the highest ClassFactory `Priority` wins, matching
|
|
103
|
+
* how every other conflict between registrations is settled.
|
|
104
|
+
*/
|
|
105
|
+
leadsWhenUnsaved?: boolean;
|
|
94
106
|
}
|
|
95
107
|
/**
|
|
96
108
|
* Abstract base for every dynamically-injectable form panel.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-form-panel.d.ts","sourceRoot":"","sources":["../../../src/lib/panel-slot/base-form-panel.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACxF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;;AAEvF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,MAAM,aAAa,GACnB,UAAU,GACV,eAAe,GACf,cAAc,GACd,eAAe,GACf,kBAAkB,CAAC;AAEzB;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,6BAA8B,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC1E,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,WAAW,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IACjC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"base-form-panel.d.ts","sourceRoot":"","sources":["../../../src/lib/panel-slot/base-form-panel.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACxF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;;AAEvF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,MAAM,aAAa,GACnB,UAAU,GACV,eAAe,GACf,cAAc,GACd,eAAe,GACf,kBAAkB,CAAC;AAEzB;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,6BAA8B,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC1E,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,WAAW,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IACjC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,aAAa,CAAC;IAE1B;;;;;;;;;;OAUG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,8BACsB,aAAa,CAAC,OAAO,SAAS,UAAU,GAAG,UAAU;IACvE;;;;OAIG;IAEH,QAAQ,CAAC,WAAW,cAAc;IAElC,6EAA6E;IACpE,MAAM,EAAG,OAAO,CAAC;IAC1B,kGAAkG;IACzF,aAAa,EAAG,iBAAiB,CAAC;IAC3C,qGAAqG;IAC5F,WAAW,CAAC,EAAE,WAAW,CAAC;IAEnC;;;;;OAKG;IACH,IAAW,QAAQ,IAAI,OAAO,CAE7B;IAED;;;;;;OAMG;IACI,QAAQ,IAAI,gBAAgB;IAQnC;;;;;OAKG;IACI,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAIhD;;OAEG;IACI,mBAAmB,CAAC,IAAI,EAAE,qBAAqB,GAAG,IAAI;IAI7D;;OAEG;IACI,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI/C;;;OAGG;IACI,oBAAoB,CAAC,GAAG,EAAE,kBAAkB,EAAE,SAAS,EAAE,OAAO,CAAC,qBAAqB,CAAC,GAAG,IAAI;IAIrG;;OAEG;IACI,eAAe,CAAC,GAAG,EAAE,kBAAkB,GAAG,IAAI;IAIrD;;OAEG;IACI,eAAe,CAAC,GAAG,EAAE,kBAAkB,GAAG,IAAI;IAIrD;;OAEG;IACI,kBAAkB,CAAC,GAAG,EAAE,kBAAkB,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAIzE;;OAEG;IACI,iBAAiB,CAAC,GAAG,EAAE,kBAAkB,GAAG,IAAI;IAIvD;;OAEG;IACI,mBAAmB,CAAC,GAAG,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;yCAxGtD,aAAa;2CAAb,aAAa;CA2GlC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-form-panel.js","sourceRoot":"","sources":["../../../src/lib/panel-slot/base-form-panel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAc,gBAAgB,EAAsB,MAAM,sBAAsB,CAAC;;AAqGxF;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,OAAgB,aAAa;IAC/B;;;;OAIG;IAEM,WAAW,GAAG,UAAU,CAAC;IAElC,6EAA6E;IACpE,MAAM,CAAW;IAC1B,kGAAkG;IACzF,aAAa,CAAqB;IAC3C,qGAAqG;IAC5F,WAAW,CAAe;IAEnC;;;;;OAKG;IACH,IAAW,QAAQ;QACf,OAAO,IAAI,CAAC,aAAa,EAAE,QAAQ,IAAI,KAAK,CAAC;IACjD,CAAC;IAED;;;;;;OAMG;IACI,QAAQ;QACX,6EAA6E;QAC7E,6DAA6D;QAC7D,MAAM,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAC;QACtC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;QACtB,OAAO,MAAM,CAAC;IAClB,CAAC;IAED;;;;;OAKG;IACI,iBAAiB,CAAC,OAAgB;QACrC,0BAA0B;IAC9B,CAAC;IAED;;OAEG;IACI,mBAAmB,CAAC,IAA2B;QAClD,IAAI,CAAC,aAAa,EAAE,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAClD,CAAC;IAED;;OAEG;IACI,qBAAqB,CAAC,GAAW;QACpC,IAAI,CAAC,aAAa,EAAE,qBAAqB,CAAC,GAAG,CAAC,CAAC;IACnD,CAAC;IAED;;;OAGG;IACI,oBAAoB,CAAC,GAAuB,EAAE,SAAyC;QAC1F,IAAI,CAAC,aAAa,EAAE,oBAAoB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAC7D,CAAC;IAED;;OAEG;IACI,eAAe,CAAC,GAAuB;QAC1C,IAAI,CAAC,aAAa,EAAE,eAAe,CAAC,GAAG,CAAC,CAAC;IAC7C,CAAC;IAED;;OAEG;IACI,eAAe,CAAC,GAAuB;QAC1C,IAAI,CAAC,aAAa,EAAE,eAAe,CAAC,GAAG,CAAC,CAAC;IAC7C,CAAC;IAED;;OAEG;IACI,kBAAkB,CAAC,GAAuB,EAAE,MAAe;QAC9D,IAAI,CAAC,aAAa,EAAE,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACxD,CAAC;IAED;;OAEG;IACI,iBAAiB,CAAC,GAAuB;QAC5C,IAAI,CAAC,aAAa,EAAE,iBAAiB,CAAC,GAAG,CAAC,CAAC;IAC/C,CAAC;IAED;;OAEG;IACI,mBAAmB,CAAC,GAAuB,EAAE,KAAa;QAC7D,IAAI,CAAC,aAAa,EAAE,mBAAmB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACxD,CAAC;uGA1GiB,aAAa;6DAAb,aAAa;YAAb,0CAAa;;;iFAAb,aAAa;cADlC,SAAS;;kBAOL,WAAW;mBAAC,eAAe;;kBAI3B,KAAK;;kBAEL,KAAK;;kBAEL,KAAK","sourcesContent":["import { Directive, HostBinding, Input } from '@angular/core';\nimport { BaseEntity, ValidationResult, type FormInclusion } from '@memberjunction/core';\nimport { BaseFormComponent } from '../base-form-component';\nimport { FormContext } from '../types/form-types';\nimport { FormToolbarItemConfig, FormToolbarItemKey } from '../types/form-toolbar-item';\n\n/**\n * Well-known slot positions where panels can be injected into a generated\n * entity form. Used as the `slot` field in a panel's registration metadata.\n *\n * Slot positions inside the form, top to bottom:\n *\n * ┌─ <mj-record-form-container>\n * │ [top-area slot] ← CodeGen-emitted; rare (entities with top-area section)\n * │ [before-fields slot] ← CodeGen-emitted; banners / warnings above field panels\n * │ <connection details>\n * │ <other generated field panels>\n * │ [after-fields slot] ← CodeGen-emitted; typed config knobs, secondary settings — most common slot\n * │ <content items grid>\n * │ <other related-entity grids>\n * │ [after-related slot] ← CodeGen-emitted; bottom-of-form addenda\n * │ [after-everything slot] ← Container-emitted; ALWAYS present (fallback target)\n * └─ </mj-record-form-container>\n *\n * Pick the slot that matches the panel's role. `after-fields` is the default\n * for most \"additional settings\" panels — it sits in the field column, before\n * the related-entity grids.\n *\n * **Fallback behavior** — see `FormSlotCoordinator`. If the registered slot is\n * missing in the current form (CodeGen hasn't been rerun against the new\n * template emitter), the panel walks forward in the chain until it finds an\n * existing slot. `after-everything` is always emitted by the container, so\n * fallback never dead-ends. Pre-CodeGen-regen forms show every panel at the\n * bottom of the form; post-regen forms show them in the preferred position.\n */\nexport type FormPanelSlot =\n | 'top-area'\n | 'before-fields'\n | 'after-fields'\n | 'after-related'\n | 'after-everything';\n\n/**\n * Shape of the `metadata` object every BaseFormPanel registration MUST attach\n * via `@RegisterClass(BaseFormPanel, { metadata: {...} })`. The\n * `<mj-form-panel-slot>` host filters registrations by matching against this\n * shape — registrations without it are silently ignored.\n *\n * - `entity` — the exact entity name (case-sensitive equality enforced by the\n * slot host), OR the wildcard `'*'` to register an\n * **entity-agnostic** panel that mounts on EVERY entity's form.\n * Wildcard panels are expected to self-hide (render nothing) when\n * they don't apply to the current record, so the cross-cutting\n * registration stays unobtrusive on forms it has no business on.\n * - `slot` — which slot the panel renders into.\n * - `sortKey`— higher = earlier within the slot. Defaults to 0 if omitted.\n * Use ranges (e.g., 100/50/10) so future panels can wedge in\n * without recomputing every neighbor's sort.\n */\nexport interface FormPanelRegistrationMetadata extends Record<string, unknown> {\n entity: string;\n slot: FormPanelSlot;\n sortKey?: number;\n /**\n * Identity for last-wins collapse. Two registrations with the same key\n * compete; highest ClassFactory `Priority` wins. Omit to derive:\n * `related:${relatedEntity}:${relatedJoinField}` when claiming a\n * relationship, otherwise the registration is unique and never collapses.\n */\n contributionKey?: string;\n /**\n * When set, this panel **replaces** the default related-entity grid for\n * that relationship on `entity`'s form. The baked CodeGen panel (if any)\n * is hidden; the stock fill-in grid is not mounted.\n */\n relatedEntity?: string;\n /**\n * Disambiguates two FKs to the same related entity (BillTo vs ShipTo).\n * Compared after stripping wrapping `[]`.\n */\n relatedJoinField?: string;\n /**\n * CodeGen `SectionKey` of a baked field (or other) panel this contribution\n * replaces — e.g. `'details'`, `'personalIdentity'`. Hidden at runtime via\n * `HiddenSectionKeys`. Use with `slot: 'before-fields'` for a form hero that\n * is not a collapsible panel. Must name a concrete `entity` (not `'*'`).\n */\n replacesSectionKey?: string;\n /**\n * Pin this contribution to a chrome bucket instead of its own rail item.\n * `'details'` — leftover own-fields group. `'more'` — overflow folder.\n */\n chromeGroup?: 'details' | 'more';\n /**\n * L1 inclusion for this contribution (same verbs as relationships).\n * `'Primary'` — own first-class rail item, in the lead band before Details.\n * `'More'` — overflow folder. `'None'` — hidden.\n * L3 `MJ: Form Chrome Rules` still wins. `chromeGroup` still merges.\n */\n inclusion?: FormInclusion;\n}\n\n/**\n * Abstract base for every dynamically-injectable form panel.\n *\n * Subclasses are standalone Angular components decorated with\n * `@RegisterClass(BaseFormPanel, { metadata: { entity, slot, sortKey? } })`.\n * At runtime, `<mj-form-panel-slot>` discovers matching registrations via\n * `ClassFactory.GetAllRegistrationsByMetadata`, instantiates each via\n * `ViewContainerRef.createComponent`, and wires `Record` + `FormComponent` +\n * `FormContext` into the inputs.\n *\n * Lifecycle hooks: standard Angular `ngOnInit` / `ngOnDestroy` work as usual.\n * `Record` is guaranteed to be set before the first change-detection pass.\n *\n * Optional `validate()` returns a synchronous validation result; the parent\n * `BaseFormComponent.Save()` path will surface it via the existing validation\n * pipeline when called. Panels that don't validate anything beyond what the\n * record itself does can leave this method off.\n */\n@Directive()\nexport abstract class BaseFormPanel<TRecord extends BaseEntity = BaseEntity> {\n /**\n * Slot-mounted hosts must not sit in the left-nav flex column — leftover\n * height targets `mj-collapsible-panel` as a direct child of\n * `.mj-forms-all-panels`. `display: contents` makes the inner panel that child.\n */\n @HostBinding('style.display')\n readonly HostDisplay = 'contents';\n\n /** The entity record being edited. Set by the slot host before view init. */\n @Input() Record!: TRecord;\n /** The host form component (use for EditMode, dirty notifications, etc). Set by the slot host. */\n @Input() FormComponent!: BaseFormComponent;\n /** Optional form context — same shape the collapsible-panel chrome expects. Set by the slot host. */\n @Input() FormContext?: FormContext;\n\n /**\n * Convenience getter for read-only / edit-mode rendering. Falls back to\n * `false` when the panel is shown outside a `BaseFormComponent` host (e.g.,\n * a dashboard quick-edit dialog reusing the same panel — see the\n * \"composable panel\" docs).\n */\n public get EditMode(): boolean {\n return this.FormComponent?.EditMode ?? false;\n }\n\n /**\n * Override to add per-panel validation that should block the parent form's\n * Save(). Return `{ Success: true, Errors: [] }` when valid, or include\n * `ValidationErrorInfo` entries to surface field-level errors. The default\n * implementation reports valid (panels that don't need extra validation\n * can leave this method off).\n */\n public validate(): ValidationResult {\n // Inline construction — ValidationResult is a class in @memberjunction/core,\n // not a plain interface, so callers can construct via `new`.\n const result = new ValidationResult();\n result.Success = true;\n return result;\n }\n\n /**\n * Called after the parent form reloads the current record from the database.\n * Default is a no-op. Override to refresh panel-owned data that is not a\n * related-entity grid (those already subscribe to\n * {@link FormRecordRefreshCoordinator} themselves).\n */\n public OnRecordRefreshed(_record: TRecord): void {\n // Subclasses can override\n }\n\n /**\n * Registers a dynamic toolbar action item / button into the host form toolbar.\n */\n public RegisterToolbarItem(item: FormToolbarItemConfig): void {\n this.FormComponent?.RegisterToolbarItem(item);\n }\n\n /**\n * Unregisters a previously registered dynamic toolbar item by key.\n */\n public UnregisterToolbarItem(key: string): void {\n this.FormComponent?.UnregisterToolbarItem(key);\n }\n\n /**\n * Configures overrides for any toolbar item (standard built-in items like 'edit',\n * 'delete', 'favorite', 'history', etc., or custom items).\n */\n public ConfigureToolbarItem(key: FormToolbarItemKey, overrides: Partial<FormToolbarItemConfig>): void {\n this.FormComponent?.ConfigureToolbarItem(key, overrides);\n }\n\n /**\n * Dynamically hides a toolbar item by key.\n */\n public HideToolbarItem(key: FormToolbarItemKey): void {\n this.FormComponent?.HideToolbarItem(key);\n }\n\n /**\n * Dynamically shows a toolbar item by key.\n */\n public ShowToolbarItem(key: FormToolbarItemKey): void {\n this.FormComponent?.ShowToolbarItem(key);\n }\n\n /**\n * Dynamically disables a toolbar item by key, with an optional reason string for the tooltip.\n */\n public DisableToolbarItem(key: FormToolbarItemKey, reason?: string): void {\n this.FormComponent?.DisableToolbarItem(key, reason);\n }\n\n /**\n * Dynamically enables a toolbar item by key.\n */\n public EnableToolbarItem(key: FormToolbarItemKey): void {\n this.FormComponent?.EnableToolbarItem(key);\n }\n\n /**\n * Sets the numeric display order for a toolbar item.\n */\n public SetToolbarItemOrder(key: FormToolbarItemKey, order: number): void {\n this.FormComponent?.SetToolbarItemOrder(key, order);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"base-form-panel.js","sourceRoot":"","sources":["../../../src/lib/panel-slot/base-form-panel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAc,gBAAgB,EAAsB,MAAM,sBAAsB,CAAC;;AAkHxF;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,OAAgB,aAAa;IAC/B;;;;OAIG;IAEM,WAAW,GAAG,UAAU,CAAC;IAElC,6EAA6E;IACpE,MAAM,CAAW;IAC1B,kGAAkG;IACzF,aAAa,CAAqB;IAC3C,qGAAqG;IAC5F,WAAW,CAAe;IAEnC;;;;;OAKG;IACH,IAAW,QAAQ;QACf,OAAO,IAAI,CAAC,aAAa,EAAE,QAAQ,IAAI,KAAK,CAAC;IACjD,CAAC;IAED;;;;;;OAMG;IACI,QAAQ;QACX,6EAA6E;QAC7E,6DAA6D;QAC7D,MAAM,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAC;QACtC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;QACtB,OAAO,MAAM,CAAC;IAClB,CAAC;IAED;;;;;OAKG;IACI,iBAAiB,CAAC,OAAgB;QACrC,0BAA0B;IAC9B,CAAC;IAED;;OAEG;IACI,mBAAmB,CAAC,IAA2B;QAClD,IAAI,CAAC,aAAa,EAAE,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAClD,CAAC;IAED;;OAEG;IACI,qBAAqB,CAAC,GAAW;QACpC,IAAI,CAAC,aAAa,EAAE,qBAAqB,CAAC,GAAG,CAAC,CAAC;IACnD,CAAC;IAED;;;OAGG;IACI,oBAAoB,CAAC,GAAuB,EAAE,SAAyC;QAC1F,IAAI,CAAC,aAAa,EAAE,oBAAoB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAC7D,CAAC;IAED;;OAEG;IACI,eAAe,CAAC,GAAuB;QAC1C,IAAI,CAAC,aAAa,EAAE,eAAe,CAAC,GAAG,CAAC,CAAC;IAC7C,CAAC;IAED;;OAEG;IACI,eAAe,CAAC,GAAuB;QAC1C,IAAI,CAAC,aAAa,EAAE,eAAe,CAAC,GAAG,CAAC,CAAC;IAC7C,CAAC;IAED;;OAEG;IACI,kBAAkB,CAAC,GAAuB,EAAE,MAAe;QAC9D,IAAI,CAAC,aAAa,EAAE,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACxD,CAAC;IAED;;OAEG;IACI,iBAAiB,CAAC,GAAuB;QAC5C,IAAI,CAAC,aAAa,EAAE,iBAAiB,CAAC,GAAG,CAAC,CAAC;IAC/C,CAAC;IAED;;OAEG;IACI,mBAAmB,CAAC,GAAuB,EAAE,KAAa;QAC7D,IAAI,CAAC,aAAa,EAAE,mBAAmB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACxD,CAAC;uGA1GiB,aAAa;6DAAb,aAAa;YAAb,0CAAa;;;iFAAb,aAAa;cADlC,SAAS;;kBAOL,WAAW;mBAAC,eAAe;;kBAI3B,KAAK;;kBAEL,KAAK;;kBAEL,KAAK","sourcesContent":["import { Directive, HostBinding, Input } from '@angular/core';\nimport { BaseEntity, ValidationResult, type FormInclusion } from '@memberjunction/core';\nimport { BaseFormComponent } from '../base-form-component';\nimport { FormContext } from '../types/form-types';\nimport { FormToolbarItemConfig, FormToolbarItemKey } from '../types/form-toolbar-item';\n\n/**\n * Well-known slot positions where panels can be injected into a generated\n * entity form. Used as the `slot` field in a panel's registration metadata.\n *\n * Slot positions inside the form, top to bottom:\n *\n * ┌─ <mj-record-form-container>\n * │ [top-area slot] ← CodeGen-emitted; rare (entities with top-area section)\n * │ [before-fields slot] ← CodeGen-emitted; banners / warnings above field panels\n * │ <connection details>\n * │ <other generated field panels>\n * │ [after-fields slot] ← CodeGen-emitted; typed config knobs, secondary settings — most common slot\n * │ <content items grid>\n * │ <other related-entity grids>\n * │ [after-related slot] ← CodeGen-emitted; bottom-of-form addenda\n * │ [after-everything slot] ← Container-emitted; ALWAYS present (fallback target)\n * └─ </mj-record-form-container>\n *\n * Pick the slot that matches the panel's role. `after-fields` is the default\n * for most \"additional settings\" panels — it sits in the field column, before\n * the related-entity grids.\n *\n * **Fallback behavior** — see `FormSlotCoordinator`. If the registered slot is\n * missing in the current form (CodeGen hasn't been rerun against the new\n * template emitter), the panel walks forward in the chain until it finds an\n * existing slot. `after-everything` is always emitted by the container, so\n * fallback never dead-ends. Pre-CodeGen-regen forms show every panel at the\n * bottom of the form; post-regen forms show them in the preferred position.\n */\nexport type FormPanelSlot =\n | 'top-area'\n | 'before-fields'\n | 'after-fields'\n | 'after-related'\n | 'after-everything';\n\n/**\n * Shape of the `metadata` object every BaseFormPanel registration MUST attach\n * via `@RegisterClass(BaseFormPanel, { metadata: {...} })`. The\n * `<mj-form-panel-slot>` host filters registrations by matching against this\n * shape — registrations without it are silently ignored.\n *\n * - `entity` — the exact entity name (case-sensitive equality enforced by the\n * slot host), OR the wildcard `'*'` to register an\n * **entity-agnostic** panel that mounts on EVERY entity's form.\n * Wildcard panels are expected to self-hide (render nothing) when\n * they don't apply to the current record, so the cross-cutting\n * registration stays unobtrusive on forms it has no business on.\n * - `slot` — which slot the panel renders into.\n * - `sortKey`— higher = earlier within the slot. Defaults to 0 if omitted.\n * Use ranges (e.g., 100/50/10) so future panels can wedge in\n * without recomputing every neighbor's sort.\n */\nexport interface FormPanelRegistrationMetadata extends Record<string, unknown> {\n entity: string;\n slot: FormPanelSlot;\n sortKey?: number;\n /**\n * Identity for last-wins collapse. Two registrations with the same key\n * compete; highest ClassFactory `Priority` wins. Omit to derive:\n * `related:${relatedEntity}:${relatedJoinField}` when claiming a\n * relationship, otherwise the registration is unique and never collapses.\n */\n contributionKey?: string;\n /**\n * When set, this panel **replaces** the default related-entity grid for\n * that relationship on `entity`'s form. The baked CodeGen panel (if any)\n * is hidden; the stock fill-in grid is not mounted.\n */\n relatedEntity?: string;\n /**\n * Disambiguates two FKs to the same related entity (BillTo vs ShipTo).\n * Compared after stripping wrapping `[]`.\n */\n relatedJoinField?: string;\n /**\n * CodeGen `SectionKey` of a baked field (or other) panel this contribution\n * replaces — e.g. `'details'`, `'personalIdentity'`. Hidden at runtime via\n * `HiddenSectionKeys`. Use with `slot: 'before-fields'` for a form hero that\n * is not a collapsible panel. Must name a concrete `entity` (not `'*'`).\n */\n replacesSectionKey?: string;\n /**\n * Pin this contribution to a chrome bucket instead of its own rail item.\n * `'details'` — leftover own-fields group. `'more'` — overflow folder.\n */\n chromeGroup?: 'details' | 'more';\n /**\n * L1 inclusion for this contribution (same verbs as relationships).\n * `'Primary'` — own first-class rail item, in the lead band before Details.\n * `'More'` — overflow folder. `'None'` — hidden.\n * L3 `MJ: Form Chrome Rules` still wins. `chromeGroup` still merges.\n */\n inclusion?: FormInclusion;\n\n /**\n * Open a NEW (unsaved) record on this contribution instead of the first first-class group.\n *\n * A saved record opens where the user last was, or on the lead group. That is right for reading a\n * record and wrong for creating one: the lead group is usually a summary, and a summary of a record\n * with no data is a page of blanks the user has to look past to find where typing starts.\n *\n * Only consulted when the record is unsaved, so it cannot change how an existing record opens.\n * If several contributions on one entity set it, the highest ClassFactory `Priority` wins, matching\n * how every other conflict between registrations is settled.\n */\n leadsWhenUnsaved?: boolean;\n}\n\n/**\n * Abstract base for every dynamically-injectable form panel.\n *\n * Subclasses are standalone Angular components decorated with\n * `@RegisterClass(BaseFormPanel, { metadata: { entity, slot, sortKey? } })`.\n * At runtime, `<mj-form-panel-slot>` discovers matching registrations via\n * `ClassFactory.GetAllRegistrationsByMetadata`, instantiates each via\n * `ViewContainerRef.createComponent`, and wires `Record` + `FormComponent` +\n * `FormContext` into the inputs.\n *\n * Lifecycle hooks: standard Angular `ngOnInit` / `ngOnDestroy` work as usual.\n * `Record` is guaranteed to be set before the first change-detection pass.\n *\n * Optional `validate()` returns a synchronous validation result; the parent\n * `BaseFormComponent.Save()` path will surface it via the existing validation\n * pipeline when called. Panels that don't validate anything beyond what the\n * record itself does can leave this method off.\n */\n@Directive()\nexport abstract class BaseFormPanel<TRecord extends BaseEntity = BaseEntity> {\n /**\n * Slot-mounted hosts must not sit in the left-nav flex column — leftover\n * height targets `mj-collapsible-panel` as a direct child of\n * `.mj-forms-all-panels`. `display: contents` makes the inner panel that child.\n */\n @HostBinding('style.display')\n readonly HostDisplay = 'contents';\n\n /** The entity record being edited. Set by the slot host before view init. */\n @Input() Record!: TRecord;\n /** The host form component (use for EditMode, dirty notifications, etc). Set by the slot host. */\n @Input() FormComponent!: BaseFormComponent;\n /** Optional form context — same shape the collapsible-panel chrome expects. Set by the slot host. */\n @Input() FormContext?: FormContext;\n\n /**\n * Convenience getter for read-only / edit-mode rendering. Falls back to\n * `false` when the panel is shown outside a `BaseFormComponent` host (e.g.,\n * a dashboard quick-edit dialog reusing the same panel — see the\n * \"composable panel\" docs).\n */\n public get EditMode(): boolean {\n return this.FormComponent?.EditMode ?? false;\n }\n\n /**\n * Override to add per-panel validation that should block the parent form's\n * Save(). Return `{ Success: true, Errors: [] }` when valid, or include\n * `ValidationErrorInfo` entries to surface field-level errors. The default\n * implementation reports valid (panels that don't need extra validation\n * can leave this method off).\n */\n public validate(): ValidationResult {\n // Inline construction — ValidationResult is a class in @memberjunction/core,\n // not a plain interface, so callers can construct via `new`.\n const result = new ValidationResult();\n result.Success = true;\n return result;\n }\n\n /**\n * Called after the parent form reloads the current record from the database.\n * Default is a no-op. Override to refresh panel-owned data that is not a\n * related-entity grid (those already subscribe to\n * {@link FormRecordRefreshCoordinator} themselves).\n */\n public OnRecordRefreshed(_record: TRecord): void {\n // Subclasses can override\n }\n\n /**\n * Registers a dynamic toolbar action item / button into the host form toolbar.\n */\n public RegisterToolbarItem(item: FormToolbarItemConfig): void {\n this.FormComponent?.RegisterToolbarItem(item);\n }\n\n /**\n * Unregisters a previously registered dynamic toolbar item by key.\n */\n public UnregisterToolbarItem(key: string): void {\n this.FormComponent?.UnregisterToolbarItem(key);\n }\n\n /**\n * Configures overrides for any toolbar item (standard built-in items like 'edit',\n * 'delete', 'favorite', 'history', etc., or custom items).\n */\n public ConfigureToolbarItem(key: FormToolbarItemKey, overrides: Partial<FormToolbarItemConfig>): void {\n this.FormComponent?.ConfigureToolbarItem(key, overrides);\n }\n\n /**\n * Dynamically hides a toolbar item by key.\n */\n public HideToolbarItem(key: FormToolbarItemKey): void {\n this.FormComponent?.HideToolbarItem(key);\n }\n\n /**\n * Dynamically shows a toolbar item by key.\n */\n public ShowToolbarItem(key: FormToolbarItemKey): void {\n this.FormComponent?.ShowToolbarItem(key);\n }\n\n /**\n * Dynamically disables a toolbar item by key, with an optional reason string for the tooltip.\n */\n public DisableToolbarItem(key: FormToolbarItemKey, reason?: string): void {\n this.FormComponent?.DisableToolbarItem(key, reason);\n }\n\n /**\n * Dynamically enables a toolbar item by key.\n */\n public EnableToolbarItem(key: FormToolbarItemKey): void {\n this.FormComponent?.EnableToolbarItem(key);\n }\n\n /**\n * Sets the numeric display order for a toolbar item.\n */\n public SetToolbarItemOrder(key: FormToolbarItemKey, order: number): void {\n this.FormComponent?.SetToolbarItemOrder(key, order);\n }\n}\n"]}
|
|
@@ -1,20 +1,57 @@
|
|
|
1
|
-
/** Toolbar row
|
|
2
|
-
export declare const RELATED_GRID_TOOLBAR_PX =
|
|
3
|
-
/**
|
|
4
|
-
|
|
1
|
+
/** Toolbar row: 48px content + its 1px bottom border (measured live). */
|
|
2
|
+
export declare const RELATED_GRID_TOOLBAR_PX = 49;
|
|
3
|
+
/**
|
|
4
|
+
* Column header row as AG Grid's theme renders it: `--ag-header-height` (48px in v35's
|
|
5
|
+
* default theme) + its 1px bottom border (measured live). This was 40px, which left every
|
|
6
|
+
* related grid 9px short and clipped the last row's bottom border even with no horizontal
|
|
7
|
+
* overflow.
|
|
8
|
+
*/
|
|
9
|
+
export declare const RELATED_GRID_HEADER_PX = 49;
|
|
5
10
|
/** One data row. */
|
|
6
11
|
export declare const RELATED_GRID_ROW_PX = 40;
|
|
7
|
-
/**
|
|
8
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Wrapper chrome the grid body never gets: the component wrapper's top+bottom
|
|
14
|
+
* border (2px) plus ag-root-wrapper's top+bottom border (2px). Unbudgeted,
|
|
15
|
+
* these four pixels squeeze the body viewport below the row total and AG Grid
|
|
16
|
+
* answers with a needless vertical scrollbar.
|
|
17
|
+
*/
|
|
18
|
+
export declare const RELATED_GRID_BORDERS_PX = 4;
|
|
19
|
+
/** Small slack so the last row's bottom border is never clipped by the grid edge. */
|
|
20
|
+
export declare const RELATED_GRID_BOTTOM_PAD_PX = 2;
|
|
21
|
+
/**
|
|
22
|
+
* AG Grid's horizontal scrollbar. It renders INSIDE the grid viewport, so when
|
|
23
|
+
* columns overflow (the norm for wide related entities inside a form panel) an
|
|
24
|
+
* unbudgeted bar eats the last row's height and clips it mid-glyph. Classic
|
|
25
|
+
* scrollbars are 15–17px; overlay scrollbars cost the reserve as a little slack.
|
|
26
|
+
*
|
|
27
|
+
* This is the FALLBACK reserve, used only by callers that do not measure the bar.
|
|
28
|
+
* `<mj-explorer-entity-data-grid>` measures it from the DOM after layout and passes
|
|
29
|
+
* the real height (0 when the columns fit, or on overlay-scrollbar platforms) as
|
|
30
|
+
* `scrollbarPx`, which replaces this reserve entirely. Reserved only when rows are
|
|
31
|
+
* shown — with zero rows there is no row to clip.
|
|
32
|
+
*/
|
|
33
|
+
export declare const RELATED_GRID_HSCROLLBAR_PX = 17;
|
|
9
34
|
/** Empty-state body when there are no rows (inline icon + title, no 200px floor). */
|
|
10
35
|
export declare const RELATED_GRID_EMPTY_BODY_PX = 56;
|
|
11
36
|
/** Default cap for nav-related grids. `null` on the input means unbounded. */
|
|
12
37
|
export declare const RELATED_GRID_DEFAULT_MAX_PX = 560;
|
|
13
38
|
/**
|
|
14
|
-
* Pixel height for a related-entity grid: toolbar + header + rows +
|
|
15
|
-
* small bottom pad. No minimum
|
|
16
|
-
* number and the content is taller, the
|
|
17
|
-
* AG Grid scrolls inside. Omit / null
|
|
39
|
+
* Pixel height for a related-entity grid: toolbar + header + rows + border
|
|
40
|
+
* chrome + a horizontal-scrollbar allowance + a small bottom pad. No minimum
|
|
41
|
+
* floor. When `maxHeight` is a positive number and the content is taller, the
|
|
42
|
+
* returned height is that cap and AG Grid scrolls inside. Omit / null
|
|
43
|
+
* `maxHeight` to grow with the rows.
|
|
44
|
+
*
|
|
45
|
+
* `scrollbarPx` is the MEASURED height of AG Grid's horizontal scrollbar. AG Grid
|
|
46
|
+
* lays that scrollbar out INSIDE the box it is given, so when the columns overflow
|
|
47
|
+
* the container it eats into the last row unless it is budgeted here. A caller that
|
|
48
|
+
* has measured it passes the number — 0 when there is no horizontal overflow, or
|
|
49
|
+
* when the platform draws overlay scrollbars that take no layout space — and that
|
|
50
|
+
* measurement replaces the fixed reserve. A caller that has not measured it omits
|
|
51
|
+
* the argument and gets `RELATED_GRID_HSCROLLBAR_PX` whenever rows are shown, so
|
|
52
|
+
* an unmeasured grid never clips a row on a classic-scrollbar platform. A negative
|
|
53
|
+
* or non-finite value is not a measurement and falls back the same way. The
|
|
54
|
+
* allowance never pushes the result past `maxHeight`.
|
|
18
55
|
*/
|
|
19
|
-
export declare function RelatedGridHeightPx(rowCount: number, maxHeight?: number | null): number;
|
|
56
|
+
export declare function RelatedGridHeightPx(rowCount: number, maxHeight?: number | null, scrollbarPx?: number): number;
|
|
20
57
|
//# sourceMappingURL=related-grid-height.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"related-grid-height.d.ts","sourceRoot":"","sources":["../../src/lib/related-grid-height.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"related-grid-height.d.ts","sourceRoot":"","sources":["../../src/lib/related-grid-height.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,KAAK,CAAC;AACzC,oBAAoB;AACpB,eAAO,MAAM,mBAAmB,KAAK,CAAC;AACtC;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,qFAAqF;AACrF,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAC5C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAC7C,qFAAqF;AACrF,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAC7C,8EAA8E;AAC9E,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAE/C;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAc7G"}
|
|
@@ -1,27 +1,68 @@
|
|
|
1
|
-
/** Toolbar row
|
|
2
|
-
export const RELATED_GRID_TOOLBAR_PX =
|
|
3
|
-
/**
|
|
4
|
-
|
|
1
|
+
/** Toolbar row: 48px content + its 1px bottom border (measured live). */
|
|
2
|
+
export const RELATED_GRID_TOOLBAR_PX = 49;
|
|
3
|
+
/**
|
|
4
|
+
* Column header row as AG Grid's theme renders it: `--ag-header-height` (48px in v35's
|
|
5
|
+
* default theme) + its 1px bottom border (measured live). This was 40px, which left every
|
|
6
|
+
* related grid 9px short and clipped the last row's bottom border even with no horizontal
|
|
7
|
+
* overflow.
|
|
8
|
+
*/
|
|
9
|
+
export const RELATED_GRID_HEADER_PX = 49;
|
|
5
10
|
/** One data row. */
|
|
6
11
|
export const RELATED_GRID_ROW_PX = 40;
|
|
7
|
-
/**
|
|
8
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Wrapper chrome the grid body never gets: the component wrapper's top+bottom
|
|
14
|
+
* border (2px) plus ag-root-wrapper's top+bottom border (2px). Unbudgeted,
|
|
15
|
+
* these four pixels squeeze the body viewport below the row total and AG Grid
|
|
16
|
+
* answers with a needless vertical scrollbar.
|
|
17
|
+
*/
|
|
18
|
+
export const RELATED_GRID_BORDERS_PX = 4;
|
|
19
|
+
/** Small slack so the last row's bottom border is never clipped by the grid edge. */
|
|
20
|
+
export const RELATED_GRID_BOTTOM_PAD_PX = 2;
|
|
21
|
+
/**
|
|
22
|
+
* AG Grid's horizontal scrollbar. It renders INSIDE the grid viewport, so when
|
|
23
|
+
* columns overflow (the norm for wide related entities inside a form panel) an
|
|
24
|
+
* unbudgeted bar eats the last row's height and clips it mid-glyph. Classic
|
|
25
|
+
* scrollbars are 15–17px; overlay scrollbars cost the reserve as a little slack.
|
|
26
|
+
*
|
|
27
|
+
* This is the FALLBACK reserve, used only by callers that do not measure the bar.
|
|
28
|
+
* `<mj-explorer-entity-data-grid>` measures it from the DOM after layout and passes
|
|
29
|
+
* the real height (0 when the columns fit, or on overlay-scrollbar platforms) as
|
|
30
|
+
* `scrollbarPx`, which replaces this reserve entirely. Reserved only when rows are
|
|
31
|
+
* shown — with zero rows there is no row to clip.
|
|
32
|
+
*/
|
|
33
|
+
export const RELATED_GRID_HSCROLLBAR_PX = 17;
|
|
9
34
|
/** Empty-state body when there are no rows (inline icon + title, no 200px floor). */
|
|
10
35
|
export const RELATED_GRID_EMPTY_BODY_PX = 56;
|
|
11
36
|
/** Default cap for nav-related grids. `null` on the input means unbounded. */
|
|
12
37
|
export const RELATED_GRID_DEFAULT_MAX_PX = 560;
|
|
13
38
|
/**
|
|
14
|
-
* Pixel height for a related-entity grid: toolbar + header + rows +
|
|
15
|
-
* small bottom pad. No minimum
|
|
16
|
-
* number and the content is taller, the
|
|
17
|
-
* AG Grid scrolls inside. Omit / null
|
|
39
|
+
* Pixel height for a related-entity grid: toolbar + header + rows + border
|
|
40
|
+
* chrome + a horizontal-scrollbar allowance + a small bottom pad. No minimum
|
|
41
|
+
* floor. When `maxHeight` is a positive number and the content is taller, the
|
|
42
|
+
* returned height is that cap and AG Grid scrolls inside. Omit / null
|
|
43
|
+
* `maxHeight` to grow with the rows.
|
|
44
|
+
*
|
|
45
|
+
* `scrollbarPx` is the MEASURED height of AG Grid's horizontal scrollbar. AG Grid
|
|
46
|
+
* lays that scrollbar out INSIDE the box it is given, so when the columns overflow
|
|
47
|
+
* the container it eats into the last row unless it is budgeted here. A caller that
|
|
48
|
+
* has measured it passes the number — 0 when there is no horizontal overflow, or
|
|
49
|
+
* when the platform draws overlay scrollbars that take no layout space — and that
|
|
50
|
+
* measurement replaces the fixed reserve. A caller that has not measured it omits
|
|
51
|
+
* the argument and gets `RELATED_GRID_HSCROLLBAR_PX` whenever rows are shown, so
|
|
52
|
+
* an unmeasured grid never clips a row on a classic-scrollbar platform. A negative
|
|
53
|
+
* or non-finite value is not a measurement and falls back the same way. The
|
|
54
|
+
* allowance never pushes the result past `maxHeight`.
|
|
18
55
|
*/
|
|
19
|
-
export function RelatedGridHeightPx(rowCount, maxHeight) {
|
|
56
|
+
export function RelatedGridHeightPx(rowCount, maxHeight, scrollbarPx) {
|
|
20
57
|
const rows = Number.isFinite(rowCount) ? Math.max(0, Math.floor(rowCount)) : 0;
|
|
58
|
+
const measured = typeof scrollbarPx === 'number' && Number.isFinite(scrollbarPx) && scrollbarPx >= 0;
|
|
59
|
+
const scrollbar = measured
|
|
60
|
+
? Math.round(scrollbarPx)
|
|
61
|
+
: (rows === 0 ? 0 : RELATED_GRID_HSCROLLBAR_PX);
|
|
21
62
|
const body = rows === 0
|
|
22
63
|
? RELATED_GRID_EMPTY_BODY_PX
|
|
23
64
|
: RELATED_GRID_HEADER_PX + rows * RELATED_GRID_ROW_PX;
|
|
24
|
-
const raw = RELATED_GRID_TOOLBAR_PX + body + RELATED_GRID_BOTTOM_PAD_PX;
|
|
65
|
+
const raw = RELATED_GRID_TOOLBAR_PX + body + RELATED_GRID_BORDERS_PX + RELATED_GRID_BOTTOM_PAD_PX + scrollbar;
|
|
25
66
|
if (typeof maxHeight === 'number' && maxHeight > 0) {
|
|
26
67
|
return Math.min(maxHeight, raw);
|
|
27
68
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"related-grid-height.js","sourceRoot":"","sources":["../../src/lib/related-grid-height.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"related-grid-height.js","sourceRoot":"","sources":["../../src/lib/related-grid-height.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,CAAC;AAC1C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,CAAC;AACzC,oBAAoB;AACpB,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,CAAC;AACtC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC;AACzC,qFAAqF;AACrF,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC;AAC5C;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,CAAC;AAC7C,qFAAqF;AACrF,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,CAAC;AAC7C,8EAA8E;AAC9E,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC;AAE/C;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB,EAAE,SAAyB,EAAE,WAAoB;IACjG,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/E,MAAM,QAAQ,GAAG,OAAO,WAAW,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,WAAW,IAAI,CAAC,CAAC;IACrG,MAAM,SAAS,GAAG,QAAQ;QACtB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC;QACzB,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,IAAI,KAAK,CAAC;QACnB,CAAC,CAAC,0BAA0B;QAC5B,CAAC,CAAC,sBAAsB,GAAG,IAAI,GAAG,mBAAmB,CAAC;IAC1D,MAAM,GAAG,GAAG,uBAAuB,GAAG,IAAI,GAAG,uBAAuB,GAAG,0BAA0B,GAAG,SAAS,CAAC;IAC9G,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QACjD,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC","sourcesContent":["/** Toolbar row: 48px content + its 1px bottom border (measured live). */\nexport const RELATED_GRID_TOOLBAR_PX = 49;\n/**\n * Column header row as AG Grid's theme renders it: `--ag-header-height` (48px in v35's\n * default theme) + its 1px bottom border (measured live). This was 40px, which left every\n * related grid 9px short and clipped the last row's bottom border even with no horizontal\n * overflow.\n */\nexport const RELATED_GRID_HEADER_PX = 49;\n/** One data row. */\nexport const RELATED_GRID_ROW_PX = 40;\n/**\n * Wrapper chrome the grid body never gets: the component wrapper's top+bottom\n * border (2px) plus ag-root-wrapper's top+bottom border (2px). Unbudgeted,\n * these four pixels squeeze the body viewport below the row total and AG Grid\n * answers with a needless vertical scrollbar.\n */\nexport const RELATED_GRID_BORDERS_PX = 4;\n/** Small slack so the last row's bottom border is never clipped by the grid edge. */\nexport const RELATED_GRID_BOTTOM_PAD_PX = 2;\n/**\n * AG Grid's horizontal scrollbar. It renders INSIDE the grid viewport, so when\n * columns overflow (the norm for wide related entities inside a form panel) an\n * unbudgeted bar eats the last row's height and clips it mid-glyph. Classic\n * scrollbars are 15–17px; overlay scrollbars cost the reserve as a little slack.\n *\n * This is the FALLBACK reserve, used only by callers that do not measure the bar.\n * `<mj-explorer-entity-data-grid>` measures it from the DOM after layout and passes\n * the real height (0 when the columns fit, or on overlay-scrollbar platforms) as\n * `scrollbarPx`, which replaces this reserve entirely. Reserved only when rows are\n * shown — with zero rows there is no row to clip.\n */\nexport const RELATED_GRID_HSCROLLBAR_PX = 17;\n/** Empty-state body when there are no rows (inline icon + title, no 200px floor). */\nexport const RELATED_GRID_EMPTY_BODY_PX = 56;\n/** Default cap for nav-related grids. `null` on the input means unbounded. */\nexport const RELATED_GRID_DEFAULT_MAX_PX = 560;\n\n/**\n * Pixel height for a related-entity grid: toolbar + header + rows + border\n * chrome + a horizontal-scrollbar allowance + a small bottom pad. No minimum\n * floor. When `maxHeight` is a positive number and the content is taller, the\n * returned height is that cap and AG Grid scrolls inside. Omit / null\n * `maxHeight` to grow with the rows.\n *\n * `scrollbarPx` is the MEASURED height of AG Grid's horizontal scrollbar. AG Grid\n * lays that scrollbar out INSIDE the box it is given, so when the columns overflow\n * the container it eats into the last row unless it is budgeted here. A caller that\n * has measured it passes the number — 0 when there is no horizontal overflow, or\n * when the platform draws overlay scrollbars that take no layout space — and that\n * measurement replaces the fixed reserve. A caller that has not measured it omits\n * the argument and gets `RELATED_GRID_HSCROLLBAR_PX` whenever rows are shown, so\n * an unmeasured grid never clips a row on a classic-scrollbar platform. A negative\n * or non-finite value is not a measurement and falls back the same way. The\n * allowance never pushes the result past `maxHeight`.\n */\nexport function RelatedGridHeightPx(rowCount: number, maxHeight?: number | null, scrollbarPx?: number): number {\n const rows = Number.isFinite(rowCount) ? Math.max(0, Math.floor(rowCount)) : 0;\n const measured = typeof scrollbarPx === 'number' && Number.isFinite(scrollbarPx) && scrollbarPx >= 0;\n const scrollbar = measured\n ? Math.round(scrollbarPx)\n : (rows === 0 ? 0 : RELATED_GRID_HSCROLLBAR_PX);\n const body = rows === 0\n ? RELATED_GRID_EMPTY_BODY_PX\n : RELATED_GRID_HEADER_PX + rows * RELATED_GRID_ROW_PX;\n const raw = RELATED_GRID_TOOLBAR_PX + body + RELATED_GRID_BORDERS_PX + RELATED_GRID_BOTTOM_PAD_PX + scrollbar;\n if (typeof maxHeight === 'number' && maxHeight > 0) {\n return Math.min(maxHeight, raw);\n }\n return raw;\n}\n"]}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Subject } from 'rxjs';
|
|
2
|
+
import { ValidationErrorInfo } from '@memberjunction/global';
|
|
3
|
+
import { type FormSectionIndicators, type ParsedValidationSource } from './form-section-indicators';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
/**
|
|
6
|
+
* Anything that can answer "what is the state of section X right now".
|
|
7
|
+
*
|
|
8
|
+
* `mj-collapsible-panel` implements this for every section it renders, deriving the
|
|
9
|
+
* counts from its `mj-form-field` children. A custom section that is NOT a collapsible
|
|
10
|
+
* panel — a hero, a designer, a grid editor — can implement it too and register with
|
|
11
|
+
* the container's {@link FormSectionIndicatorCoordinator}, so the rail treats it like
|
|
12
|
+
* any other section.
|
|
13
|
+
*/
|
|
14
|
+
export interface FormSectionIndicatorSource {
|
|
15
|
+
/** The chrome section key this source reports for (matches `mj-collapsible-panel` `SectionKey`). */
|
|
16
|
+
readonly SectionKey: string;
|
|
17
|
+
/** Current state. Called during change detection — must be cheap and side-effect free. */
|
|
18
|
+
GetSectionIndicators(): FormSectionIndicators;
|
|
19
|
+
/**
|
|
20
|
+
* Whether a form-level `ValidationErrorInfo` belongs to this section. Used only to
|
|
21
|
+
* decide which errors are UNROUTED (claimed by no section), so a failure nothing
|
|
22
|
+
* renders still reaches the form-wide total instead of vanishing.
|
|
23
|
+
*/
|
|
24
|
+
OwnsValidationSource(source: ParsedValidationSource): boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Per-container registry of section indicator sources — the join between "a rail
|
|
28
|
+
* group" and "the sections it fronts", read live rather than pushed.
|
|
29
|
+
*
|
|
30
|
+
* **Pull, not push.** Every query asks the registered sources for their current
|
|
31
|
+
* counts. Nothing is cached here and nothing is written from inside a change-detection
|
|
32
|
+
* pass, which is what keeps the rail free of `ExpressionChangedAfterItHasBeenChecked`
|
|
33
|
+
* errors: within one pass a field's dirty / error state is constant (it mutates in
|
|
34
|
+
* event handlers), so every reader in that pass sees the same answer.
|
|
35
|
+
*
|
|
36
|
+
* Provided by `<mj-record-form-container>` via `providers` (not `viewProviders`), so
|
|
37
|
+
* projected panels and slot-mounted `BaseFormPanel`s reach the same instance.
|
|
38
|
+
*/
|
|
39
|
+
export declare class FormSectionIndicatorCoordinator {
|
|
40
|
+
/** Insertion-ordered so totals are deterministic. */
|
|
41
|
+
private readonly sources;
|
|
42
|
+
/**
|
|
43
|
+
* Fires when a source registers / leaves, or when a source reports that its state
|
|
44
|
+
* changed (a field edit). The container marks itself for check on it so an `OnPush`
|
|
45
|
+
* rail re-reads the counts on the next pass instead of waiting for its poll.
|
|
46
|
+
*/
|
|
47
|
+
readonly Changes: Subject<void>;
|
|
48
|
+
/** Declare (or re-declare) a section. A second source for the same key replaces the first. */
|
|
49
|
+
Register(source: FormSectionIndicatorSource): void;
|
|
50
|
+
/** Remove a source. Keyed on identity, so a replaced source cannot evict its replacement. */
|
|
51
|
+
Unregister(source: FormSectionIndicatorSource, previousKey?: string): void;
|
|
52
|
+
/** A source's state changed (field edited, error cleared). Nudges OnPush readers. */
|
|
53
|
+
NotifyChanged(): void;
|
|
54
|
+
/** Section keys currently registered, in registration order. */
|
|
55
|
+
get RegisteredSectionKeys(): string[];
|
|
56
|
+
/** Whether a section is registered. */
|
|
57
|
+
Has(sectionKey: string): boolean;
|
|
58
|
+
/** Current indicators for one section; empty when nothing is registered under that key. */
|
|
59
|
+
IndicatorsFor(sectionKey: string): FormSectionIndicators;
|
|
60
|
+
/**
|
|
61
|
+
* Indicators summed over several section keys — what a rail group needs, since one
|
|
62
|
+
* group (notably `Details`) fronts many panels.
|
|
63
|
+
*/
|
|
64
|
+
IndicatorsForKeys(sectionKeys: readonly string[]): FormSectionIndicators;
|
|
65
|
+
/** Indicators summed over every registered section. */
|
|
66
|
+
get TotalIndicators(): FormSectionIndicators;
|
|
67
|
+
/**
|
|
68
|
+
* Form-level errors no registered section claims. Surfaced deliberately: an error that
|
|
69
|
+
* vanished from every badge is worse than the no-badge behaviour this replaced.
|
|
70
|
+
*
|
|
71
|
+
* `reachableKeys`, when given, limits WHICH sources may claim: a section that is
|
|
72
|
+
* registered but sits in no rail group (hidden by `hiddenSectionKeys`, dropped by the
|
|
73
|
+
* chrome) has no badge anywhere, so letting it claim would make its failure vanish.
|
|
74
|
+
* Its errors stay unrouted and land in the whole-form total instead.
|
|
75
|
+
*/
|
|
76
|
+
UnroutedValidationErrors(errors: readonly ValidationErrorInfo[] | null | undefined, reachableKeys?: ReadonlySet<string>): ValidationErrorInfo[];
|
|
77
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<FormSectionIndicatorCoordinator, never>;
|
|
78
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<FormSectionIndicatorCoordinator>;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=form-section-indicator-coordinator.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form-section-indicator-coordinator.service.d.ts","sourceRoot":"","sources":["../../../src/lib/section-indicators/form-section-indicator-coordinator.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAIL,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC5B,MAAM,2BAA2B,CAAC;;AAEnC;;;;;;;;GAQG;AACH,MAAM,WAAW,0BAA0B;IACzC,oGAAoG;IACpG,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,0FAA0F;IAC1F,oBAAoB,IAAI,qBAAqB,CAAC;IAC9C;;;;OAIG;IACH,oBAAoB,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC;CAC/D;AAED;;;;;;;;;;;;GAYG;AACH,qBACa,+BAA+B;IAC1C,qDAAqD;IACrD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiD;IAEzE;;;;OAIG;IACH,SAAgB,OAAO,gBAAuB;IAE9C,8FAA8F;IACvF,QAAQ,CAAC,MAAM,EAAE,0BAA0B,GAAG,IAAI;IAQzD,6FAA6F;IACtF,UAAU,CAAC,MAAM,EAAE,0BAA0B,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAQjF,qFAAqF;IAC9E,aAAa,IAAI,IAAI;IAI5B,gEAAgE;IAChE,IAAW,qBAAqB,IAAI,MAAM,EAAE,CAE3C;IAED,uCAAuC;IAChC,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAIvC,2FAA2F;IACpF,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,qBAAqB;IAK/D;;;OAGG;IACI,iBAAiB,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,qBAAqB;IAI/E,uDAAuD;IACvD,IAAW,eAAe,IAAI,qBAAqB,CAElD;IAED;;;;;;;;OAQG;IACI,wBAAwB,CAC7B,MAAM,EAAE,SAAS,mBAAmB,EAAE,GAAG,IAAI,GAAG,SAAS,EACzD,aAAa,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GAClC,mBAAmB,EAAE;yCA3Eb,+BAA+B;6CAA/B,+BAA+B;CAoF3C"}
|