@praxisui/core 6.0.0-beta.0 → 8.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Component, InjectionToken, Injectable, inject, Inject, Optional, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, ErrorHandler, APP_INITIALIZER, 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, 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';
@@ -10,12 +10,12 @@ import { Router, ActivatedRoute } from '@angular/router';
10
10
  import * as i1$1 from '@angular/forms';
11
11
  import { Validators, FormGroup, FormControl, FormsModule } from '@angular/forms';
12
12
  import { MatSnackBar } from '@angular/material/snack-bar';
13
+ import * as i3$1 from '@angular/material/icon';
14
+ import { MatIconRegistry, MatIconModule } from '@angular/material/icon';
13
15
  import * as i2 from '@angular/material/button';
14
16
  import { MatButtonModule } from '@angular/material/button';
15
17
  import * as i3 from '@angular/material/form-field';
16
18
  import { MatFormFieldModule } from '@angular/material/form-field';
17
- import * as i3$1 from '@angular/material/icon';
18
- import { MatIconModule } from '@angular/material/icon';
19
19
  import * as i5 from '@angular/material/input';
20
20
  import { MatInputModule } from '@angular/material/input';
21
21
  import * as i6 from '@angular/material/select';
@@ -3886,6 +3886,14 @@ function createDefaultTableConfig() {
3886
3886
  'stack',
3887
3887
  'tabs',
3888
3888
  'tab',
3889
+ 'text',
3890
+ 'icon',
3891
+ 'image',
3892
+ 'badge',
3893
+ 'avatar',
3894
+ 'metric',
3895
+ 'progress',
3896
+ 'compose',
3889
3897
  'card',
3890
3898
  'value',
3891
3899
  'action',
@@ -5655,6 +5663,16 @@ function providePraxisJsonLogicOperator(definition) {
5655
5663
  useValue: definition,
5656
5664
  };
5657
5665
  }
5666
+ function providePraxisJsonLogicOperatorOverride(definition) {
5667
+ return {
5668
+ provide: PRAXIS_JSON_LOGIC_OPERATORS,
5669
+ multi: true,
5670
+ useValue: {
5671
+ ...definition,
5672
+ override: true,
5673
+ },
5674
+ };
5675
+ }
5658
5676
 
5659
5677
  class PraxisJsonLogicError extends Error {
5660
5678
  code;
@@ -5667,8 +5685,11 @@ class PraxisJsonLogicError extends Error {
5667
5685
  class PraxisJsonLogicService {
5668
5686
  customOperators = new Map();
5669
5687
  constructor(operatorDefinitions) {
5670
- for (const definition of operatorDefinitions ?? DEFAULT_JSON_LOGIC_OPERATORS) {
5671
- this.customOperators.set(definition.operator, definition);
5688
+ for (const definition of DEFAULT_JSON_LOGIC_OPERATORS) {
5689
+ this.registerCustomOperator(definition, 'praxis');
5690
+ }
5691
+ for (const definition of operatorDefinitions ?? []) {
5692
+ this.registerCustomOperator(definition, 'host', definition.override === true);
5672
5693
  }
5673
5694
  }
5674
5695
  evaluate(expression, data, options) {
@@ -5715,6 +5736,38 @@ class PraxisJsonLogicService {
5715
5736
  truthy(value) {
5716
5737
  return this.isTruthy(value);
5717
5738
  }
5739
+ listOperatorDescriptors() {
5740
+ return [
5741
+ ...BUILTIN_JSON_LOGIC_OPERATOR_DESCRIPTORS,
5742
+ ...Array.from(this.customOperators.values()).map((definition) => this.toOperatorDescriptor(definition)),
5743
+ ];
5744
+ }
5745
+ getOperatorDescriptor(operator) {
5746
+ const native = BUILTIN_JSON_LOGIC_OPERATOR_DESCRIPTORS.find((item) => item.operator === operator);
5747
+ if (native) {
5748
+ return native;
5749
+ }
5750
+ const custom = this.customOperators.get(operator);
5751
+ return custom ? this.toOperatorDescriptor(custom) : undefined;
5752
+ }
5753
+ registerCustomOperator(definition, source, allowOverride = false) {
5754
+ const operator = definition.operator;
5755
+ if (BUILTIN_JSON_LOGIC_OPERATORS.includes(operator)) {
5756
+ throw new PraxisJsonLogicError('RULE_OPERATOR_CONFLICT', `JSON Logic operator "${operator}" is native and cannot be registered as a custom operator.`);
5757
+ }
5758
+ const existing = this.customOperators.get(operator);
5759
+ if (existing && !allowOverride) {
5760
+ throw new PraxisJsonLogicError('RULE_OPERATOR_CONFLICT', `JSON Logic operator "${operator}" is already registered by ${existing.source}. Use providePraxisJsonLogicOperatorOverride for an explicit override.`);
5761
+ }
5762
+ this.customOperators.set(operator, {
5763
+ ...definition,
5764
+ source,
5765
+ });
5766
+ }
5767
+ toOperatorDescriptor(definition) {
5768
+ const { evaluate: _evaluate, override: _override, ...descriptor } = definition;
5769
+ return descriptor;
5770
+ }
5718
5771
  createContext(data, options) {
5719
5772
  return {
5720
5773
  data,
@@ -5773,6 +5826,27 @@ class PraxisJsonLogicService {
5773
5826
  if (operator === 'substr') {
5774
5827
  return this.evaluateSubstr(rawArgs, context);
5775
5828
  }
5829
+ if (operator === 'merge') {
5830
+ return this.evaluateMerge(rawArgs, context);
5831
+ }
5832
+ if (operator === 'map') {
5833
+ return this.evaluateMap(rawArgs, context);
5834
+ }
5835
+ if (operator === 'filter') {
5836
+ return this.evaluateFilter(rawArgs, context);
5837
+ }
5838
+ if (operator === 'reduce') {
5839
+ return this.evaluateReduce(rawArgs, context);
5840
+ }
5841
+ if (operator === 'all') {
5842
+ return this.evaluateAll(rawArgs, context);
5843
+ }
5844
+ if (operator === 'some') {
5845
+ return this.evaluateSome(rawArgs, context);
5846
+ }
5847
+ if (operator === 'none') {
5848
+ return this.evaluateNone(rawArgs, context);
5849
+ }
5776
5850
  const custom = this.customOperators.get(operator);
5777
5851
  if (!custom) {
5778
5852
  throw new PraxisJsonLogicError('RULE_OPERATOR_UNKNOWN', `Unsupported JSON Logic operator: ${operator}`);
@@ -5931,6 +6005,82 @@ class PraxisJsonLogicService {
5931
6005
  }
5932
6006
  return value.slice(normalizedStart, normalizedStart + length);
5933
6007
  }
6008
+ evaluateMerge(rawArgs, context) {
6009
+ const args = this.toArgumentArray(rawArgs).map((arg) => this.evaluateValue(arg, context));
6010
+ const result = [];
6011
+ for (const value of args) {
6012
+ if (Array.isArray(value)) {
6013
+ result.push(...value);
6014
+ }
6015
+ else {
6016
+ result.push(value);
6017
+ }
6018
+ }
6019
+ return result;
6020
+ }
6021
+ evaluateMap(rawArgs, context) {
6022
+ const [sourceExpression, mapExpression] = this.requireHigherOrderArgs('map', rawArgs, 2, 2);
6023
+ const source = this.evaluateValue(sourceExpression, context);
6024
+ this.assertArrayOperand('map', source);
6025
+ return source.map((item) => this.evaluateValue(mapExpression, this.createChildContext(context, item)));
6026
+ }
6027
+ evaluateFilter(rawArgs, context) {
6028
+ const [sourceExpression, predicateExpression] = this.requireHigherOrderArgs('filter', rawArgs, 2, 2);
6029
+ const source = this.evaluateValue(sourceExpression, context);
6030
+ this.assertArrayOperand('filter', source);
6031
+ return source.filter((item) => this.isTruthy(this.evaluateValue(predicateExpression, this.createChildContext(context, item))));
6032
+ }
6033
+ evaluateReduce(rawArgs, context) {
6034
+ const [sourceExpression, reducerExpression, initialExpression] = this.requireHigherOrderArgs('reduce', rawArgs, 2, 3);
6035
+ const source = this.evaluateValue(sourceExpression, context);
6036
+ this.assertArrayOperand('reduce', source);
6037
+ let accumulator = initialExpression === undefined
6038
+ ? null
6039
+ : this.evaluateValue(initialExpression, context);
6040
+ for (const current of source) {
6041
+ accumulator = this.evaluateValue(reducerExpression, this.createChildContext(context, {
6042
+ current,
6043
+ accumulator,
6044
+ }));
6045
+ }
6046
+ return accumulator;
6047
+ }
6048
+ evaluateAll(rawArgs, context) {
6049
+ const [sourceExpression, predicateExpression] = this.requireHigherOrderArgs('all', rawArgs, 2, 2);
6050
+ const source = this.evaluateValue(sourceExpression, context);
6051
+ this.assertArrayOperand('all', source);
6052
+ if (!source.length) {
6053
+ return false;
6054
+ }
6055
+ return source.every((item) => this.isTruthy(this.evaluateValue(predicateExpression, this.createChildContext(context, item))));
6056
+ }
6057
+ evaluateSome(rawArgs, context) {
6058
+ const [sourceExpression, predicateExpression] = this.requireHigherOrderArgs('some', rawArgs, 2, 2);
6059
+ const source = this.evaluateValue(sourceExpression, context);
6060
+ this.assertArrayOperand('some', source);
6061
+ return source.some((item) => this.isTruthy(this.evaluateValue(predicateExpression, this.createChildContext(context, item))));
6062
+ }
6063
+ evaluateNone(rawArgs, context) {
6064
+ const [sourceExpression, predicateExpression] = this.requireHigherOrderArgs('none', rawArgs, 2, 2);
6065
+ const source = this.evaluateValue(sourceExpression, context);
6066
+ this.assertArrayOperand('none', source);
6067
+ return !source.some((item) => this.isTruthy(this.evaluateValue(predicateExpression, this.createChildContext(context, item))));
6068
+ }
6069
+ requireHigherOrderArgs(operator, rawArgs, min, max) {
6070
+ const args = this.toArgumentArray(rawArgs);
6071
+ return this.requireArgs(operator, args, min, max);
6072
+ }
6073
+ assertArrayOperand(operator, value) {
6074
+ if (!Array.isArray(value)) {
6075
+ throw new PraxisJsonLogicError('RULE_ARGUMENT_TYPE_INVALID', `Operator ${operator} requires an array as the first argument.`);
6076
+ }
6077
+ }
6078
+ createChildContext(context, data) {
6079
+ return {
6080
+ ...context,
6081
+ data: data,
6082
+ };
6083
+ }
5934
6084
  evaluateArgs(operator, rawArgs, context, min, max) {
5935
6085
  const args = this.toArgumentArray(rawArgs).map((arg) => this.evaluateValue(arg, context));
5936
6086
  return this.requireArgs(operator, args, min, max);
@@ -6151,6 +6301,16 @@ class PraxisJsonLogicService {
6151
6301
  return { min: 1 };
6152
6302
  case 'substr':
6153
6303
  return { min: 2, max: 3 };
6304
+ case 'merge':
6305
+ return { min: 1 };
6306
+ case 'map':
6307
+ case 'filter':
6308
+ case 'all':
6309
+ case 'some':
6310
+ case 'none':
6311
+ return { min: 2, max: 2 };
6312
+ case 'reduce':
6313
+ return { min: 2, max: 3 };
6154
6314
  case '+':
6155
6315
  case '*':
6156
6316
  case 'min':
@@ -6196,10 +6356,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
6196
6356
  const DEFAULT_JSON_LOGIC_OPERATORS = [
6197
6357
  {
6198
6358
  operator: 'contains',
6359
+ namespace: 'praxis',
6199
6360
  minArgs: 2,
6200
6361
  maxArgs: 2,
6362
+ returnType: 'boolean',
6363
+ purity: 'pure',
6201
6364
  evaluate: (args, _context, helpers) => {
6202
6365
  const [container, candidate] = helpers.requireArgs('contains', args, 2, 2);
6366
+ if (container === undefined || container === null) {
6367
+ return false;
6368
+ }
6203
6369
  if (typeof container === 'string' && typeof candidate === 'string') {
6204
6370
  return container.includes(candidate);
6205
6371
  }
@@ -6211,10 +6377,16 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6211
6377
  },
6212
6378
  {
6213
6379
  operator: 'startsWith',
6380
+ namespace: 'praxis',
6214
6381
  minArgs: 2,
6215
6382
  maxArgs: 2,
6383
+ returnType: 'boolean',
6384
+ purity: 'pure',
6216
6385
  evaluate: (args, _context, helpers) => {
6217
6386
  const [value, prefix] = helpers.requireArgs('startsWith', args, 2, 2);
6387
+ if (value === undefined || value === null) {
6388
+ return false;
6389
+ }
6218
6390
  if (typeof value !== 'string' || typeof prefix !== 'string') {
6219
6391
  throw new PraxisJsonLogicError('RULE_ARGUMENT_TYPE_INVALID', '`startsWith` requires string arguments.');
6220
6392
  }
@@ -6223,10 +6395,16 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6223
6395
  },
6224
6396
  {
6225
6397
  operator: 'endsWith',
6398
+ namespace: 'praxis',
6226
6399
  minArgs: 2,
6227
6400
  maxArgs: 2,
6401
+ returnType: 'boolean',
6402
+ purity: 'pure',
6228
6403
  evaluate: (args, _context, helpers) => {
6229
6404
  const [value, suffix] = helpers.requireArgs('endsWith', args, 2, 2);
6405
+ if (value === undefined || value === null) {
6406
+ return false;
6407
+ }
6230
6408
  if (typeof value !== 'string' || typeof suffix !== 'string') {
6231
6409
  throw new PraxisJsonLogicError('RULE_ARGUMENT_TYPE_INVALID', '`endsWith` requires string arguments.');
6232
6410
  }
@@ -6235,10 +6413,16 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6235
6413
  },
6236
6414
  {
6237
6415
  operator: 'matches',
6416
+ namespace: 'praxis',
6238
6417
  minArgs: 2,
6239
6418
  maxArgs: 2,
6419
+ returnType: 'boolean',
6420
+ purity: 'pure',
6240
6421
  evaluate: (args, _context, helpers) => {
6241
6422
  const [value, pattern] = helpers.requireArgs('matches', args, 2, 2);
6423
+ if (value === undefined || value === null) {
6424
+ return false;
6425
+ }
6242
6426
  if (typeof value !== 'string' || typeof pattern !== 'string') {
6243
6427
  throw new PraxisJsonLogicError('RULE_ARGUMENT_TYPE_INVALID', '`matches` requires string arguments.');
6244
6428
  }
@@ -6252,8 +6436,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6252
6436
  },
6253
6437
  {
6254
6438
  operator: 'isBlank',
6439
+ namespace: 'praxis',
6255
6440
  minArgs: 1,
6256
6441
  maxArgs: 1,
6442
+ returnType: 'boolean',
6443
+ purity: 'pure',
6257
6444
  evaluate: (args, _context, helpers) => {
6258
6445
  const [value] = helpers.requireArgs('isBlank', args, 1, 1);
6259
6446
  if (value === undefined || value === null) {
@@ -6270,8 +6457,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6270
6457
  },
6271
6458
  {
6272
6459
  operator: 'len',
6460
+ namespace: 'praxis',
6273
6461
  minArgs: 1,
6274
6462
  maxArgs: 1,
6463
+ returnType: 'number',
6464
+ purity: 'pure',
6275
6465
  evaluate: (args, _context, helpers) => {
6276
6466
  const [value] = helpers.requireArgs('len', args, 1, 1);
6277
6467
  if (value === undefined || value === null) {
@@ -6291,8 +6481,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6291
6481
  },
6292
6482
  {
6293
6483
  operator: 'round',
6484
+ namespace: 'praxis',
6294
6485
  minArgs: 1,
6295
6486
  maxArgs: 1,
6487
+ returnType: 'number',
6488
+ purity: 'pure',
6296
6489
  evaluate: (args, _context, helpers) => {
6297
6490
  const [value] = helpers.requireArgs('round', args, 1, 1);
6298
6491
  if (typeof value !== 'number' || !Number.isFinite(value)) {
@@ -6303,8 +6496,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6303
6496
  },
6304
6497
  {
6305
6498
  operator: 'ceil',
6499
+ namespace: 'praxis',
6306
6500
  minArgs: 1,
6307
6501
  maxArgs: 1,
6502
+ returnType: 'number',
6503
+ purity: 'pure',
6308
6504
  evaluate: (args, _context, helpers) => {
6309
6505
  const [value] = helpers.requireArgs('ceil', args, 1, 1);
6310
6506
  if (typeof value !== 'number' || !Number.isFinite(value)) {
@@ -6315,8 +6511,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6315
6511
  },
6316
6512
  {
6317
6513
  operator: 'floor',
6514
+ namespace: 'praxis',
6318
6515
  minArgs: 1,
6319
6516
  maxArgs: 1,
6517
+ returnType: 'number',
6518
+ purity: 'pure',
6320
6519
  evaluate: (args, _context, helpers) => {
6321
6520
  const [value] = helpers.requireArgs('floor', args, 1, 1);
6322
6521
  if (typeof value !== 'number' || !Number.isFinite(value)) {
@@ -6327,8 +6526,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6327
6526
  },
6328
6527
  {
6329
6528
  operator: 'abs',
6529
+ namespace: 'praxis',
6330
6530
  minArgs: 1,
6331
6531
  maxArgs: 1,
6532
+ returnType: 'number',
6533
+ purity: 'pure',
6332
6534
  evaluate: (args, _context, helpers) => {
6333
6535
  const [value] = helpers.requireArgs('abs', args, 1, 1);
6334
6536
  if (typeof value !== 'number' || !Number.isFinite(value)) {
@@ -6339,7 +6541,10 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6339
6541
  },
6340
6542
  {
6341
6543
  operator: 'coalesce',
6544
+ namespace: 'praxis',
6342
6545
  minArgs: 1,
6546
+ returnType: 'unknown',
6547
+ purity: 'pure',
6343
6548
  evaluate: (args, _context, helpers) => {
6344
6549
  const values = helpers.requireArgs('coalesce', args, 1);
6345
6550
  for (const value of values) {
@@ -6352,14 +6557,20 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6352
6557
  },
6353
6558
  {
6354
6559
  operator: 'now',
6560
+ namespace: 'praxis',
6355
6561
  minArgs: 0,
6356
6562
  maxArgs: 0,
6563
+ returnType: 'number',
6564
+ purity: 'contextual',
6357
6565
  evaluate: () => Date.now(),
6358
6566
  },
6359
6567
  {
6360
6568
  operator: 'date',
6569
+ namespace: 'praxis',
6361
6570
  minArgs: 1,
6362
6571
  maxArgs: 1,
6572
+ returnType: 'number',
6573
+ purity: 'pure',
6363
6574
  evaluate: (args, _context, helpers) => {
6364
6575
  const [value] = helpers.requireArgs('date', args, 1, 1);
6365
6576
  const parsed = parseTemporalValue(value);
@@ -6374,8 +6585,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6374
6585
  },
6375
6586
  {
6376
6587
  operator: 'yearsSince',
6588
+ namespace: 'praxis',
6377
6589
  minArgs: 1,
6378
6590
  maxArgs: 1,
6591
+ returnType: 'number',
6592
+ purity: 'contextual',
6379
6593
  evaluate: (args, context, helpers) => {
6380
6594
  const [value] = helpers.requireArgs('yearsSince', args, 1, 1);
6381
6595
  const parsed = parseTemporalValue(value);
@@ -6388,8 +6602,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6388
6602
  },
6389
6603
  {
6390
6604
  operator: 'monthsSince',
6605
+ namespace: 'praxis',
6391
6606
  minArgs: 1,
6392
6607
  maxArgs: 1,
6608
+ returnType: 'number',
6609
+ purity: 'contextual',
6393
6610
  evaluate: (args, context, helpers) => {
6394
6611
  const [value] = helpers.requireArgs('monthsSince', args, 1, 1);
6395
6612
  const parsed = parseTemporalValue(value);
@@ -6402,8 +6619,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6402
6619
  },
6403
6620
  {
6404
6621
  operator: 'daysSince',
6622
+ namespace: 'praxis',
6405
6623
  minArgs: 1,
6406
6624
  maxArgs: 1,
6625
+ returnType: 'number',
6626
+ purity: 'contextual',
6407
6627
  evaluate: (args, context, helpers) => {
6408
6628
  const [value] = helpers.requireArgs('daysSince', args, 1, 1);
6409
6629
  const parsed = parseTemporalValue(value);
@@ -6416,8 +6636,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6416
6636
  },
6417
6637
  {
6418
6638
  operator: 'toNumber',
6639
+ namespace: 'praxis',
6419
6640
  minArgs: 1,
6420
6641
  maxArgs: 1,
6642
+ returnType: 'number',
6643
+ purity: 'pure',
6421
6644
  evaluate: (args, _context, helpers) => {
6422
6645
  const [value] = helpers.requireArgs('toNumber', args, 1, 1);
6423
6646
  const parsed = Number(value);
@@ -6426,8 +6649,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6426
6649
  },
6427
6650
  {
6428
6651
  operator: 'stringify',
6652
+ namespace: 'praxis',
6429
6653
  minArgs: 1,
6430
6654
  maxArgs: 1,
6655
+ returnType: 'string',
6656
+ purity: 'pure',
6431
6657
  evaluate: (args, _context, helpers) => {
6432
6658
  const [value] = helpers.requireArgs('stringify', args, 1, 1);
6433
6659
  return value == null ? '' : String(value);
@@ -6435,8 +6661,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6435
6661
  },
6436
6662
  {
6437
6663
  operator: 'jsonGet',
6664
+ namespace: 'praxis',
6438
6665
  minArgs: 2,
6439
6666
  maxArgs: 2,
6667
+ returnType: 'unknown',
6668
+ purity: 'pure',
6440
6669
  evaluate: (args, _context, helpers) => {
6441
6670
  const [target, path] = helpers.requireArgs('jsonGet', args, 2, 2);
6442
6671
  if (typeof path !== 'string') {
@@ -6450,8 +6679,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6450
6679
  },
6451
6680
  {
6452
6681
  operator: 'hasKey',
6682
+ namespace: 'praxis',
6453
6683
  minArgs: 2,
6454
6684
  maxArgs: 2,
6685
+ returnType: 'boolean',
6686
+ purity: 'pure',
6455
6687
  evaluate: (args, _context, helpers) => {
6456
6688
  const [target, path] = helpers.requireArgs('hasKey', args, 2, 2);
6457
6689
  if (typeof path !== 'string') {
@@ -6465,8 +6697,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6465
6697
  },
6466
6698
  {
6467
6699
  operator: 'isToday',
6700
+ namespace: 'praxis',
6468
6701
  minArgs: 1,
6469
6702
  maxArgs: 1,
6703
+ returnType: 'boolean',
6704
+ purity: 'contextual',
6470
6705
  evaluate: (args, context, helpers) => {
6471
6706
  const [candidate] = helpers.requireArgs('isToday', args, 1, 1);
6472
6707
  const parsed = parseTemporalValue(candidate);
@@ -6478,8 +6713,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6478
6713
  },
6479
6714
  {
6480
6715
  operator: 'inLast',
6716
+ namespace: 'praxis',
6481
6717
  minArgs: 3,
6482
6718
  maxArgs: 3,
6719
+ returnType: 'boolean',
6720
+ purity: 'contextual',
6483
6721
  evaluate: (args, context, helpers) => {
6484
6722
  const [candidate, rawAmount, rawUnit] = helpers.requireArgs('inLast', args, 3, 3);
6485
6723
  const parsed = parseTemporalValue(candidate);
@@ -6496,8 +6734,11 @@ const DEFAULT_JSON_LOGIC_OPERATORS = [
6496
6734
  },
6497
6735
  {
6498
6736
  operator: 'weekdayIn',
6737
+ namespace: 'praxis',
6499
6738
  minArgs: 2,
6500
6739
  maxArgs: 2,
6740
+ returnType: 'boolean',
6741
+ purity: 'contextual',
6501
6742
  evaluate: (args, context, helpers) => {
6502
6743
  const [candidate, rawDays] = helpers.requireArgs('weekdayIn', args, 2, 2);
6503
6744
  const parsed = parseTemporalValue(candidate);
@@ -6541,6 +6782,13 @@ const BUILTIN_JSON_LOGIC_OPERATORS = [
6541
6782
  'in',
6542
6783
  'cat',
6543
6784
  'substr',
6785
+ 'merge',
6786
+ 'map',
6787
+ 'filter',
6788
+ 'reduce',
6789
+ 'all',
6790
+ 'some',
6791
+ 'none',
6544
6792
  '+',
6545
6793
  '-',
6546
6794
  '*',
@@ -6549,6 +6797,39 @@ const BUILTIN_JSON_LOGIC_OPERATORS = [
6549
6797
  'min',
6550
6798
  'max',
6551
6799
  ];
6800
+ const BUILTIN_JSON_LOGIC_OPERATOR_DESCRIPTORS = [
6801
+ { operator: 'var', source: 'native', minArgs: 1, maxArgs: 2, returnType: 'unknown', purity: 'pure' },
6802
+ { operator: '==', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'boolean', purity: 'pure' },
6803
+ { operator: '===', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'boolean', purity: 'pure' },
6804
+ { operator: '!=', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'boolean', purity: 'pure' },
6805
+ { operator: '!==', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'boolean', purity: 'pure' },
6806
+ { operator: '>', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'boolean', purity: 'pure' },
6807
+ { operator: '>=', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'boolean', purity: 'pure' },
6808
+ { operator: '<', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'boolean', purity: 'pure' },
6809
+ { operator: '<=', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'boolean', purity: 'pure' },
6810
+ { operator: '!', source: 'native', minArgs: 1, maxArgs: 1, returnType: 'boolean', purity: 'pure' },
6811
+ { operator: '!!', source: 'native', minArgs: 1, maxArgs: 1, returnType: 'boolean', purity: 'pure' },
6812
+ { operator: 'and', source: 'native', minArgs: 1, returnType: 'unknown', purity: 'pure' },
6813
+ { operator: 'or', source: 'native', minArgs: 1, returnType: 'unknown', purity: 'pure' },
6814
+ { operator: 'if', source: 'native', minArgs: 2, returnType: 'unknown', purity: 'pure' },
6815
+ { operator: 'in', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'boolean', purity: 'pure' },
6816
+ { operator: 'cat', source: 'native', minArgs: 1, returnType: 'string', purity: 'pure' },
6817
+ { operator: 'substr', source: 'native', minArgs: 2, maxArgs: 3, returnType: 'string', purity: 'pure' },
6818
+ { operator: 'merge', source: 'native', minArgs: 1, returnType: 'array', purity: 'pure' },
6819
+ { operator: 'map', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'array', purity: 'pure' },
6820
+ { operator: 'filter', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'array', purity: 'pure' },
6821
+ { operator: 'reduce', source: 'native', minArgs: 2, maxArgs: 3, returnType: 'unknown', purity: 'pure' },
6822
+ { operator: 'all', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'boolean', purity: 'pure' },
6823
+ { operator: 'some', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'boolean', purity: 'pure' },
6824
+ { operator: 'none', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'boolean', purity: 'pure' },
6825
+ { operator: '+', source: 'native', minArgs: 1, returnType: 'number', purity: 'pure' },
6826
+ { operator: '-', source: 'native', minArgs: 1, returnType: 'number', purity: 'pure' },
6827
+ { operator: '*', source: 'native', minArgs: 1, returnType: 'number', purity: 'pure' },
6828
+ { operator: '/', source: 'native', minArgs: 2, returnType: 'number', purity: 'pure' },
6829
+ { operator: '%', source: 'native', minArgs: 2, maxArgs: 2, returnType: 'number', purity: 'pure' },
6830
+ { operator: 'min', source: 'native', minArgs: 1, returnType: 'number', purity: 'pure' },
6831
+ { operator: 'max', source: 'native', minArgs: 1, returnType: 'number', purity: 'pure' },
6832
+ ];
6552
6833
  function isComparisonOperator(operator) {
6553
6834
  return ['==', '===', '!=', '!==', '>', '>=', '<', '<='].includes(operator);
6554
6835
  }
@@ -8737,6 +9018,328 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
8737
9018
  args: [{ providedIn: 'any' }]
8738
9019
  }] });
8739
9020
 
9021
+ class CrudOperationResolutionService {
9022
+ discovery = inject(ResourceDiscoveryService);
9023
+ resolve(request) {
9024
+ const operation = request.operation;
9025
+ const metadataResourcePath = this.normalizeResourcePath(request.resourcePath);
9026
+ if (!metadataResourcePath) {
9027
+ throw new Error('CrudOperationResolutionService requires resourcePath.');
9028
+ }
9029
+ const resourcePath = this.resolveCanonicalResourcePath(request, metadataResourcePath);
9030
+ const diagnostics = [];
9031
+ const resolutionOptions = this.toDiscoveryOptions(request);
9032
+ if (this.hasExplicitContract(request)) {
9033
+ return this.buildExplicitResolution(request, resourcePath, diagnostics, resolutionOptions);
9034
+ }
9035
+ const capabilities = request.capabilities ?? null;
9036
+ const operationCapability = capabilities?.operations?.[operation] ??
9037
+ this.buildCapabilityFromCanonicalFlags(capabilities, operation);
9038
+ const scope = this.resolveScope(operationCapability, operation);
9039
+ const preferredMethod = this.resolvePreferredMethod(operationCapability, operation);
9040
+ const matchingSurface = this.findSurface(request.surfaces ?? capabilities?.surfaces ?? [], operation);
9041
+ if (matchingSurface) {
9042
+ return this.buildSurfaceResolution({
9043
+ operation,
9044
+ resourcePath,
9045
+ resourceId: request.resourceId ?? null,
9046
+ diagnostics,
9047
+ resolutionOptions,
9048
+ capability: operationCapability,
9049
+ surface: matchingSurface,
9050
+ });
9051
+ }
9052
+ const linkResolution = this.resolveLink(operation, request.links, resolutionOptions, operationCapability);
9053
+ if (linkResolution) {
9054
+ return {
9055
+ operation,
9056
+ source: 'link',
9057
+ resourcePath,
9058
+ resourceId: request.resourceId ?? null,
9059
+ scope,
9060
+ supported: operationCapability?.supported ?? true,
9061
+ visible: this.isAvailable(operationCapability),
9062
+ enabled: this.isAvailable(operationCapability),
9063
+ availability: operationCapability?.availability ?? null,
9064
+ schemaUrl: this.resolveCanonicalSchemaUrl(operation, resourcePath, preferredMethod, resolutionOptions),
9065
+ responseSchemaUrl: operation === 'view'
9066
+ ? this.resolveCanonicalSchemaUrl('view', resourcePath, preferredMethod, resolutionOptions)
9067
+ : null,
9068
+ submitUrl: linkResolution.href,
9069
+ submitMethod: operation === 'view'
9070
+ ? preferredMethod
9071
+ : (linkResolution.method ?? preferredMethod)?.toLowerCase() ?? null,
9072
+ diagnostics,
9073
+ };
9074
+ }
9075
+ return this.buildConventionResolution({
9076
+ operation,
9077
+ resourcePath,
9078
+ resourceId: request.resourceId ?? null,
9079
+ diagnostics,
9080
+ resolutionOptions,
9081
+ capability: operationCapability,
9082
+ preferredMethod,
9083
+ scope,
9084
+ });
9085
+ }
9086
+ buildExplicitResolution(request, resourcePath, diagnostics, options) {
9087
+ return {
9088
+ operation: request.operation,
9089
+ source: 'explicit',
9090
+ resourcePath,
9091
+ resourceId: request.resourceId ?? null,
9092
+ scope: this.defaultScope(request.operation),
9093
+ supported: true,
9094
+ visible: true,
9095
+ enabled: true,
9096
+ availability: { allowed: true, metadata: { source: 'explicit' } },
9097
+ schemaUrl: request.explicit?.schemaUrl
9098
+ ? this.discovery.resolveHref(request.explicit.schemaUrl, options)
9099
+ : null,
9100
+ responseSchemaUrl: request.explicit?.responseSchemaUrl
9101
+ ? this.discovery.resolveHref(request.explicit.responseSchemaUrl, options)
9102
+ : null,
9103
+ submitUrl: request.explicit?.submitUrl
9104
+ ? this.discovery.resolveHref(request.explicit.submitUrl, options)
9105
+ : null,
9106
+ submitMethod: request.explicit?.submitMethod
9107
+ ? String(request.explicit.submitMethod).trim().toLowerCase()
9108
+ : null,
9109
+ diagnostics,
9110
+ };
9111
+ }
9112
+ buildSurfaceResolution(params) {
9113
+ const { operation, resourcePath, resourceId, diagnostics, resolutionOptions, capability, surface } = params;
9114
+ const isWritable = this.isWritableSurface(surface.kind);
9115
+ return {
9116
+ operation,
9117
+ source: capability ? 'capability' : 'surface',
9118
+ resourcePath,
9119
+ resourceId,
9120
+ scope: surface.scope,
9121
+ supported: capability?.supported ?? true,
9122
+ visible: this.isAvailable(capability, surface),
9123
+ enabled: this.isAvailable(capability, surface),
9124
+ availability: surface.availability ?? capability?.availability ?? null,
9125
+ schemaUrl: surface.schemaUrl
9126
+ ? this.discovery.resolveHref(surface.schemaUrl, resolutionOptions)
9127
+ : this.resolveCanonicalSchemaUrl(operation, resourcePath, this.resolvePreferredMethod(capability, operation), resolutionOptions),
9128
+ responseSchemaUrl: operation === 'view' && surface.schemaUrl
9129
+ ? this.discovery.resolveHref(surface.schemaUrl, resolutionOptions)
9130
+ : null,
9131
+ submitUrl: isWritable
9132
+ ? this.discovery.resolveHref(this.resolveActualOperationPath(surface.path, resourceId, diagnostics), resolutionOptions)
9133
+ : null,
9134
+ submitMethod: isWritable ? String(surface.method || '').trim().toLowerCase() || null : null,
9135
+ diagnostics,
9136
+ };
9137
+ }
9138
+ buildConventionResolution(params) {
9139
+ const { operation, resourcePath, resourceId, diagnostics, resolutionOptions, capability, preferredMethod, scope } = params;
9140
+ const submitUrl = this.resolveConventionSubmitUrl(operation, resourcePath, resourceId, diagnostics, resolutionOptions);
9141
+ return {
9142
+ operation,
9143
+ source: 'convention',
9144
+ resourcePath,
9145
+ resourceId,
9146
+ scope,
9147
+ supported: capability?.supported ?? true,
9148
+ visible: this.isAvailable(capability),
9149
+ enabled: this.isAvailable(capability),
9150
+ availability: capability?.availability ?? null,
9151
+ schemaUrl: this.resolveCanonicalSchemaUrl(operation, resourcePath, preferredMethod, resolutionOptions),
9152
+ responseSchemaUrl: operation === 'view'
9153
+ ? this.resolveCanonicalSchemaUrl('view', resourcePath, preferredMethod, resolutionOptions)
9154
+ : null,
9155
+ submitUrl,
9156
+ submitMethod: operation === 'view' ? preferredMethod : preferredMethod?.toLowerCase() ?? null,
9157
+ diagnostics,
9158
+ };
9159
+ }
9160
+ resolveCanonicalSchemaUrl(operation, resourcePath, preferredMethod, options) {
9161
+ if (operation === 'delete') {
9162
+ return null;
9163
+ }
9164
+ const { path, method, schemaType } = this.buildCanonicalSchemaParams(operation, resourcePath, preferredMethod);
9165
+ const query = new URLSearchParams({
9166
+ path,
9167
+ operation: method.toLowerCase(),
9168
+ schemaType,
9169
+ });
9170
+ return this.discovery.resolveHref(`/schemas/filtered?${query.toString()}`, options);
9171
+ }
9172
+ buildCanonicalSchemaParams(operation, resourcePath, preferredMethod) {
9173
+ if (operation === 'create') {
9174
+ return { path: resourcePath, method: 'POST', schemaType: 'request' };
9175
+ }
9176
+ const itemPath = `${resourcePath}/{id}`;
9177
+ if (operation === 'view') {
9178
+ return { path: itemPath, method: 'GET', schemaType: 'response' };
9179
+ }
9180
+ return {
9181
+ path: itemPath,
9182
+ method: (preferredMethod || 'PUT').toUpperCase(),
9183
+ schemaType: 'request',
9184
+ };
9185
+ }
9186
+ resolveConventionSubmitUrl(operation, resourcePath, resourceId, diagnostics, options) {
9187
+ if (operation === 'view') {
9188
+ return null;
9189
+ }
9190
+ if (operation === 'create') {
9191
+ return this.discovery.resolveHref(resourcePath, options);
9192
+ }
9193
+ if (resourceId == null) {
9194
+ diagnostics.push(`Operation "${operation}" requires resourceId for canonical submit target resolution.`);
9195
+ return null;
9196
+ }
9197
+ return this.discovery.resolveHref(`${resourcePath}/${resourceId}`, options);
9198
+ }
9199
+ resolveLink(operation, links, options, capability) {
9200
+ const rel = String(capability?.preferredRel || this.operationRel(operation)).trim();
9201
+ const link = this.discovery.getLink(links, rel);
9202
+ if (!link?.href) {
9203
+ return null;
9204
+ }
9205
+ return {
9206
+ href: this.discovery.resolveHref(link.href, options),
9207
+ method: String(link.method || '').trim().toUpperCase()
9208
+ || capability?.preferredMethod?.toUpperCase()
9209
+ || this.defaultMethod(operation),
9210
+ };
9211
+ }
9212
+ buildCapabilityFromCanonicalFlags(capabilities, operation) {
9213
+ if (!capabilities?.canonicalOperations) {
9214
+ return null;
9215
+ }
9216
+ const canonicalKey = operation === 'view' ? 'byId' : operation === 'edit' ? 'update' : operation;
9217
+ if (!(canonicalKey in capabilities.canonicalOperations)) {
9218
+ return null;
9219
+ }
9220
+ return {
9221
+ id: operation,
9222
+ supported: !!capabilities.canonicalOperations[canonicalKey],
9223
+ scope: this.defaultScope(operation),
9224
+ preferredMethod: this.defaultMethod(operation),
9225
+ preferredRel: this.operationRel(operation),
9226
+ availability: { allowed: true, metadata: { source: 'canonicalOperations' } },
9227
+ };
9228
+ }
9229
+ findSurface(surfaces, operation) {
9230
+ const candidates = surfaces.filter((surface) => this.matchesOperation(surface, operation));
9231
+ if (operation === 'create') {
9232
+ return candidates.find((surface) => surface.id.toLowerCase() === 'create') ?? candidates[0] ?? null;
9233
+ }
9234
+ if (operation === 'view') {
9235
+ return candidates.find((surface) => ['detail', 'view'].includes(surface.id.toLowerCase())) ?? candidates[0] ?? null;
9236
+ }
9237
+ if (operation === 'edit') {
9238
+ return candidates.find((surface) => ['edit', 'update'].includes(surface.id.toLowerCase())) ?? candidates[0] ?? null;
9239
+ }
9240
+ return null;
9241
+ }
9242
+ matchesOperation(surface, operation) {
9243
+ if (operation === 'create') {
9244
+ return surface.scope === 'COLLECTION' && this.isWritableSurface(surface.kind);
9245
+ }
9246
+ if (operation === 'view') {
9247
+ return surface.scope === 'ITEM' && this.isReadableSurface(surface.kind);
9248
+ }
9249
+ if (operation === 'edit') {
9250
+ return surface.scope === 'ITEM' && this.isWritableSurface(surface.kind);
9251
+ }
9252
+ return false;
9253
+ }
9254
+ isReadableSurface(kind) {
9255
+ return kind === 'VIEW' || kind === 'READ_PROJECTION';
9256
+ }
9257
+ isWritableSurface(kind) {
9258
+ return kind === 'FORM' || kind === 'PARTIAL_FORM';
9259
+ }
9260
+ resolveScope(capability, operation) {
9261
+ return capability?.scope ?? this.defaultScope(operation);
9262
+ }
9263
+ resolvePreferredMethod(capability, operation) {
9264
+ return capability?.preferredMethod?.toUpperCase() ?? this.defaultMethod(operation);
9265
+ }
9266
+ resolveActualOperationPath(pathTemplate, resourceId, diagnostics) {
9267
+ if (!/\{id\}/.test(pathTemplate)) {
9268
+ return pathTemplate;
9269
+ }
9270
+ if (resourceId == null) {
9271
+ diagnostics.push(`Path "${pathTemplate}" requires resourceId to resolve the concrete target.`);
9272
+ return pathTemplate;
9273
+ }
9274
+ return pathTemplate.replace(/\{id\}/g, encodeURIComponent(String(resourceId)));
9275
+ }
9276
+ hasExplicitContract(request) {
9277
+ return !!(request.explicit?.schemaUrl ||
9278
+ request.explicit?.responseSchemaUrl ||
9279
+ request.explicit?.submitUrl ||
9280
+ request.explicit?.submitMethod);
9281
+ }
9282
+ isAvailable(capability, surface) {
9283
+ if (surface?.availability) {
9284
+ return surface.availability.allowed !== false;
9285
+ }
9286
+ if (capability?.availability) {
9287
+ return capability.availability.allowed !== false;
9288
+ }
9289
+ return capability?.supported !== false;
9290
+ }
9291
+ operationRel(operation) {
9292
+ if (operation === 'view') {
9293
+ return 'self';
9294
+ }
9295
+ return operation;
9296
+ }
9297
+ defaultScope(operation) {
9298
+ return operation === 'create' ? 'COLLECTION' : 'ITEM';
9299
+ }
9300
+ defaultMethod(operation) {
9301
+ switch (operation) {
9302
+ case 'create':
9303
+ return 'POST';
9304
+ case 'view':
9305
+ return 'GET';
9306
+ case 'edit':
9307
+ return 'PUT';
9308
+ case 'delete':
9309
+ return 'DELETE';
9310
+ }
9311
+ }
9312
+ normalizeResourcePath(resourcePath) {
9313
+ const normalized = String(resourcePath || '').trim().replace(/\/+/g, '/');
9314
+ if (!normalized) {
9315
+ return '';
9316
+ }
9317
+ return normalized.startsWith('/') ? normalized : `/${normalized}`;
9318
+ }
9319
+ resolveCanonicalResourcePath(request, fallbackResourcePath) {
9320
+ const capabilityResourcePath = this.normalizeResourcePath(request.capabilities?.resourcePath || '');
9321
+ if (capabilityResourcePath) {
9322
+ return capabilityResourcePath;
9323
+ }
9324
+ return fallbackResourcePath;
9325
+ }
9326
+ toDiscoveryOptions(request) {
9327
+ if (!request.endpointKey && !request.apiUrlEntry) {
9328
+ return undefined;
9329
+ }
9330
+ return {
9331
+ ...(request.endpointKey ? { endpointKey: request.endpointKey } : {}),
9332
+ ...(request.apiUrlEntry ? { apiUrlEntry: request.apiUrlEntry } : {}),
9333
+ };
9334
+ }
9335
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: CrudOperationResolutionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
9336
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: CrudOperationResolutionService, providedIn: 'any' });
9337
+ }
9338
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: CrudOperationResolutionService, decorators: [{
9339
+ type: Injectable,
9340
+ args: [{ providedIn: 'any' }]
9341
+ }] });
9342
+
8740
9343
  const DEFAULT_FAMILIES = [
8741
9344
  'chart',
8742
9345
  'analytic-table',
@@ -9280,6 +9883,30 @@ function providePraxisAnalyticsGlobalActions(opts = {}) {
9280
9883
  };
9281
9884
  }
9282
9885
 
9886
+ const DEFAULT_FONT_SET_CLASS = ['material-symbols-outlined', 'mat-ligature-font'];
9887
+ function normalizeDefaultFontSetClass(options) {
9888
+ const provided = options?.defaultFontSetClass?.filter((value) => typeof value === 'string' && value.trim().length);
9889
+ return provided?.length ? provided : DEFAULT_FONT_SET_CLASS;
9890
+ }
9891
+ function providePraxisIconDefaults(options) {
9892
+ const defaultFontSetClass = normalizeDefaultFontSetClass(options);
9893
+ return [
9894
+ {
9895
+ provide: APP_INITIALIZER,
9896
+ multi: true,
9897
+ deps: [MatIconRegistry],
9898
+ useFactory: (iconRegistry) => () => {
9899
+ iconRegistry.registerFontClassAlias('ms', 'material-symbols-outlined mat-ligature-font');
9900
+ iconRegistry.registerFontClassAlias('mso', 'material-symbols-outlined mat-ligature-font');
9901
+ iconRegistry.registerFontClassAlias('msr', 'material-symbols-rounded mat-ligature-font');
9902
+ iconRegistry.registerFontClassAlias('mss', 'material-symbols-sharp mat-ligature-font');
9903
+ iconRegistry.registerFontClassAlias('mi', 'material-icons mat-ligature-font');
9904
+ iconRegistry.setDefaultFontSetClass(...defaultFontSetClass);
9905
+ },
9906
+ },
9907
+ ];
9908
+ }
9909
+
9283
9910
  /**
9284
9911
  * Registers only the default visual renderer for Praxis loading.
9285
9912
  *
@@ -11498,6 +12125,14 @@ const FieldDataType = {
11498
12125
  * - Supports Material Design 3 specifications
11499
12126
  */
11500
12127
 
12128
+ function createEmptyRichContentDocument() {
12129
+ return {
12130
+ kind: 'praxis.rich-content',
12131
+ version: '1.0.0',
12132
+ nodes: [],
12133
+ };
12134
+ }
12135
+
11501
12136
  function defaultGenerateId(kind, used) {
11502
12137
  // determinístico + compacto, evitando Math.random (facilita tests/replays)
11503
12138
  let seq = 1;
@@ -11788,10 +12423,10 @@ function createDefaultFormConfig() {
11788
12423
  ],
11789
12424
  },
11790
12425
  ],
11791
- formBlocksBefore: [],
11792
- formBlocksBeforeActions: [],
12426
+ formBlocksBefore: createEmptyRichContentDocument(),
12427
+ formBlocksBeforeActions: createEmptyRichContentDocument(),
11793
12428
  formBlocksBeforeActionsPlacement: 'afterSections',
11794
- formBlocksAfter: [],
12429
+ formBlocksAfter: createEmptyRichContentDocument(),
11795
12430
  // Default mode hints (didactic tooltips)
11796
12431
  hints: getDefaultFormHints(),
11797
12432
  };
@@ -11806,10 +12441,10 @@ function isValidFormConfig(config) {
11806
12441
  function createEmptyFormConfig() {
11807
12442
  return {
11808
12443
  sections: [],
11809
- formBlocksBefore: [],
11810
- formBlocksBeforeActions: [],
12444
+ formBlocksBefore: createEmptyRichContentDocument(),
12445
+ formBlocksBeforeActions: createEmptyRichContentDocument(),
11811
12446
  formBlocksBeforeActionsPlacement: 'afterSections',
11812
- formBlocksAfter: [],
12447
+ formBlocksAfter: createEmptyRichContentDocument(),
11813
12448
  };
11814
12449
  }
11815
12450
  /**
@@ -12011,10 +12646,10 @@ function buildFormConfigFromEditorialTemplate(template, options = {}) {
12011
12646
  const overrides = options.overrides ?? {};
12012
12647
  const base = {
12013
12648
  sections: template.layout?.sections ?? [],
12014
- formBlocksBefore: template.layout?.formBlocksBefore ?? [],
12015
- formBlocksBeforeActions: template.layout?.formBlocksBeforeActions ?? [],
12649
+ formBlocksBefore: template.layout?.formBlocksBefore ?? createEmptyRichContentDocument(),
12650
+ formBlocksBeforeActions: template.layout?.formBlocksBeforeActions ?? createEmptyRichContentDocument(),
12016
12651
  formBlocksBeforeActionsPlacement: template.layout?.formBlocksBeforeActionsPlacement ?? 'afterSections',
12017
- formBlocksAfter: template.layout?.formBlocksAfter ?? [],
12652
+ formBlocksAfter: template.layout?.formBlocksAfter ?? createEmptyRichContentDocument(),
12018
12653
  editorialContext: template.defaults?.editorialContext,
12019
12654
  fieldMetadata: template.defaults?.fieldMetadata ?? [],
12020
12655
  actions: template.layout?.actions,
@@ -12079,12 +12714,62 @@ function mergeTemplateReference(base, metadataPatch, overridePatch) {
12079
12714
  };
12080
12715
  }
12081
12716
 
12717
+ function richDoc(...nodes) {
12718
+ return {
12719
+ kind: 'praxis.rich-content',
12720
+ version: '1.0.0',
12721
+ nodes,
12722
+ };
12723
+ }
12724
+ function richFooterCard(config) {
12725
+ return richDoc({
12726
+ type: 'card',
12727
+ title: config.title,
12728
+ subtitle: config.subtitle,
12729
+ content: [
12730
+ ...(config.links?.length
12731
+ ? [
12732
+ {
12733
+ type: 'compose',
12734
+ direction: 'row',
12735
+ wrap: true,
12736
+ items: config.links.map((label) => ({
12737
+ type: 'badge',
12738
+ label,
12739
+ })),
12740
+ },
12741
+ ]
12742
+ : []),
12743
+ ],
12744
+ });
12745
+ }
12746
+ function richIntroCard(config) {
12747
+ return richDoc({
12748
+ type: 'card',
12749
+ title: config.title,
12750
+ subtitle: config.subtitle,
12751
+ content: [
12752
+ ...(config.badge
12753
+ ? [
12754
+ {
12755
+ type: 'badge',
12756
+ label: config.badge,
12757
+ },
12758
+ ]
12759
+ : []),
12760
+ {
12761
+ type: 'text',
12762
+ text: config.description,
12763
+ },
12764
+ ],
12765
+ });
12766
+ }
12082
12767
  const EVENT_REGISTRATION_EDITORIAL_TEMPLATE = {
12083
12768
  templateId: 'event-registration',
12084
12769
  version: '1.0.0',
12085
12770
  metadata: {
12086
12771
  title: 'Event Registration',
12087
- description: 'Template editorial para inscrições institucionais, eventos, workshops e programas com contexto pré-submit.',
12772
+ description: 'Template editorial para inscricoes institucionais, eventos, workshops e programas com contexto pre-submit.',
12088
12773
  category: 'registration',
12089
12774
  tags: ['event', 'registration', 'editorial', 'consent'],
12090
12775
  source: 'catalog',
@@ -12107,99 +12792,101 @@ const EVENT_REGISTRATION_EDITORIAL_TEMPLATE = {
12107
12792
  { key: 'eventContext.dateLabel', type: 'string' },
12108
12793
  ],
12109
12794
  layout: {
12110
- formBlocksBefore: [
12111
- {
12112
- id: 'widget:hero-banner',
12113
- inputs: {
12114
- instanceId: 'template:event-registration:hero',
12115
- title: 'Inscrição em evento',
12116
- titleAccent: 'institucional',
12117
- subtitle: 'Template editorial',
12118
- description: 'Estrutura base para inscrições em encontros, workshops, roadshows e experiências de marca.',
12119
- variant: 'event',
12120
- appearance: 'flat',
12121
- },
12795
+ formBlocksBefore: richDoc({
12796
+ type: 'mediaBlock',
12797
+ title: { type: 'text', text: 'Inscricao em evento institucional' },
12798
+ subtitle: { type: 'text', text: 'Template editorial' },
12799
+ meta: {
12800
+ type: 'compose',
12801
+ direction: 'row',
12802
+ wrap: true,
12803
+ items: [
12804
+ { type: 'badge', label: 'registration' },
12805
+ { type: 'text', text: 'Fluxo institucional reutilizavel' },
12806
+ ],
12122
12807
  },
12123
- {
12124
- id: 'widget:rich-text-block',
12125
- inputs: {
12126
- instanceId: 'template:event-registration:intro',
12127
- title: 'Como preencher',
12128
- subtitle: 'Orientação inicial',
12129
- icon: 'info',
12130
- variant: 'default',
12131
- appearance: 'plain',
12132
- contentFormat: 'markdown',
12133
- content: 'Use dados atualizados, revise os consentimentos e confirme sua disponibilidade antes do envio.',
12808
+ }, {
12809
+ type: 'card',
12810
+ title: 'Como preencher',
12811
+ subtitle: 'Orientacao inicial',
12812
+ content: [
12813
+ {
12814
+ type: 'text',
12815
+ text: 'Use dados atualizados, revise os consentimentos e confirme sua disponibilidade antes do envio.',
12134
12816
  },
12135
- },
12136
- ],
12817
+ ],
12818
+ }),
12137
12819
  sections: [
12138
12820
  {
12139
12821
  id: 'registration',
12140
12822
  appearance: 'step',
12141
12823
  stepLabel: '1',
12142
- title: 'Inscrição',
12143
- description: 'Dados principais do participante e critérios de participação.',
12824
+ title: 'Inscricao',
12825
+ description: 'Dados principais do participante e criterios de participacao.',
12144
12826
  rows: [
12145
12827
  { id: 'row-name', columns: [{ id: 'col-name', fields: ['fullName'] }] },
12146
12828
  { id: 'row-email', columns: [{ id: 'col-email', fields: ['email'] }] },
12147
- { id: 'row-attendance', columns: [{ id: 'col-attendance', fields: ['attendanceMode'] }] },
12148
- { id: 'row-company', columns: [{ id: 'col-company', fields: ['organizationName'] }] },
12829
+ {
12830
+ id: 'row-attendance',
12831
+ columns: [{ id: 'col-attendance', fields: ['attendanceMode'] }],
12832
+ },
12833
+ {
12834
+ id: 'row-company',
12835
+ columns: [{ id: 'col-company', fields: ['organizationName'] }],
12836
+ },
12149
12837
  { id: 'row-role', columns: [{ id: 'col-role', fields: ['jobTitle'] }] },
12150
- { id: 'row-source', columns: [{ id: 'col-source', fields: ['discoverySource'] }] },
12151
- { id: 'row-photo-consent', columns: [{ id: 'col-photo-consent', fields: ['photoConsent'] }] },
12152
- { id: 'row-privacy-consent', columns: [{ id: 'col-privacy-consent', fields: ['privacyConsent'] }] },
12838
+ {
12839
+ id: 'row-source',
12840
+ columns: [{ id: 'col-source', fields: ['discoverySource'] }],
12841
+ },
12842
+ {
12843
+ id: 'row-photo-consent',
12844
+ columns: [{ id: 'col-photo-consent', fields: ['photoConsent'] }],
12845
+ },
12846
+ {
12847
+ id: 'row-privacy-consent',
12848
+ columns: [{ id: 'col-privacy-consent', fields: ['privacyConsent'] }],
12849
+ },
12153
12850
  ],
12154
12851
  },
12155
12852
  ],
12156
- formBlocksBeforeActions: [
12157
- {
12158
- id: 'form:user-context-summary',
12159
- inputs: {
12160
- instanceId: 'template:event-registration:user-context',
12161
- title: 'Conta usada no preenchimento',
12162
- subtitle: 'Resumo contextual antes do envio.',
12163
- appearance: 'plain',
12164
- source: 'context',
12165
- context: '${accountContext}',
12166
- fields: [
12167
- { label: 'Nome', valuePath: 'user.name', fallback: '-' },
12168
- { label: 'E-mail', valuePath: 'user.email', fallback: '-' },
12169
- ],
12170
- actionId: 'switch-user',
12171
- actionLabel: 'Trocar conta',
12853
+ formBlocksBeforeActions: richDoc({
12854
+ type: 'card',
12855
+ title: 'Conta usada no preenchimento',
12856
+ subtitle: 'Resumo contextual antes do envio.',
12857
+ content: [
12858
+ {
12859
+ type: 'metric',
12860
+ label: 'Nome',
12861
+ valueExpr: '${accountContext.user.name}',
12172
12862
  },
12173
- },
12174
- {
12175
- id: 'widget:legal-notice',
12176
- inputs: {
12177
- instanceId: 'template:event-registration:privacy',
12178
- title: 'Privacidade e uso de dados',
12179
- severity: 'muted',
12180
- appearance: 'plain',
12181
- contentFormat: 'markdown',
12182
- content: 'Ao enviar a inscrição, o participante reconhece o tratamento dos dados para credenciamento, comunicações e operação do evento.',
12863
+ {
12864
+ type: 'metric',
12865
+ label: 'E-mail',
12866
+ valueExpr: '${accountContext.user.email}',
12183
12867
  },
12184
- },
12185
- ],
12186
- formBlocksBeforeActionsPlacement: 'insideLastSection',
12187
- formBlocksAfter: [
12188
- {
12189
- id: 'widget:footer-links',
12190
- inputs: {
12191
- instanceId: 'template:event-registration:footer',
12192
- brandText: 'Praxis UI',
12193
- secondaryText: 'Template editorial reutilizável para experiências de inscrição.',
12194
- layout: 'inline',
12195
- appearance: 'plain',
12196
- links: [
12197
- { label: 'Privacidade', href: '/privacidade' },
12198
- { label: 'Termos', href: '/termos' },
12199
- ],
12868
+ {
12869
+ type: 'text',
12870
+ text: 'Se necessario, troque o contexto da conta antes de concluir a inscricao.',
12200
12871
  },
12201
- },
12202
- ],
12872
+ ],
12873
+ }, {
12874
+ type: 'card',
12875
+ title: 'Privacidade e uso de dados',
12876
+ subtitle: 'Antes do envio',
12877
+ content: [
12878
+ {
12879
+ type: 'text',
12880
+ text: 'Ao enviar a inscricao, o participante reconhece o tratamento dos dados para credenciamento, comunicacoes e operacao do evento.',
12881
+ },
12882
+ ],
12883
+ }),
12884
+ formBlocksBeforeActionsPlacement: 'insideLastSection',
12885
+ formBlocksAfter: richFooterCard({
12886
+ title: 'Praxis UI',
12887
+ subtitle: 'Template editorial reutilizavel para experiencias de inscricao.',
12888
+ links: ['Privacidade', 'Termos'],
12889
+ }),
12203
12890
  actions: {
12204
12891
  placement: 'afterSections',
12205
12892
  position: 'right',
@@ -12207,7 +12894,7 @@ const EVENT_REGISTRATION_EDITORIAL_TEMPLATE = {
12207
12894
  spacing: 'normal',
12208
12895
  submit: {
12209
12896
  visible: true,
12210
- label: 'Enviar inscrição',
12897
+ label: 'Enviar inscricao',
12211
12898
  type: 'submit',
12212
12899
  color: 'primary',
12213
12900
  variant: 'raised',
@@ -12228,8 +12915,19 @@ const EVENT_REGISTRATION_EDITORIAL_TEMPLATE = {
12228
12915
  },
12229
12916
  defaults: {
12230
12917
  fieldMetadata: [
12231
- { name: 'fullName', label: 'Nome completo*', controlType: 'input', required: true },
12232
- { name: 'email', label: 'E-mail*', controlType: 'email', required: true, readonly: true },
12918
+ {
12919
+ name: 'fullName',
12920
+ label: 'Nome completo*',
12921
+ controlType: 'input',
12922
+ required: true,
12923
+ },
12924
+ {
12925
+ name: 'email',
12926
+ label: 'E-mail*',
12927
+ controlType: 'email',
12928
+ required: true,
12929
+ readonly: true,
12930
+ },
12233
12931
  {
12234
12932
  name: 'attendanceMode',
12235
12933
  label: 'Como pretende participar?*',
@@ -12241,7 +12939,12 @@ const EVENT_REGISTRATION_EDITORIAL_TEMPLATE = {
12241
12939
  { text: 'Online', value: 'ONLINE' },
12242
12940
  ],
12243
12941
  },
12244
- { name: 'organizationName', label: 'Empresa ou instituição*', controlType: 'input', required: true },
12942
+ {
12943
+ name: 'organizationName',
12944
+ label: 'Empresa ou instituicao*',
12945
+ controlType: 'input',
12946
+ required: true,
12947
+ },
12245
12948
  { name: 'jobTitle', label: 'Cargo', controlType: 'input' },
12246
12949
  {
12247
12950
  name: 'discoverySource',
@@ -12251,7 +12954,7 @@ const EVENT_REGISTRATION_EDITORIAL_TEMPLATE = {
12251
12954
  options: [
12252
12955
  { text: 'Site institucional', value: 'WEBSITE' },
12253
12956
  { text: 'LinkedIn', value: 'LINKEDIN' },
12254
- { text: 'Indicação', value: 'REFERRAL' },
12957
+ { text: 'Indicacao', value: 'REFERRAL' },
12255
12958
  { text: 'Outro', value: 'OTHER' },
12256
12959
  ],
12257
12960
  },
@@ -12267,7 +12970,7 @@ const EVENT_REGISTRATION_EDITORIAL_TEMPLATE = {
12267
12970
  },
12268
12971
  {
12269
12972
  name: 'privacyConsent',
12270
- label: 'Aceito a política de privacidade e o tratamento dos dados informados.',
12973
+ label: 'Aceito a politica de privacidade e o tratamento dos dados informados.',
12271
12974
  controlType: 'checkbox',
12272
12975
  selectionMode: 'boolean',
12273
12976
  variant: 'consent',
@@ -12283,7 +12986,7 @@ const EMPLOYEE_ONBOARDING_EDITORIAL_TEMPLATE = {
12283
12986
  version: '1.0.0',
12284
12987
  metadata: {
12285
12988
  title: 'Employee Onboarding',
12286
- description: 'Template editorial para admissão, pré-boarding e coleta inicial de dados de colaboradores.',
12989
+ description: 'Template editorial para admissao, pre-boarding e coleta inicial de dados de colaboradores.',
12287
12990
  category: 'onboarding',
12288
12991
  tags: ['employee', 'onboarding', 'hr', 'documents'],
12289
12992
  source: 'catalog',
@@ -12302,42 +13005,38 @@ const EMPLOYEE_ONBOARDING_EDITORIAL_TEMPLATE = {
12302
13005
  { key: 'company.name', type: 'string', required: true },
12303
13006
  { key: 'company.hrEmail', type: 'string' },
12304
13007
  { key: 'position.title', type: 'string' },
12305
- { key: 'manager.name', type: 'string' },
12306
- ],
12307
- layout: {
12308
- formBlocksBefore: [
12309
- {
12310
- id: 'widget:hero-banner',
12311
- inputs: {
12312
- instanceId: 'template:employee-onboarding:hero',
12313
- title: 'Boas-vindas ao processo de',
12314
- titleAccent: 'onboarding',
12315
- subtitle: 'Template corporativo',
12316
- description: 'Base para admissão, conferência cadastral, preferências de trabalho e aceite de políticas internas.',
12317
- variant: 'institutional',
12318
- appearance: 'card',
12319
- },
12320
- },
12321
- {
12322
- id: 'widget:rich-text-block',
12323
- inputs: {
12324
- instanceId: 'template:employee-onboarding:summary',
12325
- title: 'O que será coletado',
12326
- subtitle: 'Resumo do fluxo',
12327
- icon: 'badge',
12328
- variant: 'subtle',
12329
- appearance: 'plain',
12330
- contentFormat: 'markdown',
12331
- content: '- dados pessoais e de contato\n- preferências operacionais iniciais\n- anexos e termos obrigatórios',
12332
- },
13008
+ { key: 'manager.name', type: 'string' },
13009
+ ],
13010
+ layout: {
13011
+ formBlocksBefore: richDoc({
13012
+ type: 'mediaBlock',
13013
+ title: { type: 'text', text: 'Boas-vindas ao processo de onboarding' },
13014
+ subtitle: { type: 'text', text: 'Template corporativo' },
13015
+ meta: {
13016
+ type: 'compose',
13017
+ direction: 'row',
13018
+ wrap: true,
13019
+ items: [
13020
+ { type: 'badge', label: 'onboarding' },
13021
+ { type: 'text', text: 'Admissao, conferencia e preferencias iniciais' },
13022
+ ],
12333
13023
  },
12334
- ],
13024
+ }, {
13025
+ type: 'card',
13026
+ title: 'O que sera coletado',
13027
+ subtitle: 'Resumo do fluxo',
13028
+ content: [
13029
+ { type: 'text', text: 'Dados pessoais e de contato.' },
13030
+ { type: 'text', text: 'Preferencias operacionais iniciais.' },
13031
+ { type: 'text', text: 'Anexos e termos obrigatorios.' },
13032
+ ],
13033
+ }),
12335
13034
  sections: [
12336
13035
  {
12337
13036
  id: 'identity',
12338
13037
  appearance: 'step',
12339
13038
  stepLabel: '1',
12340
- title: 'Identificação',
13039
+ title: 'Identificacao',
12341
13040
  description: 'Dados essenciais para cadastro inicial do colaborador.',
12342
13041
  rows: [
12343
13042
  {
@@ -12360,28 +13059,34 @@ const EMPLOYEE_ONBOARDING_EDITORIAL_TEMPLATE = {
12360
13059
  id: 'operations',
12361
13060
  appearance: 'step',
12362
13061
  stepLabel: '2',
12363
- title: 'Operação inicial',
12364
- description: 'Dados para preparação do ambiente e comunicação inicial.',
13062
+ title: 'Operacao inicial',
13063
+ description: 'Dados para preparacao do ambiente e comunicacao inicial.',
12365
13064
  rows: [
12366
- { id: 'row-equipment', columns: [{ id: 'col-equipment', fields: ['needsEquipment'] }] },
12367
- { id: 'row-address', columns: [{ id: 'col-address', fields: ['shippingAddress'] }] },
12368
- { id: 'row-notes', columns: [{ id: 'col-notes', fields: ['accessibilityNotes'] }] },
12369
- { id: 'row-privacy', columns: [{ id: 'col-privacy', fields: ['privacyConsent'] }] },
13065
+ {
13066
+ id: 'row-equipment',
13067
+ columns: [{ id: 'col-equipment', fields: ['needsEquipment'] }],
13068
+ },
13069
+ {
13070
+ id: 'row-address',
13071
+ columns: [{ id: 'col-address', fields: ['shippingAddress'] }],
13072
+ },
13073
+ {
13074
+ id: 'row-notes',
13075
+ columns: [{ id: 'col-notes', fields: ['accessibilityNotes'] }],
13076
+ },
13077
+ {
13078
+ id: 'row-privacy',
13079
+ columns: [{ id: 'col-privacy', fields: ['privacyConsent'] }],
13080
+ },
12370
13081
  ],
12371
13082
  },
12372
13083
  ],
12373
- formBlocksBeforeActions: [
12374
- {
12375
- id: 'widget:legal-notice',
12376
- inputs: {
12377
- instanceId: 'template:employee-onboarding:notice',
12378
- title: 'Uso interno',
12379
- severity: 'info',
12380
- appearance: 'plain',
12381
- content: 'As informações deste fluxo são usadas exclusivamente para cadastro interno, provisionamento e comunicação de onboarding.',
12382
- },
12383
- },
12384
- ],
13084
+ formBlocksBeforeActions: richIntroCard({
13085
+ title: 'Uso interno',
13086
+ subtitle: 'Antes do envio',
13087
+ badge: 'info',
13088
+ description: 'As informacoes deste fluxo sao usadas exclusivamente para cadastro interno, provisionamento e comunicacao de onboarding.',
13089
+ }),
12385
13090
  formBlocksBeforeActionsPlacement: 'afterSections',
12386
13091
  actions: {
12387
13092
  placement: 'afterSections',
@@ -12393,14 +13098,34 @@ const EMPLOYEE_ONBOARDING_EDITORIAL_TEMPLATE = {
12393
13098
  color: 'primary',
12394
13099
  variant: 'raised',
12395
13100
  },
12396
- cancel: { visible: false, label: 'Cancelar', type: 'button', color: 'basic' },
12397
- reset: { visible: false, label: 'Reset', type: 'reset', color: 'basic' },
13101
+ cancel: {
13102
+ visible: false,
13103
+ label: 'Cancelar',
13104
+ type: 'button',
13105
+ color: 'basic',
13106
+ },
13107
+ reset: {
13108
+ visible: false,
13109
+ label: 'Reset',
13110
+ type: 'reset',
13111
+ color: 'basic',
13112
+ },
12398
13113
  },
12399
13114
  },
12400
13115
  defaults: {
12401
13116
  fieldMetadata: [
12402
- { name: 'fullName', label: 'Nome completo*', controlType: 'input', required: true },
12403
- { name: 'corporateEmail', label: 'E-mail corporativo*', controlType: 'email', required: true },
13117
+ {
13118
+ name: 'fullName',
13119
+ label: 'Nome completo*',
13120
+ controlType: 'input',
13121
+ required: true,
13122
+ },
13123
+ {
13124
+ name: 'corporateEmail',
13125
+ label: 'E-mail corporativo*',
13126
+ controlType: 'email',
13127
+ required: true,
13128
+ },
12404
13129
  { name: 'phoneNumber', label: 'Telefone', controlType: 'input' },
12405
13130
  {
12406
13131
  name: 'workModel',
@@ -12409,7 +13134,7 @@ const EMPLOYEE_ONBOARDING_EDITORIAL_TEMPLATE = {
12409
13134
  required: true,
12410
13135
  options: [
12411
13136
  { text: 'Presencial', value: 'ONSITE' },
12412
- { text: 'Híbrido', value: 'HYBRID' },
13137
+ { text: 'Hibrido', value: 'HYBRID' },
12413
13138
  { text: 'Remoto', value: 'REMOTE' },
12414
13139
  ],
12415
13140
  },
@@ -12420,14 +13145,22 @@ const EMPLOYEE_ONBOARDING_EDITORIAL_TEMPLATE = {
12420
13145
  required: true,
12421
13146
  options: [
12422
13147
  { text: 'Sim', value: 'YES' },
12423
- { text: 'Não', value: 'NO' },
13148
+ { text: 'Nao', value: 'NO' },
12424
13149
  ],
12425
13150
  },
12426
- { name: 'shippingAddress', label: 'Endereço para envio', controlType: 'textarea' },
12427
- { name: 'accessibilityNotes', label: 'Observações de acessibilidade ou preferências', controlType: 'textarea' },
13151
+ {
13152
+ name: 'shippingAddress',
13153
+ label: 'Endereco para envio',
13154
+ controlType: 'textarea',
13155
+ },
13156
+ {
13157
+ name: 'accessibilityNotes',
13158
+ label: 'Observacoes de acessibilidade ou preferencias',
13159
+ controlType: 'textarea',
13160
+ },
12428
13161
  {
12429
13162
  name: 'privacyConsent',
12430
- label: 'Confirmo ciência sobre o tratamento dos meus dados no processo de onboarding.',
13163
+ label: 'Confirmo ciencia sobre o tratamento dos meus dados no processo de onboarding.',
12431
13164
  controlType: 'checkbox',
12432
13165
  selectionMode: 'boolean',
12433
13166
  variant: 'consent',
@@ -12443,7 +13176,7 @@ const EMPLOYEE_ONBOARDING_GUIDED_EDITORIAL_TEMPLATE = {
12443
13176
  version: '1.0.0',
12444
13177
  metadata: {
12445
13178
  title: 'Employee Onboarding Guided',
12446
- description: 'Template editorial guiado para onboarding com identificação enriquecida, preparação operacional e actions orientadas por etapa.',
13179
+ description: 'Template editorial guiado para onboarding com identificacao enriquecida, preparacao operacional e actions orientadas por etapa.',
12447
13180
  category: 'onboarding',
12448
13181
  tags: ['employee', 'onboarding', 'hr', 'guided', 'wizard'],
12449
13182
  source: 'catalog',
@@ -12469,7 +13202,7 @@ const EMPLOYEE_ONBOARDING_GUIDED_EDITORIAL_TEMPLATE = {
12469
13202
  id: 'identity',
12470
13203
  appearance: 'step',
12471
13204
  stepLabel: '1',
12472
- title: 'Identificação',
13205
+ title: 'Identificacao',
12473
13206
  description: 'Preencha seus dados para que possamos configurar seu acesso.',
12474
13207
  rows: [
12475
13208
  {
@@ -12500,8 +13233,8 @@ const EMPLOYEE_ONBOARDING_GUIDED_EDITORIAL_TEMPLATE = {
12500
13233
  id: 'operations',
12501
13234
  appearance: 'step',
12502
13235
  stepLabel: '2',
12503
- title: 'Operação inicial',
12504
- description: 'Configure os recursos necessários para o primeiro dia.',
13236
+ title: 'Operacao inicial',
13237
+ description: 'Configure os recursos necessarios para o primeiro dia.',
12505
13238
  rows: [
12506
13239
  {
12507
13240
  id: 'operations-row-1',
@@ -12510,7 +13243,10 @@ const EMPLOYEE_ONBOARDING_GUIDED_EDITORIAL_TEMPLATE = {
12510
13243
  {
12511
13244
  id: 'operations-row-2',
12512
13245
  columns: [
12513
- { id: 'operations-col-observations', fields: ['accessibilityNotes'] },
13246
+ {
13247
+ id: 'operations-col-observations',
13248
+ fields: ['accessibilityNotes'],
13249
+ },
12514
13250
  ],
12515
13251
  },
12516
13252
  {
@@ -12520,9 +13256,9 @@ const EMPLOYEE_ONBOARDING_GUIDED_EDITORIAL_TEMPLATE = {
12520
13256
  ],
12521
13257
  },
12522
13258
  ],
12523
- formBlocksBefore: [],
12524
- formBlocksBeforeActions: [],
12525
- formBlocksAfter: [],
13259
+ formBlocksBefore: richDoc(),
13260
+ formBlocksBeforeActions: richDoc(),
13261
+ formBlocksAfter: richDoc(),
12526
13262
  actions: {
12527
13263
  placement: 'afterSections',
12528
13264
  position: 'split',
@@ -12530,7 +13266,7 @@ const EMPLOYEE_ONBOARDING_GUIDED_EDITORIAL_TEMPLATE = {
12530
13266
  spacing: 'normal',
12531
13267
  submit: {
12532
13268
  visible: true,
12533
- label: 'Próximo',
13269
+ label: 'Proximo',
12534
13270
  type: 'submit',
12535
13271
  color: 'primary',
12536
13272
  variant: 'raised',
@@ -12555,8 +13291,18 @@ const EMPLOYEE_ONBOARDING_GUIDED_EDITORIAL_TEMPLATE = {
12555
13291
  },
12556
13292
  defaults: {
12557
13293
  fieldMetadata: [
12558
- { name: 'fullName', label: 'Nome completo *', controlType: 'input', required: true },
12559
- { name: 'corporateEmail', label: 'E-mail corporativo *', controlType: 'email', required: true },
13294
+ {
13295
+ name: 'fullName',
13296
+ label: 'Nome completo *',
13297
+ controlType: 'input',
13298
+ required: true,
13299
+ },
13300
+ {
13301
+ name: 'corporateEmail',
13302
+ label: 'E-mail corporativo *',
13303
+ controlType: 'email',
13304
+ required: true,
13305
+ },
12560
13306
  { name: 'phoneNumber', label: 'Telefone', controlType: 'input' },
12561
13307
  {
12562
13308
  name: 'department',
@@ -12584,7 +13330,7 @@ const EMPLOYEE_ONBOARDING_GUIDED_EDITORIAL_TEMPLATE = {
12584
13330
  },
12585
13331
  {
12586
13332
  name: 'startDate',
12587
- label: 'Data de início',
13333
+ label: 'Data de inicio',
12588
13334
  controlType: 'date',
12589
13335
  required: true,
12590
13336
  },
@@ -12597,17 +13343,17 @@ const EMPLOYEE_ONBOARDING_GUIDED_EDITORIAL_TEMPLATE = {
12597
13343
  options: [
12598
13344
  { text: 'Presencial', value: 'Presencial' },
12599
13345
  { text: 'Remoto', value: 'Remoto' },
12600
- { text: 'Híbrido', value: 'Híbrido' },
13346
+ { text: 'Hibrido', value: 'Hibrido' },
12601
13347
  ],
12602
13348
  },
12603
13349
  {
12604
13350
  name: 'accessibilityNotes',
12605
- label: 'Observações adicionais',
13351
+ label: 'Observacoes adicionais',
12606
13352
  controlType: 'textarea',
12607
13353
  },
12608
13354
  {
12609
13355
  name: 'privacyConsent',
12610
- label: 'Confirmo ciência sobre o tratamento dos meus dados no processo de onboarding.',
13356
+ label: 'Confirmo ciencia sobre o tratamento dos meus dados no processo de onboarding.',
12611
13357
  controlType: 'checkbox',
12612
13358
  selectionMode: 'boolean',
12613
13359
  variant: 'consent',
@@ -12623,7 +13369,7 @@ const PRIVACY_CONSENT_EDITORIAL_TEMPLATE = {
12623
13369
  version: '1.0.0',
12624
13370
  metadata: {
12625
13371
  title: 'Privacy Consent',
12626
- description: 'Template focado em aceite explícito, base legal, preferências de comunicação e registro de consentimento.',
13372
+ description: 'Template focado em aceite explicito, base legal, preferencias de comunicacao e registro de consentimento.',
12627
13373
  category: 'consent',
12628
13374
  tags: ['privacy', 'consent', 'compliance', 'legal'],
12629
13375
  source: 'catalog',
@@ -12641,49 +13387,43 @@ const PRIVACY_CONSENT_EDITORIAL_TEMPLATE = {
12641
13387
  { key: 'policy.updatedAt', type: 'date' },
12642
13388
  ],
12643
13389
  layout: {
12644
- formBlocksBefore: [
12645
- {
12646
- id: 'widget:legal-notice',
12647
- inputs: {
12648
- instanceId: 'template:privacy-consent:lead',
12649
- title: 'Consentimento e tratamento de dados',
12650
- severity: 'info',
12651
- appearance: 'card',
12652
- contentFormat: 'markdown',
12653
- content: 'Use este template quando o objetivo principal do fluxo for registrar ciência, aceite e preferências relacionadas a privacidade.',
12654
- },
12655
- },
12656
- ],
13390
+ formBlocksBefore: richIntroCard({
13391
+ title: 'Consentimento e tratamento de dados',
13392
+ subtitle: 'Template regulatorio',
13393
+ badge: 'info',
13394
+ description: 'Use este template quando o objetivo principal do fluxo for registrar ciencia, aceite e preferencias relacionadas a privacidade.',
13395
+ }),
12657
13396
  sections: [
12658
13397
  {
12659
13398
  id: 'consent',
12660
13399
  appearance: 'card',
12661
- title: 'Preferências e consentimentos',
12662
- description: 'Aceites explícitos e canais opcionais de comunicação.',
13400
+ title: 'Preferencias e consentimentos',
13401
+ description: 'Aceites explicitos e canais opcionais de comunicacao.',
12663
13402
  rows: [
12664
- { id: 'row-primary', columns: [{ id: 'col-primary', fields: ['privacyConsent'] }] },
12665
- { id: 'row-marketing', columns: [{ id: 'col-marketing', fields: ['marketingConsent'] }] },
12666
- { id: 'row-channels', columns: [{ id: 'col-channels', fields: ['preferredChannel'] }] },
12667
- { id: 'row-observation', columns: [{ id: 'col-observation', fields: ['consentNotes'] }] },
13403
+ {
13404
+ id: 'row-primary',
13405
+ columns: [{ id: 'col-primary', fields: ['privacyConsent'] }],
13406
+ },
13407
+ {
13408
+ id: 'row-marketing',
13409
+ columns: [{ id: 'col-marketing', fields: ['marketingConsent'] }],
13410
+ },
13411
+ {
13412
+ id: 'row-channels',
13413
+ columns: [{ id: 'col-channels', fields: ['preferredChannel'] }],
13414
+ },
13415
+ {
13416
+ id: 'row-observation',
13417
+ columns: [{ id: 'col-observation', fields: ['consentNotes'] }],
13418
+ },
12668
13419
  ],
12669
13420
  },
12670
13421
  ],
12671
- formBlocksAfter: [
12672
- {
12673
- id: 'widget:footer-links',
12674
- inputs: {
12675
- instanceId: 'template:privacy-consent:footer',
12676
- brandText: 'Praxis UI',
12677
- secondaryText: 'Template para fluxos regulatórios e comprovação de consentimento.',
12678
- layout: 'inline',
12679
- appearance: 'divider',
12680
- links: [
12681
- { label: 'Política de Privacidade', href: '/privacidade' },
12682
- { label: 'Canal LGPD', href: '/lgpd' },
12683
- ],
12684
- },
12685
- },
12686
- ],
13422
+ formBlocksAfter: richFooterCard({
13423
+ title: 'Praxis UI',
13424
+ subtitle: 'Template para fluxos regulatorios e comprovacao de consentimento.',
13425
+ links: ['Politica de Privacidade', 'Canal LGPD'],
13426
+ }),
12687
13427
  actions: {
12688
13428
  placement: 'afterSections',
12689
13429
  position: 'right',
@@ -12694,15 +13434,25 @@ const PRIVACY_CONSENT_EDITORIAL_TEMPLATE = {
12694
13434
  color: 'primary',
12695
13435
  variant: 'raised',
12696
13436
  },
12697
- cancel: { visible: false, label: 'Cancelar', type: 'button', color: 'basic' },
12698
- reset: { visible: false, label: 'Reset', type: 'reset', color: 'basic' },
13437
+ cancel: {
13438
+ visible: false,
13439
+ label: 'Cancelar',
13440
+ type: 'button',
13441
+ color: 'basic',
13442
+ },
13443
+ reset: {
13444
+ visible: false,
13445
+ label: 'Reset',
13446
+ type: 'reset',
13447
+ color: 'basic',
13448
+ },
12699
13449
  },
12700
13450
  },
12701
13451
  defaults: {
12702
13452
  fieldMetadata: [
12703
13453
  {
12704
13454
  name: 'privacyConsent',
12705
- label: 'Li e aceito a política de privacidade aplicável.',
13455
+ label: 'Li e aceito a politica de privacidade aplicavel.',
12706
13456
  controlType: 'checkbox',
12707
13457
  selectionMode: 'boolean',
12708
13458
  variant: 'consent',
@@ -12712,7 +13462,7 @@ const PRIVACY_CONSENT_EDITORIAL_TEMPLATE = {
12712
13462
  },
12713
13463
  {
12714
13464
  name: 'marketingConsent',
12715
- label: 'Aceito receber comunicações institucionais e materiais relacionados.',
13465
+ label: 'Aceito receber comunicacoes institucionais e materiais relacionados.',
12716
13466
  controlType: 'checkbox',
12717
13467
  selectionMode: 'boolean',
12718
13468
  variant: 'consent',
@@ -12720,7 +13470,7 @@ const PRIVACY_CONSENT_EDITORIAL_TEMPLATE = {
12720
13470
  },
12721
13471
  {
12722
13472
  name: 'preferredChannel',
12723
- label: 'Canal preferencial de comunicação',
13473
+ label: 'Canal preferencial de comunicacao',
12724
13474
  controlType: 'select',
12725
13475
  options: [
12726
13476
  { text: 'E-mail', value: 'EMAIL' },
@@ -12730,7 +13480,7 @@ const PRIVACY_CONSENT_EDITORIAL_TEMPLATE = {
12730
13480
  },
12731
13481
  {
12732
13482
  name: 'consentNotes',
12733
- label: 'Observações adicionais',
13483
+ label: 'Observacoes adicionais',
12734
13484
  controlType: 'textarea',
12735
13485
  },
12736
13486
  ],
@@ -12811,6 +13561,7 @@ const RULE_PROPERTY_SCHEMA = {
12811
13561
  { name: 'validators', type: 'object', label: 'Validadores' },
12812
13562
  ],
12813
13563
  section: [
13564
+ { name: 'hidden', type: 'boolean', label: 'Oculto' },
12814
13565
  { name: 'visible', type: 'boolean', label: 'Visível' },
12815
13566
  { name: 'title', type: 'string', label: 'Título' },
12816
13567
  { name: 'description', type: 'string', label: 'Descrição' },
@@ -18392,11 +19143,11 @@ function providePraxisHeroBannerMetadata() {
18392
19143
 
18393
19144
  /**
18394
19145
  * Binds a stored icon string to a mat-icon element supporting:
18395
- * - Material Icons (classic ligatures): "mi:pending" or "pending"
19146
+ * - Material Icons (classic ligatures): "mi:pending"
18396
19147
  * - Material Symbols Outlined: "mso:right_click" or "ms:right_click"
18397
19148
  * - Material Symbols Rounded: "msr:right_click"
18398
19149
  * - Material Symbols Sharp: "mss:right_click"
18399
- * Falls back to classic Material Icons when prefix is omitted.
19150
+ * Falls back to Material Symbols Outlined when prefix is omitted.
18400
19151
  */
18401
19152
  class PraxisIconDirective {
18402
19153
  el;
@@ -18437,16 +19188,18 @@ class PraxisIconDirective {
18437
19188
  this.rd.addClass(host, 'material-symbols-sharp');
18438
19189
  break;
18439
19190
  case 'mi':
18440
- default:
18441
19191
  this.rd.addClass(host, 'material-icons');
18442
19192
  break;
19193
+ default:
19194
+ this.rd.addClass(host, 'material-symbols-outlined');
19195
+ break;
18443
19196
  }
18444
19197
  host.textContent = name;
18445
19198
  }
18446
19199
  parse(raw) {
18447
19200
  const colon = raw.indexOf(':');
18448
19201
  if (colon <= 0)
18449
- return { family: 'mi', name: raw };
19202
+ return { family: 'mso', name: raw };
18450
19203
  const prefix = raw.slice(0, colon).toLowerCase();
18451
19204
  const name = raw.slice(colon + 1).trim() || raw;
18452
19205
  if (prefix === 'ms' || prefix === 'mso')
@@ -19404,6 +20157,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
19404
20157
  type: Output
19405
20158
  }] } });
19406
20159
 
20160
+ const WIDGET_SHELL_I18N_NAMESPACE = 'widgetShell';
20161
+ const WIDGET_SHELL_I18N_CONFIG = {
20162
+ namespaces: {
20163
+ [WIDGET_SHELL_I18N_NAMESPACE]: {
20164
+ 'pt-BR': {
20165
+ 'controls.moreActions': 'Mais ações',
20166
+ 'controls.expandContent': 'Expandir conteúdo',
20167
+ 'controls.collapseContent': 'Recolher conteúdo',
20168
+ 'controls.exitFullscreen': 'Sair da tela cheia',
20169
+ 'controls.enterFullscreen': 'Tela cheia',
20170
+ },
20171
+ 'en-US': {
20172
+ 'controls.moreActions': 'More actions',
20173
+ 'controls.expandContent': 'Expand content',
20174
+ 'controls.collapseContent': 'Collapse content',
20175
+ 'controls.exitFullscreen': 'Exit fullscreen',
20176
+ 'controls.enterFullscreen': 'Fullscreen',
20177
+ },
20178
+ },
20179
+ },
20180
+ };
20181
+
19407
20182
  const BUILTIN_SHELL_PRESETS = {
19408
20183
  'dark-glass': {
19409
20184
  card: {
@@ -19425,10 +20200,10 @@ const BUILTIN_SHELL_PRESETS = {
19425
20200
  },
19426
20201
  'light-neutral': {
19427
20202
  card: {
19428
- background: '#f7f8fb',
19429
- borderColor: '#e3e7ef',
19430
- borderRadius: '14px',
19431
- shadow: '0 6px 18px rgba(15, 23, 42, 0.08)',
20203
+ background: '#f8fafc',
20204
+ borderColor: '#d7dfeb',
20205
+ borderRadius: '12px',
20206
+ shadow: '0 4px 12px rgba(15, 23, 42, 0.06)',
19432
20207
  },
19433
20208
  header: {
19434
20209
  titleColor: '#1f2937',
@@ -19451,6 +20226,7 @@ const BUILTIN_SHELL_PRESETS = {
19451
20226
  },
19452
20227
  };
19453
20228
  class WidgetShellComponent {
20229
+ i18n = inject(PraxisI18nService);
19454
20230
  shell;
19455
20231
  context = null;
19456
20232
  dragSurfaceEnabled = false;
@@ -19471,7 +20247,6 @@ class WidgetShellComponent {
19471
20247
  this.collapsed = !!this.shell?.collapsed;
19472
20248
  this.expanded = !!this.shell?.expanded;
19473
20249
  this.fullscreen = !!this.shell?.fullscreen;
19474
- // no-op: debug logs removed
19475
20250
  }
19476
20251
  get shellEnabled() {
19477
20252
  return !!this.shell && this.shell.kind !== 'none';
@@ -19536,6 +20311,9 @@ class WidgetShellComponent {
19536
20311
  this.expanded = false;
19537
20312
  this.fullscreen = false;
19538
20313
  }
20314
+ moreActionsLabel() {
20315
+ return this.t('controls.moreActions', 'Mais ações');
20316
+ }
19539
20317
  handleWindowAction(action) {
19540
20318
  if (action.id === 'collapse') {
19541
20319
  this.collapsed = !this.collapsed;
@@ -19554,8 +20332,9 @@ class WidgetShellComponent {
19554
20332
  this.expanded = true;
19555
20333
  this.collapsed = false;
19556
20334
  }
19557
- else
20335
+ else {
19558
20336
  this.expanded = false;
20337
+ }
19559
20338
  return { payload: { fullscreen: this.fullscreen } };
19560
20339
  }
19561
20340
  return null;
@@ -19571,8 +20350,10 @@ class WidgetShellComponent {
19571
20350
  actions.push({
19572
20351
  id: 'collapse',
19573
20352
  placement: 'window',
19574
- icon: this.collapsed ? 'unfold_more' : 'unfold_less',
19575
- tooltip: this.collapsed ? 'Expandir conteúdo' : 'Recolher conteúdo',
20353
+ icon: this.collapsed ? 'ms:unfold_more' : 'ms:unfold_less',
20354
+ tooltip: this.collapsed
20355
+ ? this.t('controls.expandContent', 'Expandir conteúdo')
20356
+ : this.t('controls.collapseContent', 'Recolher conteúdo'),
19576
20357
  variant: 'icon',
19577
20358
  });
19578
20359
  }
@@ -19580,8 +20361,10 @@ class WidgetShellComponent {
19580
20361
  actions.push({
19581
20362
  id: 'fullscreen',
19582
20363
  placement: 'window',
19583
- icon: this.fullscreen ? 'close_fullscreen' : 'open_in_full',
19584
- tooltip: this.fullscreen ? 'Sair da tela cheia' : 'Tela cheia',
20364
+ icon: this.fullscreen ? 'ms:close_fullscreen' : 'ms:open_in_full',
20365
+ tooltip: this.fullscreen
20366
+ ? this.t('controls.exitFullscreen', 'Sair da tela cheia')
20367
+ : this.t('controls.enterFullscreen', 'Tela cheia'),
19585
20368
  variant: 'icon',
19586
20369
  });
19587
20370
  }
@@ -19621,8 +20404,11 @@ class WidgetShellComponent {
19621
20404
  ? !!target.closest('button, a, input, select, textarea, [role="button"], [mat-menu-trigger-for]')
19622
20405
  : false;
19623
20406
  }
20407
+ t(key, fallback) {
20408
+ return this.i18n.t(key, undefined, fallback, WIDGET_SHELL_I18N_NAMESPACE);
20409
+ }
19624
20410
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: WidgetShellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
19625
- 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" }, queries: [{ propertyName: "loader", first: true, predicate: DynamicWidgetLoaderDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: `
20411
+ 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: `
19626
20412
  <section
19627
20413
  class="pdx-shell"
19628
20414
  [class.no-shell]="!shellEnabled"
@@ -19630,6 +20416,8 @@ class WidgetShellComponent {
19630
20416
  [class.collapsed]="collapsed"
19631
20417
  [class.expanded]="expanded"
19632
20418
  [class.fullscreen]="fullscreen"
20419
+ [class.body-fill]="shell?.bodyLayout === 'fill'"
20420
+ [class.body-scroll]="shell?.bodyLayout === 'scroll'"
19633
20421
  [style.--pdx-shell-card-bg]="appearance?.card?.background || null"
19634
20422
  [style.--pdx-shell-card-border]="appearance?.card?.borderColor || null"
19635
20423
  [style.--pdx-shell-card-radius]="appearance?.card?.borderRadius || null"
@@ -19702,13 +20490,13 @@ class WidgetShellComponent {
19702
20490
  <button
19703
20491
  mat-icon-button
19704
20492
  type="button"
19705
- [matTooltip]="'Mais ações'"
20493
+ [matTooltip]="moreActionsLabel()"
19706
20494
  matTooltipPosition="below"
19707
- aria-label="Mais ações"
20495
+ [attr.aria-label]="moreActionsLabel()"
19708
20496
  [matMenuTriggerFor]="overflowMenu"
19709
20497
  (click)="$event.stopPropagation()"
19710
20498
  >
19711
- <mat-icon>more_horiz</mat-icon>
20499
+ <mat-icon praxisIcon="ms:more_horiz"></mat-icon>
19712
20500
  </button>
19713
20501
  }
19714
20502
  }
@@ -19754,11 +20542,11 @@ class WidgetShellComponent {
19754
20542
  @if (expanded || fullscreen) {
19755
20543
  <div class="pdx-shell-backdrop" (click)="closeOverlay()"></div>
19756
20544
  }
19757
- `, 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, 14px);box-shadow:var(--pdx-shell-card-shadow, var(--mat-elevation-level2));overflow:hidden}.pdx-shell-header{display:flex;align-items:center;gap:12px;padding:10px 12px 8px;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:10px;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, 14px);line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-subtitle{font-size:var(--pdx-shell-subtitle-size, 12px);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:6px}.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, 10px 12px 12px 12px);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 });
20545
+ `, 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.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.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 });
19758
20546
  }
19759
20547
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: WidgetShellComponent, decorators: [{
19760
20548
  type: Component,
19761
- args: [{ selector: 'praxis-widget-shell', standalone: true, imports: [CommonModule, MatButtonModule, MatIconModule, MatMenuModule, MatTooltipModule, PraxisIconDirective], template: `
20549
+ args: [{ selector: 'praxis-widget-shell', standalone: true, imports: [CommonModule, MatButtonModule, MatIconModule, MatMenuModule, MatTooltipModule, PraxisIconDirective], providers: [providePraxisI18nConfig(WIDGET_SHELL_I18N_CONFIG)], template: `
19762
20550
  <section
19763
20551
  class="pdx-shell"
19764
20552
  [class.no-shell]="!shellEnabled"
@@ -19766,6 +20554,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
19766
20554
  [class.collapsed]="collapsed"
19767
20555
  [class.expanded]="expanded"
19768
20556
  [class.fullscreen]="fullscreen"
20557
+ [class.body-fill]="shell?.bodyLayout === 'fill'"
20558
+ [class.body-scroll]="shell?.bodyLayout === 'scroll'"
19769
20559
  [style.--pdx-shell-card-bg]="appearance?.card?.background || null"
19770
20560
  [style.--pdx-shell-card-border]="appearance?.card?.borderColor || null"
19771
20561
  [style.--pdx-shell-card-radius]="appearance?.card?.borderRadius || null"
@@ -19838,13 +20628,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
19838
20628
  <button
19839
20629
  mat-icon-button
19840
20630
  type="button"
19841
- [matTooltip]="'Mais ações'"
20631
+ [matTooltip]="moreActionsLabel()"
19842
20632
  matTooltipPosition="below"
19843
- aria-label="Mais ações"
20633
+ [attr.aria-label]="moreActionsLabel()"
19844
20634
  [matMenuTriggerFor]="overflowMenu"
19845
20635
  (click)="$event.stopPropagation()"
19846
20636
  >
19847
- <mat-icon>more_horiz</mat-icon>
20637
+ <mat-icon praxisIcon="ms:more_horiz"></mat-icon>
19848
20638
  </button>
19849
20639
  }
19850
20640
  }
@@ -19890,7 +20680,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
19890
20680
  @if (expanded || fullscreen) {
19891
20681
  <div class="pdx-shell-backdrop" (click)="closeOverlay()"></div>
19892
20682
  }
19893
- `, 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, 14px);box-shadow:var(--pdx-shell-card-shadow, var(--mat-elevation-level2));overflow:hidden}.pdx-shell-header{display:flex;align-items:center;gap:12px;padding:10px 12px 8px;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:10px;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, 14px);line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-subtitle{font-size:var(--pdx-shell-subtitle-size, 12px);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:6px}.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, 10px 12px 12px 12px);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"] }]
20683
+ `, 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.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.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"] }]
19894
20684
  }], propDecorators: { shell: [{
19895
20685
  type: Input
19896
20686
  }], context: [{
@@ -20896,14 +21686,13 @@ function applyLinkPatches(current, patches) {
20896
21686
  if (!patch) {
20897
21687
  return cloneLink(link);
20898
21688
  }
20899
- return {
20900
- ...cloneLink(link),
20901
- status: patch.status ?? link.status,
20902
- lastEventAt: pickPatchedValue(patch, 'lastEventAt', link.lastEventAt),
20903
- lastDispatchTraceId: pickPatchedValue(patch, 'lastDispatchTraceId', link.lastDispatchTraceId),
20904
- lastDeliveredValuePreview: pickPatchedValue(patch, 'lastDeliveredValuePreview', link.lastDeliveredValuePreview),
20905
- diagnostics: cloneDiagnostics$1(patch.diagnostics ?? link.diagnostics),
20906
- };
21689
+ const next = cloneLink(link);
21690
+ next.status = patch.status ?? link.status;
21691
+ setOptionalLinkValue(next, 'lastEventAt', pickPatchedValue(patch, 'lastEventAt', link.lastEventAt));
21692
+ setOptionalLinkValue(next, 'lastDispatchTraceId', pickPatchedValue(patch, 'lastDispatchTraceId', link.lastDispatchTraceId));
21693
+ setOptionalLinkValue(next, 'lastDeliveredValuePreview', pickPatchedValue(patch, 'lastDeliveredValuePreview', link.lastDeliveredValuePreview));
21694
+ next.diagnostics = cloneDiagnostics$1(patch.diagnostics ?? link.diagnostics);
21695
+ return next;
20907
21696
  });
20908
21697
  }
20909
21698
  function pickPatchedValue(patch, key, fallback) {
@@ -20915,12 +21704,24 @@ function cloneLinks(links) {
20915
21704
  return links.map((link) => cloneLink(link));
20916
21705
  }
20917
21706
  function cloneLink(link) {
20918
- return {
20919
- ...link,
21707
+ const next = {
21708
+ linkId: link.linkId,
21709
+ status: link.status,
20920
21710
  source: { ...link.source },
20921
21711
  target: { ...link.target },
20922
21712
  diagnostics: cloneDiagnostics$1(link.diagnostics),
20923
21713
  };
21714
+ setOptionalLinkValue(next, 'lastEventAt', link.lastEventAt);
21715
+ setOptionalLinkValue(next, 'lastDispatchTraceId', link.lastDispatchTraceId);
21716
+ setOptionalLinkValue(next, 'lastDeliveredValuePreview', link.lastDeliveredValuePreview);
21717
+ return next;
21718
+ }
21719
+ function setOptionalLinkValue(link, key, value) {
21720
+ if (value === undefined) {
21721
+ delete link[key];
21722
+ return;
21723
+ }
21724
+ link[key] = value;
20924
21725
  }
20925
21726
  function cloneDiagnostics$1(diagnostics) {
20926
21727
  return diagnostics.map((diagnostic) => ({
@@ -22821,6 +23622,9 @@ const DYNAMIC_WIDGET_PAGE_I18N_CONFIG = {
22821
23622
  [DYNAMIC_WIDGET_PAGE_I18N_NAMESPACE]: {
22822
23623
  'pt-BR': {
22823
23624
  'controls.pageSettings': 'Configurar página',
23625
+ 'controls.widgetSettings': 'Configurar widget',
23626
+ 'controls.widgetSettingsTooltip': 'Abrir configurações do widget',
23627
+ 'controls.cardSettings': 'Configurar card',
22824
23628
  'controls.widgetLayoutToolbar': 'Ações de layout do widget',
22825
23629
  'controls.dragWidget': 'Arrastar widget',
22826
23630
  'controls.resizeWidget': 'Redimensionar widget',
@@ -22841,6 +23645,9 @@ const DYNAMIC_WIDGET_PAGE_I18N_CONFIG = {
22841
23645
  },
22842
23646
  'en-US': {
22843
23647
  'controls.pageSettings': 'Configure page',
23648
+ 'controls.widgetSettings': 'Configure widget',
23649
+ 'controls.widgetSettingsTooltip': 'Open widget settings',
23650
+ 'controls.cardSettings': 'Configure card',
22844
23651
  'controls.widgetLayoutToolbar': 'Widget layout actions',
22845
23652
  'controls.dragWidget': 'Drag widget',
22846
23653
  'controls.resizeWidget': 'Resize widget',
@@ -23062,50 +23869,79 @@ class DynamicWidgetPageComponent {
23062
23869
  globalActions = inject(GlobalActionService);
23063
23870
  storage = inject(ASYNC_CONFIG_STORAGE);
23064
23871
  componentKeys = inject(ComponentKeyService);
23872
+ componentMetadata = inject(ComponentMetadataRegistry, {
23873
+ optional: true,
23874
+ });
23065
23875
  i18n = inject(PraxisI18nService);
23066
- route = (() => { try {
23067
- return inject(ActivatedRoute);
23068
- }
23069
- catch {
23070
- return undefined;
23071
- } })();
23876
+ route = (() => {
23877
+ try {
23878
+ return inject(ActivatedRoute);
23879
+ }
23880
+ catch {
23881
+ return undefined;
23882
+ }
23883
+ })();
23072
23884
  conn = inject(ConnectionManagerService);
23073
23885
  stateRuntime = inject(WidgetPageStateRuntimeService);
23074
- settingsPanel = inject(SETTINGS_PANEL_BRIDGE, { optional: true });
23075
- defaultShellEditor = inject(DYNAMIC_PAGE_SHELL_EDITOR, { optional: true });
23076
- defaultPageEditor = inject(DYNAMIC_PAGE_CONFIG_EDITOR, { optional: true });
23886
+ settingsPanel = inject(SETTINGS_PANEL_BRIDGE, {
23887
+ optional: true,
23888
+ });
23889
+ defaultShellEditor = inject(DYNAMIC_PAGE_SHELL_EDITOR, {
23890
+ optional: true,
23891
+ });
23892
+ defaultPageEditor = inject(DYNAMIC_PAGE_CONFIG_EDITOR, {
23893
+ optional: true,
23894
+ });
23077
23895
  constructor() { }
23078
23896
  ngOnDestroy() {
23079
23897
  this.compositionRuntime.destroy();
23080
23898
  }
23081
23899
  ngOnChanges(changes) {
23082
- if (changes['page'] || changes['context'] || changes['enableCustomization']) {
23900
+ if (changes['page'] ||
23901
+ changes['context'] ||
23902
+ changes['enableCustomization']) {
23083
23903
  const parsed = this.parsePage(this.page);
23084
23904
  const resolvedPage = parsed ? this.resolvePagePresets(parsed) : parsed;
23085
23905
  this.assertNoLegacyConnections(resolvedPage);
23086
23906
  this.widgetDiagnostics = {};
23087
23907
  this.widgetDiagnosticsChange.emit({});
23088
- this.pageDefinition = resolvedPage ? { ...resolvedPage, state: this.stateRuntime.normalizeState(resolvedPage.state) } : resolvedPage;
23908
+ this.pageDefinition = resolvedPage
23909
+ ? {
23910
+ ...resolvedPage,
23911
+ state: this.stateRuntime.normalizeState(resolvedPage.state),
23912
+ }
23913
+ : resolvedPage;
23089
23914
  this.pageRuntime = this.buildStateRuntime(this.pageDefinition?.state, this.pageDefinition?.context);
23090
23915
  this.pageState = this.pageRuntime.state;
23091
23916
  const bootstrapSnapshot = this.bootstrapCompositionAdapter(this.pageDefinition);
23092
23917
  const rawWidgets = this.pageDefinition?.widgets || [];
23093
23918
  let widgets = this.applyEditShellActions(rawWidgets);
23094
23919
  widgets = this.applyBootstrapCompositionHydration(widgets, bootstrapSnapshot);
23095
- this.pageDefinition = this.pageDefinition ? { ...this.pageDefinition, widgets } : this.pageDefinition;
23920
+ this.pageDefinition = this.pageDefinition
23921
+ ? { ...this.pageDefinition, widgets }
23922
+ : this.pageDefinition;
23096
23923
  this.page = this.pageDefinition;
23097
23924
  this.applyResponsivePresentation(this.pageDefinition, widgets, this.pageRuntime);
23098
23925
  this.reportStateDiagnostics(this.pageRuntime.diagnostics);
23099
23926
  }
23100
- if (this.autoPersist && (changes['pageIdentity'] || changes['componentInstanceId'])) {
23927
+ if (this.autoPersist &&
23928
+ (changes['pageIdentity'] || changes['componentInstanceId'])) {
23101
23929
  this.appliedPersisted = false;
23102
23930
  this.persistenceReady = false;
23103
23931
  }
23104
- if (this.autoPersist && !this.appliedPersisted && (changes['page'] || changes['context'] || changes['pageIdentity'] || changes['componentInstanceId'])) {
23932
+ if (this.autoPersist &&
23933
+ !this.appliedPersisted &&
23934
+ (changes['page'] ||
23935
+ changes['context'] ||
23936
+ changes['pageIdentity'] ||
23937
+ changes['componentInstanceId'])) {
23105
23938
  this.appliedPersisted = true;
23106
23939
  this.loadPersistedPage();
23107
23940
  }
23108
- if (this.autoPersist && this.persistenceReady && changes['page'] && !this.isHydrating) {
23941
+ if (this.autoPersist &&
23942
+ this.persistenceReady &&
23943
+ changes['page'] &&
23944
+ !this.isHydrating) {
23109
23945
  const parsed = this.parsePage(this.page);
23110
23946
  if (parsed)
23111
23947
  this.savePage(parsed);
@@ -23116,13 +23952,19 @@ class DynamicWidgetPageComponent {
23116
23952
  return;
23117
23953
  }
23118
23954
  const page = this.ensurePageDefinition();
23119
- const cycle = this.dispatchWidgetEventToComposition(page, fromKey, evt);
23120
- if (!cycle || !cycle.matchedLinkIds.length)
23955
+ const widgetInputPatchResult = this.applyWidgetInputPatchToPage(page, fromKey, evt?.payload);
23956
+ const pageWithPatchedInputs = widgetInputPatchResult.page;
23957
+ const cycle = this.dispatchWidgetEventToComposition(pageWithPatchedInputs, fromKey, evt);
23958
+ if (!cycle || !cycle.matchedLinkIds.length) {
23959
+ if (widgetInputPatchResult.changed) {
23960
+ this.applyPageUpdate(pageWithPatchedInputs, true, undefined, false, true);
23961
+ }
23121
23962
  return;
23122
- const state = this.stateFromCompositionSnapshot(page.state, cycle.snapshot.state.primaryValues);
23963
+ }
23964
+ const state = this.stateFromCompositionSnapshot(pageWithPatchedInputs.state, cycle.snapshot.state.primaryValues);
23123
23965
  const runtimeStatePaths = Array.from(new Set((cycle.snapshot.state.changedPaths || []).filter((path) => typeof path === 'string')));
23124
- const updatedPrimaryStatePaths = runtimeStatePaths.filter((path) => (!this.areStateValuesEqual(this.conn.extractByPath(this.stateRuntime.normalizeState(page.state).values || {}, path), this.conn.extractByPath(state.values || {}, path))));
23125
- let widgets = this.cloneWidgets(page.widgets || []);
23966
+ const updatedPrimaryStatePaths = runtimeStatePaths.filter((path) => !this.areStateValuesEqual(this.conn.extractByPath(this.stateRuntime.normalizeState(page.state).values || {}, path), this.conn.extractByPath(state.values || {}, path)));
23967
+ let widgets = this.cloneWidgets(pageWithPatchedInputs.widgets || []);
23126
23968
  const directDelivery = this.applyCompositionWidgetDeliveries(widgets, cycle);
23127
23969
  widgets = directDelivery.widgets;
23128
23970
  const projectedWidgets = this.compositionRuntime.projectStateWidgetInputs(this.compositionDefinition, {
@@ -23132,11 +23974,68 @@ class DynamicWidgetPageComponent {
23132
23974
  }).widgets;
23133
23975
  const stateProjectionChanged = !this.areStateValuesEqual(widgets, projectedWidgets);
23134
23976
  widgets = projectedWidgets;
23135
- const nextRuntime = this.buildStateRuntime(state, page.context);
23136
- if (!updatedPrimaryStatePaths.length && !directDelivery.changed && !stateProjectionChanged) {
23977
+ const nextRuntime = this.buildStateRuntime(state, pageWithPatchedInputs.context);
23978
+ if (!updatedPrimaryStatePaths.length &&
23979
+ !directDelivery.changed &&
23980
+ !stateProjectionChanged &&
23981
+ !widgetInputPatchResult.changed) {
23137
23982
  return;
23138
23983
  }
23139
- this.applyPageUpdate({ ...page, widgets, state }, true, nextRuntime, false);
23984
+ this.applyPageUpdate({ ...pageWithPatchedInputs, widgets, state }, true, nextRuntime, false);
23985
+ }
23986
+ applyWidgetInputPatchToPage(page, widgetKey, payload) {
23987
+ const inputPatch = this.extractWidgetInputPatch(payload);
23988
+ if (!inputPatch) {
23989
+ return { page, changed: false };
23990
+ }
23991
+ const widgets = this.cloneWidgets(page.widgets || []);
23992
+ const widgetIndex = widgets.findIndex((widget) => widget.key === widgetKey);
23993
+ if (widgetIndex < 0) {
23994
+ return { page, changed: false };
23995
+ }
23996
+ const currentInputs = this.cloneStateValues(widgets[widgetIndex].definition.inputs || {});
23997
+ let nextInputs = currentInputs;
23998
+ let patchChanged = false;
23999
+ for (const [path, value] of Object.entries(inputPatch)) {
24000
+ const normalizedPath = typeof path === 'string' ? path.trim() : '';
24001
+ if (!normalizedPath) {
24002
+ continue;
24003
+ }
24004
+ const candidateInputs = this.conn.setValueAtPath(nextInputs, normalizedPath, this.cloneStateValues(value));
24005
+ if (!this.areStateValuesEqual(nextInputs, candidateInputs)) {
24006
+ nextInputs = candidateInputs;
24007
+ patchChanged = true;
24008
+ }
24009
+ }
24010
+ if (!patchChanged) {
24011
+ return { page, changed: false };
24012
+ }
24013
+ widgets[widgetIndex] = {
24014
+ ...widgets[widgetIndex],
24015
+ definition: {
24016
+ ...widgets[widgetIndex].definition,
24017
+ inputs: nextInputs,
24018
+ },
24019
+ };
24020
+ return {
24021
+ page: {
24022
+ ...page,
24023
+ widgets,
24024
+ },
24025
+ changed: true,
24026
+ };
24027
+ }
24028
+ extractWidgetInputPatch(payload) {
24029
+ if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
24030
+ return null;
24031
+ }
24032
+ const candidate = payload.inputPatch;
24033
+ if (!candidate ||
24034
+ typeof candidate !== 'object' ||
24035
+ Array.isArray(candidate)) {
24036
+ return null;
24037
+ }
24038
+ return candidate;
23140
24039
  }
23141
24040
  buildStateRuntime(state, pageContext) {
23142
24041
  return this.stateRuntime.buildRuntimeSnapshot(state, this.buildStateContext(pageContext));
@@ -23151,12 +24050,26 @@ class DynamicWidgetPageComponent {
23151
24050
  }
23152
24051
  applyEditShellActions(widgets) {
23153
24052
  return this.cloneWidgets(widgets).map((widget) => {
23154
- if (!this.shouldInjectWidgetSettings(widget)) {
24053
+ if (!this.shouldInjectEditShellActions(widget)) {
23155
24054
  return widget;
23156
24055
  }
23157
24056
  const existingActions = widget.shell?.actions || [];
23158
- if (existingActions.some((action) => action.id === 'widget-settings')) {
23159
- return widget;
24057
+ const metadata = this.componentMetadata?.get(widget.definition?.id || '');
24058
+ const nextActions = [...existingActions];
24059
+ if (metadata?.configEditor &&
24060
+ !nextActions.some((action) => action.id === 'component-settings')) {
24061
+ nextActions.push({
24062
+ id: 'component-settings',
24063
+ icon: 'tune',
24064
+ variant: 'icon',
24065
+ placement: 'header',
24066
+ label: this.t('controls.componentSettings', 'Configurar conteudo'),
24067
+ tooltip: this.t('controls.componentSettingsTooltip', 'Abrir configuracoes do componente'),
24068
+ });
24069
+ }
24070
+ if (nextActions.some((action) => action.id === 'widget-settings') ||
24071
+ !this.canOpenWidgetShellSettings()) {
24072
+ return this.withShellActions(widget, nextActions);
23160
24073
  }
23161
24074
  const widgetSettingsAction = {
23162
24075
  id: 'widget-settings',
@@ -23166,15 +24079,23 @@ class DynamicWidgetPageComponent {
23166
24079
  label: this.t('controls.widgetSettings', 'Configurar widget'),
23167
24080
  tooltip: this.t('controls.widgetSettingsTooltip', 'Abrir configurações do widget'),
23168
24081
  };
23169
- return {
23170
- ...widget,
23171
- shell: {
23172
- ...(widget.shell || {}),
23173
- actions: [...existingActions, widgetSettingsAction],
23174
- },
23175
- };
24082
+ return this.withShellActions(widget, [...nextActions, widgetSettingsAction]);
23176
24083
  });
23177
24084
  }
24085
+ withShellActions(widget, actions) {
24086
+ const existingActions = widget.shell?.actions || [];
24087
+ if (existingActions.length === actions.length &&
24088
+ existingActions.every((action, index) => action === actions[index])) {
24089
+ return widget;
24090
+ }
24091
+ return {
24092
+ ...widget,
24093
+ shell: {
24094
+ ...(widget.shell || {}),
24095
+ actions,
24096
+ },
24097
+ };
24098
+ }
23178
24099
  applyBootstrapCompositionHydration(widgets, bootstrapSnapshot) {
23179
24100
  if (!this.compositionDefinition || !bootstrapSnapshot) {
23180
24101
  return this.cloneWidgets(widgets);
@@ -23196,10 +24117,10 @@ class DynamicWidgetPageComponent {
23196
24117
  return undefined;
23197
24118
  const definition = this.compositionDefinition ?? this.compositionFactory.create(page);
23198
24119
  this.compositionDefinition = definition;
23199
- if (!definition.links.some((link) => (link.from.kind === 'component-port'
23200
- && link.from.ref.widget === fromKey
23201
- && link.from.ref.port === output
23202
- && link.from.ref.direction === 'output'))) {
24120
+ if (!definition.links.some((link) => link.from.kind === 'component-port' &&
24121
+ link.from.ref.widget === fromKey &&
24122
+ link.from.ref.port === output &&
24123
+ link.from.ref.direction === 'output')) {
23203
24124
  return undefined;
23204
24125
  }
23205
24126
  let payload;
@@ -23242,12 +24163,15 @@ class DynamicWidgetPageComponent {
23242
24163
  };
23243
24164
  }
23244
24165
  const linksById = new Map(this.compositionDefinition.links.map((link) => [link.id, link]));
23245
- const runtimeLinks = cycle.snapshot.links.filter((link) => (link.lastDispatchTraceId === cycle.cycleId && link.status === 'delivered'));
24166
+ const runtimeLinks = cycle.snapshot.links.filter((link) => link.lastDispatchTraceId === cycle.cycleId &&
24167
+ link.status === 'delivered');
23246
24168
  let nextWidgets = this.cloneWidgets(widgets);
23247
24169
  let changed = false;
23248
24170
  for (const runtimeLink of runtimeLinks) {
23249
24171
  const link = linksById.get(runtimeLink.linkId);
23250
- if (!link || link.from.kind === 'state' || link.to.kind !== 'component-port') {
24172
+ if (!link ||
24173
+ link.from.kind === 'state' ||
24174
+ link.to.kind !== 'component-port') {
23251
24175
  continue;
23252
24176
  }
23253
24177
  const targetRef = link.to.ref;
@@ -23324,13 +24248,13 @@ class DynamicWidgetPageComponent {
23324
24248
  if (!normalizedPortId) {
23325
24249
  return normalizedBindingPath;
23326
24250
  }
23327
- if (normalizedBindingPath === normalizedPortId
23328
- || normalizedBindingPath.startsWith(`${normalizedPortId}.`)
23329
- || normalizedBindingPath.startsWith(`${normalizedPortId}[`)) {
24251
+ if (normalizedBindingPath === normalizedPortId ||
24252
+ normalizedBindingPath.startsWith(`${normalizedPortId}.`) ||
24253
+ normalizedBindingPath.startsWith(`${normalizedPortId}[`)) {
23330
24254
  return normalizedBindingPath;
23331
24255
  }
23332
- if (normalizedBindingPath.startsWith('.')
23333
- || normalizedBindingPath.startsWith('[')) {
24256
+ if (normalizedBindingPath.startsWith('.') ||
24257
+ normalizedBindingPath.startsWith('[')) {
23334
24258
  return `${normalizedPortId}${normalizedBindingPath}`;
23335
24259
  }
23336
24260
  return `${normalizedPortId}.${normalizedBindingPath}`;
@@ -23343,15 +24267,15 @@ class DynamicWidgetPageComponent {
23343
24267
  }
23344
24268
  return `widget:${fromKey}:${output}:${timestamp}:${sequence}`;
23345
24269
  }
23346
- shouldInjectWidgetSettings(widget) {
24270
+ shouldInjectEditShellActions(widget) {
23347
24271
  if (!this.enableCustomization || !this.settingsPanel) {
23348
24272
  return false;
23349
24273
  }
23350
- if (!(this.shellEditorComponent || this.defaultShellEditor)) {
23351
- return false;
23352
- }
23353
24274
  return !!widget.shell && widget.shell.kind !== 'none';
23354
24275
  }
24276
+ canOpenWidgetShellSettings() {
24277
+ return !!(this.shellEditorComponent || this.defaultShellEditor);
24278
+ }
23355
24279
  areStateValuesEqual(left, right) {
23356
24280
  if (left === right)
23357
24281
  return true;
@@ -23369,8 +24293,8 @@ class DynamicWidgetPageComponent {
23369
24293
  const rightKeys = Object.keys(right);
23370
24294
  if (leftKeys.length !== rightKeys.length)
23371
24295
  return false;
23372
- return leftKeys.every((key) => (Object.prototype.hasOwnProperty.call(right, key)
23373
- && this.areStateValuesEqual(left[key], right[key])));
24296
+ return leftKeys.every((key) => Object.prototype.hasOwnProperty.call(right, key) &&
24297
+ this.areStateValuesEqual(left[key], right[key]));
23374
24298
  }
23375
24299
  return false;
23376
24300
  }
@@ -23388,6 +24312,10 @@ class DynamicWidgetPageComponent {
23388
24312
  this.widgetDiagnosticsChange.emit({ ...this.widgetDiagnostics });
23389
24313
  }
23390
24314
  onShellAction(fromKey, evt) {
24315
+ if (evt.id === 'component-settings') {
24316
+ this.openWidgetComponentSettings(fromKey);
24317
+ return;
24318
+ }
23391
24319
  if (evt.id === 'widget-settings') {
23392
24320
  this.openWidgetShellSettings(fromKey);
23393
24321
  return;
@@ -23523,7 +24451,7 @@ class DynamicWidgetPageComponent {
23523
24451
  const uiShell = page.context?.ui?.shell || {};
23524
24452
  const ref = this.settingsPanel.open({
23525
24453
  id: `dynamic-page-shell:${key}`,
23526
- title: 'Configurar Card',
24454
+ title: this.t('controls.cardSettings', 'Configurar card'),
23527
24455
  content: {
23528
24456
  component: editor,
23529
24457
  inputs: {
@@ -23538,6 +24466,55 @@ class DynamicWidgetPageComponent {
23538
24466
  ref.applied$.subscribe((result) => this.applyWidgetShell(key, result, false));
23539
24467
  ref.saved$.subscribe((result) => this.applyWidgetShell(key, result, true));
23540
24468
  }
24469
+ openWidgetComponentSettings(key) {
24470
+ if (!this.settingsPanel)
24471
+ return;
24472
+ const page = this.ensurePageDefinition();
24473
+ const widget = page.widgets.find((w) => w.key === key);
24474
+ if (!widget)
24475
+ return;
24476
+ const metadata = this.componentMetadata?.get(widget.definition?.id || '');
24477
+ const editor = metadata?.configEditor?.component;
24478
+ if (!editor)
24479
+ return;
24480
+ const ref = this.settingsPanel.open({
24481
+ id: `dynamic-page-component:${key}`,
24482
+ title: metadata.configEditor?.title ||
24483
+ metadata.friendlyName ||
24484
+ this.t('controls.componentSettings', 'Configurar conteudo'),
24485
+ content: {
24486
+ component: editor,
24487
+ inputs: {
24488
+ inputs: this.cloneStateValues(widget.definition.inputs || {}),
24489
+ widgetKey: key,
24490
+ widgetType: widget.definition?.id,
24491
+ },
24492
+ },
24493
+ });
24494
+ ref.applied$.subscribe((result) => this.applyWidgetComponentInputs(key, result, false));
24495
+ ref.saved$.subscribe((result) => this.applyWidgetComponentInputs(key, result, true));
24496
+ }
24497
+ applyWidgetComponentInputs(key, result, persist) {
24498
+ if (!result || typeof result !== 'object' || Array.isArray(result))
24499
+ return;
24500
+ const nextInputs = 'inputs' in result &&
24501
+ result.inputs &&
24502
+ typeof result.inputs === 'object' &&
24503
+ !Array.isArray(result.inputs)
24504
+ ? result.inputs
24505
+ : result;
24506
+ const page = this.ensurePageDefinition();
24507
+ const widgets = page.widgets.map((w) => w.key === key
24508
+ ? {
24509
+ ...w,
24510
+ definition: {
24511
+ ...w.definition,
24512
+ inputs: this.cloneStateValues(nextInputs),
24513
+ },
24514
+ }
24515
+ : w);
24516
+ this.applyPageUpdate({ ...page, widgets }, persist);
24517
+ }
23541
24518
  openPageSettings() {
23542
24519
  if (!this.settingsPanel)
23543
24520
  return;
@@ -23548,7 +24525,7 @@ class DynamicWidgetPageComponent {
23548
24525
  const uiShell = page.context?.ui?.shell || {};
23549
24526
  const ref = this.settingsPanel.open({
23550
24527
  id: 'dynamic-page-settings',
23551
- title: 'Configurar Página',
24528
+ title: this.t('controls.pageSettings', 'Configurar página'),
23552
24529
  content: {
23553
24530
  component: editor,
23554
24531
  inputs: {
@@ -23566,7 +24543,7 @@ class DynamicWidgetPageComponent {
23566
24543
  if (!result)
23567
24544
  return;
23568
24545
  const page = this.ensurePageDefinition();
23569
- const widgets = page.widgets.map((w) => (w.key === key ? { ...w, shell: result.shell ?? null } : w));
24546
+ const widgets = page.widgets.map((w) => w.key === key ? { ...w, shell: result.shell ?? null } : w);
23570
24547
  let context = page.context || {};
23571
24548
  if (result.applyToAll && result.pagePreset) {
23572
24549
  const ui = { ...context.ui };
@@ -23610,28 +24587,33 @@ class DynamicWidgetPageComponent {
23610
24587
  themePreset: themePreset || undefined,
23611
24588
  }, persist);
23612
24589
  }
23613
- applyPageUpdate(next, persist = true, runtime = this.buildStateRuntime(next.state, next.context), syncCompositionAdapter = true) {
24590
+ applyPageUpdate(next, persist = true, runtime = this.buildStateRuntime(next.state, next.context), syncCompositionAdapter = true, skipStateWidgetProjection = false) {
23614
24591
  this.assertNoLegacyConnections(next);
23615
24592
  const normalized = { ...next, state: runtime.state };
23616
24593
  const normalizedWidgets = this.applyEditShellActions(normalized.widgets || []);
23617
24594
  const bootstrapSnapshot = syncCompositionAdapter
23618
24595
  ? this.bootstrapCompositionAdapter(normalized)
23619
24596
  : undefined;
23620
- const stateBoundWidgets = bootstrapSnapshot
23621
- ? this.applyBootstrapCompositionHydration(normalizedWidgets, bootstrapSnapshot)
23622
- : this.compositionDefinition
23623
- ? this.compositionRuntime.projectStateWidgetInputs(this.compositionDefinition, {
23624
- widgets: normalizedWidgets,
23625
- state: {
23626
- primaryValues: this.cloneStateValues(runtime.primaryValues),
23627
- derivedValues: this.cloneStateValues(runtime.derivedValues),
23628
- transientValues: {},
23629
- changedPaths: [],
23630
- diagnostics: [],
23631
- },
23632
- }).widgets
23633
- : normalizedWidgets;
23634
- const hydrated = this.resolvePagePresets({ ...normalized, widgets: stateBoundWidgets });
24597
+ const stateBoundWidgets = skipStateWidgetProjection
24598
+ ? normalizedWidgets
24599
+ : bootstrapSnapshot
24600
+ ? this.applyBootstrapCompositionHydration(normalizedWidgets, bootstrapSnapshot)
24601
+ : this.compositionDefinition
24602
+ ? this.compositionRuntime.projectStateWidgetInputs(this.compositionDefinition, {
24603
+ widgets: normalizedWidgets,
24604
+ state: {
24605
+ primaryValues: this.cloneStateValues(runtime.primaryValues),
24606
+ derivedValues: this.cloneStateValues(runtime.derivedValues),
24607
+ transientValues: {},
24608
+ changedPaths: [],
24609
+ diagnostics: [],
24610
+ },
24611
+ }).widgets
24612
+ : normalizedWidgets;
24613
+ const hydrated = this.resolvePagePresets({
24614
+ ...normalized,
24615
+ widgets: stateBoundWidgets,
24616
+ });
23635
24617
  this.pageDefinition = hydrated;
23636
24618
  this.page = hydrated;
23637
24619
  this.pageState = runtime.state;
@@ -23661,21 +24643,28 @@ class DynamicWidgetPageComponent {
23661
24643
  this.pageColumnCount = Math.max(1, Number(canvas.columns) || 1);
23662
24644
  this.gridTemplateColumns = `repeat(${this.pageColumnCount}, minmax(0, 1fr))`;
23663
24645
  this.pageGap = canvas.gap || fallbackLayout?.gap || '16px';
23664
- this.gridAutoRows = canvas.autoRows === 'content' ? 'auto' : (canvas.rowUnit || '88px');
24646
+ this.gridAutoRows =
24647
+ canvas.autoRows === 'content' ? 'auto' : canvas.rowUnit || '88px';
23665
24648
  }
23666
24649
  mergeContext(pageContext, inputContext, runtime, pageDefinition) {
23667
24650
  const baseContext = this.buildStateContext(pageContext);
23668
24651
  const themePresetId = pageDefinition?.themePreset || '';
23669
- const themePreset = themePresetId ? BUILTIN_PAGE_THEME_PRESETS[themePresetId] : undefined;
24652
+ const themePreset = themePresetId
24653
+ ? BUILTIN_PAGE_THEME_PRESETS[themePresetId]
24654
+ : undefined;
23670
24655
  const layoutPresetId = pageDefinition?.layoutPreset || '';
23671
- const layoutPreset = layoutPresetId ? BUILTIN_PAGE_LAYOUT_PRESETS[layoutPresetId] : undefined;
24656
+ const layoutPreset = layoutPresetId
24657
+ ? BUILTIN_PAGE_LAYOUT_PRESETS[layoutPresetId]
24658
+ : undefined;
23672
24659
  return {
23673
24660
  ...baseContext,
23674
24661
  ...(inputContext || {}),
23675
24662
  pageDeviceKind: this.resolveDeviceKind(),
23676
24663
  pageLayoutPreset: layoutPreset || null,
23677
24664
  pageThemePreset: themePreset || null,
23678
- pageCanvas: pageDefinition?.canvas ? this.cloneStateValues(pageDefinition.canvas) : null,
24665
+ pageCanvas: pageDefinition?.canvas
24666
+ ? this.cloneStateValues(pageDefinition.canvas)
24667
+ : null,
23679
24668
  pageGrouping: this.cloneGrouping(pageDefinition?.grouping),
23680
24669
  pageState: this.cloneStateValues(runtime.primaryValues),
23681
24670
  pageStateDerived: this.cloneStateValues(runtime.derivedValues),
@@ -23782,7 +24771,10 @@ class DynamicWidgetPageComponent {
23782
24771
  const parsed = this.parsePage(this.page);
23783
24772
  if (parsed)
23784
24773
  return this.resolvePagePresets(parsed);
23785
- return { widgets: this.widgets(), state: this.stateRuntime.normalizeState(this.pageState) };
24774
+ return {
24775
+ widgets: this.widgets(),
24776
+ state: this.stateRuntime.normalizeState(this.pageState),
24777
+ };
23786
24778
  }
23787
24779
  parsePage(input) {
23788
24780
  if (!input)
@@ -23801,10 +24793,14 @@ class DynamicWidgetPageComponent {
23801
24793
  return input;
23802
24794
  }
23803
24795
  resolvePagePresets(page) {
23804
- const preset = page.layoutPreset ? BUILTIN_PAGE_LAYOUT_PRESETS[page.layoutPreset] : undefined;
24796
+ const preset = page.layoutPreset
24797
+ ? BUILTIN_PAGE_LAYOUT_PRESETS[page.layoutPreset]
24798
+ : undefined;
23805
24799
  const themePresetId = page.themePreset || preset?.defaultThemePreset;
23806
24800
  const mergedLayout = this.mergeLayout(preset?.defaultLayout, page.layout);
23807
- const grouping = (page.grouping && page.grouping.length ? page.grouping : preset?.defaultGrouping) || undefined;
24801
+ const grouping = (page.grouping && page.grouping.length
24802
+ ? page.grouping
24803
+ : preset?.defaultGrouping) || undefined;
23808
24804
  return {
23809
24805
  ...page,
23810
24806
  layout: mergedLayout,
@@ -23851,7 +24847,9 @@ class DynamicWidgetPageComponent {
23851
24847
  const widgetsWithOverrides = canvas
23852
24848
  ? this.applyCanvasLayoutToWidgets(baseWidgets, canvas)
23853
24849
  : baseWidgets;
23854
- const groups = canvas ? [] : this.buildRenderedGroups(grouping, widgetsWithOverrides);
24850
+ const groups = canvas
24851
+ ? []
24852
+ : this.buildRenderedGroups(grouping, widgetsWithOverrides);
23855
24853
  return {
23856
24854
  layout,
23857
24855
  canvas,
@@ -23915,11 +24913,20 @@ class DynamicWidgetPageComponent {
23915
24913
  isCanvasMode() {
23916
24914
  return !!this.canvas;
23917
24915
  }
24916
+ shouldAutoWireOutputs(widget) {
24917
+ if (this.enableCustomization) {
24918
+ return true;
24919
+ }
24920
+ return widget?.definition?.inputs?.['enableCustomization'] === true;
24921
+ }
23918
24922
  selectCanvasWidget(widgetKey) {
24923
+ if (!this.enableCustomization)
24924
+ return;
23919
24925
  if (this.selectedCanvasWidgetKey !== widgetKey) {
23920
24926
  this.selectedCanvasWidgetKey = widgetKey;
23921
24927
  }
23922
- if (this.blockedCanvasWidgetKey && this.blockedCanvasWidgetKey !== widgetKey) {
24928
+ if (this.blockedCanvasWidgetKey &&
24929
+ this.blockedCanvasWidgetKey !== widgetKey) {
23923
24930
  this.blockedCanvasWidgetKey = null;
23924
24931
  }
23925
24932
  }
@@ -23988,7 +24995,12 @@ class DynamicWidgetPageComponent {
23988
24995
  startPage: this.clonePageDefinition(this.ensurePageDefinition()),
23989
24996
  startX: 0,
23990
24997
  startY: 0,
23991
- startItem: { ...item, constraints: item.constraints ? { ...item.constraints } : undefined },
24998
+ startItem: {
24999
+ ...item,
25000
+ constraints: item.constraints
25001
+ ? { ...item.constraints }
25002
+ : undefined,
25003
+ },
23992
25004
  columns,
23993
25005
  columnWidth: 1,
23994
25006
  rowHeight: 1,
@@ -24007,7 +25019,9 @@ class DynamicWidgetPageComponent {
24007
25019
  ...widget,
24008
25020
  renderClassName,
24009
25021
  renderSpan: override?.span,
24010
- __order: typeof override?.order === 'number' ? override.order : Number.MAX_SAFE_INTEGER,
25022
+ __order: typeof override?.order === 'number'
25023
+ ? override.order
25024
+ : Number.MAX_SAFE_INTEGER,
24011
25025
  };
24012
25026
  })
24013
25027
  .filter((widget) => !!widget)
@@ -24047,7 +25061,9 @@ class DynamicWidgetPageComponent {
24047
25061
  if (!item || !metrics)
24048
25062
  return;
24049
25063
  const pageSnapshot = this.clonePageDefinition(this.ensurePageDefinition());
24050
- const pointerTarget = event.currentTarget instanceof HTMLElement ? event.currentTarget : undefined;
25064
+ const pointerTarget = event.currentTarget instanceof HTMLElement
25065
+ ? event.currentTarget
25066
+ : undefined;
24051
25067
  if (pointerTarget?.setPointerCapture) {
24052
25068
  try {
24053
25069
  pointerTarget.setPointerCapture(event.pointerId);
@@ -24062,7 +25078,10 @@ class DynamicWidgetPageComponent {
24062
25078
  startPage: pageSnapshot,
24063
25079
  startX: event.clientX,
24064
25080
  startY: event.clientY,
24065
- startItem: { ...item, constraints: item.constraints ? { ...item.constraints } : undefined },
25081
+ startItem: {
25082
+ ...item,
25083
+ constraints: item.constraints ? { ...item.constraints } : undefined,
25084
+ },
24066
25085
  columns: metrics.columns,
24067
25086
  columnWidth: metrics.columnWidth,
24068
25087
  rowHeight: metrics.rowHeight,
@@ -24081,7 +25100,7 @@ class DynamicWidgetPageComponent {
24081
25100
  const rect = host.getBoundingClientRect();
24082
25101
  const gap = this.parseCssPixelValue(this.pageGap, 16);
24083
25102
  const columns = Math.max(1, Number(canvas.columns) || 1);
24084
- const availableWidth = Math.max(1, rect.width - (gap * Math.max(0, columns - 1)));
25103
+ const availableWidth = Math.max(1, rect.width - gap * Math.max(0, columns - 1));
24085
25104
  const columnWidth = availableWidth / columns;
24086
25105
  const rowHeight = canvas.autoRows === 'content'
24087
25106
  ? this.parseCssPixelValue(canvas.rowUnit || '88px', 88)
@@ -24114,7 +25133,9 @@ class DynamicWidgetPageComponent {
24114
25133
  return { changed: false, blocked: false };
24115
25134
  const candidate = this.normalizeCanvasItem(updater({
24116
25135
  ...current,
24117
- constraints: current.constraints ? { ...current.constraints } : undefined,
25136
+ constraints: current.constraints
25137
+ ? { ...current.constraints }
25138
+ : undefined,
24118
25139
  }), effectiveCanvas?.columns || page.canvas.columns || 1);
24119
25140
  const collisionPolicy = effectiveCanvas
24120
25141
  ? this.resolveCanvasCollisionPolicy(effectiveCanvas, interactionKind)
@@ -24126,7 +25147,12 @@ class DynamicWidgetPageComponent {
24126
25147
  if (blocked) {
24127
25148
  this.blockedCanvasWidgetKey = widgetKey;
24128
25149
  this.transientCanvasItemsState.set({});
24129
- this.canvasPreviewState.set({ ...candidate, constraints: candidate.constraints ? { ...candidate.constraints } : undefined });
25150
+ this.canvasPreviewState.set({
25151
+ ...candidate,
25152
+ constraints: candidate.constraints
25153
+ ? { ...candidate.constraints }
25154
+ : undefined,
25155
+ });
24130
25156
  this.canvasPreviewInvalidState.set(true);
24131
25157
  if (blockedAnnouncement) {
24132
25158
  this.layoutAnnouncement = blockedAnnouncement;
@@ -24165,10 +25191,22 @@ class DynamicWidgetPageComponent {
24165
25191
  this.transientCanvasItemsState.set(changed
24166
25192
  ? Object.fromEntries(Object.entries(placement.items).map(([key, item]) => [
24167
25193
  key,
24168
- { ...item, constraints: item.constraints ? { ...item.constraints } : undefined },
25194
+ {
25195
+ ...item,
25196
+ constraints: item.constraints
25197
+ ? { ...item.constraints }
25198
+ : undefined,
25199
+ },
24169
25200
  ]))
24170
25201
  : {});
24171
- this.canvasPreviewState.set(changed ? { ...placement.primaryItem, constraints: placement.primaryItem.constraints ? { ...placement.primaryItem.constraints } : undefined } : null);
25202
+ this.canvasPreviewState.set(changed
25203
+ ? {
25204
+ ...placement.primaryItem,
25205
+ constraints: placement.primaryItem.constraints
25206
+ ? { ...placement.primaryItem.constraints }
25207
+ : undefined,
25208
+ }
25209
+ : null);
24172
25210
  this.canvasPreviewInvalidState.set(false);
24173
25211
  }
24174
25212
  return { changed, blocked: false, swappedWith: placement.swappedWith };
@@ -24186,7 +25224,10 @@ class DynamicWidgetPageComponent {
24186
25224
  },
24187
25225
  });
24188
25226
  const stateBoundWidgets = previewProjection.widgets;
24189
- const hydrated = this.resolvePagePresets({ ...normalized, widgets: stateBoundWidgets });
25227
+ const hydrated = this.resolvePagePresets({
25228
+ ...normalized,
25229
+ widgets: stateBoundWidgets,
25230
+ });
24190
25231
  this.pageDefinition = hydrated;
24191
25232
  this.page = hydrated;
24192
25233
  this.pageState = runtime.state;
@@ -24205,7 +25246,8 @@ class DynamicWidgetPageComponent {
24205
25246
  return page.canvas;
24206
25247
  }
24207
25248
  applyCanvasDrag(item, interaction, colDelta, rowDelta) {
24208
- const locked = item.constraints?.lockPosition || interaction.startItem.constraints?.lockPosition;
25249
+ const locked = item.constraints?.lockPosition ||
25250
+ interaction.startItem.constraints?.lockPosition;
24209
25251
  if (locked)
24210
25252
  return item;
24211
25253
  const nextCol = this.clampCanvasCol(interaction.startItem.col + colDelta, interaction.startItem.colSpan, interaction.columns);
@@ -24299,8 +25341,12 @@ class DynamicWidgetPageComponent {
24299
25341
  }
24300
25342
  canvasAnnouncement(kind, widgetKey) {
24301
25343
  return kind === 'drag'
24302
- ? this.t('announcements.moved', 'Widget movido: {{widget}}', { widget: widgetKey })
24303
- : this.t('announcements.resized', 'Widget redimensionado: {{widget}}', { widget: widgetKey });
25344
+ ? this.t('announcements.moved', 'Widget movido: {{widget}}', {
25345
+ widget: widgetKey,
25346
+ })
25347
+ : this.t('announcements.resized', 'Widget redimensionado: {{widget}}', {
25348
+ widget: widgetKey,
25349
+ });
24304
25350
  }
24305
25351
  blockedCanvasAnnouncement(kind) {
24306
25352
  return kind === 'drag'
@@ -24386,7 +25432,8 @@ class DynamicWidgetPageComponent {
24386
25432
  }
24387
25433
  return {
24388
25434
  blocked: false,
24389
- changed: !this.isSameCanvasItem(current, candidate) || !this.isSameCanvasItem(collision.item, swappedItem),
25435
+ changed: !this.isSameCanvasItem(current, candidate) ||
25436
+ !this.isSameCanvasItem(collision.item, swappedItem),
24390
25437
  primaryItem: candidate,
24391
25438
  items: {
24392
25439
  [widgetKey]: candidate,
@@ -24397,7 +25444,8 @@ class DynamicWidgetPageComponent {
24397
25444
  }
24398
25445
  findCanvasCollisions(widgetKey, candidate, canvas) {
24399
25446
  return Object.entries(canvas.items || {})
24400
- .filter(([otherKey, otherItem]) => otherKey !== widgetKey && this.canvasItemsOverlap(candidate, otherItem))
25447
+ .filter(([otherKey, otherItem]) => otherKey !== widgetKey &&
25448
+ this.canvasItemsOverlap(candidate, otherItem))
24401
25449
  .map(([key, item]) => ({ key, item }));
24402
25450
  }
24403
25451
  buildCanvasSwapItem(movingWidgetKey, sourceItem, targetWidgetKey, targetItem, movedItem, canvas) {
@@ -24427,24 +25475,24 @@ class DynamicWidgetPageComponent {
24427
25475
  return normalizedSwapItem;
24428
25476
  }
24429
25477
  canPlaceCanvasItem(widgetKey, candidate, canvas) {
24430
- return !Object.entries(canvas.items || {}).some(([otherKey, otherItem]) => (otherKey !== widgetKey && this.canvasItemsOverlap(candidate, otherItem)));
25478
+ return !Object.entries(canvas.items || {}).some(([otherKey, otherItem]) => otherKey !== widgetKey && this.canvasItemsOverlap(candidate, otherItem));
24431
25479
  }
24432
25480
  canvasItemsOverlap(left, right) {
24433
25481
  const leftRight = left.col + left.colSpan - 1;
24434
25482
  const rightRight = right.col + right.colSpan - 1;
24435
25483
  const leftBottom = left.row + left.rowSpan - 1;
24436
25484
  const rightBottom = right.row + right.rowSpan - 1;
24437
- return left.col <= rightRight
24438
- && leftRight >= right.col
24439
- && left.row <= rightBottom
24440
- && leftBottom >= right.row;
25485
+ return (left.col <= rightRight &&
25486
+ leftRight >= right.col &&
25487
+ left.row <= rightBottom &&
25488
+ leftBottom >= right.row);
24441
25489
  }
24442
25490
  isSameCanvasItem(left, right) {
24443
- return left.col === right.col
24444
- && left.row === right.row
24445
- && left.colSpan === right.colSpan
24446
- && left.rowSpan === right.rowSpan
24447
- && left.zIndex === right.zIndex;
25491
+ return (left.col === right.col &&
25492
+ left.row === right.row &&
25493
+ left.colSpan === right.colSpan &&
25494
+ left.rowSpan === right.rowSpan &&
25495
+ left.zIndex === right.zIndex);
24448
25496
  }
24449
25497
  clampCanvasCol(col, span, columns) {
24450
25498
  return this.clampNumber(col, 1, Math.max(1, columns - span + 1));
@@ -24455,7 +25503,9 @@ class DynamicWidgetPageComponent {
24455
25503
  parseCssPixelValue(value, fallback) {
24456
25504
  if (!value)
24457
25505
  return fallback;
24458
- const match = String(value).trim().match(/^(-?\d+(?:\.\d+)?)px$/i);
25506
+ const match = String(value)
25507
+ .trim()
25508
+ .match(/^(-?\d+(?:\.\d+)?)px$/i);
24459
25509
  if (!match)
24460
25510
  return fallback;
24461
25511
  const parsed = Number(match[1]);
@@ -24497,7 +25547,9 @@ class DynamicWidgetPageComponent {
24497
25547
  }
24498
25548
  return {
24499
25549
  ...group,
24500
- widgetKeys: override.widgetKeys?.length ? override.widgetKeys : group.widgetKeys,
25550
+ widgetKeys: override.widgetKeys?.length
25551
+ ? override.widgetKeys
25552
+ : group.widgetKeys,
24501
25553
  };
24502
25554
  })
24503
25555
  .filter((group) => !!group);
@@ -24610,7 +25662,9 @@ class DynamicWidgetPageComponent {
24610
25662
  return this.resolveRenderedCanvasItem(widget)?.zIndex ?? null;
24611
25663
  }
24612
25664
  widgetClassName(widget) {
24613
- return widget.renderClassName || widget.className || '';
25665
+ return (widget.renderClassName ||
25666
+ widget.className ||
25667
+ '');
24614
25668
  }
24615
25669
  mergeClassNames(...classNames) {
24616
25670
  const merged = classNames
@@ -24620,7 +25674,7 @@ class DynamicWidgetPageComponent {
24620
25674
  return merged.length ? Array.from(new Set(merged)).join(' ') : undefined;
24621
25675
  }
24622
25676
  resolveRenderedCanvasItem(widget) {
24623
- return this.transientCanvasItemsState()[widget.key] || widget.renderCanvasItem;
25677
+ return (this.transientCanvasItemsState()[widget.key] || widget.renderCanvasItem);
24624
25678
  }
24625
25679
  toPersistedCanonicalPage(page) {
24626
25680
  this.assertNoLegacyConnections(page);
@@ -24631,7 +25685,10 @@ class DynamicWidgetPageComponent {
24631
25685
  if (!key)
24632
25686
  return;
24633
25687
  try {
24634
- this.storage.saveConfig(key, this.toPersistedCanonicalPage(page)).pipe(take(1)).subscribe({ error: () => { } });
25688
+ this.storage
25689
+ .saveConfig(key, this.toPersistedCanonicalPage(page))
25690
+ .pipe(take(1))
25691
+ .subscribe({ error: () => { } });
24635
25692
  }
24636
25693
  catch { }
24637
25694
  }
@@ -24642,7 +25699,10 @@ class DynamicWidgetPageComponent {
24642
25699
  return;
24643
25700
  }
24644
25701
  try {
24645
- this.storage.loadConfig(key).pipe(take(1)).subscribe({
25702
+ this.storage
25703
+ .loadConfig(key)
25704
+ .pipe(take(1))
25705
+ .subscribe({
24646
25706
  next: (stored) => {
24647
25707
  if (!stored)
24648
25708
  return;
@@ -24666,7 +25726,9 @@ class DynamicWidgetPageComponent {
24666
25726
  if (this.pageIdentity?.routePath) {
24667
25727
  const base = buildPageKey(this.pageIdentity);
24668
25728
  const instance = this.sanitizeSegment(this.componentInstanceId);
24669
- return instance ? `dynamic-page:${base}:ik=${instance}` : `dynamic-page:${base}`;
25729
+ return instance
25730
+ ? `dynamic-page:${base}:ik=${instance}`
25731
+ : `dynamic-page:${base}`;
24670
25732
  }
24671
25733
  const id = this.componentKeyId();
24672
25734
  if (!id)
@@ -24704,7 +25766,9 @@ class DynamicWidgetPageComponent {
24704
25766
  sanitizeSegment(value) {
24705
25767
  if (!value)
24706
25768
  return '';
24707
- return String(value).trim().replace(/[\r\n\t|:]/g, '-');
25769
+ return String(value)
25770
+ .trim()
25771
+ .replace(/[\r\n\t|:]/g, '-');
24708
25772
  }
24709
25773
  assertNoLegacyConnections(page) {
24710
25774
  if (!page)
@@ -24718,17 +25782,17 @@ class DynamicWidgetPageComponent {
24718
25782
  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: `
24719
25783
  <div class="pdx-page-wrapper" [class.editing]="enableCustomization">
24720
25784
  @if (enableCustomization && showPageSettingsButton) {
24721
- <button
24722
- class="pdx-page-settings"
24723
- mat-icon-button
24724
- type="button"
24725
- [matTooltip]="pageSettingsLabel()"
24726
- matTooltipPosition="below"
24727
- [attr.aria-label]="pageSettingsLabel()"
24728
- (click)="openPageSettings()"
24729
- >
24730
- <mat-icon>settings</mat-icon>
24731
- </button>
25785
+ <button
25786
+ class="pdx-page-settings"
25787
+ mat-icon-button
25788
+ type="button"
25789
+ [matTooltip]="pageSettingsLabel()"
25790
+ matTooltipPosition="below"
25791
+ [attr.aria-label]="pageSettingsLabel()"
25792
+ (click)="openPageSettings()"
25793
+ >
25794
+ <mat-icon fontSet="material-symbols-outlined">settings</mat-icon>
25795
+ </button>
24732
25796
  }
24733
25797
  <div
24734
25798
  #pageCanvasHost
@@ -24743,8 +25807,12 @@ class DynamicWidgetPageComponent {
24743
25807
  <div
24744
25808
  class="pdx-widget pdx-widget--canvas"
24745
25809
  [class.pdx-widget--interactive]="enableCustomization"
24746
- [class.pdx-widget--canvas-selected]="isCanvasWidgetSelected(w.key)"
24747
- [class.pdx-widget--canvas-blocked]="isCanvasWidgetBlocked(w.key)"
25810
+ [class.pdx-widget--canvas-selected]="
25811
+ enableCustomization && isCanvasWidgetSelected(w.key)
25812
+ "
25813
+ [class.pdx-widget--canvas-blocked]="
25814
+ enableCustomization && isCanvasWidgetBlocked(w.key)
25815
+ "
24748
25816
  [class]="widgetClassName(w)"
24749
25817
  [style.gridColumn]="widgetGridColumn(w)"
24750
25818
  [style.gridRow]="widgetGridRow(w)"
@@ -24762,7 +25830,9 @@ class DynamicWidgetPageComponent {
24762
25830
  [attr.aria-label]="resizeHandleLabel(handle.id)"
24763
25831
  [title]="resizeHandleLabel(handle.id)"
24764
25832
  (pointerdown)="startCanvasResize(w.key, handle.id, $event)"
24765
- (keydown)="onCanvasResizeHandleKeydown(w.key, handle.id, $event)"
25833
+ (keydown)="
25834
+ onCanvasResizeHandleKeydown(w.key, handle.id, $event)
25835
+ "
24766
25836
  >
24767
25837
  <span class="pdx-canvas-resize-grip"></span>
24768
25838
  </button>
@@ -24775,13 +25845,16 @@ class DynamicWidgetPageComponent {
24775
25845
  [dragSurfaceLabel]="dragWidgetLabel()"
24776
25846
  (action)="onShellAction(w.key, $event)"
24777
25847
  (dragSurfacePointerDown)="startCanvasDrag(w.key, $event)"
24778
- (dragSurfaceKeydown)="onCanvasHandleKeydown(w.key, 'drag', $event)"
25848
+ (dragSurfaceKeydown)="
25849
+ onCanvasHandleKeydown(w.key, 'drag', $event)
25850
+ "
24779
25851
  >
24780
- <ng-container
25852
+ <ng-container
24781
25853
  [dynamicWidgetLoader]="w.definition"
24782
25854
  [ownerWidgetKey]="w.key"
24783
25855
  [context]="mergedContext"
24784
25856
  [strictValidation]="strictValidation"
25857
+ [autoWireOutputs]="shouldAutoWireOutputs(w)"
24785
25858
  (widgetEvent)="onWidgetEvent(w.key, $event)"
24786
25859
  (widgetDiagnostic)="onWidgetDiagnostic(w.key, $event)"
24787
25860
  ></ng-container>
@@ -24800,7 +25873,15 @@ class DynamicWidgetPageComponent {
24800
25873
  @for (group of renderedGroups(); track group.id) {
24801
25874
  <section
24802
25875
  class="pdx-group"
24803
- [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 : '')"
25876
+ [class]="
25877
+ 'pdx-group--' +
25878
+ group.kind +
25879
+ (group.layout ? ' pdx-group--layout-' + group.layout : '') +
25880
+ (group.emphasis
25881
+ ? ' pdx-group--emphasis-' + group.emphasis
25882
+ : '') +
25883
+ (group.side ? ' pdx-group--side-' + group.side : '')
25884
+ "
24804
25885
  [style.gridColumn]="groupGridColumn(group)"
24805
25886
  [attr.data-group-id]="group.id"
24806
25887
  [attr.data-group-kind]="group.kind"
@@ -24826,9 +25907,19 @@ class DynamicWidgetPageComponent {
24826
25907
  </div>
24827
25908
  @for (tab of group.tabs || []; track tab.id) {
24828
25909
  @if (activeTabId(group.id) === tab.id) {
24829
- <div class="pdx-group-content" [class]="'pdx-group-content--' + resolveGroupContentLayout(group)">
25910
+ <div
25911
+ class="pdx-group-content"
25912
+ [class]="
25913
+ 'pdx-group-content--' +
25914
+ resolveGroupContentLayout(group)
25915
+ "
25916
+ >
24830
25917
  @for (w of tab.widgets; track w.key) {
24831
- <div class="pdx-widget" [class]="w.renderClassName || w.className || ''" [style.gridColumn]="widgetGridColumn(w)">
25918
+ <div
25919
+ class="pdx-widget"
25920
+ [class]="w.renderClassName || w.className || ''"
25921
+ [style.gridColumn]="widgetGridColumn(w)"
25922
+ >
24832
25923
  <praxis-widget-shell
24833
25924
  [shell]="w.shell"
24834
25925
  [context]="mergedContext"
@@ -24839,8 +25930,11 @@ class DynamicWidgetPageComponent {
24839
25930
  [ownerWidgetKey]="w.key"
24840
25931
  [context]="mergedContext"
24841
25932
  [strictValidation]="strictValidation"
25933
+ [autoWireOutputs]="shouldAutoWireOutputs(w)"
24842
25934
  (widgetEvent)="onWidgetEvent(w.key, $event)"
24843
- (widgetDiagnostic)="onWidgetDiagnostic(w.key, $event)"
25935
+ (widgetDiagnostic)="
25936
+ onWidgetDiagnostic(w.key, $event)
25937
+ "
24844
25938
  ></ng-container>
24845
25939
  </praxis-widget-shell>
24846
25940
  </div>
@@ -24850,9 +25944,18 @@ class DynamicWidgetPageComponent {
24850
25944
  }
24851
25945
  </div>
24852
25946
  } @else {
24853
- <div class="pdx-group-content" [class]="'pdx-group-content--' + resolveGroupContentLayout(group)">
25947
+ <div
25948
+ class="pdx-group-content"
25949
+ [class]="
25950
+ 'pdx-group-content--' + resolveGroupContentLayout(group)
25951
+ "
25952
+ >
24854
25953
  @for (w of group.widgets; track w.key) {
24855
- <div class="pdx-widget" [class]="widgetClassName(w)" [style.gridColumn]="widgetGridColumn(w)">
25954
+ <div
25955
+ class="pdx-widget"
25956
+ [class]="widgetClassName(w)"
25957
+ [style.gridColumn]="widgetGridColumn(w)"
25958
+ >
24856
25959
  <praxis-widget-shell
24857
25960
  [shell]="w.shell"
24858
25961
  [context]="mergedContext"
@@ -24863,6 +25966,7 @@ class DynamicWidgetPageComponent {
24863
25966
  [ownerWidgetKey]="w.key"
24864
25967
  [context]="mergedContext"
24865
25968
  [strictValidation]="strictValidation"
25969
+ [autoWireOutputs]="shouldAutoWireOutputs(w)"
24866
25970
  (widgetEvent)="onWidgetEvent(w.key, $event)"
24867
25971
  (widgetDiagnostic)="onWidgetDiagnostic(w.key, $event)"
24868
25972
  ></ng-container>
@@ -24875,7 +25979,11 @@ class DynamicWidgetPageComponent {
24875
25979
  }
24876
25980
  } @else {
24877
25981
  @for (w of widgets(); track w.key) {
24878
- <div class="pdx-widget" [class]="widgetClassName(w)" [style.gridColumn]="widgetGridColumn(w)">
25982
+ <div
25983
+ class="pdx-widget"
25984
+ [class]="widgetClassName(w)"
25985
+ [style.gridColumn]="widgetGridColumn(w)"
25986
+ >
24879
25987
  <praxis-widget-shell
24880
25988
  [shell]="w.shell"
24881
25989
  [context]="mergedContext"
@@ -24886,6 +25994,7 @@ class DynamicWidgetPageComponent {
24886
25994
  [ownerWidgetKey]="w.key"
24887
25995
  [context]="mergedContext"
24888
25996
  [strictValidation]="strictValidation"
25997
+ [autoWireOutputs]="shouldAutoWireOutputs(w)"
24889
25998
  (widgetEvent)="onWidgetEvent(w.key, $event)"
24890
25999
  (widgetDiagnostic)="onWidgetDiagnostic(w.key, $event)"
24891
26000
  ></ng-container>
@@ -24895,27 +26004,36 @@ class DynamicWidgetPageComponent {
24895
26004
  }
24896
26005
  </div>
24897
26006
  @if (layoutAnnouncement) {
24898
- <div class="pdx-sr-only" aria-live="polite">{{ layoutAnnouncement }}</div>
26007
+ <div class="pdx-sr-only" aria-live="polite">
26008
+ {{ layoutAnnouncement }}
26009
+ </div>
24899
26010
  }
24900
26011
  </div>
24901
- `, isInline: true, styles: [".pdx-page-wrapper{position:relative;display:block}.pdx-page{display:grid;gap:16px;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:999px;margin-bottom:8px}.pdx-widget{position:relative;background:var(--pfx-surface, transparent);border-radius:8px;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"] }] });
26012
+ `, 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"] }] });
24902
26013
  }
24903
26014
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DynamicWidgetPageComponent, decorators: [{
24904
26015
  type: Component,
24905
- args: [{ selector: 'praxis-dynamic-page', standalone: true, imports: [CommonModule, MatButtonModule, MatIconModule, MatTooltipModule, DynamicWidgetLoaderDirective, WidgetShellComponent], providers: [providePraxisI18nConfig(DYNAMIC_WIDGET_PAGE_I18N_CONFIG)], template: `
26016
+ args: [{ selector: 'praxis-dynamic-page', standalone: true, imports: [
26017
+ CommonModule,
26018
+ MatButtonModule,
26019
+ MatIconModule,
26020
+ MatTooltipModule,
26021
+ DynamicWidgetLoaderDirective,
26022
+ WidgetShellComponent,
26023
+ ], providers: [providePraxisI18nConfig(DYNAMIC_WIDGET_PAGE_I18N_CONFIG)], template: `
24906
26024
  <div class="pdx-page-wrapper" [class.editing]="enableCustomization">
24907
26025
  @if (enableCustomization && showPageSettingsButton) {
24908
- <button
24909
- class="pdx-page-settings"
24910
- mat-icon-button
24911
- type="button"
24912
- [matTooltip]="pageSettingsLabel()"
24913
- matTooltipPosition="below"
24914
- [attr.aria-label]="pageSettingsLabel()"
24915
- (click)="openPageSettings()"
24916
- >
24917
- <mat-icon>settings</mat-icon>
24918
- </button>
26026
+ <button
26027
+ class="pdx-page-settings"
26028
+ mat-icon-button
26029
+ type="button"
26030
+ [matTooltip]="pageSettingsLabel()"
26031
+ matTooltipPosition="below"
26032
+ [attr.aria-label]="pageSettingsLabel()"
26033
+ (click)="openPageSettings()"
26034
+ >
26035
+ <mat-icon fontSet="material-symbols-outlined">settings</mat-icon>
26036
+ </button>
24919
26037
  }
24920
26038
  <div
24921
26039
  #pageCanvasHost
@@ -24930,8 +26048,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
24930
26048
  <div
24931
26049
  class="pdx-widget pdx-widget--canvas"
24932
26050
  [class.pdx-widget--interactive]="enableCustomization"
24933
- [class.pdx-widget--canvas-selected]="isCanvasWidgetSelected(w.key)"
24934
- [class.pdx-widget--canvas-blocked]="isCanvasWidgetBlocked(w.key)"
26051
+ [class.pdx-widget--canvas-selected]="
26052
+ enableCustomization && isCanvasWidgetSelected(w.key)
26053
+ "
26054
+ [class.pdx-widget--canvas-blocked]="
26055
+ enableCustomization && isCanvasWidgetBlocked(w.key)
26056
+ "
24935
26057
  [class]="widgetClassName(w)"
24936
26058
  [style.gridColumn]="widgetGridColumn(w)"
24937
26059
  [style.gridRow]="widgetGridRow(w)"
@@ -24949,7 +26071,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
24949
26071
  [attr.aria-label]="resizeHandleLabel(handle.id)"
24950
26072
  [title]="resizeHandleLabel(handle.id)"
24951
26073
  (pointerdown)="startCanvasResize(w.key, handle.id, $event)"
24952
- (keydown)="onCanvasResizeHandleKeydown(w.key, handle.id, $event)"
26074
+ (keydown)="
26075
+ onCanvasResizeHandleKeydown(w.key, handle.id, $event)
26076
+ "
24953
26077
  >
24954
26078
  <span class="pdx-canvas-resize-grip"></span>
24955
26079
  </button>
@@ -24962,13 +26086,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
24962
26086
  [dragSurfaceLabel]="dragWidgetLabel()"
24963
26087
  (action)="onShellAction(w.key, $event)"
24964
26088
  (dragSurfacePointerDown)="startCanvasDrag(w.key, $event)"
24965
- (dragSurfaceKeydown)="onCanvasHandleKeydown(w.key, 'drag', $event)"
26089
+ (dragSurfaceKeydown)="
26090
+ onCanvasHandleKeydown(w.key, 'drag', $event)
26091
+ "
24966
26092
  >
24967
- <ng-container
26093
+ <ng-container
24968
26094
  [dynamicWidgetLoader]="w.definition"
24969
26095
  [ownerWidgetKey]="w.key"
24970
26096
  [context]="mergedContext"
24971
26097
  [strictValidation]="strictValidation"
26098
+ [autoWireOutputs]="shouldAutoWireOutputs(w)"
24972
26099
  (widgetEvent)="onWidgetEvent(w.key, $event)"
24973
26100
  (widgetDiagnostic)="onWidgetDiagnostic(w.key, $event)"
24974
26101
  ></ng-container>
@@ -24987,7 +26114,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
24987
26114
  @for (group of renderedGroups(); track group.id) {
24988
26115
  <section
24989
26116
  class="pdx-group"
24990
- [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 : '')"
26117
+ [class]="
26118
+ 'pdx-group--' +
26119
+ group.kind +
26120
+ (group.layout ? ' pdx-group--layout-' + group.layout : '') +
26121
+ (group.emphasis
26122
+ ? ' pdx-group--emphasis-' + group.emphasis
26123
+ : '') +
26124
+ (group.side ? ' pdx-group--side-' + group.side : '')
26125
+ "
24991
26126
  [style.gridColumn]="groupGridColumn(group)"
24992
26127
  [attr.data-group-id]="group.id"
24993
26128
  [attr.data-group-kind]="group.kind"
@@ -25013,9 +26148,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
25013
26148
  </div>
25014
26149
  @for (tab of group.tabs || []; track tab.id) {
25015
26150
  @if (activeTabId(group.id) === tab.id) {
25016
- <div class="pdx-group-content" [class]="'pdx-group-content--' + resolveGroupContentLayout(group)">
26151
+ <div
26152
+ class="pdx-group-content"
26153
+ [class]="
26154
+ 'pdx-group-content--' +
26155
+ resolveGroupContentLayout(group)
26156
+ "
26157
+ >
25017
26158
  @for (w of tab.widgets; track w.key) {
25018
- <div class="pdx-widget" [class]="w.renderClassName || w.className || ''" [style.gridColumn]="widgetGridColumn(w)">
26159
+ <div
26160
+ class="pdx-widget"
26161
+ [class]="w.renderClassName || w.className || ''"
26162
+ [style.gridColumn]="widgetGridColumn(w)"
26163
+ >
25019
26164
  <praxis-widget-shell
25020
26165
  [shell]="w.shell"
25021
26166
  [context]="mergedContext"
@@ -25026,8 +26171,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
25026
26171
  [ownerWidgetKey]="w.key"
25027
26172
  [context]="mergedContext"
25028
26173
  [strictValidation]="strictValidation"
26174
+ [autoWireOutputs]="shouldAutoWireOutputs(w)"
25029
26175
  (widgetEvent)="onWidgetEvent(w.key, $event)"
25030
- (widgetDiagnostic)="onWidgetDiagnostic(w.key, $event)"
26176
+ (widgetDiagnostic)="
26177
+ onWidgetDiagnostic(w.key, $event)
26178
+ "
25031
26179
  ></ng-container>
25032
26180
  </praxis-widget-shell>
25033
26181
  </div>
@@ -25037,9 +26185,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
25037
26185
  }
25038
26186
  </div>
25039
26187
  } @else {
25040
- <div class="pdx-group-content" [class]="'pdx-group-content--' + resolveGroupContentLayout(group)">
26188
+ <div
26189
+ class="pdx-group-content"
26190
+ [class]="
26191
+ 'pdx-group-content--' + resolveGroupContentLayout(group)
26192
+ "
26193
+ >
25041
26194
  @for (w of group.widgets; track w.key) {
25042
- <div class="pdx-widget" [class]="widgetClassName(w)" [style.gridColumn]="widgetGridColumn(w)">
26195
+ <div
26196
+ class="pdx-widget"
26197
+ [class]="widgetClassName(w)"
26198
+ [style.gridColumn]="widgetGridColumn(w)"
26199
+ >
25043
26200
  <praxis-widget-shell
25044
26201
  [shell]="w.shell"
25045
26202
  [context]="mergedContext"
@@ -25050,6 +26207,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
25050
26207
  [ownerWidgetKey]="w.key"
25051
26208
  [context]="mergedContext"
25052
26209
  [strictValidation]="strictValidation"
26210
+ [autoWireOutputs]="shouldAutoWireOutputs(w)"
25053
26211
  (widgetEvent)="onWidgetEvent(w.key, $event)"
25054
26212
  (widgetDiagnostic)="onWidgetDiagnostic(w.key, $event)"
25055
26213
  ></ng-container>
@@ -25062,7 +26220,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
25062
26220
  }
25063
26221
  } @else {
25064
26222
  @for (w of widgets(); track w.key) {
25065
- <div class="pdx-widget" [class]="widgetClassName(w)" [style.gridColumn]="widgetGridColumn(w)">
26223
+ <div
26224
+ class="pdx-widget"
26225
+ [class]="widgetClassName(w)"
26226
+ [style.gridColumn]="widgetGridColumn(w)"
26227
+ >
25066
26228
  <praxis-widget-shell
25067
26229
  [shell]="w.shell"
25068
26230
  [context]="mergedContext"
@@ -25073,6 +26235,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
25073
26235
  [ownerWidgetKey]="w.key"
25074
26236
  [context]="mergedContext"
25075
26237
  [strictValidation]="strictValidation"
26238
+ [autoWireOutputs]="shouldAutoWireOutputs(w)"
25076
26239
  (widgetEvent)="onWidgetEvent(w.key, $event)"
25077
26240
  (widgetDiagnostic)="onWidgetDiagnostic(w.key, $event)"
25078
26241
  ></ng-container>
@@ -25082,10 +26245,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
25082
26245
  }
25083
26246
  </div>
25084
26247
  @if (layoutAnnouncement) {
25085
- <div class="pdx-sr-only" aria-live="polite">{{ layoutAnnouncement }}</div>
26248
+ <div class="pdx-sr-only" aria-live="polite">
26249
+ {{ layoutAnnouncement }}
26250
+ </div>
25086
26251
  }
25087
26252
  </div>
25088
- `, styles: [".pdx-page-wrapper{position:relative;display:block}.pdx-page{display:grid;gap:16px;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:999px;margin-bottom:8px}.pdx-widget{position:relative;background:var(--pfx-surface, transparent);border-radius:8px;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"] }]
26253
+ `, 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"] }]
25089
26254
  }], ctorParameters: () => [], propDecorators: { pageCanvasHost: [{
25090
26255
  type: ViewChild,
25091
26256
  args: ['pageCanvasHost']
@@ -26575,4 +27740,4 @@ function provideHookWhitelist(allowed) {
26575
27740
  * Generated bundle index. Do not edit.
26576
27741
  */
26577
27742
 
26578
- 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, 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, 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, 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 };
27743
+ 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 };