@praxisui/tabs 9.0.4-rc.2 → 9.0.4-rc.20

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 CHANGED
@@ -13,7 +13,7 @@ Use this package for UI composition. The host still owns route-level state, doma
13
13
  ## Install
14
14
 
15
15
  ```bash
16
- npm i @praxisui/tabs@latest
16
+ npm i @praxisui/tabs@rc
17
17
  ```
18
18
 
19
19
  Peer dependencies:
@@ -102,6 +102,8 @@ const navTabs: TabsMetadata = {
102
102
 
103
103
  Use stable ids for tabs and nav links. When `tabsId` is provided, the component stores configuration under a key derived from route, component type, `tabsId` and optional `componentInstanceId`.
104
104
 
105
+ When a tab or navigation link contains multiple `widgets`, the runtime renders them as sibling surfaces in a density-aware vertical stack. The default rhythm is 12 px for `compact`, 16 px for `comfortable`, and 24 px for `spacious`, preventing adjacent tables, forms, lists, or related-resource outlets from visually merging. This is container chrome only; it does not change widget inputs, events, identity, or composition bindings.
106
+
105
107
  ## Runtime Authoring
106
108
 
107
109
  With `enableCustomization`, the component can open quick setup or the full `PraxisTabsConfigEditor` through Settings Panel. The editor round-trips through `TabsAuthoringDocument`, applies only runtime-backed fields and emits `configChange` so the host can persist canonical page or manifest changes.
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-07-31T10:13:34.390Z",
3
+ "generatedAt": "2026-08-04T11:45:12.207Z",
4
4
  "packageName": "@praxisui/tabs",
5
- "packageVersion": "9.0.4-rc.2",
5
+ "packageVersion": "9.0.4-rc.20",
6
6
  "sourceRegistry": "praxis-component-registry-ingestion",
7
7
  "sourceRegistryVersion": "1.0.0",
8
8
  "componentCount": 1,
@@ -4376,13 +4376,17 @@ class PraxisTabs {
4376
4376
  ></ng-container>
4377
4377
  }
4378
4378
  @if (safeWidgetDefinitions(l.widgets).length) {
4379
- @for (w of safeWidgetDefinitions(l.widgets); track trackWidgetDefinition(wi, w); let wi = $index) {
4380
- <ng-container
4381
- [dynamicWidgetLoader]="resolveWidgetDefinition(w)"
4382
- [context]="context || {}"
4383
- (widgetEvent)="emitWidgetEvent(linkEventPath(l.id, currentNavIndex()), $event)"
4384
- ></ng-container>
4385
- }
4379
+ <div class="praxis-tabs-widget-stack" data-role="nested-widget-stack">
4380
+ @for (w of safeWidgetDefinitions(l.widgets); track trackWidgetDefinition(wi, w); let wi = $index) {
4381
+ <div class="praxis-tabs-widget-surface" [attr.data-child-widget-key]="trackWidgetDefinition(wi, w)">
4382
+ <ng-container
4383
+ [dynamicWidgetLoader]="resolveWidgetDefinition(w)"
4384
+ [context]="context || {}"
4385
+ (widgetEvent)="emitWidgetEvent(linkEventPath(l.id, currentNavIndex()), $event)"
4386
+ ></ng-container>
4387
+ </div>
4388
+ }
4389
+ </div>
4386
4390
  }
4387
4391
  } @else {
4388
4392
  <praxis-empty-state-card
@@ -4478,13 +4482,17 @@ class PraxisTabs {
4478
4482
  ></ng-container>
4479
4483
  }
4480
4484
  @if (safeWidgetDefinitions(entry.tab.widgets).length) {
4481
- @for (w of safeWidgetDefinitions(entry.tab.widgets); track trackWidgetDefinition(wi, w); let wi = $index) {
4482
- <ng-container
4483
- [dynamicWidgetLoader]="resolveWidgetDefinition(w)"
4484
- [context]="context || {}"
4485
- (widgetEvent)="emitWidgetEvent(tabEventPath(entry.tab.id, entry.index), $event)"
4486
- ></ng-container>
4487
- }
4485
+ <div class="praxis-tabs-widget-stack" data-role="nested-widget-stack">
4486
+ @for (w of safeWidgetDefinitions(entry.tab.widgets); track trackWidgetDefinition(wi, w); let wi = $index) {
4487
+ <div class="praxis-tabs-widget-surface" [attr.data-child-widget-key]="trackWidgetDefinition(wi, w)">
4488
+ <ng-container
4489
+ [dynamicWidgetLoader]="resolveWidgetDefinition(w)"
4490
+ [context]="context || {}"
4491
+ (widgetEvent)="emitWidgetEvent(tabEventPath(entry.tab.id, entry.index), $event)"
4492
+ ></ng-container>
4493
+ </div>
4494
+ }
4495
+ </div>
4488
4496
  }
4489
4497
  } @else {
4490
4498
  <praxis-empty-state-card
@@ -4527,7 +4535,7 @@ class PraxisTabs {
4527
4535
  </button>
4528
4536
  }
4529
4537
  </div>
4530
- `, 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,.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}.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 });
4538
+ `, 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,.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 });
4531
4539
  }
4532
4540
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisTabs, decorators: [{
4533
4541
  type: Component,
@@ -4689,13 +4697,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
4689
4697
  ></ng-container>
4690
4698
  }
4691
4699
  @if (safeWidgetDefinitions(l.widgets).length) {
4692
- @for (w of safeWidgetDefinitions(l.widgets); track trackWidgetDefinition(wi, w); let wi = $index) {
4693
- <ng-container
4694
- [dynamicWidgetLoader]="resolveWidgetDefinition(w)"
4695
- [context]="context || {}"
4696
- (widgetEvent)="emitWidgetEvent(linkEventPath(l.id, currentNavIndex()), $event)"
4697
- ></ng-container>
4698
- }
4700
+ <div class="praxis-tabs-widget-stack" data-role="nested-widget-stack">
4701
+ @for (w of safeWidgetDefinitions(l.widgets); track trackWidgetDefinition(wi, w); let wi = $index) {
4702
+ <div class="praxis-tabs-widget-surface" [attr.data-child-widget-key]="trackWidgetDefinition(wi, w)">
4703
+ <ng-container
4704
+ [dynamicWidgetLoader]="resolveWidgetDefinition(w)"
4705
+ [context]="context || {}"
4706
+ (widgetEvent)="emitWidgetEvent(linkEventPath(l.id, currentNavIndex()), $event)"
4707
+ ></ng-container>
4708
+ </div>
4709
+ }
4710
+ </div>
4699
4711
  }
4700
4712
  } @else {
4701
4713
  <praxis-empty-state-card
@@ -4791,13 +4803,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
4791
4803
  ></ng-container>
4792
4804
  }
4793
4805
  @if (safeWidgetDefinitions(entry.tab.widgets).length) {
4794
- @for (w of safeWidgetDefinitions(entry.tab.widgets); track trackWidgetDefinition(wi, w); let wi = $index) {
4795
- <ng-container
4796
- [dynamicWidgetLoader]="resolveWidgetDefinition(w)"
4797
- [context]="context || {}"
4798
- (widgetEvent)="emitWidgetEvent(tabEventPath(entry.tab.id, entry.index), $event)"
4799
- ></ng-container>
4800
- }
4806
+ <div class="praxis-tabs-widget-stack" data-role="nested-widget-stack">
4807
+ @for (w of safeWidgetDefinitions(entry.tab.widgets); track trackWidgetDefinition(wi, w); let wi = $index) {
4808
+ <div class="praxis-tabs-widget-surface" [attr.data-child-widget-key]="trackWidgetDefinition(wi, w)">
4809
+ <ng-container
4810
+ [dynamicWidgetLoader]="resolveWidgetDefinition(w)"
4811
+ [context]="context || {}"
4812
+ (widgetEvent)="emitWidgetEvent(tabEventPath(entry.tab.id, entry.index), $event)"
4813
+ ></ng-container>
4814
+ </div>
4815
+ }
4816
+ </div>
4801
4817
  }
4802
4818
  } @else {
4803
4819
  <praxis-empty-state-card
@@ -4840,7 +4856,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
4840
4856
  </button>
4841
4857
  }
4842
4858
  </div>
4843
- `, 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,.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}.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"] }]
4859
+ `, 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,.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"] }]
4844
4860
  }], propDecorators: { config: [{
4845
4861
  type: Input
4846
4862
  }], tabsId: [{
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@praxisui/tabs",
3
- "version": "9.0.4-rc.2",
3
+ "version": "9.0.4-rc.20",
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.4-rc.2",
11
- "@praxisui/dynamic-fields": "^9.0.4-rc.2",
12
- "@praxisui/settings-panel": "^9.0.4-rc.2",
10
+ "@praxisui/core": "^9.0.4-rc.20",
11
+ "@praxisui/dynamic-fields": "^9.0.4-rc.20",
12
+ "@praxisui/settings-panel": "^9.0.4-rc.20",
13
13
  "@angular/forms": "^21.0.0",
14
14
  "@angular/router": "^21.0.0",
15
- "@praxisui/ai": "^9.0.4-rc.2",
15
+ "@praxisui/ai": "^9.0.4-rc.20",
16
16
  "rxjs": "~7.8.0"
17
17
  },
18
18
  "dependencies": {