@praxisui/core 9.0.41 → 9.0.43
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/ai/component-registry.json +4 -4
- package/fesm2022/praxisui-core.mjs +88 -13
- package/package.json +1 -1
- package/types/praxisui-core.d.ts +14 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "1.0.0",
|
|
3
|
-
"generatedAt": "2026-08-
|
|
3
|
+
"generatedAt": "2026-08-30T14:33:21.224Z",
|
|
4
4
|
"packageName": "@praxisui/core",
|
|
5
|
-
"packageVersion": "9.0.
|
|
5
|
+
"packageVersion": "9.0.43",
|
|
6
6
|
"sourceRegistry": "praxis-component-registry-ingestion",
|
|
7
7
|
"sourceRegistryVersion": "1.0.0",
|
|
8
8
|
"componentCount": 4,
|
|
@@ -4584,9 +4584,9 @@
|
|
|
4584
4584
|
{
|
|
4585
4585
|
"chunkIndex": 159,
|
|
4586
4586
|
"chunkKind": "recipe",
|
|
4587
|
-
"content": "{\"_comment\":\"Recipe para agentes criarem uma Praxis Dynamic Page com tabela rica sobre o quickstart publicado.\",\"_comment2\":\"Use quando a meta for demonstrar renderers, formatters e configuracao de coluna em praxis-table sem mudar o backend.\",\"templateMeta\":{\"registryKey\":\"praxis-dynamic-page\",\"variantId\":\"rich-table-surface\",\"status\":\"public-example\",\"useWhen\":\"Create a metadata-driven page that turns one resource table into a rich operational surface with explicit renderers and formatters.\",\"examplePrompts\":[\"crie uma tabela rica de funcionarios com avatar, badges, salario e datas\",\"gere um exemplo de praxis-table mostrando renderers e formatters\",\"monte uma dynamic page com tabela operacional usando o quickstart publicado\"]},\"platformValue\":{\"canonicalContract\":\"praxis-metadata-starter publishes the structural funcionarios schema through /schemas/filtered.\",\"referenceApi\":\"praxis-api-quickstart serves funcionarios data and options on Render.\",\"angularRuntime\":\"@praxisui/core resolves praxis-dynamic-page and @praxisui/table renders the configured table.\",\"publicExamples\":\"praxis-ui-landing-page exposes the JSON envelope, live runtime preview and capability coverage map.\",\"agentCorpus\":\"praxisui-http-examples provides executable metadata and filter evidence.\"},\"operationalEvidence\":{\"baseUrl\":\"https://praxis-api-quickstart.onrender.com\",\"safeFirstIds\":[\"filtered-schema-response-funcionarios\",\"funcionarios-filter-basic\"],\"httpExamples\":[\"praxisui-http-examples/http/metadata/filtered_schema_response_funcionarios.http\",\"praxisui-http-examples/http/resources/funcionarios_filter_basic.http\"]},\"authoringGuidance\":[\"Keep resourcePath as the base resource path, without /filter.\",\"Let /schemas/filtered provide the canonical field metadata.\",\"
|
|
4587
|
+
"content": "{\"_comment\":\"Recipe para agentes criarem uma Praxis Dynamic Page com tabela rica sobre o quickstart publicado.\",\"_comment2\":\"Use quando a meta for demonstrar renderers, formatters e configuracao de coluna em praxis-table sem mudar o backend.\",\"templateMeta\":{\"registryKey\":\"praxis-dynamic-page\",\"variantId\":\"rich-table-surface\",\"status\":\"public-example\",\"useWhen\":\"Create a metadata-driven page that turns one resource table into a rich operational surface with explicit renderers and formatters.\",\"examplePrompts\":[\"crie uma tabela rica de funcionarios com avatar, badges, salario e datas\",\"gere um exemplo de praxis-table mostrando renderers e formatters\",\"monte uma dynamic page com tabela operacional usando o quickstart publicado\"]},\"platformValue\":{\"canonicalContract\":\"praxis-metadata-starter publishes the structural funcionarios schema through /schemas/filtered.\",\"referenceApi\":\"praxis-api-quickstart serves funcionarios data and options on Render.\",\"angularRuntime\":\"@praxisui/core resolves praxis-dynamic-page and @praxisui/table renders the configured table.\",\"publicExamples\":\"praxis-ui-landing-page exposes the JSON envelope, live runtime preview and capability coverage map.\",\"agentCorpus\":\"praxisui-http-examples provides executable metadata and filter evidence.\"},\"operationalEvidence\":{\"baseUrl\":\"https://praxis-api-quickstart.onrender.com\",\"safeFirstIds\":[\"filtered-schema-response-funcionarios\",\"funcionarios-filter-basic\"],\"httpExamples\":[\"praxisui-http-examples/http/metadata/filtered_schema_response_funcionarios.http\",\"praxisui-http-examples/http/resources/funcionarios_filter_basic.http\"]},\"authoringGuidance\":[\"Keep resourcePath as the base resource path, without /filter.\",\"Let /schemas/filtered provide the canonical field metadata.\",\"Keep columns empty and use columnProjection overrides for renderers, formatting, width, sticky columns and visual density.\",\"Prefer renderer examples that map to real backend fields; do not invent frontend-only fields for a remote example.\",\"Keep status presentation read-only unless a real backend action is configured.\",\"Treat salary as sensitive demonstration data; real hosts should gate visibility and exports through policy.\",\"Emit rowClick and selectionChange so the page can later compose this table with forms, charts or actions.\"],\"teaches\":[\"table.renderers.avatar\",\"table.renderers.compose\",\"table.renderers.badge\",\"table.renderers.chip\",\"table.conditional-renderers.status-badge\",\"table.formatters.currency\",\"table.formatters.date\",\"table.selection-state\"],\"page\":{\"layout\":{\"orientation\":\"columns\",\"columns\":1,\"gap\":\"16px\"},\"widgets\":[{\"key\":\"funcionariosRichTable\",\"shell\":{\"kind\":\"dashboard-card\",\"icon\":\"table\",\"title\":\"Funcionarios rich surface\",\"subtitle\":\"Renderers, formatters and dense business columns\"},\"definition\":{\"id\":\"praxis-table\",\"bindingOrder\":[\"config\",\"resourcePath\"],\"inputs\":{\"resourcePath\":\"human-resources/funcionarios\",\"tableId\":\"human-resources-funcionarios-rich-surface\",\"config\":{\"toolbar\":{\"visible\":true,\"title\":\"Funcionarios\",\"subtitle\":\"Rich metadata-driven employee surface\"},\"columns\":[],\"columnProjection\":{\"source\":\"schema\",\"include\":[\"nomeCompleto\",\"email\",\"telefone\",\"salario\",\"cargoNome\",\"departamentoNome\",\"estadoCivil\",\"dataAdmissao\",\"dataNascimento\",\"ativo\"],\"overrides\":{\"nomeCompleto\":{\"header\":\"Nome Completo\",\"sticky\":\"start\",\"width\":\"260px\",\"renderer\":{\"type\":\"compose\",\"compose\":{\"items\":[{\"type\":\"avatar\",\"avatar\":{\"srcField\":\"avatarUrl\",\"altField\":\"nomeCompleto\",\"initialsField\":\"nomeCompleto\",\"shape\":\"circle\",\"size\":36}},{\"type\":\"value\",\"field\":\"nomeCompleto\"}],\"layout\":{\"direction\":\"row\",\"align\":\"center\",\"gap\":10}}}},\"email\":{\"header\":\"Email\",\"width\":\"260px\"},\"telefone\":{\"header\":\"Telefone\",\"width\":\"160px\"},\"salario\":{\"header\":\"Salario\",\"type\":\"currency\",\"align\":\"end\",\"format\":\"BRL|symbol|2\",\"width\":\"150px\"},\"cargoNome\":{\"header\":\"Cargo\",\"renderer\":{\"type\":\"chip\",\"chip\":{\"textField\":\"cargoNome\",\"variant\":\"outlined\",\"color\":\"primary\"}},\"width\":\"190px\"},\"departamentoNome\":{\"header\":\"Departamento\",\"renderer\":{\"type\":\"badge\",\"badge\":{\"textField\":\"departamentoNome\",\"variant\":\"soft\",\"color\":\"accent\"}},\"width\":\"180px\"},\"estadoCivil\":{\"header\":\"Estado Civil\",\"renderer\":{\"type\":\"badge\",\"badge\":{\"textField\":\"estadoCivil\",\"variant\":\"outlined\",\"color\":\"primary\"}},\"width\":\"150px\"},\"dataAdmissao\":{\"header\":\"Data de Admissao\",\"format\":\"dd/MM/yyyy\",\"width\":\"170px\"},\"dataNascimento\":{\"header\":\"Data de Nascimento\",\"format\":\"dd/MM/yyyy\",\"width\":\"190px\"},\"ativo\":{\"header\":\"Status\",\"align\":\"center\",\"format\":\"active-inactive\",\"width\":\"130px\",\"conditionalRenderers\":[{\"id\":\"status-ativo\",\"condition\":{\"==\":[{\"var\":\"ativo\"},true]},\"renderer\":{\"type\":\"badge\",\"badge\":{\"text\":\"Ativo\",\"color\":\"success\",\"variant\":\"filled\",\"icon\":\"check_circle\"}}},{\"id\":\"status-inativo\",\"condition\":{\"==\":[{\"var\":\"ativo\"},false]},\"renderer\":{\"type\":\"badge\",\"badge\":{\"text\":\"Inativo\",\"color\":\"warn\",\"variant\":\"outlined\",\"icon\":\"block\"}}}]}}},\"behavior\":{\"selection\":{\"enabled\":true,\"type\":\"multiple\"},\"density\":\"compact\"}}},\"outputs\":{\"rowClick\":\"emit\",\"selectionChange\":\"emit\"}}}]}}",
|
|
4588
4588
|
"sourcePointer": "examples/ai-recipes/praxis-dynamic-page.rich-table-surface.json",
|
|
4589
|
-
"contentHash": "
|
|
4589
|
+
"contentHash": "aa3ab19cc0da083075076d3efa34a947b4ec087f09aba04260d6af8ee53282b6",
|
|
4590
4590
|
"sourceKind": "component_definition",
|
|
4591
4591
|
"sourceId": "praxis-dynamic-page",
|
|
4592
4592
|
"corpusVersion": "1.0.0"
|
|
@@ -40667,12 +40667,14 @@ class DynamicWidgetPageComponent {
|
|
|
40667
40667
|
this.savePage(canonicalPage);
|
|
40668
40668
|
}
|
|
40669
40669
|
}
|
|
40670
|
-
applyLayout(layout, grouping) {
|
|
40670
|
+
applyLayout(layout, grouping, deviceLayoutColumnsSelected = false) {
|
|
40671
40671
|
this.layout = layout;
|
|
40672
40672
|
this.canvas = undefined;
|
|
40673
40673
|
this.grouping = grouping || [];
|
|
40674
40674
|
const orientation = layout?.orientation || 'vertical';
|
|
40675
|
-
const columns = orientation === 'columns'
|
|
40675
|
+
const columns = orientation === 'columns'
|
|
40676
|
+
? this.resolveColumns(layout, deviceLayoutColumnsSelected)
|
|
40677
|
+
: 1;
|
|
40676
40678
|
this.pageColumnCount = columns;
|
|
40677
40679
|
this.gridTemplateColumns = `repeat(${columns}, minmax(0, 1fr))`;
|
|
40678
40680
|
this.pageGap = layout?.gap || '16px';
|
|
@@ -40832,14 +40834,16 @@ class DynamicWidgetPageComponent {
|
|
|
40832
40834
|
this.layoutAnnouncement = this.blockedCanvasAnnouncement(interaction.kind);
|
|
40833
40835
|
this.applyTransientPagePreview(interaction.startPage, this.buildStateRuntime(interaction.startPage.state, interaction.startPage.context));
|
|
40834
40836
|
}
|
|
40835
|
-
resolveColumns(layout) {
|
|
40837
|
+
resolveColumns(layout, deviceLayoutColumnsSelected = false) {
|
|
40836
40838
|
const base = Math.max(1, Number(layout?.columns) || 2);
|
|
40837
|
-
const defaults =
|
|
40838
|
-
sm:
|
|
40839
|
-
|
|
40840
|
-
|
|
40841
|
-
|
|
40842
|
-
|
|
40839
|
+
const defaults = deviceLayoutColumnsSelected
|
|
40840
|
+
? { sm: base, md: base, lg: base, xl: base }
|
|
40841
|
+
: {
|
|
40842
|
+
sm: 1,
|
|
40843
|
+
md: Math.min(2, base),
|
|
40844
|
+
lg: Math.min(3, base),
|
|
40845
|
+
xl: base,
|
|
40846
|
+
};
|
|
40843
40847
|
const bp = layout?.breakpoints || {};
|
|
40844
40848
|
const columns = {
|
|
40845
40849
|
sm: Math.max(1, Number(bp.sm ?? defaults.sm)),
|
|
@@ -40928,7 +40932,7 @@ class DynamicWidgetPageComponent {
|
|
|
40928
40932
|
this.applyCanvasLayout(effective.canvas, effective.layout, effective.grouping);
|
|
40929
40933
|
}
|
|
40930
40934
|
else {
|
|
40931
|
-
this.applyLayout(effective.layout, effective.grouping);
|
|
40935
|
+
this.applyLayout(effective.layout, effective.grouping, effective.deviceLayoutColumnsSelected);
|
|
40932
40936
|
}
|
|
40933
40937
|
this.syncActiveTabs(effective.groups);
|
|
40934
40938
|
this.mergedContext = this.mergeContext(pageDefinition?.context, this.context, runtime, {
|
|
@@ -40987,6 +40991,7 @@ class DynamicWidgetPageComponent {
|
|
|
40987
40991
|
layout,
|
|
40988
40992
|
canvas,
|
|
40989
40993
|
grouping,
|
|
40994
|
+
deviceLayoutColumnsSelected: variant?.layout?.columns !== undefined,
|
|
40990
40995
|
widgets: renderedWidgets,
|
|
40991
40996
|
groups,
|
|
40992
40997
|
};
|
|
@@ -41905,9 +41910,10 @@ class DynamicWidgetPageComponent {
|
|
|
41905
41910
|
if (canvasItem) {
|
|
41906
41911
|
return `${canvasItem.col} / span ${canvasItem.colSpan}`;
|
|
41907
41912
|
}
|
|
41908
|
-
|
|
41913
|
+
const renderSpan = Math.min(this.pageColumnCount, Math.max(1, Math.trunc(Number(widget.renderSpan) || 1)));
|
|
41914
|
+
if (renderSpan <= 1)
|
|
41909
41915
|
return null;
|
|
41910
|
-
return `span ${
|
|
41916
|
+
return `span ${renderSpan}`;
|
|
41911
41917
|
}
|
|
41912
41918
|
widgetGridRow(widget) {
|
|
41913
41919
|
const canvasItem = this.resolveRenderedCanvasItem(widget);
|
|
@@ -41935,7 +41941,76 @@ class DynamicWidgetPageComponent {
|
|
|
41935
41941
|
}
|
|
41936
41942
|
toPersistedCanonicalPage(page) {
|
|
41937
41943
|
this.assertNoLegacyConnections(page);
|
|
41938
|
-
|
|
41944
|
+
const canonicalPage = this.stripDerivedPresetDefaults(page);
|
|
41945
|
+
return writeCompositionLinksToPersistedPage(canonicalPage, canonicalPage.composition?.links || []);
|
|
41946
|
+
}
|
|
41947
|
+
/**
|
|
41948
|
+
* Preset defaults are a runtime projection, not authored page state.
|
|
41949
|
+
*
|
|
41950
|
+
* Keeping an identical derived grouping in the persisted document would turn
|
|
41951
|
+
* semantic slot ids such as `master` and `detail-table` into apparent widget
|
|
41952
|
+
* references. The canonical page therefore keeps the preset id and slot
|
|
41953
|
+
* assignments while omitting defaults that the runtime can deterministically
|
|
41954
|
+
* rehydrate. Explicit overrides remain persisted.
|
|
41955
|
+
*/
|
|
41956
|
+
stripDerivedPresetDefaults(page) {
|
|
41957
|
+
const canonical = this.clonePageDefinition(page);
|
|
41958
|
+
const preset = this.resolveLayoutPresetDefinition(canonical);
|
|
41959
|
+
if (!preset)
|
|
41960
|
+
return canonical;
|
|
41961
|
+
const layoutDelta = this.jsonObjectDelta(canonical.layout, preset.defaultLayout);
|
|
41962
|
+
if (layoutDelta) {
|
|
41963
|
+
canonical.layout = layoutDelta;
|
|
41964
|
+
}
|
|
41965
|
+
else {
|
|
41966
|
+
delete canonical.layout;
|
|
41967
|
+
}
|
|
41968
|
+
if (this.sameJsonStructure(canonical.grouping, preset.defaultGrouping)) {
|
|
41969
|
+
delete canonical.grouping;
|
|
41970
|
+
}
|
|
41971
|
+
if (canonical.themePreset === preset.defaultThemePreset) {
|
|
41972
|
+
delete canonical.themePreset;
|
|
41973
|
+
}
|
|
41974
|
+
return canonical;
|
|
41975
|
+
}
|
|
41976
|
+
jsonObjectDelta(value, defaults) {
|
|
41977
|
+
if (!value)
|
|
41978
|
+
return undefined;
|
|
41979
|
+
const delta = {};
|
|
41980
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
41981
|
+
const defaultEntry = defaults?.[key];
|
|
41982
|
+
if (this.isJsonObject(entry) && this.isJsonObject(defaultEntry)) {
|
|
41983
|
+
const nestedDelta = this.jsonObjectDelta(entry, defaultEntry);
|
|
41984
|
+
if (nestedDelta)
|
|
41985
|
+
delta[key] = nestedDelta;
|
|
41986
|
+
continue;
|
|
41987
|
+
}
|
|
41988
|
+
if (!this.sameJsonStructure(entry, defaultEntry)) {
|
|
41989
|
+
delta[key] = this.stableJsonValue(entry);
|
|
41990
|
+
}
|
|
41991
|
+
}
|
|
41992
|
+
return Object.keys(delta).length ? delta : undefined;
|
|
41993
|
+
}
|
|
41994
|
+
isJsonObject(value) {
|
|
41995
|
+
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
41996
|
+
}
|
|
41997
|
+
sameJsonStructure(left, right) {
|
|
41998
|
+
return JSON.stringify(this.stableJsonValue(left)) ===
|
|
41999
|
+
JSON.stringify(this.stableJsonValue(right));
|
|
42000
|
+
}
|
|
42001
|
+
stableJsonValue(value) {
|
|
42002
|
+
if (Array.isArray(value)) {
|
|
42003
|
+
return value.map((entry) => this.stableJsonValue(entry));
|
|
42004
|
+
}
|
|
42005
|
+
if (this.isJsonObject(value)) {
|
|
42006
|
+
return Object.keys(value)
|
|
42007
|
+
.sort()
|
|
42008
|
+
.reduce((result, key) => {
|
|
42009
|
+
result[key] = this.stableJsonValue(value[key]);
|
|
42010
|
+
return result;
|
|
42011
|
+
}, {});
|
|
42012
|
+
}
|
|
42013
|
+
return value;
|
|
41939
42014
|
}
|
|
41940
42015
|
savePage(page) {
|
|
41941
42016
|
const key = this.storageKey();
|
package/package.json
CHANGED
package/types/praxisui-core.d.ts
CHANGED
|
@@ -16835,6 +16835,20 @@ declare class DynamicWidgetPageComponent implements OnChanges, OnDestroy {
|
|
|
16835
16835
|
private mergeClassNames;
|
|
16836
16836
|
private resolveRenderedCanvasItem;
|
|
16837
16837
|
private toPersistedCanonicalPage;
|
|
16838
|
+
/**
|
|
16839
|
+
* Preset defaults are a runtime projection, not authored page state.
|
|
16840
|
+
*
|
|
16841
|
+
* Keeping an identical derived grouping in the persisted document would turn
|
|
16842
|
+
* semantic slot ids such as `master` and `detail-table` into apparent widget
|
|
16843
|
+
* references. The canonical page therefore keeps the preset id and slot
|
|
16844
|
+
* assignments while omitting defaults that the runtime can deterministically
|
|
16845
|
+
* rehydrate. Explicit overrides remain persisted.
|
|
16846
|
+
*/
|
|
16847
|
+
private stripDerivedPresetDefaults;
|
|
16848
|
+
private jsonObjectDelta;
|
|
16849
|
+
private isJsonObject;
|
|
16850
|
+
private sameJsonStructure;
|
|
16851
|
+
private stableJsonValue;
|
|
16838
16852
|
private savePage;
|
|
16839
16853
|
private loadPersistedPage;
|
|
16840
16854
|
private storageKey;
|