@praxisui/core 7.0.0-beta.0 → 8.0.0-beta.1

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,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Component, InjectionToken, Injectable, inject, Inject, Optional, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, APP_INITIALIZER, ErrorHandler, EventEmitter, Output, Input, ChangeDetectionStrategy, Directive, SecurityContext, ViewContainerRef, ContentChild, signal, HostListener, ViewChild, computed } from '@angular/core';
2
+ import { Component, InjectionToken, Injectable, inject, Inject, Optional, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, APP_INITIALIZER, ErrorHandler, EventEmitter, Output, Input, ChangeDetectionStrategy, Directive, SecurityContext, ViewContainerRef, ContentChild, HostBinding, signal, HostListener, ViewChild, computed } from '@angular/core';
3
3
  import * as i1 from '@angular/common/http';
4
4
  import { HttpHeaders, HttpClient, HttpParams, HttpResponse, HttpContextToken, HTTP_INTERCEPTORS, withInterceptors } from '@angular/common/http';
5
5
  import { of, defer, throwError, from, EMPTY, BehaviorSubject, firstValueFrom, Subject, map as map$1 } from 'rxjs';
@@ -1549,6 +1549,7 @@ class ApiConfigStorage {
1549
1549
  http = inject(HttpClient);
1550
1550
  opts = inject(API_CONFIG_STORAGE_OPTIONS, { optional: true });
1551
1551
  baseUrl = (this.opts?.baseUrl || '/api/praxis/config/ui').replace(/\/$/, '');
1552
+ scope = this.opts?.scope?.trim();
1552
1553
  headersFactory = this.opts?.headersFactory || (() => ({}));
1553
1554
  defaultHeaders = this.opts?.defaultHeaders;
1554
1555
  componentTypeResolver = (key) => {
@@ -1739,11 +1740,15 @@ class ApiConfigStorage {
1739
1740
  return new HttpHeaders(merged);
1740
1741
  }
1741
1742
  buildParams(componentType, componentId) {
1743
+ const params = {
1744
+ componentType,
1745
+ componentId,
1746
+ };
1747
+ if (this.scope) {
1748
+ params['scope'] = this.scope;
1749
+ }
1742
1750
  return new HttpParams({
1743
- fromObject: {
1744
- componentType,
1745
- componentId,
1746
- },
1751
+ fromObject: params,
1747
1752
  });
1748
1753
  }
1749
1754
  resolveKey(key) {
@@ -2111,6 +2116,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
2111
2116
  args: [{ providedIn: 'root' }]
2112
2117
  }], ctorParameters: () => [] });
2113
2118
 
2119
+ const SCHEMA_CACHE_GLOBAL_CONFIG_READY_TIMEOUT_MS = 1200;
2114
2120
  /**
2115
2121
  * Serviço genérico para operações CRUD em APIs REST padronizadas.
2116
2122
  *
@@ -2180,7 +2186,10 @@ class GenericCrudService {
2180
2186
  if (!this.schemaCacheReady) {
2181
2187
  this.schemaCacheReady = (async () => {
2182
2188
  try {
2183
- await this.globalConfig.ready();
2189
+ await Promise.race([
2190
+ this.globalConfig.ready(),
2191
+ new Promise((resolve) => setTimeout(resolve, SCHEMA_CACHE_GLOBAL_CONFIG_READY_TIMEOUT_MS)),
2192
+ ]);
2184
2193
  }
2185
2194
  catch { }
2186
2195
  const disableCache = this.globalConfig.get('cache.disableSchemaCache');
@@ -3886,6 +3895,14 @@ function createDefaultTableConfig() {
3886
3895
  'stack',
3887
3896
  'tabs',
3888
3897
  'tab',
3898
+ 'text',
3899
+ 'icon',
3900
+ 'image',
3901
+ 'badge',
3902
+ 'avatar',
3903
+ 'metric',
3904
+ 'progress',
3905
+ 'compose',
3889
3906
  'card',
3890
3907
  'value',
3891
3908
  'action',
@@ -5655,6 +5672,16 @@ function providePraxisJsonLogicOperator(definition) {
5655
5672
  useValue: definition,
5656
5673
  };
5657
5674
  }
5675
+ function providePraxisJsonLogicOperatorOverride(definition) {
5676
+ return {
5677
+ provide: PRAXIS_JSON_LOGIC_OPERATORS,
5678
+ multi: true,
5679
+ useValue: {
5680
+ ...definition,
5681
+ override: true,
5682
+ },
5683
+ };
5684
+ }
5658
5685
 
5659
5686
  class PraxisJsonLogicError extends Error {
5660
5687
  code;
@@ -5667,8 +5694,11 @@ class PraxisJsonLogicError extends Error {
5667
5694
  class PraxisJsonLogicService {
5668
5695
  customOperators = new Map();
5669
5696
  constructor(operatorDefinitions) {
5670
- for (const definition of operatorDefinitions ?? DEFAULT_JSON_LOGIC_OPERATORS) {
5671
- this.customOperators.set(definition.operator, definition);
5697
+ for (const definition of DEFAULT_JSON_LOGIC_OPERATORS) {
5698
+ this.registerCustomOperator(definition, 'praxis');
5699
+ }
5700
+ for (const definition of operatorDefinitions ?? []) {
5701
+ this.registerCustomOperator(definition, 'host', definition.override === true);
5672
5702
  }
5673
5703
  }
5674
5704
  evaluate(expression, data, options) {
@@ -5715,6 +5745,38 @@ class PraxisJsonLogicService {
5715
5745
  truthy(value) {
5716
5746
  return this.isTruthy(value);
5717
5747
  }
5748
+ listOperatorDescriptors() {
5749
+ return [
5750
+ ...BUILTIN_JSON_LOGIC_OPERATOR_DESCRIPTORS,
5751
+ ...Array.from(this.customOperators.values()).map((definition) => this.toOperatorDescriptor(definition)),
5752
+ ];
5753
+ }
5754
+ getOperatorDescriptor(operator) {
5755
+ const native = BUILTIN_JSON_LOGIC_OPERATOR_DESCRIPTORS.find((item) => item.operator === operator);
5756
+ if (native) {
5757
+ return native;
5758
+ }
5759
+ const custom = this.customOperators.get(operator);
5760
+ return custom ? this.toOperatorDescriptor(custom) : undefined;
5761
+ }
5762
+ registerCustomOperator(definition, source, allowOverride = false) {
5763
+ const operator = definition.operator;
5764
+ if (BUILTIN_JSON_LOGIC_OPERATORS.includes(operator)) {
5765
+ throw new PraxisJsonLogicError('RULE_OPERATOR_CONFLICT', `JSON Logic operator "${operator}" is native and cannot be registered as a custom operator.`);
5766
+ }
5767
+ const existing = this.customOperators.get(operator);
5768
+ if (existing && !allowOverride) {
5769
+ throw new PraxisJsonLogicError('RULE_OPERATOR_CONFLICT', `JSON Logic operator "${operator}" is already registered by ${existing.source}. Use providePraxisJsonLogicOperatorOverride for an explicit override.`);
5770
+ }
5771
+ this.customOperators.set(operator, {
5772
+ ...definition,
5773
+ source,
5774
+ });
5775
+ }
5776
+ toOperatorDescriptor(definition) {
5777
+ const { evaluate: _evaluate, override: _override, ...descriptor } = definition;
5778
+ return descriptor;
5779
+ }
5718
5780
  createContext(data, options) {
5719
5781
  return {
5720
5782
  data,
@@ -5773,6 +5835,27 @@ class PraxisJsonLogicService {
5773
5835
  if (operator === 'substr') {
5774
5836
  return this.evaluateSubstr(rawArgs, context);
5775
5837
  }
5838
+ if (operator === 'merge') {
5839
+ return this.evaluateMerge(rawArgs, context);
5840
+ }
5841
+ if (operator === 'map') {
5842
+ return this.evaluateMap(rawArgs, context);
5843
+ }
5844
+ if (operator === 'filter') {
5845
+ return this.evaluateFilter(rawArgs, context);
5846
+ }
5847
+ if (operator === 'reduce') {
5848
+ return this.evaluateReduce(rawArgs, context);
5849
+ }
5850
+ if (operator === 'all') {
5851
+ return this.evaluateAll(rawArgs, context);
5852
+ }
5853
+ if (operator === 'some') {
5854
+ return this.evaluateSome(rawArgs, context);
5855
+ }
5856
+ if (operator === 'none') {
5857
+ return this.evaluateNone(rawArgs, context);
5858
+ }
5776
5859
  const custom = this.customOperators.get(operator);
5777
5860
  if (!custom) {
5778
5861
  throw new PraxisJsonLogicError('RULE_OPERATOR_UNKNOWN', `Unsupported JSON Logic operator: ${operator}`);
@@ -5931,6 +6014,82 @@ class PraxisJsonLogicService {
5931
6014
  }
5932
6015
  return value.slice(normalizedStart, normalizedStart + length);
5933
6016
  }
6017
+ evaluateMerge(rawArgs, context) {
6018
+ const args = this.toArgumentArray(rawArgs).map((arg) => this.evaluateValue(arg, context));
6019
+ const result = [];
6020
+ for (const value of args) {
6021
+ if (Array.isArray(value)) {
6022
+ result.push(...value);
6023
+ }
6024
+ else {
6025
+ result.push(value);
6026
+ }
6027
+ }
6028
+ return result;
6029
+ }
6030
+ evaluateMap(rawArgs, context) {
6031
+ const [sourceExpression, mapExpression] = this.requireHigherOrderArgs('map', rawArgs, 2, 2);
6032
+ const source = this.evaluateValue(sourceExpression, context);
6033
+ this.assertArrayOperand('map', source);
6034
+ return source.map((item) => this.evaluateValue(mapExpression, this.createChildContext(context, item)));
6035
+ }
6036
+ evaluateFilter(rawArgs, context) {
6037
+ const [sourceExpression, predicateExpression] = this.requireHigherOrderArgs('filter', rawArgs, 2, 2);
6038
+ const source = this.evaluateValue(sourceExpression, context);
6039
+ this.assertArrayOperand('filter', source);
6040
+ return source.filter((item) => this.isTruthy(this.evaluateValue(predicateExpression, this.createChildContext(context, item))));
6041
+ }
6042
+ evaluateReduce(rawArgs, context) {
6043
+ const [sourceExpression, reducerExpression, initialExpression] = this.requireHigherOrderArgs('reduce', rawArgs, 2, 3);
6044
+ const source = this.evaluateValue(sourceExpression, context);
6045
+ this.assertArrayOperand('reduce', source);
6046
+ let accumulator = initialExpression === undefined
6047
+ ? null
6048
+ : this.evaluateValue(initialExpression, context);
6049
+ for (const current of source) {
6050
+ accumulator = this.evaluateValue(reducerExpression, this.createChildContext(context, {
6051
+ current,
6052
+ accumulator,
6053
+ }));
6054
+ }
6055
+ return accumulator;
6056
+ }
6057
+ evaluateAll(rawArgs, context) {
6058
+ const [sourceExpression, predicateExpression] = this.requireHigherOrderArgs('all', rawArgs, 2, 2);
6059
+ const source = this.evaluateValue(sourceExpression, context);
6060
+ this.assertArrayOperand('all', source);
6061
+ if (!source.length) {
6062
+ return false;
6063
+ }
6064
+ return source.every((item) => this.isTruthy(this.evaluateValue(predicateExpression, this.createChildContext(context, item))));
6065
+ }
6066
+ evaluateSome(rawArgs, context) {
6067
+ const [sourceExpression, predicateExpression] = this.requireHigherOrderArgs('some', rawArgs, 2, 2);
6068
+ const source = this.evaluateValue(sourceExpression, context);
6069
+ this.assertArrayOperand('some', source);
6070
+ return source.some((item) => this.isTruthy(this.evaluateValue(predicateExpression, this.createChildContext(context, item))));
6071
+ }
6072
+ evaluateNone(rawArgs, context) {
6073
+ const [sourceExpression, predicateExpression] = this.requireHigherOrderArgs('none', rawArgs, 2, 2);
6074
+ const source = this.evaluateValue(sourceExpression, context);
6075
+ this.assertArrayOperand('none', source);
6076
+ return !source.some((item) => this.isTruthy(this.evaluateValue(predicateExpression, this.createChildContext(context, item))));
6077
+ }
6078
+ requireHigherOrderArgs(operator, rawArgs, min, max) {
6079
+ const args = this.toArgumentArray(rawArgs);
6080
+ return this.requireArgs(operator, args, min, max);
6081
+ }
6082
+ assertArrayOperand(operator, value) {
6083
+ if (!Array.isArray(value)) {
6084
+ throw new PraxisJsonLogicError('RULE_ARGUMENT_TYPE_INVALID', `Operator ${operator} requires an array as the first argument.`);
6085
+ }
6086
+ }
6087
+ createChildContext(context, data) {
6088
+ return {
6089
+ ...context,
6090
+ data: data,
6091
+ };
6092
+ }
5934
6093
  evaluateArgs(operator, rawArgs, context, min, max) {
5935
6094
  const args = this.toArgumentArray(rawArgs).map((arg) => this.evaluateValue(arg, context));
5936
6095
  return this.requireArgs(operator, args, min, max);
@@ -6151,6 +6310,16 @@ class PraxisJsonLogicService {
6151
6310
  return { min: 1 };
6152
6311
  case 'substr':
6153
6312
  return { min: 2, max: 3 };
6313
+ case 'merge':
6314
+ return { min: 1 };
6315
+ case 'map':
6316
+ case 'filter':
6317
+ case 'all':
6318
+ case 'some':
6319
+ case 'none':
6320
+ return { min: 2, max: 2 };
6321
+ case 'reduce':
6322
+ return { min: 2, max: 3 };
6154
6323
  case '+':
6155
6324
  case '*':
6156
6325
  case 'min':
@@ -6196,10 +6365,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
6196
6365
  const DEFAULT_JSON_LOGIC_OPERATORS = [
6197
6366
  {
6198
6367
  operator: 'contains',
6368
+ namespace: 'praxis',
6199
6369
  minArgs: 2,
6200
6370
  maxArgs: 2,
6371
+ returnType: 'boolean',
6372
+ purity: 'pure',
6201
6373
  evaluate: (args, _context, helpers) => {
6202
6374
  const [container, candidate] = helpers.requireArgs('contains', args, 2, 2);
6375
+ if (container === undefined || container === null) {
6376
+ return false;
6377
+ }
6203
6378
  if (typeof container === 'string' && typeof candidate === 'string') {
6204
6379
  return container.includes(candidate);
6205
6380
  }
@@ -6211,10 +6386,16 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6211
6386
  },
6212
6387
  {
6213
6388
  operator: 'startsWith',
6389
+ namespace: 'praxis',
6214
6390
  minArgs: 2,
6215
6391
  maxArgs: 2,
6392
+ returnType: 'boolean',
6393
+ purity: 'pure',
6216
6394
  evaluate: (args, _context, helpers) => {
6217
6395
  const [value, prefix] = helpers.requireArgs('startsWith', args, 2, 2);
6396
+ if (value === undefined || value === null) {
6397
+ return false;
6398
+ }
6218
6399
  if (typeof value !== 'string' || typeof prefix !== 'string') {
6219
6400
  throw new PraxisJsonLogicError('RULE_ARGUMENT_TYPE_INVALID', '`startsWith` requires string arguments.');
6220
6401
  }
@@ -6223,10 +6404,16 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6223
6404
  },
6224
6405
  {
6225
6406
  operator: 'endsWith',
6407
+ namespace: 'praxis',
6226
6408
  minArgs: 2,
6227
6409
  maxArgs: 2,
6410
+ returnType: 'boolean',
6411
+ purity: 'pure',
6228
6412
  evaluate: (args, _context, helpers) => {
6229
6413
  const [value, suffix] = helpers.requireArgs('endsWith', args, 2, 2);
6414
+ if (value === undefined || value === null) {
6415
+ return false;
6416
+ }
6230
6417
  if (typeof value !== 'string' || typeof suffix !== 'string') {
6231
6418
  throw new PraxisJsonLogicError('RULE_ARGUMENT_TYPE_INVALID', '`endsWith` requires string arguments.');
6232
6419
  }
@@ -6235,10 +6422,16 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6235
6422
  },
6236
6423
  {
6237
6424
  operator: 'matches',
6425
+ namespace: 'praxis',
6238
6426
  minArgs: 2,
6239
6427
  maxArgs: 2,
6428
+ returnType: 'boolean',
6429
+ purity: 'pure',
6240
6430
  evaluate: (args, _context, helpers) => {
6241
6431
  const [value, pattern] = helpers.requireArgs('matches', args, 2, 2);
6432
+ if (value === undefined || value === null) {
6433
+ return false;
6434
+ }
6242
6435
  if (typeof value !== 'string' || typeof pattern !== 'string') {
6243
6436
  throw new PraxisJsonLogicError('RULE_ARGUMENT_TYPE_INVALID', '`matches` requires string arguments.');
6244
6437
  }
@@ -6252,8 +6445,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6252
6445
  },
6253
6446
  {
6254
6447
  operator: 'isBlank',
6448
+ namespace: 'praxis',
6255
6449
  minArgs: 1,
6256
6450
  maxArgs: 1,
6451
+ returnType: 'boolean',
6452
+ purity: 'pure',
6257
6453
  evaluate: (args, _context, helpers) => {
6258
6454
  const [value] = helpers.requireArgs('isBlank', args, 1, 1);
6259
6455
  if (value === undefined || value === null) {
@@ -6270,8 +6466,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6270
6466
  },
6271
6467
  {
6272
6468
  operator: 'len',
6469
+ namespace: 'praxis',
6273
6470
  minArgs: 1,
6274
6471
  maxArgs: 1,
6472
+ returnType: 'number',
6473
+ purity: 'pure',
6275
6474
  evaluate: (args, _context, helpers) => {
6276
6475
  const [value] = helpers.requireArgs('len', args, 1, 1);
6277
6476
  if (value === undefined || value === null) {
@@ -6291,8 +6490,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6291
6490
  },
6292
6491
  {
6293
6492
  operator: 'round',
6493
+ namespace: 'praxis',
6294
6494
  minArgs: 1,
6295
6495
  maxArgs: 1,
6496
+ returnType: 'number',
6497
+ purity: 'pure',
6296
6498
  evaluate: (args, _context, helpers) => {
6297
6499
  const [value] = helpers.requireArgs('round', args, 1, 1);
6298
6500
  if (typeof value !== 'number' || !Number.isFinite(value)) {
@@ -6303,8 +6505,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6303
6505
  },
6304
6506
  {
6305
6507
  operator: 'ceil',
6508
+ namespace: 'praxis',
6306
6509
  minArgs: 1,
6307
6510
  maxArgs: 1,
6511
+ returnType: 'number',
6512
+ purity: 'pure',
6308
6513
  evaluate: (args, _context, helpers) => {
6309
6514
  const [value] = helpers.requireArgs('ceil', args, 1, 1);
6310
6515
  if (typeof value !== 'number' || !Number.isFinite(value)) {
@@ -6315,8 +6520,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6315
6520
  },
6316
6521
  {
6317
6522
  operator: 'floor',
6523
+ namespace: 'praxis',
6318
6524
  minArgs: 1,
6319
6525
  maxArgs: 1,
6526
+ returnType: 'number',
6527
+ purity: 'pure',
6320
6528
  evaluate: (args, _context, helpers) => {
6321
6529
  const [value] = helpers.requireArgs('floor', args, 1, 1);
6322
6530
  if (typeof value !== 'number' || !Number.isFinite(value)) {
@@ -6327,8 +6535,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6327
6535
  },
6328
6536
  {
6329
6537
  operator: 'abs',
6538
+ namespace: 'praxis',
6330
6539
  minArgs: 1,
6331
6540
  maxArgs: 1,
6541
+ returnType: 'number',
6542
+ purity: 'pure',
6332
6543
  evaluate: (args, _context, helpers) => {
6333
6544
  const [value] = helpers.requireArgs('abs', args, 1, 1);
6334
6545
  if (typeof value !== 'number' || !Number.isFinite(value)) {
@@ -6339,7 +6550,10 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6339
6550
  },
6340
6551
  {
6341
6552
  operator: 'coalesce',
6553
+ namespace: 'praxis',
6342
6554
  minArgs: 1,
6555
+ returnType: 'unknown',
6556
+ purity: 'pure',
6343
6557
  evaluate: (args, _context, helpers) => {
6344
6558
  const values = helpers.requireArgs('coalesce', args, 1);
6345
6559
  for (const value of values) {
@@ -6352,14 +6566,20 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6352
6566
  },
6353
6567
  {
6354
6568
  operator: 'now',
6569
+ namespace: 'praxis',
6355
6570
  minArgs: 0,
6356
6571
  maxArgs: 0,
6572
+ returnType: 'number',
6573
+ purity: 'contextual',
6357
6574
  evaluate: () => Date.now(),
6358
6575
  },
6359
6576
  {
6360
6577
  operator: 'date',
6578
+ namespace: 'praxis',
6361
6579
  minArgs: 1,
6362
6580
  maxArgs: 1,
6581
+ returnType: 'number',
6582
+ purity: 'pure',
6363
6583
  evaluate: (args, _context, helpers) => {
6364
6584
  const [value] = helpers.requireArgs('date', args, 1, 1);
6365
6585
  const parsed = parseTemporalValue(value);
@@ -6374,8 +6594,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6374
6594
  },
6375
6595
  {
6376
6596
  operator: 'yearsSince',
6597
+ namespace: 'praxis',
6377
6598
  minArgs: 1,
6378
6599
  maxArgs: 1,
6600
+ returnType: 'number',
6601
+ purity: 'contextual',
6379
6602
  evaluate: (args, context, helpers) => {
6380
6603
  const [value] = helpers.requireArgs('yearsSince', args, 1, 1);
6381
6604
  const parsed = parseTemporalValue(value);
@@ -6388,8 +6611,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6388
6611
  },
6389
6612
  {
6390
6613
  operator: 'monthsSince',
6614
+ namespace: 'praxis',
6391
6615
  minArgs: 1,
6392
6616
  maxArgs: 1,
6617
+ returnType: 'number',
6618
+ purity: 'contextual',
6393
6619
  evaluate: (args, context, helpers) => {
6394
6620
  const [value] = helpers.requireArgs('monthsSince', args, 1, 1);
6395
6621
  const parsed = parseTemporalValue(value);
@@ -6402,8 +6628,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6402
6628
  },
6403
6629
  {
6404
6630
  operator: 'daysSince',
6631
+ namespace: 'praxis',
6405
6632
  minArgs: 1,
6406
6633
  maxArgs: 1,
6634
+ returnType: 'number',
6635
+ purity: 'contextual',
6407
6636
  evaluate: (args, context, helpers) => {
6408
6637
  const [value] = helpers.requireArgs('daysSince', args, 1, 1);
6409
6638
  const parsed = parseTemporalValue(value);
@@ -6416,8 +6645,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6416
6645
  },
6417
6646
  {
6418
6647
  operator: 'toNumber',
6648
+ namespace: 'praxis',
6419
6649
  minArgs: 1,
6420
6650
  maxArgs: 1,
6651
+ returnType: 'number',
6652
+ purity: 'pure',
6421
6653
  evaluate: (args, _context, helpers) => {
6422
6654
  const [value] = helpers.requireArgs('toNumber', args, 1, 1);
6423
6655
  const parsed = Number(value);
@@ -6426,8 +6658,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6426
6658
  },
6427
6659
  {
6428
6660
  operator: 'stringify',
6661
+ namespace: 'praxis',
6429
6662
  minArgs: 1,
6430
6663
  maxArgs: 1,
6664
+ returnType: 'string',
6665
+ purity: 'pure',
6431
6666
  evaluate: (args, _context, helpers) => {
6432
6667
  const [value] = helpers.requireArgs('stringify', args, 1, 1);
6433
6668
  return value == null ? '' : String(value);
@@ -6435,8 +6670,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6435
6670
  },
6436
6671
  {
6437
6672
  operator: 'jsonGet',
6673
+ namespace: 'praxis',
6438
6674
  minArgs: 2,
6439
6675
  maxArgs: 2,
6676
+ returnType: 'unknown',
6677
+ purity: 'pure',
6440
6678
  evaluate: (args, _context, helpers) => {
6441
6679
  const [target, path] = helpers.requireArgs('jsonGet', args, 2, 2);
6442
6680
  if (typeof path !== 'string') {
@@ -6450,8 +6688,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6450
6688
  },
6451
6689
  {
6452
6690
  operator: 'hasKey',
6691
+ namespace: 'praxis',
6453
6692
  minArgs: 2,
6454
6693
  maxArgs: 2,
6694
+ returnType: 'boolean',
6695
+ purity: 'pure',
6455
6696
  evaluate: (args, _context, helpers) => {
6456
6697
  const [target, path] = helpers.requireArgs('hasKey', args, 2, 2);
6457
6698
  if (typeof path !== 'string') {
@@ -6465,8 +6706,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6465
6706
  },
6466
6707
  {
6467
6708
  operator: 'isToday',
6709
+ namespace: 'praxis',
6468
6710
  minArgs: 1,
6469
6711
  maxArgs: 1,
6712
+ returnType: 'boolean',
6713
+ purity: 'contextual',
6470
6714
  evaluate: (args, context, helpers) => {
6471
6715
  const [candidate] = helpers.requireArgs('isToday', args, 1, 1);
6472
6716
  const parsed = parseTemporalValue(candidate);
@@ -6478,8 +6722,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6478
6722
  },
6479
6723
  {
6480
6724
  operator: 'inLast',
6725
+ namespace: 'praxis',
6481
6726
  minArgs: 3,
6482
6727
  maxArgs: 3,
6728
+ returnType: 'boolean',
6729
+ purity: 'contextual',
6483
6730
  evaluate: (args, context, helpers) => {
6484
6731
  const [candidate, rawAmount, rawUnit] = helpers.requireArgs('inLast', args, 3, 3);
6485
6732
  const parsed = parseTemporalValue(candidate);
@@ -6496,8 +6743,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6496
6743
  },
6497
6744
  {
6498
6745
  operator: 'weekdayIn',
6746
+ namespace: 'praxis',
6499
6747
  minArgs: 2,
6500
6748
  maxArgs: 2,
6749
+ returnType: 'boolean',
6750
+ purity: 'contextual',
6501
6751
  evaluate: (args, context, helpers) => {
6502
6752
  const [candidate, rawDays] = helpers.requireArgs('weekdayIn', args, 2, 2);
6503
6753
  const parsed = parseTemporalValue(candidate);
@@ -6541,6 +6791,13 @@ const BUILTIN_JSON_LOGIC_OPERATORS = [
6541
6791
  'in',
6542
6792
  'cat',
6543
6793
  'substr',
6794
+ 'merge',
6795
+ 'map',
6796
+ 'filter',
6797
+ 'reduce',
6798
+ 'all',
6799
+ 'some',
6800
+ 'none',
6544
6801
  '+',
6545
6802
  '-',
6546
6803
  '*',
@@ -6549,6 +6806,39 @@ const BUILTIN_JSON_LOGIC_OPERATORS = [
6549
6806
  'min',
6550
6807
  'max',
6551
6808
  ];
6809
+ const BUILTIN_JSON_LOGIC_OPERATOR_DESCRIPTORS = [
6810
+ { operator: 'var', source: 'native', minArgs: 1, maxArgs: 2, returnType: 'unknown', purity: 'pure' },
6811
+ { operator: '==', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'boolean', purity: 'pure' },
6812
+ { operator: '===', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'boolean', purity: 'pure' },
6813
+ { operator: '!=', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'boolean', purity: 'pure' },
6814
+ { operator: '!==', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'boolean', purity: 'pure' },
6815
+ { operator: '>', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'boolean', purity: 'pure' },
6816
+ { operator: '>=', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'boolean', purity: 'pure' },
6817
+ { operator: '<', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'boolean', purity: 'pure' },
6818
+ { operator: '<=', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'boolean', purity: 'pure' },
6819
+ { operator: '!', source: 'native', minArgs: 1, maxArgs: 1, returnType: 'boolean', purity: 'pure' },
6820
+ { operator: '!!', source: 'native', minArgs: 1, maxArgs: 1, returnType: 'boolean', purity: 'pure' },
6821
+ { operator: 'and', source: 'native', minArgs: 1, returnType: 'unknown', purity: 'pure' },
6822
+ { operator: 'or', source: 'native', minArgs: 1, returnType: 'unknown', purity: 'pure' },
6823
+ { operator: 'if', source: 'native', minArgs: 2, returnType: 'unknown', purity: 'pure' },
6824
+ { operator: 'in', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'boolean', purity: 'pure' },
6825
+ { operator: 'cat', source: 'native', minArgs: 1, returnType: 'string', purity: 'pure' },
6826
+ { operator: 'substr', source: 'native', minArgs: 2, maxArgs: 3, returnType: 'string', purity: 'pure' },
6827
+ { operator: 'merge', source: 'native', minArgs: 1, returnType: 'array', purity: 'pure' },
6828
+ { operator: 'map', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'array', purity: 'pure' },
6829
+ { operator: 'filter', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'array', purity: 'pure' },
6830
+ { operator: 'reduce', source: 'native', minArgs: 2, maxArgs: 3, returnType: 'unknown', purity: 'pure' },
6831
+ { operator: 'all', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'boolean', purity: 'pure' },
6832
+ { operator: 'some', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'boolean', purity: 'pure' },
6833
+ { operator: 'none', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'boolean', purity: 'pure' },
6834
+ { operator: '+', source: 'native', minArgs: 1, returnType: 'number', purity: 'pure' },
6835
+ { operator: '-', source: 'native', minArgs: 1, returnType: 'number', purity: 'pure' },
6836
+ { operator: '*', source: 'native', minArgs: 1, returnType: 'number', purity: 'pure' },
6837
+ { operator: '/', source: 'native', minArgs: 2, returnType: 'number', purity: 'pure' },
6838
+ { operator: '%', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'number', purity: 'pure' },
6839
+ { operator: 'min', source: 'native', minArgs: 1, returnType: 'number', purity: 'pure' },
6840
+ { operator: 'max', source: 'native', minArgs: 1, returnType: 'number', purity: 'pure' },
6841
+ ];
6552
6842
  function isComparisonOperator(operator) {
6553
6843
  return ['==', '===', '!=', '!==', '>', '>=', '<', '<='].includes(operator);
6554
6844
  }
@@ -8240,6 +8530,14 @@ function buildPraxisLayerScaleCss(scale = PRAXIS_LAYER_SCALE_DEFAULTS) {
8240
8530
  z-index: var(${PRAXIS_LAYER_SCALE_VARS.cdkOverlayBackdrop}, ${scale.cdkOverlayBackdrop}) !important;
8241
8531
  }
8242
8532
 
8533
+ .cdk-overlay-pane {
8534
+ z-index: var(${PRAXIS_LAYER_SCALE_VARS.cdkOverlayWrapper}, ${scale.cdkOverlayWrapper}) !important;
8535
+ }
8536
+
8537
+ .cdk-overlay-connected-position-bounding-box {
8538
+ z-index: var(${PRAXIS_LAYER_SCALE_VARS.cdkOverlayWrapper}, ${scale.cdkOverlayWrapper}) !important;
8539
+ }
8540
+
8243
8541
  .cdk-global-overlay-wrapper {
8244
8542
  z-index: var(${PRAXIS_LAYER_SCALE_VARS.cdkOverlayWrapper}, ${scale.cdkOverlayWrapper}) !important;
8245
8543
  }
@@ -8880,7 +9178,8 @@ class CrudOperationResolutionService {
8880
9178
  if (operation === 'delete') {
8881
9179
  return null;
8882
9180
  }
8883
- const { path, method, schemaType } = this.buildCanonicalSchemaParams(operation, resourcePath, preferredMethod);
9181
+ const schemaResourcePath = this.resolveSchemaResourcePath(resourcePath, options);
9182
+ const { path, method, schemaType } = this.buildCanonicalSchemaParams(operation, schemaResourcePath, preferredMethod);
8884
9183
  const query = new URLSearchParams({
8885
9184
  path,
8886
9185
  operation: method.toLowerCase(),
@@ -9033,7 +9332,21 @@ class CrudOperationResolutionService {
9033
9332
  if (!normalized) {
9034
9333
  return '';
9035
9334
  }
9036
- return normalized.startsWith('/') ? normalized : `/${normalized}`;
9335
+ return normalized.replace(/\/+$/, '');
9336
+ }
9337
+ resolveSchemaResourcePath(resourcePath, options) {
9338
+ const normalized = this.normalizeResourcePath(resourcePath);
9339
+ if (!normalized) {
9340
+ return '';
9341
+ }
9342
+ try {
9343
+ const resolved = this.discovery.resolveHref(normalized, options);
9344
+ const pathname = new URL(resolved).pathname.replace(/\/+/g, '/').replace(/\/+$/, '');
9345
+ return pathname || (normalized.startsWith('/') ? normalized : `/${normalized}`);
9346
+ }
9347
+ catch {
9348
+ return normalized.startsWith('/') ? normalized : `/${normalized}`;
9349
+ }
9037
9350
  }
9038
9351
  resolveCanonicalResourcePath(request, fallbackResourcePath) {
9039
9352
  const capabilityResourcePath = this.normalizeResourcePath(request.capabilities?.resourcePath || '');
@@ -9477,6 +9790,8 @@ class AnalyticsStatsRequestBuilderService {
9477
9790
  case 'count':
9478
9791
  case '':
9479
9792
  return 'COUNT';
9793
+ case 'distinct-count':
9794
+ return 'DISTINCT_COUNT';
9480
9795
  case 'sum':
9481
9796
  return 'SUM';
9482
9797
  default:
@@ -9502,18 +9817,14 @@ class AnalyticsStatsRequestBuilderService {
9502
9817
  }
9503
9818
  mapGranularityToBackend(granularity) {
9504
9819
  switch (granularity) {
9505
- case 'hour':
9506
- return 'HOUR';
9507
9820
  case 'day':
9508
9821
  return 'DAY';
9509
9822
  case 'week':
9510
9823
  return 'WEEK';
9511
9824
  case 'month':
9512
9825
  return 'MONTH';
9513
- case 'quarter':
9514
- return 'QUARTER';
9515
- case 'year':
9516
- return 'YEAR';
9826
+ default:
9827
+ throw new Error(`Analytics stats granularity "${granularity}" is not supported in praxis.stats execution.`);
9517
9828
  }
9518
9829
  }
9519
9830
  getExecutionMetrics(projection) {
@@ -10859,11 +11170,14 @@ function providePraxisGlobalConfigBootstrap(options) {
10859
11170
  }
10860
11171
 
10861
11172
  function providePraxisI18nConfig(config) {
10862
- return {
10863
- provide: PRAXIS_I18N_CONFIG,
10864
- useValue: config,
10865
- multi: true,
10866
- };
11173
+ return [
11174
+ {
11175
+ provide: PRAXIS_I18N_CONFIG,
11176
+ useValue: config,
11177
+ multi: true,
11178
+ },
11179
+ PraxisI18nService,
11180
+ ];
10867
11181
  }
10868
11182
  const providePraxisI18n = providePraxisI18nConfig;
10869
11183
  function providePraxisI18nTranslator(translator) {
@@ -12031,7 +12345,9 @@ function normalizeSelectLike(meta) {
12031
12345
  m.filterCriteria = m.filter;
12032
12346
  warnings.push('filter→filterCriteria');
12033
12347
  }
12034
- // Unificar endpoint/resourcePath (preferir resourcePath)
12348
+ // Unificar endpoint/resourcePath para metadados legados.
12349
+ // Quando ambos existem, endpoint representa a operacao concreta publicada pelo schema
12350
+ // (ex.: /options/filter) e resourcePath representa o recurso dono.
12035
12351
  if (m.resourcePath == null && m.endpoint != null) {
12036
12352
  m.resourcePath = m.endpoint;
12037
12353
  warnings.push('endpoint→resourcePath');
@@ -12104,8 +12420,6 @@ function normalizeSelectLike(meta) {
12104
12420
  delete m.valueField;
12105
12421
  if (m.filter !== undefined)
12106
12422
  delete m.filter;
12107
- if (m.endpoint !== undefined)
12108
- delete m.endpoint;
12109
12423
  return m;
12110
12424
  }
12111
12425
 
@@ -12217,6 +12531,16 @@ function getReferencedFieldMetadata(config, allFieldMetadata) {
12217
12531
  // Return only metadata for referenced fields
12218
12532
  return allFieldMetadata.filter((metadata) => referencedFieldNames.has(metadata.name));
12219
12533
  }
12534
+ function isLocalFieldMetadata(field) {
12535
+ return field.source === 'local';
12536
+ }
12537
+ function stripLocalSubmitSemantics$1(field) {
12538
+ const { source, transient, submitPolicy, ...rest } = field;
12539
+ void source;
12540
+ void transient;
12541
+ void submitPolicy;
12542
+ return rest;
12543
+ }
12220
12544
  /**
12221
12545
  * Synchronizes local config with server metadata
12222
12546
  * Detects additions, removals, and modifications
@@ -12230,7 +12554,7 @@ function syncWithServerMetadata(localConfig, serverMetadata) {
12230
12554
  // Detect additions/removals
12231
12555
  const addedFields = serverFields.filter((f) => !localFieldsMap.has(f.name));
12232
12556
  const removedFields = localFields
12233
- .filter((f) => !serverFieldsMap.has(f.name))
12557
+ .filter((f) => !serverFieldsMap.has(f.name) && !isLocalFieldMetadata(f))
12234
12558
  .map((f) => f.name);
12235
12559
  // Merge overlapping fields: prefer server as base, preserve local customizations
12236
12560
  const mergedOverlapping = [];
@@ -12241,7 +12565,7 @@ function syncWithServerMetadata(localConfig, serverMetadata) {
12241
12565
  return; // handled later
12242
12566
  // Deep-ish merge with special handling for validators/options
12243
12567
  const base = { ...serverField };
12244
- const loc = { ...localField };
12568
+ const loc = { ...stripLocalSubmitSemantics$1(localField) };
12245
12569
  const mergedValidators = { ...serverField.validators, ...localField.validators };
12246
12570
  // Options/nodes family: keep local options if provided, else server
12247
12571
  const pick = (k) => (loc[k] !== undefined ? loc[k] : base[k]);
@@ -13280,6 +13604,7 @@ const RULE_PROPERTY_SCHEMA = {
13280
13604
  { name: 'validators', type: 'object', label: 'Validadores' },
13281
13605
  ],
13282
13606
  section: [
13607
+ { name: 'hidden', type: 'boolean', label: 'Oculto' },
13283
13608
  { name: 'visible', type: 'boolean', label: 'Visível' },
13284
13609
  { name: 'title', type: 'string', label: 'Título' },
13285
13610
  { name: 'description', type: 'string', label: 'Descrição' },
@@ -14887,7 +15212,22 @@ function normalizeEndpoint(path) {
14887
15212
  }
14888
15213
  }
14889
15214
  // Remove leading slashes and any duplicated `api` segments
14890
- return path.replace(/^\/+/, '').replace(/^(?:api\/)+/, '');
15215
+ const normalized = path.replace(/^\/+/, '').replace(/^(?:api\/)+/, '');
15216
+ return normalized.replace(/\/options\/filter\/?$/i, '');
15217
+ }
15218
+ function isOptionsFilterEndpoint(path) {
15219
+ if (!path) {
15220
+ return false;
15221
+ }
15222
+ if (/^https?:\/\//i.test(path)) {
15223
+ try {
15224
+ path = new URL(path).pathname;
15225
+ }
15226
+ catch {
15227
+ // Keep the original string when it cannot be parsed as a URL.
15228
+ }
15229
+ }
15230
+ return /\/options\/filter\/?$/i.test(path);
14891
15231
  }
14892
15232
  function normalizeOptionSource(optionSource) {
14893
15233
  if (!optionSource?.key) {
@@ -14979,6 +15319,10 @@ function mapFieldDefinitionToMetadata(field) {
14979
15319
  if (normalizedOptionSource) {
14980
15320
  metadata.optionSource = normalizedOptionSource;
14981
15321
  }
15322
+ const hasOptionsFilterEndpoint = isOptionsFilterEndpoint(field.endpoint);
15323
+ if (field.endpoint) {
15324
+ metadata.endpoint = field.endpoint;
15325
+ }
14982
15326
  const endpointPath = normalizeEndpoint(normalizedOptionSource?.resourcePath ?? field.resourcePath ?? field.endpoint);
14983
15327
  if (endpointPath) {
14984
15328
  // Canonicalize: only expose resourcePath; do not write legacy alias
@@ -15021,13 +15365,13 @@ function mapFieldDefinitionToMetadata(field) {
15021
15365
  if (field.displayField) {
15022
15366
  metadata.optionLabelKey = field.displayField;
15023
15367
  }
15024
- else if (normalizedOptionSource) {
15368
+ else if (normalizedOptionSource || hasOptionsFilterEndpoint) {
15025
15369
  metadata.optionLabelKey = 'label';
15026
15370
  }
15027
15371
  if (field.valueField) {
15028
15372
  metadata.optionValueKey = field.valueField;
15029
15373
  }
15030
- else if (normalizedOptionSource) {
15374
+ else if (normalizedOptionSource || hasOptionsFilterEndpoint) {
15031
15375
  metadata.optionValueKey = 'id';
15032
15376
  }
15033
15377
  if (field.filter) {
@@ -16956,6 +17300,8 @@ const ENUMS$1 = {
16956
17300
  dependencyMergeStrategy: ['replace', 'merge'],
16957
17301
  dependencyLoadOnChange: ['respectLoadOn', 'immediate', 'manual'],
16958
17302
  textTransformApply: ['displayOnly', 'saveOnly', 'both'],
17303
+ fieldSource: ['schema', 'local'],
17304
+ fieldSubmitPolicy: ['include', 'omit', 'includeWhenDirty'],
16959
17305
  visibleIn: ['form', 'filter', 'table', 'dialog'],
16960
17306
  appearance: ['fill', 'outline'],
16961
17307
  color: ['primary', 'accent', 'warn'],
@@ -16966,7 +17312,7 @@ const ENUMS$1 = {
16966
17312
  sectionDescriptionStyle: ['bodyLarge', 'bodyMedium', 'bodySmall'],
16967
17313
  };
16968
17314
  const FIELD_METADATA_CAPABILITIES = {
16969
- version: 'v1.3',
17315
+ version: 'v1.4',
16970
17316
  enums: ENUMS$1,
16971
17317
  notes: [
16972
17318
  'Condições booleanas declarativas devem usar Json Logic canônico. Funções permanecem restritas a escapes host-level como transforms e validators customizados.',
@@ -16975,6 +17321,8 @@ const FIELD_METADATA_CAPABILITIES = {
16975
17321
  'Detalhes específicos de cada controle (ex: opções de datepicker, máscaras específicas) devem ser consultados nos catálogos de microcomponentes.',
16976
17322
  'POLICY: Arrays e objetos (ex: options, validators) devem sofrer merge/append, nunca substituição completa sem confirmação.',
16977
17323
  'Não gere função para conditionalDisplay/conditionalRequired. Use Json Logic serializável; funções ficam restritas a transforms e validators customizados.',
17324
+ 'POLICY: Campos auxiliares do host devem usar source=local ou transient=true em FieldMetadata; nao invente campos no DTO/backend quando eles nao devem participar do payload persistido.',
17325
+ 'POLICY: formSubmit.formData e o payload filtrado para backend; formSubmit.rawFormData preserva os valores completos da UI, incluindo campos locais/transient.',
16978
17326
  ],
16979
17327
  capabilities: [
16980
17328
  // =============================================================================
@@ -17169,6 +17517,32 @@ const FIELD_METADATA_CAPABILITIES = {
17169
17517
  description: 'Tipo de dado do campo (text, number, date, etc).',
17170
17518
  intentExamples: ['tipo de dado numero', 'campo de data'],
17171
17519
  },
17520
+ {
17521
+ path: 'source',
17522
+ category: 'data',
17523
+ valueKind: 'enum',
17524
+ allowedValues: ENUMS$1.fieldSource,
17525
+ description: 'Origem semantica do campo. Use local para campos do host que nao vem do schema backend.',
17526
+ intentExamples: ['campo local', 'campo auxiliar do host', 'campo que nao vem do schema'],
17527
+ safetyNotes: 'Nao marque como local um campo que exista no schema backend; remova a semantica local quando houver colisao com campo server-backed.',
17528
+ },
17529
+ {
17530
+ path: 'transient',
17531
+ category: 'data',
17532
+ valueKind: 'boolean',
17533
+ description: 'Marca o campo como temporario/local para preenchimento. O dynamic-form omite do submit por padrao.',
17534
+ intentExamples: ['campo temporario', 'campo transient', 'nao enviar no payload', 'usar apenas na UI'],
17535
+ safetyNotes: 'Campos transient continuam participando de UI, validacao, regras, visibilidade e valueChange; eles apenas saem do payload persistido por padrao.',
17536
+ },
17537
+ {
17538
+ path: 'submitPolicy',
17539
+ category: 'behavior',
17540
+ valueKind: 'enum',
17541
+ allowedValues: ENUMS$1.fieldSubmitPolicy,
17542
+ description: 'Politica de submit para sobrescrever o padrao de campos locais/transient.',
17543
+ intentExamples: ['omitir do submit', 'enviar mesmo sendo local', 'enviar apenas se alterado'],
17544
+ safetyNotes: 'Use omit para nunca persistir, include para enviar sempre e includeWhenDirty apenas quando o controle estiver dirty.',
17545
+ },
17172
17546
  // =============================================================================
17173
17547
  // MATERIAL DESIGN (APARÊNCIA GLOBAL)
17174
17548
  // =============================================================================
@@ -19573,9 +19947,7 @@ class DynamicWidgetLoaderDirective {
19573
19947
  }
19574
19948
  try {
19575
19949
  // Faz o binding com coerção de tipos quando possível
19576
- this.bindInputs(this.compRef, def.id, inputs, def.bindingOrder, meta || undefined, {
19577
- flushPerPrioritizedInput: !needsRecreate,
19578
- });
19950
+ this.bindInputs(this.compRef, def.id, inputs, def.bindingOrder, meta || undefined);
19579
19951
  this.bindOutputs(this.compRef.instance, def.id, outputs, meta || undefined);
19580
19952
  this.compRef.changeDetectorRef.detectChanges();
19581
19953
  this.widgetDiagnostic.emit({
@@ -19635,7 +20007,7 @@ class DynamicWidgetLoaderDirective {
19635
20007
  }
19636
20008
  this.vcRef.clear();
19637
20009
  }
19638
- bindInputs(compRef, id, inputs, bindingOrder, meta, options) {
20010
+ bindInputs(compRef, id, inputs, bindingOrder, meta) {
19639
20011
  // Derive priority order
19640
20012
  const defaultOrderMap = {
19641
20013
  'praxis-table': ['tableId', 'componentInstanceId', 'resourcePath', 'data', 'config'],
@@ -19682,17 +20054,10 @@ class DynamicWidgetLoaderDirective {
19682
20054
  console.warn(`[DynamicWidgetLoader] Failed to set input ${key}`, e);
19683
20055
  }
19684
20056
  };
19685
- const flushPerPrioritizedInput = options?.flushPerPrioritizedInput !== false;
19686
- // Apply prioritized inputs with eager flush only when updating an existing component.
19687
- // On the first bind, flushing after each input can fire ngOnInit before config/ids land together.
20057
+ // Apply every input before the final detectChanges so ngOnChanges never observes
20058
+ // a partial bindingOrder state, especially during existing component updates.
19688
20059
  for (const [key, raw] of prioritized) {
19689
20060
  apply(key, raw);
19690
- if (flushPerPrioritizedInput) {
19691
- try {
19692
- compRef.changeDetectorRef.detectChanges();
19693
- }
19694
- catch { }
19695
- }
19696
20061
  }
19697
20062
  // Apply remaining inputs
19698
20063
  for (const [key, raw] of others) {
@@ -19945,6 +20310,9 @@ const BUILTIN_SHELL_PRESETS = {
19945
20310
  };
19946
20311
  class WidgetShellComponent {
19947
20312
  i18n = inject(PraxisI18nService);
20313
+ get hostCollapsed() {
20314
+ return this.collapsed && !this.expanded && !this.fullscreen;
20315
+ }
19948
20316
  shell;
19949
20317
  context = null;
19950
20318
  dragSurfaceEnabled = false;
@@ -20126,7 +20494,7 @@ class WidgetShellComponent {
20126
20494
  return this.i18n.t(key, undefined, fallback, WIDGET_SHELL_I18N_NAMESPACE);
20127
20495
  }
20128
20496
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: WidgetShellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
20129
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: WidgetShellComponent, isStandalone: true, selector: "praxis-widget-shell", inputs: { shell: "shell", context: "context", dragSurfaceEnabled: "dragSurfaceEnabled", dragSurfaceLabel: "dragSurfaceLabel" }, outputs: { action: "action", dragSurfacePointerDown: "dragSurfacePointerDown", dragSurfaceKeydown: "dragSurfaceKeydown" }, providers: [providePraxisI18nConfig(WIDGET_SHELL_I18N_CONFIG)], queries: [{ propertyName: "loader", first: true, predicate: DynamicWidgetLoaderDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: `
20497
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: WidgetShellComponent, isStandalone: true, selector: "praxis-widget-shell", inputs: { shell: "shell", context: "context", dragSurfaceEnabled: "dragSurfaceEnabled", dragSurfaceLabel: "dragSurfaceLabel" }, outputs: { action: "action", dragSurfacePointerDown: "dragSurfacePointerDown", dragSurfaceKeydown: "dragSurfaceKeydown" }, host: { properties: { "class.pdx-widget-shell-collapsed": "this.hostCollapsed" } }, providers: [providePraxisI18nConfig(WIDGET_SHELL_I18N_CONFIG)], queries: [{ propertyName: "loader", first: true, predicate: DynamicWidgetLoaderDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: `
20130
20498
  <section
20131
20499
  class="pdx-shell"
20132
20500
  [class.no-shell]="!shellEnabled"
@@ -20134,6 +20502,8 @@ class WidgetShellComponent {
20134
20502
  [class.collapsed]="collapsed"
20135
20503
  [class.expanded]="expanded"
20136
20504
  [class.fullscreen]="fullscreen"
20505
+ [class.body-fill]="shell?.bodyLayout === 'fill'"
20506
+ [class.body-scroll]="shell?.bodyLayout === 'scroll'"
20137
20507
  [style.--pdx-shell-card-bg]="appearance?.card?.background || null"
20138
20508
  [style.--pdx-shell-card-border]="appearance?.card?.borderColor || null"
20139
20509
  [style.--pdx-shell-card-radius]="appearance?.card?.borderRadius || null"
@@ -20258,7 +20628,7 @@ class WidgetShellComponent {
20258
20628
  @if (expanded || fullscreen) {
20259
20629
  <div class="pdx-shell-backdrop" (click)="closeOverlay()"></div>
20260
20630
  }
20261
- `, isInline: true, styles: [":host{display:block;height:100%}.pdx-shell{position:relative;height:100%;display:flex;flex-direction:column}.pdx-shell.no-shell{background:transparent;border:none;border-radius:0;box-shadow:none}.pdx-shell.dashboard{background:var(--pdx-shell-card-bg, var(--pdx-dashboard-card-bg, var(--md-sys-color-surface-container-low)));border:1px solid var(--pdx-shell-card-border, var(--pdx-dashboard-card-border, var(--md-sys-color-outline-variant)));border-radius:var(--pdx-shell-card-radius, 12px);box-shadow:var(--pdx-shell-card-shadow, 0 4px 12px rgba(15, 23, 42, .06));overflow:hidden}.pdx-shell-header{display:flex;align-items:center;gap:10px;padding:8px 10px 7px;border-bottom:1px solid var(--pdx-shell-header-border, var(--md-sys-color-outline-variant));background:var(--pdx-shell-header-bg, var(--md-sys-color-surface-container))}.pdx-shell-header--drag-enabled{cursor:grab;-webkit-user-select:none;user-select:none;touch-action:none}.pdx-shell-header--drag-enabled:active{cursor:grabbing}.pdx-shell-header--drag-enabled:focus-visible{outline:2px solid color-mix(in srgb,var(--md-sys-color-primary) 72%,white 28%);outline-offset:-2px}.pdx-shell-title{display:flex;align-items:center;gap:8px;min-width:0;flex:1;color:var(--pdx-shell-title-color, inherit)}.pdx-shell-title mat-icon{color:var(--pdx-shell-icon-color, currentColor)}.pdx-shell-text{min-width:0}.pdx-shell-title-text{font-weight:var(--pdx-shell-title-weight, 600);font-size:var(--pdx-shell-title-size, 13px);line-height:1.15;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-subtitle{font-size:var(--pdx-shell-subtitle-size, 11px);opacity:.75;color:var(--pdx-shell-subtitle-color, currentColor);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-actions,.pdx-shell-window-actions{display:flex;align-items:center;gap:4px}.pdx-shell-window-actions{margin-left:auto}.pdx-action-outlined{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;padding:0 10px}.pdx-action-text{padding:0 8px}.pdx-action-label{font-size:12px;font-weight:500}.pdx-shell-body{flex:1;min-height:0;padding:var(--pdx-shell-body-padding, 8px 10px 10px 10px);background:var(--pdx-shell-body-bg, transparent);color:var(--pdx-shell-body-color, inherit)}.pdx-shell.no-shell .pdx-shell-body{padding:0}.pdx-shell-body.hidden{display:none}.pdx-shell.collapsed .pdx-shell-header{border-bottom-color:transparent}.pdx-shell.expanded .pdx-shell-body,.pdx-shell.fullscreen .pdx-shell-body{overflow:auto;display:flex;flex-direction:column;min-height:0}.pdx-shell.expanded .pdx-shell-body>*,.pdx-shell.fullscreen .pdx-shell-body>*{flex:1 1 auto;min-height:0;width:100%}.pdx-shell.expanded{position:fixed;top:10vh;left:50%;width:min(920px,92vw);height:min(640px,82vh);transform:translate(-50%);z-index:var(--praxis-layer-widget-shell-expanded, 1290);box-shadow:var(--mat-elevation-level8)}.pdx-shell.fullscreen{position:fixed;top:50%;left:50%;width:95vw;height:95vh;transform:translate(-50%,-50%);z-index:var(--praxis-layer-widget-shell-fullscreen, 1291);box-shadow:var(--mat-elevation-level8)}.pdx-shell-backdrop{position:fixed;inset:0;z-index:var(--praxis-layer-widget-shell-backdrop, 1280);background:#0000008c;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i4.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i4.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i4.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
20631
+ `, isInline: true, styles: [":host{display:block;height:100%}:host(.pdx-widget-shell-collapsed){height:auto}.pdx-shell{position:relative;height:100%;display:flex;flex-direction:column}.pdx-shell.no-shell{background:transparent;border:none;border-radius:0;box-shadow:none}.pdx-shell.dashboard{background:var(--pdx-shell-card-bg, var(--pdx-dashboard-card-bg, var(--md-sys-color-surface-container-low)));border:1px solid var(--pdx-shell-card-border, var(--pdx-dashboard-card-border, var(--md-sys-color-outline-variant)));border-radius:var(--pdx-shell-card-radius, 12px);box-shadow:var(--pdx-shell-card-shadow, 0 4px 12px rgba(15, 23, 42, .06));overflow:hidden}.pdx-shell-header{display:flex;align-items:center;gap:10px;padding:8px 10px 7px;border-bottom:1px solid var(--pdx-shell-header-border, var(--md-sys-color-outline-variant));background:var(--pdx-shell-header-bg, var(--md-sys-color-surface-container))}.pdx-shell-header--drag-enabled{cursor:grab;-webkit-user-select:none;user-select:none;touch-action:none}.pdx-shell-header--drag-enabled:active{cursor:grabbing}.pdx-shell-header--drag-enabled:focus-visible{outline:2px solid color-mix(in srgb,var(--md-sys-color-primary) 72%,white 28%);outline-offset:-2px}.pdx-shell-title{display:flex;align-items:center;gap:8px;min-width:0;flex:1;color:var(--pdx-shell-title-color, inherit)}.pdx-shell-title mat-icon{color:var(--pdx-shell-icon-color, currentColor)}.pdx-shell-text{min-width:0}.pdx-shell-title-text{font-weight:var(--pdx-shell-title-weight, 600);font-size:var(--pdx-shell-title-size, 13px);line-height:1.15;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-subtitle{font-size:var(--pdx-shell-subtitle-size, 11px);opacity:.75;color:var(--pdx-shell-subtitle-color, currentColor);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-actions,.pdx-shell-window-actions{display:flex;align-items:center;gap:4px}.pdx-shell-window-actions{margin-left:auto}.pdx-action-outlined{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;padding:0 10px}.pdx-action-text{padding:0 8px}.pdx-action-label{font-size:12px;font-weight:500}.pdx-shell-body{flex:1;min-height:0;padding:var(--pdx-shell-body-padding, 8px 10px 10px 10px);background:var(--pdx-shell-body-bg, transparent);color:var(--pdx-shell-body-color, inherit)}.pdx-shell.no-shell .pdx-shell-body{padding:0}.pdx-shell-body.hidden{display:none}.pdx-shell.collapsed{height:auto}.pdx-shell.collapsed .pdx-shell-header{border-bottom-color:transparent}.pdx-shell.body-fill .pdx-shell-body,.pdx-shell.body-scroll .pdx-shell-body,.pdx-shell.expanded .pdx-shell-body,.pdx-shell.fullscreen .pdx-shell-body{overflow:auto;display:flex;flex-direction:column;min-height:0}.pdx-shell.collapsed .pdx-shell-body{display:none}.pdx-shell.body-fill .pdx-shell-body{overflow:hidden}.pdx-shell.body-scroll .pdx-shell-body{overflow:auto}.pdx-shell.body-fill .pdx-shell-body>*,.pdx-shell.body-scroll .pdx-shell-body>*,.pdx-shell.expanded .pdx-shell-body>*,.pdx-shell.fullscreen .pdx-shell-body>*{flex:1 1 auto;min-height:0;width:100%}.pdx-shell.expanded{position:fixed;top:10vh;left:50%;width:min(920px,92vw);height:min(640px,82vh);transform:translate(-50%);z-index:var(--praxis-layer-widget-shell-expanded, 1290);box-shadow:var(--mat-elevation-level8)}.pdx-shell.fullscreen{position:fixed;top:50%;left:50%;width:95vw;height:95vh;transform:translate(-50%,-50%);z-index:var(--praxis-layer-widget-shell-fullscreen, 1291);box-shadow:var(--mat-elevation-level8)}.pdx-shell-backdrop{position:fixed;inset:0;z-index:var(--praxis-layer-widget-shell-backdrop, 1280);background:#0000008c;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i4.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i4.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i4.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
20262
20632
  }
20263
20633
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: WidgetShellComponent, decorators: [{
20264
20634
  type: Component,
@@ -20270,6 +20640,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
20270
20640
  [class.collapsed]="collapsed"
20271
20641
  [class.expanded]="expanded"
20272
20642
  [class.fullscreen]="fullscreen"
20643
+ [class.body-fill]="shell?.bodyLayout === 'fill'"
20644
+ [class.body-scroll]="shell?.bodyLayout === 'scroll'"
20273
20645
  [style.--pdx-shell-card-bg]="appearance?.card?.background || null"
20274
20646
  [style.--pdx-shell-card-border]="appearance?.card?.borderColor || null"
20275
20647
  [style.--pdx-shell-card-radius]="appearance?.card?.borderRadius || null"
@@ -20394,8 +20766,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
20394
20766
  @if (expanded || fullscreen) {
20395
20767
  <div class="pdx-shell-backdrop" (click)="closeOverlay()"></div>
20396
20768
  }
20397
- `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;height:100%}.pdx-shell{position:relative;height:100%;display:flex;flex-direction:column}.pdx-shell.no-shell{background:transparent;border:none;border-radius:0;box-shadow:none}.pdx-shell.dashboard{background:var(--pdx-shell-card-bg, var(--pdx-dashboard-card-bg, var(--md-sys-color-surface-container-low)));border:1px solid var(--pdx-shell-card-border, var(--pdx-dashboard-card-border, var(--md-sys-color-outline-variant)));border-radius:var(--pdx-shell-card-radius, 12px);box-shadow:var(--pdx-shell-card-shadow, 0 4px 12px rgba(15, 23, 42, .06));overflow:hidden}.pdx-shell-header{display:flex;align-items:center;gap:10px;padding:8px 10px 7px;border-bottom:1px solid var(--pdx-shell-header-border, var(--md-sys-color-outline-variant));background:var(--pdx-shell-header-bg, var(--md-sys-color-surface-container))}.pdx-shell-header--drag-enabled{cursor:grab;-webkit-user-select:none;user-select:none;touch-action:none}.pdx-shell-header--drag-enabled:active{cursor:grabbing}.pdx-shell-header--drag-enabled:focus-visible{outline:2px solid color-mix(in srgb,var(--md-sys-color-primary) 72%,white 28%);outline-offset:-2px}.pdx-shell-title{display:flex;align-items:center;gap:8px;min-width:0;flex:1;color:var(--pdx-shell-title-color, inherit)}.pdx-shell-title mat-icon{color:var(--pdx-shell-icon-color, currentColor)}.pdx-shell-text{min-width:0}.pdx-shell-title-text{font-weight:var(--pdx-shell-title-weight, 600);font-size:var(--pdx-shell-title-size, 13px);line-height:1.15;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-subtitle{font-size:var(--pdx-shell-subtitle-size, 11px);opacity:.75;color:var(--pdx-shell-subtitle-color, currentColor);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-actions,.pdx-shell-window-actions{display:flex;align-items:center;gap:4px}.pdx-shell-window-actions{margin-left:auto}.pdx-action-outlined{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;padding:0 10px}.pdx-action-text{padding:0 8px}.pdx-action-label{font-size:12px;font-weight:500}.pdx-shell-body{flex:1;min-height:0;padding:var(--pdx-shell-body-padding, 8px 10px 10px 10px);background:var(--pdx-shell-body-bg, transparent);color:var(--pdx-shell-body-color, inherit)}.pdx-shell.no-shell .pdx-shell-body{padding:0}.pdx-shell-body.hidden{display:none}.pdx-shell.collapsed .pdx-shell-header{border-bottom-color:transparent}.pdx-shell.expanded .pdx-shell-body,.pdx-shell.fullscreen .pdx-shell-body{overflow:auto;display:flex;flex-direction:column;min-height:0}.pdx-shell.expanded .pdx-shell-body>*,.pdx-shell.fullscreen .pdx-shell-body>*{flex:1 1 auto;min-height:0;width:100%}.pdx-shell.expanded{position:fixed;top:10vh;left:50%;width:min(920px,92vw);height:min(640px,82vh);transform:translate(-50%);z-index:var(--praxis-layer-widget-shell-expanded, 1290);box-shadow:var(--mat-elevation-level8)}.pdx-shell.fullscreen{position:fixed;top:50%;left:50%;width:95vw;height:95vh;transform:translate(-50%,-50%);z-index:var(--praxis-layer-widget-shell-fullscreen, 1291);box-shadow:var(--mat-elevation-level8)}.pdx-shell-backdrop{position:fixed;inset:0;z-index:var(--praxis-layer-widget-shell-backdrop, 1280);background:#0000008c;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}\n"] }]
20398
- }], propDecorators: { shell: [{
20769
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;height:100%}:host(.pdx-widget-shell-collapsed){height:auto}.pdx-shell{position:relative;height:100%;display:flex;flex-direction:column}.pdx-shell.no-shell{background:transparent;border:none;border-radius:0;box-shadow:none}.pdx-shell.dashboard{background:var(--pdx-shell-card-bg, var(--pdx-dashboard-card-bg, var(--md-sys-color-surface-container-low)));border:1px solid var(--pdx-shell-card-border, var(--pdx-dashboard-card-border, var(--md-sys-color-outline-variant)));border-radius:var(--pdx-shell-card-radius, 12px);box-shadow:var(--pdx-shell-card-shadow, 0 4px 12px rgba(15, 23, 42, .06));overflow:hidden}.pdx-shell-header{display:flex;align-items:center;gap:10px;padding:8px 10px 7px;border-bottom:1px solid var(--pdx-shell-header-border, var(--md-sys-color-outline-variant));background:var(--pdx-shell-header-bg, var(--md-sys-color-surface-container))}.pdx-shell-header--drag-enabled{cursor:grab;-webkit-user-select:none;user-select:none;touch-action:none}.pdx-shell-header--drag-enabled:active{cursor:grabbing}.pdx-shell-header--drag-enabled:focus-visible{outline:2px solid color-mix(in srgb,var(--md-sys-color-primary) 72%,white 28%);outline-offset:-2px}.pdx-shell-title{display:flex;align-items:center;gap:8px;min-width:0;flex:1;color:var(--pdx-shell-title-color, inherit)}.pdx-shell-title mat-icon{color:var(--pdx-shell-icon-color, currentColor)}.pdx-shell-text{min-width:0}.pdx-shell-title-text{font-weight:var(--pdx-shell-title-weight, 600);font-size:var(--pdx-shell-title-size, 13px);line-height:1.15;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-subtitle{font-size:var(--pdx-shell-subtitle-size, 11px);opacity:.75;color:var(--pdx-shell-subtitle-color, currentColor);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-actions,.pdx-shell-window-actions{display:flex;align-items:center;gap:4px}.pdx-shell-window-actions{margin-left:auto}.pdx-action-outlined{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;padding:0 10px}.pdx-action-text{padding:0 8px}.pdx-action-label{font-size:12px;font-weight:500}.pdx-shell-body{flex:1;min-height:0;padding:var(--pdx-shell-body-padding, 8px 10px 10px 10px);background:var(--pdx-shell-body-bg, transparent);color:var(--pdx-shell-body-color, inherit)}.pdx-shell.no-shell .pdx-shell-body{padding:0}.pdx-shell-body.hidden{display:none}.pdx-shell.collapsed{height:auto}.pdx-shell.collapsed .pdx-shell-header{border-bottom-color:transparent}.pdx-shell.body-fill .pdx-shell-body,.pdx-shell.body-scroll .pdx-shell-body,.pdx-shell.expanded .pdx-shell-body,.pdx-shell.fullscreen .pdx-shell-body{overflow:auto;display:flex;flex-direction:column;min-height:0}.pdx-shell.collapsed .pdx-shell-body{display:none}.pdx-shell.body-fill .pdx-shell-body{overflow:hidden}.pdx-shell.body-scroll .pdx-shell-body{overflow:auto}.pdx-shell.body-fill .pdx-shell-body>*,.pdx-shell.body-scroll .pdx-shell-body>*,.pdx-shell.expanded .pdx-shell-body>*,.pdx-shell.fullscreen .pdx-shell-body>*{flex:1 1 auto;min-height:0;width:100%}.pdx-shell.expanded{position:fixed;top:10vh;left:50%;width:min(920px,92vw);height:min(640px,82vh);transform:translate(-50%);z-index:var(--praxis-layer-widget-shell-expanded, 1290);box-shadow:var(--mat-elevation-level8)}.pdx-shell.fullscreen{position:fixed;top:50%;left:50%;width:95vw;height:95vh;transform:translate(-50%,-50%);z-index:var(--praxis-layer-widget-shell-fullscreen, 1291);box-shadow:var(--mat-elevation-level8)}.pdx-shell-backdrop{position:fixed;inset:0;z-index:var(--praxis-layer-widget-shell-backdrop, 1280);background:#0000008c;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}\n"] }]
20770
+ }], propDecorators: { hostCollapsed: [{
20771
+ type: HostBinding,
20772
+ args: ['class.pdx-widget-shell-collapsed']
20773
+ }], shell: [{
20399
20774
  type: Input
20400
20775
  }], context: [{
20401
20776
  type: Input
@@ -21400,14 +21775,13 @@ function applyLinkPatches(current, patches) {
21400
21775
  if (!patch) {
21401
21776
  return cloneLink(link);
21402
21777
  }
21403
- return {
21404
- ...cloneLink(link),
21405
- status: patch.status ?? link.status,
21406
- lastEventAt: pickPatchedValue(patch, 'lastEventAt', link.lastEventAt),
21407
- lastDispatchTraceId: pickPatchedValue(patch, 'lastDispatchTraceId', link.lastDispatchTraceId),
21408
- lastDeliveredValuePreview: pickPatchedValue(patch, 'lastDeliveredValuePreview', link.lastDeliveredValuePreview),
21409
- diagnostics: cloneDiagnostics$1(patch.diagnostics ?? link.diagnostics),
21410
- };
21778
+ const next = cloneLink(link);
21779
+ next.status = patch.status ?? link.status;
21780
+ setOptionalLinkValue(next, 'lastEventAt', pickPatchedValue(patch, 'lastEventAt', link.lastEventAt));
21781
+ setOptionalLinkValue(next, 'lastDispatchTraceId', pickPatchedValue(patch, 'lastDispatchTraceId', link.lastDispatchTraceId));
21782
+ setOptionalLinkValue(next, 'lastDeliveredValuePreview', pickPatchedValue(patch, 'lastDeliveredValuePreview', link.lastDeliveredValuePreview));
21783
+ next.diagnostics = cloneDiagnostics$1(patch.diagnostics ?? link.diagnostics);
21784
+ return next;
21411
21785
  });
21412
21786
  }
21413
21787
  function pickPatchedValue(patch, key, fallback) {
@@ -21419,12 +21793,24 @@ function cloneLinks(links) {
21419
21793
  return links.map((link) => cloneLink(link));
21420
21794
  }
21421
21795
  function cloneLink(link) {
21422
- return {
21423
- ...link,
21796
+ const next = {
21797
+ linkId: link.linkId,
21798
+ status: link.status,
21424
21799
  source: { ...link.source },
21425
21800
  target: { ...link.target },
21426
21801
  diagnostics: cloneDiagnostics$1(link.diagnostics),
21427
21802
  };
21803
+ setOptionalLinkValue(next, 'lastEventAt', link.lastEventAt);
21804
+ setOptionalLinkValue(next, 'lastDispatchTraceId', link.lastDispatchTraceId);
21805
+ setOptionalLinkValue(next, 'lastDeliveredValuePreview', link.lastDeliveredValuePreview);
21806
+ return next;
21807
+ }
21808
+ function setOptionalLinkValue(link, key, value) {
21809
+ if (value === undefined) {
21810
+ delete link[key];
21811
+ return;
21812
+ }
21813
+ link[key] = value;
21428
21814
  }
21429
21815
  function cloneDiagnostics$1(diagnostics) {
21430
21816
  return diagnostics.map((diagnostic) => ({
@@ -23531,6 +23917,7 @@ class DynamicWidgetPageComponent {
23531
23917
  /** Optional instance key for pages rendered multiple times. */
23532
23918
  componentInstanceId;
23533
23919
  pageChange = new EventEmitter();
23920
+ widgetEvent = new EventEmitter();
23534
23921
  widgetDiagnosticsChange = new EventEmitter();
23535
23922
  widgets = signal([], ...(ngDevMode ? [{ debugName: "widgets" }] : []));
23536
23923
  renderedGroups = signal([], ...(ngDevMode ? [{ debugName: "renderedGroups" }] : []));
@@ -23572,56 +23959,89 @@ class DynamicWidgetPageComponent {
23572
23959
  globalActions = inject(GlobalActionService);
23573
23960
  storage = inject(ASYNC_CONFIG_STORAGE);
23574
23961
  componentKeys = inject(ComponentKeyService);
23962
+ componentMetadata = inject(ComponentMetadataRegistry, {
23963
+ optional: true,
23964
+ });
23575
23965
  i18n = inject(PraxisI18nService);
23576
- route = (() => { try {
23577
- return inject(ActivatedRoute);
23578
- }
23579
- catch {
23580
- return undefined;
23581
- } })();
23966
+ route = (() => {
23967
+ try {
23968
+ return inject(ActivatedRoute);
23969
+ }
23970
+ catch {
23971
+ return undefined;
23972
+ }
23973
+ })();
23582
23974
  conn = inject(ConnectionManagerService);
23583
23975
  stateRuntime = inject(WidgetPageStateRuntimeService);
23584
- settingsPanel = inject(SETTINGS_PANEL_BRIDGE, { optional: true });
23585
- defaultShellEditor = inject(DYNAMIC_PAGE_SHELL_EDITOR, { optional: true });
23586
- defaultPageEditor = inject(DYNAMIC_PAGE_CONFIG_EDITOR, { optional: true });
23976
+ settingsPanel = inject(SETTINGS_PANEL_BRIDGE, {
23977
+ optional: true,
23978
+ });
23979
+ defaultShellEditor = inject(DYNAMIC_PAGE_SHELL_EDITOR, {
23980
+ optional: true,
23981
+ });
23982
+ defaultPageEditor = inject(DYNAMIC_PAGE_CONFIG_EDITOR, {
23983
+ optional: true,
23984
+ });
23587
23985
  constructor() { }
23588
23986
  ngOnDestroy() {
23589
23987
  this.compositionRuntime.destroy();
23590
23988
  }
23591
23989
  ngOnChanges(changes) {
23592
- if (changes['page'] || changes['context'] || changes['enableCustomization']) {
23990
+ if (changes['page'] ||
23991
+ changes['context'] ||
23992
+ changes['enableCustomization']) {
23593
23993
  const parsed = this.parsePage(this.page);
23594
23994
  const resolvedPage = parsed ? this.resolvePagePresets(parsed) : parsed;
23595
23995
  this.assertNoLegacyConnections(resolvedPage);
23596
23996
  this.widgetDiagnostics = {};
23597
23997
  this.widgetDiagnosticsChange.emit({});
23598
- this.pageDefinition = resolvedPage ? { ...resolvedPage, state: this.stateRuntime.normalizeState(resolvedPage.state) } : resolvedPage;
23998
+ this.pageDefinition = resolvedPage
23999
+ ? {
24000
+ ...resolvedPage,
24001
+ state: this.stateRuntime.normalizeState(resolvedPage.state),
24002
+ }
24003
+ : resolvedPage;
23599
24004
  this.pageRuntime = this.buildStateRuntime(this.pageDefinition?.state, this.pageDefinition?.context);
23600
24005
  this.pageState = this.pageRuntime.state;
23601
24006
  const bootstrapSnapshot = this.bootstrapCompositionAdapter(this.pageDefinition);
23602
24007
  const rawWidgets = this.pageDefinition?.widgets || [];
23603
24008
  let widgets = this.applyEditShellActions(rawWidgets);
23604
24009
  widgets = this.applyBootstrapCompositionHydration(widgets, bootstrapSnapshot);
23605
- this.pageDefinition = this.pageDefinition ? { ...this.pageDefinition, widgets } : this.pageDefinition;
24010
+ this.pageDefinition = this.pageDefinition
24011
+ ? { ...this.pageDefinition, widgets }
24012
+ : this.pageDefinition;
23606
24013
  this.page = this.pageDefinition;
23607
24014
  this.applyResponsivePresentation(this.pageDefinition, widgets, this.pageRuntime);
23608
24015
  this.reportStateDiagnostics(this.pageRuntime.diagnostics);
23609
24016
  }
23610
- if (this.autoPersist && (changes['pageIdentity'] || changes['componentInstanceId'])) {
24017
+ if (this.autoPersist &&
24018
+ (changes['pageIdentity'] || changes['componentInstanceId'])) {
23611
24019
  this.appliedPersisted = false;
23612
24020
  this.persistenceReady = false;
23613
24021
  }
23614
- if (this.autoPersist && !this.appliedPersisted && (changes['page'] || changes['context'] || changes['pageIdentity'] || changes['componentInstanceId'])) {
24022
+ if (this.autoPersist &&
24023
+ !this.appliedPersisted &&
24024
+ (changes['page'] ||
24025
+ changes['context'] ||
24026
+ changes['pageIdentity'] ||
24027
+ changes['componentInstanceId'])) {
23615
24028
  this.appliedPersisted = true;
23616
24029
  this.loadPersistedPage();
23617
24030
  }
23618
- if (this.autoPersist && this.persistenceReady && changes['page'] && !this.isHydrating) {
24031
+ if (this.autoPersist &&
24032
+ this.persistenceReady &&
24033
+ changes['page'] &&
24034
+ !this.isHydrating) {
23619
24035
  const parsed = this.parsePage(this.page);
23620
24036
  if (parsed)
23621
24037
  this.savePage(parsed);
23622
24038
  }
23623
24039
  }
23624
24040
  onWidgetEvent(fromKey, evt) {
24041
+ this.widgetEvent.emit({
24042
+ ...evt,
24043
+ ownerWidgetKey: evt.ownerWidgetKey || fromKey,
24044
+ });
23625
24045
  if (evt?.output && this.maybeExecuteMappedAction(fromKey, evt)) {
23626
24046
  return;
23627
24047
  }
@@ -23637,7 +24057,7 @@ class DynamicWidgetPageComponent {
23637
24057
  }
23638
24058
  const state = this.stateFromCompositionSnapshot(pageWithPatchedInputs.state, cycle.snapshot.state.primaryValues);
23639
24059
  const runtimeStatePaths = Array.from(new Set((cycle.snapshot.state.changedPaths || []).filter((path) => typeof path === 'string')));
23640
- const updatedPrimaryStatePaths = runtimeStatePaths.filter((path) => (!this.areStateValuesEqual(this.conn.extractByPath(this.stateRuntime.normalizeState(page.state).values || {}, path), this.conn.extractByPath(state.values || {}, path))));
24060
+ const updatedPrimaryStatePaths = runtimeStatePaths.filter((path) => !this.areStateValuesEqual(this.conn.extractByPath(this.stateRuntime.normalizeState(page.state).values || {}, path), this.conn.extractByPath(state.values || {}, path)));
23641
24061
  let widgets = this.cloneWidgets(pageWithPatchedInputs.widgets || []);
23642
24062
  const directDelivery = this.applyCompositionWidgetDeliveries(widgets, cycle);
23643
24063
  widgets = directDelivery.widgets;
@@ -23649,7 +24069,10 @@ class DynamicWidgetPageComponent {
23649
24069
  const stateProjectionChanged = !this.areStateValuesEqual(widgets, projectedWidgets);
23650
24070
  widgets = projectedWidgets;
23651
24071
  const nextRuntime = this.buildStateRuntime(state, pageWithPatchedInputs.context);
23652
- if (!updatedPrimaryStatePaths.length && !directDelivery.changed && !stateProjectionChanged && !widgetInputPatchResult.changed) {
24072
+ if (!updatedPrimaryStatePaths.length &&
24073
+ !directDelivery.changed &&
24074
+ !stateProjectionChanged &&
24075
+ !widgetInputPatchResult.changed) {
23653
24076
  return;
23654
24077
  }
23655
24078
  this.applyPageUpdate({ ...pageWithPatchedInputs, widgets, state }, true, nextRuntime, false);
@@ -23701,7 +24124,9 @@ class DynamicWidgetPageComponent {
23701
24124
  return null;
23702
24125
  }
23703
24126
  const candidate = payload.inputPatch;
23704
- if (!candidate || typeof candidate !== 'object' || Array.isArray(candidate)) {
24127
+ if (!candidate ||
24128
+ typeof candidate !== 'object' ||
24129
+ Array.isArray(candidate)) {
23705
24130
  return null;
23706
24131
  }
23707
24132
  return candidate;
@@ -23719,12 +24144,26 @@ class DynamicWidgetPageComponent {
23719
24144
  }
23720
24145
  applyEditShellActions(widgets) {
23721
24146
  return this.cloneWidgets(widgets).map((widget) => {
23722
- if (!this.shouldInjectWidgetSettings(widget)) {
24147
+ if (!this.shouldInjectEditShellActions(widget)) {
23723
24148
  return widget;
23724
24149
  }
23725
24150
  const existingActions = widget.shell?.actions || [];
23726
- if (existingActions.some((action) => action.id === 'widget-settings')) {
23727
- return widget;
24151
+ const metadata = this.componentMetadata?.get(widget.definition?.id || '');
24152
+ const nextActions = [...existingActions];
24153
+ if (metadata?.configEditor &&
24154
+ !nextActions.some((action) => action.id === 'component-settings')) {
24155
+ nextActions.push({
24156
+ id: 'component-settings',
24157
+ icon: 'tune',
24158
+ variant: 'icon',
24159
+ placement: 'header',
24160
+ label: this.t('controls.componentSettings', 'Configurar conteudo'),
24161
+ tooltip: this.t('controls.componentSettingsTooltip', 'Abrir configuracoes do componente'),
24162
+ });
24163
+ }
24164
+ if (nextActions.some((action) => action.id === 'widget-settings') ||
24165
+ !this.canOpenWidgetShellSettings()) {
24166
+ return this.withShellActions(widget, nextActions);
23728
24167
  }
23729
24168
  const widgetSettingsAction = {
23730
24169
  id: 'widget-settings',
@@ -23734,15 +24173,23 @@ class DynamicWidgetPageComponent {
23734
24173
  label: this.t('controls.widgetSettings', 'Configurar widget'),
23735
24174
  tooltip: this.t('controls.widgetSettingsTooltip', 'Abrir configurações do widget'),
23736
24175
  };
23737
- return {
23738
- ...widget,
23739
- shell: {
23740
- ...(widget.shell || {}),
23741
- actions: [...existingActions, widgetSettingsAction],
23742
- },
23743
- };
24176
+ return this.withShellActions(widget, [...nextActions, widgetSettingsAction]);
23744
24177
  });
23745
24178
  }
24179
+ withShellActions(widget, actions) {
24180
+ const existingActions = widget.shell?.actions || [];
24181
+ if (existingActions.length === actions.length &&
24182
+ existingActions.every((action, index) => action === actions[index])) {
24183
+ return widget;
24184
+ }
24185
+ return {
24186
+ ...widget,
24187
+ shell: {
24188
+ ...(widget.shell || {}),
24189
+ actions,
24190
+ },
24191
+ };
24192
+ }
23746
24193
  applyBootstrapCompositionHydration(widgets, bootstrapSnapshot) {
23747
24194
  if (!this.compositionDefinition || !bootstrapSnapshot) {
23748
24195
  return this.cloneWidgets(widgets);
@@ -23764,10 +24211,10 @@ class DynamicWidgetPageComponent {
23764
24211
  return undefined;
23765
24212
  const definition = this.compositionDefinition ?? this.compositionFactory.create(page);
23766
24213
  this.compositionDefinition = definition;
23767
- if (!definition.links.some((link) => (link.from.kind === 'component-port'
23768
- && link.from.ref.widget === fromKey
23769
- && link.from.ref.port === output
23770
- && link.from.ref.direction === 'output'))) {
24214
+ if (!definition.links.some((link) => link.from.kind === 'component-port' &&
24215
+ link.from.ref.widget === fromKey &&
24216
+ link.from.ref.port === output &&
24217
+ link.from.ref.direction === 'output')) {
23771
24218
  return undefined;
23772
24219
  }
23773
24220
  let payload;
@@ -23810,12 +24257,15 @@ class DynamicWidgetPageComponent {
23810
24257
  };
23811
24258
  }
23812
24259
  const linksById = new Map(this.compositionDefinition.links.map((link) => [link.id, link]));
23813
- const runtimeLinks = cycle.snapshot.links.filter((link) => (link.lastDispatchTraceId === cycle.cycleId && link.status === 'delivered'));
24260
+ const runtimeLinks = cycle.snapshot.links.filter((link) => link.lastDispatchTraceId === cycle.cycleId &&
24261
+ link.status === 'delivered');
23814
24262
  let nextWidgets = this.cloneWidgets(widgets);
23815
24263
  let changed = false;
23816
24264
  for (const runtimeLink of runtimeLinks) {
23817
24265
  const link = linksById.get(runtimeLink.linkId);
23818
- if (!link || link.from.kind === 'state' || link.to.kind !== 'component-port') {
24266
+ if (!link ||
24267
+ link.from.kind === 'state' ||
24268
+ link.to.kind !== 'component-port') {
23819
24269
  continue;
23820
24270
  }
23821
24271
  const targetRef = link.to.ref;
@@ -23892,13 +24342,13 @@ class DynamicWidgetPageComponent {
23892
24342
  if (!normalizedPortId) {
23893
24343
  return normalizedBindingPath;
23894
24344
  }
23895
- if (normalizedBindingPath === normalizedPortId
23896
- || normalizedBindingPath.startsWith(`${normalizedPortId}.`)
23897
- || normalizedBindingPath.startsWith(`${normalizedPortId}[`)) {
24345
+ if (normalizedBindingPath === normalizedPortId ||
24346
+ normalizedBindingPath.startsWith(`${normalizedPortId}.`) ||
24347
+ normalizedBindingPath.startsWith(`${normalizedPortId}[`)) {
23898
24348
  return normalizedBindingPath;
23899
24349
  }
23900
- if (normalizedBindingPath.startsWith('.')
23901
- || normalizedBindingPath.startsWith('[')) {
24350
+ if (normalizedBindingPath.startsWith('.') ||
24351
+ normalizedBindingPath.startsWith('[')) {
23902
24352
  return `${normalizedPortId}${normalizedBindingPath}`;
23903
24353
  }
23904
24354
  return `${normalizedPortId}.${normalizedBindingPath}`;
@@ -23911,15 +24361,15 @@ class DynamicWidgetPageComponent {
23911
24361
  }
23912
24362
  return `widget:${fromKey}:${output}:${timestamp}:${sequence}`;
23913
24363
  }
23914
- shouldInjectWidgetSettings(widget) {
24364
+ shouldInjectEditShellActions(widget) {
23915
24365
  if (!this.enableCustomization || !this.settingsPanel) {
23916
24366
  return false;
23917
24367
  }
23918
- if (!(this.shellEditorComponent || this.defaultShellEditor)) {
23919
- return false;
23920
- }
23921
24368
  return !!widget.shell && widget.shell.kind !== 'none';
23922
24369
  }
24370
+ canOpenWidgetShellSettings() {
24371
+ return !!(this.shellEditorComponent || this.defaultShellEditor);
24372
+ }
23923
24373
  areStateValuesEqual(left, right) {
23924
24374
  if (left === right)
23925
24375
  return true;
@@ -23937,8 +24387,8 @@ class DynamicWidgetPageComponent {
23937
24387
  const rightKeys = Object.keys(right);
23938
24388
  if (leftKeys.length !== rightKeys.length)
23939
24389
  return false;
23940
- return leftKeys.every((key) => (Object.prototype.hasOwnProperty.call(right, key)
23941
- && this.areStateValuesEqual(left[key], right[key])));
24390
+ return leftKeys.every((key) => Object.prototype.hasOwnProperty.call(right, key) &&
24391
+ this.areStateValuesEqual(left[key], right[key]));
23942
24392
  }
23943
24393
  return false;
23944
24394
  }
@@ -23956,6 +24406,10 @@ class DynamicWidgetPageComponent {
23956
24406
  this.widgetDiagnosticsChange.emit({ ...this.widgetDiagnostics });
23957
24407
  }
23958
24408
  onShellAction(fromKey, evt) {
24409
+ if (evt.id === 'component-settings') {
24410
+ this.openWidgetComponentSettings(fromKey);
24411
+ return;
24412
+ }
23959
24413
  if (evt.id === 'widget-settings') {
23960
24414
  this.openWidgetShellSettings(fromKey);
23961
24415
  return;
@@ -24106,6 +24560,55 @@ class DynamicWidgetPageComponent {
24106
24560
  ref.applied$.subscribe((result) => this.applyWidgetShell(key, result, false));
24107
24561
  ref.saved$.subscribe((result) => this.applyWidgetShell(key, result, true));
24108
24562
  }
24563
+ openWidgetComponentSettings(key) {
24564
+ if (!this.settingsPanel)
24565
+ return;
24566
+ const page = this.ensurePageDefinition();
24567
+ const widget = page.widgets.find((w) => w.key === key);
24568
+ if (!widget)
24569
+ return;
24570
+ const metadata = this.componentMetadata?.get(widget.definition?.id || '');
24571
+ const editor = metadata?.configEditor?.component;
24572
+ if (!editor)
24573
+ return;
24574
+ const ref = this.settingsPanel.open({
24575
+ id: `dynamic-page-component:${key}`,
24576
+ title: metadata.configEditor?.title ||
24577
+ metadata.friendlyName ||
24578
+ this.t('controls.componentSettings', 'Configurar conteudo'),
24579
+ content: {
24580
+ component: editor,
24581
+ inputs: {
24582
+ inputs: this.cloneStateValues(widget.definition.inputs || {}),
24583
+ widgetKey: key,
24584
+ widgetType: widget.definition?.id,
24585
+ },
24586
+ },
24587
+ });
24588
+ ref.applied$.subscribe((result) => this.applyWidgetComponentInputs(key, result, false));
24589
+ ref.saved$.subscribe((result) => this.applyWidgetComponentInputs(key, result, true));
24590
+ }
24591
+ applyWidgetComponentInputs(key, result, persist) {
24592
+ if (!result || typeof result !== 'object' || Array.isArray(result))
24593
+ return;
24594
+ const nextInputs = 'inputs' in result &&
24595
+ result.inputs &&
24596
+ typeof result.inputs === 'object' &&
24597
+ !Array.isArray(result.inputs)
24598
+ ? result.inputs
24599
+ : result;
24600
+ const page = this.ensurePageDefinition();
24601
+ const widgets = page.widgets.map((w) => w.key === key
24602
+ ? {
24603
+ ...w,
24604
+ definition: {
24605
+ ...w.definition,
24606
+ inputs: this.cloneStateValues(nextInputs),
24607
+ },
24608
+ }
24609
+ : w);
24610
+ this.applyPageUpdate({ ...page, widgets }, persist);
24611
+ }
24109
24612
  openPageSettings() {
24110
24613
  if (!this.settingsPanel)
24111
24614
  return;
@@ -24134,7 +24637,7 @@ class DynamicWidgetPageComponent {
24134
24637
  if (!result)
24135
24638
  return;
24136
24639
  const page = this.ensurePageDefinition();
24137
- const widgets = page.widgets.map((w) => (w.key === key ? { ...w, shell: result.shell ?? null } : w));
24640
+ const widgets = page.widgets.map((w) => w.key === key ? { ...w, shell: result.shell ?? null } : w);
24138
24641
  let context = page.context || {};
24139
24642
  if (result.applyToAll && result.pagePreset) {
24140
24643
  const ui = { ...context.ui };
@@ -24201,7 +24704,10 @@ class DynamicWidgetPageComponent {
24201
24704
  },
24202
24705
  }).widgets
24203
24706
  : normalizedWidgets;
24204
- const hydrated = this.resolvePagePresets({ ...normalized, widgets: stateBoundWidgets });
24707
+ const hydrated = this.resolvePagePresets({
24708
+ ...normalized,
24709
+ widgets: stateBoundWidgets,
24710
+ });
24205
24711
  this.pageDefinition = hydrated;
24206
24712
  this.page = hydrated;
24207
24713
  this.pageState = runtime.state;
@@ -24231,21 +24737,28 @@ class DynamicWidgetPageComponent {
24231
24737
  this.pageColumnCount = Math.max(1, Number(canvas.columns) || 1);
24232
24738
  this.gridTemplateColumns = `repeat(${this.pageColumnCount}, minmax(0, 1fr))`;
24233
24739
  this.pageGap = canvas.gap || fallbackLayout?.gap || '16px';
24234
- this.gridAutoRows = canvas.autoRows === 'content' ? 'auto' : (canvas.rowUnit || '88px');
24740
+ this.gridAutoRows =
24741
+ canvas.autoRows === 'content' ? 'auto' : canvas.rowUnit || '88px';
24235
24742
  }
24236
24743
  mergeContext(pageContext, inputContext, runtime, pageDefinition) {
24237
24744
  const baseContext = this.buildStateContext(pageContext);
24238
24745
  const themePresetId = pageDefinition?.themePreset || '';
24239
- const themePreset = themePresetId ? BUILTIN_PAGE_THEME_PRESETS[themePresetId] : undefined;
24746
+ const themePreset = themePresetId
24747
+ ? BUILTIN_PAGE_THEME_PRESETS[themePresetId]
24748
+ : undefined;
24240
24749
  const layoutPresetId = pageDefinition?.layoutPreset || '';
24241
- const layoutPreset = layoutPresetId ? BUILTIN_PAGE_LAYOUT_PRESETS[layoutPresetId] : undefined;
24750
+ const layoutPreset = layoutPresetId
24751
+ ? BUILTIN_PAGE_LAYOUT_PRESETS[layoutPresetId]
24752
+ : undefined;
24242
24753
  return {
24243
24754
  ...baseContext,
24244
24755
  ...(inputContext || {}),
24245
24756
  pageDeviceKind: this.resolveDeviceKind(),
24246
24757
  pageLayoutPreset: layoutPreset || null,
24247
24758
  pageThemePreset: themePreset || null,
24248
- pageCanvas: pageDefinition?.canvas ? this.cloneStateValues(pageDefinition.canvas) : null,
24759
+ pageCanvas: pageDefinition?.canvas
24760
+ ? this.cloneStateValues(pageDefinition.canvas)
24761
+ : null,
24249
24762
  pageGrouping: this.cloneGrouping(pageDefinition?.grouping),
24250
24763
  pageState: this.cloneStateValues(runtime.primaryValues),
24251
24764
  pageStateDerived: this.cloneStateValues(runtime.derivedValues),
@@ -24352,7 +24865,10 @@ class DynamicWidgetPageComponent {
24352
24865
  const parsed = this.parsePage(this.page);
24353
24866
  if (parsed)
24354
24867
  return this.resolvePagePresets(parsed);
24355
- return { widgets: this.widgets(), state: this.stateRuntime.normalizeState(this.pageState) };
24868
+ return {
24869
+ widgets: this.widgets(),
24870
+ state: this.stateRuntime.normalizeState(this.pageState),
24871
+ };
24356
24872
  }
24357
24873
  parsePage(input) {
24358
24874
  if (!input)
@@ -24371,10 +24887,14 @@ class DynamicWidgetPageComponent {
24371
24887
  return input;
24372
24888
  }
24373
24889
  resolvePagePresets(page) {
24374
- const preset = page.layoutPreset ? BUILTIN_PAGE_LAYOUT_PRESETS[page.layoutPreset] : undefined;
24890
+ const preset = page.layoutPreset
24891
+ ? BUILTIN_PAGE_LAYOUT_PRESETS[page.layoutPreset]
24892
+ : undefined;
24375
24893
  const themePresetId = page.themePreset || preset?.defaultThemePreset;
24376
24894
  const mergedLayout = this.mergeLayout(preset?.defaultLayout, page.layout);
24377
- const grouping = (page.grouping && page.grouping.length ? page.grouping : preset?.defaultGrouping) || undefined;
24895
+ const grouping = (page.grouping && page.grouping.length
24896
+ ? page.grouping
24897
+ : preset?.defaultGrouping) || undefined;
24378
24898
  return {
24379
24899
  ...page,
24380
24900
  layout: mergedLayout,
@@ -24421,7 +24941,9 @@ class DynamicWidgetPageComponent {
24421
24941
  const widgetsWithOverrides = canvas
24422
24942
  ? this.applyCanvasLayoutToWidgets(baseWidgets, canvas)
24423
24943
  : baseWidgets;
24424
- const groups = canvas ? [] : this.buildRenderedGroups(grouping, widgetsWithOverrides);
24944
+ const groups = canvas
24945
+ ? []
24946
+ : this.buildRenderedGroups(grouping, widgetsWithOverrides);
24425
24947
  return {
24426
24948
  layout,
24427
24949
  canvas,
@@ -24492,10 +25014,13 @@ class DynamicWidgetPageComponent {
24492
25014
  return widget?.definition?.inputs?.['enableCustomization'] === true;
24493
25015
  }
24494
25016
  selectCanvasWidget(widgetKey) {
25017
+ if (!this.enableCustomization)
25018
+ return;
24495
25019
  if (this.selectedCanvasWidgetKey !== widgetKey) {
24496
25020
  this.selectedCanvasWidgetKey = widgetKey;
24497
25021
  }
24498
- if (this.blockedCanvasWidgetKey && this.blockedCanvasWidgetKey !== widgetKey) {
25022
+ if (this.blockedCanvasWidgetKey &&
25023
+ this.blockedCanvasWidgetKey !== widgetKey) {
24499
25024
  this.blockedCanvasWidgetKey = null;
24500
25025
  }
24501
25026
  }
@@ -24564,7 +25089,12 @@ class DynamicWidgetPageComponent {
24564
25089
  startPage: this.clonePageDefinition(this.ensurePageDefinition()),
24565
25090
  startX: 0,
24566
25091
  startY: 0,
24567
- startItem: { ...item, constraints: item.constraints ? { ...item.constraints } : undefined },
25092
+ startItem: {
25093
+ ...item,
25094
+ constraints: item.constraints
25095
+ ? { ...item.constraints }
25096
+ : undefined,
25097
+ },
24568
25098
  columns,
24569
25099
  columnWidth: 1,
24570
25100
  rowHeight: 1,
@@ -24583,7 +25113,9 @@ class DynamicWidgetPageComponent {
24583
25113
  ...widget,
24584
25114
  renderClassName,
24585
25115
  renderSpan: override?.span,
24586
- __order: typeof override?.order === 'number' ? override.order : Number.MAX_SAFE_INTEGER,
25116
+ __order: typeof override?.order === 'number'
25117
+ ? override.order
25118
+ : Number.MAX_SAFE_INTEGER,
24587
25119
  };
24588
25120
  })
24589
25121
  .filter((widget) => !!widget)
@@ -24623,7 +25155,9 @@ class DynamicWidgetPageComponent {
24623
25155
  if (!item || !metrics)
24624
25156
  return;
24625
25157
  const pageSnapshot = this.clonePageDefinition(this.ensurePageDefinition());
24626
- const pointerTarget = event.currentTarget instanceof HTMLElement ? event.currentTarget : undefined;
25158
+ const pointerTarget = event.currentTarget instanceof HTMLElement
25159
+ ? event.currentTarget
25160
+ : undefined;
24627
25161
  if (pointerTarget?.setPointerCapture) {
24628
25162
  try {
24629
25163
  pointerTarget.setPointerCapture(event.pointerId);
@@ -24638,7 +25172,10 @@ class DynamicWidgetPageComponent {
24638
25172
  startPage: pageSnapshot,
24639
25173
  startX: event.clientX,
24640
25174
  startY: event.clientY,
24641
- startItem: { ...item, constraints: item.constraints ? { ...item.constraints } : undefined },
25175
+ startItem: {
25176
+ ...item,
25177
+ constraints: item.constraints ? { ...item.constraints } : undefined,
25178
+ },
24642
25179
  columns: metrics.columns,
24643
25180
  columnWidth: metrics.columnWidth,
24644
25181
  rowHeight: metrics.rowHeight,
@@ -24657,7 +25194,7 @@ class DynamicWidgetPageComponent {
24657
25194
  const rect = host.getBoundingClientRect();
24658
25195
  const gap = this.parseCssPixelValue(this.pageGap, 16);
24659
25196
  const columns = Math.max(1, Number(canvas.columns) || 1);
24660
- const availableWidth = Math.max(1, rect.width - (gap * Math.max(0, columns - 1)));
25197
+ const availableWidth = Math.max(1, rect.width - gap * Math.max(0, columns - 1));
24661
25198
  const columnWidth = availableWidth / columns;
24662
25199
  const rowHeight = canvas.autoRows === 'content'
24663
25200
  ? this.parseCssPixelValue(canvas.rowUnit || '88px', 88)
@@ -24690,7 +25227,9 @@ class DynamicWidgetPageComponent {
24690
25227
  return { changed: false, blocked: false };
24691
25228
  const candidate = this.normalizeCanvasItem(updater({
24692
25229
  ...current,
24693
- constraints: current.constraints ? { ...current.constraints } : undefined,
25230
+ constraints: current.constraints
25231
+ ? { ...current.constraints }
25232
+ : undefined,
24694
25233
  }), effectiveCanvas?.columns || page.canvas.columns || 1);
24695
25234
  const collisionPolicy = effectiveCanvas
24696
25235
  ? this.resolveCanvasCollisionPolicy(effectiveCanvas, interactionKind)
@@ -24702,7 +25241,12 @@ class DynamicWidgetPageComponent {
24702
25241
  if (blocked) {
24703
25242
  this.blockedCanvasWidgetKey = widgetKey;
24704
25243
  this.transientCanvasItemsState.set({});
24705
- this.canvasPreviewState.set({ ...candidate, constraints: candidate.constraints ? { ...candidate.constraints } : undefined });
25244
+ this.canvasPreviewState.set({
25245
+ ...candidate,
25246
+ constraints: candidate.constraints
25247
+ ? { ...candidate.constraints }
25248
+ : undefined,
25249
+ });
24706
25250
  this.canvasPreviewInvalidState.set(true);
24707
25251
  if (blockedAnnouncement) {
24708
25252
  this.layoutAnnouncement = blockedAnnouncement;
@@ -24741,10 +25285,22 @@ class DynamicWidgetPageComponent {
24741
25285
  this.transientCanvasItemsState.set(changed
24742
25286
  ? Object.fromEntries(Object.entries(placement.items).map(([key, item]) => [
24743
25287
  key,
24744
- { ...item, constraints: item.constraints ? { ...item.constraints } : undefined },
25288
+ {
25289
+ ...item,
25290
+ constraints: item.constraints
25291
+ ? { ...item.constraints }
25292
+ : undefined,
25293
+ },
24745
25294
  ]))
24746
25295
  : {});
24747
- this.canvasPreviewState.set(changed ? { ...placement.primaryItem, constraints: placement.primaryItem.constraints ? { ...placement.primaryItem.constraints } : undefined } : null);
25296
+ this.canvasPreviewState.set(changed
25297
+ ? {
25298
+ ...placement.primaryItem,
25299
+ constraints: placement.primaryItem.constraints
25300
+ ? { ...placement.primaryItem.constraints }
25301
+ : undefined,
25302
+ }
25303
+ : null);
24748
25304
  this.canvasPreviewInvalidState.set(false);
24749
25305
  }
24750
25306
  return { changed, blocked: false, swappedWith: placement.swappedWith };
@@ -24762,7 +25318,10 @@ class DynamicWidgetPageComponent {
24762
25318
  },
24763
25319
  });
24764
25320
  const stateBoundWidgets = previewProjection.widgets;
24765
- const hydrated = this.resolvePagePresets({ ...normalized, widgets: stateBoundWidgets });
25321
+ const hydrated = this.resolvePagePresets({
25322
+ ...normalized,
25323
+ widgets: stateBoundWidgets,
25324
+ });
24766
25325
  this.pageDefinition = hydrated;
24767
25326
  this.page = hydrated;
24768
25327
  this.pageState = runtime.state;
@@ -24781,7 +25340,8 @@ class DynamicWidgetPageComponent {
24781
25340
  return page.canvas;
24782
25341
  }
24783
25342
  applyCanvasDrag(item, interaction, colDelta, rowDelta) {
24784
- const locked = item.constraints?.lockPosition || interaction.startItem.constraints?.lockPosition;
25343
+ const locked = item.constraints?.lockPosition ||
25344
+ interaction.startItem.constraints?.lockPosition;
24785
25345
  if (locked)
24786
25346
  return item;
24787
25347
  const nextCol = this.clampCanvasCol(interaction.startItem.col + colDelta, interaction.startItem.colSpan, interaction.columns);
@@ -24875,8 +25435,12 @@ class DynamicWidgetPageComponent {
24875
25435
  }
24876
25436
  canvasAnnouncement(kind, widgetKey) {
24877
25437
  return kind === 'drag'
24878
- ? this.t('announcements.moved', 'Widget movido: {{widget}}', { widget: widgetKey })
24879
- : this.t('announcements.resized', 'Widget redimensionado: {{widget}}', { widget: widgetKey });
25438
+ ? this.t('announcements.moved', 'Widget movido: {{widget}}', {
25439
+ widget: widgetKey,
25440
+ })
25441
+ : this.t('announcements.resized', 'Widget redimensionado: {{widget}}', {
25442
+ widget: widgetKey,
25443
+ });
24880
25444
  }
24881
25445
  blockedCanvasAnnouncement(kind) {
24882
25446
  return kind === 'drag'
@@ -24962,7 +25526,8 @@ class DynamicWidgetPageComponent {
24962
25526
  }
24963
25527
  return {
24964
25528
  blocked: false,
24965
- changed: !this.isSameCanvasItem(current, candidate) || !this.isSameCanvasItem(collision.item, swappedItem),
25529
+ changed: !this.isSameCanvasItem(current, candidate) ||
25530
+ !this.isSameCanvasItem(collision.item, swappedItem),
24966
25531
  primaryItem: candidate,
24967
25532
  items: {
24968
25533
  [widgetKey]: candidate,
@@ -24973,7 +25538,8 @@ class DynamicWidgetPageComponent {
24973
25538
  }
24974
25539
  findCanvasCollisions(widgetKey, candidate, canvas) {
24975
25540
  return Object.entries(canvas.items || {})
24976
- .filter(([otherKey, otherItem]) => otherKey !== widgetKey && this.canvasItemsOverlap(candidate, otherItem))
25541
+ .filter(([otherKey, otherItem]) => otherKey !== widgetKey &&
25542
+ this.canvasItemsOverlap(candidate, otherItem))
24977
25543
  .map(([key, item]) => ({ key, item }));
24978
25544
  }
24979
25545
  buildCanvasSwapItem(movingWidgetKey, sourceItem, targetWidgetKey, targetItem, movedItem, canvas) {
@@ -25003,24 +25569,24 @@ class DynamicWidgetPageComponent {
25003
25569
  return normalizedSwapItem;
25004
25570
  }
25005
25571
  canPlaceCanvasItem(widgetKey, candidate, canvas) {
25006
- return !Object.entries(canvas.items || {}).some(([otherKey, otherItem]) => (otherKey !== widgetKey && this.canvasItemsOverlap(candidate, otherItem)));
25572
+ return !Object.entries(canvas.items || {}).some(([otherKey, otherItem]) => otherKey !== widgetKey && this.canvasItemsOverlap(candidate, otherItem));
25007
25573
  }
25008
25574
  canvasItemsOverlap(left, right) {
25009
25575
  const leftRight = left.col + left.colSpan - 1;
25010
25576
  const rightRight = right.col + right.colSpan - 1;
25011
25577
  const leftBottom = left.row + left.rowSpan - 1;
25012
25578
  const rightBottom = right.row + right.rowSpan - 1;
25013
- return left.col <= rightRight
25014
- && leftRight >= right.col
25015
- && left.row <= rightBottom
25016
- && leftBottom >= right.row;
25579
+ return (left.col <= rightRight &&
25580
+ leftRight >= right.col &&
25581
+ left.row <= rightBottom &&
25582
+ leftBottom >= right.row);
25017
25583
  }
25018
25584
  isSameCanvasItem(left, right) {
25019
- return left.col === right.col
25020
- && left.row === right.row
25021
- && left.colSpan === right.colSpan
25022
- && left.rowSpan === right.rowSpan
25023
- && left.zIndex === right.zIndex;
25585
+ return (left.col === right.col &&
25586
+ left.row === right.row &&
25587
+ left.colSpan === right.colSpan &&
25588
+ left.rowSpan === right.rowSpan &&
25589
+ left.zIndex === right.zIndex);
25024
25590
  }
25025
25591
  clampCanvasCol(col, span, columns) {
25026
25592
  return this.clampNumber(col, 1, Math.max(1, columns - span + 1));
@@ -25031,7 +25597,9 @@ class DynamicWidgetPageComponent {
25031
25597
  parseCssPixelValue(value, fallback) {
25032
25598
  if (!value)
25033
25599
  return fallback;
25034
- const match = String(value).trim().match(/^(-?\d+(?:\.\d+)?)px$/i);
25600
+ const match = String(value)
25601
+ .trim()
25602
+ .match(/^(-?\d+(?:\.\d+)?)px$/i);
25035
25603
  if (!match)
25036
25604
  return fallback;
25037
25605
  const parsed = Number(match[1]);
@@ -25073,7 +25641,9 @@ class DynamicWidgetPageComponent {
25073
25641
  }
25074
25642
  return {
25075
25643
  ...group,
25076
- widgetKeys: override.widgetKeys?.length ? override.widgetKeys : group.widgetKeys,
25644
+ widgetKeys: override.widgetKeys?.length
25645
+ ? override.widgetKeys
25646
+ : group.widgetKeys,
25077
25647
  };
25078
25648
  })
25079
25649
  .filter((group) => !!group);
@@ -25186,7 +25756,9 @@ class DynamicWidgetPageComponent {
25186
25756
  return this.resolveRenderedCanvasItem(widget)?.zIndex ?? null;
25187
25757
  }
25188
25758
  widgetClassName(widget) {
25189
- return widget.renderClassName || widget.className || '';
25759
+ return (widget.renderClassName ||
25760
+ widget.className ||
25761
+ '');
25190
25762
  }
25191
25763
  mergeClassNames(...classNames) {
25192
25764
  const merged = classNames
@@ -25196,7 +25768,7 @@ class DynamicWidgetPageComponent {
25196
25768
  return merged.length ? Array.from(new Set(merged)).join(' ') : undefined;
25197
25769
  }
25198
25770
  resolveRenderedCanvasItem(widget) {
25199
- return this.transientCanvasItemsState()[widget.key] || widget.renderCanvasItem;
25771
+ return (this.transientCanvasItemsState()[widget.key] || widget.renderCanvasItem);
25200
25772
  }
25201
25773
  toPersistedCanonicalPage(page) {
25202
25774
  this.assertNoLegacyConnections(page);
@@ -25207,7 +25779,10 @@ class DynamicWidgetPageComponent {
25207
25779
  if (!key)
25208
25780
  return;
25209
25781
  try {
25210
- this.storage.saveConfig(key, this.toPersistedCanonicalPage(page)).pipe(take(1)).subscribe({ error: () => { } });
25782
+ this.storage
25783
+ .saveConfig(key, this.toPersistedCanonicalPage(page))
25784
+ .pipe(take(1))
25785
+ .subscribe({ error: () => { } });
25211
25786
  }
25212
25787
  catch { }
25213
25788
  }
@@ -25218,7 +25793,10 @@ class DynamicWidgetPageComponent {
25218
25793
  return;
25219
25794
  }
25220
25795
  try {
25221
- this.storage.loadConfig(key).pipe(take(1)).subscribe({
25796
+ this.storage
25797
+ .loadConfig(key)
25798
+ .pipe(take(1))
25799
+ .subscribe({
25222
25800
  next: (stored) => {
25223
25801
  if (!stored)
25224
25802
  return;
@@ -25242,7 +25820,9 @@ class DynamicWidgetPageComponent {
25242
25820
  if (this.pageIdentity?.routePath) {
25243
25821
  const base = buildPageKey(this.pageIdentity);
25244
25822
  const instance = this.sanitizeSegment(this.componentInstanceId);
25245
- return instance ? `dynamic-page:${base}:ik=${instance}` : `dynamic-page:${base}`;
25823
+ return instance
25824
+ ? `dynamic-page:${base}:ik=${instance}`
25825
+ : `dynamic-page:${base}`;
25246
25826
  }
25247
25827
  const id = this.componentKeyId();
25248
25828
  if (!id)
@@ -25280,7 +25860,9 @@ class DynamicWidgetPageComponent {
25280
25860
  sanitizeSegment(value) {
25281
25861
  if (!value)
25282
25862
  return '';
25283
- return String(value).trim().replace(/[\r\n\t|:]/g, '-');
25863
+ return String(value)
25864
+ .trim()
25865
+ .replace(/[\r\n\t|:]/g, '-');
25284
25866
  }
25285
25867
  assertNoLegacyConnections(page) {
25286
25868
  if (!page)
@@ -25291,20 +25873,20 @@ class DynamicWidgetPageComponent {
25291
25873
  throw new Error('DynamicWidgetPageComponent no longer accepts `page.connections`. Use `composition.links` only.');
25292
25874
  }
25293
25875
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DynamicWidgetPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
25294
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: DynamicWidgetPageComponent, isStandalone: true, selector: "praxis-dynamic-page", inputs: { page: "page", context: "context", strictValidation: "strictValidation", enableCustomization: "enableCustomization", showPageSettingsButton: "showPageSettingsButton", shellEditorComponent: "shellEditorComponent", pageEditorComponent: "pageEditorComponent", autoPersist: "autoPersist", pageIdentity: "pageIdentity", componentInstanceId: "componentInstanceId" }, outputs: { pageChange: "pageChange", widgetDiagnosticsChange: "widgetDiagnosticsChange" }, host: { listeners: { "window:resize": "onWindowResize()", "window:pointermove": "onCanvasPointerMove($event)", "window:pointerup": "onCanvasPointerUp($event)", "window:pointercancel": "onCanvasPointerCancel($event)" } }, providers: [providePraxisI18nConfig(DYNAMIC_WIDGET_PAGE_I18N_CONFIG)], viewQueries: [{ propertyName: "pageCanvasHost", first: true, predicate: ["pageCanvasHost"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
25876
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: DynamicWidgetPageComponent, isStandalone: true, selector: "praxis-dynamic-page", inputs: { page: "page", context: "context", strictValidation: "strictValidation", enableCustomization: "enableCustomization", showPageSettingsButton: "showPageSettingsButton", shellEditorComponent: "shellEditorComponent", pageEditorComponent: "pageEditorComponent", autoPersist: "autoPersist", pageIdentity: "pageIdentity", componentInstanceId: "componentInstanceId" }, outputs: { pageChange: "pageChange", widgetEvent: "widgetEvent", widgetDiagnosticsChange: "widgetDiagnosticsChange" }, host: { listeners: { "window:resize": "onWindowResize()", "window:pointermove": "onCanvasPointerMove($event)", "window:pointerup": "onCanvasPointerUp($event)", "window:pointercancel": "onCanvasPointerCancel($event)" } }, providers: [providePraxisI18nConfig(DYNAMIC_WIDGET_PAGE_I18N_CONFIG)], viewQueries: [{ propertyName: "pageCanvasHost", first: true, predicate: ["pageCanvasHost"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
25295
25877
  <div class="pdx-page-wrapper" [class.editing]="enableCustomization">
25296
25878
  @if (enableCustomization && showPageSettingsButton) {
25297
- <button
25298
- class="pdx-page-settings"
25299
- mat-icon-button
25300
- type="button"
25301
- [matTooltip]="pageSettingsLabel()"
25302
- matTooltipPosition="below"
25303
- [attr.aria-label]="pageSettingsLabel()"
25304
- (click)="openPageSettings()"
25305
- >
25306
- <mat-icon fontSet="material-symbols-outlined">settings</mat-icon>
25307
- </button>
25879
+ <button
25880
+ class="pdx-page-settings"
25881
+ mat-icon-button
25882
+ type="button"
25883
+ [matTooltip]="pageSettingsLabel()"
25884
+ matTooltipPosition="below"
25885
+ [attr.aria-label]="pageSettingsLabel()"
25886
+ (click)="openPageSettings()"
25887
+ >
25888
+ <mat-icon fontSet="material-symbols-outlined">settings</mat-icon>
25889
+ </button>
25308
25890
  }
25309
25891
  <div
25310
25892
  #pageCanvasHost
@@ -25319,8 +25901,12 @@ class DynamicWidgetPageComponent {
25319
25901
  <div
25320
25902
  class="pdx-widget pdx-widget--canvas"
25321
25903
  [class.pdx-widget--interactive]="enableCustomization"
25322
- [class.pdx-widget--canvas-selected]="isCanvasWidgetSelected(w.key)"
25323
- [class.pdx-widget--canvas-blocked]="isCanvasWidgetBlocked(w.key)"
25904
+ [class.pdx-widget--canvas-selected]="
25905
+ enableCustomization && isCanvasWidgetSelected(w.key)
25906
+ "
25907
+ [class.pdx-widget--canvas-blocked]="
25908
+ enableCustomization && isCanvasWidgetBlocked(w.key)
25909
+ "
25324
25910
  [class]="widgetClassName(w)"
25325
25911
  [style.gridColumn]="widgetGridColumn(w)"
25326
25912
  [style.gridRow]="widgetGridRow(w)"
@@ -25338,7 +25924,9 @@ class DynamicWidgetPageComponent {
25338
25924
  [attr.aria-label]="resizeHandleLabel(handle.id)"
25339
25925
  [title]="resizeHandleLabel(handle.id)"
25340
25926
  (pointerdown)="startCanvasResize(w.key, handle.id, $event)"
25341
- (keydown)="onCanvasResizeHandleKeydown(w.key, handle.id, $event)"
25927
+ (keydown)="
25928
+ onCanvasResizeHandleKeydown(w.key, handle.id, $event)
25929
+ "
25342
25930
  >
25343
25931
  <span class="pdx-canvas-resize-grip"></span>
25344
25932
  </button>
@@ -25351,9 +25939,11 @@ class DynamicWidgetPageComponent {
25351
25939
  [dragSurfaceLabel]="dragWidgetLabel()"
25352
25940
  (action)="onShellAction(w.key, $event)"
25353
25941
  (dragSurfacePointerDown)="startCanvasDrag(w.key, $event)"
25354
- (dragSurfaceKeydown)="onCanvasHandleKeydown(w.key, 'drag', $event)"
25942
+ (dragSurfaceKeydown)="
25943
+ onCanvasHandleKeydown(w.key, 'drag', $event)
25944
+ "
25355
25945
  >
25356
- <ng-container
25946
+ <ng-container
25357
25947
  [dynamicWidgetLoader]="w.definition"
25358
25948
  [ownerWidgetKey]="w.key"
25359
25949
  [context]="mergedContext"
@@ -25377,7 +25967,15 @@ class DynamicWidgetPageComponent {
25377
25967
  @for (group of renderedGroups(); track group.id) {
25378
25968
  <section
25379
25969
  class="pdx-group"
25380
- [class]="'pdx-group--' + group.kind + (group.layout ? ' pdx-group--layout-' + group.layout : '') + (group.emphasis ? ' pdx-group--emphasis-' + group.emphasis : '') + (group.side ? ' pdx-group--side-' + group.side : '')"
25970
+ [class]="
25971
+ 'pdx-group--' +
25972
+ group.kind +
25973
+ (group.layout ? ' pdx-group--layout-' + group.layout : '') +
25974
+ (group.emphasis
25975
+ ? ' pdx-group--emphasis-' + group.emphasis
25976
+ : '') +
25977
+ (group.side ? ' pdx-group--side-' + group.side : '')
25978
+ "
25381
25979
  [style.gridColumn]="groupGridColumn(group)"
25382
25980
  [attr.data-group-id]="group.id"
25383
25981
  [attr.data-group-kind]="group.kind"
@@ -25403,9 +26001,19 @@ class DynamicWidgetPageComponent {
25403
26001
  </div>
25404
26002
  @for (tab of group.tabs || []; track tab.id) {
25405
26003
  @if (activeTabId(group.id) === tab.id) {
25406
- <div class="pdx-group-content" [class]="'pdx-group-content--' + resolveGroupContentLayout(group)">
26004
+ <div
26005
+ class="pdx-group-content"
26006
+ [class]="
26007
+ 'pdx-group-content--' +
26008
+ resolveGroupContentLayout(group)
26009
+ "
26010
+ >
25407
26011
  @for (w of tab.widgets; track w.key) {
25408
- <div class="pdx-widget" [class]="w.renderClassName || w.className || ''" [style.gridColumn]="widgetGridColumn(w)">
26012
+ <div
26013
+ class="pdx-widget"
26014
+ [class]="w.renderClassName || w.className || ''"
26015
+ [style.gridColumn]="widgetGridColumn(w)"
26016
+ >
25409
26017
  <praxis-widget-shell
25410
26018
  [shell]="w.shell"
25411
26019
  [context]="mergedContext"
@@ -25418,7 +26026,9 @@ class DynamicWidgetPageComponent {
25418
26026
  [strictValidation]="strictValidation"
25419
26027
  [autoWireOutputs]="shouldAutoWireOutputs(w)"
25420
26028
  (widgetEvent)="onWidgetEvent(w.key, $event)"
25421
- (widgetDiagnostic)="onWidgetDiagnostic(w.key, $event)"
26029
+ (widgetDiagnostic)="
26030
+ onWidgetDiagnostic(w.key, $event)
26031
+ "
25422
26032
  ></ng-container>
25423
26033
  </praxis-widget-shell>
25424
26034
  </div>
@@ -25428,9 +26038,18 @@ class DynamicWidgetPageComponent {
25428
26038
  }
25429
26039
  </div>
25430
26040
  } @else {
25431
- <div class="pdx-group-content" [class]="'pdx-group-content--' + resolveGroupContentLayout(group)">
26041
+ <div
26042
+ class="pdx-group-content"
26043
+ [class]="
26044
+ 'pdx-group-content--' + resolveGroupContentLayout(group)
26045
+ "
26046
+ >
25432
26047
  @for (w of group.widgets; track w.key) {
25433
- <div class="pdx-widget" [class]="widgetClassName(w)" [style.gridColumn]="widgetGridColumn(w)">
26048
+ <div
26049
+ class="pdx-widget"
26050
+ [class]="widgetClassName(w)"
26051
+ [style.gridColumn]="widgetGridColumn(w)"
26052
+ >
25434
26053
  <praxis-widget-shell
25435
26054
  [shell]="w.shell"
25436
26055
  [context]="mergedContext"
@@ -25454,7 +26073,11 @@ class DynamicWidgetPageComponent {
25454
26073
  }
25455
26074
  } @else {
25456
26075
  @for (w of widgets(); track w.key) {
25457
- <div class="pdx-widget" [class]="widgetClassName(w)" [style.gridColumn]="widgetGridColumn(w)">
26076
+ <div
26077
+ class="pdx-widget"
26078
+ [class]="widgetClassName(w)"
26079
+ [style.gridColumn]="widgetGridColumn(w)"
26080
+ >
25458
26081
  <praxis-widget-shell
25459
26082
  [shell]="w.shell"
25460
26083
  [context]="mergedContext"
@@ -25475,27 +26098,36 @@ class DynamicWidgetPageComponent {
25475
26098
  }
25476
26099
  </div>
25477
26100
  @if (layoutAnnouncement) {
25478
- <div class="pdx-sr-only" aria-live="polite">{{ layoutAnnouncement }}</div>
26101
+ <div class="pdx-sr-only" aria-live="polite">
26102
+ {{ layoutAnnouncement }}
26103
+ </div>
25479
26104
  }
25480
26105
  </div>
25481
26106
  `, isInline: true, styles: [".pdx-page-wrapper{position:relative;display:block}.pdx-page{display:grid;gap:12px;grid-template-columns:minmax(0,1fr)}.pdx-page--canvas{align-items:start;grid-auto-flow:dense}.pdx-page-settings{position:sticky;top:8px;z-index:2;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);color:inherit;border-radius:12px;width:36px;height:36px;margin-bottom:6px}.pdx-widget{position:relative;background:var(--pfx-surface, transparent);border-radius:6px;min-width:0;min-height:0}.pdx-widget--canvas{align-self:stretch;--pdx-resize-gradient-horizontal: linear-gradient( 90deg, color-mix(in srgb, var(--md-sys-color-primary) 94%, white 6%), color-mix(in srgb, var(--md-sys-color-tertiary) 90%, white 10%), color-mix(in srgb, var(--md-sys-color-secondary) 88%, white 12%) );--pdx-resize-gradient-vertical: linear-gradient( 180deg, color-mix(in srgb, var(--md-sys-color-primary) 94%, white 6%), color-mix(in srgb, var(--md-sys-color-tertiary) 90%, white 10%), color-mix(in srgb, var(--md-sys-color-secondary) 88%, white 12%) );--pdx-resize-gradient-diagonal-se: linear-gradient( 135deg, color-mix(in srgb, var(--md-sys-color-primary) 94%, white 6%), color-mix(in srgb, var(--md-sys-color-tertiary) 90%, white 10%), color-mix(in srgb, var(--md-sys-color-secondary) 88%, white 12%) );--pdx-resize-gradient-diagonal-sw: linear-gradient( 225deg, color-mix(in srgb, var(--md-sys-color-primary) 94%, white 6%), color-mix(in srgb, var(--md-sys-color-tertiary) 90%, white 10%), color-mix(in srgb, var(--md-sys-color-secondary) 88%, white 12%) );--pdx-active-resize-gradient: var(--pdx-resize-gradient-diagonal-se)}.pdx-widget--canvas:after{content:\"\";position:absolute;inset:0;padding:2px;border-radius:14px;background:var(--pdx-active-resize-gradient);opacity:0;pointer-events:none;transition:opacity .14s ease,filter .14s ease;filter:saturate(1.02) drop-shadow(0 0 5px color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent));-webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);-webkit-mask-composite:xor;mask-composite:exclude}.pdx-widget--canvas-selected:before,.pdx-widget--canvas-blocked:before{content:\"\";position:absolute;inset:0;border-radius:14px;pointer-events:none;z-index:1;transition:opacity .14s ease,box-shadow .14s ease,border-color .14s ease}.pdx-widget--canvas-selected:before{border:1px dashed color-mix(in srgb,var(--md-sys-color-primary) 34%,transparent);box-shadow:0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 6%,transparent),0 8px 20px color-mix(in srgb,var(--md-sys-color-primary) 6%,transparent)}.pdx-widget--canvas-blocked:before{border:1px solid color-mix(in srgb,var(--md-sys-color-error) 74%,transparent);box-shadow:0 0 0 1px color-mix(in srgb,var(--md-sys-color-error) 20%,transparent),0 10px 24px color-mix(in srgb,var(--md-sys-color-error) 12%,transparent)}.pdx-widget--canvas:has(.pdx-canvas-resize:hover):after,.pdx-widget--canvas:has(.pdx-canvas-resize:focus-visible):after{opacity:.82}.pdx-widget--canvas:has(.pdx-canvas-resize--north:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--north:focus-visible),.pdx-widget--canvas:has(.pdx-canvas-resize--south:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--south:focus-visible){--pdx-active-resize-gradient: var(--pdx-resize-gradient-horizontal)}.pdx-widget--canvas:has(.pdx-canvas-resize--east:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--east:focus-visible),.pdx-widget--canvas:has(.pdx-canvas-resize--west:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--west:focus-visible){--pdx-active-resize-gradient: var(--pdx-resize-gradient-vertical)}.pdx-widget--canvas:has(.pdx-canvas-resize--north-east:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--north-east:focus-visible),.pdx-widget--canvas:has(.pdx-canvas-resize--south-west:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--south-west:focus-visible){--pdx-active-resize-gradient: var(--pdx-resize-gradient-diagonal-sw)}.pdx-widget--canvas:has(.pdx-canvas-resize--north-west:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--north-west:focus-visible),.pdx-widget--canvas:has(.pdx-canvas-resize--south-east:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--south-east:focus-visible){--pdx-active-resize-gradient: var(--pdx-resize-gradient-diagonal-se)}.pdx-canvas-resize{position:absolute;z-index:7;border:0;padding:0;margin:0;background:transparent;touch-action:none;cursor:pointer;opacity:0;pointer-events:none;transform:scale(.94);transition:opacity .14s ease,transform .14s ease,filter .14s ease;filter:saturate(.9)}.pdx-widget--canvas:hover .pdx-canvas-resize,.pdx-widget--canvas:focus-within .pdx-canvas-resize,.pdx-widget--canvas-selected .pdx-canvas-resize{opacity:.88;pointer-events:auto;transform:scale(1);filter:saturate(1)}.pdx-canvas-resize-grip{display:block;width:9px;height:9px;border-radius:999px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 42%,var(--md-sys-color-outline-variant) 58%);background:color-mix(in srgb,var(--md-sys-color-surface) 92%,var(--md-sys-color-primary) 8%);box-shadow:0 1px 4px color-mix(in srgb,var(--md-sys-color-shadow) 10%,transparent);transition:transform .14s ease,border-color .14s ease,background .14s ease,box-shadow .14s ease}.pdx-canvas-resize:hover .pdx-canvas-resize-grip,.pdx-canvas-resize:focus-visible .pdx-canvas-resize-grip{border-color:color-mix(in srgb,var(--md-sys-color-primary) 58%,var(--md-sys-color-outline-variant) 42%);background:color-mix(in srgb,var(--md-sys-color-surface) 84%,var(--md-sys-color-primary) 16%);box-shadow:0 2px 7px color-mix(in srgb,var(--md-sys-color-primary) 14%,transparent);transform:scale(1.04)}.pdx-canvas-resize--north,.pdx-canvas-resize--south{left:50%;width:40px;height:18px;margin-left:-20px;display:flex;align-items:center;justify-content:center}.pdx-canvas-resize--north{top:-8px;cursor:ns-resize}.pdx-canvas-resize--south{bottom:-8px;cursor:ns-resize}.pdx-canvas-resize--east,.pdx-canvas-resize--west{top:50%;width:18px;height:40px;margin-top:-20px;display:flex;align-items:center;justify-content:center}.pdx-canvas-resize--east{right:-8px;cursor:ew-resize}.pdx-canvas-resize--west{left:-8px;cursor:ew-resize}.pdx-canvas-resize--north-east,.pdx-canvas-resize--north-west,.pdx-canvas-resize--south-east,.pdx-canvas-resize--south-west{width:18px;height:18px;display:flex;align-items:center;justify-content:center}.pdx-canvas-resize--north-east{top:-8px;right:-8px;cursor:nesw-resize}.pdx-canvas-resize--north-west{top:-8px;left:-8px;cursor:nwse-resize}.pdx-canvas-resize--south-east{bottom:-8px;right:-8px;cursor:nwse-resize}.pdx-canvas-resize--south-west{bottom:-8px;left:-8px;cursor:nesw-resize}.pdx-canvas-snap-preview{position:relative;align-self:stretch;border-radius:12px;pointer-events:none;z-index:0;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent),color-mix(in srgb,var(--md-sys-color-tertiary) 12%,transparent));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 42%,transparent),inset 0 0 0 2px color-mix(in srgb,var(--md-sys-color-surface) 55%,transparent);animation:pdx-snap-preview-pulse .48s ease-out infinite alternate}.pdx-canvas-snap-preview:before,.pdx-canvas-snap-preview:after{content:\"\";position:absolute;border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-primary) 82%,var(--md-sys-color-tertiary) 18%);opacity:.72}.pdx-canvas-snap-preview:before{inset:0 auto 0 0;width:3px}.pdx-canvas-snap-preview:after{inset:0 0 auto;height:3px}.pdx-canvas-snap-preview--invalid{background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-error) 18%,transparent),color-mix(in srgb,var(--md-sys-color-error-container) 22%,transparent));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--md-sys-color-error) 58%,transparent),inset 0 0 0 2px color-mix(in srgb,var(--md-sys-color-surface) 40%,transparent)}.pdx-canvas-snap-preview--invalid:before,.pdx-canvas-snap-preview--invalid:after{background:color-mix(in srgb,var(--md-sys-color-error) 86%,var(--md-sys-color-error-container) 14%)}.pdx-canvas-resize:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pdx-canvas-resize:hover .pdx-canvas-resize-grip,.pdx-canvas-resize:focus-visible .pdx-canvas-resize-grip{border-color:transparent;box-shadow:0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 20%,transparent),var(--mat-elevation-level3)}.pdx-canvas-resize--north:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--north:focus-visible .pdx-canvas-resize-grip,.pdx-canvas-resize--south:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--south:focus-visible .pdx-canvas-resize-grip{background:var(--pdx-resize-gradient-horizontal)}.pdx-canvas-resize--east:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--east:focus-visible .pdx-canvas-resize-grip,.pdx-canvas-resize--west:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--west:focus-visible .pdx-canvas-resize-grip{background:var(--pdx-resize-gradient-vertical)}.pdx-canvas-resize--north-east:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--north-east:focus-visible .pdx-canvas-resize-grip,.pdx-canvas-resize--south-west:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--south-west:focus-visible .pdx-canvas-resize-grip{background:var(--pdx-resize-gradient-diagonal-sw)}.pdx-canvas-resize--north-west:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--north-west:focus-visible .pdx-canvas-resize-grip,.pdx-canvas-resize--south-east:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--south-east:focus-visible .pdx-canvas-resize-grip{background:var(--pdx-resize-gradient-diagonal-se)}.pdx-canvas-resize:hover .pdx-canvas-resize-grip,.pdx-canvas-resize:focus-visible .pdx-canvas-resize-grip{transform:scale(1.08)}@keyframes pdx-snap-preview-pulse{0%{opacity:.72;transform:scale(.996)}to{opacity:1;transform:scale(1)}}.pdx-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.pdx-group{display:grid;gap:12px;grid-column:1 / -1;padding:12px;border-radius:16px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 76%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 72%,transparent)}.pdx-group--hero{padding:16px;background:linear-gradient(180deg,color-mix(in srgb,var(--md-sys-color-primary-container) 42%,transparent),color-mix(in srgb,var(--md-sys-color-surface-container-low) 86%,transparent))}.pdx-group--rail{align-self:start}.pdx-group-header{display:flex;align-items:center;justify-content:space-between;gap:12px}.pdx-group-title{font-size:.95rem;font-weight:600;color:var(--md-sys-color-on-surface)}.pdx-group-content{display:grid;gap:12px}.pdx-group-content--stack{grid-template-columns:minmax(0,1fr)}.pdx-group-content--row{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.pdx-group-content--grid{grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}.pdx-group-tabs{display:grid;gap:12px}.pdx-tabs-header{display:flex;flex-wrap:wrap;gap:8px}.pdx-tab-chip{appearance:none;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest);color:var(--md-sys-color-on-surface);border-radius:999px;padding:8px 12px;font:inherit;cursor:pointer}.pdx-tab-chip.active{border-color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 78%,transparent);color:var(--md-sys-color-on-primary-container)}.pdx-page-wrapper.editing .pdx-widget-settings{opacity:1}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: DynamicWidgetLoaderDirective, selector: "[dynamicWidgetLoader]", inputs: ["dynamicWidgetLoader", "ownerWidgetKey", "context", "strictValidation", "autoWireOutputs"], outputs: ["widgetEvent", "widgetDiagnostic"], exportAs: ["dynamicWidgetLoader"] }, { kind: "component", type: WidgetShellComponent, selector: "praxis-widget-shell", inputs: ["shell", "context", "dragSurfaceEnabled", "dragSurfaceLabel"], outputs: ["action", "dragSurfacePointerDown", "dragSurfaceKeydown"] }] });
25482
26107
  }
25483
26108
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DynamicWidgetPageComponent, decorators: [{
25484
26109
  type: Component,
25485
- args: [{ selector: 'praxis-dynamic-page', standalone: true, imports: [CommonModule, MatButtonModule, MatIconModule, MatTooltipModule, DynamicWidgetLoaderDirective, WidgetShellComponent], providers: [providePraxisI18nConfig(DYNAMIC_WIDGET_PAGE_I18N_CONFIG)], template: `
26110
+ args: [{ selector: 'praxis-dynamic-page', standalone: true, imports: [
26111
+ CommonModule,
26112
+ MatButtonModule,
26113
+ MatIconModule,
26114
+ MatTooltipModule,
26115
+ DynamicWidgetLoaderDirective,
26116
+ WidgetShellComponent,
26117
+ ], providers: [providePraxisI18nConfig(DYNAMIC_WIDGET_PAGE_I18N_CONFIG)], template: `
25486
26118
  <div class="pdx-page-wrapper" [class.editing]="enableCustomization">
25487
26119
  @if (enableCustomization && showPageSettingsButton) {
25488
- <button
25489
- class="pdx-page-settings"
25490
- mat-icon-button
25491
- type="button"
25492
- [matTooltip]="pageSettingsLabel()"
25493
- matTooltipPosition="below"
25494
- [attr.aria-label]="pageSettingsLabel()"
25495
- (click)="openPageSettings()"
25496
- >
25497
- <mat-icon fontSet="material-symbols-outlined">settings</mat-icon>
25498
- </button>
26120
+ <button
26121
+ class="pdx-page-settings"
26122
+ mat-icon-button
26123
+ type="button"
26124
+ [matTooltip]="pageSettingsLabel()"
26125
+ matTooltipPosition="below"
26126
+ [attr.aria-label]="pageSettingsLabel()"
26127
+ (click)="openPageSettings()"
26128
+ >
26129
+ <mat-icon fontSet="material-symbols-outlined">settings</mat-icon>
26130
+ </button>
25499
26131
  }
25500
26132
  <div
25501
26133
  #pageCanvasHost
@@ -25510,8 +26142,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
25510
26142
  <div
25511
26143
  class="pdx-widget pdx-widget--canvas"
25512
26144
  [class.pdx-widget--interactive]="enableCustomization"
25513
- [class.pdx-widget--canvas-selected]="isCanvasWidgetSelected(w.key)"
25514
- [class.pdx-widget--canvas-blocked]="isCanvasWidgetBlocked(w.key)"
26145
+ [class.pdx-widget--canvas-selected]="
26146
+ enableCustomization && isCanvasWidgetSelected(w.key)
26147
+ "
26148
+ [class.pdx-widget--canvas-blocked]="
26149
+ enableCustomization && isCanvasWidgetBlocked(w.key)
26150
+ "
25515
26151
  [class]="widgetClassName(w)"
25516
26152
  [style.gridColumn]="widgetGridColumn(w)"
25517
26153
  [style.gridRow]="widgetGridRow(w)"
@@ -25529,7 +26165,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
25529
26165
  [attr.aria-label]="resizeHandleLabel(handle.id)"
25530
26166
  [title]="resizeHandleLabel(handle.id)"
25531
26167
  (pointerdown)="startCanvasResize(w.key, handle.id, $event)"
25532
- (keydown)="onCanvasResizeHandleKeydown(w.key, handle.id, $event)"
26168
+ (keydown)="
26169
+ onCanvasResizeHandleKeydown(w.key, handle.id, $event)
26170
+ "
25533
26171
  >
25534
26172
  <span class="pdx-canvas-resize-grip"></span>
25535
26173
  </button>
@@ -25542,9 +26180,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
25542
26180
  [dragSurfaceLabel]="dragWidgetLabel()"
25543
26181
  (action)="onShellAction(w.key, $event)"
25544
26182
  (dragSurfacePointerDown)="startCanvasDrag(w.key, $event)"
25545
- (dragSurfaceKeydown)="onCanvasHandleKeydown(w.key, 'drag', $event)"
26183
+ (dragSurfaceKeydown)="
26184
+ onCanvasHandleKeydown(w.key, 'drag', $event)
26185
+ "
25546
26186
  >
25547
- <ng-container
26187
+ <ng-container
25548
26188
  [dynamicWidgetLoader]="w.definition"
25549
26189
  [ownerWidgetKey]="w.key"
25550
26190
  [context]="mergedContext"
@@ -25568,7 +26208,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
25568
26208
  @for (group of renderedGroups(); track group.id) {
25569
26209
  <section
25570
26210
  class="pdx-group"
25571
- [class]="'pdx-group--' + group.kind + (group.layout ? ' pdx-group--layout-' + group.layout : '') + (group.emphasis ? ' pdx-group--emphasis-' + group.emphasis : '') + (group.side ? ' pdx-group--side-' + group.side : '')"
26211
+ [class]="
26212
+ 'pdx-group--' +
26213
+ group.kind +
26214
+ (group.layout ? ' pdx-group--layout-' + group.layout : '') +
26215
+ (group.emphasis
26216
+ ? ' pdx-group--emphasis-' + group.emphasis
26217
+ : '') +
26218
+ (group.side ? ' pdx-group--side-' + group.side : '')
26219
+ "
25572
26220
  [style.gridColumn]="groupGridColumn(group)"
25573
26221
  [attr.data-group-id]="group.id"
25574
26222
  [attr.data-group-kind]="group.kind"
@@ -25594,9 +26242,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
25594
26242
  </div>
25595
26243
  @for (tab of group.tabs || []; track tab.id) {
25596
26244
  @if (activeTabId(group.id) === tab.id) {
25597
- <div class="pdx-group-content" [class]="'pdx-group-content--' + resolveGroupContentLayout(group)">
26245
+ <div
26246
+ class="pdx-group-content"
26247
+ [class]="
26248
+ 'pdx-group-content--' +
26249
+ resolveGroupContentLayout(group)
26250
+ "
26251
+ >
25598
26252
  @for (w of tab.widgets; track w.key) {
25599
- <div class="pdx-widget" [class]="w.renderClassName || w.className || ''" [style.gridColumn]="widgetGridColumn(w)">
26253
+ <div
26254
+ class="pdx-widget"
26255
+ [class]="w.renderClassName || w.className || ''"
26256
+ [style.gridColumn]="widgetGridColumn(w)"
26257
+ >
25600
26258
  <praxis-widget-shell
25601
26259
  [shell]="w.shell"
25602
26260
  [context]="mergedContext"
@@ -25609,7 +26267,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
25609
26267
  [strictValidation]="strictValidation"
25610
26268
  [autoWireOutputs]="shouldAutoWireOutputs(w)"
25611
26269
  (widgetEvent)="onWidgetEvent(w.key, $event)"
25612
- (widgetDiagnostic)="onWidgetDiagnostic(w.key, $event)"
26270
+ (widgetDiagnostic)="
26271
+ onWidgetDiagnostic(w.key, $event)
26272
+ "
25613
26273
  ></ng-container>
25614
26274
  </praxis-widget-shell>
25615
26275
  </div>
@@ -25619,9 +26279,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
25619
26279
  }
25620
26280
  </div>
25621
26281
  } @else {
25622
- <div class="pdx-group-content" [class]="'pdx-group-content--' + resolveGroupContentLayout(group)">
26282
+ <div
26283
+ class="pdx-group-content"
26284
+ [class]="
26285
+ 'pdx-group-content--' + resolveGroupContentLayout(group)
26286
+ "
26287
+ >
25623
26288
  @for (w of group.widgets; track w.key) {
25624
- <div class="pdx-widget" [class]="widgetClassName(w)" [style.gridColumn]="widgetGridColumn(w)">
26289
+ <div
26290
+ class="pdx-widget"
26291
+ [class]="widgetClassName(w)"
26292
+ [style.gridColumn]="widgetGridColumn(w)"
26293
+ >
25625
26294
  <praxis-widget-shell
25626
26295
  [shell]="w.shell"
25627
26296
  [context]="mergedContext"
@@ -25645,7 +26314,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
25645
26314
  }
25646
26315
  } @else {
25647
26316
  @for (w of widgets(); track w.key) {
25648
- <div class="pdx-widget" [class]="widgetClassName(w)" [style.gridColumn]="widgetGridColumn(w)">
26317
+ <div
26318
+ class="pdx-widget"
26319
+ [class]="widgetClassName(w)"
26320
+ [style.gridColumn]="widgetGridColumn(w)"
26321
+ >
25649
26322
  <praxis-widget-shell
25650
26323
  [shell]="w.shell"
25651
26324
  [context]="mergedContext"
@@ -25666,7 +26339,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
25666
26339
  }
25667
26340
  </div>
25668
26341
  @if (layoutAnnouncement) {
25669
- <div class="pdx-sr-only" aria-live="polite">{{ layoutAnnouncement }}</div>
26342
+ <div class="pdx-sr-only" aria-live="polite">
26343
+ {{ layoutAnnouncement }}
26344
+ </div>
25670
26345
  }
25671
26346
  </div>
25672
26347
  `, styles: [".pdx-page-wrapper{position:relative;display:block}.pdx-page{display:grid;gap:12px;grid-template-columns:minmax(0,1fr)}.pdx-page--canvas{align-items:start;grid-auto-flow:dense}.pdx-page-settings{position:sticky;top:8px;z-index:2;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);color:inherit;border-radius:12px;width:36px;height:36px;margin-bottom:6px}.pdx-widget{position:relative;background:var(--pfx-surface, transparent);border-radius:6px;min-width:0;min-height:0}.pdx-widget--canvas{align-self:stretch;--pdx-resize-gradient-horizontal: linear-gradient( 90deg, color-mix(in srgb, var(--md-sys-color-primary) 94%, white 6%), color-mix(in srgb, var(--md-sys-color-tertiary) 90%, white 10%), color-mix(in srgb, var(--md-sys-color-secondary) 88%, white 12%) );--pdx-resize-gradient-vertical: linear-gradient( 180deg, color-mix(in srgb, var(--md-sys-color-primary) 94%, white 6%), color-mix(in srgb, var(--md-sys-color-tertiary) 90%, white 10%), color-mix(in srgb, var(--md-sys-color-secondary) 88%, white 12%) );--pdx-resize-gradient-diagonal-se: linear-gradient( 135deg, color-mix(in srgb, var(--md-sys-color-primary) 94%, white 6%), color-mix(in srgb, var(--md-sys-color-tertiary) 90%, white 10%), color-mix(in srgb, var(--md-sys-color-secondary) 88%, white 12%) );--pdx-resize-gradient-diagonal-sw: linear-gradient( 225deg, color-mix(in srgb, var(--md-sys-color-primary) 94%, white 6%), color-mix(in srgb, var(--md-sys-color-tertiary) 90%, white 10%), color-mix(in srgb, var(--md-sys-color-secondary) 88%, white 12%) );--pdx-active-resize-gradient: var(--pdx-resize-gradient-diagonal-se)}.pdx-widget--canvas:after{content:\"\";position:absolute;inset:0;padding:2px;border-radius:14px;background:var(--pdx-active-resize-gradient);opacity:0;pointer-events:none;transition:opacity .14s ease,filter .14s ease;filter:saturate(1.02) drop-shadow(0 0 5px color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent));-webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);-webkit-mask-composite:xor;mask-composite:exclude}.pdx-widget--canvas-selected:before,.pdx-widget--canvas-blocked:before{content:\"\";position:absolute;inset:0;border-radius:14px;pointer-events:none;z-index:1;transition:opacity .14s ease,box-shadow .14s ease,border-color .14s ease}.pdx-widget--canvas-selected:before{border:1px dashed color-mix(in srgb,var(--md-sys-color-primary) 34%,transparent);box-shadow:0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 6%,transparent),0 8px 20px color-mix(in srgb,var(--md-sys-color-primary) 6%,transparent)}.pdx-widget--canvas-blocked:before{border:1px solid color-mix(in srgb,var(--md-sys-color-error) 74%,transparent);box-shadow:0 0 0 1px color-mix(in srgb,var(--md-sys-color-error) 20%,transparent),0 10px 24px color-mix(in srgb,var(--md-sys-color-error) 12%,transparent)}.pdx-widget--canvas:has(.pdx-canvas-resize:hover):after,.pdx-widget--canvas:has(.pdx-canvas-resize:focus-visible):after{opacity:.82}.pdx-widget--canvas:has(.pdx-canvas-resize--north:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--north:focus-visible),.pdx-widget--canvas:has(.pdx-canvas-resize--south:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--south:focus-visible){--pdx-active-resize-gradient: var(--pdx-resize-gradient-horizontal)}.pdx-widget--canvas:has(.pdx-canvas-resize--east:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--east:focus-visible),.pdx-widget--canvas:has(.pdx-canvas-resize--west:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--west:focus-visible){--pdx-active-resize-gradient: var(--pdx-resize-gradient-vertical)}.pdx-widget--canvas:has(.pdx-canvas-resize--north-east:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--north-east:focus-visible),.pdx-widget--canvas:has(.pdx-canvas-resize--south-west:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--south-west:focus-visible){--pdx-active-resize-gradient: var(--pdx-resize-gradient-diagonal-sw)}.pdx-widget--canvas:has(.pdx-canvas-resize--north-west:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--north-west:focus-visible),.pdx-widget--canvas:has(.pdx-canvas-resize--south-east:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--south-east:focus-visible){--pdx-active-resize-gradient: var(--pdx-resize-gradient-diagonal-se)}.pdx-canvas-resize{position:absolute;z-index:7;border:0;padding:0;margin:0;background:transparent;touch-action:none;cursor:pointer;opacity:0;pointer-events:none;transform:scale(.94);transition:opacity .14s ease,transform .14s ease,filter .14s ease;filter:saturate(.9)}.pdx-widget--canvas:hover .pdx-canvas-resize,.pdx-widget--canvas:focus-within .pdx-canvas-resize,.pdx-widget--canvas-selected .pdx-canvas-resize{opacity:.88;pointer-events:auto;transform:scale(1);filter:saturate(1)}.pdx-canvas-resize-grip{display:block;width:9px;height:9px;border-radius:999px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 42%,var(--md-sys-color-outline-variant) 58%);background:color-mix(in srgb,var(--md-sys-color-surface) 92%,var(--md-sys-color-primary) 8%);box-shadow:0 1px 4px color-mix(in srgb,var(--md-sys-color-shadow) 10%,transparent);transition:transform .14s ease,border-color .14s ease,background .14s ease,box-shadow .14s ease}.pdx-canvas-resize:hover .pdx-canvas-resize-grip,.pdx-canvas-resize:focus-visible .pdx-canvas-resize-grip{border-color:color-mix(in srgb,var(--md-sys-color-primary) 58%,var(--md-sys-color-outline-variant) 42%);background:color-mix(in srgb,var(--md-sys-color-surface) 84%,var(--md-sys-color-primary) 16%);box-shadow:0 2px 7px color-mix(in srgb,var(--md-sys-color-primary) 14%,transparent);transform:scale(1.04)}.pdx-canvas-resize--north,.pdx-canvas-resize--south{left:50%;width:40px;height:18px;margin-left:-20px;display:flex;align-items:center;justify-content:center}.pdx-canvas-resize--north{top:-8px;cursor:ns-resize}.pdx-canvas-resize--south{bottom:-8px;cursor:ns-resize}.pdx-canvas-resize--east,.pdx-canvas-resize--west{top:50%;width:18px;height:40px;margin-top:-20px;display:flex;align-items:center;justify-content:center}.pdx-canvas-resize--east{right:-8px;cursor:ew-resize}.pdx-canvas-resize--west{left:-8px;cursor:ew-resize}.pdx-canvas-resize--north-east,.pdx-canvas-resize--north-west,.pdx-canvas-resize--south-east,.pdx-canvas-resize--south-west{width:18px;height:18px;display:flex;align-items:center;justify-content:center}.pdx-canvas-resize--north-east{top:-8px;right:-8px;cursor:nesw-resize}.pdx-canvas-resize--north-west{top:-8px;left:-8px;cursor:nwse-resize}.pdx-canvas-resize--south-east{bottom:-8px;right:-8px;cursor:nwse-resize}.pdx-canvas-resize--south-west{bottom:-8px;left:-8px;cursor:nesw-resize}.pdx-canvas-snap-preview{position:relative;align-self:stretch;border-radius:12px;pointer-events:none;z-index:0;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent),color-mix(in srgb,var(--md-sys-color-tertiary) 12%,transparent));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 42%,transparent),inset 0 0 0 2px color-mix(in srgb,var(--md-sys-color-surface) 55%,transparent);animation:pdx-snap-preview-pulse .48s ease-out infinite alternate}.pdx-canvas-snap-preview:before,.pdx-canvas-snap-preview:after{content:\"\";position:absolute;border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-primary) 82%,var(--md-sys-color-tertiary) 18%);opacity:.72}.pdx-canvas-snap-preview:before{inset:0 auto 0 0;width:3px}.pdx-canvas-snap-preview:after{inset:0 0 auto;height:3px}.pdx-canvas-snap-preview--invalid{background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-error) 18%,transparent),color-mix(in srgb,var(--md-sys-color-error-container) 22%,transparent));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--md-sys-color-error) 58%,transparent),inset 0 0 0 2px color-mix(in srgb,var(--md-sys-color-surface) 40%,transparent)}.pdx-canvas-snap-preview--invalid:before,.pdx-canvas-snap-preview--invalid:after{background:color-mix(in srgb,var(--md-sys-color-error) 86%,var(--md-sys-color-error-container) 14%)}.pdx-canvas-resize:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pdx-canvas-resize:hover .pdx-canvas-resize-grip,.pdx-canvas-resize:focus-visible .pdx-canvas-resize-grip{border-color:transparent;box-shadow:0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 20%,transparent),var(--mat-elevation-level3)}.pdx-canvas-resize--north:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--north:focus-visible .pdx-canvas-resize-grip,.pdx-canvas-resize--south:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--south:focus-visible .pdx-canvas-resize-grip{background:var(--pdx-resize-gradient-horizontal)}.pdx-canvas-resize--east:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--east:focus-visible .pdx-canvas-resize-grip,.pdx-canvas-resize--west:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--west:focus-visible .pdx-canvas-resize-grip{background:var(--pdx-resize-gradient-vertical)}.pdx-canvas-resize--north-east:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--north-east:focus-visible .pdx-canvas-resize-grip,.pdx-canvas-resize--south-west:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--south-west:focus-visible .pdx-canvas-resize-grip{background:var(--pdx-resize-gradient-diagonal-sw)}.pdx-canvas-resize--north-west:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--north-west:focus-visible .pdx-canvas-resize-grip,.pdx-canvas-resize--south-east:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--south-east:focus-visible .pdx-canvas-resize-grip{background:var(--pdx-resize-gradient-diagonal-se)}.pdx-canvas-resize:hover .pdx-canvas-resize-grip,.pdx-canvas-resize:focus-visible .pdx-canvas-resize-grip{transform:scale(1.08)}@keyframes pdx-snap-preview-pulse{0%{opacity:.72;transform:scale(.996)}to{opacity:1;transform:scale(1)}}.pdx-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.pdx-group{display:grid;gap:12px;grid-column:1 / -1;padding:12px;border-radius:16px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 76%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 72%,transparent)}.pdx-group--hero{padding:16px;background:linear-gradient(180deg,color-mix(in srgb,var(--md-sys-color-primary-container) 42%,transparent),color-mix(in srgb,var(--md-sys-color-surface-container-low) 86%,transparent))}.pdx-group--rail{align-self:start}.pdx-group-header{display:flex;align-items:center;justify-content:space-between;gap:12px}.pdx-group-title{font-size:.95rem;font-weight:600;color:var(--md-sys-color-on-surface)}.pdx-group-content{display:grid;gap:12px}.pdx-group-content--stack{grid-template-columns:minmax(0,1fr)}.pdx-group-content--row{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.pdx-group-content--grid{grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}.pdx-group-tabs{display:grid;gap:12px}.pdx-tabs-header{display:flex;flex-wrap:wrap;gap:8px}.pdx-tab-chip{appearance:none;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest);color:var(--md-sys-color-on-surface);border-radius:999px;padding:8px 12px;font:inherit;cursor:pointer}.pdx-tab-chip.active{border-color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 78%,transparent);color:var(--md-sys-color-on-primary-container)}.pdx-page-wrapper.editing .pdx-widget-settings{opacity:1}\n"] }]
@@ -25695,6 +26370,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
25695
26370
  type: Input
25696
26371
  }], pageChange: [{
25697
26372
  type: Output
26373
+ }], widgetEvent: [{
26374
+ type: Output
25698
26375
  }], widgetDiagnosticsChange: [{
25699
26376
  type: Output
25700
26377
  }], onWindowResize: [{
@@ -25733,6 +26410,7 @@ const PRAXIS_DYNAMIC_PAGE_COMPONENT_METADATA = {
25733
26410
  ],
25734
26411
  outputs: [
25735
26412
  { name: 'pageChange', type: 'WidgetPageDefinition', description: 'Emitido ao alterar a definicao da pagina.' },
26413
+ { name: 'widgetEvent', type: 'WidgetEventEnvelope', description: 'Reemite eventos dos widgets filhos com ownerWidgetKey para integracoes do host.' },
25736
26414
  { name: 'widgetDiagnosticsChange', type: 'Record<string, WidgetResolutionDiagnostic>', description: 'Emitido quando o runtime detecta widgets resolvidos ou falhos durante o carregamento dinamico.' },
25737
26415
  ],
25738
26416
  tags: ['widget', 'page', 'dynamic', 'layout'],
@@ -26669,12 +27347,18 @@ function buildBaseFormField(def) {
26669
27347
  }
26670
27348
  function applyLocalCustomizations$1(base, local) {
26671
27349
  const typeChanged = (base.controlType || '') !== (local.controlType || '');
27350
+ const serverBackedLocal = stripLocalSubmitSemantics(local);
26672
27351
  // Server authority on identity/core props
26673
27352
  const authoritative = {
26674
27353
  name: base.name,
26675
27354
  label: base.label,
26676
27355
  controlType: base.controlType,
26677
27356
  required: base.required,
27357
+ endpoint: base.endpoint,
27358
+ resourcePath: base.resourcePath,
27359
+ optionSource: base.optionSource,
27360
+ optionLabelKey: base.optionLabelKey,
27361
+ optionValueKey: base.optionValueKey,
26678
27362
  // Validators: server overrides conflicting keys; keep local extras
26679
27363
  validators: {
26680
27364
  ...local?.validators,
@@ -26697,24 +27381,32 @@ function applyLocalCustomizations$1(base, local) {
26697
27381
  ...local.materialDesign,
26698
27382
  ...base.materialDesign,
26699
27383
  },
26700
- // Options-like families: keep local if explicitly provided, otherwise server
27384
+ // Static option lists can be local UI customization. Remote option source
27385
+ // semantics are owned by the server schema for server-backed fields.
26701
27386
  options: local.options !== undefined
26702
27387
  ? local.options
26703
27388
  : base.options,
26704
- endpoint: local.endpoint !== undefined
26705
- ? local.endpoint
26706
- : base.endpoint,
26707
- queryParams: local.queryParams !== undefined
26708
- ? local.queryParams
27389
+ queryParams: serverBackedLocal.queryParams !== undefined
27390
+ ? serverBackedLocal.queryParams
26709
27391
  : base.queryParams,
26710
27392
  };
26711
27393
  return {
26712
27394
  ...base,
26713
- ...local,
27395
+ ...serverBackedLocal,
26714
27396
  ...authoritative,
26715
27397
  ...preserved,
26716
27398
  };
26717
27399
  }
27400
+ function stripLocalSubmitSemantics(field) {
27401
+ const { source, transient, submitPolicy, ...rest } = field;
27402
+ void source;
27403
+ void transient;
27404
+ void submitPolicy;
27405
+ return rest;
27406
+ }
27407
+ function isLocalField(field) {
27408
+ return field.source === 'local';
27409
+ }
26718
27410
  function reconcileFormConfig(layout, serverDefs) {
26719
27411
  const serverMetas = mapFieldDefinitionsToMetadata(serverDefs);
26720
27412
  const localMetas = (layout.fieldMetadata || []);
@@ -26732,11 +27424,13 @@ function reconcileFormConfig(layout, serverDefs) {
26732
27424
  merged.push(buildBaseFormField(serverField));
26733
27425
  }
26734
27426
  }
26735
- // Orphans: keep but hide in form
27427
+ // Orphans: preserve explicit local fields; hide legacy schema fields that no
27428
+ // longer exist on the server.
26736
27429
  for (const [name, localField] of localByName) {
26737
27430
  if (!serverByName.has(name)) {
26738
- const hidden = { ...localField, formHidden: true };
26739
- merged.push(hidden);
27431
+ merged.push(isLocalField(localField)
27432
+ ? localField
27433
+ : { ...localField, formHidden: true });
26740
27434
  }
26741
27435
  }
26742
27436
  // Preserve layout (sections/rows/columns) order, only affect fieldMetadata
@@ -27159,4 +27853,4 @@ function provideHookWhitelist(allowed) {
27159
27853
  * Generated bundle index. Do not edit.
27160
27854
  */
27161
27855
 
27162
- export { API_CONFIG_STORAGE_OPTIONS, API_URL, ASYNC_CONFIG_STORAGE, AllowedFileTypes, AnalyticsPresentationResolver, AnalyticsSchemaContractService, AnalyticsStatsRequestBuilderService, ApiConfigStorage, ApiEndpoint, BUILTIN_PAGE_LAYOUT_PRESETS, BUILTIN_PAGE_THEME_PRESETS, BUILTIN_SHELL_PRESETS, CONFIG_STORAGE, CONNECTION_STORAGE, ComponentKeyService, ComponentMetadataRegistry, CompositionRuntimeFacade, ConsoleLoggerSink, CrudOperationResolutionService, DEFAULT_FIELD_SELECTOR_CONTROL_TYPE_MAP, DEFAULT_JSON_LOGIC_OPERATORS, DEFAULT_TABLE_CONFIG, DYNAMIC_PAGE_AI_CAPABILITIES, DYNAMIC_PAGE_COMPONENT_CONTEXT_PACK, DYNAMIC_PAGE_CONFIG_EDITOR, DYNAMIC_PAGE_SHELL_EDITOR, DefaultLoadingRenderer, DeferredAsyncConfigStorage, DynamicFormService, DynamicWidgetLoaderDirective, DynamicWidgetPageComponent, EDITORIAL_ALLOWED_CONTENT_FORMATS, EDITORIAL_COMPLIANCE_PRESETS, EDITORIAL_EXTERNAL_LINK_REL, EDITORIAL_FORM_TEMPLATE_CATALOG, EDITORIAL_HTML_ENABLED, EDITORIAL_MARKDOWN_IMAGES_ENABLED, EDITORIAL_SOLUTION_CATALOG, EDITORIAL_SOLUTION_PRESETS, EDITORIAL_THEME_PRESETS, EDITORIAL_WIDGET_CONVENTION_INPUTS, EDITORIAL_WIDGET_TAG, EMPLOYEE_ONBOARDING_EDITORIAL_SOLUTION, EMPLOYEE_ONBOARDING_EDITORIAL_TEMPLATE, EMPLOYEE_ONBOARDING_GUIDED_EDITORIAL_SOLUTION, EMPLOYEE_ONBOARDING_GUIDED_EDITORIAL_TEMPLATE, EVENT_REGISTRATION_EDITORIAL_SOLUTION, EVENT_REGISTRATION_EDITORIAL_TEMPLATE, EmptyStateCardComponent, ErrorMessageService, FIELD_METADATA_CAPABILITIES, FIELD_SELECTOR_REGISTRY_BASE, FIELD_SELECTOR_REGISTRY_DISABLE_DEFAULTS, FIELD_SELECTOR_REGISTRY_OVERRIDES, FORM_HOOKS, FORM_HOOKS_PRESETS, FORM_HOOKS_WHITELIST, FORM_HOOK_RESOLVERS, FieldControlType, FieldDataType, FieldSelectorRegistry, FormHooksRegistry, GLOBAL_ACTION_CATALOG$1 as GLOBAL_ACTION_CATALOG, GLOBAL_ACTION_HANDLERS, GLOBAL_ACTION_CATALOG as GLOBAL_ACTION_SPEC_CATALOG, GLOBAL_ACTION_UI_SCHEMAS, GLOBAL_ANALYTICS_SERVICE, GLOBAL_API_CLIENT, GLOBAL_CONFIG, GLOBAL_DIALOG_SERVICE, GLOBAL_ROUTE_GUARD_RESOLVER, GLOBAL_SURFACE_SERVICE, GLOBAL_TOAST_SERVICE, GenericCrudService, GlobalActionService, GlobalConfigService, INLINE_FILTER_ALIAS_TOKENS, INLINE_FILTER_CONTROL_TYPES, INLINE_FILTER_CONTROL_TYPE_SET, INLINE_FILTER_CONTROL_TYPE_VALUES, INLINE_FILTER_TOKEN_TO_BASE_CONTROL_TYPE, INLINE_FILTER_TOKEN_TO_CONTROL_TYPE, IconPickerService, IconPosition, IconSize, LOGGER_LEVEL_BY_ENV, LOGGER_LEVEL_PRIORITY, LoadingOrchestrator, LocalConnectionStorage, LocalStorageAsyncAdapter, LocalStorageCacheAdapter, LocalStorageConfigService, LoggerService, LoggerThrottleTracker, LoggerWarnOnceTracker, MemoryCacheAdapter, NumericFormat, OVERLAY_DECIDER_DEBUG, OVERLAY_DECISION_MATRIX, ObservabilityDashboardService, OverlayDeciderService, PRAXIS_CORPORATE_SENSITIVE_KEYS, PRAXIS_DEFAULT_OBSERVABILITY_ALERT_RULES, PRAXIS_DYNAMIC_PAGE_COMPONENT_METADATA, PRAXIS_FOOTER_LINKS_METADATA, PRAXIS_GLOBAL_ACTION_CATALOG, PRAXIS_GLOBAL_CONFIG_BOOTSTRAP_OPTIONS, PRAXIS_GLOBAL_CONFIG_BOOTSTRAP_READY, PRAXIS_GLOBAL_CONFIG_TENANT_RESOLVER, PRAXIS_HERO_BANNER_METADATA, PRAXIS_I18N_CONFIG, PRAXIS_I18N_TRANSLATOR, PRAXIS_JSON_LOGIC_OPERATORS, PRAXIS_LAYER_SCALE_DEFAULTS, PRAXIS_LAYER_SCALE_VARS, PRAXIS_LEGAL_NOTICE_METADATA, PRAXIS_LOADING_CTX, PRAXIS_LOADING_RENDERER, PRAXIS_LOGGER_CONFIG, PRAXIS_LOGGER_SINKS, PRAXIS_OBSERVABILITY_DASHBOARD_OPTIONS, PRAXIS_RICH_TEXT_BLOCK_METADATA, PRAXIS_TELEMETRY_TRANSPORT, PRAXIS_USER_CONTEXT_SUMMARY_METADATA, PRIVACY_CONSENT_EDITORIAL_SOLUTION, PRIVACY_CONSENT_EDITORIAL_TEMPLATE, PraxisCore, PraxisFooterLinksComponent, PraxisGlobalErrorHandler, PraxisHeroBannerComponent, PraxisI18nService, PraxisIconDirective, PraxisIconPickerComponent, PraxisJsonLogicError, PraxisJsonLogicService, PraxisLayerScaleStyleService, PraxisLegalNoticeComponent, PraxisLoadingInterceptor, PraxisRichTextBlockComponent, PraxisSurfaceHostComponent, PraxisUserContextSummaryComponent, RESOURCE_DISCOVERY_I18N_CONFIG, RESOURCE_DISCOVERY_I18N_NAMESPACE, RULE_PROPERTY_SCHEMA, RemoteConfigStorage, ResourceActionOpenAdapterService, ResourceDiscoveryService, ResourceQuickConnectComponent, ResourceSurfaceOpenAdapterService, SCHEMA_VIEWER_CONTEXT, SETTINGS_PANEL_BRIDGE, SETTINGS_PANEL_DATA, STEPPER_CONFIG_EDITOR, SURFACE_DRAWER_BRIDGE, SURFACE_OPEN_I18N_CONFIG, SURFACE_OPEN_I18N_NAMESPACE, SURFACE_OPEN_PRESETS, SchemaMetadataClient, SchemaNormalizerService, SchemaViewerComponent, SurfaceBindingRuntimeService, SurfaceOpenActionEditorComponent, TABLE_CONFIG_EDITOR, TableConfigService, TelemetryLoggerSink, TelemetryService, ValidationPattern, WidgetPageStateRuntimeService, WidgetShellComponent, applyLocalCustomizations$2 as applyLocalCustomizations, applyLocalCustomizations$1 as applyLocalFormCustomizations, buildAngularValidators, buildApiUrl, buildBaseColumnFromDef, buildBaseFormField, buildFormConfigFromEditorialTemplate, buildHeaders, buildPageKey, buildPraxisLayerScaleCss, buildSchemaId, buildValidatorsFromValidatorOptions, cancelIfCpfInvalidHook, clampRange, cloneTableConfig, cnpjAlphaValidator, collapseWhitespace, composeHeadersWithVersion, conditionalAsyncValidator, convertFormLayoutToConfig, createCorporateLoggerConfig, createCorporateObservabilityOptions, createCpfCnpjValidator, createDefaultFormConfig, createDefaultTableConfig, createEmptyFormConfig, createEmptyRichContentDocument, createPersistedPage, customAsyncValidatorFn, customValidatorFn, debounceAsyncValidator, deepMerge, ensureIds, ensureNoConflictsHookFactory, ensurePageIds, extractNormalizedError, fetchWithETag, fileTypeValidator, fillUndefined, generateId, getDefaultFormHints, getEditorialCompliancePresetById, getEditorialFormTemplateById, getEditorialFormTemplateCatalog, getEditorialSolutionById, getEditorialSolutionCatalog, getEditorialSolutionPresetById, getEditorialThemePresetById, getEssentialConfig, getFieldMetadataCapabilities, getGlobalActionCatalog, getGlobalActionUiSchema, getReferencedFieldMetadata, getTextTransformer, interpolatePraxisTranslation, isAllowedEditorialContentFormat, isAllowedEditorialHref, isCssTextTransform, isEditorialComponentMeta, isInlineFilterControlType, isRangeValidForFilter, isTableConfigV2, isValidFormConfig, isValidTableConfig, legacyCnpjValidator, legacyCpfValidator, logOnErrorHook, mapFieldDefinitionToMetadata, mapFieldDefinitionsToMetadata, matchFieldValidator, maxFileSizeValidator, mergeFieldMetadata, mergePraxisI18nConfigs, mergeTableConfigs, migrateFormLayoutRule, migrateLegacyCompositionLink, migrateLegacyCompositionLinks, minWordsValidator, normalizeControlTypeKey, normalizeControlTypeToken, normalizeEditorialLink, normalizeEnd, normalizeFieldConstraints, normalizeFormConfig, normalizeFormMetadata, normalizePath, normalizePraxisDataQueryContext, normalizeResourceAvailabilityReasonCode, normalizeStart, normalizeUnknownError, notifySuccessHook, parseJsonResponseOrEmpty, praxisLoadingInterceptorFn, prefillFromContextHook, provideDefaultFormHooks, provideFieldSelectorRegistryBase, provideFieldSelectorRegistryOverride, provideFieldSelectorRegistryRuntime, provideFormHookPresets, provideFormHooks, provideGlobalActionCatalog, provideGlobalActionHandler, provideGlobalConfig, provideGlobalConfigReady, provideGlobalConfigSeed, provideGlobalConfigTenant, provideHookResolvers, provideHookWhitelist, provideOverlayDecisionMatrix, providePraxisAnalyticsGlobalActions, providePraxisDynamicPageMetadata, providePraxisFooterLinksMetadata, providePraxisGlobalActionCatalog, providePraxisGlobalActions, providePraxisGlobalConfigBootstrap, providePraxisHeroBannerMetadata, providePraxisHttpLoading, providePraxisI18n, providePraxisI18nConfig, providePraxisI18nTranslator, providePraxisIconDefaults, providePraxisJsonLogicOperator, providePraxisLegalNoticeMetadata, providePraxisLoadingDefaults, providePraxisLogging, providePraxisRichTextBlockMetadata, providePraxisToastGlobalActions, providePraxisUserContextSummaryMetadata, provideRemoteGlobalConfig, reconcileFilterConfig, reconcileFormConfig, reconcileTableConfig, removeDiacritics, reportTelemetryHookFactory, requiredCheckedValidator, resolveBuiltinPresets, resolveControlTypeAlias, resolveDefaultValuePresentationFormat, resolveHidden, resolveInlineFilterControlType, resolveInlineFilterControlTypeToBaseControlType, resolveLoggerConfig, resolveObservabilityOptions, resolveOffset, resolveOrder, resolvePraxisFilterCriteria, resolveResourceAvailabilityReasonKey, resolveSpan, resolveValuePresentation, resolveValuePresentationLocale, slugify, stripMasksHook, supportsImplicitValuePresentation, syncWithServerMetadata, toCamel, toCapitalize, toKebab, toPascal, toSentenceCase, toSnake, toTitleCase, translateResourceAvailabilityReason, translateResourceDiscoveryText, translateUnavailableWorkflowMessage, trim, uniqueAsyncValidator, urlValidator, withMessage, withPraxisHttpLoading };
27856
+ export { API_CONFIG_STORAGE_OPTIONS, API_URL, ASYNC_CONFIG_STORAGE, AllowedFileTypes, AnalyticsPresentationResolver, AnalyticsSchemaContractService, AnalyticsStatsRequestBuilderService, ApiConfigStorage, ApiEndpoint, BUILTIN_PAGE_LAYOUT_PRESETS, BUILTIN_PAGE_THEME_PRESETS, BUILTIN_SHELL_PRESETS, CONFIG_STORAGE, CONNECTION_STORAGE, ComponentKeyService, ComponentMetadataRegistry, CompositionRuntimeFacade, ConsoleLoggerSink, CrudOperationResolutionService, DEFAULT_FIELD_SELECTOR_CONTROL_TYPE_MAP, DEFAULT_JSON_LOGIC_OPERATORS, DEFAULT_TABLE_CONFIG, DYNAMIC_PAGE_AI_CAPABILITIES, DYNAMIC_PAGE_COMPONENT_CONTEXT_PACK, DYNAMIC_PAGE_CONFIG_EDITOR, DYNAMIC_PAGE_SHELL_EDITOR, DefaultLoadingRenderer, DeferredAsyncConfigStorage, DynamicFormService, DynamicWidgetLoaderDirective, DynamicWidgetPageComponent, EDITORIAL_ALLOWED_CONTENT_FORMATS, EDITORIAL_COMPLIANCE_PRESETS, EDITORIAL_EXTERNAL_LINK_REL, EDITORIAL_FORM_TEMPLATE_CATALOG, EDITORIAL_HTML_ENABLED, EDITORIAL_MARKDOWN_IMAGES_ENABLED, EDITORIAL_SOLUTION_CATALOG, EDITORIAL_SOLUTION_PRESETS, EDITORIAL_THEME_PRESETS, EDITORIAL_WIDGET_CONVENTION_INPUTS, EDITORIAL_WIDGET_TAG, EMPLOYEE_ONBOARDING_EDITORIAL_SOLUTION, EMPLOYEE_ONBOARDING_EDITORIAL_TEMPLATE, EMPLOYEE_ONBOARDING_GUIDED_EDITORIAL_SOLUTION, EMPLOYEE_ONBOARDING_GUIDED_EDITORIAL_TEMPLATE, EVENT_REGISTRATION_EDITORIAL_SOLUTION, EVENT_REGISTRATION_EDITORIAL_TEMPLATE, EmptyStateCardComponent, ErrorMessageService, FIELD_METADATA_CAPABILITIES, FIELD_SELECTOR_REGISTRY_BASE, FIELD_SELECTOR_REGISTRY_DISABLE_DEFAULTS, FIELD_SELECTOR_REGISTRY_OVERRIDES, FORM_HOOKS, FORM_HOOKS_PRESETS, FORM_HOOKS_WHITELIST, FORM_HOOK_RESOLVERS, FieldControlType, FieldDataType, FieldSelectorRegistry, FormHooksRegistry, GLOBAL_ACTION_CATALOG$1 as GLOBAL_ACTION_CATALOG, GLOBAL_ACTION_HANDLERS, GLOBAL_ACTION_CATALOG as GLOBAL_ACTION_SPEC_CATALOG, GLOBAL_ACTION_UI_SCHEMAS, GLOBAL_ANALYTICS_SERVICE, GLOBAL_API_CLIENT, GLOBAL_CONFIG, GLOBAL_DIALOG_SERVICE, GLOBAL_ROUTE_GUARD_RESOLVER, GLOBAL_SURFACE_SERVICE, GLOBAL_TOAST_SERVICE, GenericCrudService, GlobalActionService, GlobalConfigService, INLINE_FILTER_ALIAS_TOKENS, INLINE_FILTER_CONTROL_TYPES, INLINE_FILTER_CONTROL_TYPE_SET, INLINE_FILTER_CONTROL_TYPE_VALUES, INLINE_FILTER_TOKEN_TO_BASE_CONTROL_TYPE, INLINE_FILTER_TOKEN_TO_CONTROL_TYPE, IconPickerService, IconPosition, IconSize, LOGGER_LEVEL_BY_ENV, LOGGER_LEVEL_PRIORITY, LoadingOrchestrator, LocalConnectionStorage, LocalStorageAsyncAdapter, LocalStorageCacheAdapter, LocalStorageConfigService, LoggerService, LoggerThrottleTracker, LoggerWarnOnceTracker, MemoryCacheAdapter, NumericFormat, OVERLAY_DECIDER_DEBUG, OVERLAY_DECISION_MATRIX, ObservabilityDashboardService, OverlayDeciderService, PRAXIS_CORPORATE_SENSITIVE_KEYS, PRAXIS_DEFAULT_OBSERVABILITY_ALERT_RULES, PRAXIS_DYNAMIC_PAGE_COMPONENT_METADATA, PRAXIS_FOOTER_LINKS_METADATA, PRAXIS_GLOBAL_ACTION_CATALOG, PRAXIS_GLOBAL_CONFIG_BOOTSTRAP_OPTIONS, PRAXIS_GLOBAL_CONFIG_BOOTSTRAP_READY, PRAXIS_GLOBAL_CONFIG_TENANT_RESOLVER, PRAXIS_HERO_BANNER_METADATA, PRAXIS_I18N_CONFIG, PRAXIS_I18N_TRANSLATOR, PRAXIS_JSON_LOGIC_OPERATORS, PRAXIS_LAYER_SCALE_DEFAULTS, PRAXIS_LAYER_SCALE_VARS, PRAXIS_LEGAL_NOTICE_METADATA, PRAXIS_LOADING_CTX, PRAXIS_LOADING_RENDERER, PRAXIS_LOGGER_CONFIG, PRAXIS_LOGGER_SINKS, PRAXIS_OBSERVABILITY_DASHBOARD_OPTIONS, PRAXIS_RICH_TEXT_BLOCK_METADATA, PRAXIS_TELEMETRY_TRANSPORT, PRAXIS_USER_CONTEXT_SUMMARY_METADATA, PRIVACY_CONSENT_EDITORIAL_SOLUTION, PRIVACY_CONSENT_EDITORIAL_TEMPLATE, PraxisCore, PraxisFooterLinksComponent, PraxisGlobalErrorHandler, PraxisHeroBannerComponent, PraxisI18nService, PraxisIconDirective, PraxisIconPickerComponent, PraxisJsonLogicError, PraxisJsonLogicService, PraxisLayerScaleStyleService, PraxisLegalNoticeComponent, PraxisLoadingInterceptor, PraxisRichTextBlockComponent, PraxisSurfaceHostComponent, PraxisUserContextSummaryComponent, RESOURCE_DISCOVERY_I18N_CONFIG, RESOURCE_DISCOVERY_I18N_NAMESPACE, RULE_PROPERTY_SCHEMA, RemoteConfigStorage, ResourceActionOpenAdapterService, ResourceDiscoveryService, ResourceQuickConnectComponent, ResourceSurfaceOpenAdapterService, SCHEMA_VIEWER_CONTEXT, SETTINGS_PANEL_BRIDGE, SETTINGS_PANEL_DATA, STEPPER_CONFIG_EDITOR, SURFACE_DRAWER_BRIDGE, SURFACE_OPEN_I18N_CONFIG, SURFACE_OPEN_I18N_NAMESPACE, SURFACE_OPEN_PRESETS, SchemaMetadataClient, SchemaNormalizerService, SchemaViewerComponent, SurfaceBindingRuntimeService, SurfaceOpenActionEditorComponent, TABLE_CONFIG_EDITOR, TableConfigService, TelemetryLoggerSink, TelemetryService, ValidationPattern, WidgetPageStateRuntimeService, WidgetShellComponent, applyLocalCustomizations$2 as applyLocalCustomizations, applyLocalCustomizations$1 as applyLocalFormCustomizations, buildAngularValidators, buildApiUrl, buildBaseColumnFromDef, buildBaseFormField, buildFormConfigFromEditorialTemplate, buildHeaders, buildPageKey, buildPraxisLayerScaleCss, buildSchemaId, buildValidatorsFromValidatorOptions, cancelIfCpfInvalidHook, clampRange, cloneTableConfig, cnpjAlphaValidator, collapseWhitespace, composeHeadersWithVersion, conditionalAsyncValidator, convertFormLayoutToConfig, createCorporateLoggerConfig, createCorporateObservabilityOptions, createCpfCnpjValidator, createDefaultFormConfig, createDefaultTableConfig, createEmptyFormConfig, createEmptyRichContentDocument, createPersistedPage, customAsyncValidatorFn, customValidatorFn, debounceAsyncValidator, deepMerge, ensureIds, ensureNoConflictsHookFactory, ensurePageIds, extractNormalizedError, fetchWithETag, fileTypeValidator, fillUndefined, generateId, getDefaultFormHints, getEditorialCompliancePresetById, getEditorialFormTemplateById, getEditorialFormTemplateCatalog, getEditorialSolutionById, getEditorialSolutionCatalog, getEditorialSolutionPresetById, getEditorialThemePresetById, getEssentialConfig, getFieldMetadataCapabilities, getGlobalActionCatalog, getGlobalActionUiSchema, getReferencedFieldMetadata, getTextTransformer, interpolatePraxisTranslation, isAllowedEditorialContentFormat, isAllowedEditorialHref, isCssTextTransform, isEditorialComponentMeta, isInlineFilterControlType, isRangeValidForFilter, isTableConfigV2, isValidFormConfig, isValidTableConfig, legacyCnpjValidator, legacyCpfValidator, logOnErrorHook, mapFieldDefinitionToMetadata, mapFieldDefinitionsToMetadata, matchFieldValidator, maxFileSizeValidator, mergeFieldMetadata, mergePraxisI18nConfigs, mergeTableConfigs, migrateFormLayoutRule, migrateLegacyCompositionLink, migrateLegacyCompositionLinks, minWordsValidator, normalizeControlTypeKey, normalizeControlTypeToken, normalizeEditorialLink, normalizeEnd, normalizeFieldConstraints, normalizeFormConfig, normalizeFormMetadata, normalizePath, normalizePraxisDataQueryContext, normalizeResourceAvailabilityReasonCode, normalizeStart, normalizeUnknownError, notifySuccessHook, parseJsonResponseOrEmpty, praxisLoadingInterceptorFn, prefillFromContextHook, provideDefaultFormHooks, provideFieldSelectorRegistryBase, provideFieldSelectorRegistryOverride, provideFieldSelectorRegistryRuntime, provideFormHookPresets, provideFormHooks, provideGlobalActionCatalog, provideGlobalActionHandler, provideGlobalConfig, provideGlobalConfigReady, provideGlobalConfigSeed, provideGlobalConfigTenant, provideHookResolvers, provideHookWhitelist, provideOverlayDecisionMatrix, providePraxisAnalyticsGlobalActions, providePraxisDynamicPageMetadata, providePraxisFooterLinksMetadata, providePraxisGlobalActionCatalog, providePraxisGlobalActions, providePraxisGlobalConfigBootstrap, providePraxisHeroBannerMetadata, providePraxisHttpLoading, providePraxisI18n, providePraxisI18nConfig, providePraxisI18nTranslator, providePraxisIconDefaults, providePraxisJsonLogicOperator, providePraxisJsonLogicOperatorOverride, providePraxisLegalNoticeMetadata, providePraxisLoadingDefaults, providePraxisLogging, providePraxisRichTextBlockMetadata, providePraxisToastGlobalActions, providePraxisUserContextSummaryMetadata, provideRemoteGlobalConfig, reconcileFilterConfig, reconcileFormConfig, reconcileTableConfig, removeDiacritics, reportTelemetryHookFactory, requiredCheckedValidator, resolveBuiltinPresets, resolveControlTypeAlias, resolveDefaultValuePresentationFormat, resolveHidden, resolveInlineFilterControlType, resolveInlineFilterControlTypeToBaseControlType, resolveLoggerConfig, resolveObservabilityOptions, resolveOffset, resolveOrder, resolvePraxisFilterCriteria, resolveResourceAvailabilityReasonKey, resolveSpan, resolveValuePresentation, resolveValuePresentationLocale, slugify, stripMasksHook, supportsImplicitValuePresentation, syncWithServerMetadata, toCamel, toCapitalize, toKebab, toPascal, toSentenceCase, toSnake, toTitleCase, translateResourceAvailabilityReason, translateResourceDiscoveryText, translateUnavailableWorkflowMessage, trim, uniqueAsyncValidator, urlValidator, withMessage, withPraxisHttpLoading };