@praxisui/core 9.0.0-beta.62 → 9.0.0-beta.64

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-07-09T14:19:11.232Z",
3
+ "generatedAt": "2026-07-09T17:49:20.835Z",
4
4
  "packageName": "@praxisui/core",
5
- "packageVersion": "9.0.0-beta.62",
5
+ "packageVersion": "9.0.0-beta.64",
6
6
  "sourceRegistry": "praxis-component-registry-ingestion",
7
7
  "sourceRegistryVersion": "1.0.0",
8
8
  "componentCount": 4,
@@ -3523,9 +3523,9 @@
3523
3523
  {
3524
3524
  "chunkIndex": 1,
3525
3525
  "chunkKind": "recipe",
3526
- "content": "{\n \"_comment\": \"Recipe para agentes usarem surface.relatedResource com o runtime canonico praxis-related-resource-outlet.\",\n \"_comment2\": \"O filtro pai-filho deve vir de relatedResource.childParentField; nao duplique a mesma regra em composition.links quando o outlet puder resolver.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-related-resource-outlet\",\n \"variantId\": \"inline-table-child-resource\",\n \"status\": \"public-example\",\n \"useWhen\": \"Render a related child resource from surfaceId or ResourceSurfaceCatalogItem.relatedResource without hand-writing table filters or host-specific code.\",\n \"examplePrompts\": [\n \"renderize recursos relacionados de uma linha selecionada\",\n \"crie tabela filha a partir de relatedResource\",\n \"mostrar participantes filtrados pela missao selecionada sem composition manual\"\n ]\n },\n \"platformValue\": {\n \"canonicalContract\": \"praxis-metadata-starter publishes ResourceSurfaceCatalogItem.relatedResource in the surfaces catalog.\",\n \"angularRuntime\": \"@praxisui/core discovers the requested surface by surfaceId when needed, resolves relatedResource into a SurfaceOpenPayload and materializes praxis-table through DynamicWidgetLoader.\",\n \"migrationValue\": \"Hosts keep only surfaceId plus parentRecord or parentResourceId in the page; parent-child filtering is declared once in metadata.\",\n \"agentCorpus\": \"This recipe keeps surfaceId, parentResourcePath, parentResourceId and parentRecord explicit so agents do not infer relationships from labels.\"\n },\n \"authoringGuidance\": [\n \"Use praxis-related-resource-outlet with surfaceId when the parent resource publishes item-level surfaces.\",\n \"Pass surface directly only when the host already has the ResourceSurfaceCatalogItem available.\",\n \"Pass parentRecord when the selected row is available; pass parentResourceId when only the id is available.\",\n \"Do not repeat childParentField filters in composition.links unless the page intentionally overrides queryContext.\",\n \"Keep availability fail-closed; permission-limited and not-found states should render as outlet states instead of empty tables.\",\n \"Use mode=open-action when the host owns drawer/dialog orchestration; use mode=inline for embedded child tables.\"\n ],\n \"teaches\": [\n \"surface.relatedResource\",\n \"surfaceId\",\n \"praxis-related-resource-outlet\",\n \"related-resource.childParentField\",\n \"related-resource.childResourcePath\",\n \"resourceEvent\",\n \"surfaceOpen\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 2,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"missionParticipants\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"hub\",\n \"title\": \"Related participants\",\n \"subtitle\": \"Child table resolved from surface.relatedResource\"\n },\n \"definition\": {\n \"id\": \"praxis-related-resource-outlet\",\n \"bindingOrder\": [\n \"surfaceId\",\n \"parentRecord\",\n \"parentResourceId\",\n \"parentResourcePath\",\n \"mode\"\n ],\n \"inputs\": {\n \"mode\": \"inline\",\n \"surfaceId\": \"team\",\n \"parentResourcePath\": \"operations/missoes\",\n \"parentResourceId\": 1,\n \"parentRecord\": {\n \"id\": 1,\n \"titulo\": \"Atlantic Shield\",\n \"status\": \"PLANEJADA\"\n }\n },\n \"outputs\": {\n \"widgetEvent\": \"emit\",\n \"resourceEvent\": \"emit\",\n \"surfaceOpen\": \"emit\"\n }\n }\n }\n ]\n }\n}\n",
3526
+ "content": "{\n \"_comment\": \"Recipe para agentes usarem surface.relatedResource com o runtime canonico praxis-related-resource-outlet.\",\n \"_comment2\": \"O filtro pai-filho deve vir de relatedResource.childParentField; nao duplique a mesma regra em composition.links quando o outlet puder resolver.\",\n \"templateMeta\": {\n \"registryKey\": \"praxis-related-resource-outlet\",\n \"variantId\": \"inline-table-child-resource\",\n \"status\": \"public-example\",\n \"useWhen\": \"Render a related child resource from surfaceId or ResourceSurfaceCatalogItem.relatedResource without hand-writing table filters or host-specific code.\",\n \"examplePrompts\": [\n \"renderize recursos relacionados de uma linha selecionada\",\n \"crie tabela filha a partir de relatedResource\",\n \"mostrar participantes filtrados pela missao selecionada sem composition manual\"\n ]\n },\n \"platformValue\": {\n \"canonicalContract\": \"praxis-metadata-starter publishes ResourceSurfaceCatalogItem.relatedResource in the surfaces catalog.\",\n \"angularRuntime\": \"@praxisui/core discovers the requested surface by surfaceId when needed, resolves relatedResource into a SurfaceOpenPayload and materializes praxis-table through DynamicWidgetLoader.\",\n \"migrationValue\": \"Hosts keep only surfaceId plus parentRecord or parentResourceId in the page; parent-child filtering is declared once in metadata.\",\n \"agentCorpus\": \"This recipe keeps surfaceId, parentResourcePath, parentResourceId and parentRecord explicit so agents do not infer relationships from labels.\"\n },\n \"authoringGuidance\": [\n \"Use praxis-related-resource-outlet with surfaceId when the parent resource publishes item-level surfaces.\",\n \"Pass surface directly only when the host already has the ResourceSurfaceCatalogItem available.\",\n \"Pass parentRecord when the selected row is available; pass parentResourceId when only the id is available.\",\n \"Do not repeat childParentField filters in composition.links unless the page intentionally overrides queryContext.\",\n \"Keep availability fail-closed; permission-limited and not-found states should render as outlet states instead of empty tables.\",\n \"Omit emptyState for the default related-resource empty copy; the runtime derives contextual copy and create action from surface.relatedResource. Pass emptyState only when domain-specific wording must override the platform default.\",\n \"Use mode=open-action when the host owns drawer/dialog orchestration; use mode=inline for embedded child tables.\"\n ],\n \"teaches\": [\n \"surface.relatedResource\",\n \"surfaceId\",\n \"praxis-related-resource-outlet\",\n \"related-resource.childParentField\",\n \"related-resource.childResourcePath\",\n \"resourceEvent\",\n \"surfaceOpen\"\n ],\n \"page\": {\n \"layout\": {\n \"orientation\": \"columns\",\n \"columns\": 2,\n \"gap\": \"16px\"\n },\n \"widgets\": [\n {\n \"key\": \"missionParticipants\",\n \"shell\": {\n \"kind\": \"dashboard-card\",\n \"icon\": \"hub\",\n \"title\": \"Related participants\",\n \"subtitle\": \"Child table resolved from surface.relatedResource\"\n },\n \"definition\": {\n \"id\": \"praxis-related-resource-outlet\",\n \"bindingOrder\": [\n \"surfaceId\",\n \"parentRecord\",\n \"parentResourceId\",\n \"parentResourcePath\",\n \"mode\"\n ],\n \"inputs\": {\n \"mode\": \"inline\",\n \"surfaceId\": \"team\",\n \"parentResourcePath\": \"operations/missoes\",\n \"parentResourceId\": 1,\n \"parentRecord\": {\n \"id\": 1,\n \"titulo\": \"Atlantic Shield\",\n \"status\": \"PLANEJADA\"\n }\n },\n \"outputs\": {\n \"widgetEvent\": \"emit\",\n \"resourceEvent\": \"emit\",\n \"surfaceOpen\": \"emit\"\n }\n }\n }\n ]\n }\n}\n",
3527
3527
  "sourcePointer": "praxis-ui-angular/examples/ai-recipes/praxis-related-resource-outlet.json",
3528
- "contentHash": "e9e842635ad7211ff2f021ebbcc1071a8a491cd5c88885525ba153a8a49223b8",
3528
+ "contentHash": "42ae917652755ce436674353d912f7fff6548f61be3e523d940aae6983af3d1a",
3529
3529
  "sourceKind": "component_definition",
3530
3530
  "sourceId": "praxis-related-resource-outlet",
3531
3531
  "corpusVersion": "1.0.0"
@@ -14009,7 +14009,60 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
14009
14009
  args: [{ providedIn: 'any' }]
14010
14010
  }] });
14011
14011
 
14012
+ const RELATED_RESOURCE_OUTLET_I18N_NAMESPACE = 'relatedResourceOutlet';
14013
+ const RELATED_RESOURCE_OUTLET_I18N_CONFIG = {
14014
+ namespaces: {
14015
+ [RELATED_RESOURCE_OUTLET_I18N_NAMESPACE]: {
14016
+ 'pt-BR': {
14017
+ 'state.idle.title': 'Recurso relacionado não selecionado',
14018
+ 'state.idle.description': 'Selecione uma surface relacionada para carregar os dados.',
14019
+ 'state.resolving.title': 'Resolvendo recurso relacionado',
14020
+ 'state.resolving.description': 'Validando metadados e permissões da relação.',
14021
+ 'state.loading.title': 'Carregando recurso relacionado',
14022
+ 'state.loading.description': 'Aguarde enquanto a coleção relacionada é carregada.',
14023
+ 'state.empty.title': 'Nenhuma operação de leitura publicada',
14024
+ 'state.empty.description': 'A relação existe, mas não há operação de lista ou filtro disponível.',
14025
+ 'state.permission-limited.title': 'Acesso limitado',
14026
+ 'state.permission-limited.description': 'O contexto atual não permite abrir este recurso relacionado.',
14027
+ 'state.not-found.title': 'Relação indisponível',
14028
+ 'state.not-found.description': 'Não foi possível resolver a relação ou o identificador do registro pai.',
14029
+ 'state.error.title': 'Falha ao preparar recurso relacionado',
14030
+ 'state.error.description': 'Ocorreu um erro ao preparar a superfície relacionada.',
14031
+ 'emptyState.related.title': 'Sem registros em {label}',
14032
+ 'emptyState.related.description': 'Esta coleção relacionada não possui registros para o contexto selecionado.',
14033
+ 'emptyState.related.descriptionWithAction': 'Use a ação principal para adicionar um registro relacionado quando houver informações para registrar.',
14034
+ 'emptyState.related.action.create': 'Adicionar registro',
14035
+ 'action.open': 'Abrir relacionado',
14036
+ 'status.ready': 'Recurso relacionado pronto',
14037
+ },
14038
+ 'en-US': {
14039
+ 'state.idle.title': 'Related resource not selected',
14040
+ 'state.idle.description': 'Select a related surface to load its data.',
14041
+ 'state.resolving.title': 'Resolving related resource',
14042
+ 'state.resolving.description': 'Validating relation metadata and permissions.',
14043
+ 'state.loading.title': 'Loading related resource',
14044
+ 'state.loading.description': 'Wait while the related collection is loaded.',
14045
+ 'state.empty.title': 'No read operation published',
14046
+ 'state.empty.description': 'The relation exists, but no list or filter operation is available.',
14047
+ 'state.permission-limited.title': 'Limited access',
14048
+ 'state.permission-limited.description': 'The current context cannot open this related resource.',
14049
+ 'state.not-found.title': 'Relation unavailable',
14050
+ 'state.not-found.description': 'The relation or parent record identifier could not be resolved.',
14051
+ 'state.error.title': 'Failed to prepare related resource',
14052
+ 'state.error.description': 'An error occurred while preparing the related surface.',
14053
+ 'emptyState.related.title': 'No records in {label}',
14054
+ 'emptyState.related.description': 'This related collection has no records for the selected context.',
14055
+ 'emptyState.related.descriptionWithAction': 'Use the primary action to add a related record when there is information to capture.',
14056
+ 'emptyState.related.action.create': 'Add record',
14057
+ 'action.open': 'Open related',
14058
+ 'status.ready': 'Related resource ready',
14059
+ },
14060
+ },
14061
+ },
14062
+ };
14063
+
14012
14064
  class RelatedResourceSurfaceResolverService {
14065
+ i18n = inject(PraxisI18nService, { optional: true });
14013
14066
  resolve(request) {
14014
14067
  try {
14015
14068
  if (!request?.surface) {
@@ -14092,7 +14145,7 @@ class RelatedResourceSurfaceResolverService {
14092
14145
  apiEndpointKey: request.apiEndpointKey ?? null,
14093
14146
  apiUrlEntry: request.apiUrlEntry ?? null,
14094
14147
  tableId: request.tableId || this.buildStableTableId(surface, relatedResource, parentResourceId),
14095
- config: this.buildTableConfig(request.tableConfig, request.emptyState),
14148
+ config: this.buildTableConfig(surface, relatedResource, request),
14096
14149
  queryContext,
14097
14150
  };
14098
14151
  payload.context = {
@@ -14115,28 +14168,66 @@ class RelatedResourceSurfaceResolverService {
14115
14168
  };
14116
14169
  return payload;
14117
14170
  }
14118
- buildTableConfig(tableConfig, emptyState) {
14171
+ buildTableConfig(surface, relatedResource, request) {
14172
+ const tableConfig = request.tableConfig;
14173
+ const emptyState = request.emptyState;
14119
14174
  const hasTableConfig = !!tableConfig && typeof tableConfig === 'object' && !Array.isArray(tableConfig);
14120
14175
  const hasEmptyState = !!emptyState && typeof emptyState === 'object' && !Array.isArray(emptyState);
14121
- if (!hasTableConfig && !hasEmptyState) {
14122
- return undefined;
14123
- }
14124
14176
  const base = hasTableConfig ? tableConfig : {};
14125
- if (!hasEmptyState) {
14126
- return base;
14127
- }
14128
14177
  const behavior = this.objectValue(base['behavior']);
14178
+ const currentEmptyState = this.objectValue(behavior['emptyState']);
14179
+ const hasCurrentEmptyState = Object.keys(currentEmptyState).length > 0;
14180
+ const resolvedEmptyState = hasEmptyState
14181
+ ? {
14182
+ ...currentEmptyState,
14183
+ ...emptyState,
14184
+ }
14185
+ : hasCurrentEmptyState
14186
+ ? currentEmptyState
14187
+ : this.buildRelatedEmptyState(surface, relatedResource, request);
14188
+ if (!hasTableConfig && !resolvedEmptyState) {
14189
+ return undefined;
14190
+ }
14129
14191
  return {
14130
14192
  ...base,
14131
14193
  behavior: {
14132
14194
  ...behavior,
14133
- emptyState: {
14134
- ...this.objectValue(behavior['emptyState']),
14135
- ...emptyState,
14136
- },
14195
+ emptyState: resolvedEmptyState,
14137
14196
  },
14138
14197
  };
14139
14198
  }
14199
+ buildRelatedEmptyState(surface, relatedResource, request) {
14200
+ const label = this.trim(request.title)
14201
+ || this.trim(surface.title)
14202
+ || this.humanizeResourceKey(relatedResource.childResourceKey);
14203
+ const canCreate = relatedResource.childOperations.includes('CREATE');
14204
+ const descriptionKey = canCreate
14205
+ ? 'emptyState.related.descriptionWithAction'
14206
+ : 'emptyState.related.description';
14207
+ const actions = canCreate
14208
+ ? [
14209
+ {
14210
+ label: this.t('emptyState.related.action.create', 'Adicionar registro'),
14211
+ action: 'create',
14212
+ icon: 'add',
14213
+ primary: true,
14214
+ },
14215
+ ]
14216
+ : [];
14217
+ return {
14218
+ title: this.t('emptyState.related.title', 'Sem registros em {label}', { label }),
14219
+ message: this.t(descriptionKey, canCreate
14220
+ ? 'Use a ação principal para adicionar um registro relacionado quando houver informações para registrar.'
14221
+ : 'Esta coleção relacionada não possui registros para o contexto selecionado.', { label }),
14222
+ icon: this.trim(request.icon) || 'hub',
14223
+ tone: 'neutral',
14224
+ variant: 'inline',
14225
+ density: 'compact',
14226
+ alignment: 'center',
14227
+ iconContainer: 'soft',
14228
+ actions,
14229
+ };
14230
+ }
14140
14231
  objectValue(value) {
14141
14232
  return value && typeof value === 'object' && !Array.isArray(value)
14142
14233
  ? value
@@ -14207,6 +14298,22 @@ class RelatedResourceSurfaceResolverService {
14207
14298
  sanitizeStableId(value) {
14208
14299
  return value.replace(/[^a-zA-Z0-9._-]+/g, '-');
14209
14300
  }
14301
+ humanizeResourceKey(value) {
14302
+ const lastSegment = this.trim(value).split(/[./_-]+/).filter(Boolean).pop() || 'registros';
14303
+ return lastSegment
14304
+ .replace(/([a-z])([A-Z])/g, '$1 $2')
14305
+ .replace(/\s+/g, ' ')
14306
+ .trim();
14307
+ }
14308
+ t(key, fallback, params) {
14309
+ if (this.i18n) {
14310
+ return this.interpolate(this.i18n.t(key, params, fallback, RELATED_RESOURCE_OUTLET_I18N_NAMESPACE), params);
14311
+ }
14312
+ return this.interpolate(fallback, params);
14313
+ }
14314
+ interpolate(template, params) {
14315
+ return Object.entries(params || {}).reduce((current, [name, value]) => current.replace(new RegExp(`\\{${name}\\}`, 'g'), String(value ?? '')), template);
14316
+ }
14210
14317
  trim(value) {
14211
14318
  return typeof value === 'string' ? value.trim() : '';
14212
14319
  }
@@ -37417,50 +37524,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
37417
37524
  args: ['afterWidgetLoader', { read: DynamicWidgetLoaderDirective }]
37418
37525
  }] } });
37419
37526
 
37420
- const RELATED_RESOURCE_OUTLET_I18N_NAMESPACE = 'relatedResourceOutlet';
37421
- const RELATED_RESOURCE_OUTLET_I18N_CONFIG = {
37422
- namespaces: {
37423
- [RELATED_RESOURCE_OUTLET_I18N_NAMESPACE]: {
37424
- 'pt-BR': {
37425
- 'state.idle.title': 'Recurso relacionado não selecionado',
37426
- 'state.idle.description': 'Selecione uma surface relacionada para carregar os dados.',
37427
- 'state.resolving.title': 'Resolvendo recurso relacionado',
37428
- 'state.resolving.description': 'Validando metadados e permissões da relação.',
37429
- 'state.loading.title': 'Carregando recurso relacionado',
37430
- 'state.loading.description': 'Aguarde enquanto a coleção relacionada é carregada.',
37431
- 'state.empty.title': 'Nenhuma operação de leitura publicada',
37432
- 'state.empty.description': 'A relação existe, mas não há operação de lista ou filtro disponível.',
37433
- 'state.permission-limited.title': 'Acesso limitado',
37434
- 'state.permission-limited.description': 'O contexto atual não permite abrir este recurso relacionado.',
37435
- 'state.not-found.title': 'Relação indisponível',
37436
- 'state.not-found.description': 'Não foi possível resolver a relação ou o identificador do registro pai.',
37437
- 'state.error.title': 'Falha ao preparar recurso relacionado',
37438
- 'state.error.description': 'Ocorreu um erro ao preparar a superfície relacionada.',
37439
- 'action.open': 'Abrir relacionado',
37440
- 'status.ready': 'Recurso relacionado pronto',
37441
- },
37442
- 'en-US': {
37443
- 'state.idle.title': 'Related resource not selected',
37444
- 'state.idle.description': 'Select a related surface to load its data.',
37445
- 'state.resolving.title': 'Resolving related resource',
37446
- 'state.resolving.description': 'Validating relation metadata and permissions.',
37447
- 'state.loading.title': 'Loading related resource',
37448
- 'state.loading.description': 'Wait while the related collection is loaded.',
37449
- 'state.empty.title': 'No read operation published',
37450
- 'state.empty.description': 'The relation exists, but no list or filter operation is available.',
37451
- 'state.permission-limited.title': 'Limited access',
37452
- 'state.permission-limited.description': 'The current context cannot open this related resource.',
37453
- 'state.not-found.title': 'Relation unavailable',
37454
- 'state.not-found.description': 'The relation or parent record identifier could not be resolved.',
37455
- 'state.error.title': 'Failed to prepare related resource',
37456
- 'state.error.description': 'An error occurred while preparing the related surface.',
37457
- 'action.open': 'Open related',
37458
- 'status.ready': 'Related resource ready',
37459
- },
37460
- },
37461
- },
37462
- };
37463
-
37464
37527
  class PraxisRelatedResourceOutletComponent {
37465
37528
  resolver = inject(RelatedResourceSurfaceResolverService);
37466
37529
  materializer = inject(SurfaceOpenMaterializerService);
@@ -37880,7 +37943,7 @@ const PRAXIS_RELATED_RESOURCE_OUTLET_COMPONENT_METADATA = {
37880
37943
  { name: 'parentResourcePath', type: 'string | null', description: 'ResourcePath do recurso pai para contexto da surface.' },
37881
37944
  { name: 'queryContext', type: 'RelatedResourceQueryContext | null', description: 'QueryContext base mesclado com o filtro canônico da relação filha.' },
37882
37945
  { name: 'tableConfig', type: 'Record<string, unknown> | null', description: 'Configuracao parcial da tabela filha materializada, mesclada ao preset canonico.' },
37883
- { name: 'emptyState', type: 'Record<string, unknown> | null', description: 'Atalho para behavior.emptyState da tabela filha, usado para texto, icone, tom e layout do estado vazio.' },
37946
+ { name: 'emptyState', type: 'Record<string, unknown> | null', description: 'Override opcional para behavior.emptyState da tabela filha. Quando omitido, o outlet deriva texto, icone, layout e ação create a partir de surface.relatedResource e dos metadados da surface.' },
37884
37947
  { name: 'mode', type: "'inline' | 'open-action'", description: 'Renderiza a tabela filha inline ou emite payload para abertura host-mediated.', default: 'inline' },
37885
37948
  { name: 'state', type: 'RelatedResourceResolutionState | null', description: 'Override de estado para hosts/outlets que estejam carregando discovery remoto.' },
37886
37949
  { name: 'compact', type: 'boolean', description: 'Reduz densidade visual dos estados não materializados.', default: false },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxisui/core",
3
- "version": "9.0.0-beta.62",
3
+ "version": "9.0.0-beta.64",
4
4
  "description": "Core library for Praxis UI Workspace: types, tokens, services and utilities shared across @praxisui/* packages.",
5
5
  "peerDependencies": {
6
6
  "@angular/common": "^21.0.0",
@@ -9741,10 +9741,12 @@ interface RelatedResourceSurfaceResolution {
9741
9741
  payload?: SurfaceOpenPayload;
9742
9742
  }
9743
9743
  declare class RelatedResourceSurfaceResolverService {
9744
+ private readonly i18n;
9744
9745
  resolve(request: RelatedResourceSurfaceResolverRequest | null | undefined): RelatedResourceSurfaceResolution;
9745
9746
  state(state: RelatedResourceResolutionState, reason?: string): RelatedResourceSurfaceResolution;
9746
9747
  private buildPayload;
9747
9748
  private buildTableConfig;
9749
+ private buildRelatedEmptyState;
9748
9750
  private objectValue;
9749
9751
  private buildQueryContext;
9750
9752
  private resolveParentResourceId;
@@ -9754,6 +9756,9 @@ declare class RelatedResourceSurfaceResolverService {
9754
9756
  private buildStableTableId;
9755
9757
  private normalizeResourcePath;
9756
9758
  private sanitizeStableId;
9759
+ private humanizeResourceKey;
9760
+ private t;
9761
+ private interpolate;
9757
9762
  private trim;
9758
9763
  private clone;
9759
9764
  static ɵfac: i0.ɵɵFactoryDeclaration<RelatedResourceSurfaceResolverService, never>;