@praxisui/page-builder 6.0.0-beta.0 → 8.0.0-beta.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 CHANGED
@@ -53,6 +53,7 @@ import { bootstrapApplication } from '@angular/platform-browser';
53
53
  import { PAGE_BUILDER_WIDGET_AI_CATALOGS, providePageBuilderWidgetAiCatalogs } from '@praxisui/page-builder';
54
54
  import { TABLE_AI_CAPABILITIES } from '@praxisui/table';
55
55
  import { CRUD_AI_CAPABILITIES } from '@praxisui/crud';
56
+ import { RICH_CONTENT_AI_CAPABILITIES } from '@praxisui/rich-content';
56
57
  import { AppComponent } from './app/app.component';
57
58
 
58
59
  bootstrapApplication(AppComponent, {
@@ -62,6 +63,7 @@ bootstrapApplication(AppComponent, {
62
63
  useValue: {
63
64
  'praxis-table': TABLE_AI_CAPABILITIES,
64
65
  'praxis-crud': CRUD_AI_CAPABILITIES,
66
+ 'praxis-rich-content': RICH_CONTENT_AI_CAPABILITIES,
65
67
  },
66
68
  },
67
69
  providePageBuilderWidgetAiCatalogs(),
@@ -75,10 +77,12 @@ Registro manual (util para apps que precisam customizar o mapa):
75
77
  import { registerWidgetAiCatalogs } from '@praxisui/page-builder';
76
78
  import { TABLE_AI_CAPABILITIES } from '@praxisui/table';
77
79
  import { CRUD_AI_CAPABILITIES } from '@praxisui/crud';
80
+ import { RICH_CONTENT_AI_CAPABILITIES } from '@praxisui/rich-content';
78
81
 
79
82
  registerWidgetAiCatalogs({
80
83
  'praxis-table': TABLE_AI_CAPABILITIES,
81
84
  'praxis-crud': CRUD_AI_CAPABILITIES,
85
+ 'praxis-rich-content': RICH_CONTENT_AI_CAPABILITIES,
82
86
  });
83
87
  ```
84
88
 
@@ -101,10 +105,32 @@ providers: [
101
105
  ]
102
106
  ```
103
107
 
108
+ ## Component Config Editors
109
+
110
+ O page-builder não deve implementar editores locais para os inputs de cada
111
+ widget. Quando um componente registra `ComponentDocMeta.configEditor`, o runtime
112
+ canônico (`praxis-dynamic-page`) injeta a ação "Configurar conteudo" no shell do
113
+ widget e abre o editor declarado pelo dono do componente.
114
+
115
+ Fluxo canônico:
116
+
117
+ - a lib dona registra `configEditor` em `ComponentMetadataRegistry`
118
+ - o page-builder habilita customization e fornece `SETTINGS_PANEL_BRIDGE`
119
+ - o editor recebe `{ inputs, widgetKey, widgetType }`
120
+ - `Apply` atualiza `definition.inputs` sem fechar o painel; ele não é rollback transacional e pode ser observado pelo host imediatamente
121
+ - `Save` atualiza `definition.inputs` e persiste a página quando houver `pageIdentity`
122
+ - `Reset` restaura o estado interno do editor para o snapshot aberto; ele não desfaz automaticamente um `Apply` já emitido ao runtime/host
123
+
124
+ Exemplo com `praxis-rich-content`: o editor canônico é
125
+ `PraxisRichContentConfigEditor`, publicado por `@praxisui/rich-content`. Ele
126
+ edita `definition.inputs.document`, `layout` e `rootClassName` sem criar uma DSL
127
+ local de page-builder para blocos ricos.
128
+
104
129
  Catalogos conhecidos (exports):
105
130
  - `TABLE_AI_CAPABILITIES` - `@praxisui/table` (`praxis-table`)
106
131
  - `CRUD_AI_CAPABILITIES` - `@praxisui/crud` (`praxis-crud`)
107
132
  - `LIST_AI_CAPABILITIES` - `@praxisui/list` (`praxis-list`)
133
+ - `RICH_CONTENT_AI_CAPABILITIES` - `@praxisui/rich-content` (`praxis-rich-content`)
108
134
  - `FORM_AI_CAPABILITIES` - `@praxisui/dynamic-form` (`praxis-dynamic-form`)
109
135
  - `FILES_UPLOAD_AI_CAPABILITIES` - `@praxisui/files-upload` (`praxis-files-upload`)
110
136
  - `STEPPER_AI_CAPABILITIES` - `@praxisui/stepper` (`praxis-stepper`)
@@ -126,6 +152,12 @@ O builder canonico expoe authoring de shell/palette sobre `praxis-dynamic-page`.
126
152
 
127
153
  `page` e um `WidgetPageDefinition` (do `@praxisui/core`) contendo `widgets` e opcionalmente `composition.links`. O envelope `composition` e o caminho `composition.links` formam a superficie canonica persistida para wiring da pagina, com `condition` em Json Logic e `policy` para comportamento operacional.
128
154
 
155
+ Para conteudo editorial rico dentro da pagina, use um widget `praxis-rich-content`
156
+ com `definition.inputs.document: RichContentDocument`. Isso evita criar uma DSL
157
+ local de page-builder para cards, imagens, timelines ou blocos de apresentacao,
158
+ e preserva `WidgetPageDefinition.widgets` como superficie unica de ocupacao do
159
+ canvas.
160
+
129
161
  ## Widget Shell (Dashboard Cards)
130
162
 
131
163
  Cada widget pode declarar um `shell` para renderizar um card padronizado com cabecalho rico, acoes de contexto e controles de janela (expandir/recolher).
@@ -9,7 +9,7 @@ import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
9
9
  import * as i3 from '@angular/material/icon';
10
10
  import { MatIconModule } from '@angular/material/icon';
11
11
  import * as i2$2 from '@praxisui/core';
12
- import { PraxisIconDirective, BUILTIN_SHELL_PRESETS, SETTINGS_PANEL_DATA as SETTINGS_PANEL_DATA$1, providePraxisI18n, BUILTIN_PAGE_LAYOUT_PRESETS, BUILTIN_PAGE_THEME_PRESETS, PraxisI18nService, generateId, SETTINGS_PANEL_BRIDGE, DynamicWidgetPageComponent, DYNAMIC_PAGE_SHELL_EDITOR } from '@praxisui/core';
12
+ import { PraxisIconDirective, BUILTIN_SHELL_PRESETS, SETTINGS_PANEL_DATA as SETTINGS_PANEL_DATA$1, providePraxisI18n, BUILTIN_PAGE_LAYOUT_PRESETS, BUILTIN_PAGE_THEME_PRESETS, PraxisI18nService, ComponentMetadataRegistry, generateId, SETTINGS_PANEL_BRIDGE, DynamicWidgetPageComponent, DYNAMIC_PAGE_SHELL_EDITOR } from '@praxisui/core';
13
13
  export { WidgetShellComponent } from '@praxisui/core';
14
14
  import * as i4 from '@angular/material/tooltip';
15
15
  import { MatTooltipModule } from '@angular/material/tooltip';
@@ -4614,6 +4614,8 @@ const PAGE_BUILDER_AI_CAPABILITIES = {
4614
4614
  ],
4615
4615
  notes: [
4616
4616
  'page segue o modelo canonico WidgetPageDefinition (widgets, composition.links, context e state opcional).',
4617
+ 'Conteudo editorial rico deve ser modelado como widget praxis-rich-content com definition.inputs.document: RichContentDocument, nao como DSL local do page-builder.',
4618
+ 'Edicao visual de inputs de widget deve usar ComponentDocMeta.configEditor publicado pela lib dona do componente; nao criar editor local no page-builder para semantica de outro pacote.',
4617
4619
  'Canvas e o modelo espacial canonico da pagina quando houver posicionamento explicito.',
4618
4620
  'Taxonomia editorial: condition usa Json Logic canonico; transform usa pipeline declarativo; policy cobre apenas comportamento operacional.',
4619
4621
  'Payloads legados de layout ainda podem ser ingeridos, mas sao normalizados para canvas e nao devem ser reemitidos.',
@@ -4656,7 +4658,11 @@ const PAGE_BUILDER_AI_CAPABILITIES = {
4656
4658
  { path: 'page.widgets[].definition', category: 'widgets', valueKind: 'object', description: 'Definicao do widget (WidgetDefinition).' },
4657
4659
  { path: 'page.widgets[].definition.id', category: 'widgets', valueKind: 'string', description: 'ID do componente registrado.' },
4658
4660
  { path: 'page.widgets[].definition.inputs', category: 'widgets', valueKind: 'object', description: 'Inputs do componente.' },
4661
+ { path: 'page.widgets[].definition.inputs.document', category: 'widgets', valueKind: 'object', description: 'RichContentDocument quando definition.id for praxis-rich-content.' },
4659
4662
  { path: 'page.widgets[].definition.bindingOrder', category: 'widgets', valueKind: 'array', description: 'Ordem de aplicacao dos inputs.' },
4663
+ { path: 'ComponentDocMeta.configEditor', category: 'widgets', valueKind: 'object', description: 'Editor canonico de inputs publicado pela lib dona do componente e aberto pelo settings-panel do host.' },
4664
+ { path: 'ComponentDocMeta.configEditor.component', category: 'widgets', valueKind: 'object', description: 'Componente standalone que implementa SettingsValueProvider para editar definition.inputs.' },
4665
+ { path: 'ComponentDocMeta.configEditor.title', category: 'widgets', valueKind: 'string', description: 'Titulo opcional usado pelo host ao abrir o editor de inputs do componente.' },
4660
4666
  { path: 'page.composition', category: 'connections', valueKind: 'object', description: 'Envelope canonico da composicao persistida.' },
4661
4667
  { path: 'page.composition.version', category: 'connections', valueKind: 'string', description: 'Versao do envelope de composicao.' },
4662
4668
  { path: 'page.composition.links', category: 'connections', valueKind: 'array', description: 'Links canonicos entre widgets e estado.' },
@@ -5320,6 +5326,7 @@ class DynamicPageBuilderComponent {
5320
5326
  dialog;
5321
5327
  settingsPanel;
5322
5328
  i18n = inject(PraxisI18nService);
5329
+ componentMetadata = inject(ComponentMetadataRegistry);
5323
5330
  runtime;
5324
5331
  page;
5325
5332
  context = null;
@@ -5372,7 +5379,7 @@ class DynamicPageBuilderComponent {
5372
5379
  addWidget(type) {
5373
5380
  const next = this.clonePage(this.currentPage());
5374
5381
  const key = `${type}-${generateId()}`;
5375
- const widgets = [...(next.widgets || []), { key, definition: { id: type, inputs: {} } }];
5382
+ const widgets = [...(next.widgets || []), { key, definition: { id: type, inputs: this.defaultInputsFor(type) } }];
5376
5383
  next.widgets = widgets;
5377
5384
  if (next.canvas) {
5378
5385
  const lastRow = Math.max(1, ...Object.values(next.canvas.items || {}).map((item) => (item.row + item.rowSpan) - 1));
@@ -5423,6 +5430,22 @@ class DynamicPageBuilderComponent {
5423
5430
  clonePage(page) {
5424
5431
  return JSON.parse(JSON.stringify(page));
5425
5432
  }
5433
+ defaultInputsFor(type) {
5434
+ const metadata = this.componentMetadata.get(type);
5435
+ const inputs = {};
5436
+ for (const input of metadata?.inputs ?? []) {
5437
+ if (input.default !== undefined) {
5438
+ inputs[input.name] = this.cloneValue(input.default);
5439
+ }
5440
+ }
5441
+ return inputs;
5442
+ }
5443
+ cloneValue(value) {
5444
+ if (value == null || typeof value !== 'object') {
5445
+ return value;
5446
+ }
5447
+ return JSON.parse(JSON.stringify(value));
5448
+ }
5426
5449
  tx(key, fallback) {
5427
5450
  return resolvePraxisPageBuilderText(this.i18n, key, fallback);
5428
5451
  }
package/index.d.ts CHANGED
@@ -249,7 +249,7 @@ declare class DynamicPageConfigEditorComponent implements OnInit, SettingsValueP
249
249
  readonly canvasColumnsControl: FormControl<number>;
250
250
  readonly canvasRowUnitControl: FormControl<string>;
251
251
  readonly canvasGapControl: FormControl<string>;
252
- readonly canvasAutoRowsControl: FormControl<"fixed" | "content">;
252
+ readonly canvasAutoRowsControl: FormControl<"content" | "fixed">;
253
253
  readonly layoutPresetControl: FormControl<string>;
254
254
  readonly themePresetControl: FormControl<string>;
255
255
  readonly shellPresetControl: FormControl<string>;
@@ -600,6 +600,7 @@ declare class DynamicPageBuilderComponent implements OnChanges {
600
600
  private dialog;
601
601
  private settingsPanel;
602
602
  private readonly i18n;
603
+ private readonly componentMetadata;
603
604
  runtime?: DynamicWidgetPageComponent;
604
605
  page?: WidgetPageDefinition | string;
605
606
  context?: Record<string, unknown> | null;
@@ -626,6 +627,8 @@ declare class DynamicPageBuilderComponent implements OnChanges {
626
627
  focusCanvasWidget(widgetKey: string): void;
627
628
  private parsePage;
628
629
  private clonePage;
630
+ private defaultInputsFor;
631
+ private cloneValue;
629
632
  tx(key: string, fallback: string): string;
630
633
  static ɵfac: i0.ɵɵFactoryDeclaration<DynamicPageBuilderComponent, [null, { optional: true; }]>;
631
634
  static ɵcmp: i0.ɵɵComponentDeclaration<DynamicPageBuilderComponent, "praxis-dynamic-page-builder", never, { "page": { "alias": "page"; "required": false; }; "context": { "alias": "context"; "required": false; }; "strictValidation": { "alias": "strictValidation"; "required": false; }; "enableCustomization": { "alias": "enableCustomization"; "required": false; }; "showSettingsButton": { "alias": "showSettingsButton"; "required": false; }; "pageIdentity": { "alias": "pageIdentity"; "required": false; }; "componentInstanceId": { "alias": "componentInstanceId"; "required": false; }; "pageEditorComponent": { "alias": "pageEditorComponent"; "required": false; }; }, { "pageChange": "pageChange"; }, never, never, true, never>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxisui/page-builder",
3
- "version": "6.0.0-beta.0",
3
+ "version": "8.0.0-beta.0",
4
4
  "description": "Page and widget builder utilities for Praxis UI (grid, dynamic widgets, editors).",
5
5
  "peerDependencies": {
6
6
  "@angular/common": "^20.0.0",
@@ -8,8 +8,8 @@
8
8
  "@angular/forms": "^20.0.0",
9
9
  "@angular/cdk": "^20.0.0",
10
10
  "@angular/material": "^20.0.0",
11
- "@praxisui/core": "^6.0.0-beta.0",
12
- "@praxisui/settings-panel": "^6.0.0-beta.0"
11
+ "@praxisui/core": "^8.0.0-beta.0",
12
+ "@praxisui/settings-panel": "^8.0.0-beta.0"
13
13
  },
14
14
  "dependencies": {
15
15
  "tslib": "^2.3.0"