@praxisui/page-builder 9.0.4-rc.39 → 9.0.4-rc.40

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.
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-08-10T02:36:18.987Z",
3
+ "generatedAt": "2026-08-10T11:49:21.807Z",
4
4
  "packageName": "@praxisui/page-builder",
5
- "packageVersion": "9.0.4-rc.39",
5
+ "packageVersion": "9.0.4-rc.40",
6
6
  "sourceRegistry": "praxis-component-registry-ingestion",
7
7
  "sourceRegistryVersion": "1.0.0",
8
8
  "componentCount": 1,
@@ -900,6 +900,9 @@ class WidgetShellEditorComponent {
900
900
  isValid$ = this.validSubject.asObservable();
901
901
  isBusy$ = this.busySubject.asObservable();
902
902
  snapshot = '';
903
+ initialTitle;
904
+ initialSubtitle;
905
+ actionCopySources = new WeakMap();
903
906
  presetOptions = [...BUILTIN_PRESET_OPTIONS];
904
907
  presets = { ...BUILTIN_PRESET_MAP };
905
908
  availableActions = [];
@@ -971,6 +974,8 @@ class WidgetShellEditorComponent {
971
974
  this.applyShell(shell);
972
975
  }
973
976
  applyShell(shell) {
977
+ this.initialTitle = shell?.title;
978
+ this.initialSubtitle = shell?.subtitle;
974
979
  const showHeader = shell?.showHeader == null ? 'auto' : shell.showHeader ? 'true' : 'false';
975
980
  const window = shell?.windowActions || {};
976
981
  const appearance = shell?.appearance || {};
@@ -983,8 +988,8 @@ class WidgetShellEditorComponent {
983
988
  kind: shell?.kind === 'none' ? 'none' : 'dashboard-card',
984
989
  preset: shell?.preset || '',
985
990
  applyToAll: false,
986
- title: shell?.title || '',
987
- subtitle: shell?.subtitle || '',
991
+ title: this.editableText(shell?.title),
992
+ subtitle: this.editableText(shell?.subtitle),
988
993
  icon: shell?.icon || '',
989
994
  showHeader,
990
995
  collapsible: window.collapsible !== false,
@@ -1039,19 +1044,21 @@ class WidgetShellEditorComponent {
1039
1044
  this.availableActions = [...actions, ...commands];
1040
1045
  }
1041
1046
  createActionGroup(seed) {
1042
- return new FormGroup({
1047
+ const group = new FormGroup({
1043
1048
  id: new FormControl(seed?.id || '', { nonNullable: true, validators: [Validators.required] }),
1044
- label: new FormControl(seed?.label || '', { nonNullable: true }),
1049
+ label: new FormControl(this.editableText(seed?.label), { nonNullable: true }),
1045
1050
  icon: new FormControl(seed?.icon || '', { nonNullable: true }),
1046
1051
  variant: new FormControl(seed?.variant || 'text', { nonNullable: true }),
1047
1052
  placement: new FormControl(seed?.placement || 'header', { nonNullable: true }),
1048
1053
  emit: new FormControl(seed?.emit || '', { nonNullable: true }),
1049
- tooltip: new FormControl(seed?.tooltip || '', { nonNullable: true }),
1054
+ tooltip: new FormControl(this.editableText(seed?.tooltip), { nonNullable: true }),
1050
1055
  command: new FormControl(seed?.command || '', { nonNullable: true }),
1051
1056
  payload: new FormControl(seed?.payload != null ? JSON.stringify(seed.payload) : '', { nonNullable: true }),
1052
1057
  visible: new FormControl(seed?.visible !== false, { nonNullable: true }),
1053
1058
  disabled: new FormControl(!!seed?.disabled, { nonNullable: true }),
1054
1059
  });
1060
+ this.actionCopySources.set(group, { label: seed?.label, tooltip: seed?.tooltip });
1061
+ return group;
1055
1062
  }
1056
1063
  buildShell() {
1057
1064
  const raw = this.form.getRawValue();
@@ -1061,10 +1068,12 @@ class WidgetShellEditorComponent {
1061
1068
  const shell = {};
1062
1069
  if (raw.preset)
1063
1070
  shell.preset = raw.preset;
1064
- if (raw.title.trim())
1065
- shell.title = raw.title.trim();
1066
- if (raw.subtitle.trim())
1067
- shell.subtitle = raw.subtitle.trim();
1071
+ const title = this.preserveTextDescriptor(this.initialTitle, raw.title);
1072
+ const subtitle = this.preserveTextDescriptor(this.initialSubtitle, raw.subtitle);
1073
+ if (title)
1074
+ shell.title = title;
1075
+ if (subtitle)
1076
+ shell.subtitle = subtitle;
1068
1077
  if (raw.icon.trim())
1069
1078
  shell.icon = raw.icon.trim();
1070
1079
  if (raw.showHeader !== 'auto')
@@ -1074,8 +1083,8 @@ class WidgetShellEditorComponent {
1074
1083
  windowActions.collapsible = false;
1075
1084
  if (Object.keys(windowActions).length)
1076
1085
  shell.windowActions = windowActions;
1077
- const actions = (raw.actions || [])
1078
- .map((a) => this.normalizeAction(a))
1086
+ const actions = this.actions.controls
1087
+ .map((group) => this.normalizeAction(group.getRawValue(), this.actionCopySources.get(group)))
1079
1088
  .filter((a) => a.id);
1080
1089
  if (actions.length)
1081
1090
  shell.actions = actions;
@@ -1171,11 +1180,11 @@ class WidgetShellEditorComponent {
1171
1180
  return !!(raw.title || raw.subtitle || raw.icon);
1172
1181
  }
1173
1182
  previewTitle() {
1174
- const title = this.form.controls.title.value.trim();
1183
+ const title = this.editableText(this.form.controls.title.value).trim();
1175
1184
  return title || 'Titulo do card';
1176
1185
  }
1177
1186
  previewSubtitle() {
1178
- const subtitle = this.form.controls.subtitle.value.trim();
1187
+ const subtitle = this.editableText(this.form.controls.subtitle.value).trim();
1179
1188
  return subtitle || 'Subtitulo opcional';
1180
1189
  }
1181
1190
  buildPreviewAppearance() {
@@ -1219,21 +1228,23 @@ class WidgetShellEditorComponent {
1219
1228
  previewWindowActions() {
1220
1229
  return this.previewActions().filter((a) => (a.placement || 'header') === 'window');
1221
1230
  }
1222
- normalizeAction(raw) {
1231
+ normalizeAction(raw, source) {
1223
1232
  const action = { id: String(raw.id || '').trim() };
1224
1233
  const label = String(raw.label || '').trim();
1225
1234
  const icon = String(raw.icon || '').trim();
1226
1235
  const emit = String(raw.emit || '').trim();
1227
1236
  const tooltip = String(raw.tooltip || '').trim();
1228
1237
  const command = String(raw.command || '').trim();
1229
- if (label)
1230
- action.label = label;
1238
+ const normalizedLabel = this.preserveTextDescriptor(source?.label, label);
1239
+ const normalizedTooltip = this.preserveTextDescriptor(source?.tooltip, tooltip);
1240
+ if (normalizedLabel)
1241
+ action.label = normalizedLabel;
1231
1242
  if (icon)
1232
1243
  action.icon = icon;
1233
1244
  if (emit)
1234
1245
  action.emit = emit;
1235
- if (tooltip)
1236
- action.tooltip = tooltip;
1246
+ if (normalizedTooltip)
1247
+ action.tooltip = normalizedTooltip;
1237
1248
  if (command)
1238
1249
  action.command = command;
1239
1250
  if (raw.variant && raw.variant !== 'text')
@@ -1249,6 +1260,21 @@ class WidgetShellEditorComponent {
1249
1260
  action.payload = payload;
1250
1261
  return action;
1251
1262
  }
1263
+ editableText(value) {
1264
+ if (typeof value === 'string')
1265
+ return value;
1266
+ return value?.text || value?.key || '';
1267
+ }
1268
+ preserveTextDescriptor(source, editedValue) {
1269
+ const edited = String(editedValue ?? '').trim();
1270
+ if (!edited)
1271
+ return undefined;
1272
+ if (source && typeof source === 'object') {
1273
+ const authoredText = this.editableText(source).trim();
1274
+ return edited === authoredText ? { ...source } : edited;
1275
+ }
1276
+ return edited;
1277
+ }
1252
1278
  tryParsePayload(raw) {
1253
1279
  const value = String(raw || '').trim();
1254
1280
  if (!value)
@@ -3658,7 +3684,7 @@ function deriveConnectionEditorGraph(page, options = {}) {
3658
3684
  }
3659
3685
  return {
3660
3686
  id: widgetId,
3661
- title: widget.shell?.title || widgetId,
3687
+ title: editableText(widget.shell?.title) || widgetId,
3662
3688
  subtitle: componentType,
3663
3689
  icon: widget.shell?.icon ?? iconForComponentType(componentType),
3664
3690
  x: center.x + Math.cos(angle) * radiusX,
@@ -3755,6 +3781,11 @@ function deriveConnectionEditorGraph(page, options = {}) {
3755
3781
  diagnostics: connections.flatMap((connection) => connection.diagnostics),
3756
3782
  };
3757
3783
  }
3784
+ function editableText(value) {
3785
+ if (typeof value === 'string')
3786
+ return value;
3787
+ return value?.text ?? value?.key ?? '';
3788
+ }
3758
3789
  function feedbackDiagnosticsForLinks(links) {
3759
3790
  const edges = links.map((link) => ({
3760
3791
  link,
@@ -23879,7 +23910,7 @@ class DynamicPageBuilderComponent {
23879
23910
  : label || fallbackKey;
23880
23911
  }
23881
23912
  resolveWidgetDisplayName(widget) {
23882
- const shellTitle = String(widget.shell?.title || '').trim();
23913
+ const shellTitle = this.i18n.resolve(widget.shell?.title, '').trim();
23883
23914
  if (shellTitle)
23884
23915
  return shellTitle;
23885
23916
  const componentId = widget.definition?.id || '';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxisui/page-builder",
3
- "version": "9.0.4-rc.39",
3
+ "version": "9.0.4-rc.40",
4
4
  "description": "Page and widget builder utilities for Praxis UI (grid, dynamic widgets, editors).",
5
5
  "peerDependencies": {
6
6
  "@angular/common": "^21.0.0",
@@ -8,9 +8,9 @@
8
8
  "@angular/forms": "^21.0.0",
9
9
  "@angular/cdk": "^21.0.0",
10
10
  "@angular/material": "^21.0.0",
11
- "@praxisui/ai": "^9.0.4-rc.39",
12
- "@praxisui/core": "^9.0.4-rc.39",
13
- "@praxisui/settings-panel": "^9.0.4-rc.39",
11
+ "@praxisui/ai": "^9.0.4-rc.40",
12
+ "@praxisui/core": "^9.0.4-rc.40",
13
+ "@praxisui/settings-panel": "^9.0.4-rc.40",
14
14
  "rxjs": "~7.8.0"
15
15
  },
16
16
  "dependencies": {
@@ -179,6 +179,9 @@ declare class WidgetShellEditorComponent implements SettingsValueProvider {
179
179
  isValid$: rxjs.Observable<boolean>;
180
180
  isBusy$: rxjs.Observable<boolean>;
181
181
  private snapshot;
182
+ private initialTitle;
183
+ private initialSubtitle;
184
+ private readonly actionCopySources;
182
185
  presetOptions: Array<{
183
186
  id: string;
184
187
  label: string;
@@ -222,6 +225,8 @@ declare class WidgetShellEditorComponent implements SettingsValueProvider {
222
225
  previewOverflowCount(): number;
223
226
  previewWindowActions(): WidgetShellAction[];
224
227
  private normalizeAction;
228
+ private editableText;
229
+ private preserveTextDescriptor;
225
230
  private tryParsePayload;
226
231
  private snapshotValue;
227
232
  filteredAvailableActions(): AvailableShellAction[];