@praxisui/tabs 9.0.66 → 9.0.68-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -0
- package/ai/component-registry.json +2 -2
- package/fesm2022/praxisui-tabs.mjs +80 -5
- package/package.json +5 -5
- package/types/praxisui-tabs.d.ts +9 -0
package/README.md
CHANGED
|
@@ -4,6 +4,32 @@
|
|
|
4
4
|
|
|
5
5
|
Use this package for UI composition. The host still owns route-level state, domain persistence, widget data providers and authorization.
|
|
6
6
|
|
|
7
|
+
### Resizing a tab container
|
|
8
|
+
|
|
9
|
+
In paginated `group` and `nav` headers, changing the container width reveals the
|
|
10
|
+
active label without moving keyboard focus or emitting a selection event. This
|
|
11
|
+
also applies to widget resizing without a window resize, in LTR and RTL. A label
|
|
12
|
+
wider than the available strip is aligned to its leading edge; it cannot be shown
|
|
13
|
+
in full. Explicitly disabled pagination is respected.
|
|
14
|
+
|
|
15
|
+
The runtime observes the header size and preserves Material's scrolling animation.
|
|
16
|
+
The group adapter accesses Material's internal tab header because `MatTabGroup`
|
|
17
|
+
has no focus-neutral reveal operation. Keep the group/nav, LTR/RTL resize regression
|
|
18
|
+
tests when upgrading Material; consumers must not replicate this bridge.
|
|
19
|
+
|
|
20
|
+
### Nested page headers and scrolling
|
|
21
|
+
|
|
22
|
+
In `group` mode with `group.dynamicHeight: true`, tab bodies clip their content
|
|
23
|
+
without becoming independent scroll containers. A nested Dynamic Page can therefore
|
|
24
|
+
keep its opt-in Widget Shell sticky headers aligned with the enclosing page's
|
|
25
|
+
scrollport. Fixed-height groups keep Material's internal scrolling behavior.
|
|
26
|
+
|
|
27
|
+
Declaring `tabs[].widgets` does not itself create Widget Shells. To compose a nested
|
|
28
|
+
page, register `providePraxisDynamicPageMetadata()` from `@praxisui/core`, use the
|
|
29
|
+
`praxis-dynamic-page` widget, and author shells in its `WidgetPageDefinition`.
|
|
30
|
+
Do not add shell properties to `WidgetDefinition`. Keep the integration regression
|
|
31
|
+
when upgrading Material: this clipping bridge depends on its tab-body structure.
|
|
32
|
+
|
|
7
33
|
## LLM Recommendation Guide
|
|
8
34
|
|
|
9
35
|
- Recommend when: users need metadata-driven tab groups or nav tabs with editable tab content, visibility, order, icons, and runtime authoring.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "1.0.0",
|
|
3
|
-
"generatedAt": "2026-09-
|
|
3
|
+
"generatedAt": "2026-09-09T10:03:24.330Z",
|
|
4
4
|
"packageName": "@praxisui/tabs",
|
|
5
|
-
"packageVersion": "9.0.
|
|
5
|
+
"packageVersion": "9.0.68-rc.0",
|
|
6
6
|
"sourceRegistry": "praxis-component-registry-ingestion",
|
|
7
7
|
"sourceRegistryVersion": "1.0.0",
|
|
8
8
|
"componentCount": 1,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, Input, Inject, Component, ChangeDetectorRef, effect, EventEmitter, signal, ViewChild, Output, ChangeDetectionStrategy, ENVIRONMENT_INITIALIZER } from '@angular/core';
|
|
2
|
+
import { inject, Input, Inject, Component, ChangeDetectorRef, effect, EventEmitter, signal, ElementRef, afterEveryRender, ViewChild, Output, ChangeDetectionStrategy, ENVIRONMENT_INITIALIZER } from '@angular/core';
|
|
3
3
|
import { ActivatedRoute } from '@angular/router';
|
|
4
4
|
import * as i1$1 from '@angular/common';
|
|
5
5
|
import { CommonModule } from '@angular/common';
|
|
6
6
|
import * as i3 from '@angular/material/tabs';
|
|
7
|
-
import { MatTabsModule, MatTabGroup } from '@angular/material/tabs';
|
|
7
|
+
import { MatTabsModule, MatTabGroup, MatTabNav } from '@angular/material/tabs';
|
|
8
8
|
import * as i4$1 from '@angular/material/icon';
|
|
9
9
|
import { MatIconModule } from '@angular/material/icon';
|
|
10
10
|
import * as i10 from '@angular/material/tooltip';
|
|
@@ -3184,6 +3184,15 @@ class PraxisTabs {
|
|
|
3184
3184
|
controlledSelectedIndex;
|
|
3185
3185
|
destroyed = false;
|
|
3186
3186
|
groupComponent;
|
|
3187
|
+
navComponent;
|
|
3188
|
+
hostElement = inject(ElementRef);
|
|
3189
|
+
headerResizeObserver;
|
|
3190
|
+
observedHeader;
|
|
3191
|
+
headerResizeFrame;
|
|
3192
|
+
observedHeaderWidth = -1;
|
|
3193
|
+
observeHeaderAfterRender = afterEveryRender({
|
|
3194
|
+
read: () => this.observeHeaderResize(),
|
|
3195
|
+
});
|
|
3187
3196
|
destroy$ = new Subject();
|
|
3188
3197
|
widgetDefinitionCache = new WeakMap();
|
|
3189
3198
|
generatedContentForm = new FormGroup({});
|
|
@@ -3214,6 +3223,10 @@ class PraxisTabs {
|
|
|
3214
3223
|
}
|
|
3215
3224
|
ngOnDestroy() {
|
|
3216
3225
|
this.destroyed = true;
|
|
3226
|
+
this.headerResizeObserver?.disconnect();
|
|
3227
|
+
if (this.headerResizeFrame !== undefined) {
|
|
3228
|
+
this.hostElement.nativeElement.ownerDocument.defaultView?.cancelAnimationFrame(this.headerResizeFrame);
|
|
3229
|
+
}
|
|
3217
3230
|
this.assistantSessions.removeContextSession(this.buildAiAssistantContextSnapshot().identity);
|
|
3218
3231
|
this.aiAssistantStateSubscription?.unsubscribe();
|
|
3219
3232
|
this.destroy$.next();
|
|
@@ -3222,6 +3235,65 @@ class PraxisTabs {
|
|
|
3222
3235
|
isNavMode() {
|
|
3223
3236
|
return !!this.config?.nav && !!this.config?.nav?.links?.length;
|
|
3224
3237
|
}
|
|
3238
|
+
observeHeaderResize() {
|
|
3239
|
+
const header = this.hostElement.nativeElement.querySelector(':scope > .praxis-tabs-root > mat-tab-group > mat-tab-header, :scope > .praxis-tabs-root > nav[mat-tab-nav-bar]') ?? undefined;
|
|
3240
|
+
if (header === this.observedHeader || typeof ResizeObserver === 'undefined')
|
|
3241
|
+
return;
|
|
3242
|
+
this.headerResizeObserver?.disconnect();
|
|
3243
|
+
this.observedHeader = header;
|
|
3244
|
+
this.observedHeaderWidth = -1;
|
|
3245
|
+
if (!header)
|
|
3246
|
+
return;
|
|
3247
|
+
this.headerResizeObserver = new ResizeObserver(() => {
|
|
3248
|
+
const width = header.clientWidth;
|
|
3249
|
+
if (width === this.observedHeaderWidth)
|
|
3250
|
+
return;
|
|
3251
|
+
this.observedHeaderWidth = width;
|
|
3252
|
+
const view = header.ownerDocument.defaultView;
|
|
3253
|
+
if (!view)
|
|
3254
|
+
return;
|
|
3255
|
+
if (this.headerResizeFrame !== undefined)
|
|
3256
|
+
view.cancelAnimationFrame(this.headerResizeFrame);
|
|
3257
|
+
this.headerResizeFrame = view.requestAnimationFrame(() => {
|
|
3258
|
+
this.headerResizeFrame = undefined;
|
|
3259
|
+
if (!this.destroyed && header === this.observedHeader && width > 0) {
|
|
3260
|
+
this.revealActiveHeaderLabel(header);
|
|
3261
|
+
}
|
|
3262
|
+
});
|
|
3263
|
+
});
|
|
3264
|
+
this.headerResizeObserver.observe(header);
|
|
3265
|
+
}
|
|
3266
|
+
revealActiveHeaderLabel(element) {
|
|
3267
|
+
// Material adapter boundary: MatTabGroup exposes no focus-neutral reveal API.
|
|
3268
|
+
// Keep access to its header here; do not change selectedIndex or focusIndex.
|
|
3269
|
+
const header = this.isNavMode() ? this.navComponent : this.groupComponent?._tabHeader;
|
|
3270
|
+
if (!header || header.disablePagination)
|
|
3271
|
+
return;
|
|
3272
|
+
header.updatePagination();
|
|
3273
|
+
this.cdr.detectChanges(); // Material paginator controls must occupy their final width.
|
|
3274
|
+
const viewport = element.querySelector('.mat-mdc-tab-label-container, .mat-mdc-tab-link-container');
|
|
3275
|
+
const active = element.querySelector('[role="tab"][aria-selected="true"]');
|
|
3276
|
+
if (!viewport || !active)
|
|
3277
|
+
return;
|
|
3278
|
+
const rtl = element.ownerDocument.defaultView?.getComputedStyle(element).direction === 'rtl';
|
|
3279
|
+
const labelContainer = active.offsetParent;
|
|
3280
|
+
if (rtl && !labelContainer)
|
|
3281
|
+
return;
|
|
3282
|
+
// Offset geometry excludes the in-flight transform animation. Reading painted
|
|
3283
|
+
// rectangles here would apply an intermediate animation delta a second time.
|
|
3284
|
+
const end = rtl ? labelContainer.offsetWidth - active.offsetLeft
|
|
3285
|
+
: active.offsetLeft + active.offsetWidth;
|
|
3286
|
+
const start = end - active.offsetWidth;
|
|
3287
|
+
const before = header.scrollDistance;
|
|
3288
|
+
const after = before + viewport.clientWidth;
|
|
3289
|
+
const delta = start < before ? start - before
|
|
3290
|
+
: end > after ? Math.min(end - after, start - before) : 0;
|
|
3291
|
+
if (Math.abs(delta) < 1)
|
|
3292
|
+
return;
|
|
3293
|
+
header.scrollDistance += delta;
|
|
3294
|
+
header.updatePagination();
|
|
3295
|
+
this.cdr.markForCheck();
|
|
3296
|
+
}
|
|
3225
3297
|
effectiveAnimationDuration() {
|
|
3226
3298
|
const reduce = this.config?.accessibility?.reduceMotion;
|
|
3227
3299
|
if (reduce)
|
|
@@ -4314,7 +4386,7 @@ class PraxisTabs {
|
|
|
4314
4386
|
return JSON.parse(JSON.stringify(config));
|
|
4315
4387
|
}
|
|
4316
4388
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisTabs, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4317
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisTabs, isStandalone: true, selector: "praxis-tabs", inputs: { config: "config", tabsId: "tabsId", componentInstanceId: "componentInstanceId", configPersistenceStrategy: "configPersistenceStrategy", selectedIndex: "selectedIndex", enableCustomization: "enableCustomization", form: "form", context: "context" }, outputs: { animationDone: "animationDone", focusChange: "focusChange", selectedIndexChange: "selectedIndexChange", selectedTabChange: "selectedTabChange", indexFocused: "indexFocused", selectFocusedIndex: "selectFocusedIndex", configChange: "configChange", widgetEvent: "widgetEvent" }, providers: [providePraxisI18nConfig(PRAXIS_TABS_I18N_CONFIG)], viewQueries: [{ propertyName: "groupComponent", first: true, predicate: MatTabGroup, descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
4389
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisTabs, isStandalone: true, selector: "praxis-tabs", inputs: { config: "config", tabsId: "tabsId", componentInstanceId: "componentInstanceId", configPersistenceStrategy: "configPersistenceStrategy", selectedIndex: "selectedIndex", enableCustomization: "enableCustomization", form: "form", context: "context" }, outputs: { animationDone: "animationDone", focusChange: "focusChange", selectedIndexChange: "selectedIndexChange", selectedTabChange: "selectedTabChange", indexFocused: "indexFocused", selectFocusedIndex: "selectFocusedIndex", configChange: "configChange", widgetEvent: "widgetEvent" }, providers: [providePraxisI18nConfig(PRAXIS_TABS_I18N_CONFIG)], viewQueries: [{ propertyName: "groupComponent", first: true, predicate: MatTabGroup, descendants: true }, { propertyName: "navComponent", first: true, predicate: MatTabNav, descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
4318
4390
|
<div
|
|
4319
4391
|
class="praxis-tabs-root"
|
|
4320
4392
|
[class.density-compact]="config?.appearance?.density === 'compact'"
|
|
@@ -4620,7 +4692,7 @@ class PraxisTabs {
|
|
|
4620
4692
|
</button>
|
|
4621
4693
|
}
|
|
4622
4694
|
</div>
|
|
4623
|
-
`, isInline: true, styles: [".praxis-tabs-root{position:relative;display:block}.praxis-tabs-group.align-start .mat-mdc-tab-header{justify-content:flex-start}.praxis-tabs-group.align-center .mat-mdc-tab-header{justify-content:center}.praxis-tabs-group.align-end .mat-mdc-tab-header{justify-content:flex-end}.praxis-tabs-group--header-only .mat-mdc-tab-body-wrapper
|
|
4695
|
+
`, isInline: true, styles: [".praxis-tabs-root{position:relative;display:block}.praxis-tabs-group.align-start .mat-mdc-tab-header{justify-content:flex-start}.praxis-tabs-group.align-center .mat-mdc-tab-header{justify-content:center}.praxis-tabs-group.align-end .mat-mdc-tab-header{justify-content:flex-end}.praxis-tabs-group--header-only .mat-mdc-tab-body-wrapper{display:none}:host ::ng-deep .praxis-tabs-group.mat-mdc-tab-group-dynamic-height>.mat-mdc-tab-body-wrapper,:host ::ng-deep .praxis-tabs-group.mat-mdc-tab-group-dynamic-height>.mat-mdc-tab-body-wrapper>.mat-mdc-tab-body,:host ::ng-deep .praxis-tabs-group.mat-mdc-tab-group-dynamic-height>.mat-mdc-tab-body-wrapper>.mat-mdc-tab-body>.mat-mdc-tab-body-content{overflow:clip}.praxis-tabs-nav-panel--header-only{display:none}.density-compact .mat-mdc-tab-body-content{padding:8px}.density-comfortable .mat-mdc-tab-body-content{padding:16px}.density-spacious .mat-mdc-tab-body-content{padding:24px}.praxis-tabs-widget-stack{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--p-tabs-widget-stack-gap, 16px);min-width:0}.praxis-tabs-widget-surface{display:block;min-width:0}.density-compact .praxis-tabs-widget-stack{--p-tabs-widget-stack-gap: 12px}.density-comfortable .praxis-tabs-widget-stack{--p-tabs-widget-stack-gap: 16px}.density-spacious .praxis-tabs-widget-stack{--p-tabs-widget-stack-gap: 24px}.tabs-ai-assistant{position:absolute;right:12px;bottom:72px;z-index:3}.tabs-ai-assistant-trigger{box-shadow:var(--md-sys-elevation-level2)}.edit-fab{position:absolute;right:12px;bottom:12px;z-index:2}.edit-fab-secondary{right:56px}.tab-empty{padding:16px;color:var(--md-sys-color-on-surface-variant);font-style:italic}.high-contrast{filter:contrast(1.2)}.reduce-motion{--mat-animation-duration: 0ms}.drag-handle{display:inline-flex;align-items:center;vertical-align:middle;margin-right:4px;cursor:grab}.tab-label-icon{font-size:18px;width:18px;height:18px;margin-right:6px;vertical-align:middle}:host-context(.pdx-gridster-item) .praxis-tabs-root{display:flex;flex-direction:column;height:100%;min-height:0}:host-context(.pdx-gridster-item) .praxis-tabs-group,:host-context(.pdx-gridster-item) .mat-mdc-tab-group{flex:1 1 auto;min-height:0}:host-context(.pdx-gridster-item) .mat-mdc-tab-body-wrapper,:host-context(.pdx-gridster-item) .mat-mdc-tab-body-content{height:100%;min-height:0}:host-context(.pdx-gridster-item) .mat-mdc-tab-body-content{overflow:auto}:host-context(.pdx-gridster-item) .praxis-tabnav-content{flex:1 1 auto;min-height:0;overflow:auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2_1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2_1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "directive", type: i3.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "component", type: i3.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i3.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: i3.MatTabNav, selector: "[mat-tab-nav-bar]", inputs: ["fitInkBarToContent", "mat-stretch-tabs", "animationDuration", "backgroundColor", "disableRipple", "color", "tabPanel"], exportAs: ["matTabNavBar", "matTabNav"] }, { kind: "component", type: i3.MatTabNavPanel, selector: "mat-tab-nav-panel", inputs: ["id"], exportAs: ["matTabNavPanel"] }, { kind: "component", type: i3.MatTabLink, selector: "[mat-tab-link], [matTabLink]", inputs: ["active", "disabled", "disableRipple", "tabIndex", "id"], exportAs: ["matTabLink"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i6.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i9.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i9.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i9.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: EmptyStateCardComponent, selector: "praxis-empty-state-card", inputs: ["icon", "title", "description", "primaryAction", "secondaryActions", "inline", "tone", "variant", "alignment", "density", "iconContainer"] }, { kind: "directive", type: DynamicFieldLoaderDirective, selector: "[dynamicFieldLoader]", inputs: ["fields", "formGroup", "enableExternalControlBinding", "itemTemplate", "debugTrace", "debugTraceLabel", "readonlyMode", "disabledMode", "presentationMode", "visible", "canvasMode"], outputs: ["componentsCreated", "fieldCreated", "fieldDestroyed", "renderError", "canvasMouseEnter", "canvasMouseLeave", "canvasClick", "canvasFocus"] }, { kind: "directive", type: DynamicWidgetLoaderDirective, selector: "[dynamicWidgetLoader]", inputs: ["dynamicWidgetLoader", "ownerWidgetKey", "context", "strictValidation", "autoWireOutputs"], outputs: ["widgetEvent", "widgetDiagnostic"], exportAs: ["dynamicWidgetLoader"] }, { kind: "component", type: PraxisAiAssistantShellComponent, selector: "praxis-ai-assistant-shell", inputs: ["labels", "mode", "state", "contextItems", "attachments", "messages", "quickReplies", "recommendedIntents", "prompt", "statusText", "errorText", "testIdPrefix", "panelTestId", "submitTestId", "applyTestId", "primaryAction", "secondaryActions", "governanceActions", "busy", "canSubmit", "canApply", "submitOnEnter", "showAttachAction", "enablePastedAttachments", "enableFileAttachments", "attachmentAccept", "attachmentMultiple", "voiceInputMode", "voiceLanguage", "draggable", "resizable", "minWidth", "minHeight", "margin", "layout"], outputs: ["promptChange", "submitPrompt", "apply", "retryTurn", "cancelTurn", "shellAction", "close", "attach", "attachmentsPasted", "attachmentsSelected", "removeAttachment", "messageAction", "editMessage", "resendMessage", "quickReply", "recommendedIntent", "layoutChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4624
4696
|
}
|
|
4625
4697
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisTabs, decorators: [{
|
|
4626
4698
|
type: Component,
|
|
@@ -4944,7 +5016,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
4944
5016
|
</button>
|
|
4945
5017
|
}
|
|
4946
5018
|
</div>
|
|
4947
|
-
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".praxis-tabs-root{position:relative;display:block}.praxis-tabs-group.align-start .mat-mdc-tab-header{justify-content:flex-start}.praxis-tabs-group.align-center .mat-mdc-tab-header{justify-content:center}.praxis-tabs-group.align-end .mat-mdc-tab-header{justify-content:flex-end}.praxis-tabs-group--header-only .mat-mdc-tab-body-wrapper
|
|
5019
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".praxis-tabs-root{position:relative;display:block}.praxis-tabs-group.align-start .mat-mdc-tab-header{justify-content:flex-start}.praxis-tabs-group.align-center .mat-mdc-tab-header{justify-content:center}.praxis-tabs-group.align-end .mat-mdc-tab-header{justify-content:flex-end}.praxis-tabs-group--header-only .mat-mdc-tab-body-wrapper{display:none}:host ::ng-deep .praxis-tabs-group.mat-mdc-tab-group-dynamic-height>.mat-mdc-tab-body-wrapper,:host ::ng-deep .praxis-tabs-group.mat-mdc-tab-group-dynamic-height>.mat-mdc-tab-body-wrapper>.mat-mdc-tab-body,:host ::ng-deep .praxis-tabs-group.mat-mdc-tab-group-dynamic-height>.mat-mdc-tab-body-wrapper>.mat-mdc-tab-body>.mat-mdc-tab-body-content{overflow:clip}.praxis-tabs-nav-panel--header-only{display:none}.density-compact .mat-mdc-tab-body-content{padding:8px}.density-comfortable .mat-mdc-tab-body-content{padding:16px}.density-spacious .mat-mdc-tab-body-content{padding:24px}.praxis-tabs-widget-stack{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--p-tabs-widget-stack-gap, 16px);min-width:0}.praxis-tabs-widget-surface{display:block;min-width:0}.density-compact .praxis-tabs-widget-stack{--p-tabs-widget-stack-gap: 12px}.density-comfortable .praxis-tabs-widget-stack{--p-tabs-widget-stack-gap: 16px}.density-spacious .praxis-tabs-widget-stack{--p-tabs-widget-stack-gap: 24px}.tabs-ai-assistant{position:absolute;right:12px;bottom:72px;z-index:3}.tabs-ai-assistant-trigger{box-shadow:var(--md-sys-elevation-level2)}.edit-fab{position:absolute;right:12px;bottom:12px;z-index:2}.edit-fab-secondary{right:56px}.tab-empty{padding:16px;color:var(--md-sys-color-on-surface-variant);font-style:italic}.high-contrast{filter:contrast(1.2)}.reduce-motion{--mat-animation-duration: 0ms}.drag-handle{display:inline-flex;align-items:center;vertical-align:middle;margin-right:4px;cursor:grab}.tab-label-icon{font-size:18px;width:18px;height:18px;margin-right:6px;vertical-align:middle}:host-context(.pdx-gridster-item) .praxis-tabs-root{display:flex;flex-direction:column;height:100%;min-height:0}:host-context(.pdx-gridster-item) .praxis-tabs-group,:host-context(.pdx-gridster-item) .mat-mdc-tab-group{flex:1 1 auto;min-height:0}:host-context(.pdx-gridster-item) .mat-mdc-tab-body-wrapper,:host-context(.pdx-gridster-item) .mat-mdc-tab-body-content{height:100%;min-height:0}:host-context(.pdx-gridster-item) .mat-mdc-tab-body-content{overflow:auto}:host-context(.pdx-gridster-item) .praxis-tabnav-content{flex:1 1 auto;min-height:0;overflow:auto}\n"] }]
|
|
4948
5020
|
}], propDecorators: { config: [{
|
|
4949
5021
|
type: Input
|
|
4950
5022
|
}], tabsId: [{
|
|
@@ -4981,6 +5053,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
4981
5053
|
}], groupComponent: [{
|
|
4982
5054
|
type: ViewChild,
|
|
4983
5055
|
args: [MatTabGroup]
|
|
5056
|
+
}], navComponent: [{
|
|
5057
|
+
type: ViewChild,
|
|
5058
|
+
args: [MatTabNav]
|
|
4984
5059
|
}] } });
|
|
4985
5060
|
|
|
4986
5061
|
class PraxisTabsWidgetConfigEditor {
|
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxisui/tabs",
|
|
3
|
-
"version": "9.0.
|
|
3
|
+
"version": "9.0.68-rc.0",
|
|
4
4
|
"description": "Configurable tabs (group and nav) for Praxis UI with metadata-driven content and runtime editor.",
|
|
5
5
|
"peerDependencies": {
|
|
6
6
|
"@angular/common": "^21.0.0",
|
|
7
7
|
"@angular/core": "^21.0.0",
|
|
8
8
|
"@angular/material": "^21.0.0",
|
|
9
9
|
"@angular/cdk": "^21.0.0",
|
|
10
|
-
"@praxisui/core": "^9.0.
|
|
11
|
-
"@praxisui/dynamic-fields": "^9.0.
|
|
12
|
-
"@praxisui/settings-panel": "^9.0.
|
|
10
|
+
"@praxisui/core": "^9.0.68-rc.0",
|
|
11
|
+
"@praxisui/dynamic-fields": "^9.0.68-rc.0",
|
|
12
|
+
"@praxisui/settings-panel": "^9.0.68-rc.0",
|
|
13
13
|
"@angular/forms": "^21.0.0",
|
|
14
14
|
"@angular/router": "^21.0.0",
|
|
15
|
-
"@praxisui/ai": "^9.0.
|
|
15
|
+
"@praxisui/ai": "^9.0.68-rc.0",
|
|
16
16
|
"rxjs": "~7.8.0"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
package/types/praxisui-tabs.d.ts
CHANGED
|
@@ -208,6 +208,13 @@ declare class PraxisTabs implements OnInit, OnChanges, OnDestroy {
|
|
|
208
208
|
private controlledSelectedIndex?;
|
|
209
209
|
private destroyed;
|
|
210
210
|
private groupComponent?;
|
|
211
|
+
private navComponent?;
|
|
212
|
+
private readonly hostElement;
|
|
213
|
+
private headerResizeObserver?;
|
|
214
|
+
private observedHeader?;
|
|
215
|
+
private headerResizeFrame?;
|
|
216
|
+
private observedHeaderWidth;
|
|
217
|
+
private readonly observeHeaderAfterRender;
|
|
211
218
|
private readonly destroy$;
|
|
212
219
|
private widgetDefinitionCache;
|
|
213
220
|
private readonly generatedContentForm;
|
|
@@ -215,6 +222,8 @@ declare class PraxisTabs implements OnInit, OnChanges, OnDestroy {
|
|
|
215
222
|
ngOnChanges(changes: SimpleChanges): void;
|
|
216
223
|
ngOnDestroy(): void;
|
|
217
224
|
isNavMode(): boolean;
|
|
225
|
+
private observeHeaderResize;
|
|
226
|
+
private revealActiveHeaderLabel;
|
|
218
227
|
effectiveAnimationDuration(): string;
|
|
219
228
|
getNavActive(i: number): boolean;
|
|
220
229
|
protected visibleNavLinkEntries(): Array<{
|