@praxisui/dynamic-fields 9.0.0-beta.70 → 9.0.0-beta.72

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.
@@ -0,0 +1,474 @@
1
+ ---
2
+ title: "Date Range Rust Host Integration"
3
+ slug: "date-range-rust-host-integration"
4
+ description: "Guia para hosts Rust publicarem atalhos corporativos de date range como metadata JSON resolvida, sem executar regras de negocio no frontend."
5
+ doc_type: "guide"
6
+ document_kind: "host-guide"
7
+ component: "dynamic-fields"
8
+ category: "integration"
9
+ audience:
10
+ - "backend"
11
+ - "host"
12
+ - "frontend"
13
+ - "architect"
14
+ level: "enterprise"
15
+ status: "active"
16
+ owner: "praxis-ui"
17
+ tags:
18
+ - "dynamic-fields"
19
+ - "date-range"
20
+ - "rust"
21
+ - "metadata"
22
+ - "business-periods"
23
+ order: 45
24
+ icon: "calendar_month"
25
+ toc: true
26
+ sidebar: true
27
+ search_boost: 1.2
28
+ reading_time: 24
29
+ estimated_setup_time: 35
30
+ version: "1.0"
31
+ related_docs:
32
+ - "pdx-material-date-range-json-api"
33
+ - "pdx-inline-date-range-json-api"
34
+ - "dynamic-fields-inline-filter-runtime-contract"
35
+ - "date-range-business-shortcuts-evolution-plan"
36
+ keywords:
37
+ - "StaticDateRangePreset"
38
+ - "serde"
39
+ - "inlineQuickPresets.position"
40
+ - "startDate"
41
+ - "endDate"
42
+ - "calculateRange"
43
+ last_updated: "2026-07-11"
44
+ ---
45
+
46
+ # Date Range Rust Host Integration
47
+
48
+ ## Objetivo
49
+
50
+ Orientar hosts Rust que publicam metadata Praxis para `pdx-material-date-range`
51
+ e `pdx-inline-date-range` com atalhos corporativos resolvidos pelo dominio.
52
+
53
+ O contrato de runtime Angular aceita built-ins, presets programaticos
54
+ TypeScript e presets estaticos serializaveis. Hosts Rust devem publicar apenas
55
+ os built-ins e os presets estaticos. Funcoes JavaScript como `calculateRange`
56
+ nao pertencem ao JSON publicado pelo backend.
57
+
58
+ ## Pre-requisitos
59
+
60
+ - Host Rust responsavel por publicar metadata Praxis para schema, recurso ou
61
+ endpoint equivalente.
62
+ - Dominio capaz de resolver periodos de negocio antes da serializacao JSON.
63
+ - Conhecimento do contrato `pdx-material-date-range` ou
64
+ `pdx-inline-date-range`.
65
+ - Pipeline de testes que consiga validar serializacao Rust e consumir a
66
+ metadata em uma superficie Praxis oficial.
67
+
68
+ ## Responsabilidades
69
+
70
+ | Camada | Responsabilidade |
71
+ | --- | --- |
72
+ | Rust/backend | Calcular regras eleitorais, legais, fiscais, contratuais, feriados, dias contaveis, autorizacao, confidencialidade e vigencia antes de publicar metadata. |
73
+ | Metadata publicada | Transportar somente intervalos resolvidos, labels, descricoes, icones semanticos, tons semanticos e configuracao de layout. |
74
+ | Angular/Praxis UI | Materializar o catalogo recebido, preservar constraints do campo, teclado, foco, RTL, tema e payload canonico. |
75
+ | Auditoria de negocio | Permanecer no backend/dominio; `shortcutId`/`id` pode apoiar observabilidade de UI, mas nunca substitui as datas. |
76
+
77
+ O frontend nao executa regras fiscais, eleitorais, juridicas ou de dias uteis
78
+ recebidas por JSON. Se a regra muda por calendario, jurisdicao, tenant,
79
+ permissao ou feriado, o Rust publica um novo intervalo ja resolvido.
80
+
81
+ ## Contrato JSON
82
+
83
+ ### Built-in
84
+
85
+ ```json
86
+ {
87
+ "controlType": "dateRange",
88
+ "shortcuts": ["today", "thisWeek", "thisMonth"]
89
+ }
90
+ ```
91
+
92
+ Built-ins sao identificadores conhecidos pelo runtime. Use-os apenas quando a
93
+ semantica relativa for aceitavel para o campo.
94
+
95
+ ### Preset estatico
96
+
97
+ ```json
98
+ {
99
+ "id": "periodo-votacao-2026",
100
+ "label": "Periodo de votacao 2026",
101
+ "description": "Janela oficial resolvida pelo dominio eleitoral.",
102
+ "startDate": "2026-07-06",
103
+ "endDate": "2026-10-04",
104
+ "timeZone": "America/Sao_Paulo",
105
+ "icon": "how_to_vote",
106
+ "tone": "info",
107
+ "effectiveFrom": "2026-06-01",
108
+ "effectiveTo": "2026-10-04"
109
+ }
110
+ ```
111
+
112
+ Campos suportados:
113
+
114
+ | Campo | Obrigatorio | Semantica |
115
+ | --- | --- | --- |
116
+ | `id` | Sim | Identificador estavel do atalho para estado ativo e observabilidade. |
117
+ | `label` | Sim | Texto publicado pelo dominio ou por i18n governado do host. |
118
+ | `startDate` | Sim | Inicio inclusivo do intervalo resolvido. |
119
+ | `endDate` | Sim | Fim inclusivo do intervalo resolvido. |
120
+ | `timeZone` | Nao | Timezone IANA usado pelo dominio ao resolver o periodo. |
121
+ | `icon` | Nao | Nome de icone semantico suportado pelo host/Praxis. |
122
+ | `description` | Nao | Explicacao operacional do periodo. |
123
+ | `tone` | Nao | `neutral`, `info`, `success` ou `warning`; nunca cor arbitraria. |
124
+ | `effectiveFrom` | Nao | Inicio da vigencia da metadata do atalho. |
125
+ | `effectiveTo` | Nao | Fim da vigencia da metadata do atalho. |
126
+
127
+ ### Lista mista e composicao inline
128
+
129
+ ```json
130
+ {
131
+ "controlType": "inlineDateRange",
132
+ "label": "Periodo",
133
+ "shortcuts": [
134
+ "today",
135
+ {
136
+ "id": "competencia-fiscal-2026-03",
137
+ "label": "Competencia fiscal 03/2026",
138
+ "description": "Periodo fiscal fechado pelo dominio tributario.",
139
+ "startDate": "2026-03-01",
140
+ "endDate": "2026-03-31",
141
+ "timeZone": "America/Sao_Paulo",
142
+ "icon": "account_balance",
143
+ "tone": "success"
144
+ }
145
+ ],
146
+ "inlineQuickPresets": {
147
+ "enabled": true,
148
+ "maxVisible": 4,
149
+ "position": "start"
150
+ },
151
+ "inlineOverlay": {
152
+ "applyMode": "explicit",
153
+ "actions": {
154
+ "apply": { "label": "Aplicar", "appearance": "filled", "colorRole": "primary" },
155
+ "cancel": { "label": "Cancelar", "appearance": "text", "colorRole": "neutral" }
156
+ }
157
+ }
158
+ }
159
+ ```
160
+
161
+ `inlineQuickPresets.position` aceita:
162
+
163
+ | Valor | Uso |
164
+ | --- | --- |
165
+ | `footer` | Atalhos no rodape, antes de Cancelar/Aplicar. |
166
+ | `start` | Rail logica antes do calendario; esquerda em LTR e direita em RTL. |
167
+ | `end` | Rail logica depois do calendario; direita em LTR e esquerda em RTL. |
168
+ | `auto` | Runtime escolhe rail ou rodape conforme espaco, touch e viewport. |
169
+
170
+ Em viewport estreito, por exemplo 390 px, `auto`, `start` e `end` podem cair
171
+ para `footer` para preservar legibilidade, foco e ordem de tabulacao.
172
+
173
+ ## Datas, timezone e payload
174
+
175
+ Use `YYYY-MM-DD` para data civil quando o periodo e contado em dias. O runtime
176
+ trata date-only como data local civil e preserva a semantica de intervalo
177
+ inclusivo de inicio/fim.
178
+
179
+ Use datetime somente se o contrato do recurso exigir instantes com hora. Para
180
+ filtros de periodo civil, prefira date-only e deixe o backend traduzir para
181
+ limites de query conforme timezone, banco e regra do dominio.
182
+
183
+ O payload final do filtro continua canonico:
184
+
185
+ ```json
186
+ {
187
+ "startDate": "2026-03-01",
188
+ "endDate": "2026-03-31"
189
+ }
190
+ ```
191
+
192
+ O `id` do preset pode aparecer em estado interno, destaque visual ou telemetria
193
+ opcional. Ele nao substitui `startDate` e `endDate` no contrato de filtro.
194
+
195
+ ## Exemplo Rust reproduzivel
196
+
197
+ Dependencias sugeridas:
198
+
199
+ ```toml
200
+ [dependencies]
201
+ chrono = { version = "0.4", features = ["serde"] }
202
+ chrono-tz = "0.10"
203
+ serde = { version = "1", features = ["derive"] }
204
+ serde_json = "1"
205
+ thiserror = "2"
206
+ ```
207
+
208
+ DTOs serializaveis:
209
+
210
+ ```rust
211
+ use chrono::NaiveDate;
212
+ use chrono_tz::Tz;
213
+ use serde::Serialize;
214
+ use thiserror::Error;
215
+
216
+ #[derive(Debug, Clone, Serialize)]
217
+ #[serde(rename_all = "camelCase")]
218
+ pub struct StaticDateRangePresetDto {
219
+ pub id: String,
220
+ pub label: String,
221
+ pub start_date: String,
222
+ pub end_date: String,
223
+ #[serde(skip_serializing_if = "Option::is_none")]
224
+ pub time_zone: Option<String>,
225
+ #[serde(skip_serializing_if = "Option::is_none")]
226
+ pub icon: Option<String>,
227
+ #[serde(skip_serializing_if = "Option::is_none")]
228
+ pub description: Option<String>,
229
+ #[serde(skip_serializing_if = "Option::is_none")]
230
+ pub tone: Option<StaticDateRangePresetToneDto>,
231
+ #[serde(skip_serializing_if = "Option::is_none")]
232
+ pub effective_from: Option<String>,
233
+ #[serde(skip_serializing_if = "Option::is_none")]
234
+ pub effective_to: Option<String>,
235
+ }
236
+
237
+ #[derive(Debug, Clone, Serialize)]
238
+ #[serde(rename_all = "camelCase")]
239
+ pub enum StaticDateRangePresetToneDto {
240
+ Neutral,
241
+ Info,
242
+ Success,
243
+ Warning,
244
+ }
245
+
246
+ #[derive(Debug, Clone, Serialize)]
247
+ #[serde(untagged)]
248
+ pub enum DateRangeShortcutDto {
249
+ BuiltIn(String),
250
+ Static(StaticDateRangePresetDto),
251
+ }
252
+
253
+ #[derive(Debug, Clone, Serialize)]
254
+ #[serde(rename_all = "camelCase")]
255
+ pub struct InlineQuickPresetsDto {
256
+ pub enabled: bool,
257
+ pub max_visible: Option<u8>,
258
+ pub position: InlineQuickPresetsPositionDto,
259
+ }
260
+
261
+ #[derive(Debug, Clone, Serialize)]
262
+ #[serde(rename_all = "camelCase")]
263
+ pub enum InlineQuickPresetsPositionDto {
264
+ Auto,
265
+ Footer,
266
+ Start,
267
+ End,
268
+ }
269
+
270
+ #[derive(Debug, Clone, Serialize)]
271
+ #[serde(rename_all = "camelCase")]
272
+ pub struct DateRangeFieldMetadataDto {
273
+ pub control_type: String,
274
+ pub label: String,
275
+ pub shortcuts: Vec<DateRangeShortcutDto>,
276
+ pub inline_quick_presets: InlineQuickPresetsDto,
277
+ }
278
+
279
+ #[derive(Debug, Error)]
280
+ pub enum DateRangeMetadataError {
281
+ #[error("invalid date {value}; expected YYYY-MM-DD")]
282
+ InvalidDate { value: String },
283
+ #[error("startDate must be before or equal to endDate")]
284
+ InvertedInterval,
285
+ #[error("invalid IANA timezone {value}")]
286
+ InvalidTimeZone { value: String },
287
+ }
288
+
289
+ fn parse_date(value: &str) -> Result<NaiveDate, DateRangeMetadataError> {
290
+ NaiveDate::parse_from_str(value, "%Y-%m-%d")
291
+ .map_err(|_| DateRangeMetadataError::InvalidDate { value: value.to_owned() })
292
+ }
293
+
294
+ pub fn validate_static_preset(
295
+ preset: &StaticDateRangePresetDto,
296
+ ) -> Result<(), DateRangeMetadataError> {
297
+ let start = parse_date(&preset.start_date)?;
298
+ let end = parse_date(&preset.end_date)?;
299
+ if start > end {
300
+ return Err(DateRangeMetadataError::InvertedInterval);
301
+ }
302
+ if let Some(zone) = &preset.time_zone {
303
+ zone.parse::<Tz>()
304
+ .map_err(|_| DateRangeMetadataError::InvalidTimeZone { value: zone.clone() })?;
305
+ }
306
+ Ok(())
307
+ }
308
+ ```
309
+
310
+ Periodo de negocio resolvido pelo backend:
311
+
312
+ ```rust
313
+ pub fn voting_period_metadata() -> Result<DateRangeFieldMetadataDto, DateRangeMetadataError> {
314
+ let voting_period = StaticDateRangePresetDto {
315
+ id: "periodo-votacao-2026".into(),
316
+ label: "Periodo de votacao 2026".into(),
317
+ description: Some("Janela oficial resolvida pelo dominio eleitoral.".into()),
318
+ start_date: "2026-07-06".into(),
319
+ end_date: "2026-10-04".into(),
320
+ time_zone: Some("America/Sao_Paulo".into()),
321
+ icon: Some("how_to_vote".into()),
322
+ tone: Some(StaticDateRangePresetToneDto::Info),
323
+ effective_from: Some("2026-06-01".into()),
324
+ effective_to: Some("2026-10-04".into()),
325
+ };
326
+
327
+ validate_static_preset(&voting_period)?;
328
+
329
+ Ok(DateRangeFieldMetadataDto {
330
+ control_type: "inlineDateRange".into(),
331
+ label: "Periodo".into(),
332
+ shortcuts: vec![
333
+ DateRangeShortcutDto::BuiltIn("today".into()),
334
+ DateRangeShortcutDto::Static(voting_period),
335
+ ],
336
+ inline_quick_presets: InlineQuickPresetsDto {
337
+ enabled: true,
338
+ max_visible: Some(4),
339
+ position: InlineQuickPresetsPositionDto::Auto,
340
+ },
341
+ })
342
+ }
343
+ ```
344
+
345
+ Teste de serializacao:
346
+
347
+ ```rust
348
+ #[test]
349
+ fn serializes_resolved_business_period_metadata() {
350
+ let metadata = voting_period_metadata().expect("valid metadata");
351
+ let json = serde_json::to_value(metadata).expect("serializable");
352
+
353
+ assert_eq!(json["controlType"], "inlineDateRange");
354
+ assert_eq!(json["shortcuts"][0], "today");
355
+ assert_eq!(json["shortcuts"][1]["id"], "periodo-votacao-2026");
356
+ assert_eq!(json["shortcuts"][1]["startDate"], "2026-07-06");
357
+ assert_eq!(json["shortcuts"][1]["endDate"], "2026-10-04");
358
+ assert!(json["shortcuts"][1].get("calculateRange").is_none());
359
+ }
360
+
361
+ #[test]
362
+ fn rejects_inverted_interval() {
363
+ let preset = StaticDateRangePresetDto {
364
+ id: "invalid".into(),
365
+ label: "Invalid".into(),
366
+ start_date: "2026-10-04".into(),
367
+ end_date: "2026-07-06".into(),
368
+ time_zone: Some("America/Sao_Paulo".into()),
369
+ icon: None,
370
+ description: None,
371
+ tone: None,
372
+ effective_from: None,
373
+ effective_to: None,
374
+ };
375
+
376
+ assert!(matches!(
377
+ validate_static_preset(&preset),
378
+ Err(DateRangeMetadataError::InvertedInterval)
379
+ ));
380
+ }
381
+
382
+ #[test]
383
+ fn rejects_invalid_timezone() {
384
+ let preset = StaticDateRangePresetDto {
385
+ id: "invalid-zone".into(),
386
+ label: "Invalid zone".into(),
387
+ start_date: "2026-07-06".into(),
388
+ end_date: "2026-10-04".into(),
389
+ time_zone: Some("America/Sao_Paulo/BRT".into()),
390
+ icon: None,
391
+ description: None,
392
+ tone: None,
393
+ effective_from: None,
394
+ effective_to: None,
395
+ };
396
+
397
+ assert!(matches!(
398
+ validate_static_preset(&preset),
399
+ Err(DateRangeMetadataError::InvalidTimeZone { .. })
400
+ ));
401
+ }
402
+ ```
403
+
404
+ ## Governanca e seguranca
405
+
406
+ - Decida permissao e confidencialidade antes de publicar metadata. Se revelar
407
+ a existencia do periodo ja for sensivel, omita o atalho.
408
+ - O contrato atual de preset estatico nao possui campo publico `disabled`.
409
+ Quando o usuario nao puder usar o periodo, prefira omitir. Publique um item
410
+ indisponivel somente quando existir contrato governado para isso e quando a
411
+ propria existencia do periodo puder ser exibida.
412
+ - Registre no backend a origem do periodo resolvido: calendario, norma,
413
+ tenant, versao de regra, usuario/role e instante de publicacao.
414
+ - Quando a metadata expirar, publique novo snapshot ou remova o atalho. Nao
415
+ conte com o frontend para recalcular vigencia.
416
+ - `tone` e semantico. Use tokens Praxis/host no frontend; nao envie cores
417
+ arbitrarias como parte do preset.
418
+ - `icon`, `label` e `description` devem vir de catalogo governado ou i18n do
419
+ host. Nao use labels como mecanismo primario de roteamento de intencao.
420
+ - Nunca envie callbacks, expressoes JavaScript, snippets, URLs executaveis ou
421
+ `calculateRange` em JSON. Rust publica dados, nao codigo.
422
+
423
+ ## Operacao e testes
424
+
425
+ Contrato minimo entre backend e frontend:
426
+
427
+ 1. backend publica `shortcuts` como lista ordenada de built-ins e presets
428
+ estaticos;
429
+ 2. backend valida datas, timezone, autorizacao, confidencialidade e vigencia;
430
+ 3. frontend materializa o catalogo e preserva `minDate`, `maxDate`,
431
+ `dateFilter`, ordem inicio/fim, RTL, teclado, foco e tema;
432
+ 4. submit/filtro envia `{ startDate, endDate }`.
433
+
434
+ Testes recomendados:
435
+
436
+ - teste Rust de serializacao com `serde_json`;
437
+ - teste Rust de rejeicao de datas invalidas, intervalos invertidos e timezone
438
+ invalido;
439
+ - spec Angular focal de `@praxisui/core` para normalizacao de presets;
440
+ - spec Angular focal de `@praxisui/dynamic-fields` para materializacao em
441
+ `pdx-material-date-range` e `pdx-inline-date-range`;
442
+ - E2E de consumidor na superficie oficial
443
+ `src/app/features/filter-demo/praxis-filter-e2e-inventory.component.ts`,
444
+ rota `http://localhost:4003/filter-demo-e2e-inventory`, cobrindo built-in,
445
+ periodo corporativo estatico, `footer`, `start`, `end`, fallback `auto`,
446
+ tema claro/escuro, desktop, 390 px, teclado, foco, Cancelar/Aplicar, payload
447
+ e RTL quando houver composicao lateral.
448
+
449
+ ## Checklist de publicacao
450
+
451
+ - [ ] O Rust calculou o periodo antes da serializacao.
452
+ - [ ] O JSON nao contem `calculateRange`, funcoes, snippets ou expressoes.
453
+ - [ ] Cada preset estatico tem `id`, `label`, `startDate` e `endDate`.
454
+ - [ ] Datas seguem `YYYY-MM-DD` quando representam periodo civil.
455
+ - [ ] `startDate <= endDate`.
456
+ - [ ] `timeZone`, quando presente, e IANA valido.
457
+ - [ ] Permissao e confidencialidade foram decididas antes de publicar.
458
+ - [ ] O payload observado no consumidor permanece `{ startDate, endDate }`.
459
+ - [ ] `inlineQuickPresets.position` foi validado em `footer`, `start`, `end`
460
+ ou `auto` conforme a superficie usada.
461
+
462
+ ## Criterio sobre skill dedicada
463
+
464
+ Esta documentacao nao cria uma skill nova. A evidencia atual mostra um contrato
465
+ publico estabilizado para atalhos estaticos, mas o fluxo Rust ainda e um guia
466
+ de integracao de host, nao uma rotina transversal repetida em multiplos hosts
467
+ Rust versionados no workspace.
468
+
469
+ Criar uma skill canonica somente quando houver evidencia concreta de repeticao:
470
+ mais de um host Rust publicando a mesma familia de metadata, erros recorrentes
471
+ de validacao/serializacao, manifestos em `praxis-codex-skills` atualizados e
472
+ sincronizacao oficial. A eventual skill deve orientar publicacao de metadata
473
+ resolvida pelo backend, sem duplicar a skill de Dynamic Fields nem mover regra
474
+ de negocio para Angular.
@@ -143,7 +143,7 @@ Use `stateInitialValues` apenas quando o valor do preset precisa continuar coere
143
143
  | -------------- | ----------------------------------------------- | ----------------------------- | ----------------------------------------------- | ----------------------- | ------------------------------------------------------- | -------------------------------------- |
144
144
  | Date input | <span id="dateinput"></span>`dateInput` | integracao com input nativo | quando o host precisa UX Material forte | `string \| Date` | `{ name: 'birthDate', controlType: 'dateInput' }` | `pdx-date-input.json-api.md` |
145
145
  | Date picker | <span id="date"></span>`date` | selecao de data no formulario | se o fluxo pede intervalo | `Date \| string` | `{ name: 'startDate', controlType: 'date' }` | `pdx-material-datepicker.json-api.md` |
146
- | Date range | <span id="daterange"></span>`dateRange` | intervalo de datas | data unica | `{ startDate,endDate }` | `{ name: 'period', controlType: 'dateRange' }` | `pdx-material-date-range.json-api.md` |
146
+ | Date range | <span id="daterange"></span>`dateRange` | intervalo de datas, incluindo periodos corporativos estaticos publicados por metadata | data unica | `{ startDate,endDate }` | `{ name: 'period', controlType: 'dateRange', shortcuts: ['today'] }` | `pdx-material-date-range.json-api.md` |
147
147
  | Datetime local | <span id="datetimelocal"></span>`dateTimeLocal` | data + hora local em um campo | quando o fluxo precisa seletor dedicado de hora | `string` | `{ name: 'appointment', controlType: 'dateTimeLocal' }` | `pdx-datetime-local-input.json-api.md` |
148
148
  | Month input | <span id="month"></span>`month` | mes/ano | datas completas | `string` | `{ name: 'competence', controlType: 'month' }` | `pdx-month-input.json-api.md` |
149
149
  | Time input | <span id="time"></span>`time` | hora simples | intervalo de horario | `string` | `{ name: 'startAt', controlType: 'time' }` | `pdx-time-input.json-api.md` |
@@ -328,7 +328,7 @@ Fonte de verdade: `projects/praxis-metadata-editor/src/lib/config/*.config.ts`.
328
328
 
329
329
  #### `date-range.config.ts`
330
330
 
331
- `label, hint, startPlaceholder, endPlaceholder, defaultValue.startDate, defaultValue.endDate, prefixIcon, prefixIconColor, suffixIconColor, suffixIcon, startView, startAt, touchUi, required, minDate, maxDate, validators.requiredMessage, materialDesign.appearance, materialDesign.color, materialDesign.floatLabel, materialDesign.subscriptSizing, inlineAutoSize.minWidth, inlineAutoSize.maxWidth, inlineAutoSize.minWidthMobile, inlineAutoSize.maxWidthMobile, materialDesign.hideRequiredMarker, errorStateMatcher, startAriaLabel, endAriaLabel, tabIndex, dataAttributes, showShortcuts, shortcutsPosition, applyOnShortcutClick, shortcuts, inlineQuickPresets.enabled, inlineQuickPresets.maxVisible, inlineQuickPresetsAriaLabel, inlineOverlay.applyMode, inlineOverlay.actions.apply.label, inlineOverlay.actions.apply.ariaLabel, inlineOverlay.actions.apply.appearance, inlineOverlay.actions.apply.colorRole, inlineOverlay.actions.cancel.label, inlineOverlay.actions.cancel.ariaLabel, inlineOverlay.actions.cancel.appearance, inlineOverlay.actions.cancel.colorRole, clearButton.enabled, clearButton.icon, clearButton.iconColor, clearButton.tooltip, clearButton.ariaLabel, clearButton.showOnlyWhenFilled`
331
+ `label, hint, startPlaceholder, endPlaceholder, defaultValue.startDate, defaultValue.endDate, prefixIcon, prefixIconColor, suffixIconColor, suffixIcon, startView, startAt, touchUi, required, minDate, maxDate, validators.requiredMessage, materialDesign.appearance, materialDesign.color, materialDesign.floatLabel, materialDesign.subscriptSizing, inlineAutoSize.minWidth, inlineAutoSize.maxWidth, inlineAutoSize.minWidthMobile, inlineAutoSize.maxWidthMobile, materialDesign.hideRequiredMarker, errorStateMatcher, startAriaLabel, endAriaLabel, tabIndex, dataAttributes, showShortcuts, shortcutsPosition, applyOnShortcutClick, shortcuts, inlineQuickPresets.enabled, inlineQuickPresets.maxVisible, inlineQuickPresets.position, inlineQuickPresetsAriaLabel, inlineOverlay.applyMode, inlineOverlay.actions.apply.label, inlineOverlay.actions.apply.ariaLabel, inlineOverlay.actions.apply.appearance, inlineOverlay.actions.apply.colorRole, inlineOverlay.actions.cancel.label, inlineOverlay.actions.cancel.ariaLabel, inlineOverlay.actions.cancel.appearance, inlineOverlay.actions.cancel.colorRole, clearButton.enabled, clearButton.icon, clearButton.iconColor, clearButton.tooltip, clearButton.ariaLabel, clearButton.showOnlyWhenFilled`
332
332
 
333
333
  #### `time-picker.config.ts`
334
334
 
@@ -451,6 +451,8 @@ Convenções importantes para contrato corporativo:
451
451
  - `explicit`: preset ou calendário fica em rascunho no overlay; só `Aplicar` comita no valor final e `Cancelar` descarta.
452
452
  - `inlineQuickPresetsApplyMode` continua como compatibilidade específica do date-range e é interpretado depois de `inlineOverlay.applyMode`.
453
453
  - Labels, aria, `appearance` e `colorRole` dos botões `Aplicar` e `Cancelar` devem vir de `inlineOverlay.actions.*`; os campos `inlineQuickPresets*Label` são fallback legado.
454
+ - `shortcuts` aceita ids built-in, presets TypeScript com `calculateRange()` e `StaticDateRangePreset` serializável com `startDate`/`endDate` resolvidos pelo domínio. O runtime nunca executa regra de negócio recebida por JSON.
455
+ - `inlineQuickPresets.position` aceita `auto`, `footer`, `start` e `end`; `start`/`end` são posições lógicas e voltam para `footer` em viewport estreito ou `touchUi`.
454
456
  - O trigger preenchido deve permanecer previsível em uso corporativo: clique no ícone, no texto ou no espaço interno da pill abre o calendário; clique no clear remove o valor e não abre o calendário.
455
457
 
456
458
  Exemplo rápido para `inlineRange` com presets automáticos:
@@ -340,10 +340,27 @@ Para hosts oficiais:
340
340
  - Snippet:
341
341
 
342
342
  ```json
343
- { "name": "period", "controlType": "inlineDateRange", "showShortcuts": true }
343
+ {
344
+ "name": "period",
345
+ "controlType": "inlineDateRange",
346
+ "showShortcuts": true,
347
+ "shortcuts": [
348
+ "today",
349
+ {
350
+ "id": "periodo-votacao-2026",
351
+ "label": "Periodo de votacao 2026",
352
+ "startDate": "2026-07-06",
353
+ "endDate": "2026-10-04",
354
+ "timeZone": "America/Sao_Paulo",
355
+ "tone": "info"
356
+ }
357
+ ],
358
+ "inlineQuickPresets": { "enabled": true, "maxVisible": 4, "position": "auto" }
359
+ }
344
360
  ```
345
361
 
346
362
  - UX note: shortcuts nao podem mascarar o shape final enviado ao backend
363
+ - Domain note: periodos corporativos chegam resolvidos por metadata; o frontend nao calcula regras eleitorais, fiscais, juridicas, feriados ou dias contaveis.
347
364
  - Docs relacionadas: `dynamic-filter-range-filters-guide`
348
365
 
349
366
  ### <span id="inline-time"></span>`inlineTime`