@praxisui/crud 10.0.0-rc.8 → 10.0.0-rc.9
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 +10 -0
- package/ai/component-registry.json +2 -2
- package/fesm2022/praxisui-crud.mjs +52 -19
- package/package.json +7 -7
- package/types/praxisui-crud.d.ts +7 -1
package/README.md
CHANGED
|
@@ -4,6 +4,16 @@ CRUD shell for Praxis UI applications.
|
|
|
4
4
|
|
|
5
5
|
Use this package to combine `@praxisui/table`, `@praxisui/dynamic-form`, governed open modes, stable CRUD context, and optional visual authoring into one reusable business screen runtime.
|
|
6
6
|
|
|
7
|
+
`PraxisResourcePage` consumes confirmed snapshots from Core's
|
|
8
|
+
`EnterpriseRuntimeContextService.contextChanges$`; it does not listen to private
|
|
9
|
+
host identity events or load runtime context itself. Initial bootstrap and
|
|
10
|
+
unchanged snapshots retain the child CRUD. Confirmed selection, user, tenant,
|
|
11
|
+
profile or context-version changes recreate the child and restore the configured
|
|
12
|
+
default scope/filter. Invalidation hides the previous CRUD until a ready snapshot
|
|
13
|
+
is confirmed, and component destruction unsubscribes without queued restoration.
|
|
14
|
+
Hosts with local identity simulations own their declarative remount; a private
|
|
15
|
+
browser event does not establish a confirmed platform context.
|
|
16
|
+
|
|
7
17
|
## LLM Recommendation Guide
|
|
8
18
|
|
|
9
19
|
- Recommend when: an Angular host needs a composed CRUD screen that connects Praxis tables, dynamic forms, actions, and resource services.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "1.0.0",
|
|
3
|
-
"generatedAt": "2026-10-
|
|
3
|
+
"generatedAt": "2026-10-12T12:49:05.370Z",
|
|
4
4
|
"packageName": "@praxisui/crud",
|
|
5
|
-
"packageVersion": "10.0.0-rc.
|
|
5
|
+
"packageVersion": "10.0.0-rc.9",
|
|
6
6
|
"sourceRegistry": "praxis-component-registry-ingestion",
|
|
7
7
|
"sourceRegistryVersion": "1.0.0",
|
|
8
8
|
"componentCount": 2,
|
|
@@ -8930,7 +8930,12 @@ const PRAXIS_CRUD_AUTHORING_MANIFEST = {
|
|
|
8930
8930
|
*/
|
|
8931
8931
|
class PraxisResourcePage {
|
|
8932
8932
|
route = inject(ActivatedRoute, { optional: true });
|
|
8933
|
+
runtimeContext = inject(EnterpriseRuntimeContextService, { optional: true });
|
|
8933
8934
|
routeSub;
|
|
8935
|
+
contextSub;
|
|
8936
|
+
observedContext = false;
|
|
8937
|
+
confirmedContextIdentity;
|
|
8938
|
+
contextInvalidated = false;
|
|
8934
8939
|
resource;
|
|
8935
8940
|
resourcePath;
|
|
8936
8941
|
crudId;
|
|
@@ -9086,27 +9091,50 @@ class PraxisResourcePage {
|
|
|
9086
9091
|
defaultMetadata = computed(() => {
|
|
9087
9092
|
return this.effectiveMetadata();
|
|
9088
9093
|
}, ...(ngDevMode ? [{ debugName: "defaultMetadata" }] : /* istanbul ignore next */ []));
|
|
9089
|
-
|
|
9090
|
-
this.activeScopeFilter.set({});
|
|
9091
|
-
this.activeScopeId.set(this.defaultScopeId || 'all');
|
|
9092
|
-
this.identityRenderKey.update((k) => k + 1);
|
|
9093
|
-
this.identityVisible.set(false);
|
|
9094
|
-
queueMicrotask(() => this.identityVisible.set(true));
|
|
9095
|
-
};
|
|
9096
|
-
ngOnInit() {
|
|
9094
|
+
restoreDefaultScope() {
|
|
9097
9095
|
const sb = this.effectiveScopeBar();
|
|
9098
|
-
const initialId = this.defaultScopeId ||
|
|
9099
|
-
sb?.
|
|
9100
|
-
|
|
9101
|
-
'all';
|
|
9096
|
+
const initialId = this.defaultScopeId || sb?.activeId
|
|
9097
|
+
|| sb?.items?.find((item) => item.isDefault)?.id || 'all';
|
|
9098
|
+
this.activeScopeFilter.set({});
|
|
9102
9099
|
this.activeScopeId.set(initialId);
|
|
9103
|
-
const initialItem = sb?.items?.find((
|
|
9104
|
-
if (initialItem)
|
|
9100
|
+
const initialItem = sb?.items?.find((item) => item.id === initialId);
|
|
9101
|
+
if (initialItem)
|
|
9105
9102
|
this.applyItemFilter(initialItem);
|
|
9103
|
+
}
|
|
9104
|
+
onRuntimeContext(context) {
|
|
9105
|
+
const initial = !this.observedContext;
|
|
9106
|
+
this.observedContext = true;
|
|
9107
|
+
const effective = context?.state === 'ready' ? context.effectiveContext : null;
|
|
9108
|
+
if (!effective) {
|
|
9109
|
+
// An unconfigured runtime starts at null. Do not remount on bootstrap.
|
|
9110
|
+
if (context === null && this.confirmedContextIdentity === undefined && !this.contextInvalidated)
|
|
9111
|
+
return;
|
|
9112
|
+
if (!this.contextInvalidated) {
|
|
9113
|
+
this.restoreDefaultScope();
|
|
9114
|
+
if (!initial)
|
|
9115
|
+
this.identityRenderKey.update((key) => key + 1);
|
|
9116
|
+
}
|
|
9117
|
+
this.contextInvalidated = true;
|
|
9118
|
+
this.identityVisible.set(false);
|
|
9119
|
+
return;
|
|
9106
9120
|
}
|
|
9107
|
-
|
|
9108
|
-
|
|
9121
|
+
const identity = JSON.stringify([
|
|
9122
|
+
context.selectionVersion, context.user.userId, effective.contextVersion,
|
|
9123
|
+
effective.activeTenant.tenantId, effective.activeOrganizationId,
|
|
9124
|
+
effective.activeProfileId, effective.activeModuleKey, effective.environment,
|
|
9125
|
+
effective.locale, effective.timezone,
|
|
9126
|
+
]);
|
|
9127
|
+
const changed = this.confirmedContextIdentity !== undefined && identity !== this.confirmedContextIdentity;
|
|
9128
|
+
this.confirmedContextIdentity = identity;
|
|
9129
|
+
if (changed || this.contextInvalidated) {
|
|
9130
|
+
this.restoreDefaultScope();
|
|
9131
|
+
if (!this.contextInvalidated)
|
|
9132
|
+
this.identityRenderKey.update((key) => key + 1);
|
|
9109
9133
|
}
|
|
9134
|
+
this.contextInvalidated = false;
|
|
9135
|
+
this.identityVisible.set(true);
|
|
9136
|
+
}
|
|
9137
|
+
ngOnInit() {
|
|
9110
9138
|
if (this.route) {
|
|
9111
9139
|
// 1. Extração estática síncrona
|
|
9112
9140
|
const data = this.route.snapshot.data || {};
|
|
@@ -9137,12 +9165,13 @@ class PraxisResourcePage {
|
|
|
9137
9165
|
}));
|
|
9138
9166
|
}
|
|
9139
9167
|
}
|
|
9168
|
+
this.restoreDefaultScope();
|
|
9169
|
+
this.contextSub = this.runtimeContext?.contextChanges$
|
|
9170
|
+
.subscribe((context) => this.onRuntimeContext(context));
|
|
9140
9171
|
}
|
|
9141
9172
|
ngOnDestroy() {
|
|
9142
9173
|
this.routeSub?.unsubscribe();
|
|
9143
|
-
|
|
9144
|
-
window.removeEventListener('praxis:identity-switch', this.onIdentitySwitch);
|
|
9145
|
-
}
|
|
9174
|
+
this.contextSub?.unsubscribe();
|
|
9146
9175
|
}
|
|
9147
9176
|
onScopeChange(item) {
|
|
9148
9177
|
this.activeScopeId.set(item.id);
|
|
@@ -9262,6 +9291,7 @@ class PraxisResourcePage {
|
|
|
9262
9291
|
|
|
9263
9292
|
<!-- Praxis CRUD Runtime com isolamento reativo multi-tenant -->
|
|
9264
9293
|
@if (effectiveResource() && identityVisible()) {
|
|
9294
|
+
@for (renderKey of [identityRenderKey()]; track renderKey) {
|
|
9265
9295
|
<section class="praxis-resource-page__crud-surface crud-surface glass-panel">
|
|
9266
9296
|
<praxis-crud
|
|
9267
9297
|
[resource]="effectiveResource()!"
|
|
@@ -9283,6 +9313,7 @@ class PraxisResourcePage {
|
|
|
9283
9313
|
(error)="error.emit($event)"
|
|
9284
9314
|
></praxis-crud>
|
|
9285
9315
|
</section>
|
|
9316
|
+
}
|
|
9286
9317
|
}
|
|
9287
9318
|
</div>
|
|
9288
9319
|
`, isInline: true, styles: [":host{display:block;width:100%;min-height:100%;box-sizing:border-box}.praxis-resource-page{width:100%;display:flex;flex-direction:column;gap:20px;padding:var(--praxis-page-padding, 24px);box-sizing:border-box;max-width:1540px;margin:0 auto}.praxis-resource-page__header{display:flex;justify-content:space-between;align-items:flex-start;gap:16px;flex-wrap:wrap}.praxis-resource-page__header-main{min-width:0;display:flex;flex-direction:column}.praxis-resource-page__domain-badge{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:9999px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;margin-bottom:8px;align-self:flex-start;background:var(--praxis-domain-badge-bg, rgba(255, 255, 255, .08));color:var(--praxis-domain-badge-color, inherit);border:1px solid var(--praxis-domain-badge-border, rgba(255, 255, 255, .1))}.praxis-resource-page__domain-badge span.material-symbols-outlined{font-size:14px}.praxis-resource-page__title{margin:0 0 6px;font-size:var(--praxis-page-title-size, 2rem);font-weight:800;letter-spacing:-.02em;color:var(--praxis-page-title-color, var(--foreground, inherit));line-height:1.2}.praxis-resource-page__subtitle{margin:0;font-size:var(--praxis-page-subtitle-size, .9rem);color:var(--muted-foreground, #94a3b8);max-width:800px;line-height:1.5}.praxis-resource-page__crud-surface{width:100%;border-radius:var(--praxis-surface-radius, 16px);overflow:hidden}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: PraxisCrudComponent, selector: "praxis-crud", inputs: ["metadata", "crudId", "resource", "componentInstanceId", "tableConfigPersistenceStrategy", "context", "enableCustomization", "showResourceIdentityKey", "authoringCapability", "filterCriteria", "filterTeleport", "disableAutoDrawer"], outputs: ["configureRequested", "afterOpen", "afterClose", "afterSave", "afterDelete", "reactiveDeterminationExecuted", "reactiveDeterminationPendingChange", "reactiveDeterminationStabilityChange", "error", "rowClick", "rowAction", "selectionChange", "resourceEvent", "tableRuntimeConfigChange", "drawerOpen", "drawerClose", "crudAuthoringDocumentApplied", "crudAuthoringDocumentSaved", "kpiCardClick"] }, { kind: "component", type: PraxisScopeBarComponent, selector: "praxis-scope-bar", inputs: ["items", "activeId", "showOmnibox", "omniboxPlaceholder", "omniboxValue", "omniboxDebounceMs", "leadIcon", "leadLabel", "showClearButton", "clearLabel", "target", "targetWidgetId", "scopeBarId", "searchField"], outputs: ["activeIdChange", "omniboxValueChange", "scopeChange", "searchChange", "filterCriteriaChange", "clear"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
@@ -9336,6 +9367,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
9336
9367
|
|
|
9337
9368
|
<!-- Praxis CRUD Runtime com isolamento reativo multi-tenant -->
|
|
9338
9369
|
@if (effectiveResource() && identityVisible()) {
|
|
9370
|
+
@for (renderKey of [identityRenderKey()]; track renderKey) {
|
|
9339
9371
|
<section class="praxis-resource-page__crud-surface crud-surface glass-panel">
|
|
9340
9372
|
<praxis-crud
|
|
9341
9373
|
[resource]="effectiveResource()!"
|
|
@@ -9357,6 +9389,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
9357
9389
|
(error)="error.emit($event)"
|
|
9358
9390
|
></praxis-crud>
|
|
9359
9391
|
</section>
|
|
9392
|
+
}
|
|
9360
9393
|
}
|
|
9361
9394
|
</div>
|
|
9362
9395
|
`, styles: [":host{display:block;width:100%;min-height:100%;box-sizing:border-box}.praxis-resource-page{width:100%;display:flex;flex-direction:column;gap:20px;padding:var(--praxis-page-padding, 24px);box-sizing:border-box;max-width:1540px;margin:0 auto}.praxis-resource-page__header{display:flex;justify-content:space-between;align-items:flex-start;gap:16px;flex-wrap:wrap}.praxis-resource-page__header-main{min-width:0;display:flex;flex-direction:column}.praxis-resource-page__domain-badge{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:9999px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;margin-bottom:8px;align-self:flex-start;background:var(--praxis-domain-badge-bg, rgba(255, 255, 255, .08));color:var(--praxis-domain-badge-color, inherit);border:1px solid var(--praxis-domain-badge-border, rgba(255, 255, 255, .1))}.praxis-resource-page__domain-badge span.material-symbols-outlined{font-size:14px}.praxis-resource-page__title{margin:0 0 6px;font-size:var(--praxis-page-title-size, 2rem);font-weight:800;letter-spacing:-.02em;color:var(--praxis-page-title-color, var(--foreground, inherit));line-height:1.2}.praxis-resource-page__subtitle{margin:0;font-size:var(--praxis-page-subtitle-size, .9rem);color:var(--muted-foreground, #94a3b8);max-width:800px;line-height:1.5}.praxis-resource-page__crud-surface{width:100%;border-radius:var(--praxis-surface-radius, 16px);overflow:hidden}\n"] }]
|
package/package.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxisui/crud",
|
|
3
|
-
"version": "10.0.0-rc.
|
|
3
|
+
"version": "10.0.0-rc.9",
|
|
4
4
|
"description": "CRUD building blocks for Praxis UI: integrates dynamic forms and tables with unified configuration and services.",
|
|
5
5
|
"peerDependencies": {
|
|
6
6
|
"@angular/common": "^21.0.0",
|
|
7
7
|
"@angular/core": "^21.0.0",
|
|
8
|
-
"@praxisui/dynamic-form": "^10.0.0-rc.
|
|
9
|
-
"@praxisui/table": "^10.0.0-rc.
|
|
10
|
-
"@praxisui/core": "^10.0.0-rc.
|
|
11
|
-
"@praxisui/dynamic-fields": "^10.0.0-rc.
|
|
12
|
-
"@praxisui/settings-panel": "^10.0.0-rc.
|
|
8
|
+
"@praxisui/dynamic-form": "^10.0.0-rc.9",
|
|
9
|
+
"@praxisui/table": "^10.0.0-rc.9",
|
|
10
|
+
"@praxisui/core": "^10.0.0-rc.9",
|
|
11
|
+
"@praxisui/dynamic-fields": "^10.0.0-rc.9",
|
|
12
|
+
"@praxisui/settings-panel": "^10.0.0-rc.9",
|
|
13
13
|
"@angular/cdk": "^21.0.0",
|
|
14
14
|
"@angular/forms": "^21.0.0",
|
|
15
15
|
"@angular/material": "^21.0.0",
|
|
16
16
|
"@angular/router": "^21.0.0",
|
|
17
|
-
"@praxisui/ai": "^10.0.0-rc.
|
|
17
|
+
"@praxisui/ai": "^10.0.0-rc.9",
|
|
18
18
|
"rxjs": "~7.8.0"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
package/types/praxisui-crud.d.ts
CHANGED
|
@@ -1039,7 +1039,12 @@ interface PraxisResourceScopeBarConfig {
|
|
|
1039
1039
|
*/
|
|
1040
1040
|
declare class PraxisResourcePage implements OnInit, OnDestroy {
|
|
1041
1041
|
private readonly route;
|
|
1042
|
+
private readonly runtimeContext;
|
|
1042
1043
|
private routeSub?;
|
|
1044
|
+
private contextSub?;
|
|
1045
|
+
private observedContext;
|
|
1046
|
+
private confirmedContextIdentity?;
|
|
1047
|
+
private contextInvalidated;
|
|
1043
1048
|
resource?: string;
|
|
1044
1049
|
resourcePath?: string;
|
|
1045
1050
|
crudId?: string;
|
|
@@ -1099,7 +1104,8 @@ declare class PraxisResourcePage implements OnInit, OnDestroy {
|
|
|
1099
1104
|
readonly resolvedCrudId: _angular_core.Signal<string>;
|
|
1100
1105
|
readonly effectiveMetadata: _angular_core.Signal<CrudMetadata>;
|
|
1101
1106
|
readonly defaultMetadata: _angular_core.Signal<CrudMetadata>;
|
|
1102
|
-
private
|
|
1107
|
+
private restoreDefaultScope;
|
|
1108
|
+
private onRuntimeContext;
|
|
1103
1109
|
ngOnInit(): void;
|
|
1104
1110
|
ngOnDestroy(): void;
|
|
1105
1111
|
onScopeChange(item: PraxisScopeBarItem): void;
|