@trismegisto/spine 3.2.0 → 3.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/README.md +19 -11
  2. package/fesm2022/trismegisto-spine-audit.mjs +16 -12
  3. package/fesm2022/trismegisto-spine-audit.mjs.map +1 -1
  4. package/fesm2022/{trismegisto-spine-auto-service-apps.usage-po9Ds_SU.mjs → trismegisto-spine-auto-service-apps.usage-C0F_MlCo.mjs} +3 -3
  5. package/fesm2022/{trismegisto-spine-auto-service-apps.usage-po9Ds_SU.mjs.map → trismegisto-spine-auto-service-apps.usage-C0F_MlCo.mjs.map} +1 -1
  6. package/fesm2022/{trismegisto-spine-auto-service-auto-service-audit.component-tfGcVR3i.mjs → trismegisto-spine-auto-service-auto-service-audit.component-D8HUpZtA.mjs} +4 -4
  7. package/fesm2022/{trismegisto-spine-auto-service-auto-service-audit.component-tfGcVR3i.mjs.map → trismegisto-spine-auto-service-auto-service-audit.component-D8HUpZtA.mjs.map} +1 -1
  8. package/fesm2022/trismegisto-spine-auto-service-auto-service-client-picker.component-NawbfdLW.mjs +65 -0
  9. package/fesm2022/trismegisto-spine-auto-service-auto-service-client-picker.component-NawbfdLW.mjs.map +1 -0
  10. package/fesm2022/{trismegisto-spine-auto-service-auto-service-client.component-DzmlpLPu.mjs → trismegisto-spine-auto-service-auto-service-client.component-BAfeLyTB.mjs} +32 -19
  11. package/fesm2022/trismegisto-spine-auto-service-auto-service-client.component-BAfeLyTB.mjs.map +1 -0
  12. package/fesm2022/trismegisto-spine-auto-service-auto-service-groups.component-BYjIQ9ID.mjs +635 -0
  13. package/fesm2022/trismegisto-spine-auto-service-auto-service-groups.component-BYjIQ9ID.mjs.map +1 -0
  14. package/fesm2022/{trismegisto-spine-auto-service-auto-service-login-attempts.component-CRvxfSWD.mjs → trismegisto-spine-auto-service-auto-service-login-attempts.component-DoyhkSYc.mjs} +4 -4
  15. package/fesm2022/{trismegisto-spine-auto-service-auto-service-login-attempts.component-CRvxfSWD.mjs.map → trismegisto-spine-auto-service-auto-service-login-attempts.component-DoyhkSYc.mjs.map} +1 -1
  16. package/fesm2022/trismegisto-spine-auto-service-auto-service-news-page.component-CBemH4hr.mjs +432 -0
  17. package/fesm2022/trismegisto-spine-auto-service-auto-service-news-page.component-CBemH4hr.mjs.map +1 -0
  18. package/fesm2022/trismegisto-spine-auto-service-auto-service-ratings-page.component-C_THGTkw.mjs +769 -0
  19. package/fesm2022/trismegisto-spine-auto-service-auto-service-ratings-page.component-C_THGTkw.mjs.map +1 -0
  20. package/fesm2022/trismegisto-spine-auto-service-auto-service-suggestions-page.component-DIeunpQ9.mjs +2123 -0
  21. package/fesm2022/trismegisto-spine-auto-service-auto-service-suggestions-page.component-DIeunpQ9.mjs.map +1 -0
  22. package/fesm2022/{trismegisto-spine-auto-service-auto-service.component-C4FBAefe.mjs → trismegisto-spine-auto-service-auto-service.component-QsIQ61w2.mjs} +36 -23
  23. package/fesm2022/trismegisto-spine-auto-service-auto-service.component-QsIQ61w2.mjs.map +1 -0
  24. package/fesm2022/{trismegisto-spine-auto-service-client.usage-B16r3IHk.mjs → trismegisto-spine-auto-service-client.usage-CJxn9Ysz.mjs} +7 -4
  25. package/fesm2022/trismegisto-spine-auto-service-client.usage-CJxn9Ysz.mjs.map +1 -0
  26. package/fesm2022/{trismegisto-spine-auto-service-groups.technical-9aPPulhy.mjs → trismegisto-spine-auto-service-groups.technical-_jQrg1Qh.mjs} +7 -5
  27. package/fesm2022/trismegisto-spine-auto-service-groups.technical-_jQrg1Qh.mjs.map +1 -0
  28. package/fesm2022/{trismegisto-spine-auto-service-groups.usage-CYh61LFL.mjs → trismegisto-spine-auto-service-groups.usage-OvWjNeeT.mjs} +7 -6
  29. package/fesm2022/{trismegisto-spine-auto-service-groups.usage-CYh61LFL.mjs.map → trismegisto-spine-auto-service-groups.usage-OvWjNeeT.mjs.map} +1 -1
  30. package/fesm2022/trismegisto-spine-auto-service-home.component-rQ3dIGIE.mjs +315 -0
  31. package/fesm2022/trismegisto-spine-auto-service-home.component-rQ3dIGIE.mjs.map +1 -0
  32. package/fesm2022/trismegisto-spine-auto-service-home.technical-Ce7oYRdg.mjs +46 -0
  33. package/fesm2022/trismegisto-spine-auto-service-home.technical-Ce7oYRdg.mjs.map +1 -0
  34. package/fesm2022/trismegisto-spine-auto-service-home.usage-D9R_ZMuU.mjs +48 -0
  35. package/fesm2022/trismegisto-spine-auto-service-home.usage-D9R_ZMuU.mjs.map +1 -0
  36. package/fesm2022/trismegisto-spine-auto-service-news.technical-DV9UpobG.mjs +38 -0
  37. package/fesm2022/trismegisto-spine-auto-service-news.technical-DV9UpobG.mjs.map +1 -0
  38. package/fesm2022/trismegisto-spine-auto-service-news.usage-CeuZnG0V.mjs +48 -0
  39. package/fesm2022/trismegisto-spine-auto-service-news.usage-CeuZnG0V.mjs.map +1 -0
  40. package/fesm2022/trismegisto-spine-auto-service-ratings.technical-QIVj6HBU.mjs +52 -0
  41. package/fesm2022/trismegisto-spine-auto-service-ratings.technical-QIVj6HBU.mjs.map +1 -0
  42. package/fesm2022/trismegisto-spine-auto-service-ratings.usage-BkteY8lz.mjs +45 -0
  43. package/fesm2022/trismegisto-spine-auto-service-ratings.usage-BkteY8lz.mjs.map +1 -0
  44. package/fesm2022/trismegisto-spine-auto-service-suggestions.technical-BtUK6sKD.mjs +69 -0
  45. package/fesm2022/trismegisto-spine-auto-service-suggestions.technical-BtUK6sKD.mjs.map +1 -0
  46. package/fesm2022/trismegisto-spine-auto-service-suggestions.usage-BwO9Hjsx.mjs +72 -0
  47. package/fesm2022/trismegisto-spine-auto-service-suggestions.usage-BwO9Hjsx.mjs.map +1 -0
  48. package/fesm2022/trismegisto-spine-auto-service.mjs +50 -20
  49. package/fesm2022/trismegisto-spine-auto-service.mjs.map +1 -1
  50. package/fesm2022/trismegisto-spine-graphql.mjs +11 -2
  51. package/fesm2022/trismegisto-spine-graphql.mjs.map +1 -1
  52. package/fesm2022/trismegisto-spine-layout.mjs +3171 -1291
  53. package/fesm2022/trismegisto-spine-layout.mjs.map +1 -1
  54. package/fesm2022/trismegisto-spine-modal.mjs +7 -5
  55. package/fesm2022/trismegisto-spine-modal.mjs.map +1 -1
  56. package/fesm2022/trismegisto-spine-notification.mjs +27 -24
  57. package/fesm2022/trismegisto-spine-notification.mjs.map +1 -1
  58. package/fesm2022/trismegisto-spine-routing.mjs +12 -20
  59. package/fesm2022/trismegisto-spine-routing.mjs.map +1 -1
  60. package/fesm2022/trismegisto-spine-shell.mjs +20 -45
  61. package/fesm2022/trismegisto-spine-shell.mjs.map +1 -1
  62. package/fesm2022/trismegisto-spine-side-panel.mjs +7 -5
  63. package/fesm2022/trismegisto-spine-side-panel.mjs.map +1 -1
  64. package/fesm2022/trismegisto-spine.mjs +1972 -282
  65. package/fesm2022/trismegisto-spine.mjs.map +1 -1
  66. package/package.json +6 -6
  67. package/types/trismegisto-spine-audit.d.ts +2 -12
  68. package/types/trismegisto-spine-audit.d.ts.map +1 -1
  69. package/types/trismegisto-spine-auto-service.d.ts +22 -5
  70. package/types/trismegisto-spine-auto-service.d.ts.map +1 -1
  71. package/types/trismegisto-spine-layout.d.ts +1090 -286
  72. package/types/trismegisto-spine-layout.d.ts.map +1 -1
  73. package/types/trismegisto-spine-modal.d.ts +1 -0
  74. package/types/trismegisto-spine-modal.d.ts.map +1 -1
  75. package/types/trismegisto-spine-notification.d.ts +13 -12
  76. package/types/trismegisto-spine-notification.d.ts.map +1 -1
  77. package/types/trismegisto-spine-routing.d.ts +3 -12
  78. package/types/trismegisto-spine-routing.d.ts.map +1 -1
  79. package/types/trismegisto-spine-shell.d.ts +2 -15
  80. package/types/trismegisto-spine-shell.d.ts.map +1 -1
  81. package/types/trismegisto-spine-side-panel.d.ts +1 -0
  82. package/types/trismegisto-spine-side-panel.d.ts.map +1 -1
  83. package/types/trismegisto-spine.d.ts +739 -165
  84. package/types/trismegisto-spine.d.ts.map +1 -1
  85. package/fesm2022/trismegisto-spine-auto-service-auto-service-client-picker.component-Cl7ahisu.mjs +0 -65
  86. package/fesm2022/trismegisto-spine-auto-service-auto-service-client-picker.component-Cl7ahisu.mjs.map +0 -1
  87. package/fesm2022/trismegisto-spine-auto-service-auto-service-client.component-DzmlpLPu.mjs.map +0 -1
  88. package/fesm2022/trismegisto-spine-auto-service-auto-service-groups.component-D6L0gTmd.mjs +0 -605
  89. package/fesm2022/trismegisto-spine-auto-service-auto-service-groups.component-D6L0gTmd.mjs.map +0 -1
  90. package/fesm2022/trismegisto-spine-auto-service-auto-service.component-C4FBAefe.mjs.map +0 -1
  91. package/fesm2022/trismegisto-spine-auto-service-client.usage-B16r3IHk.mjs.map +0 -1
  92. package/fesm2022/trismegisto-spine-auto-service-groups.technical-9aPPulhy.mjs.map +0 -1
  93. package/fesm2022/trismegisto-spine-auto-service-home.component-5_aji1hf.mjs +0 -239
  94. package/fesm2022/trismegisto-spine-auto-service-home.component-5_aji1hf.mjs.map +0 -1
  95. package/fesm2022/trismegisto-spine-auto-service-home.technical-BrVhcgDO.mjs +0 -35
  96. package/fesm2022/trismegisto-spine-auto-service-home.technical-BrVhcgDO.mjs.map +0 -1
  97. package/fesm2022/trismegisto-spine-auto-service-home.usage-D6cb4B3Z.mjs +0 -43
  98. package/fesm2022/trismegisto-spine-auto-service-home.usage-D6cb4B3Z.mjs.map +0 -1
@@ -1,13 +1,13 @@
1
1
  import * as _angular_core from '@angular/core';
2
- import { OnDestroy, OnInit, ElementRef, InjectionToken, Type, Provider } from '@angular/core';
2
+ import { OnDestroy, OnInit, InjectionToken, Type, Provider, TemplateRef } from '@angular/core';
3
3
  import { Router } from '@angular/router';
4
4
  import * as _trismegisto_spine from '@trismegisto/spine';
5
- import { SpineConfig, SpineNewsSlide, Route, ThemeService, ThemePresetService, DensityService, SpineHourCyclePreference, SpineStartPagePreference, SpineNoticeType, SpinePreferencesService, SpineMcpServer, SpineFeatures } from '@trismegisto/spine';
6
- import { BehaviorSubject, Observable, Subject } from 'rxjs';
5
+ import { Route, ThemeService, ThemePresetService, DensityService, SpineConfig, SpinePreferencesService, SpineHourCyclePreference, SpineStartPagePreference, SpineNoticeType, SpineMcpServer, SpineFeatures } from '@trismegisto/spine';
6
+ import { Subject } from 'rxjs';
7
7
  import * as _trismegisto_angular from '@trismegisto/angular';
8
- import { HermesShortcutItem, WorkspaceStore, TabItem, MenuItem, SidebarNode, HermesThemeMode, HermesDensity, HermesSidebarService, SegmentedOption, ComboboxOption } from '@trismegisto/angular';
8
+ import { HermesShortcutItem, WorkspaceStore, TabItem, MenuItem, HermesCommand, SidebarNode, HermesThemeMode, HermesDensity, SegmentedOption, HermesSidebarService, ComboboxOption, BreadcrumbItem, TagColor } from '@trismegisto/angular';
9
9
  import * as _trismegisto_primitives from '@trismegisto/primitives';
10
- import { formatMessage, HermesMotionPreference, Weekday, AlertVariant, HermesFont } from '@trismegisto/primitives';
10
+ import { formatMessage, ShortcutDisplay, HermesMotionPreference, Weekday, AlertVariant, PaginationState } from '@trismegisto/primitives';
11
11
  import * as _orfeu_angular_core from '@orfeu/angular/core';
12
12
  import { AuthorizationService, ViewService, UserProfile, AppDef, RealmAppsService } from '@orfeu/angular/core';
13
13
  import * as _trismegisto_tokens from '@trismegisto/tokens';
@@ -16,147 +16,177 @@ import { RouteDocument } from '@trismegisto/spine/routing';
16
16
  import { SafeHtml } from '@angular/platform-browser';
17
17
  import { Config } from 'dompurify';
18
18
 
19
+ /** `full`: aparência e depois o essencial (primeiro acesso, "Refazer"). `essentials`: só os cartões do essencial. */
20
+ type SpineInitialSetupMode = 'full' | 'essentials';
21
+ /** Etapa na tela: a escolha de aparência ou os cartões do essencial. */
22
+ type SpineInitialSetupStep = 'appearance' | 'essentials';
19
23
  /**
20
- * Fase do tour: `idle` (inativo: não é devido, terminou, foi pulado/interrompido ou não sobrou passo),
21
- * `pending` (vai aparecer: desde o `maybeStart()`/`restart()` até o primeiro passo, enquanto espera o
22
- * shell e os alvos) e `running` (um passo na tela). Quem não pode disputar a tela com o tour (o painel
23
- * de novidades) espera `idle` — não um tempo fixo.
24
- */
25
- type OnboardingState = 'idle' | 'pending' | 'running';
26
- interface OnboardingStep {
27
- /** seletor CSS do alvo; ausente = passo centralizado (boas-vindas/encerramento). */
28
- target?: string;
29
- title: string;
30
- /** pode conter HTML simples (<b>). */
31
- description: string;
32
- }
33
- /**
34
- * Primeiro elemento do seletor que está de fato na tela (tem tamanho e conteúdo). Não usa
35
- * `offsetParent`: ele é `null` pra `position: fixed` (a sidebar) e pra `display: contents`, e o
36
- * passo sumia do tour mesmo com o alvo visível. Com as abas vivas do workspace há uma barra de
37
- * página por aba — só a da aba ativa tem tamanho, e é ela que o holofote precisa achar.
38
- */
39
- declare function findTourTarget(selector: string): HTMLElement | null;
40
- /**
41
- * Onboarding interativo próprio (sem dependência externa). O overlay/holofote e o
42
- * balão são renderizados pelo OnboardingOverlayComponent, que escuta este serviço.
43
- * Aparece uma vez por máquina (flag em localStorage), namespaced por cliente.
24
+ * Configuração inicial em tela cheia (`spine-initial-setup`, montada no layout): no primeiro acesso a pessoa escolhe
25
+ * tema, cor, densidade, tamanho do texto, fonte e animações, com a prévia ao lado, e depois vê o essencial (busca,
26
+ * abas, favoritos, configurações). Pode pular a qualquer momento: pular também conta como feita.
27
+ *
28
+ * "Feita" é da pessoa, não do app (`SpineAccountPreferencesService.setupDone`, no documento global do Argos): quem
29
+ * fez num sistema não a vê de novo em outro. Sem a conta, fica no navegador. Desligada com
30
+ * `SpineFeatures.initialSetup: false`.
44
31
  */
45
- declare class OnboardingService {
46
- private readonly text;
47
- /** Passo atual (null = tour inativo). O overlay component reage a isto. */
48
- readonly current$: BehaviorSubject<{
49
- step: OnboardingStep;
50
- index: number;
51
- total: number;
52
- } | null>;
53
- private readonly stateSubject;
54
- /** Fase do tour (ver `OnboardingState`). Emite o valor atual ao assinar. */
55
- readonly state$: Observable<OnboardingState>;
56
- /** Fase atual, síncrona. */
57
- get state(): OnboardingState;
58
- private readonly doneKey;
59
- private steps;
60
- private index;
61
- private waiting;
62
- constructor(config: SpineConfig | null);
63
- private get done();
64
- private markDone;
65
- /**
66
- * Dispara o tour só se ainda não foi visto nesta máquina. Chamar após o login. Quando é devido, o
67
- * estado vira `pending` NA HORA (síncrono), antes da espera pelo shell — é isso que segura as
68
- * novidades; quando não é, continua `idle`. Chamar de novo com o tour já em andamento não faz nada.
69
- */
70
- maybeStart(): void;
71
- /** Reabre o tour manualmente (menu Ajuda), ignorando a flag. Também passa por `pending` → `running`. */
72
- restart(): void;
73
- /**
74
- * Interrompe o tour (pendente ou na tela) SEM marcar como visto: o automático volta na próxima entrada.
75
- * Usado quando a pessoa abre outra coisa que disputaria a tela com ele (as novidades pelo menu).
76
- */
77
- stop(): void;
78
- /** Passos no idioma ativo (o texto é lido do catálogo ao começar o tour). Descrições com `<b>`. */
79
- private allSteps;
32
+ declare class SpineInitialSetupService {
33
+ private readonly preferences;
34
+ private readonly injector;
35
+ /** Ligada (padrão) ou desligada pelo app (`SpineFeatures.initialSetup: false`). */
36
+ readonly enabled: boolean;
37
+ readonly isOpen: _angular_core.WritableSignal<boolean>;
38
+ readonly mode: _angular_core.WritableSignal<SpineInitialSetupMode>;
39
+ readonly step: _angular_core.WritableSignal<SpineInitialSetupStep>;
40
+ private asked;
80
41
  /**
81
- * Começa do primeiro passo assim que todos os alvos estão na tela, ou no fim do prazo só com os passos
82
- * que têm alvo visível (e os sem alvo). Sem nenhum passo, só marca como visto. Não bloqueia: confere
83
- * de novo a cada `TARGET_POLL_MS`.
42
+ * Chamado uma vez pelo layout na entrada: abre se a configuração ainda não foi feita. Espera a conta responder
43
+ * (`setupDone` deixa de ser `null`), sem prazo: quem decide é a conta, e a falha dela cai no que o navegador sabe.
84
44
  */
85
- private start;
86
- private emit;
87
- private setState;
88
- private clearWaiting;
45
+ maybeOpen(): void;
46
+ /** Abre a configuração inteira (aparência e o essencial), mesmo já feita: "Refazer" nas configurações. */
47
+ open(): void;
48
+ /** Só os cartões do essencial ("Rever o essencial": menu do perfil, atalhos, tela inicial). */
49
+ openEssentials(): void;
89
50
  next(): void;
90
- prev(): void;
91
- /** Encerra o tour (concluído ou pulado) e marca como visto. */
51
+ back(): void;
52
+ /** Concluída ou pulada: marca como feita e fecha. */
92
53
  finish(): void;
93
- get isFirst(): boolean;
94
- get isLast(): boolean;
95
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<OnboardingService, [{ optional: true; }]>;
96
- static ɵprov: _angular_core.ɵɵInjectableDeclaration<OnboardingService>;
54
+ /** `true` quando já deu para decidir (feita ou aberta agora). */
55
+ private decide;
56
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SpineInitialSetupService, never>;
57
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<SpineInitialSetupService>;
97
58
  }
98
59
 
60
+ /** Quem escreveu a novidade, como o argos-admin devolve (nome ou usuário, e a foto). */
61
+ interface SpineNewsAuthor {
62
+ readonly name: string;
63
+ readonly picture: string | null;
64
+ }
65
+ /**
66
+ * Tipo da novidade: só texto (`informativo`); "o que há de novo", com introdução e a lista de mudanças
67
+ * (`implementacao`); ou "como era x como ficou", com introdução e o antes e o agora (`alteracao`).
68
+ */
69
+ type SpineNewsKind = 'informativo' | 'implementacao' | 'alteracao';
70
+ /** Uma novidade na lista (`GET /me/news`): sem o corpo. */
71
+ interface SpineNewsSummary {
72
+ readonly id: string;
73
+ /** Servidor antigo não manda: vale `informativo`. */
74
+ readonly kind?: SpineNewsKind;
75
+ readonly title: string;
76
+ readonly summary: string;
77
+ readonly published_at: string;
78
+ readonly author: SpineNewsAuthor | null;
79
+ }
99
80
  /**
100
- * Painel de novidades do app (ver `provideSpineNews`). Decide o que está devido — ainda não visto
101
- * NESTE navegador e ainda dentro do `until` — e abre sozinho uma vez, depois do tour de boas-vindas.
102
- * O "já visto" é por app (`hermes_<clientId>_news_seen`): novidade de um app não some por ter sido
103
- * vista em outro no mesmo domínio.
81
+ * Uma novidade aberta (`GET /me/news/:id`): com o conteúdo, já saneado pelo servidor ao gravar. `body_html` é o texto
82
+ * (no informativo) ou a introdução (nos outros tipos); `items` é a lista da implementação; `before_html` e `after_html`,
83
+ * os dois lados da alteração.
84
+ */
85
+ interface SpineNewsDetail extends SpineNewsSummary {
86
+ readonly body_html: string;
87
+ readonly items?: readonly string[];
88
+ readonly before_html?: string;
89
+ readonly after_html?: string;
90
+ /** Alterada depois de publicada: quem editou por último e quando (servidor antigo não manda). */
91
+ readonly edited?: (SpineNewsAuthor & {
92
+ readonly at: string;
93
+ }) | null;
94
+ }
95
+ /** Uma página da lista. */
96
+ interface SpineNewsPage {
97
+ readonly news: readonly SpineNewsSummary[];
98
+ readonly total: number;
99
+ readonly page: number;
100
+ readonly limit: number;
101
+ }
102
+ /**
103
+ * Novidades do app, escritas por quem o administra (auto-serviço ou painel central do Argos) e lidas de
104
+ * `argos-admin /me/news` — sempre da aplicação LOGADA e só as publicadas, na validade e para o público da pessoa (o
105
+ * servidor filtra). Sem `SPINE_ADMIN_API` (ou sem HTTP) não há novidades e nada aparece, sem erro.
106
+ *
107
+ * Sem interromper ninguém:
108
+ * - na entrada (`announceOnEntry`), lê as mais recentes e avisa no canto as ainda não anunciadas ("Novidade: …" ou
109
+ * "N novidades", com "Ver"), uma vez por novidade e depois da configuração inicial;
110
+ * - o menu do perfil mostra quantas faltam ver (`unseenCount`) e o Início lista as primeiras (`highlights`);
111
+ * - "Ver" (aviso, menu, Início, configurações) abre o painel lateral (`showAll`), paginado; abrir uma novidade
112
+ * (`markSeen`) a marca como vista.
104
113
  *
105
- * Tour e novidades nunca dividem a tela: na entrada, as novidades esperam o tour ficar `idle` (ver
106
- * `OnboardingState`); fora dela, vale a última ação explícita da pessoa — o tour reaberto pelo menu
107
- * Ajuda fecha o painel de novidades, e as novidades abertas pelo menu interrompem o tour (sem marcá-lo
108
- * como visto).
114
+ * "Anunciada", "vista" e "favorita" são por app, por navegador e por id (`hermes_<clientId>_news_*`): novidade de um
115
+ * app não some por ter sido vista em outro no mesmo domínio. "Marcar como não lida" (`markUnseen`) desfaz o "vista".
109
116
  */
110
117
  declare class SpineNewsService {
111
- private readonly onboarding;
112
- private readonly items;
118
+ private readonly http;
119
+ private readonly auth;
120
+ private readonly adminApi;
121
+ private readonly toast;
122
+ private readonly text;
123
+ private readonly setup;
124
+ private readonly preferences;
125
+ private readonly injector;
113
126
  private readonly seenKey;
114
- /** Slides em exibição (os devidos, ou todos os vigentes quando reaberto pelo menu). */
115
- readonly slides: _angular_core.WritableSignal<readonly SpineNewsSlide[]>;
127
+ private readonly announcedKey;
128
+ private readonly favoritesKey;
129
+ /** Há onde buscar (argos-admin configurado). */
130
+ readonly available: boolean;
116
131
  readonly isOpen: _angular_core.WritableSignal<boolean>;
117
- /** Há alguma novidade vigente — o item "Novidades" do menu só aparece com isto. */
132
+ /** Novidade a abrir junto com o painel (o Início pede uma específica); o painel consome e limpa. */
133
+ readonly requested: _angular_core.WritableSignal<string | null>;
134
+ /** As mais recentes (primeira página), lidas em `refresh`. */
135
+ readonly latest: _angular_core.WritableSignal<readonly SpineNewsSummary[]>;
136
+ /** Há alguma novidade para a pessoa — o item "Novidades" do menu só aparece com isto. */
118
137
  readonly hasAny: _angular_core.Signal<boolean>;
138
+ /** As mais recentes para o card do Início; `unseen` = ainda não aberta neste navegador. */
139
+ readonly highlights: _angular_core.Signal<{
140
+ id: string;
141
+ title: string;
142
+ text: string;
143
+ unseen: boolean;
144
+ }[]>;
145
+ /** Quantas das mais recentes ainda não foram abertas (a contagem do menu do perfil). */
146
+ readonly unseenCount: _angular_core.Signal<number>;
147
+ /** Muda quando o "já visto" é gravado, para quem lê `isUnseen`/`highlights` reler. */
148
+ readonly seenVersion: _angular_core.WritableSignal<number>;
149
+ /** Muda quando os favoritos mudam, para quem lê `isFavorite` reler. */
150
+ readonly favoritesVersion: _angular_core.WritableSignal<number>;
151
+ private announced;
119
152
  constructor();
153
+ private get headers();
154
+ /** Relê as mais recentes; qualquer falha deixa a lista vazia (o item some em vez de mostrar um erro sem contexto). */
155
+ refresh(): Promise<void>;
156
+ /** Uma página da lista (`page` a partir de 1). Falha propaga: o painel mostra o erro com "Tentar de novo". */
157
+ page(page: number, limit: number): Promise<SpineNewsPage>;
158
+ /** Uma novidade com o corpo. */
159
+ detail(id: string): Promise<SpineNewsDetail>;
120
160
  /**
121
- * Chamado uma vez pelo layout na entrada: abre as devidas quando o tour estiver `idle` (não devido,
122
- * concluído, pulado ou sem passo), mais `AFTER_TOUR_MS` para não emendar. Se o tour começar nesse
123
- * intervalo, volta a esperar — por isso a ordem com `OnboardingService.maybeStart()` não importa,
124
- * desde que ele seja chamado dentro desse intervalo (o layout chama os dois juntos, tour primeiro).
125
- */
126
- scheduleOnEntry(): void;
127
- /** Marca como vistas todas as novidades devidas e as abre num único painel. */
128
- showDue(): void;
129
- /**
130
- * Reabre todas as vigentes (menu do perfil), vistas ou não; as devidas entre elas passam a vistas.
131
- * Interrompe o tour se ele estiver pendente ou na tela (ação mais recente da pessoa).
161
+ * Chamado uma vez pelo layout na entrada: lê as mais recentes, espera a configuração inicial se decidir (e terminar,
162
+ * se abriu) e avisa no canto as ainda não anunciadas. Nunca abre o painel sozinho.
132
163
  */
164
+ announceOnEntry(): Promise<void>;
165
+ /** Abre o painel lateral com a lista; as mais recentes deixam de ser anunciadas (o selo "Nova" fica até abrir). */
133
166
  showAll(): void;
167
+ /** Abre o painel já com uma novidade aberta (o card do Início). */
168
+ showItem(id: string): void;
134
169
  close(): void;
135
- private open;
136
- /** Vigentes: sem `until`, ou com `until` ainda não passado (comparação por data, AAAA-MM-DD). */
137
- private current;
138
- private due;
139
- private readSeen;
140
- private markSeen;
170
+ /** Ainda não aberta neste navegador. Lê `seenVersion` (reage a `markSeen`). */
171
+ isUnseen(id: string): boolean;
172
+ /** Abriu a novidade: vista (e anunciada) neste navegador. */
173
+ markSeen(id: string): void;
174
+ /** "Marcar como não lida": volta o selo "Nova" (e conta de novo no menu e no Início); não volta a ser anunciada. */
175
+ markUnseen(id: string): void;
176
+ /** Favorita neste navegador. Lê `favoritesVersion` (reage a `toggleFavorite`). */
177
+ isFavorite(id: string): boolean;
178
+ /** Liga ou desliga o favorito (marcador do painel). */
179
+ toggleFavorite(id: string): void;
180
+ private announce;
181
+ /** Mais recentes ainda não vistas nem anunciadas. */
182
+ private pending;
183
+ private read;
184
+ private remove;
185
+ private write;
141
186
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<SpineNewsService, never>;
142
187
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<SpineNewsService>;
143
188
  }
144
189
 
145
- /** Grupo do painel de atalhos. Id estável; o nome exibido vem do catálogo da lib (`shortcuts.groups`). */
146
- type ShortcutGroupId = 'navigation' | 'actions' | 'general';
147
- /** Item exibido no painel de atalhos (cheatsheet, aberto com "?"). */
148
- interface ShortcutItem {
149
- /** Teclas já em texto, na plataforma atual (`'Ctrl + K'`, `'⌘K'`, `'G depois H'`). */
150
- keys: string;
151
- description: string;
152
- group: ShortcutGroupId;
153
- }
154
- /** Atalhos agrupados, já com o nome do grupo no idioma ativo. */
155
- interface ShortcutGroup {
156
- id: ShortcutGroupId;
157
- name: string;
158
- items: ShortcutItem[];
159
- }
160
190
  /** Ações concretas que o atalho dispara — ligadas pelo LayoutComponent. */
161
191
  interface ShortcutActions {
162
192
  navigate?: (url: string) => void;
@@ -183,7 +213,6 @@ declare class ShortcutService implements OnDestroy {
183
213
  private removers;
184
214
  private readonly userStorage;
185
215
  private readonly hermes;
186
- private readonly lib;
187
216
  private readonly text;
188
217
  /** Emite quando o usuário pede o painel de atalhos (tecla "?" ou menu do perfil). */
189
218
  readonly help$: Subject<void>;
@@ -199,17 +228,6 @@ declare class ShortcutService implements OnDestroy {
199
228
  * Acompanha registro/remoção e a troca de idioma do catálogo da lib.
200
229
  */
201
230
  readonly panelItems: _angular_core.Signal<readonly HermesShortcutItem[]>;
202
- /**
203
- * Lista do painel em texto, no idioma e na plataforma atuais.
204
- * @deprecated Use o `hm-shortcut-list` com `panelItems()` (ou `HermesShortcutService.list()`).
205
- * Mantido para quem montava o próprio painel; sai numa próxima versão.
206
- */
207
- get shortcuts(): ShortcutItem[];
208
- /**
209
- * Atalhos por grupo, na ordem navegação → ações → geral, com o nome do grupo traduzido.
210
- * @deprecated Use o `hm-shortcut-list` (agrupa, traduz e desenha as teclas). Sai numa próxima versão.
211
- */
212
- groups(): ShortcutGroup[];
213
231
  /** Liga as ações e registra os atalhos no `HermesShortcutService` (idempotente: chamadas seguintes só trocam as ações). */
214
232
  setActions(actions: ShortcutActions): void;
215
233
  ngOnDestroy(): void;
@@ -218,8 +236,6 @@ declare class ShortcutService implements OnDestroy {
218
236
  private navigate;
219
237
  /** Navega para o N-ésimo favorito (1-based) lido da store da navegação; N = o dígito do evento. */
220
238
  private goToFavorite;
221
- /** Texto corrido das teclas para a API antiga (`shortcuts`): "Ctrl + K", "G depois H", "… ou …". */
222
- private keysText;
223
239
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<ShortcutService, never>;
224
240
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<ShortcutService>;
225
241
  }
@@ -245,6 +261,12 @@ declare class SpineWorkspaceNavService {
245
261
  readonly focusedChain: _angular_core.Signal<Route[] | null>;
246
262
  private lastKnownPath;
247
263
  constructor();
264
+ /**
265
+ * As abas abertas passam a obedecer à view atual: aba de tela que a pessoa não pode mais abrir fecha (e o
266
+ * conteúdo dela é destruído junto); painel que ficaria sem aba nenhuma mostra o Início no lugar; a aba ativa
267
+ * de cada painel recebe o nome e o ícone da view nova. View vazia (ainda carregando) não fecha nada.
268
+ */
269
+ reconcileWithView(): void;
248
270
  /** Resolve a cadeia de rotas pra uma URL, direto na view atual — sem `Router`, sem `async`
249
271
  * (o componente da folha só é carregado por quem for de fato desenhar o painel). Desce sozinho
250
272
  * por nós organizacionais (com filhos, sem conteúdo próprio) — o rótulo/ícone da aba e o que a
@@ -269,8 +291,9 @@ declare class SpineWorkspaceNavService {
269
291
  * (`hm-sidebar` fixa + `.main` com `hm-workspace`). **Sem barra de breadcrumb própria** — isso
270
292
  * era resíduo do spine antigo (`spine-navigation`), removido: o docs não tem uma, a navegação
271
293
  * inteira mora na sidebar. Entre o header e o corpo fica o `spine-connection-banner` (aviso de conexão
272
- * do `@orfeu/angular`, vazio quando `online`). Os avisos ficam no `spine-notification` (`NotificationService`) e
273
- * no `hm-toast-stack` (`HermesToastService`), os dois montados aqui: o app não monta nenhum.
294
+ * do `@orfeu/angular`, vazio quando `online`). Todos os avisos (os do `NotificationService`,
295
+ * os do `SpineNoticesService` e os do próprio app) saem no `hm-toast-stack` (`HermesToastService`), montado aqui: o
296
+ * app não monta nenhum.
274
297
  *
275
298
  * O `<router-outlet>` que sobra aqui é só pra `/no-permission` (a única rota do shell com
276
299
  * `component` de verdade — o resto da árvore do backend nunca passa pelo `Router` pra renderizar,
@@ -283,7 +306,6 @@ declare class LayoutComponent implements OnInit {
283
306
  private router;
284
307
  private theme;
285
308
  private shortcuts;
286
- private onboarding;
287
309
  private news;
288
310
  /** Aplica no boot o idioma e o fuso que a pessoa escolheu nas configurações. */
289
311
  private readonly preferences;
@@ -295,6 +317,7 @@ declare class LayoutComponent implements OnInit {
295
317
  private readonly idle;
296
318
  private readonly startPage;
297
319
  private readonly accountPreferences;
320
+ protected readonly setup: SpineInitialSetupService;
298
321
  /** Esconde sidebar e área de trabalho quando a rota ATIVA (do Router real, ver
299
322
  * `router.events` abaixo) é a de sem-permissão — nesse caso não existe menu/página válido
300
323
  * como contexto. Note que isto reflete só a URL do painel FOCADO (dona do Router real); um
@@ -302,7 +325,7 @@ declare class LayoutComponent implements OnInit {
302
325
  * o bastante (sem-permissão normalmente bloqueia o app inteiro, não uma aba) pra não justificar
303
326
  * mais complexidade agora. */
304
327
  isNoPermission: boolean;
305
- constructor(router: Router, theme: ThemeService, shortcuts: ShortcutService, onboarding: OnboardingService, news: SpineNewsService);
328
+ constructor(router: Router, theme: ThemeService, shortcuts: ShortcutService, news: SpineNewsService);
306
329
  private matchesNoPermission;
307
330
  ngOnInit(): void;
308
331
  protected onLocalNavigate(panelId: string, href: string): void;
@@ -325,7 +348,6 @@ declare class HeaderComponent implements OnInit {
325
348
  protected densityService: DensityService;
326
349
  private viewService;
327
350
  private router;
328
- private onboarding;
329
351
  private shortcuts;
330
352
  isFullscreen: boolean;
331
353
  element: HTMLElement;
@@ -335,7 +357,10 @@ declare class HeaderComponent implements OnInit {
335
357
  homeRoute: string | null;
336
358
  /** Nome do app (SpineConfig.appName; padrão "Hermes") — quem desenha é o `spine-brand`. */
337
359
  protected readonly appName: string;
338
- private readonly injector;
360
+ /** OnPush: view, crachá, perfil e histórico mudam fora dos eventos do template (observáveis do Orfeu,
361
+ * outra aba, promessa da tela cheia) — cada um marca a view. Tema/densidade/família são signals. */
362
+ private readonly cdr;
363
+ private readonly destroyRef;
339
364
  protected readonly text: {
340
365
  home: string;
341
366
  apps: string;
@@ -350,23 +375,31 @@ declare class HeaderComponent implements OnInit {
350
375
  settings: string;
351
376
  appearance: string;
352
377
  shortcuts: string;
353
- tour: string;
354
378
  news: string;
379
+ newsUnseen: string;
355
380
  logout: string;
356
381
  search: string;
357
382
  searchPlaceholder: string;
358
- recentSearches: string;
359
- clearRecent: string;
360
- noResults: string;
383
+ searchFavorites: string;
384
+ searchRecent: string;
385
+ searchModules: string;
386
+ searchScreens: string;
361
387
  };
362
- protected readonly fmt: typeof formatMessage;
363
388
  private readonly settings;
364
389
  private readonly news;
390
+ /** "Avaliar o {app}": a estrela do cabeçalho (`spine-rate-app-button`) e a janela de avaliação (`spine-rating-window`). */
391
+ private readonly ratings;
392
+ /**
393
+ * O botão de tela cheia só aparece sem avaliação: com ela, a estrela de avaliar ocupa o lugar dele (o atalho de
394
+ * teclado da tela cheia continua) e o cabeçalho não fica com buraco quando `SpineFeatures.ratings` é `false`.
395
+ */
396
+ readonly showFullscreenButton: boolean;
397
+ private readonly setup;
365
398
  private readonly userStorage;
366
399
  private readonly logoutService;
367
400
  /** Por usuário (`SpineUserStorage`): `<clientId>_header_recent_searches_<sub>`; apagada no logout. */
368
401
  private get recentSearchKey();
369
- constructor(authService: AuthorizationService, themeService: ThemeService, themePresetService: ThemePresetService, densityService: DensityService, viewService: ViewService, router: Router, onboarding: OnboardingService, shortcuts: ShortcutService, config: SpineConfig | null);
402
+ constructor(authService: AuthorizationService, themeService: ThemeService, themePresetService: ThemePresetService, densityService: DensityService, viewService: ViewService, router: Router, shortcuts: ShortcutService, config: SpineConfig | null);
370
403
  ngOnInit(): Promise<void>;
371
404
  updateView(data: any): void;
372
405
  /** Primeira rota navegável (DFS), atravessando grupos "transparentes" sem route_redirect. */
@@ -381,40 +414,38 @@ declare class HeaderComponent implements OnInit {
381
414
  switchBadge(badgeTypeId: string): Promise<void>;
382
415
  /** Sai pelo `SpineLogoutService`: com falha no Argos a pessoa fica aqui, com aviso, e o histórico fica. */
383
416
  logout(): Promise<boolean>;
384
- /** Reabre o tour guiado de onboarding. */
385
- startTour(): void;
417
+ /** Os cartões do essencial (busca, abas, favoritos, configurações). */
418
+ openEssentials(): void;
386
419
  /** Abre o painel de atalhos de teclado. */
387
420
  openShortcuts(): void;
388
421
  /** Menu do perfil: achatado (badges, se houver mais de um, + ações), já que `hm-menu`
389
422
  * não tem submenu aninhado como o `hermes-dropdown` antigo tinha para a troca de crachá. */
390
423
  get profileMenuItems(): MenuItem[];
391
424
  onProfileMenuChosen(id: string): void;
392
- quickBox?: ElementRef<HTMLElement>;
393
- quickQuery: string;
425
+ private readonly quickAccess;
394
426
  quickOpen: boolean;
395
- quickResults: QuickItem[];
396
- quickActive: number;
397
427
  private quickIndex;
398
- /** Histórico de buscas (mostrado ao focar com o campo vazio). */
428
+ /** Telas abertas pela busca (Configurações › Dados do navegador conta e apaga esta lista). */
399
429
  recentSearches: QuickItem[];
400
- /** Verdadeiro quando o painel está exibindo o histórico (campo vazio). */
401
- showingRecent: boolean;
430
+ /** Montados ao abrir: favoritos, abertos há pouco e módulos (o que aparece com o campo vazio) e as telas. */
431
+ searchCommands: readonly HermesCommand[];
432
+ protected readonly searchBrowse: string[];
433
+ protected readonly searchIcons: Readonly<Record<string, string>>;
402
434
  /** Achata a árvore de rotas em itens navegáveis (com trilha de ancestrais). */
403
435
  private flattenRoutes;
404
- /** Chamado pelo `(searchRequested)` do `hm-header` (clique no campo ou `Ctrl K`, já tratado
405
- * internamente por ele) — abre o modal de busca, mesmo padrão do `docs/website`
406
- * (`openSearch()` em `app.component.ts`: `@if` monta o `hm-modal` só quando aberto). */
436
+ /** Chamado pelo `(searchRequested)` do `hm-header` (clique no campo ou `Ctrl K`, já tratado por ele): abre a paleta. */
407
437
  onSearchRequested(): void;
408
- /** `(openChange)` do `hm-modal` — fecha ao clicar fora/Esc/botão de fechar. */
409
- onQuickModalOpenChange(open: boolean): void;
410
- onQuickSearch(): void;
411
- quickGo(item: QuickItem): void;
412
- quickMove(delta: number): void;
438
+ /**
439
+ * Comandos da paleta. Cada tela aparece uma vez: favoritos primeiro, depois os abertos há pouco que não são
440
+ * favoritos, os módulos (topo do menu) e, só na busca, o resto das telas. Favoritos e recentes valem só se a
441
+ * view atual (o crachá) ainda alcança a tela.
442
+ */
443
+ private buildSearchCommands;
444
+ private goTo;
413
445
  private readJson;
414
446
  private loadRecent;
415
447
  private pushRecent;
416
- clearRecent(event?: Event): void;
417
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<HeaderComponent, [null, null, null, null, null, null, null, null, { optional: true; }]>;
448
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<HeaderComponent, [null, null, null, null, null, null, null, { optional: true; }]>;
418
449
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<HeaderComponent, "spine-header", never, {}, {}, never, never, true, never>;
419
450
  }
420
451
 
@@ -440,14 +471,15 @@ declare class AppLauncherComponent implements OnInit {
440
471
  settings: string;
441
472
  appearance: string;
442
473
  shortcuts: string;
443
- tour: string;
444
474
  news: string;
475
+ newsUnseen: string;
445
476
  logout: string;
446
477
  search: string;
447
478
  searchPlaceholder: string;
448
- recentSearches: string;
449
- clearRecent: string;
450
- noResults: string;
479
+ searchFavorites: string;
480
+ searchRecent: string;
481
+ searchModules: string;
482
+ searchScreens: string;
451
483
  };
452
484
  private readonly cdr;
453
485
  apps: AppDef[];
@@ -633,107 +665,268 @@ declare class SpineLogoutService {
633
665
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<SpineLogoutService>;
634
666
  }
635
667
 
636
- interface Box {
637
- top: number;
638
- left: number;
639
- width: number;
640
- height: number;
668
+ /** Um cartão do essencial: o texto tem `{key}` onde entra a tecla (desenhada como `<kbd>`). */
669
+ interface EssentialCard {
670
+ readonly id: string;
671
+ readonly icon: string;
672
+ readonly title: string;
673
+ readonly before: string;
674
+ readonly after: string;
675
+ readonly keys: ShortcutDisplay | null;
641
676
  }
642
677
  /**
643
- * Desenho do tour guiado: escurece a tela, recorta um holofote sobre o alvo do passo e põe o balão
644
- * (título, texto, progresso e navegação) onde couber. Segue o `OnboardingService`; recalcula a cada
645
- * passo e quando a janela rola ou muda de tamanho.
678
+ * Tela cheia da configuração inicial (ver `SpineInitialSetupService`): sem cabeçalho nem menu, por cima do shell
679
+ * (que fica `inert` enquanto ela está aberta). Cada escolha vale na hora — chama os mesmos serviços do painel de
680
+ * configurações —, e a prévia ao lado é desenhada com os tokens do tema, então acompanha tudo.
646
681
  */
647
- declare class OnboardingOverlayComponent implements OnInit, OnDestroy {
648
- private onboarding;
649
- protected readonly text: {
650
- progress: string;
682
+ declare class SpineInitialSetupComponent {
683
+ protected readonly setup: SpineInitialSetupService;
684
+ private readonly messages;
685
+ protected readonly t: {
686
+ label: string;
687
+ step: string;
651
688
  skip: string;
652
689
  back: string;
653
690
  next: string;
654
691
  finish: string;
655
- welcomeTitle: string;
656
- welcomeText: string;
657
- appsTitle: string;
658
- appsText: string;
692
+ close: string;
693
+ greeting: string;
694
+ greetingAnonymous: string;
695
+ appearanceIntro: string;
696
+ preview: string;
697
+ previewPage: string;
698
+ essentialsTitle: string;
699
+ essentialsIntro: string;
659
700
  searchTitle: string;
660
701
  searchText: string;
661
- navModulesTitle: string;
662
- navModulesText: string;
663
- navModeTitle: string;
664
- navModeText: string;
665
702
  tabsTitle: string;
666
703
  tabsText: string;
667
- splitTitle: string;
668
- splitText: string;
669
- whereTitle: string;
670
- whereText: string;
671
- themeTitle: string;
672
- themeText: string;
673
- densityTitle: string;
674
- densityText: string;
675
- fullscreenTitle: string;
676
- fullscreenText: string;
677
- profileTitle: string;
678
- profileText: string;
679
- doneTitle: string;
680
- doneText: string;
704
+ favoritesTitle: string;
705
+ favoritesText: string;
706
+ settingsTitle: string;
707
+ settingsText: string;
681
708
  };
682
- protected readonly fmt: typeof formatMessage;
683
- cardRef?: ElementRef<HTMLDivElement>;
684
- step: OnboardingStep | null;
685
- index: number;
686
- total: number;
687
- /** holofote (null = passo centralizado, sem recorte). */
688
- spot: Box | null;
689
- /** posição do balão. */
690
- card: {
691
- top: number;
692
- left: number;
693
- centered: boolean;
709
+ protected readonly s: {
710
+ heading: string;
711
+ appearance: string;
712
+ appearanceKeywords: string;
713
+ theme: string;
714
+ themeDescription: string;
715
+ themeKeywords: string;
716
+ themeLight: string;
717
+ themeDark: string;
718
+ themeSystem: string;
719
+ accent: string;
720
+ accentDescription: string;
721
+ accentKeywords: string;
722
+ density: string;
723
+ densityDescription: string;
724
+ densityKeywords: string;
725
+ comfortable: string;
726
+ compact: string;
727
+ font: string;
728
+ fontDescription: string;
729
+ fontKeywords: string;
730
+ sidebar: string;
731
+ sidebarDescription: string;
732
+ sidebarKeywords: string;
733
+ sidebarHelp: string;
734
+ sidebarAuto: string;
735
+ sidebarFixed: string;
736
+ sidebarCompact: string;
737
+ region: string;
738
+ regionKeywords: string;
739
+ language: string;
740
+ languageDescription: string;
741
+ languageKeywords: string;
742
+ languageAuto: string;
743
+ timeZone: string;
744
+ timeZoneKeywords: string;
745
+ timeZoneHint: string;
746
+ timeZoneAuto: string;
747
+ hourCycle: string;
748
+ hourCycleHint: string;
749
+ hourCycleKeywords: string;
750
+ hourCycleAuto: string;
751
+ hourCycle24: string;
752
+ hourCycle12: string;
753
+ weekStart: string;
754
+ weekStartDescription: string;
755
+ weekStartKeywords: string;
756
+ weekStartAuto: string;
757
+ shortcuts: string;
758
+ shortcutsDescription: string;
759
+ shortcutsKeywords: string;
760
+ setup: string;
761
+ setupDescription: string;
762
+ setupKeywords: string;
763
+ redoSetup: string;
764
+ essentials: string;
765
+ essentialsDescription: string;
766
+ essentialsKeywords: string;
767
+ showEssentials: string;
768
+ accessibility: string;
769
+ accessibilityKeywords: string;
770
+ textSize: string;
771
+ textSizeDescription: string;
772
+ textSizeKeywords: string;
773
+ motion: string;
774
+ motionDescription: string;
775
+ motionKeywords: string;
776
+ motionSystem: string;
777
+ motionReduce: string;
778
+ motionFull: string;
779
+ help: string;
780
+ helpKeywords: string;
781
+ news: string;
782
+ newsDescription: string;
783
+ newsKeywords: string;
784
+ showNews: string;
785
+ browserData: string;
786
+ browserDataDescription: string;
787
+ browserDataKeywords: string;
788
+ recentPages: string;
789
+ recentPagesKeywords: string;
790
+ recentSearches: string;
791
+ recentSearchesKeywords: string;
792
+ favorites: string;
793
+ favoritesKeywords: string;
794
+ pagesCount: _trismegisto_primitives.PluralMessage;
795
+ searchesCount: _trismegisto_primitives.PluralMessage;
796
+ clear: string;
797
+ confirmClear: string;
798
+ cancel: string;
799
+ recentPagesCleared: string;
800
+ recentSearchesCleared: string;
801
+ favoritesCleared: string;
802
+ restorePreferences: string;
803
+ restorePreferencesDescription: string;
804
+ restorePreferencesHelp: string;
805
+ restorePreferencesKeywords: string;
806
+ restore: string;
807
+ confirmRestore: string;
808
+ preferencesRestored: string;
809
+ account: string;
810
+ accountKeywords: string;
811
+ user: string;
812
+ accessLevel: string;
813
+ accessLevelKeywords: string;
814
+ session: string;
815
+ sessionDescription: string;
816
+ sessionKeywords: string;
817
+ sessionUnknown: string;
818
+ sessionExpired: string;
819
+ sessionExpiresIn: string;
820
+ sessionExpiresAt: string;
821
+ accessToken: string;
822
+ accessTokenDescription: string;
823
+ accessTokenKeywords: string;
824
+ copy: string;
825
+ moreAbout: string;
826
+ appTokens: string;
827
+ appTokensDescription: string;
828
+ appTokensKeywords: string;
829
+ appTokensHelp: string;
830
+ groups: string;
831
+ groupsDescription: string;
832
+ groupsKeywords: string;
833
+ groupRole: string;
834
+ groupRoleDisabled: string;
835
+ logout: string;
836
+ logoutDescription: string;
837
+ logoutKeywords: string;
838
+ mfa: string;
839
+ mfaDescription: string;
840
+ mfaKeywords: string;
841
+ signedInAccount: string;
842
+ signedInRealm: string;
843
+ twoFactor: string;
844
+ twoFactorDescription: string;
845
+ twoFactorKeywords: string;
846
+ recoveryCodes: string;
847
+ recoveryCodesDescription: string;
848
+ recoveryCodesKeywords: string;
849
+ sessions: string;
850
+ sessionsDescription: string;
851
+ sessionsKeywords: string;
852
+ sessionsSection: string;
853
+ sessionsSectionDescription: string;
854
+ sessionsSectionKeywords: string;
855
+ about: string;
856
+ aboutKeywords: string;
857
+ application: string;
858
+ version: string;
859
+ versionKeywords: string;
860
+ buildDate: string;
861
+ environment: string;
862
+ environmentKeywords: string;
863
+ links: string;
864
+ linksKeywords: string;
865
+ docs: string;
866
+ reportIssue: string;
867
+ repository: string;
868
+ dependencies: string;
869
+ dependenciesDescription: string;
870
+ dependenciesKeywords: string;
871
+ supportInfo: string;
872
+ supportInfoDescription: string;
873
+ supportInfoKeywords: string;
874
+ noSessionToken: string;
875
+ tokenCopied: string;
876
+ supportCopied: string;
877
+ copyBlocked: string;
694
878
  };
695
- private sub?;
696
- private reposition?;
697
- private readonly cdr;
698
- private readonly injector;
699
- constructor(onboarding: OnboardingService);
700
- get isFirst(): boolean;
701
- get isLast(): boolean;
702
- ngOnInit(): void;
703
- ngOnDestroy(): void;
704
- /** Holofote e balão do passo atual: primeiro com a altura estimada, depois com a medida real. */
705
- private layout;
706
- /**
707
- * Refina a posição depois que o balão foi desenhado (a altura depende do texto). Roda depois do
708
- * render e só marca a view se a posição mudou: sem NG0100 e sem precisar do zone.js.
709
- */
710
- private positionCard;
711
- /** Alvo fora da faixa visível: rola até o meio antes de medir (o `scroll` da janela refaz a conta). */
712
- private bringIntoView;
713
- /** Largura que o CSS dá ao balão (medida quando já existe) e a altura informada. */
714
- private cardSize;
715
- private viewport;
716
- private samePosition;
717
- onViewportChange(): void;
718
- next(): void;
719
- prev(): void;
720
- skip(): void;
721
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<OnboardingOverlayComponent, never>;
722
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<OnboardingOverlayComponent, "spine-onboarding-overlay", never, {}, {}, never, never, true, never>;
879
+ protected readonly fmt: typeof formatMessage;
880
+ private readonly theme;
881
+ private readonly hermesTheme;
882
+ private readonly themeConfig;
883
+ private readonly presets;
884
+ private readonly density;
885
+ private readonly i18n;
886
+ protected readonly preferences: SpinePreferencesService;
887
+ protected readonly appName: string;
888
+ private readonly heading;
889
+ /** Primeiro nome do perfil, para a saudação. */
890
+ protected readonly greeting: string;
891
+ protected readonly stepNumber: _angular_core.Signal<1 | 2>;
892
+ protected readonly stepTotal: _angular_core.Signal<1 | 2>;
893
+ protected readonly families: readonly _trismegisto_tokens.HermesFamily[];
894
+ protected readonly themeMode: _angular_core.Signal<HermesThemeMode>;
895
+ protected readonly appliedTheme: _angular_core.Signal<_trismegisto_tokens.HermesThemeName>;
896
+ protected readonly family: _angular_core.Signal<string>;
897
+ protected readonly densityValue: _angular_core.Signal<HermesDensity>;
898
+ protected readonly fontValue: _angular_core.Signal<_trismegisto_primitives.HermesBuiltinFont>;
899
+ protected readonly textSizeValue: _angular_core.Signal<string>;
900
+ protected readonly themeOptions: readonly SegmentedOption[];
901
+ protected readonly densityOptions: readonly SegmentedOption[];
902
+ protected readonly fontOptions: readonly SegmentedOption[];
903
+ protected readonly motionOptions: readonly SegmentedOption[];
904
+ protected readonly textSizeOptions: _angular_core.Signal<readonly SegmentedOption<string>[]>;
905
+ private readonly platform;
906
+ protected readonly essentials: readonly EssentialCard[];
907
+ constructor();
908
+ protected setThemeMode(mode: string): void;
909
+ protected setFamily(id: string): void;
910
+ protected setDensity(value: string): void;
911
+ protected setFont(value: string): void;
912
+ protected setTextSize(value: string): void;
913
+ protected setMotion(value: string): void;
914
+ private card;
915
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SpineInitialSetupComponent, never>;
916
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<SpineInitialSetupComponent, "spine-initial-setup", never, {}, {}, never, never, true, never>;
723
917
  }
724
918
 
725
919
  /**
726
920
  * Painel de atalhos (cheatsheet). Abre com "?" (via `ShortcutService.help$`) e lista, com o
727
921
  * `hm-shortcut-list` da lib, os atalhos agrupados — com busca e o interruptor dos atalhos de tecla
728
- * única (WCAG 2.1.4; a escolha persiste no `SpinePreferencesService`). Também é o último passo do
729
- * onboarding.
922
+ * única (WCAG 2.1.4; a escolha persiste no `SpinePreferencesService`). Leva também ao essencial.
730
923
  */
731
924
  declare class ShortcutsCheatsheetComponent implements OnInit, OnDestroy {
732
925
  open: boolean;
733
926
  protected readonly text: {
734
927
  heading: string;
735
928
  hint: string;
736
- replayTour: string;
929
+ essentials: string;
737
930
  dismiss: string;
738
931
  openSearch: string;
739
932
  goHome: string;
@@ -747,20 +940,18 @@ declare class ShortcutsCheatsheetComponent implements OnInit, OnDestroy {
747
940
  closeOverlay: string;
748
941
  };
749
942
  private readonly shortcuts;
750
- private readonly onboarding;
943
+ private readonly setup;
944
+ /** OnPush: o "?" e o menu do perfil abrem o painel por `help$`, fora dos eventos deste template. */
945
+ private readonly cdr;
751
946
  /** Atalhos do painel: registrados (favoritos numa linha só) + os que outra peça dispara. */
752
947
  protected readonly items: _angular_core.Signal<readonly _trismegisto_angular.HermesShortcutItem[]>;
753
948
  /** Atalhos de tecla única ligados — sem eles o "?" da dica não funciona. */
754
949
  protected readonly characterKeys: _angular_core.Signal<boolean>;
755
950
  /** Dica com a tecla no meio: o texto do catálogo partido em volta de `{key}`. */
756
951
  protected get hintParts(): string[];
757
- /** @deprecated O painel agora é o `hm-shortcut-list`; use `ShortcutService.panelItems()`. Sai numa próxima versão. */
758
- get groups(): ShortcutGroup[];
759
- /** @deprecated As teclas são desenhadas pelo `hm-shortcut-list`. Sai numa próxima versão. */
760
- chips(keys: string): string[];
761
952
  private sub?;
762
- /** Reabre o tour de onboarding e fecha este painel. */
763
- replayTour(): void;
953
+ /** Abre os cartões do essencial e fecha este painel. */
954
+ openEssentials(): void;
764
955
  ngOnInit(): void;
765
956
  ngOnDestroy(): void;
766
957
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<ShortcutsCheatsheetComponent, never>;
@@ -774,7 +965,7 @@ declare const SPINE_SETTINGS_KEYS: {
774
965
  readonly accessibility: "acessibilidade";
775
966
  readonly region: "regiao";
776
967
  readonly shortcuts: "atalhos";
777
- /** Novidades e tour guiado. */
968
+ /** Novidades, configuração inicial e o essencial. */
778
969
  readonly help: "ajuda";
779
970
  /** Tipos de aviso do app e aviso do navegador (`SpineFeatures.notices`). */
780
971
  readonly notices: "notificacoes";
@@ -787,9 +978,6 @@ declare const SPINE_SETTINGS_KEYS: {
787
978
  readonly sessions: "sessoes";
788
979
  /** Grupos desta aplicação em que a pessoa tem função (argos-admin `/me/groups`); só aparece com algum. */
789
980
  readonly groups: "grupos";
790
- /** @deprecated A seção "Conta e segurança" virou "MFA" e "Sessões": `seguranca` abre a de MFA (ver
791
- * `SPINE_SETTINGS_ALIASES`). Use `mfa` ou `sessions`. */
792
- readonly security: "seguranca";
793
981
  readonly about: "sobre";
794
982
  };
795
983
  /** Chaves antigas de `?settings=` que continuam abrindo a seção que as substituiu (links já publicados). */
@@ -849,6 +1037,17 @@ interface SpineAccountPreferencesDoc {
849
1037
  browserNotices?: boolean;
850
1038
  favorites?: unknown[];
851
1039
  }
1040
+ /**
1041
+ * Chaves que são da pessoa, não do app: com o Argos que tem `{api}/preferences/global`, vão no documento global e
1042
+ * valem em todos os apps (escolhidas uma vez). O resto (menu lateral, atalhos, inatividade, tela inicial, avisos,
1043
+ * favoritos) continua no documento do app.
1044
+ */
1045
+ declare const SPINE_GLOBAL_PREFERENCE_KEYS: readonly ["themeMode", "family", "density", "font", "textScale", "motion", "language", "timeZone", "hourCycle", "weekStart"];
1046
+ /** Documento global (`PUT {api}/preferences/global`): aparência e região, mais a configuração inicial feita. */
1047
+ type SpineGlobalPreferencesDoc = Pick<SpineAccountPreferencesDoc, 'v' | (typeof SPINE_GLOBAL_PREFERENCE_KEYS)[number]> & {
1048
+ /** A configuração inicial já foi feita (ou pulada): não aparece de novo em nenhum app. */
1049
+ setupDone?: boolean;
1050
+ };
852
1051
  /** `local`: só no navegador (recurso desligado, sem API da conta, ou Argos sem o endpoint). */
853
1052
  type SpineAccountPreferencesStatus = 'idle' | 'local' | 'loading' | 'saving' | 'synced' | 'error';
854
1053
  /**
@@ -864,6 +1063,12 @@ type SpineAccountPreferencesStatus = 'idle' | 'local' | 'loading' | 'saving' | '
864
1063
  * - Depois, cada mudança é gravada na conta, agrupada (`SPINE_PREFERENCES_SAVE_DELAY_MS`).
865
1064
  * - Sem a API da conta, com o recurso desligado ou com um Argos que não tem o endpoint (404/400), fica só no
866
1065
  * navegador (`status() === 'local'`), sem erro na tela.
1066
+ * - Com o documento global (`{api}/preferences/global`), a aparência e a região (`SPINE_GLOBAL_PREFERENCE_KEYS`)
1067
+ * vão nele e valem em todos os apps; o do app fica com o resto. Na leitura, o do app é aplicado primeiro (o que
1068
+ * ele ainda tiver de antes do global) e o global por cima. Argos sem a rota global: tudo no do app, como antes.
1069
+ *
1070
+ * Também guarda se a configuração inicial já foi feita (`setupDone`): no documento global quando há, senão no
1071
+ * navegador. Quem já tinha aparência guardada (na conta ou no navegador) conta como feita.
867
1072
  */
868
1073
  declare class SpineAccountPreferencesService {
869
1074
  private readonly browser;
@@ -881,10 +1086,15 @@ declare class SpineAccountPreferencesService {
881
1086
  readonly status: _angular_core.WritableSignal<SpineAccountPreferencesStatus>;
882
1087
  /** Hora da última leitura/gravação bem-sucedida. */
883
1088
  readonly syncedAt: _angular_core.WritableSignal<Date | null>;
1089
+ /** Configuração inicial feita (ou pulada). `null` enquanto a conta não respondeu. */
1090
+ readonly setupDone: _angular_core.WritableSignal<boolean | null>;
884
1091
  /** O documento que o navegador tem agora. */
885
1092
  readonly snapshot: _angular_core.Signal<SpineAccountPreferencesDoc>;
886
1093
  private loaded;
1094
+ /** O Argos tem o documento global (lido com sucesso nesta sessão). */
1095
+ private globalOn;
887
1096
  private lastSaved;
1097
+ private lastSavedGlobal;
888
1098
  private timer;
889
1099
  private readyPromise;
890
1100
  constructor();
@@ -896,12 +1106,22 @@ declare class SpineAccountPreferencesService {
896
1106
  ready(timeoutMs?: number): Promise<void>;
897
1107
  /** Grava agora o que estiver pendente ("Sincronizar agora"); relê a conta se ela ainda não respondeu. */
898
1108
  syncNow(): Promise<void>;
1109
+ /** Marca a configuração inicial como feita (concluída ou pulada): vai para a conta com o resto, ou fica aqui. */
1110
+ completeSetup(): void;
899
1111
  private load;
1112
+ /** O documento global, ou `null` quando o Argos não tem a rota (versão anterior): aí tudo fica no do app. */
1113
+ private loadGlobal;
1114
+ /** O que vai em cada documento agora. Sem o global, tudo no do app. */
1115
+ private split;
900
1116
  /** Aplica o documento da conta pelos mesmos caminhos das telas (cada `set*` também grava no navegador). */
901
1117
  private apply;
902
1118
  private schedule;
1119
+ /** Grava o que mudou desde a última gravação (`force`: os dois documentos, mudados ou não). */
903
1120
  private save;
904
1121
  private failed;
1122
+ /** Configuração inicial feita neste navegador, ou aparência já escolhida aqui antes de ela existir. */
1123
+ private localSetupDone;
1124
+ private writeLocalSetupDone;
905
1125
  private clearTimer;
906
1126
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<SpineAccountPreferencesService, never>;
907
1127
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<SpineAccountPreferencesService>;
@@ -912,7 +1132,7 @@ declare function stable(value: unknown): string;
912
1132
  /** Um aviso do app (`SpineNoticesService.notify`). */
913
1133
  interface SpineNotice {
914
1134
  title: string;
915
- /** Detalhe (segunda linha do aviso do navegador; no aviso da tela vai depois do título). */
1135
+ /** Detalhe (segunda linha do aviso do navegador; no aviso da tela é o texto, com `title` no título). */
916
1136
  body?: string;
917
1137
  /** Caminho interno (`/solicitacoes/42`) aberto pelo "Abrir" do aviso e pelo clique no aviso do navegador. */
918
1138
  url?: string;
@@ -976,7 +1196,7 @@ type BrowserList = 'recents' | 'searches' | 'favorites';
976
1196
  * sessão, sair), MFA (verificação em duas etapas e códigos de recuperação do Argos), Sessões (token de
977
1197
  * acesso, tokens de aplicação e sessões e dispositivos do Argos), Aparência, Acessibilidade (tamanho do texto,
978
1198
  * animações), Região (idioma, fuso, formato de hora, primeiro dia da semana), Atalhos, Dados do navegador
979
- * (limpar listas, restaurar preferências), Ajuda (novidades, tour) e Sobre, mais as seções que o app registrar
1199
+ * (limpar listas, restaurar preferências), Ajuda (novidades, configuração inicial, o essencial) e Sobre, mais as seções que o app registrar
980
1200
  * com `provideSettingsSection`. Tudo vale na hora — cada controle chama o serviço que já persiste aquela
981
1201
  * preferência (tema, densidade, menu lateral, fuso, tamanho do texto…).
982
1202
  *
@@ -1036,10 +1256,14 @@ declare class SettingsPanelComponent {
1036
1256
  shortcuts: string;
1037
1257
  shortcutsDescription: string;
1038
1258
  shortcutsKeywords: string;
1039
- tour: string;
1040
- tourDescription: string;
1041
- tourKeywords: string;
1042
- replayTour: string;
1259
+ setup: string;
1260
+ setupDescription: string;
1261
+ setupKeywords: string;
1262
+ redoSetup: string;
1263
+ essentials: string;
1264
+ essentialsDescription: string;
1265
+ essentialsKeywords: string;
1266
+ showEssentials: string;
1043
1267
  accessibility: string;
1044
1268
  accessibilityKeywords: string;
1045
1269
  textSize: string;
@@ -1164,7 +1388,6 @@ declare class SettingsPanelComponent {
1164
1388
  readonly mfa: "mfa";
1165
1389
  readonly sessions: "sessoes";
1166
1390
  readonly groups: "grupos";
1167
- readonly security: "seguranca";
1168
1391
  readonly about: "sobre";
1169
1392
  };
1170
1393
  /** Seção aberta, com a chave antiga já trocada pela nova (`seguranca` → `mfa`). */
@@ -1182,7 +1405,7 @@ declare class SettingsPanelComponent {
1182
1405
  protected readonly sidebar: HermesSidebarService;
1183
1406
  protected readonly preferences: SpinePreferencesService;
1184
1407
  private readonly shortcutService;
1185
- private readonly onboarding;
1408
+ private readonly setup;
1186
1409
  private readonly auth;
1187
1410
  private readonly authConfig;
1188
1411
  private readonly toast;
@@ -1269,6 +1492,125 @@ declare class SettingsPanelComponent {
1269
1492
  syncError: string;
1270
1493
  syncNow: string;
1271
1494
  };
1495
+ /** Sobre › Avaliação: a média da ferramenta e "Avaliar" (`SpineFeatures.ratings` com `SPINE_ADMIN_API`). */
1496
+ protected readonly ratingsEnabled: boolean;
1497
+ protected readonly ratingText: {
1498
+ rateScreen: string;
1499
+ rateApp: string;
1500
+ ratedApp: string;
1501
+ heading: string;
1502
+ subheading: string;
1503
+ aboutScreen: string;
1504
+ aboutApp: string;
1505
+ score: string;
1506
+ scoreOf: string;
1507
+ scoreNamed: string;
1508
+ scoreShort: string;
1509
+ scoreNames: Record<1 | 2 | 3 | 4 | 5, string>;
1510
+ noScore: string;
1511
+ scaleHint: string;
1512
+ comment: string;
1513
+ commentPlaceholder: string;
1514
+ submit: string;
1515
+ update: string;
1516
+ previous: string;
1517
+ scoreRequired: string;
1518
+ loading: string;
1519
+ thanks: string;
1520
+ updated: string;
1521
+ saveError: string;
1522
+ period: string;
1523
+ periods: Record<"all" | "d7" | "d30" | "d90", string>;
1524
+ refresh: string;
1525
+ appCard: string;
1526
+ screensCard: string;
1527
+ appCardHint: string;
1528
+ screensCardHint: string;
1529
+ scoreMax: string;
1530
+ average: string;
1531
+ total: _trismegisto_primitives.PluralMessage;
1532
+ comments: _trismegisto_primitives.PluralMessage;
1533
+ noRatings: string;
1534
+ distribution: string;
1535
+ distributionRow: string;
1536
+ ranking: string;
1537
+ rankingHint: string;
1538
+ sort: string;
1539
+ sorts: Record<"worst" | "best" | "most", string>;
1540
+ noScreens: string;
1541
+ filterByScreen: string;
1542
+ recent: string;
1543
+ recentHint: string;
1544
+ filterScope: string;
1545
+ allScopes: string;
1546
+ tool: string;
1547
+ screens: string;
1548
+ filterScreen: string;
1549
+ allScreens: string;
1550
+ filterScore: string;
1551
+ allScores: string;
1552
+ withComment: string;
1553
+ clearFilters: string;
1554
+ noComment: string;
1555
+ itemActions: string;
1556
+ copyComment: string;
1557
+ commentCopied: string;
1558
+ copyFailed: string;
1559
+ showAppRatings: string;
1560
+ showScreenRatings: string;
1561
+ emptyList: string;
1562
+ pagination: string;
1563
+ unknownUser: string;
1564
+ loadError: string;
1565
+ forbidden: string;
1566
+ updatedAt: string;
1567
+ details: string;
1568
+ detailsOf: string;
1569
+ tabScreens: string;
1570
+ tabAreas: string;
1571
+ tabTrends: string;
1572
+ viewAll: string;
1573
+ allHeading: string;
1574
+ justNow: string;
1575
+ yesterdayAt: string;
1576
+ dateAt: string;
1577
+ sortsShort: Record<"worst" | "best" | "most", string>;
1578
+ bands: Record<"all" | "bad" | "mid" | "good", string>;
1579
+ bandFilter: string;
1580
+ filterArea: string;
1581
+ allAreas: string;
1582
+ noArea: string;
1583
+ filterByArea: string;
1584
+ screensCount: _trismegisto_primitives.PluralMessage;
1585
+ searchScreens: string;
1586
+ searchScreensLabel: string;
1587
+ searchAreas: string;
1588
+ searchAreasLabel: string;
1589
+ tableEmpty: string;
1590
+ areasEmpty: string;
1591
+ colScreen: string;
1592
+ colArea: string;
1593
+ colScreens: string;
1594
+ colScore: string;
1595
+ colTotal: string;
1596
+ colComments: string;
1597
+ colTrend: string;
1598
+ colOpen: string;
1599
+ tablePagination: string;
1600
+ areasPagination: string;
1601
+ trendOf: string;
1602
+ trendNone: string;
1603
+ trendCaption: string;
1604
+ trendEmpty: string;
1605
+ trendValue: string;
1606
+ trendWeek: string;
1607
+ aboutRating: string;
1608
+ aboutRatingKeywords: string;
1609
+ rateAction: string;
1610
+ noRatingsYet: string;
1611
+ loadingAverage: string;
1612
+ averageError: string;
1613
+ };
1272
1614
  /**
1273
1615
  * "Copiar token de acesso" é ferramenta de desenvolvimento: põe o token da sessão (Bearer de tudo que a
1274
1616
  * pessoa pode fazer) na área de transferência, ao alcance de qualquer app/extensão que leia o clipboard.
@@ -1283,7 +1625,7 @@ declare class SettingsPanelComponent {
1283
1625
  protected readonly appliedTheme: _angular_core.Signal<_trismegisto_tokens.HermesThemeName>;
1284
1626
  protected readonly family: _angular_core.Signal<string>;
1285
1627
  protected readonly densityValue: _angular_core.Signal<HermesDensity>;
1286
- protected readonly fontValue: _angular_core.Signal<HermesFont>;
1628
+ protected readonly fontValue: _angular_core.Signal<_trismegisto_primitives.HermesBuiltinFont>;
1287
1629
  protected readonly families: readonly _trismegisto_tokens.HermesFamily[];
1288
1630
  protected setThemeMode(mode: string): void;
1289
1631
  protected setFamily(id: string): void;
@@ -1316,11 +1658,14 @@ declare class SettingsPanelComponent {
1316
1658
  protected setWeekStart(value: string): void;
1317
1659
  /** Atalhos registrados (favoritos numa linha só) + os que outra peça dispara — os mesmos do painel "?". */
1318
1660
  protected readonly shortcutItems: _angular_core.Signal<readonly _trismegisto_angular.HermesShortcutItem[]>;
1319
- /** "Ver novidades" só quando o app tem alguma vigente (`provideSpineNews`). */
1661
+ /** "Ver novidades" só com alguma novidade para a pessoa (argos-admin `/me/news`). */
1320
1662
  protected readonly hasNews: _angular_core.Signal<boolean>;
1321
- /** Fecha o painel antes: novidades e tour ocupam a tela. */
1663
+ /** "Refazer" a configuração inicial só quando o app não a desligou. */
1664
+ protected readonly setupEnabled: boolean;
1665
+ /** Fecha o painel antes: novidades, configuração inicial e o essencial ocupam a tela. */
1322
1666
  protected showNews(): void;
1323
- protected replayTour(): void;
1667
+ protected redoSetup(): void;
1668
+ protected showEssentials(): void;
1324
1669
  /** Relida quando o painel abre e depois de limpar (as buscas recentes não têm sinal próprio). */
1325
1670
  private readonly dataVersion;
1326
1671
  protected readonly counts: _angular_core.Signal<Readonly<Record<BrowserList, number>>>;
@@ -1376,6 +1721,8 @@ declare class SettingsPanelComponent {
1376
1721
  /** Grupos desta aplicação de que a pessoa é membro (relidos a cada abertura); sem nenhum, a seção some. */
1377
1722
  private readonly myGroupsService;
1378
1723
  protected readonly myGroups: _angular_core.WritableSignal<_trismegisto_spine_layout.ManagedGroup[]>;
1724
+ /** Grupo aberto na seção Grupos (tela de membros): o cabeçalho da seção sai de vista. */
1725
+ protected readonly groupOpen: _angular_core.WritableSignal<boolean>;
1379
1726
  private readonly idle;
1380
1727
  private readonly startPageService;
1381
1728
  private readonly router;
@@ -1500,6 +1847,14 @@ interface ManagedGroup {
1500
1847
  assignable_roles: GroupRole[];
1501
1848
  /** Só Administrador troca a função dos outros membros. */
1502
1849
  can_change_roles: boolean;
1850
+ /** Resumo dos membros (servidor que já manda): total e os primeiros, com foto. */
1851
+ members_count?: number;
1852
+ members_preview?: {
1853
+ user_id: string;
1854
+ username: string;
1855
+ name: string | null;
1856
+ picture: string | null;
1857
+ }[];
1503
1858
  }
1504
1859
  interface GroupMember {
1505
1860
  user_id: string;
@@ -1724,6 +2079,10 @@ declare class SpineAccountSecurityService {
1724
2079
  preferences(): Promise<AccountPreferences>;
1725
2080
  /** Substitui o documento de preferências desta aplicação na conta (até 16 KB). */
1726
2081
  savePreferences(preferences: Record<string, unknown>): Promise<AccountPreferences>;
2082
+ /** Preferências da pessoa que valem em todos os apps (`GET {api}/preferences/global`). */
2083
+ globalPreferences(): Promise<AccountPreferences>;
2084
+ /** Substitui o documento global (até 16 KB). */
2085
+ saveGlobalPreferences(preferences: Record<string, unknown>): Promise<AccountPreferences>;
1727
2086
  private send;
1728
2087
  private request;
1729
2088
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<SpineAccountSecurityService, never>;
@@ -2126,30 +2485,475 @@ declare class SpineDocsService {
2126
2485
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<SpineDocsService>;
2127
2486
  }
2128
2487
 
2488
+ /** Filtro em pílula do topo do painel. */
2489
+ type SpineNewsFilter = 'all' | 'unread' | 'favorites';
2490
+ interface MonthGroup {
2491
+ readonly key: string;
2492
+ readonly label: string;
2493
+ readonly items: readonly SpineNewsSummary[];
2494
+ }
2129
2495
  /**
2130
- * Painel de novidades: um diálogo com carrossel — "olha o que mudou", não tutorial (esse é o tour
2131
- * de boas-vindas). Montado uma vez no layout; quem decide quando abre é o `SpineNewsService`.
2496
+ * Painel lateral de novidades e o modal de leitura. Montado uma vez no layout; quem abre é o `SpineNewsService` (aviso
2497
+ * da entrada, menu do perfil, Início, configurações).
2498
+ *
2499
+ * Painel: sem cards — itens de texto separados por divisor, agrupados por mês (data, selo "Nova", título, resumo em
2500
+ * duas linhas e o autor com foto), com busca ("Buscar novidades…") e filtros em pílula (Todas, Não lidas, Favoritas,
2501
+ * cada um com a contagem). Favoritar é o marcador à direita de cada item. O item aberto ganha a barra de destaque.
2502
+ *
2503
+ * Busca e filtros rodam no navegador: "não lida" e "favorita" só existem nele (por id, no localStorage), então o
2504
+ * painel lê as mais recentes de `/me/news` em páginas de 50, em sequência, até ter todas (teto de 200) e filtra a
2505
+ * lista carregada — as contagens das pílulas batem com o que aparece.
2506
+ *
2507
+ * Modal: trilha "Início › Novidades › título", título grande (com "Nova" se ainda não tinha sido aberta), a linha de
2508
+ * meta (data, autor, tipo), o resumo como texto de abertura e o conteúdo do tipo — o texto (informativo), "O que
2509
+ * mudou" com os checks (implementação) ou o antes e o agora lado a lado (alteração). Rodapé: "Marcar como não lida" e
2510
+ * "Entendi".
2511
+ *
2512
+ * O HTML vem de rich text, saneado pelo servidor ao gravar, e é mostrado pelo próprio `hm-rich-text` em `readonly`
2513
+ * (que passa pela lista branca dele de novo) — nunca por `[innerHTML]`. Os itens da implementação são texto puro.
2132
2514
  */
2133
2515
  declare class SpineNewsComponent {
2134
2516
  protected readonly news: SpineNewsService;
2135
2517
  protected readonly text: {
2136
2518
  heading: string;
2137
- carousel: string;
2138
- dismiss: string;
2519
+ close: string;
2520
+ unseen: string;
2521
+ toastOne: string;
2522
+ toastMany: string;
2523
+ see: string;
2524
+ loading: string;
2525
+ empty: string;
2526
+ loadError: string;
2527
+ retry: string;
2528
+ pages: string;
2529
+ search: string;
2530
+ searchPlaceholder: string;
2531
+ filters: string;
2532
+ filterAll: string;
2533
+ filterUnread: string;
2534
+ filterFavorites: string;
2535
+ favorite: string;
2536
+ unfavorite: string;
2537
+ noResults: string;
2538
+ home: string;
2539
+ changes: string;
2540
+ before: string;
2541
+ after: string;
2542
+ markUnread: string;
2543
+ gotIt: string;
2544
+ kindInformativo: string;
2545
+ kindImplementacao: string;
2546
+ kindAlteracao: string;
2547
+ publishedOn: string;
2548
+ editedOn: string;
2549
+ body: string;
2550
+ detailError: string;
2139
2551
  };
2140
- private readonly document;
2141
- /** O hm-carousel pede `image`/`alt` sempre presentes (vazios = sem imagem / decorativa). A
2142
- * ilustração é desenhada na hora de abrir, com as cores do tema daquele momento. */
2143
- protected readonly slides: _angular_core.Signal<{
2144
- title: string;
2145
- text: string;
2146
- image: string;
2147
- alt: string;
2148
- }[]>;
2552
+ private readonly locale;
2553
+ private readonly dateFormat;
2554
+ private readonly dayFormat;
2555
+ private readonly monthFormat;
2556
+ protected readonly uid: string;
2557
+ protected readonly filters: readonly SpineNewsFilter[];
2558
+ protected readonly hasText: (html: string | undefined) => boolean;
2559
+ /** Tudo o que foi carregado (as mais recentes, até o teto). */
2560
+ protected readonly items: _angular_core.WritableSignal<readonly SpineNewsSummary[]>;
2561
+ protected readonly loading: _angular_core.WritableSignal<boolean>;
2562
+ protected readonly error: _angular_core.WritableSignal<boolean>;
2563
+ readonly query: _angular_core.WritableSignal<string>;
2564
+ readonly filter: _angular_core.WritableSignal<SpineNewsFilter>;
2565
+ /** Página atual e quantas novidades cabem no painel (medido pela altura dele; refeito ao redimensionar). */
2566
+ readonly page: _angular_core.WritableSignal<number>;
2567
+ readonly pageSize: _angular_core.WritableSignal<number>;
2568
+ protected readonly pageState: _angular_core.Signal<PaginationState>;
2569
+ private readonly toolsRef;
2570
+ private readonly listRef;
2571
+ /** Altura de um item, medida no primeiro que aparece (estável: não muda a cada página). */
2572
+ private rowPx;
2573
+ /** A novidade aberta no modal (o resumo, já na mão) e o conteúdo dela quando chega. */
2574
+ protected readonly opened: _angular_core.WritableSignal<SpineNewsSummary | null>;
2575
+ /** Estava "Nova" quando abriu (abrir já marca como vista; o selo do modal lembra que era). */
2576
+ protected readonly openedUnseen: _angular_core.WritableSignal<boolean>;
2577
+ protected readonly detail: _angular_core.WritableSignal<SpineNewsDetail | null>;
2578
+ protected readonly detailError: _angular_core.WritableSignal<boolean>;
2579
+ /** Respostas fora de ordem (reabriu o painel, abriu outra) não sobrescrevem a atual. */
2580
+ private loadSeq;
2581
+ private detailSeq;
2582
+ /** Contagem de cada pílula, sobre o que foi carregado (a busca não muda as contagens). */
2583
+ protected readonly counts: _angular_core.Signal<Record<SpineNewsFilter, number>>;
2584
+ /** O que passa no filtro e na busca (na ordem da lista: da mais recente). */
2585
+ protected readonly filtered: _angular_core.Signal<readonly SpineNewsSummary[]>;
2586
+ /** A página dentro do total (trocar o filtro ou o tamanho da página não deixa numa página que não existe). */
2587
+ protected readonly currentPage: _angular_core.Signal<number>;
2588
+ /** A página atual, agrupada por mês. */
2589
+ protected readonly groups: _angular_core.Signal<readonly MonthGroup[]>;
2590
+ /** "Nova" = ainda não aberta neste navegador (reage a `markSeen`/`markUnseen`). */
2591
+ protected readonly unseen: (id: string) => boolean;
2592
+ protected readonly favorite: (id: string) => boolean;
2593
+ constructor();
2594
+ private measure;
2595
+ protected changePage(next: PaginationState): void;
2596
+ protected filterLabel(f: SpineNewsFilter): string;
2597
+ protected favoriteLabel(item: SpineNewsSummary): string;
2598
+ protected kindOf(item: SpineNewsSummary): SpineNewsKind;
2599
+ protected kindIcon(item: SpineNewsSummary): string;
2600
+ protected kindLabel(item: SpineNewsSummary): string;
2601
+ protected crumbs(item: SpineNewsSummary): BreadcrumbItem[];
2602
+ /** "Início" da trilha leva à tela inicial: fecha o modal e o painel. */
2603
+ protected onCrumb(crumb: BreadcrumbItem): void;
2604
+ protected dayOf(item: SpineNewsSummary): string;
2605
+ protected publishedOn(item: SpineNewsSummary): string;
2606
+ protected editedOn(at: string): string;
2607
+ /** Lê as páginas em sequência (50 por vez) até ter todas ou o teto; a lista aparece já com a primeira. */
2608
+ load(): Promise<void>;
2609
+ /** Abre no modal e marca como vista; o conteúdo chega em seguida. */
2610
+ open(item: SpineNewsSummary): void;
2611
+ /** "Marcar como não lida": volta o selo "Nova" e fecha. */
2612
+ protected markUnread(): void;
2613
+ protected closeItem(): void;
2149
2614
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<SpineNewsComponent, never>;
2150
2615
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<SpineNewsComponent, "spine-news", never, {}, {}, never, never, true, never>;
2151
2616
  }
2152
2617
 
2618
+ /** O que se avalia: a ferramenta inteira (`app`) ou uma tela (`screen`). */
2619
+ type SpineRatingScope = 'app' | 'screen';
2620
+ /** Alvo de uma avaliação. Tela: `screenPath` é a chave (a rota); `screenLabel`, o caminho legível que vai junto. */
2621
+ interface SpineRatingTarget {
2622
+ scope: SpineRatingScope;
2623
+ screenPath?: string | null;
2624
+ screenLabel?: string | null;
2625
+ }
2626
+ /** A avaliação da pessoa como o argos-admin devolve (`/me/ratings`). */
2627
+ interface SpineRating {
2628
+ scope: SpineRatingScope;
2629
+ screen_path: string | null;
2630
+ screen_label: string | null;
2631
+ /** 0 a 10 (10 = 5 estrelas; 7 = 3,5). */
2632
+ score: number;
2633
+ comment: string | null;
2634
+ created_at: string;
2635
+ updated_at: string;
2636
+ }
2637
+ /** Média da ferramenta que qualquer pessoa logada vê (`/me/ratings/summary`): 0 a 10 com uma casa, ou `null`. */
2638
+ interface SpineRatingAverage {
2639
+ average: number | null;
2640
+ total: number;
2641
+ }
2642
+ /** Chave de um alvo ("app" ou "screen:<rota>"): o que foi avaliado nesta sessão e a troca de alvo da janela. */
2643
+ declare const ratingTargetKey: (t: SpineRatingTarget) => string;
2644
+ /** Teto do comentário (o mesmo do servidor e da coluna). */
2645
+ declare const SPINE_RATING_COMMENT_MAX = 500;
2646
+ /**
2647
+ * Avaliações da pessoa (nota de 0 a 10, 5 estrelas com meia, e um comentário) — `argos-admin /me/ratings`, sempre da
2648
+ * aplicação LOGADA (o servidor tira o client do token da sessão) e uma por escopo/tela: avaliar de novo substitui. Liga
2649
+ * com `SpineFeatures.ratings` e só com `SPINE_ADMIN_API`; sem os dois, `enabled` é falso e nada de avaliação aparece.
2650
+ *
2651
+ * `windowTarget` é o que a janela de avaliação (flutuante, montada no cabeçalho) está avaliando: `openApp` (a estrela
2652
+ * do cabeçalho e Configurações › Sobre) e `openScreen` (a estrela da barra da página) trocam o alvo da mesma janela, e
2653
+ * `closeWindow` fecha. `appRated` diz se a pessoa já avaliou a ferramenta (a estrela do cabeçalho fica cheia) e
2654
+ * `appAverage` é a média da ferramenta (Configurações › Sobre); os dois são lidos uma vez, por quem os mostra.
2655
+ */
2656
+ declare class SpineRatingsService {
2657
+ private readonly http;
2658
+ private readonly auth;
2659
+ private readonly adminApi;
2660
+ /** Ligado por padrão (como as sugestões): só `features.ratings: false` desliga; sem a API da conta ou HTTP, nada. */
2661
+ readonly enabled: boolean;
2662
+ /** O que a janela de avaliação está avaliando; `null` = fechada. Uma janela só, para a ferramenta e para a tela. */
2663
+ readonly windowTarget: _angular_core.WritableSignal<SpineRatingTarget | null>;
2664
+ /** Alvos avaliados nesta sessão do app (a estrela da barra fica cheia); não pergunta ao servidor a cada tela. */
2665
+ private readonly ratedNow;
2666
+ /** A pessoa já avaliou a ferramenta (servidor, lido uma vez por `checkAppRated`, ou gravado agora). */
2667
+ readonly appRated: _angular_core.WritableSignal<boolean>;
2668
+ /** Média da ferramenta (`loadAppAverage`); `null` enquanto não foi lida. */
2669
+ readonly appAverage: _angular_core.WritableSignal<SpineRatingAverage | null>;
2670
+ private appRatedChecked;
2671
+ private get url();
2672
+ private get headers();
2673
+ /** "Avaliar o {app}": abre a janela (ou troca o conteúdo dela) para a ferramenta. */
2674
+ openApp(): void;
2675
+ /** "Avaliar esta tela": abre a janela (ou troca o conteúdo dela) para a tela. */
2676
+ openScreen(target: SpineRatingTarget): void;
2677
+ closeWindow(): void;
2678
+ isRated(target: SpineRatingTarget): boolean;
2679
+ /**
2680
+ * Lê uma vez se a pessoa já avaliou a ferramenta (a estrela do cabeçalho). Falha de rede deixa vazia, sem aviso:
2681
+ * avaliar continua funcionando, só a estrela não sabe da avaliação antiga.
2682
+ */
2683
+ checkAppRated(): Promise<void>;
2684
+ /** Média e total da ferramenta (`GET /me/ratings/summary`); quem mostra trata a falha. */
2685
+ loadAppAverage(): Promise<SpineRatingAverage>;
2686
+ /** A avaliação atual da pessoa nesse alvo (para pré-preencher), ou `null` se ainda não avaliou. */
2687
+ mine(target: SpineRatingTarget): Promise<SpineRating | null>;
2688
+ /** Cria ou atualiza a avaliação (nota 0 a 10); comentário vazio vai como `null`. */
2689
+ save(target: SpineRatingTarget, score: number, comment: string): Promise<SpineRating>;
2690
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SpineRatingsService, never>;
2691
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<SpineRatingsService>;
2692
+ }
2693
+
2694
+ /** Nota máxima: 10 = 5 estrelas cheias (cada estrela vale 2, meia estrela vale 1). */
2695
+ declare const SPINE_RATING_SCORE_MAX = 10;
2696
+ type SpineScoreBand = 1 | 2 | 3 | 4 | 5;
2697
+ type SpineStarFill = 'empty' | 'half' | 'full';
2698
+ /** Faixa do rótulo qualitativo de uma nota: 0–2 ruim, 3–4 regular, 5–6 bom, 7–8 muito bom, 9–10 excelente. */
2699
+ declare function spineScoreBand(score: number): SpineScoreBand;
2700
+ /** Preenchimento das 5 estrelas para a nota (uma média vai para a meia estrela mais próxima: 8,4 = 4 estrelas). */
2701
+ declare function spineStarFills(score: number | null | undefined): SpineStarFill[];
2702
+ /**
2703
+ * Estrelas de uma nota de 0 a 10, com meia estrela: 10 = 5 estrelas, 7 = 3,5, 0 = nenhuma. Ao lado, a nota em número
2704
+ * ("7/10"; média com uma casa, "8,4/10").
2705
+ *
2706
+ * - `readonly`: só mostra (média do auto-serviço, Configurações › Sobre). Para o leitor é uma imagem com o nome
2707
+ * "8,4 de 10".
2708
+ * - editável (o formulário de avaliação): um `role="slider"` de 0 a 10 com o valor falado "7 de 10 — Muito bom". As
2709
+ * setas mudam de meia em meia estrela (1 ponto), PageUp/PageDown de estrela em estrela, Home dá 0 e End dá 10. No
2710
+ * mouse, a metade inicial da estrela é a meia e a final é a inteira; clicar de novo na primeira metade da primeira
2711
+ * estrela (nota 1) deixa em 0. Sem nota escolhida (`null`), o valor falado é "Sem nota".
2712
+ *
2713
+ * Meia estrela sem desenho próprio: a estrela vazia por baixo e a cheia por cima, cortada na metade do lado inicial
2714
+ * (em RTL, o lado direito).
2715
+ */
2716
+ declare class SpineRatingStarsComponent {
2717
+ /** Nota de 0 a 10 (média pode ter casa decimal); `null` = sem nota. Editável: muda com o clique e o teclado. */
2718
+ readonly value: _angular_core.ModelSignal<number | null>;
2719
+ /** Só mostra (sem foco nem clique). */
2720
+ readonly readonly: _angular_core.InputSignal<boolean>;
2721
+ /** A nota em número ao lado ("7/10"). */
2722
+ readonly showValue: _angular_core.InputSignal<boolean>;
2723
+ /** Editável: também o rótulo qualitativo ("Muito bom") ao lado da nota. */
2724
+ readonly showName: _angular_core.InputSignal<boolean>;
2725
+ readonly size: _angular_core.InputSignal<"small" | "medium" | "large">;
2726
+ /** Nome acessível do slider (ou `labelledBy`, o id de um rótulo visível). */
2727
+ readonly label: _angular_core.InputSignal<string>;
2728
+ readonly labelledBy: _angular_core.InputSignal<string>;
2729
+ readonly describedBy: _angular_core.InputSignal<string>;
2730
+ readonly invalid: _angular_core.InputSignal<boolean>;
2731
+ private readonly messages;
2732
+ private readonly text;
2733
+ private readonly host;
2734
+ private readonly numberFormat;
2735
+ protected readonly max = 10;
2736
+ /** Prévia do mouse (editável): vence a nota escolhida no desenho, não no valor. */
2737
+ protected readonly hovered: _angular_core.WritableSignal<number | null>;
2738
+ protected readonly shown: _angular_core.Signal<number | null>;
2739
+ protected readonly fills: _angular_core.Signal<SpineStarFill[]>;
2740
+ protected readonly short: _angular_core.Signal<string>;
2741
+ protected readonly named: _angular_core.Signal<string>;
2742
+ /** O que o leitor fala: "8,4 de 10" (imagem) ou "7 de 10 — Muito bom" (slider). */
2743
+ protected readonly spoken: _angular_core.Signal<string>;
2744
+ private format;
2745
+ /** Clique numa metade: aquela nota; de novo na primeira metade (nota 1), 0 -- o "nenhuma estrela" do mouse. */
2746
+ protected pick(score: number): void;
2747
+ protected onKey(event: KeyboardEvent): void;
2748
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SpineRatingStarsComponent, never>;
2749
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<SpineRatingStarsComponent, "spine-rating-stars", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "showValue": { "alias": "showValue"; "required": false; "isSignal": true; }; "showName": { "alias": "showName"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelledBy": { "alias": "labelledBy"; "required": false; "isSignal": true; }; "describedBy": { "alias": "describedBy"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
2750
+ }
2751
+
2752
+ /**
2753
+ * Lugar das ações da tela na barra da página (`spine-page-bar`): um por painel do workspace, fornecido pelo
2754
+ * `spine-page-panel`. A tela não fala com ele direto: usa `<ng-template spinePageActions>`.
2755
+ */
2756
+ declare class SpinePageActionsSlot {
2757
+ readonly template: _angular_core.WritableSignal<TemplateRef<unknown> | null>;
2758
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SpinePageActionsSlot, never>;
2759
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<SpinePageActionsSlot>;
2760
+ }
2761
+ /**
2762
+ * Ações que valem para a tela inteira (período, "Atualizar", "Atualizado em…") na barra da página, à direita do título:
2763
+ *
2764
+ * ```html
2765
+ * <ng-template spinePageActions>
2766
+ * <hm-segmented-control … />
2767
+ * <hm-button icon="refresh" (clicked)="reload()">Atualizar</hm-button>
2768
+ * </ng-template>
2769
+ * ```
2770
+ *
2771
+ * O conteúdo continua sendo da tela (bindings e eventos no componente dela); só aparece na barra do painel em que a tela
2772
+ * está. Fora de um painel (tela montada sozinha, teste), aparece no próprio lugar do `ng-template`. Uma tela por painel:
2773
+ * a última que registrar vale, e sair da tela tira as ações da barra.
2774
+ */
2775
+ declare class SpinePageActionsDirective implements OnDestroy {
2776
+ private readonly slot;
2777
+ private readonly template;
2778
+ constructor();
2779
+ ngOnDestroy(): void;
2780
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SpinePageActionsDirective, never>;
2781
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<SpinePageActionsDirective, "ng-template[spinePageActions]", never, {}, {}, never, never, true, never>;
2782
+ }
2783
+
2784
+ /** Tipos de sugestão, como o Argos guarda (`web.app_suggestions.kind`). */
2785
+ declare const SPINE_SUGGESTION_KINDS: readonly ["melhoria", "nova_funcionalidade", "problema", "outro"];
2786
+ type SpineSuggestionKind = (typeof SPINE_SUGGESTION_KINDS)[number];
2787
+ /**
2788
+ * Os status, na ordem das colunas. Toda sugestão nasce `em_analise` (o antigo "Nova" saiu; ainda aparece no histórico,
2789
+ * pelo `legacyStatuses` do catálogo). `concluida` e `recusada` encerram: recusada sai do quadro na hora, concluída
2790
+ * depois de alguns dias (o servidor decide; ver `done_days` do quadro), e as duas ficam no arquivo.
2791
+ */
2792
+ declare const SPINE_SUGGESTION_STATUSES: readonly ["em_analise", "planejada", "em_desenvolvimento", "concluida", "recusada"];
2793
+ type SpineSuggestionStatus = (typeof SPINE_SUGGESTION_STATUSES)[number];
2794
+ /** Os status que aparecem em "Sugestões do app" (as de todo mundo): a recusada não entra (nem a arquivada pela equipe). */
2795
+ declare const SPINE_SUGGESTION_PUBLIC_STATUSES: readonly ["em_analise", "planejada", "em_desenvolvimento", "concluida"];
2796
+ type SpineSuggestionPublicStatus = (typeof SPINE_SUGGESTION_PUBLIC_STATUSES)[number];
2797
+ /** Ordem de "Sugestões do app": as mais apoiadas (padrão do servidor) ou as mais novas. */
2798
+ declare const SPINE_SUGGESTION_PUBLIC_SORTS: readonly ["votes", "recent"];
2799
+ type SpineSuggestionPublicSort = (typeof SPINE_SUGGESTION_PUBLIC_SORTS)[number];
2800
+ /** Cor da etiqueta de status (a mesma em "Minhas sugestões" e no kanban do auto-serviço). */
2801
+ declare const SPINE_SUGGESTION_STATUS_COLORS: Record<SpineSuggestionStatus, TagColor>;
2802
+ /** Ícone de cada status (coluna do kanban, etiqueta do arquivo). */
2803
+ declare const SPINE_SUGGESTION_STATUS_ICONS: Record<SpineSuggestionStatus, string>;
2804
+ /** Ícone e cor de cada tipo (o modal de nova sugestão e o cartão do kanban). */
2805
+ declare const SPINE_SUGGESTION_KIND_ICONS: Record<SpineSuggestionKind, string>;
2806
+ declare const SPINE_SUGGESTION_KIND_COLORS: Record<SpineSuggestionKind, TagColor>;
2807
+ /** Limites do servidor (colunas da migration): o formulário corta antes. */
2808
+ declare const SPINE_SUGGESTION_LIMITS: {
2809
+ readonly title: 140;
2810
+ readonly description: 4000;
2811
+ readonly screen: 512;
2812
+ };
2813
+ interface SpineSuggestionPerson {
2814
+ user_id: string;
2815
+ username: string | null;
2816
+ name: string | null;
2817
+ picture: string | null;
2818
+ }
2819
+ /** Uma sugestão como o argos-admin devolve (`/me/suggestions` e `/auto-service/:clientId/suggestions`). */
2820
+ interface SpineSuggestion {
2821
+ id: string;
2822
+ /** A chave da sugestão no app ("SUG-12"), a mesma que a equipe usa no quadro. */
2823
+ key?: string;
2824
+ kind: SpineSuggestionKind;
2825
+ title: string;
2826
+ description: string;
2827
+ screen: {
2828
+ path: string | null;
2829
+ label: string | null;
2830
+ };
2831
+ status: SpineSuggestionStatus;
2832
+ position: number;
2833
+ votes: number;
2834
+ /** Quem consulta também apoia (só nas leituras da pessoa). */
2835
+ voted: boolean;
2836
+ comments_count: number;
2837
+ last_comment: {
2838
+ comment: string;
2839
+ created_at: string;
2840
+ } | null;
2841
+ /** Desde quando está no status atual (o último evento para ele; sem evento, a criação). */
2842
+ status_at?: string;
2843
+ created_at: string;
2844
+ updated_at: string;
2845
+ /** Só no auto-serviço: quem pediu, com a foto (null = pessoa removida). */
2846
+ author?: SpineSuggestionPerson | null;
2847
+ /** Só em "já pediram nesta tela": a sugestão é de quem consulta (autora ou relatora). */
2848
+ mine?: boolean;
2849
+ /** Só em "Minhas": quem consulta é relatora (a sugestão dela foi agrupada nesta), não a autora. */
2850
+ reporter?: boolean;
2851
+ /** Só em "Minhas": as sugestões de quem consulta agrupadas nesta ("SUG-30 agrupada em SUG-12"). */
2852
+ merged_from?: Array<{
2853
+ id: string;
2854
+ key: string;
2855
+ title: string;
2856
+ }>;
2857
+ }
2858
+ /**
2859
+ * Uma sugestão em "Sugestões do app" (`/me/suggestions/all`): só o que é público do pedido, de quem quer que seja —
2860
+ * nada do quadro de trabalho da equipe, e os comentários contados e o último são só os públicos.
2861
+ */
2862
+ interface SpineAppSuggestion {
2863
+ id: string;
2864
+ key: string;
2865
+ kind: SpineSuggestionKind;
2866
+ title: string;
2867
+ /** Texto puro (a descrição inteira, até 4000). */
2868
+ description: string;
2869
+ screen: {
2870
+ path: string | null;
2871
+ label: string | null;
2872
+ };
2873
+ status: SpineSuggestionStatus;
2874
+ votes: number;
2875
+ /** Quem consulta apoia. */
2876
+ voted: boolean;
2877
+ /** É de quem consulta: não dá para apoiar (o servidor responde `409 own_suggestion`). */
2878
+ mine: boolean;
2879
+ comments_count: number;
2880
+ last_comment: {
2881
+ comment: string;
2882
+ created_at: string;
2883
+ } | null;
2884
+ created_at: string;
2885
+ /** Quem pediu, com a foto (null = pessoa removida). */
2886
+ author: SpineSuggestionPerson | null;
2887
+ }
2888
+ /** Comentário público de uma sugestão (`/me/suggestions/:id/comments`); `status` = a mudança que ele acompanha. */
2889
+ interface SpineSuggestionComment {
2890
+ id: string;
2891
+ comment: string;
2892
+ status: SpineSuggestionStatus | null;
2893
+ created_at: string;
2894
+ author: SpineSuggestionPerson | null;
2895
+ }
2896
+ interface SpineAppSuggestionsQuery {
2897
+ limit: number;
2898
+ offset: number;
2899
+ status?: SpineSuggestionPublicStatus | '';
2900
+ /** Título, descrição, tela ou a chave ("SUG-12"). */
2901
+ q?: string;
2902
+ /** Só as pedidas nesta rota. */
2903
+ screen?: string;
2904
+ sort?: SpineSuggestionPublicSort;
2905
+ }
2906
+ interface SpineSuggestionDraft {
2907
+ kind: SpineSuggestionKind;
2908
+ title: string;
2909
+ description: string;
2910
+ screen: {
2911
+ path: string | null;
2912
+ label: string | null;
2913
+ };
2914
+ }
2915
+ /**
2916
+ * Sugestões de melhoria da pessoa — `argos-admin /me/suggestions`. Sempre da aplicação LOGADA (o servidor tira o client
2917
+ * do access-token da sessão) e com o token da sessão (o servidor recusa x-app-token). Sem `SPINE_ADMIN_API` não há
2918
+ * para onde mandar: o botão da barra da página nem aparece (`SpineSuggestButtonComponent`).
2919
+ */
2920
+ declare class SpineSuggestionsService {
2921
+ private readonly http;
2922
+ private readonly auth;
2923
+ private readonly adminApi;
2924
+ private url;
2925
+ private get headers();
2926
+ create(draft: SpineSuggestionDraft): Promise<SpineSuggestion>;
2927
+ /** As minhas, da mais nova; `status` filtra uma coluna. */
2928
+ mine(opts: {
2929
+ limit: number;
2930
+ offset: number;
2931
+ status?: SpineSuggestionStatus | '';
2932
+ }): Promise<{
2933
+ suggestions: SpineSuggestion[];
2934
+ total: number;
2935
+ }>;
2936
+ /** "Sugestões do app": as de todas as pessoas no app (menos recusadas e arquivadas), com filtros e paginação. */
2937
+ all(query: SpineAppSuggestionsQuery): Promise<{
2938
+ suggestions: SpineAppSuggestion[];
2939
+ total: number;
2940
+ }>;
2941
+ /** Os comentários públicos de uma sugestão (o detalhe só de leitura), do mais novo. */
2942
+ comments(id: string, page: {
2943
+ limit: number;
2944
+ offset: number;
2945
+ }): Promise<{
2946
+ comments: SpineSuggestionComment[];
2947
+ total: number;
2948
+ }>;
2949
+ /** As ainda abertas da tela, de qualquer pessoa: o modal oferece apoiar em vez de repetir. */
2950
+ byScreen(path: string): Promise<SpineSuggestion[]>;
2951
+ vote(id: string): Promise<void>;
2952
+ unvote(id: string): Promise<void>;
2953
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SpineSuggestionsService, never>;
2954
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<SpineSuggestionsService>;
2955
+ }
2956
+
2153
2957
  /**
2154
2958
  * Modal de documentação das telas: índice (com busca) à esquerda e leitura à direita. Montado uma vez
2155
2959
  * pelo `spine-layout`; abrir, fechar e o que se lê vêm todos do `SpineDocsService`.
@@ -2195,6 +2999,6 @@ declare const SPINE_MARKDOWN_PURIFY_CONFIG: Config;
2195
2999
  /** HTML limpo pelo perfil do spine, ou `null` quando não há DOM (SSR: melhor não renderizar). */
2196
3000
  declare function sanitizeSpineMarkdownHtml(html: string): string | null;
2197
3001
 
2198
- export { AiAgentComponent, AppLauncherComponent, HeaderComponent, LayoutComponent, OnboardingOverlayComponent, OnboardingService, SPINE_BRAND, SPINE_IDLE_WARNING_SECONDS, SPINE_MARKDOWN_PURIFY_CONFIG, SPINE_PREFERENCES_SAVE_DELAY_MS, SPINE_SETTINGS_ALIASES, SPINE_SETTINGS_KEYS, SPINE_SETTINGS_SECTIONS, SettingsPanelComponent, ShortcutService, ShortcutsCheatsheetComponent, SidebarComponent, SpineAccountPreferencesService, SpineAccountSecurityService, SpineAppTokensService, SpineBrandComponent, SpineConnectionBannerComponent, SpineDocsComponent, SpineDocsService, SpineIdleService, SpineIdleWarningComponent, SpineLogoutService, SpineMarkdownComponent, SpineMyGroupsService, SpineNewsComponent, SpineNewsService, SpineNoticesService, SpineSettingsService, SpineStartPageService, accountErrorCode, argosAccountApi, buildMcpConfig, effectiveIdleMinutes, findTourTarget, idleLimits, isInternalPath, provideSettingsSection, resolveSettingsSection, sanitizeSpineMarkdownHtml, stable };
2199
- export type { AccountActivityEntry, AccountActivityPage, AccountBadges, AccountMethod, AccountOverview, AccountPreferences, AccountReauth, AccountSession, AppToken, AppTokenList, AppTokenOptions, CreatedAppToken, DocsEntry, DocsGroup, DocsView, GroupMember, GroupRole, ManagedGroup, OnboardingState, OnboardingStep, RealmUser, ShortcutActions, ShortcutGroup, ShortcutGroupId, ShortcutItem, SpineAccountPreferencesDoc, SpineAccountPreferencesStatus, SpineIdleLimits, SpineNotice, SpineNoticePermission, SpineSettingsSection };
3002
+ export { AiAgentComponent, AppLauncherComponent, HeaderComponent, LayoutComponent, SPINE_BRAND, SPINE_GLOBAL_PREFERENCE_KEYS, SPINE_IDLE_WARNING_SECONDS, SPINE_MARKDOWN_PURIFY_CONFIG, SPINE_PREFERENCES_SAVE_DELAY_MS, SPINE_RATING_COMMENT_MAX, SPINE_RATING_SCORE_MAX, SPINE_SETTINGS_ALIASES, SPINE_SETTINGS_KEYS, SPINE_SETTINGS_SECTIONS, SPINE_SUGGESTION_KINDS, SPINE_SUGGESTION_KIND_COLORS, SPINE_SUGGESTION_KIND_ICONS, SPINE_SUGGESTION_LIMITS, SPINE_SUGGESTION_PUBLIC_SORTS, SPINE_SUGGESTION_PUBLIC_STATUSES, SPINE_SUGGESTION_STATUSES, SPINE_SUGGESTION_STATUS_COLORS, SPINE_SUGGESTION_STATUS_ICONS, SettingsPanelComponent, ShortcutService, ShortcutsCheatsheetComponent, SidebarComponent, SpineAccountPreferencesService, SpineAccountSecurityService, SpineAppTokensService, SpineBrandComponent, SpineConnectionBannerComponent, SpineDocsComponent, SpineDocsService, SpineIdleService, SpineIdleWarningComponent, SpineInitialSetupComponent, SpineInitialSetupService, SpineLogoutService, SpineMarkdownComponent, SpineMyGroupsService, SpineNewsComponent, SpineNewsService, SpineNoticesService, SpinePageActionsDirective, SpinePageActionsSlot, SpineRatingStarsComponent, SpineRatingsService, SpineSettingsService, SpineStartPageService, SpineSuggestionsService, accountErrorCode, argosAccountApi, buildMcpConfig, effectiveIdleMinutes, idleLimits, isInternalPath, provideSettingsSection, ratingTargetKey, resolveSettingsSection, sanitizeSpineMarkdownHtml, spineScoreBand, spineStarFills, stable };
3003
+ export type { AccountActivityEntry, AccountActivityPage, AccountBadges, AccountMethod, AccountOverview, AccountPreferences, AccountReauth, AccountSession, AppToken, AppTokenList, AppTokenOptions, CreatedAppToken, DocsEntry, DocsGroup, DocsView, GroupMember, GroupRole, ManagedGroup, RealmUser, ShortcutActions, SpineAccountPreferencesDoc, SpineAccountPreferencesStatus, SpineAppSuggestion, SpineAppSuggestionsQuery, SpineGlobalPreferencesDoc, SpineIdleLimits, SpineInitialSetupMode, SpineInitialSetupStep, SpineNewsAuthor, SpineNewsDetail, SpineNewsFilter, SpineNewsKind, SpineNewsPage, SpineNewsSummary, SpineNotice, SpineNoticePermission, SpineRating, SpineRatingAverage, SpineRatingScope, SpineRatingTarget, SpineScoreBand, SpineSettingsSection, SpineStarFill, SpineSuggestion, SpineSuggestionComment, SpineSuggestionDraft, SpineSuggestionKind, SpineSuggestionPerson, SpineSuggestionPublicSort, SpineSuggestionPublicStatus, SpineSuggestionStatus };
2200
3004
  //# sourceMappingURL=trismegisto-spine-layout.d.ts.map