@trismegisto/spine 3.3.3 → 3.3.5
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.
- package/README.md +15 -2
- package/fesm2022/trismegisto-spine-audit.mjs +6 -6
- package/fesm2022/trismegisto-spine-audit.mjs.map +1 -1
- package/fesm2022/{trismegisto-spine-auto-service-auto-service-client.component-BAfeLyTB.mjs → trismegisto-spine-auto-service-auto-service-client.component-kAXaCM5W.mjs} +8 -8
- package/fesm2022/{trismegisto-spine-auto-service-auto-service-client.component-BAfeLyTB.mjs.map → trismegisto-spine-auto-service-auto-service-client.component-kAXaCM5W.mjs.map} +1 -1
- package/fesm2022/{trismegisto-spine-auto-service-auto-service-groups.component-BYjIQ9ID.mjs → trismegisto-spine-auto-service-auto-service-groups.component-DE2QIGRH.mjs} +251 -85
- package/fesm2022/trismegisto-spine-auto-service-auto-service-groups.component-DE2QIGRH.mjs.map +1 -0
- package/fesm2022/{trismegisto-spine-auto-service-auto-service-news-page.component-CBemH4hr.mjs → trismegisto-spine-auto-service-auto-service-news-page.component-BW7BJ0oD.mjs} +2 -2
- package/fesm2022/{trismegisto-spine-auto-service-auto-service-news-page.component-CBemH4hr.mjs.map → trismegisto-spine-auto-service-auto-service-news-page.component-BW7BJ0oD.mjs.map} +1 -1
- package/fesm2022/{trismegisto-spine-auto-service-auto-service-ratings-page.component-C_THGTkw.mjs → trismegisto-spine-auto-service-auto-service-ratings-page.component-CHPU-QLJ.mjs} +2 -2
- package/fesm2022/{trismegisto-spine-auto-service-auto-service-ratings-page.component-C_THGTkw.mjs.map → trismegisto-spine-auto-service-auto-service-ratings-page.component-CHPU-QLJ.mjs.map} +1 -1
- package/fesm2022/trismegisto-spine-auto-service-auto-service-suggestions-page.component-CkiCTmXD.mjs +3733 -0
- package/fesm2022/trismegisto-spine-auto-service-auto-service-suggestions-page.component-CkiCTmXD.mjs.map +1 -0
- package/fesm2022/{trismegisto-spine-auto-service-auto-service.component-QsIQ61w2.mjs → trismegisto-spine-auto-service-auto-service.component-D58Ht9PH.mjs} +7 -7
- package/fesm2022/{trismegisto-spine-auto-service-auto-service.component-QsIQ61w2.mjs.map → trismegisto-spine-auto-service-auto-service.component-D58Ht9PH.mjs.map} +1 -1
- package/fesm2022/{trismegisto-spine-auto-service-groups.technical-_jQrg1Qh.mjs → trismegisto-spine-auto-service-groups.technical-CB1D3ANC.mjs} +12 -3
- package/fesm2022/trismegisto-spine-auto-service-groups.technical-CB1D3ANC.mjs.map +1 -0
- package/fesm2022/{trismegisto-spine-auto-service-groups.usage-OvWjNeeT.mjs → trismegisto-spine-auto-service-groups.usage-De2MhlE7.mjs} +7 -2
- package/fesm2022/{trismegisto-spine-auto-service-groups.usage-OvWjNeeT.mjs.map → trismegisto-spine-auto-service-groups.usage-De2MhlE7.mjs.map} +1 -1
- package/fesm2022/{trismegisto-spine-auto-service-suggestions.technical-BtUK6sKD.mjs → trismegisto-spine-auto-service-suggestions.technical-CGBBzAR8.mjs} +14 -1
- package/fesm2022/{trismegisto-spine-auto-service-suggestions.technical-BtUK6sKD.mjs.map → trismegisto-spine-auto-service-suggestions.technical-CGBBzAR8.mjs.map} +1 -1
- package/fesm2022/{trismegisto-spine-auto-service-suggestions.usage-BwO9Hjsx.mjs → trismegisto-spine-auto-service-suggestions.usage-DnAJS-Z0.mjs} +26 -3
- package/fesm2022/trismegisto-spine-auto-service-suggestions.usage-DnAJS-Z0.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-auto-service.mjs +24 -11
- package/fesm2022/trismegisto-spine-auto-service.mjs.map +1 -1
- package/fesm2022/{trismegisto-spine-layout-suggestions-page.component-xI2gDMok.mjs → trismegisto-spine-layout-suggestions-page.component-CEKMqera.mjs} +3 -3
- package/fesm2022/{trismegisto-spine-layout-suggestions-page.component-xI2gDMok.mjs.map → trismegisto-spine-layout-suggestions-page.component-CEKMqera.mjs.map} +1 -1
- package/fesm2022/{trismegisto-spine-layout-trismegisto-spine-layout-Clphrsgc.mjs → trismegisto-spine-layout-trismegisto-spine-layout-DiAfxIGP.mjs} +428 -93
- package/fesm2022/trismegisto-spine-layout-trismegisto-spine-layout-DiAfxIGP.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-layout.mjs +1 -1
- package/fesm2022/trismegisto-spine-side-panel.mjs +1 -1
- package/fesm2022/trismegisto-spine-side-panel.mjs.map +1 -1
- package/fesm2022/trismegisto-spine.mjs +528 -10
- package/fesm2022/trismegisto-spine.mjs.map +1 -1
- package/package.json +6 -6
- package/types/trismegisto-spine-auto-service.d.ts +20 -4
- package/types/trismegisto-spine-auto-service.d.ts.map +1 -1
- package/types/trismegisto-spine-layout.d.ts +327 -63
- package/types/trismegisto-spine-layout.d.ts.map +1 -1
- package/types/trismegisto-spine.d.ts +221 -3
- package/types/trismegisto-spine.d.ts.map +1 -1
- package/fesm2022/trismegisto-spine-auto-service-auto-service-groups.component-BYjIQ9ID.mjs.map +0 -1
- package/fesm2022/trismegisto-spine-auto-service-auto-service-suggestions-page.component-mMjE3JOL.mjs +0 -2179
- package/fesm2022/trismegisto-spine-auto-service-auto-service-suggestions-page.component-mMjE3JOL.mjs.map +0 -1
- package/fesm2022/trismegisto-spine-auto-service-groups.technical-_jQrg1Qh.mjs.map +0 -1
- package/fesm2022/trismegisto-spine-auto-service-suggestions.usage-BwO9Hjsx.mjs.map +0 -1
- package/fesm2022/trismegisto-spine-layout-trismegisto-spine-layout-Clphrsgc.mjs.map +0 -1
|
@@ -3,18 +3,19 @@ import { inject, ChangeDetectorRef, ChangeDetectionStrategy, Component, Injectio
|
|
|
3
3
|
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
|
|
4
4
|
import * as i3 from '@angular/router';
|
|
5
5
|
import { RouterLink, Router, NavigationEnd, NavigationSkipped, RouterOutlet } from '@angular/router';
|
|
6
|
-
import { firstValueFrom, filter, Subject, take, debounceTime, distinctUntilChanged } from 'rxjs';
|
|
7
|
-
import { MenuButtonComponent, HermesThemeService, HERMES_THEME_CONFIG, HermesSidebarService, HermesToastService, IconComponent, ButtonComponent, SkeletonComponent, TextareaComponent, FloatingWindowComponent, IconButtonComponent, AccountAvatarComponent, BadgeComponent, PopoverComponent, PopoverTriggerDirective, HermesShortcutService, HeaderComponent as HeaderComponent$1, CommandPaletteComponent, createPersistedWorkspaceStore, HERMES_WORKSPACE_PERSISTENCE_CONFIG, findPanelTabs, SidebarComponent as SidebarComponent$1, SidebarNodeComponent, HermesI18nService, SegmentedControlComponent, ThemePickerComponent, AlertComponent, BreadcrumbComponent, DrawerComponent, ModalComponent, PaginatorComponent, RichTextComponent, SearchFieldComponent, ShortcutListComponent, TagComponent, CodeInputComponent, InputComponent, RadioComponent, CheckboxComponent, CodeViewerComponent, SelectComponent, AvatarGroupComponent, HERMES_SIDEBAR_CONFIG, ComboboxComponent, SettingsDialogComponent, SettingsRowComponent, SettingsSectionComponent, ToggletipComponent, TooltipDirective, LoadingSquareComponent, WorkspaceComponent, ToastStackComponent, MessageScrollerComponent, BubbleComponent, MessageComponent, MessageDividerComponent } from '@trismegisto/angular';
|
|
6
|
+
import { firstValueFrom, filter, Subject, take, Subscription, debounceTime, distinctUntilChanged } from 'rxjs';
|
|
7
|
+
import { MenuButtonComponent, HermesThemeService, HERMES_THEME_CONFIG, HermesSidebarService, HermesToastService, IconComponent, ButtonComponent, SkeletonComponent, TextareaComponent, FloatingWindowComponent, IconButtonComponent, AccountAvatarComponent, BadgeComponent, PopoverComponent, PopoverTriggerDirective, HermesShortcutService, HeaderComponent as HeaderComponent$1, CommandPaletteComponent, panelIdsInOrder, createPersistedWorkspaceStore, HERMES_WORKSPACE_PERSISTENCE_CONFIG, findPanelTabs, canSplitPanel, cyclicPanelNeighbor, ContextMenuDirective, SidebarComponent as SidebarComponent$1, SidebarNodeComponent, HermesI18nService, SegmentedControlComponent, ThemePickerComponent, AlertComponent, BreadcrumbComponent, DrawerComponent, ModalComponent, PaginatorComponent, RichTextComponent, SearchFieldComponent, ShortcutListComponent, TagComponent, CodeInputComponent, InputComponent, RadioComponent, CheckboxComponent, CodeViewerComponent, SelectComponent, AvatarGroupComponent, HERMES_SIDEBAR_CONFIG, ComboboxComponent, SettingsDialogComponent, SettingsRowComponent, SettingsSectionComponent, ToggletipComponent, TooltipDirective, LoadingSquareComponent, registerUnsavedChanges, HermesUnsavedChangesService, WorkspaceComponent, ToastStackComponent, SkipLinkComponent, MessageScrollerComponent, BubbleComponent, MessageComponent, MessageDividerComponent } from '@trismegisto/angular';
|
|
8
|
+
import { HermesSidebarService as HermesSidebarService$1 } from '@trismegisto/angular/sidebar';
|
|
8
9
|
import { ModalComponent as ModalComponent$1 } from '@trismegisto/spine/modal';
|
|
9
10
|
import { SidePanelComponent } from '@trismegisto/spine/side-panel';
|
|
10
11
|
import * as i2$1 from '@trismegisto/spine';
|
|
11
12
|
import { SPINE_MESSAGES, SPINE_CONFIG, ThemeService, resolveSpineLogo, SpinePreferencesService, SpineQuickAccessService, DensityService, ThemePresetService, SPINE_ADMIN_API, SpineUserStorage, SPINE_USER_STORAGE_KEYS, spineRoutesOf, routerIdOf, SPINE_IDLE_OPTIONS, APP_PACKAGE_INFO, registerSpineBuiltinPage } from '@trismegisto/spine';
|
|
12
13
|
import * as i2 from '@angular/common';
|
|
13
|
-
import { CommonModule, NgTemplateOutlet, NgComponentOutlet, isPlatformBrowser } from '@angular/common';
|
|
14
|
+
import { CommonModule, NgTemplateOutlet, NgComponentOutlet, isPlatformBrowser, Location } from '@angular/common';
|
|
14
15
|
import * as i1 from '@orfeu/angular/core';
|
|
15
16
|
import { AuthorizationService, AUTH_CONFIG, ViewService, RealmAppsService } from '@orfeu/angular/core';
|
|
16
17
|
import { HttpClient, HttpErrorResponse, HttpHeaders, HttpParams } from '@angular/common/http';
|
|
17
|
-
import { urlPath, formatMessage, pluralMessage, tabUrl, HERMES_FONTS, HERMES_TEXT_SCALES,
|
|
18
|
+
import { urlPath, formatMessage, pluralMessage, detectShortcutPlatform, tabUrl, HERMES_FONTS, HERMES_TEXT_SCALES, formatShortcut, formatMessageHtml, weekdayNames, FALLBACK_FAMILY, findPanelTabs as findPanelTabs$1, isMessageContinuation } from '@trismegisto/primitives';
|
|
18
19
|
import { NotificationService, AlertType } from '@trismegisto/spine/notification';
|
|
19
20
|
import { resolveEffectiveRouteChain, ComponentDistributorService, componentRouterId, LoggerService } from '@trismegisto/spine/routing';
|
|
20
21
|
import * as i1$1 from '@angular/forms';
|
|
@@ -334,8 +335,8 @@ const READY_TIMEOUT_MS = 2000;
|
|
|
334
335
|
const SETUP_DONE_SUFFIX = '_setup_done';
|
|
335
336
|
/**
|
|
336
337
|
* Chaves que são da pessoa, não do app: com o Argos que tem `{api}/preferences/global`, vão no documento global e
|
|
337
|
-
* valem em todos os apps (escolhidas uma vez). O resto (menu lateral, atalhos, inatividade, tela inicial,
|
|
338
|
-
* favoritos) continua no documento do app.
|
|
338
|
+
* valem em todos os apps (escolhidas uma vez). O resto (menu lateral, dividir abas, atalhos, inatividade, tela inicial,
|
|
339
|
+
* avisos, favoritos) continua no documento do app.
|
|
339
340
|
*/
|
|
340
341
|
const SPINE_GLOBAL_PREFERENCE_KEYS = [
|
|
341
342
|
'themeMode', 'family', 'density', 'font', 'textScale', 'motion', 'language', 'timeZone', 'hourCycle', 'weekStart',
|
|
@@ -343,8 +344,8 @@ const SPINE_GLOBAL_PREFERENCE_KEYS = [
|
|
|
343
344
|
/**
|
|
344
345
|
* Preferências na conta (`SpineFeatures.accountPreferences`): espelha no Argos (`GET/PUT {api}/preferences`, por
|
|
345
346
|
* usuário e aplicação) o que o painel de configurações guarda no navegador — tema, cor, densidade, fonte, menu
|
|
346
|
-
* lateral, idioma, fuso, relógio, primeiro dia da semana, tamanho do texto, animações, atalhos de tecla
|
|
347
|
-
* inatividade, tela inicial, tipos de aviso e favoritos. As telas Aparência, Região etc. não mudam: o
|
|
347
|
+
* lateral, dividir abas, idioma, fuso, relógio, primeiro dia da semana, tamanho do texto, animações, atalhos de tecla
|
|
348
|
+
* única, inatividade, tela inicial, tipos de aviso e favoritos. As telas Aparência, Região etc. não mudam: o
|
|
348
349
|
* armazenamento local continua sendo a fonte de cada tela, e este serviço só sincroniza.
|
|
349
350
|
*
|
|
350
351
|
* - No início da sessão (`start()`, chamado pelo layout e pelo `/callback`), lê a conta e aplica o que estiver lá
|
|
@@ -400,6 +401,7 @@ class SpineAccountPreferencesService {
|
|
|
400
401
|
startPage: p.startPage(),
|
|
401
402
|
notices: { ...p.noticeTypes() },
|
|
402
403
|
browserNotices: p.browserNotices(),
|
|
404
|
+
splitTabs: p.splitTabs(),
|
|
403
405
|
favorites: this.quickAccess.favorites().slice(0, MAX_FAVORITES).map((f) => ({ ...f })),
|
|
404
406
|
};
|
|
405
407
|
}, ...(ngDevMode ? [{ debugName: "snapshot" }] : /* istanbul ignore next */ []));
|
|
@@ -553,6 +555,8 @@ class SpineAccountPreferencesService {
|
|
|
553
555
|
// O aviso do navegador depende da permissão DESTE navegador: a conta só desliga, nunca liga sozinha.
|
|
554
556
|
if (doc.browserNotices === false && p.browserNotices())
|
|
555
557
|
p.setBrowserNotices(false);
|
|
558
|
+
if (typeof doc.splitTabs === 'boolean' && doc.splitTabs !== p.splitTabs())
|
|
559
|
+
p.setSplitTabs(doc.splitTabs);
|
|
556
560
|
if (Array.isArray(doc.favorites)) {
|
|
557
561
|
const remote = doc.favorites;
|
|
558
562
|
const ids = new Set(remote.map((f) => f?.id));
|
|
@@ -1406,7 +1410,7 @@ class SpineRatingFormComponent {
|
|
|
1406
1410
|
</div>
|
|
1407
1411
|
}
|
|
1408
1412
|
</div>
|
|
1409
|
-
`, isInline: true, styles: [":host{display:block}.spine-rating{display:flex;flex-direction:column;gap:var(--hm-space-sm);inline-size:min(22rem,100%)}.spine-rating__lead{margin:0;color:var(--hm-text);font-size:var(--hm-font-size-sm, 14px)}.spine-rating__about{margin:calc(-1 * var(--hm-space-xs)) 0 0;overflow:hidden;color:var(--hm-muted);font-size:var(--hm-font-size-xs, 12px);text-overflow:ellipsis;white-space:nowrap}.spine-rating__score{display:flex;flex-direction:column;align-items:flex-start;gap:var(--hm-space-xxs, 4px)}.spine-rating__label{color:var(--hm-text);font-size:var(--hm-font-size-sm, 14px);font-weight:var(--hm-font-weight-semibold, 600)}.spine-rating__hint{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-xs, 12px)}.spine-rating__error{margin:0;color:var(--hm-danger);font-size:var(--hm-font-size-xs, 12px)}.spine-rating__previous{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-xs, 12px)}.spine-rating__actions{display:flex;justify-content:flex-end}\n"], dependencies: [{ kind: "component", type: ButtonComponent, selector: "hm-button", inputs: ["emphasis", "intent", "size", "type", "icon", "iconDirection", "iconEnd", "disabled", "loading", "loadingState", "block", "link", "newTab", "caret", "inMenu", "toggle", "pressed"], outputs: ["loadingStateChange", "pressedChange", "clicked"] }, { kind: "component", type: SkeletonComponent, selector: "hm-skeleton", inputs: ["shape", "count", "label"] }, { kind: "component", type: TextareaComponent, selector: "hm-textarea", inputs: ["value", "label", "hint", "placeholder", "maxLength", "rows", "autoGrow", "labelHidden", "loading", "maxRows", "submitKey"], outputs: ["valueChange", "submitted"] }, { kind: "component", type: SpineRatingStarsComponent, selector: "spine-rating-stars", inputs: ["value", "readonly", "showValue", "showName", "size", "label", "labelledBy", "describedBy", "invalid"], outputs: ["valueChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1413
|
+
`, isInline: true, styles: [":host{display:block}.spine-rating{display:flex;flex-direction:column;gap:var(--hm-space-sm);inline-size:min(22rem,100%)}.spine-rating__lead{margin:0;color:var(--hm-text);font-size:var(--hm-font-size-sm, 14px)}.spine-rating__about{margin:calc(-1 * var(--hm-space-xs)) 0 0;overflow:hidden;color:var(--hm-muted);font-size:var(--hm-font-size-xs, 12px);text-overflow:ellipsis;white-space:nowrap}.spine-rating__score{display:flex;flex-direction:column;align-items:flex-start;gap:var(--hm-space-xxs, 4px)}.spine-rating__label{color:var(--hm-text);font-size:var(--hm-font-size-sm, 14px);font-weight:var(--hm-font-weight-semibold, 600)}.spine-rating__hint{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-xs, 12px)}.spine-rating__error{margin:0;color:var(--hm-danger);font-size:var(--hm-font-size-xs, 12px)}.spine-rating__previous{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-xs, 12px)}.spine-rating__actions{display:flex;justify-content:flex-end}\n"], dependencies: [{ kind: "component", type: ButtonComponent, selector: "hm-button", inputs: ["emphasis", "intent", "size", "type", "icon", "iconDirection", "iconEnd", "disabled", "loading", "loadingState", "block", "link", "newTab", "caret", "inMenu", "toggle", "pressed"], outputs: ["loadingStateChange", "pressedChange", "clicked"] }, { kind: "component", type: SkeletonComponent, selector: "hm-skeleton", inputs: ["shape", "count", "label"] }, { kind: "component", type: TextareaComponent, selector: "hm-textarea", inputs: ["value", "label", "hint", "placeholder", "maxLength", "rows", "autoGrow", "labelHidden", "loading", "maxRows", "submitKey", "mentionCandidates", "mentionTrigger", "texts"], outputs: ["valueChange", "submitted", "mentioned"] }, { kind: "component", type: SpineRatingStarsComponent, selector: "spine-rating-stars", inputs: ["value", "readonly", "showValue", "showName", "size", "label", "labelledBy", "describedBy", "invalid"], outputs: ["valueChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1410
1414
|
}
|
|
1411
1415
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: SpineRatingFormComponent, decorators: [{
|
|
1412
1416
|
type: Component,
|
|
@@ -1803,7 +1807,7 @@ class SpineInboxButtonComponent {
|
|
|
1803
1807
|
}
|
|
1804
1808
|
</hm-popover>
|
|
1805
1809
|
}
|
|
1806
|
-
`, isInline: true, styles: [":host{display:contents}.spine-inbox{position:relative;display:inline-flex}.spine-inbox__badge{position:absolute;inset-block-start:0;inset-inline-end:0;pointer-events:none;transform:translate(25%,-15%)}.spine-inbox__list{display:flex;flex-direction:column;inline-size:min(21rem,calc(100vw - 4rem));max-block-size:min(28rem,70dvh);margin:0;padding:0;overflow-x:hidden;overflow-y:auto;list-style:none}.spine-inbox__item{display:flex;gap:var(--hm-space-sm);inline-size:100%;padding:var(--hm-space-xs) var(--hm-space-xxxs);border:0;border-radius:var(--hm-radius);background:none;color:var(--hm-text);font:inherit;text-align:start;cursor:pointer}.spine-inbox__item:hover{background:var(--hm-hover)}.spine-inbox__item:focus-visible{outline:var(--hm-border-thin) solid var(--hm-focus-color);outline-offset:calc(var(--hm-border-thin) * -1)}.spine-inbox__icon{display:inline-flex;flex:none;align-items:center;justify-content:center;inline-size:2rem;block-size:2rem;border-radius:50%;background:var(--hm-accent-subtle);color:var(--hm-accent)}.spine-inbox__text{display:flex;flex:1;flex-direction:column;gap:var(--hm-space-micro);min-inline-size:0}.spine-inbox__source{color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.spine-inbox__title{overflow:hidden;font-size:var(--hm-font-size-sm);font-weight:var(--hm-font-weight-semibold);text-overflow:ellipsis;white-space:nowrap}.spine-inbox__body{display:-webkit-box;overflow:hidden;color:var(--hm-text);font-size:var(--hm-font-size-sm);overflow-wrap:anywhere;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2}.spine-inbox__meta{display:flex;gap:var(--hm-space-micro);color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.spine-inbox__empty{margin:0;padding-block:var(--hm-space-sm);color:var(--hm-muted);font-size:var(--hm-font-size-sm)}\n"], dependencies: [{ kind: "component", type: AccountAvatarComponent, selector: "hm-account-avatar", inputs: ["name", "imageUrl", "size", "loading"] }, { kind: "component", type: BadgeComponent, selector: "hm-badge", inputs: ["value", "max", "dot", "intent", "label"] }, { kind: "component", type: ButtonComponent, selector: "hm-button", inputs: ["emphasis", "intent", "size", "type", "icon", "iconDirection", "iconEnd", "disabled", "loading", "loadingState", "block", "link", "newTab", "caret", "inMenu", "toggle", "pressed"], outputs: ["loadingStateChange", "pressedChange", "clicked"] }, { kind: "component", type: IconButtonComponent, selector: "hm-icon-button", inputs: ["label", "icon", "solid", "iconDirection", "emphasis", "intent", "size", "disabled", "toggle", "pressed", "keyShortcuts"], outputs: ["pressedChange", "clicked"] }, { kind: "component", type: IconComponent, selector: "hm-icon", inputs: ["shape", "direction", "size", "solid", "badge", "status", "flip", "inverse", "label"] }, { kind: "component", type: PopoverComponent, selector: "hm-popover", inputs: ["open", "heading", "headingLevel", "label", "side", "align", "arrow", "closable", "closeLabel", "closeOnOutsideClick", "openOn", "openDelay", "closeDelay"], outputs: ["openChange"] }, { kind: "directive", type: PopoverTriggerDirective, selector: "[hmPopoverTrigger]", inputs: ["hmPopoverTrigger"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1810
|
+
`, isInline: true, styles: [":host{display:contents}.spine-inbox{position:relative;display:inline-flex}.spine-inbox__badge{position:absolute;inset-block-start:0;inset-inline-end:0;pointer-events:none;transform:translate(25%,-15%)}.spine-inbox__list{display:flex;flex-direction:column;inline-size:min(21rem,calc(100vw - 4rem));max-block-size:min(28rem,70dvh);margin:0;padding:0;overflow-x:hidden;overflow-y:auto;list-style:none}.spine-inbox__item{display:flex;gap:var(--hm-space-sm);inline-size:100%;padding:var(--hm-space-xs) var(--hm-space-xxxs);border:0;border-radius:var(--hm-radius);background:none;color:var(--hm-text);font:inherit;text-align:start;cursor:pointer}.spine-inbox__item:hover{background:var(--hm-hover)}.spine-inbox__item:focus-visible{outline:var(--hm-border-thin) solid var(--hm-focus-color);outline-offset:calc(var(--hm-border-thin) * -1)}.spine-inbox__icon{display:inline-flex;flex:none;align-items:center;justify-content:center;inline-size:2rem;block-size:2rem;border-radius:50%;background:var(--hm-accent-subtle);color:var(--hm-accent)}.spine-inbox__text{display:flex;flex:1;flex-direction:column;gap:var(--hm-space-micro);min-inline-size:0}.spine-inbox__source{color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.spine-inbox__title{overflow:hidden;font-size:var(--hm-font-size-sm);font-weight:var(--hm-font-weight-semibold);text-overflow:ellipsis;white-space:nowrap}.spine-inbox__body{display:-webkit-box;overflow:hidden;color:var(--hm-text);font-size:var(--hm-font-size-sm);overflow-wrap:anywhere;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2}.spine-inbox__meta{display:flex;gap:var(--hm-space-micro);color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.spine-inbox__empty{margin:0;padding-block:var(--hm-space-sm);color:var(--hm-muted);font-size:var(--hm-font-size-sm)}\n"], dependencies: [{ kind: "component", type: AccountAvatarComponent, selector: "hm-account-avatar", inputs: ["name", "imageUrl", "size", "loading", "presence", "texts"] }, { kind: "component", type: BadgeComponent, selector: "hm-badge", inputs: ["value", "max", "dot", "intent", "label"] }, { kind: "component", type: ButtonComponent, selector: "hm-button", inputs: ["emphasis", "intent", "size", "type", "icon", "iconDirection", "iconEnd", "disabled", "loading", "loadingState", "block", "link", "newTab", "caret", "inMenu", "toggle", "pressed"], outputs: ["loadingStateChange", "pressedChange", "clicked"] }, { kind: "component", type: IconButtonComponent, selector: "hm-icon-button", inputs: ["label", "icon", "solid", "iconDirection", "emphasis", "intent", "size", "disabled", "toggle", "pressed", "keyShortcuts"], outputs: ["pressedChange", "clicked"] }, { kind: "component", type: IconComponent, selector: "hm-icon", inputs: ["shape", "direction", "size", "solid", "badge", "status", "flip", "inverse", "label"] }, { kind: "component", type: PopoverComponent, selector: "hm-popover", inputs: ["open", "heading", "headingLevel", "label", "describedBy", "side", "align", "arrow", "closable", "closeLabel", "closeOnOutsideClick", "openOn", "openDelay", "closeDelay"], outputs: ["openChange"] }, { kind: "directive", type: PopoverTriggerDirective, selector: "[hmPopoverTrigger]", inputs: ["hmPopoverTrigger"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1807
1811
|
}
|
|
1808
1812
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: SpineInboxButtonComponent, decorators: [{
|
|
1809
1813
|
type: Component,
|
|
@@ -1856,7 +1860,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImpo
|
|
|
1856
1860
|
const LOGOUT_FAILED_SECONDS = 8;
|
|
1857
1861
|
/**
|
|
1858
1862
|
* Saída da sessão pelo shell: todo botão/atalho de sair do spine passa por aqui (menu do perfil, painel de
|
|
1859
|
-
* configurações,
|
|
1863
|
+
* configurações, tela `/blocked`).
|
|
1860
1864
|
*
|
|
1861
1865
|
* - Assina `logoutFailed$` do `@orfeu/angular` (1.3.x) uma vez só: quando o logout no Argos falha (a lib repete uma
|
|
1862
1866
|
* vez e mantém a sessão), mostra o aviso de erro `session.logoutFailed` (`hm-alert` de erro, `role="alert"`). Vale
|
|
@@ -2009,14 +2013,17 @@ const FAVORITE_DISPLAY_KEYS = 'G 1…9';
|
|
|
2009
2013
|
* Atalhos de teclado globais do sistema, sobre o `HermesShortcutService` da lib (um listener só,
|
|
2010
2014
|
* sequência `G H`, conflito, campo editável, interruptor de tecla única da WCAG 2.1.4).
|
|
2011
2015
|
*
|
|
2012
|
-
* `setActions` registra os atalhos do shell: `G H` (Home), `G 1`…`G 9` (favoritos), `Mod
|
|
2013
|
-
*
|
|
2014
|
-
*
|
|
2016
|
+
* `setActions` registra os atalhos do shell: `G H` (Home), `G 1`…`G 9` (favoritos), `G T` (tema), `Mod+B` (menu
|
|
2017
|
+
* lateral), `Mod+,` (configurações) e `?` (painel de atalhos, via `help$`). `Mod+,` vale também com o foco num campo;
|
|
2018
|
+
* os demais, não (`Mod+B` num editor continua sendo negrito).
|
|
2019
|
+
*
|
|
2020
|
+
* Sem atalho de propósito: sair (um deslize perderia o que estava sendo digitado; fica no menu do perfil) e tela cheia
|
|
2021
|
+
* (o navegador já tem `F11`, e o botão fica no cabeçalho).
|
|
2015
2022
|
*
|
|
2016
2023
|
* O painel (`spine-shortcuts-cheatsheet` e a seção Atalhos das configurações) usa o
|
|
2017
2024
|
* `hm-shortcut-list` com `panelItems()`: tudo o que está registrado no `HermesShortcutService`
|
|
2018
2025
|
* (inclusive o que o app liga com `[hmShortcut]`) mais o que o spine só exibe e outra peça dispara
|
|
2019
|
-
* (`Mod+K` do `hm-header`,
|
|
2026
|
+
* (`Mod+K` e `/` do `hm-header`, voltar/avançar do navegador, `Esc` dos diálogos).
|
|
2020
2027
|
*/
|
|
2021
2028
|
class ShortcutService {
|
|
2022
2029
|
constructor() {
|
|
@@ -2052,10 +2059,9 @@ class ShortcutService {
|
|
|
2052
2059
|
return [
|
|
2053
2060
|
{ keys: ['G H'], describe: () => t.goHome, group: 'navigation', handler: () => this.navigate('/home') },
|
|
2054
2061
|
{ keys: FAVORITE_KEYS, describe: () => t.goFavorite, group: 'navigation', handler: (e) => this.goToFavorite(e) },
|
|
2062
|
+
{ keys: ['Mod+B'], describe: () => t.toggleSidebar, group: 'navigation', handler: () => this.call(this.actions.toggleSidebar) },
|
|
2055
2063
|
{ keys: ['Mod+,'], describe: () => t.openSettings, group: 'actions', allowInInputs: true, handler: () => this.call(this.actions.openSettings) },
|
|
2056
|
-
{ keys: ['
|
|
2057
|
-
{ keys: ['Mod+Shift+F'], describe: () => t.fullscreen, group: 'actions', allowInInputs: true, handler: () => this.call(this.actions.toggleFullscreen) },
|
|
2058
|
-
{ keys: ['Mod+Shift+L'], describe: () => t.logout, group: 'actions', allowInInputs: true, handler: () => this.call(this.actions.logout) },
|
|
2064
|
+
{ keys: ['G T'], describe: () => t.toggleTheme, group: 'actions', handler: () => this.call(this.actions.toggleTheme) },
|
|
2059
2065
|
{ keys: ['?'], describe: () => t.showHelp, group: 'general', handler: () => this.help$.next() },
|
|
2060
2066
|
];
|
|
2061
2067
|
}
|
|
@@ -2063,8 +2069,9 @@ class ShortcutService {
|
|
|
2063
2069
|
displayOnly() {
|
|
2064
2070
|
const t = this.text;
|
|
2065
2071
|
return [
|
|
2066
|
-
{ keys: 'Mod+K', description: t.openSearch, group: 'navigation' },
|
|
2067
|
-
|
|
2072
|
+
{ keys: ['Mod+K', '/'], description: t.openSearch, group: 'navigation' },
|
|
2073
|
+
// O atalho é do navegador, e no Mac ele é outro.
|
|
2074
|
+
{ keys: detectShortcutPlatform() === 'mac' ? ['Mod+[', 'Mod+]'] : ['Alt+Left', 'Alt+Right'], description: t.history, group: 'navigation' },
|
|
2068
2075
|
{ keys: 'Esc', description: t.closeOverlay, group: 'general' },
|
|
2069
2076
|
];
|
|
2070
2077
|
}
|
|
@@ -2329,7 +2336,7 @@ class HeaderComponent {
|
|
|
2329
2336
|
}
|
|
2330
2337
|
return out;
|
|
2331
2338
|
}
|
|
2332
|
-
/** Chamado pelo `(searchRequested)` do `hm-header` (clique no campo
|
|
2339
|
+
/** Chamado pelo `(searchRequested)` do `hm-header` (clique no campo, `Ctrl K` ou `/`, já tratados por ele): abre a paleta. */
|
|
2333
2340
|
onSearchRequested() {
|
|
2334
2341
|
this.searchCommands = this.buildSearchCommands();
|
|
2335
2342
|
this.quickOpen = true;
|
|
@@ -2408,7 +2415,7 @@ class HeaderComponent {
|
|
|
2408
2415
|
catch { /* storage cheio/indisponível */ }
|
|
2409
2416
|
}
|
|
2410
2417
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: HeaderComponent, deps: [{ token: i1.AuthorizationService }, { token: i2$1.ThemeService }, { token: i2$1.ThemePresetService }, { token: i2$1.DensityService }, { token: i1.ViewService }, { token: i3.Router }, { token: ShortcutService }, { token: SPINE_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2411
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: HeaderComponent, isStandalone: true, selector: "spine-header", ngImport: i0, template: "<hm-header [class.header-blocked]=\"headerBlocked\" (searchRequested)=\"onSearchRequested()\">\n <div *ngIf=\"headerBlocked\" class=\"header-overlay\"></div>\n\n <spine-app-launcher></spine-app-launcher>\n\n <!-- Marca: logo do app (SpineConfig.logo, padr\u00E3o assets/images/logo.svg) + SpineConfig.appName,\n levando \u00E0 primeira rota naveg\u00E1vel. Ver SpineBrandComponent. -->\n <spine-brand [homeRoute]=\"homeRoute\" [label]=\"text.home\" />\n\n <div actions class=\"h-right\">\n <!-- central de notifica\u00E7\u00F5es: o sino, com as novidades das fontes registradas (sem fonte, n\u00E3o aparece) -->\n <spine-inbox-button />\n\n <!-- tema claro/escuro -->\n <hm-icon-button emphasis=\"subtle\" (clicked)=\"setTheme(themeService.current == 'light' ? 'dark' : 'light')\"\n [icon]=\"themeService.current == 'light' ? 'moon' : 'sun'\"\n [label]=\"themeService.current == 'light' ? text.themeDark : text.themeLight\">\n </hm-icon-button>\n\n <!-- densidade -->\n <hm-icon-button emphasis=\"subtle\" (clicked)=\"setDensity()\"\n [icon]=\"isCompactDensity ? 'density-comfortable' : 'density-compact'\"\n [label]=\"isCompactDensity ? text.densityComfortable : text.densityCompact\">\n </hm-icon-button>\n\n <!-- Avaliar o {app} (SpineFeatures.ratings): a estrela abre o di\u00E1logo e fica cheia depois de avaliar. Toma o\n lugar do bot\u00E3o de tela cheia (o atalho de teclado continua); sem avalia\u00E7\u00E3o, a tela cheia volta aqui. -->\n @if (showFullscreenButton) {\n <hm-icon-button emphasis=\"subtle\" (clicked)=\"toggleFullscreen()\"\n [icon]=\"isFullscreen ? 'shrink' : 'resize'\"\n [label]=\"isFullscreen ? text.exitFullscreen : text.fullscreen\">\n </hm-icon-button>\n } @else {\n <spine-rate-app-button />\n }\n\n <span class=\"h-divider\" aria-hidden=\"true\"></span>\n\n <!-- perfil: crach\u00E1, ajuda, tema e sair ficam dentro do menu -->\n <hm-menu-button class=\"h-profile\" [label]=\"profile.name ?? text.user\" align=\"end\" [items]=\"profileMenuItems\" (chosen)=\"onProfileMenuChosen($event)\">\n <hm-account-avatar [name]=\"profile.name ?? text.user\" [imageUrl]=\"profile.picture\"></hm-account-avatar>\n <span class=\"h-profile-info\">\n <span class=\"h-profile-name\">{{ profile.name ?? text.user }}</span>\n <span class=\"h-profile-role\" *ngIf=\"badge\">{{ badge?.name }}</span>\n </span>\n </hm-menu-button>\n </div>\n</hm-header>\n\n<!-- Busca global: paleta ancorada logo abaixo do cabe\u00E7alho. Campo vazio = favoritos, abertos h\u00E1 pouco e\n m\u00F3dulos; com texto, busca em todas as telas. Setas/Enter navegam, Esc fecha. -->\n<hm-command-palette\n [(open)]=\"quickOpen\"\n [commands]=\"searchCommands\"\n [browseGroups]=\"searchBrowse\"\n [groupIcons]=\"searchIcons\"\n [label]=\"text.search\"\n [placeholder]=\"text.searchPlaceholder\"\n/>\n\n<!-- A janela de avalia\u00E7\u00E3o (flutuante, canto inferior direito): \"Avaliar o {app}\" da estrela do cabe\u00E7alho e de\n Configura\u00E7\u00F5es \u203A Sobre, e \"Avaliar esta tela\" da barra da p\u00E1gina (SpineFeatures.ratings). S\u00F3 desenha com o recurso\n ligado e aberta. -->\n<spine-rating-window />\n", styles: ["@charset \"UTF-8\";:host{display:contents}.header-overlay{position:absolute;inset:0;z-index:9999;cursor:not-allowed}.h-btn{display:inline-flex;align-items:center;justify-content:center;gap:3px;height:40px;min-width:40px;padding:0 10px;border:none;background:transparent;cursor:pointer;border-radius:9px;text-decoration:none;color:var(--hm-navbar-text);outline:none}.h-btn:focus-visible,.h-btn:hover{background:var(--hm-navbar-hover)}.h-btn.active{background:var(--hm-navbar-hover)}.h-right{display:flex;align-items:center;gap:var(--hm-header-action-gap)}.h-divider{width:1px;height:24px;margin:0 4px;background:var(--hm-navbar-hover)}.h-profile{display:inline-flex;align-items:center;gap:6px;height:40px;padding:0 4px 0 2px}.h-profile hm-account-avatar{background:color-mix(in srgb,var(--hm-navbar-text) 18%,transparent);color:var(--hm-navbar-text)}.h-profile-info{display:flex;flex-direction:column;min-width:0;max-width:140px;line-height:1.2;text-align:left}.h-profile-name{font-size:
|
|
2418
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: HeaderComponent, isStandalone: true, selector: "spine-header", ngImport: i0, template: "<hm-header [class.header-blocked]=\"headerBlocked\" (searchRequested)=\"onSearchRequested()\">\n <div *ngIf=\"headerBlocked\" class=\"header-overlay\"></div>\n\n <spine-app-launcher></spine-app-launcher>\n\n <!-- Marca: logo do app (SpineConfig.logo, padr\u00E3o assets/images/logo.svg) + SpineConfig.appName,\n levando \u00E0 primeira rota naveg\u00E1vel. Ver SpineBrandComponent. -->\n <spine-brand [homeRoute]=\"homeRoute\" [label]=\"text.home\" />\n\n <div actions class=\"h-right\">\n <!-- central de notifica\u00E7\u00F5es: o sino, com as novidades das fontes registradas (sem fonte, n\u00E3o aparece) -->\n <spine-inbox-button />\n\n <!-- tema claro/escuro -->\n <hm-icon-button emphasis=\"subtle\" (clicked)=\"setTheme(themeService.current == 'light' ? 'dark' : 'light')\"\n [icon]=\"themeService.current == 'light' ? 'moon' : 'sun'\"\n [label]=\"themeService.current == 'light' ? text.themeDark : text.themeLight\">\n </hm-icon-button>\n\n <!-- densidade -->\n <hm-icon-button emphasis=\"subtle\" (clicked)=\"setDensity()\"\n [icon]=\"isCompactDensity ? 'density-comfortable' : 'density-compact'\"\n [label]=\"isCompactDensity ? text.densityComfortable : text.densityCompact\">\n </hm-icon-button>\n\n <!-- Avaliar o {app} (SpineFeatures.ratings): a estrela abre o di\u00E1logo e fica cheia depois de avaliar. Toma o\n lugar do bot\u00E3o de tela cheia (o atalho de teclado continua); sem avalia\u00E7\u00E3o, a tela cheia volta aqui. -->\n @if (showFullscreenButton) {\n <hm-icon-button emphasis=\"subtle\" (clicked)=\"toggleFullscreen()\"\n [icon]=\"isFullscreen ? 'shrink' : 'resize'\"\n [label]=\"isFullscreen ? text.exitFullscreen : text.fullscreen\">\n </hm-icon-button>\n } @else {\n <spine-rate-app-button />\n }\n\n <span class=\"h-divider\" aria-hidden=\"true\"></span>\n\n <!-- perfil: crach\u00E1, ajuda, tema e sair ficam dentro do menu -->\n <hm-menu-button class=\"h-profile\" [label]=\"profile.name ?? text.user\" align=\"end\" [items]=\"profileMenuItems\" (chosen)=\"onProfileMenuChosen($event)\">\n <hm-account-avatar [name]=\"profile.name ?? text.user\" [imageUrl]=\"profile.picture\"></hm-account-avatar>\n <span class=\"h-profile-info\">\n <span class=\"h-profile-name\">{{ profile.name ?? text.user }}</span>\n <span class=\"h-profile-role\" *ngIf=\"badge\">{{ badge?.name }}</span>\n </span>\n </hm-menu-button>\n </div>\n</hm-header>\n\n<!-- Busca global: paleta ancorada logo abaixo do cabe\u00E7alho. Campo vazio = favoritos, abertos h\u00E1 pouco e\n m\u00F3dulos; com texto, busca em todas as telas. Setas/Enter navegam, Esc fecha. -->\n<hm-command-palette\n [(open)]=\"quickOpen\"\n [commands]=\"searchCommands\"\n [browseGroups]=\"searchBrowse\"\n [groupIcons]=\"searchIcons\"\n [label]=\"text.search\"\n [placeholder]=\"text.searchPlaceholder\"\n/>\n\n<!-- A janela de avalia\u00E7\u00E3o (flutuante, canto inferior direito): \"Avaliar o {app}\" da estrela do cabe\u00E7alho e de\n Configura\u00E7\u00F5es \u203A Sobre, e \"Avaliar esta tela\" da barra da p\u00E1gina (SpineFeatures.ratings). S\u00F3 desenha com o recurso\n ligado e aberta. -->\n<spine-rating-window />\n", styles: ["@charset \"UTF-8\";:host{display:contents}.header-overlay{position:absolute;inset:0;z-index:9999;cursor:not-allowed}.h-btn{display:inline-flex;align-items:center;justify-content:center;gap:3px;height:40px;min-width:40px;padding:0 10px;border:none;background:transparent;cursor:pointer;border-radius:9px;text-decoration:none;color:var(--hm-navbar-text);outline:none}.h-btn:focus-visible,.h-btn:hover{background:var(--hm-navbar-hover)}.h-btn.active{background:var(--hm-navbar-hover)}.h-right{display:flex;align-items:center;gap:var(--hm-header-action-gap)}.h-divider{width:1px;height:24px;margin:0 4px;background:var(--hm-navbar-hover)}.h-profile{display:inline-flex;align-items:center;gap:6px;height:40px;padding:0 4px 0 2px}.h-profile hm-account-avatar{background:color-mix(in srgb,var(--hm-navbar-text) 18%,transparent);color:var(--hm-navbar-text)}.h-profile-info{display:flex;flex-direction:column;min-width:0;max-width:140px;line-height:1.2;text-align:left}.h-profile-name{font-size:var(--hm-font-size-label);font-weight:var(--hm-font-weight-semibold);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.h-profile-role{color:color-mix(in srgb,var(--hm-navbar-text) 65%,transparent);font-size:var(--hm-font-size-xs);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: HeaderComponent$1, selector: "hm-header", inputs: ["searchPlaceholder", "searchLabel"], outputs: ["searchRequested"] }, { kind: "component", type: IconButtonComponent, selector: "hm-icon-button", inputs: ["label", "icon", "solid", "iconDirection", "emphasis", "intent", "size", "disabled", "toggle", "pressed", "keyShortcuts"], outputs: ["pressedChange", "clicked"] }, { kind: "component", type: MenuButtonComponent, selector: "hm-menu-button", inputs: ["label", "icon", "items", "showArrow", "align", "side", "size", "shape", "layer", "closeOnCheck", "disabled"], outputs: ["chosen", "checkedChange"] }, { kind: "component", type: AccountAvatarComponent, selector: "hm-account-avatar", inputs: ["name", "imageUrl", "size", "loading", "presence", "texts"] }, { kind: "component", type: CommandPaletteComponent, selector: "hm-command-palette", inputs: ["open", "commands", "shortcut", "label", "placeholder", "recentLimit", "recentIds", "closeOnRun", "browseGroups", "groupIcons"], outputs: ["openChange", "recentIdsChange", "executed"] }, { kind: "component", type: AppLauncherComponent, selector: "spine-app-launcher" }, { kind: "component", type: SpineBrandComponent, selector: "spine-brand", inputs: ["homeRoute", "label"] }, { kind: "component", type: SpineRatingWindowComponent, selector: "spine-rating-window" }, { kind: "component", type: SpineRateAppButtonComponent, selector: "spine-rate-app-button" }, { kind: "component", type: SpineInboxButtonComponent, selector: "spine-inbox-button" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2412
2419
|
}
|
|
2413
2420
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: HeaderComponent, decorators: [{
|
|
2414
2421
|
type: Component,
|
|
@@ -2416,7 +2423,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImpo
|
|
|
2416
2423
|
CommonModule,
|
|
2417
2424
|
HeaderComponent$1, IconButtonComponent, IconComponent, MenuButtonComponent, AccountAvatarComponent, CommandPaletteComponent,
|
|
2418
2425
|
AppLauncherComponent, SpineBrandComponent, SpineRatingWindowComponent, SpineRateAppButtonComponent, SpineInboxButtonComponent,
|
|
2419
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<hm-header [class.header-blocked]=\"headerBlocked\" (searchRequested)=\"onSearchRequested()\">\n <div *ngIf=\"headerBlocked\" class=\"header-overlay\"></div>\n\n <spine-app-launcher></spine-app-launcher>\n\n <!-- Marca: logo do app (SpineConfig.logo, padr\u00E3o assets/images/logo.svg) + SpineConfig.appName,\n levando \u00E0 primeira rota naveg\u00E1vel. Ver SpineBrandComponent. -->\n <spine-brand [homeRoute]=\"homeRoute\" [label]=\"text.home\" />\n\n <div actions class=\"h-right\">\n <!-- central de notifica\u00E7\u00F5es: o sino, com as novidades das fontes registradas (sem fonte, n\u00E3o aparece) -->\n <spine-inbox-button />\n\n <!-- tema claro/escuro -->\n <hm-icon-button emphasis=\"subtle\" (clicked)=\"setTheme(themeService.current == 'light' ? 'dark' : 'light')\"\n [icon]=\"themeService.current == 'light' ? 'moon' : 'sun'\"\n [label]=\"themeService.current == 'light' ? text.themeDark : text.themeLight\">\n </hm-icon-button>\n\n <!-- densidade -->\n <hm-icon-button emphasis=\"subtle\" (clicked)=\"setDensity()\"\n [icon]=\"isCompactDensity ? 'density-comfortable' : 'density-compact'\"\n [label]=\"isCompactDensity ? text.densityComfortable : text.densityCompact\">\n </hm-icon-button>\n\n <!-- Avaliar o {app} (SpineFeatures.ratings): a estrela abre o di\u00E1logo e fica cheia depois de avaliar. Toma o\n lugar do bot\u00E3o de tela cheia (o atalho de teclado continua); sem avalia\u00E7\u00E3o, a tela cheia volta aqui. -->\n @if (showFullscreenButton) {\n <hm-icon-button emphasis=\"subtle\" (clicked)=\"toggleFullscreen()\"\n [icon]=\"isFullscreen ? 'shrink' : 'resize'\"\n [label]=\"isFullscreen ? text.exitFullscreen : text.fullscreen\">\n </hm-icon-button>\n } @else {\n <spine-rate-app-button />\n }\n\n <span class=\"h-divider\" aria-hidden=\"true\"></span>\n\n <!-- perfil: crach\u00E1, ajuda, tema e sair ficam dentro do menu -->\n <hm-menu-button class=\"h-profile\" [label]=\"profile.name ?? text.user\" align=\"end\" [items]=\"profileMenuItems\" (chosen)=\"onProfileMenuChosen($event)\">\n <hm-account-avatar [name]=\"profile.name ?? text.user\" [imageUrl]=\"profile.picture\"></hm-account-avatar>\n <span class=\"h-profile-info\">\n <span class=\"h-profile-name\">{{ profile.name ?? text.user }}</span>\n <span class=\"h-profile-role\" *ngIf=\"badge\">{{ badge?.name }}</span>\n </span>\n </hm-menu-button>\n </div>\n</hm-header>\n\n<!-- Busca global: paleta ancorada logo abaixo do cabe\u00E7alho. Campo vazio = favoritos, abertos h\u00E1 pouco e\n m\u00F3dulos; com texto, busca em todas as telas. Setas/Enter navegam, Esc fecha. -->\n<hm-command-palette\n [(open)]=\"quickOpen\"\n [commands]=\"searchCommands\"\n [browseGroups]=\"searchBrowse\"\n [groupIcons]=\"searchIcons\"\n [label]=\"text.search\"\n [placeholder]=\"text.searchPlaceholder\"\n/>\n\n<!-- A janela de avalia\u00E7\u00E3o (flutuante, canto inferior direito): \"Avaliar o {app}\" da estrela do cabe\u00E7alho e de\n Configura\u00E7\u00F5es \u203A Sobre, e \"Avaliar esta tela\" da barra da p\u00E1gina (SpineFeatures.ratings). S\u00F3 desenha com o recurso\n ligado e aberta. -->\n<spine-rating-window />\n", styles: ["@charset \"UTF-8\";:host{display:contents}.header-overlay{position:absolute;inset:0;z-index:9999;cursor:not-allowed}.h-btn{display:inline-flex;align-items:center;justify-content:center;gap:3px;height:40px;min-width:40px;padding:0 10px;border:none;background:transparent;cursor:pointer;border-radius:9px;text-decoration:none;color:var(--hm-navbar-text);outline:none}.h-btn:focus-visible,.h-btn:hover{background:var(--hm-navbar-hover)}.h-btn.active{background:var(--hm-navbar-hover)}.h-right{display:flex;align-items:center;gap:var(--hm-header-action-gap)}.h-divider{width:1px;height:24px;margin:0 4px;background:var(--hm-navbar-hover)}.h-profile{display:inline-flex;align-items:center;gap:6px;height:40px;padding:0 4px 0 2px}.h-profile hm-account-avatar{background:color-mix(in srgb,var(--hm-navbar-text) 18%,transparent);color:var(--hm-navbar-text)}.h-profile-info{display:flex;flex-direction:column;min-width:0;max-width:140px;line-height:1.2;text-align:left}.h-profile-name{font-size:
|
|
2426
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<hm-header [class.header-blocked]=\"headerBlocked\" (searchRequested)=\"onSearchRequested()\">\n <div *ngIf=\"headerBlocked\" class=\"header-overlay\"></div>\n\n <spine-app-launcher></spine-app-launcher>\n\n <!-- Marca: logo do app (SpineConfig.logo, padr\u00E3o assets/images/logo.svg) + SpineConfig.appName,\n levando \u00E0 primeira rota naveg\u00E1vel. Ver SpineBrandComponent. -->\n <spine-brand [homeRoute]=\"homeRoute\" [label]=\"text.home\" />\n\n <div actions class=\"h-right\">\n <!-- central de notifica\u00E7\u00F5es: o sino, com as novidades das fontes registradas (sem fonte, n\u00E3o aparece) -->\n <spine-inbox-button />\n\n <!-- tema claro/escuro -->\n <hm-icon-button emphasis=\"subtle\" (clicked)=\"setTheme(themeService.current == 'light' ? 'dark' : 'light')\"\n [icon]=\"themeService.current == 'light' ? 'moon' : 'sun'\"\n [label]=\"themeService.current == 'light' ? text.themeDark : text.themeLight\">\n </hm-icon-button>\n\n <!-- densidade -->\n <hm-icon-button emphasis=\"subtle\" (clicked)=\"setDensity()\"\n [icon]=\"isCompactDensity ? 'density-comfortable' : 'density-compact'\"\n [label]=\"isCompactDensity ? text.densityComfortable : text.densityCompact\">\n </hm-icon-button>\n\n <!-- Avaliar o {app} (SpineFeatures.ratings): a estrela abre o di\u00E1logo e fica cheia depois de avaliar. Toma o\n lugar do bot\u00E3o de tela cheia (o atalho de teclado continua); sem avalia\u00E7\u00E3o, a tela cheia volta aqui. -->\n @if (showFullscreenButton) {\n <hm-icon-button emphasis=\"subtle\" (clicked)=\"toggleFullscreen()\"\n [icon]=\"isFullscreen ? 'shrink' : 'resize'\"\n [label]=\"isFullscreen ? text.exitFullscreen : text.fullscreen\">\n </hm-icon-button>\n } @else {\n <spine-rate-app-button />\n }\n\n <span class=\"h-divider\" aria-hidden=\"true\"></span>\n\n <!-- perfil: crach\u00E1, ajuda, tema e sair ficam dentro do menu -->\n <hm-menu-button class=\"h-profile\" [label]=\"profile.name ?? text.user\" align=\"end\" [items]=\"profileMenuItems\" (chosen)=\"onProfileMenuChosen($event)\">\n <hm-account-avatar [name]=\"profile.name ?? text.user\" [imageUrl]=\"profile.picture\"></hm-account-avatar>\n <span class=\"h-profile-info\">\n <span class=\"h-profile-name\">{{ profile.name ?? text.user }}</span>\n <span class=\"h-profile-role\" *ngIf=\"badge\">{{ badge?.name }}</span>\n </span>\n </hm-menu-button>\n </div>\n</hm-header>\n\n<!-- Busca global: paleta ancorada logo abaixo do cabe\u00E7alho. Campo vazio = favoritos, abertos h\u00E1 pouco e\n m\u00F3dulos; com texto, busca em todas as telas. Setas/Enter navegam, Esc fecha. -->\n<hm-command-palette\n [(open)]=\"quickOpen\"\n [commands]=\"searchCommands\"\n [browseGroups]=\"searchBrowse\"\n [groupIcons]=\"searchIcons\"\n [label]=\"text.search\"\n [placeholder]=\"text.searchPlaceholder\"\n/>\n\n<!-- A janela de avalia\u00E7\u00E3o (flutuante, canto inferior direito): \"Avaliar o {app}\" da estrela do cabe\u00E7alho e de\n Configura\u00E7\u00F5es \u203A Sobre, e \"Avaliar esta tela\" da barra da p\u00E1gina (SpineFeatures.ratings). S\u00F3 desenha com o recurso\n ligado e aberta. -->\n<spine-rating-window />\n", styles: ["@charset \"UTF-8\";:host{display:contents}.header-overlay{position:absolute;inset:0;z-index:9999;cursor:not-allowed}.h-btn{display:inline-flex;align-items:center;justify-content:center;gap:3px;height:40px;min-width:40px;padding:0 10px;border:none;background:transparent;cursor:pointer;border-radius:9px;text-decoration:none;color:var(--hm-navbar-text);outline:none}.h-btn:focus-visible,.h-btn:hover{background:var(--hm-navbar-hover)}.h-btn.active{background:var(--hm-navbar-hover)}.h-right{display:flex;align-items:center;gap:var(--hm-header-action-gap)}.h-divider{width:1px;height:24px;margin:0 4px;background:var(--hm-navbar-hover)}.h-profile{display:inline-flex;align-items:center;gap:6px;height:40px;padding:0 4px 0 2px}.h-profile hm-account-avatar{background:color-mix(in srgb,var(--hm-navbar-text) 18%,transparent);color:var(--hm-navbar-text)}.h-profile-info{display:flex;flex-direction:column;min-width:0;max-width:140px;line-height:1.2;text-align:left}.h-profile-name{font-size:var(--hm-font-size-label);font-weight:var(--hm-font-weight-semibold);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.h-profile-role{color:color-mix(in srgb,var(--hm-navbar-text) 65%,transparent);font-size:var(--hm-font-size-xs);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"] }]
|
|
2420
2427
|
}], ctorParameters: () => [{ type: i1.AuthorizationService }, { type: i2$1.ThemeService }, { type: i2$1.ThemePresetService }, { type: i2$1.DensityService }, { type: i1.ViewService }, { type: i3.Router }, { type: ShortcutService }, { type: undefined, decorators: [{
|
|
2421
2428
|
type: Optional
|
|
2422
2429
|
}, {
|
|
@@ -2428,6 +2435,20 @@ const HOME_PATH = '/home';
|
|
|
2428
2435
|
function leavesOf(node) {
|
|
2429
2436
|
return node.kind === 'panel' ? [node] : [...leavesOf(node.a), ...leavesOf(node.b)];
|
|
2430
2437
|
}
|
|
2438
|
+
/** Limite da grade de painéis do shell: no máximo 2 lado a lado e 2 empilhados (os quatro cantos da tela). */
|
|
2439
|
+
const SPINE_WORKSPACE_LIMITS = { maxColumns: 2, maxRows: 2 };
|
|
2440
|
+
/** O painel do outro lado da divisão lado a lado mais próxima de `panelId` (o primeiro dele, na ordem da árvore). */
|
|
2441
|
+
function besidePanel(node, panelId) {
|
|
2442
|
+
if (node.kind === 'panel')
|
|
2443
|
+
return null;
|
|
2444
|
+
const inA = panelIdsInOrder(node.a).includes(panelId);
|
|
2445
|
+
if (!inA && !panelIdsInOrder(node.b).includes(panelId))
|
|
2446
|
+
return null;
|
|
2447
|
+
const deeper = besidePanel(inA ? node.a : node.b, panelId);
|
|
2448
|
+
if (deeper)
|
|
2449
|
+
return deeper;
|
|
2450
|
+
return node.direction === 'row' ? panelIdsInOrder(inA ? node.b : node.a)[0] : null;
|
|
2451
|
+
}
|
|
2431
2452
|
/** O caminho de um endereço (sem query nem fragmento). */
|
|
2432
2453
|
function spinePathOf(url) {
|
|
2433
2454
|
return url.split(/[?#]/)[0] || HOME_PATH;
|
|
@@ -2481,11 +2502,20 @@ function keepsIdentity(id, url) {
|
|
|
2481
2502
|
* 3. outra aba do painel já está nesse endereço → ela é ativada;
|
|
2482
2503
|
* 4. senão → a aba ativa passa a ser a da tela nova (o comportamento de sempre).
|
|
2483
2504
|
* `openTab` abre (ou foca, em qualquer painel) a aba de um endereço com parâmetros.
|
|
2505
|
+
*
|
|
2506
|
+
* **Dividir abas é preferência da pessoa** (`SpinePreferencesService.splitTabs`, desligada por padrão): o shell só
|
|
2507
|
+
* deixa dividir a área em painéis com ela ligada (`split`). Desligada — ao carregar ou ao desligar —, um arranjo com
|
|
2508
|
+
* vários painéis (salvo no navegador ou feito antes) é fundido num painel só, sem perder aba (`mergePanels`).
|
|
2484
2509
|
*/
|
|
2485
2510
|
class SpineWorkspaceNavService {
|
|
2486
2511
|
constructor() {
|
|
2487
2512
|
this.router = inject(Router);
|
|
2488
2513
|
this.viewService = inject(ViewService);
|
|
2514
|
+
this.preferences = inject(SpinePreferencesService);
|
|
2515
|
+
/** A pessoa pode dividir a área de abas em painéis (a preferência "Dividir abas"). */
|
|
2516
|
+
this.split = computed(() => this.preferences.splitTabs(), ...(ngDevMode ? [{ debugName: "split" }] : /* istanbul ignore next */ []));
|
|
2517
|
+
/** Até onde dá para dividir (o shell passa para o `hm-workspace`; `openTab` com `beside` respeita). */
|
|
2518
|
+
this.limits = SPINE_WORKSPACE_LIMITS;
|
|
2489
2519
|
this.store = createPersistedWorkspaceStore({ tabs: [this.tabFor(HOME_PATH)], activeId: HOME_PATH }, (id, saved) => this.restoreTab(id, saved), inject(HERMES_WORKSPACE_PERSISTENCE_CONFIG));
|
|
2490
2520
|
this.state = signal(this.store.getState(), ...(ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ []));
|
|
2491
2521
|
this.root = computed(() => this.state().root, ...(ngDevMode ? [{ debugName: "root" }] : /* istanbul ignore next */ []));
|
|
@@ -2502,6 +2532,13 @@ class SpineWorkspaceNavService {
|
|
|
2502
2532
|
/** O último endereço que o `Router` mostrou (normalizado, com a query): o `effect` abaixo não navega para ele de novo. */
|
|
2503
2533
|
this.lastKnownUrl = '';
|
|
2504
2534
|
this.store.subscribe((s) => this.state.set(s));
|
|
2535
|
+
// Já antes da primeira tela: o arranjo salvo com vários painéis volta num painel só se a divisão está desligada.
|
|
2536
|
+
if (!this.split())
|
|
2537
|
+
this.mergePanels();
|
|
2538
|
+
effect(() => {
|
|
2539
|
+
if (!this.split())
|
|
2540
|
+
untracked(() => this.mergePanels());
|
|
2541
|
+
});
|
|
2505
2542
|
this.router.events.subscribe((event) => {
|
|
2506
2543
|
if (!(event instanceof NavigationEnd))
|
|
2507
2544
|
return;
|
|
@@ -2629,6 +2666,18 @@ class SpineWorkspaceNavService {
|
|
|
2629
2666
|
label: (id.includes('?') && cleanLabel(saved?.label)) || fresh.label,
|
|
2630
2667
|
};
|
|
2631
2668
|
}
|
|
2669
|
+
/**
|
|
2670
|
+
* Junta todos os painéis no focado, sem perder aba: as abas ficam na ordem dos painéis (da esquerda para a direita,
|
|
2671
|
+
* de cima para baixo), uma aba repetida em dois painéis vira uma só (vale a do focado), e a aba ativa do painel focado
|
|
2672
|
+
* continua a ativa (`WorkspaceStore.mergePanels`). Com um painel só, não faz nada.
|
|
2673
|
+
*/
|
|
2674
|
+
mergePanels() {
|
|
2675
|
+
const { root, focusedPanelId } = this.store.getState();
|
|
2676
|
+
if (root.kind === 'panel')
|
|
2677
|
+
return;
|
|
2678
|
+
const ids = panelIdsInOrder(root);
|
|
2679
|
+
this.store.mergePanels(ids.includes(focusedPanelId) ? focusedPanelId : ids[0]);
|
|
2680
|
+
}
|
|
2632
2681
|
/** O `+` de um painel: abre a home ali, como um navegador. */
|
|
2633
2682
|
openNewTab(panelId) {
|
|
2634
2683
|
this.store.openTab(panelId, this.tabFor(HOME_PATH));
|
|
@@ -2637,7 +2686,7 @@ class SpineWorkspaceNavService {
|
|
|
2637
2686
|
* Abre (ou foca) a aba de um endereço com parâmetros — um registro por aba na mesma tela:
|
|
2638
2687
|
* `openTab('/vendas/pedidos?pedido=123&secao=itens', { label: 'Pedido 123', match: ['pedido'] })`.
|
|
2639
2688
|
* Se alguma aba (em qualquer painel) já tem essa identidade, ela é focada e passa a esse endereço; senão abre uma
|
|
2640
|
-
* no painel focado (ou num painel novo ao lado, com `beside`). Só abre o que a view da pessoa permite (a mesma
|
|
2689
|
+
* no painel focado (ou num painel novo ao lado, com `beside` e a divisão ligada). Só abre o que a view da pessoa permite (a mesma
|
|
2641
2690
|
* regra do menu e do `ViewGuard`); fora dela, não faz nada.
|
|
2642
2691
|
*/
|
|
2643
2692
|
openTab(url, options = {}) {
|
|
@@ -2659,10 +2708,21 @@ class SpineWorkspaceNavService {
|
|
|
2659
2708
|
}
|
|
2660
2709
|
const fresh = this.tabFor(target);
|
|
2661
2710
|
const tab = { ...fresh, id, ...patch, label: label ?? fresh.label, icon: options.icon ?? fresh.icon };
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2711
|
+
const { root, focusedPanelId } = this.state();
|
|
2712
|
+
if (options.beside && this.split()) {
|
|
2713
|
+
if (canSplitPanel(root, focusedPanelId, 'row', this.limits)) {
|
|
2714
|
+
this.store.splitPanel(focusedPanelId, 'row', tab);
|
|
2715
|
+
return;
|
|
2716
|
+
}
|
|
2717
|
+
// No limite de colunas: abre no painel que já está ao lado (o do outro lado da divisão), sem dividir.
|
|
2718
|
+
const beside = besidePanel(root, focusedPanelId) ?? cyclicPanelNeighbor(panelIdsInOrder(root), focusedPanelId, 1);
|
|
2719
|
+
if (beside) {
|
|
2720
|
+
this.store.openTab(beside, tab);
|
|
2721
|
+
this.store.focusPanel(beside);
|
|
2722
|
+
return;
|
|
2723
|
+
}
|
|
2724
|
+
}
|
|
2725
|
+
this.store.openTab(focusedPanelId, tab);
|
|
2666
2726
|
}
|
|
2667
2727
|
/** O nome (e o ícone) de uma aba, dado pela tela (`SPINE_TAB.setLabel`). */
|
|
2668
2728
|
setTabLabel(panelId, tabId, label, icon) {
|
|
@@ -2737,6 +2797,27 @@ function toSidebarNode(route) {
|
|
|
2737
2797
|
* atual muda (navegação real feita, mesma UX do `leaveModule()` do docs).
|
|
2738
2798
|
*/
|
|
2739
2799
|
class SidebarComponent {
|
|
2800
|
+
/** Botão direito (ou Shift+F10/tecla Menu, que o navegador traduz em `contextmenu`) numa página do menu. Grupo e
|
|
2801
|
+
* entrada de módulo não são páginas: ali o menu nativo continua valendo. */
|
|
2802
|
+
onContextMenu(event, menu) {
|
|
2803
|
+
const link = event.target.closest('a.hm-sidebar-link:not(.hm-sidebar-link--opens-menu)');
|
|
2804
|
+
const href = link?.getAttribute('href');
|
|
2805
|
+
if (!link || !href)
|
|
2806
|
+
return;
|
|
2807
|
+
event.preventDefault();
|
|
2808
|
+
this.menuPage = this.location.normalize(href);
|
|
2809
|
+
// No modo automático a coluna fecharia: o ponteiro vai para o menu, que fica fora dela.
|
|
2810
|
+
this.column.holdOpen(true);
|
|
2811
|
+
// Pelo teclado o evento pode vir sem coordenadas: abre colado no link.
|
|
2812
|
+
const box = link.getBoundingClientRect();
|
|
2813
|
+
menu.openAt(event.clientX || box.left, event.clientY || box.bottom);
|
|
2814
|
+
}
|
|
2815
|
+
onPageMenuClosed() {
|
|
2816
|
+
this.column.holdOpen(false);
|
|
2817
|
+
}
|
|
2818
|
+
openPageInNewTab() {
|
|
2819
|
+
this.workspace.openTab(this.menuPage);
|
|
2820
|
+
}
|
|
2740
2821
|
constructor() {
|
|
2741
2822
|
this.text = inject(SPINE_MESSAGES).sidebar;
|
|
2742
2823
|
this.fmt = formatMessage;
|
|
@@ -2744,6 +2825,11 @@ class SidebarComponent {
|
|
|
2744
2825
|
this.viewService = inject(ViewService);
|
|
2745
2826
|
this.authService = inject(AuthorizationService);
|
|
2746
2827
|
this.realmApps = inject(RealmAppsService);
|
|
2828
|
+
this.location = inject(Location);
|
|
2829
|
+
this.column = inject(HermesSidebarService);
|
|
2830
|
+
this.pageMenu = [{ id: 'new-tab', label: this.text.openInNewTab, icon: 'plus' }];
|
|
2831
|
+
/** Endereço da página em que o menu de contexto foi aberto. */
|
|
2832
|
+
this.menuPage = '';
|
|
2747
2833
|
/** Aplicações do realm (o app atual já vem excluído pelo backend) — exibidas só no mobile. */
|
|
2748
2834
|
this.apps = signal([], ...(ngDevMode ? [{ debugName: "apps" }] : /* istanbul ignore next */ []));
|
|
2749
2835
|
this.currentView = toSignal(this.viewService.currentView$, { initialValue: this.viewService.currentView });
|
|
@@ -2801,11 +2887,11 @@ class SidebarComponent {
|
|
|
2801
2887
|
this.wantsModules.set(true);
|
|
2802
2888
|
}
|
|
2803
2889
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: SidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2804
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: SidebarComponent, isStandalone: true, selector: "spine-sidebar", ngImport: i0, template: "<hm-sidebar\n *ngIf=\"modules().length != 0 || menus().length != 0\"\n [label]=\"!viewingModules() && currentModule() ? fmt(text.moduleNavigation, { module: currentModule()!.route_display_name ?? '' }) : text.modules\"\n [heading]=\"!viewingModules() ? (currentModule()?.route_display_name ?? '') : ''\"\n [headingIcon]=\"currentModule()?.route_icon ?? 'grid'\"\n [backLabel]=\"!viewingModules() && modules().length > 1 ? text.modules : ''\"\n [direction]=\"viewingModules() ? 'back' : 'forward'\"\n (back)=\"showModules()\"\n>\n <!-- S\u00F3 no mobile: o seletor de aplica\u00E7\u00F5es do header some e vem para c\u00E1. -->\n @if (apps().length) {\n <section class=\"spine-sidebar-apps\" [attr.aria-label]=\"text.apps\">\n <p class=\"spine-sidebar-apps__title\"><hm-icon shape=\"grid\" /> {{ text.apps }}</p>\n @for (app of apps(); track app.app_url) {\n <a class=\"spine-sidebar-apps__link\" [href]=\"app.app_url\" target=\"_blank\" rel=\"noopener noreferrer\">\n <hm-icon shape=\"applications\" />\n <span>{{ app.name }}</span>\n </a>\n }\n </section>\n }\n @if (viewingModules()) {\n @for (m of modules(); track m.id) {\n <hm-sidebar-node [node]=\"m\" [depth]=\"0\" />\n }\n } @else {\n @for (menu of menus(); track menu.id) {\n <!-- Infinity, n\u00E3o um n\u00FAmero fixo: o backend do spine j\u00E1 usa `route_type` pra limitar a\n \u00E1rvore a 6 n\u00EDveis (header\u2192navigation\u2192menu\u2192item\u2192submenu\u2192page \u2014 ver `route.model.ts`),\n ent\u00E3o n\u00E3o h\u00E1 necessidade de um segundo teto aqui. Um teto baixo (achado ao vivo,\n 2026-09-28: `depth=2`) for\u00E7ava o pen\u00FAltimo n\u00EDvel a virar link plano mesmo tendo\n filhos reais (ex.: \"submenu\" com p\u00E1ginas embaixo sumia da \u00E1rvore vis\u00EDvel). -->\n <hm-sidebar-node [node]=\"menu\" [depth]=\"maxDepth\" />\n }\n }\n</hm-sidebar>\n", styles: [".spine-sidebar-apps{display:none}@media(max-width:767px){.spine-sidebar-apps{display:flex;flex-direction:column;gap:var(--hm-space-micro);margin-bottom:var(--hm-space-sm);padding-bottom:var(--hm-space-sm);border-bottom:var(--hm-border-hairline) solid var(--hm-divider)}.spine-sidebar-apps__title{display:flex;align-items:center;gap:var(--hm-space-nano);margin:0 var(--hm-space-xxxs);color:var(--hm-muted);font-size:var(--hm-font-size-xs);font-weight:var(--hm-font-weight-semibold);letter-spacing:.04em;text-transform:uppercase}.spine-sidebar-apps__link{display:flex;align-items:center;gap:var(--hm-space-nano);min-height:var(--hm-space-2xl);padding:var(--hm-space-nano) var(--hm-space-xxxs);border-radius:var(--hm-radius-control);color:inherit;font-size:var(--hm-font-size-sm);text-decoration:none}.spine-sidebar-apps__link:hover,.spine-sidebar-apps__link:focus-visible{background:var(--hm-hover)}}:host{display:flex;flex-direction:column;height:100%}:host ::ng-deep .hm-sidebar{height:100%;flex-grow:1}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: SidebarComponent$1, selector: "hm-sidebar", inputs: ["label", "heading", "headingIcon", "backLabel", "direction", "collapsible"], outputs: ["back"] }, { kind: "component", type: SidebarNodeComponent, selector: "hm-sidebar-node", inputs: ["node", "depth"] }, { kind: "component", type: IconComponent, selector: "hm-icon", inputs: ["shape", "direction", "size", "solid", "badge", "status", "flip", "inverse", "label"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2890
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: SidebarComponent, isStandalone: true, selector: "spine-sidebar", ngImport: i0, template: "<span hidden [hmContextMenu]=\"pageMenu\" #pageContextMenu=\"hmContextMenu\" (chosen)=\"openPageInNewTab()\" (closed)=\"onPageMenuClosed()\"></span>\n<hm-sidebar\n *ngIf=\"modules().length != 0 || menus().length != 0\"\n [label]=\"!viewingModules() && currentModule() ? fmt(text.moduleNavigation, { module: currentModule()!.route_display_name ?? '' }) : text.modules\"\n [heading]=\"!viewingModules() ? (currentModule()?.route_display_name ?? '') : ''\"\n [headingIcon]=\"currentModule()?.route_icon ?? 'grid'\"\n [backLabel]=\"!viewingModules() && modules().length > 1 ? text.modules : ''\"\n [direction]=\"viewingModules() ? 'back' : 'forward'\"\n (back)=\"showModules()\"\n (contextmenu)=\"onContextMenu($event, pageContextMenu)\"\n>\n <!-- S\u00F3 no mobile: o seletor de aplica\u00E7\u00F5es do header some e vem para c\u00E1. -->\n @if (apps().length) {\n <section class=\"spine-sidebar-apps\" [attr.aria-label]=\"text.apps\">\n <p class=\"spine-sidebar-apps__title\"><hm-icon shape=\"grid\" /> {{ text.apps }}</p>\n @for (app of apps(); track app.app_url) {\n <a class=\"spine-sidebar-apps__link\" [href]=\"app.app_url\" target=\"_blank\" rel=\"noopener noreferrer\">\n <hm-icon shape=\"applications\" />\n <span>{{ app.name }}</span>\n </a>\n }\n </section>\n }\n @if (viewingModules()) {\n @for (m of modules(); track m.id) {\n <hm-sidebar-node [node]=\"m\" [depth]=\"0\" />\n }\n } @else {\n @for (menu of menus(); track menu.id) {\n <!-- Infinity, n\u00E3o um n\u00FAmero fixo: o backend do spine j\u00E1 usa `route_type` pra limitar a\n \u00E1rvore a 6 n\u00EDveis (header\u2192navigation\u2192menu\u2192item\u2192submenu\u2192page \u2014 ver `route.model.ts`),\n ent\u00E3o n\u00E3o h\u00E1 necessidade de um segundo teto aqui. Um teto baixo (achado ao vivo,\n 2026-09-28: `depth=2`) for\u00E7ava o pen\u00FAltimo n\u00EDvel a virar link plano mesmo tendo\n filhos reais (ex.: \"submenu\" com p\u00E1ginas embaixo sumia da \u00E1rvore vis\u00EDvel). -->\n <hm-sidebar-node [node]=\"menu\" [depth]=\"maxDepth\" />\n }\n }\n</hm-sidebar>\n", styles: [".spine-sidebar-apps{display:none}@media(max-width:767px){.spine-sidebar-apps{display:flex;flex-direction:column;gap:var(--hm-space-micro);margin-bottom:var(--hm-space-sm);padding-bottom:var(--hm-space-sm);border-bottom:var(--hm-border-hairline) solid var(--hm-divider)}.spine-sidebar-apps__title{display:flex;align-items:center;gap:var(--hm-space-nano);margin:0 var(--hm-space-xxxs);color:var(--hm-muted);font-size:var(--hm-font-size-xs);font-weight:var(--hm-font-weight-semibold);letter-spacing:.04em;text-transform:uppercase}.spine-sidebar-apps__link{display:flex;align-items:center;gap:var(--hm-space-nano);min-height:var(--hm-space-2xl);padding:var(--hm-space-nano) var(--hm-space-xxxs);border-radius:var(--hm-radius-control);color:inherit;font-size:var(--hm-font-size-sm);text-decoration:none}.spine-sidebar-apps__link:hover,.spine-sidebar-apps__link:focus-visible{background:var(--hm-hover)}}:host{display:flex;flex-direction:column;height:100%}:host ::ng-deep .hm-sidebar{height:100%;flex-grow:1}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: ContextMenuDirective, selector: "[hmContextMenu]", inputs: ["hmContextMenu", "hmContextMenuLabel", "hmContextMenuDisabled", "hmContextMenuLayer", "hmContextMenuCloseOnCheck"], outputs: ["chosen", "closed", "checkedChange"], exportAs: ["hmContextMenu"] }, { kind: "component", type: SidebarComponent$1, selector: "hm-sidebar", inputs: ["label", "heading", "headingIcon", "backLabel", "direction", "collapsible"], outputs: ["back"] }, { kind: "component", type: SidebarNodeComponent, selector: "hm-sidebar-node", inputs: ["node", "depth"] }, { kind: "component", type: IconComponent, selector: "hm-icon", inputs: ["shape", "direction", "size", "solid", "badge", "status", "flip", "inverse", "label"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2805
2891
|
}
|
|
2806
2892
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: SidebarComponent, decorators: [{
|
|
2807
2893
|
type: Component,
|
|
2808
|
-
args: [{ selector: 'spine-sidebar', imports: [CommonModule, SidebarComponent$1, SidebarNodeComponent, IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<hm-sidebar\n *ngIf=\"modules().length != 0 || menus().length != 0\"\n [label]=\"!viewingModules() && currentModule() ? fmt(text.moduleNavigation, { module: currentModule()!.route_display_name ?? '' }) : text.modules\"\n [heading]=\"!viewingModules() ? (currentModule()?.route_display_name ?? '') : ''\"\n [headingIcon]=\"currentModule()?.route_icon ?? 'grid'\"\n [backLabel]=\"!viewingModules() && modules().length > 1 ? text.modules : ''\"\n [direction]=\"viewingModules() ? 'back' : 'forward'\"\n (back)=\"showModules()\"\n>\n <!-- S\u00F3 no mobile: o seletor de aplica\u00E7\u00F5es do header some e vem para c\u00E1. -->\n @if (apps().length) {\n <section class=\"spine-sidebar-apps\" [attr.aria-label]=\"text.apps\">\n <p class=\"spine-sidebar-apps__title\"><hm-icon shape=\"grid\" /> {{ text.apps }}</p>\n @for (app of apps(); track app.app_url) {\n <a class=\"spine-sidebar-apps__link\" [href]=\"app.app_url\" target=\"_blank\" rel=\"noopener noreferrer\">\n <hm-icon shape=\"applications\" />\n <span>{{ app.name }}</span>\n </a>\n }\n </section>\n }\n @if (viewingModules()) {\n @for (m of modules(); track m.id) {\n <hm-sidebar-node [node]=\"m\" [depth]=\"0\" />\n }\n } @else {\n @for (menu of menus(); track menu.id) {\n <!-- Infinity, n\u00E3o um n\u00FAmero fixo: o backend do spine j\u00E1 usa `route_type` pra limitar a\n \u00E1rvore a 6 n\u00EDveis (header\u2192navigation\u2192menu\u2192item\u2192submenu\u2192page \u2014 ver `route.model.ts`),\n ent\u00E3o n\u00E3o h\u00E1 necessidade de um segundo teto aqui. Um teto baixo (achado ao vivo,\n 2026-09-28: `depth=2`) for\u00E7ava o pen\u00FAltimo n\u00EDvel a virar link plano mesmo tendo\n filhos reais (ex.: \"submenu\" com p\u00E1ginas embaixo sumia da \u00E1rvore vis\u00EDvel). -->\n <hm-sidebar-node [node]=\"menu\" [depth]=\"maxDepth\" />\n }\n }\n</hm-sidebar>\n", styles: [".spine-sidebar-apps{display:none}@media(max-width:767px){.spine-sidebar-apps{display:flex;flex-direction:column;gap:var(--hm-space-micro);margin-bottom:var(--hm-space-sm);padding-bottom:var(--hm-space-sm);border-bottom:var(--hm-border-hairline) solid var(--hm-divider)}.spine-sidebar-apps__title{display:flex;align-items:center;gap:var(--hm-space-nano);margin:0 var(--hm-space-xxxs);color:var(--hm-muted);font-size:var(--hm-font-size-xs);font-weight:var(--hm-font-weight-semibold);letter-spacing:.04em;text-transform:uppercase}.spine-sidebar-apps__link{display:flex;align-items:center;gap:var(--hm-space-nano);min-height:var(--hm-space-2xl);padding:var(--hm-space-nano) var(--hm-space-xxxs);border-radius:var(--hm-radius-control);color:inherit;font-size:var(--hm-font-size-sm);text-decoration:none}.spine-sidebar-apps__link:hover,.spine-sidebar-apps__link:focus-visible{background:var(--hm-hover)}}:host{display:flex;flex-direction:column;height:100%}:host ::ng-deep .hm-sidebar{height:100%;flex-grow:1}\n"] }]
|
|
2894
|
+
args: [{ selector: 'spine-sidebar', imports: [CommonModule, ContextMenuDirective, SidebarComponent$1, SidebarNodeComponent, IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<span hidden [hmContextMenu]=\"pageMenu\" #pageContextMenu=\"hmContextMenu\" (chosen)=\"openPageInNewTab()\" (closed)=\"onPageMenuClosed()\"></span>\n<hm-sidebar\n *ngIf=\"modules().length != 0 || menus().length != 0\"\n [label]=\"!viewingModules() && currentModule() ? fmt(text.moduleNavigation, { module: currentModule()!.route_display_name ?? '' }) : text.modules\"\n [heading]=\"!viewingModules() ? (currentModule()?.route_display_name ?? '') : ''\"\n [headingIcon]=\"currentModule()?.route_icon ?? 'grid'\"\n [backLabel]=\"!viewingModules() && modules().length > 1 ? text.modules : ''\"\n [direction]=\"viewingModules() ? 'back' : 'forward'\"\n (back)=\"showModules()\"\n (contextmenu)=\"onContextMenu($event, pageContextMenu)\"\n>\n <!-- S\u00F3 no mobile: o seletor de aplica\u00E7\u00F5es do header some e vem para c\u00E1. -->\n @if (apps().length) {\n <section class=\"spine-sidebar-apps\" [attr.aria-label]=\"text.apps\">\n <p class=\"spine-sidebar-apps__title\"><hm-icon shape=\"grid\" /> {{ text.apps }}</p>\n @for (app of apps(); track app.app_url) {\n <a class=\"spine-sidebar-apps__link\" [href]=\"app.app_url\" target=\"_blank\" rel=\"noopener noreferrer\">\n <hm-icon shape=\"applications\" />\n <span>{{ app.name }}</span>\n </a>\n }\n </section>\n }\n @if (viewingModules()) {\n @for (m of modules(); track m.id) {\n <hm-sidebar-node [node]=\"m\" [depth]=\"0\" />\n }\n } @else {\n @for (menu of menus(); track menu.id) {\n <!-- Infinity, n\u00E3o um n\u00FAmero fixo: o backend do spine j\u00E1 usa `route_type` pra limitar a\n \u00E1rvore a 6 n\u00EDveis (header\u2192navigation\u2192menu\u2192item\u2192submenu\u2192page \u2014 ver `route.model.ts`),\n ent\u00E3o n\u00E3o h\u00E1 necessidade de um segundo teto aqui. Um teto baixo (achado ao vivo,\n 2026-09-28: `depth=2`) for\u00E7ava o pen\u00FAltimo n\u00EDvel a virar link plano mesmo tendo\n filhos reais (ex.: \"submenu\" com p\u00E1ginas embaixo sumia da \u00E1rvore vis\u00EDvel). -->\n <hm-sidebar-node [node]=\"menu\" [depth]=\"maxDepth\" />\n }\n }\n</hm-sidebar>\n", styles: [".spine-sidebar-apps{display:none}@media(max-width:767px){.spine-sidebar-apps{display:flex;flex-direction:column;gap:var(--hm-space-micro);margin-bottom:var(--hm-space-sm);padding-bottom:var(--hm-space-sm);border-bottom:var(--hm-border-hairline) solid var(--hm-divider)}.spine-sidebar-apps__title{display:flex;align-items:center;gap:var(--hm-space-nano);margin:0 var(--hm-space-xxxs);color:var(--hm-muted);font-size:var(--hm-font-size-xs);font-weight:var(--hm-font-weight-semibold);letter-spacing:.04em;text-transform:uppercase}.spine-sidebar-apps__link{display:flex;align-items:center;gap:var(--hm-space-nano);min-height:var(--hm-space-2xl);padding:var(--hm-space-nano) var(--hm-space-xxxs);border-radius:var(--hm-radius-control);color:inherit;font-size:var(--hm-font-size-sm);text-decoration:none}.spine-sidebar-apps__link:hover,.spine-sidebar-apps__link:focus-visible{background:var(--hm-hover)}}:host{display:flex;flex-direction:column;height:100%}:host ::ng-deep .hm-sidebar{height:100%;flex-grow:1}\n"] }]
|
|
2809
2895
|
}], ctorParameters: () => [] });
|
|
2810
2896
|
|
|
2811
2897
|
/**
|
|
@@ -2902,11 +2988,11 @@ class SpineInitialSetupComponent {
|
|
|
2902
2988
|
return { id, icon, title, before, after, keys: keys ? formatShortcut(keys, this.platform)[0] : null };
|
|
2903
2989
|
}
|
|
2904
2990
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: SpineInitialSetupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2905
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: SpineInitialSetupComponent, isStandalone: true, selector: "spine-initial-setup", viewQueries: [{ propertyName: "heading", first: true, predicate: ["heading"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"setup\" role=\"dialog\" aria-modal=\"true\" [attr.aria-label]=\"t.label\">\n <div class=\"setup__bar\">\n @if (stepTotal() > 1) {\n <span class=\"setup__step\">{{ fmt(t.step, { current: stepNumber(), total: stepTotal() }) }}</span>\n <span class=\"setup__dots\" aria-hidden=\"true\">\n <span class=\"setup__dot\" [class.setup__dot--on]=\"stepNumber() >= 1\"></span>\n <span class=\"setup__dot\" [class.setup__dot--on]=\"stepNumber() >= 2\"></span>\n </span>\n }\n @if (setup.mode() === 'full') {\n <hm-button class=\"setup__skip\" emphasis=\"minimal\" (clicked)=\"setup.finish()\">{{ t.skip }}</hm-button>\n }\n </div>\n\n @if (setup.step() === 'appearance') {\n <div class=\"setup__body\">\n <section class=\"setup__form\">\n <h1 #heading class=\"setup__title\" tabindex=\"-1\">{{ greeting }}</h1>\n <p class=\"setup__intro\">{{ t.appearanceIntro }}</p>\n\n <div class=\"setup__fields\">\n <div class=\"setup__field\">\n <span class=\"setup__label\">{{ s.theme }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"s.theme\" [options]=\"themeOptions\" [value]=\"themeMode()\" (valueChange)=\"setThemeMode($event)\" />\n </div>\n\n <div class=\"setup__field setup__field--wide\">\n <span class=\"setup__label\">{{ s.accent }}</span>\n <hm-theme-picker\n [families]=\"families\"\n [family]=\"family()\"\n [theme]=\"appliedTheme()\"\n [showMode]=\"false\"\n (familyChosen)=\"setFamily($event)\"\n />\n </div>\n\n <div class=\"setup__field\">\n <span class=\"setup__label\">{{ s.density }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"s.density\" [options]=\"densityOptions\" [value]=\"densityValue()\" (valueChange)=\"setDensity($event)\" />\n </div>\n\n <div class=\"setup__field\">\n <span class=\"setup__label\">{{ s.textSize }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"s.textSize\" [options]=\"textSizeOptions()\" [value]=\"textSizeValue()\" (valueChange)=\"setTextSize($event)\" />\n </div>\n\n @if (fontOptions.length > 1) {\n <div class=\"setup__field\">\n <span class=\"setup__label\">{{ s.font }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"s.font\" [options]=\"fontOptions\" [value]=\"fontValue()\" (valueChange)=\"setFont($event)\" />\n </div>\n }\n\n <div class=\"setup__field\">\n <span class=\"setup__label\">{{ s.motion }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"s.motion\" [options]=\"motionOptions\" [value]=\"preferences.motion()\" (valueChange)=\"setMotion($event)\" />\n </div>\n </div>\n\n <div class=\"setup__actions\">\n <hm-button emphasis=\"high\" iconEnd=\"arrow-right\" (clicked)=\"setup.next()\">{{ t.next }}</hm-button>\n </div>\n </section>\n\n <!-- Pr\u00E9via: um shell em miniatura pintado com os tokens do tema, ent\u00E3o acompanha cada escolha. Decorativa. -->\n <figure class=\"setup__preview\">\n <figcaption class=\"setup__preview-label\">{{ t.preview }}</figcaption>\n <div class=\"pv\" aria-hidden=\"true\">\n <div class=\"pv__header\">\n <spine-brand class=\"pv__brand\" [label]=\"appName\" />\n <span class=\"pv__search\"></span>\n <span class=\"pv__avatar\"></span>\n </div>\n <div class=\"pv__body\">\n <div class=\"pv__side\">\n <span class=\"pv__item pv__item--on\"></span>\n <span class=\"pv__item\"></span>\n <span class=\"pv__item\"></span>\n <span class=\"pv__item\"></span>\n <span class=\"pv__item pv__item--short\"></span>\n </div>\n <div class=\"pv__main\">\n <div class=\"pv__tabs\">\n <span class=\"pv__tab pv__tab--on\">{{ t.previewPage }}</span>\n <span class=\"pv__tab\"><span class=\"pv__line\"></span></span>\n <span class=\"pv__tab\"><span class=\"pv__line\"></span></span>\n </div>\n <div class=\"pv__page\">\n <span class=\"pv__title\"></span>\n <div class=\"pv__cards\">\n @for (n of [1, 2, 3]; track n) {\n <span class=\"pv__card\"><span class=\"pv__num\"></span><span class=\"pv__line\"></span></span>\n }\n </div>\n <div class=\"pv__table\">\n <span class=\"pv__row pv__row--head\"></span>\n @for (n of [1, 2, 3, 4]; track n) {\n <span class=\"pv__row\"><span class=\"pv__line\"></span><span class=\"pv__line pv__line--short\"></span></span>\n }\n </div>\n <div class=\"pv__buttons\">\n <span class=\"pv__btn pv__btn--ghost\"></span>\n <span class=\"pv__btn\"></span>\n </div>\n </div>\n </div>\n </div>\n </div>\n </figure>\n </div>\n } @else {\n <div class=\"setup__body setup__body--essentials\">\n <section class=\"setup__essentials\">\n <h1 #heading class=\"setup__title\" tabindex=\"-1\">{{ t.essentialsTitle }}</h1>\n <p class=\"setup__intro\">{{ t.essentialsIntro }}</p>\n\n <ul class=\"setup__cards\">\n @for (card of essentials; track card.id) {\n <li class=\"setup__card\">\n <span class=\"setup__card-icon\"><hm-icon [shape]=\"card.icon\" /></span>\n <h2 class=\"setup__card-title\">{{ card.title }}</h2>\n <p class=\"setup__card-text\">\n {{ card.before }}@if (card.keys) {<span class=\"setup__keys\">@for (step of card.keys; track $index) {@for (key of step; track $index) {<kbd>{{ key.label }}</kbd>}}</span>}{{ card.after }}\n </p>\n </li>\n }\n </ul>\n\n <div class=\"setup__actions\">\n @if (setup.mode() === 'full') {\n <hm-button emphasis=\"medium\" icon=\"arrow-left\" (clicked)=\"setup.back()\">{{ t.back }}</hm-button>\n <hm-button emphasis=\"high\" (clicked)=\"setup.finish()\">{{ t.finish }}</hm-button>\n } @else {\n <hm-button emphasis=\"high\" (clicked)=\"setup.finish()\">{{ t.close }}</hm-button>\n }\n </div>\n </section>\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:host{position:fixed;inset:0;z-index:var(--hm-z-overlay);display:block;overflow:auto;background:var(--hm-surface);color:var(--hm-text)}.setup{display:flex;flex-direction:column;min-height:100%;max-width:76rem;margin:0 auto;padding:var(--hm-space-lg) var(--hm-space-xl) var(--hm-space-2xl);box-sizing:border-box}.setup__bar{display:flex;align-items:center;gap:var(--hm-space-md);min-height:var(--hm-control-height, 40px)}.setup__step{color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.setup__dots{display:inline-flex;gap:6px}.setup__dot{width:24px;height:4px;border-radius:var(--hm-radius-pill);background:var(--hm-border)}.setup__dot--on{background:var(--hm-accent)}.setup__skip{margin-left:auto}.setup__body{flex:1;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);gap:clamp(var(--hm-space-xl),5vw,5rem);align-items:center;padding-top:var(--hm-space-xl)}.setup__body--essentials{grid-template-columns:minmax(0,1fr);justify-items:center}.setup__title{margin:0;font-size:var(--hm-font-size-xxl);font-weight:650;line-height:1.2;letter-spacing:-.01em;outline:none}.setup__intro{margin:var(--hm-space-sm) 0 0;max-width:34rem;color:var(--hm-muted);line-height:1.5}.setup__fields{display:flex;flex-direction:column;gap:var(--hm-space-lg);margin-top:var(--hm-space-xl)}.setup__field{display:flex;flex-direction:column;align-items:flex-start;gap:var(--hm-space-xs)}.setup__field--wide{align-items:stretch}.setup__label{font-size:var(--hm-font-size-sm);font-weight:600}.setup__actions{display:flex;gap:var(--hm-space-sm);margin-top:var(--hm-space-xl)}.setup__preview{margin:0;display:flex;flex-direction:column;gap:var(--hm-space-sm)}.setup__preview-label{color:var(--hm-muted);font-size:var(--hm-font-size-xs);font-weight:600;letter-spacing:.06em;text-transform:uppercase}.pv{display:flex;flex-direction:column;aspect-ratio:16/11;overflow:hidden;border:1px solid var(--hm-border);border-radius:14px;background:var(--hm-surface);box-shadow:var(--hm-shadow-lg)}.pv__header{display:flex;align-items:center;gap:10px;height:34px;padding:0 10px;background:var(--hm-navbar-surface);color:var(--hm-navbar-text);flex:none}.pv__brand{display:flex;align-items:center;height:18px;font-size:11px;pointer-events:none}.pv__brand ::ng-deep img{height:18px;width:auto}.pv__search{flex:0 1 36%;height:16px;margin-left:auto;border-radius:var(--hm-radius-pill);background:color-mix(in srgb,var(--hm-navbar-text) 16%,transparent)}.pv__avatar{width:18px;height:18px;border-radius:50%;background:color-mix(in srgb,var(--hm-navbar-text) 30%,transparent)}.pv__body{flex:1;display:flex;min-height:0}.pv__side{display:flex;flex-direction:column;gap:8px;width:22%;padding:12px 10px;background:var(--hm-sidebar-bg);border-right:1px solid var(--hm-border);box-sizing:border-box}.pv__item{height:9px;border-radius:4px;background:color-mix(in srgb,var(--hm-text) 14%,transparent)}.pv__item--on{background:var(--hm-accent)}.pv__item--short{width:60%}.pv__main{flex:1;display:flex;flex-direction:column;min-width:0}.pv__tabs{display:flex;align-items:flex-end;gap:4px;height:26px;padding:0 8px;background:var(--hm-shell-tab-strip-bg);flex:none}.pv__tab{display:flex;align-items:center;width:64px;height:20px;padding:0 8px;border-radius:7px 7px 0 0;box-sizing:border-box;font-size:9px;color:var(--hm-muted)}.pv__tab--on{background:var(--hm-surface-raised);color:var(--hm-text);font-weight:600}.pv__page{flex:1;display:flex;flex-direction:column;gap:10px;padding:12px 14px;background:var(--hm-surface-raised);min-height:0}.pv__title{width:38%;height:11px;border-radius:4px;background:color-mix(in srgb,var(--hm-text) 55%,transparent)}.pv__cards{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}.pv__card{display:flex;flex-direction:column;gap:6px;padding:8px;border:1px solid var(--hm-border);border-radius:8px;background:var(--hm-surface)}.pv__num{width:40%;height:10px;border-radius:3px;background:var(--hm-accent)}.pv__line{display:block;width:70%;height:6px;border-radius:3px;background:color-mix(in srgb,var(--hm-text) 18%,transparent)}.pv__line--short{width:30%}.pv__table{display:flex;flex-direction:column;overflow:hidden;border:1px solid var(--hm-border);border-radius:8px}.pv__row{display:flex;align-items:center;justify-content:space-between;gap:8px;height:calc(16px * var(--hm-text-scale, 1));padding:0 8px;background:var(--hm-surface)}.pv__row:nth-child(odd):not(.pv__row--head){background:color-mix(in srgb,var(--hm-accent) 5%,var(--hm-surface))}:host-context([data-density=compact]) .pv__row{height:calc(12px * var(--hm-text-scale, 1))}.pv__row--head{background:color-mix(in srgb,var(--hm-accent) 20%,var(--hm-surface-raised))}.pv__buttons{display:flex;justify-content:flex-end;gap:6px;margin-top:auto}.pv__btn{width:52px;height:16px;border-radius:var(--hm-radius-control);background:var(--hm-action)}.pv__btn--ghost{background:transparent;border:1px solid var(--hm-border)}.setup__essentials{width:100%;max-width:56rem}.setup__cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(13rem,1fr));gap:var(--hm-space-md);margin:var(--hm-space-xl) 0 0;padding:0;list-style:none}.setup__card{display:flex;flex-direction:column;gap:var(--hm-space-xs);padding:var(--hm-space-lg);border:1px solid var(--hm-border);border-radius:12px;background:var(--hm-surface-raised)}.setup__card-icon{display:inline-grid;place-items:center;width:36px;height:36px;margin-bottom:var(--hm-space-xs);border-radius:10px;background:var(--hm-accent-subtle);color:var(--hm-accent)}.setup__card-title{margin:0;font-size:var(--hm-font-size-md);font-weight:600}.setup__card-text{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-sm);line-height:1.5}.setup__keys{display:inline-flex;gap:3px;vertical-align:baseline}.setup__keys kbd{padding:0 5px;border:1px solid var(--hm-border);border-bottom-width:2px;border-radius:5px;background:var(--hm-surface);color:var(--hm-text);font:inherit;font-size:var(--hm-font-size-xs);font-weight:600}@media(max-width:860px){.setup{padding:var(--hm-space-md)}.setup__body{grid-template-columns:minmax(0,1fr);align-items:start}.setup__preview{display:none}}\n"], dependencies: [{ kind: "component", type: ButtonComponent, selector: "hm-button", inputs: ["emphasis", "intent", "size", "type", "icon", "iconDirection", "iconEnd", "disabled", "loading", "loadingState", "block", "link", "newTab", "caret", "inMenu", "toggle", "pressed"], outputs: ["loadingStateChange", "pressedChange", "clicked"] }, { kind: "component", type: IconComponent, selector: "hm-icon", inputs: ["shape", "direction", "size", "solid", "badge", "status", "flip", "inverse", "label"] }, { kind: "component", type: SegmentedControlComponent, selector: "hm-segmented-control", inputs: ["options", "value", "label", "size", "emphasis"], outputs: ["valueChange"] }, { kind: "component", type: ThemePickerComponent, selector: "hm-theme-picker", inputs: ["families", "family", "theme", "showMode"], outputs: ["familyChosen", "themeChosen"] }, { kind: "component", type: SpineBrandComponent, selector: "spine-brand", inputs: ["homeRoute", "label"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2991
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: SpineInitialSetupComponent, isStandalone: true, selector: "spine-initial-setup", viewQueries: [{ propertyName: "heading", first: true, predicate: ["heading"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"setup\" role=\"dialog\" aria-modal=\"true\" [attr.aria-label]=\"t.label\">\n <div class=\"setup__bar\">\n @if (stepTotal() > 1) {\n <span class=\"setup__step\">{{ fmt(t.step, { current: stepNumber(), total: stepTotal() }) }}</span>\n <span class=\"setup__dots\" aria-hidden=\"true\">\n <span class=\"setup__dot\" [class.setup__dot--on]=\"stepNumber() >= 1\"></span>\n <span class=\"setup__dot\" [class.setup__dot--on]=\"stepNumber() >= 2\"></span>\n </span>\n }\n @if (setup.mode() === 'full') {\n <hm-button class=\"setup__skip\" emphasis=\"minimal\" (clicked)=\"setup.finish()\">{{ t.skip }}</hm-button>\n }\n </div>\n\n @if (setup.step() === 'appearance') {\n <div class=\"setup__body\">\n <section class=\"setup__form\">\n <h1 #heading class=\"setup__title\" tabindex=\"-1\">{{ greeting }}</h1>\n <p class=\"setup__intro\">{{ t.appearanceIntro }}</p>\n\n <div class=\"setup__fields\">\n <div class=\"setup__field\">\n <span class=\"setup__label\">{{ s.theme }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"s.theme\" [options]=\"themeOptions\" [value]=\"themeMode()\" (valueChange)=\"setThemeMode($event)\" />\n </div>\n\n <div class=\"setup__field setup__field--wide\">\n <span class=\"setup__label\">{{ s.accent }}</span>\n <hm-theme-picker\n [families]=\"families\"\n [family]=\"family()\"\n [theme]=\"appliedTheme()\"\n [showMode]=\"false\"\n (familyChosen)=\"setFamily($event)\"\n />\n </div>\n\n <div class=\"setup__field\">\n <span class=\"setup__label\">{{ s.density }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"s.density\" [options]=\"densityOptions\" [value]=\"densityValue()\" (valueChange)=\"setDensity($event)\" />\n </div>\n\n <div class=\"setup__field\">\n <span class=\"setup__label\">{{ s.textSize }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"s.textSize\" [options]=\"textSizeOptions()\" [value]=\"textSizeValue()\" (valueChange)=\"setTextSize($event)\" />\n </div>\n\n @if (fontOptions.length > 1) {\n <div class=\"setup__field\">\n <span class=\"setup__label\">{{ s.font }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"s.font\" [options]=\"fontOptions\" [value]=\"fontValue()\" (valueChange)=\"setFont($event)\" />\n </div>\n }\n\n <div class=\"setup__field\">\n <span class=\"setup__label\">{{ s.motion }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"s.motion\" [options]=\"motionOptions\" [value]=\"preferences.motion()\" (valueChange)=\"setMotion($event)\" />\n </div>\n </div>\n\n <div class=\"setup__actions\">\n <hm-button emphasis=\"high\" iconEnd=\"arrow-right\" (clicked)=\"setup.next()\">{{ t.next }}</hm-button>\n </div>\n </section>\n\n <!-- Pr\u00E9via: um shell em miniatura pintado com os tokens do tema, ent\u00E3o acompanha cada escolha. Decorativa. -->\n <figure class=\"setup__preview\">\n <figcaption class=\"setup__preview-label\">{{ t.preview }}</figcaption>\n <div class=\"pv\" aria-hidden=\"true\">\n <div class=\"pv__header\">\n <spine-brand class=\"pv__brand\" [label]=\"appName\" />\n <span class=\"pv__search\"></span>\n <span class=\"pv__avatar\"></span>\n </div>\n <div class=\"pv__body\">\n <div class=\"pv__side\">\n <span class=\"pv__item pv__item--on\"></span>\n <span class=\"pv__item\"></span>\n <span class=\"pv__item\"></span>\n <span class=\"pv__item\"></span>\n <span class=\"pv__item pv__item--short\"></span>\n </div>\n <div class=\"pv__main\">\n <div class=\"pv__tabs\">\n <span class=\"pv__tab pv__tab--on\">{{ t.previewPage }}</span>\n <span class=\"pv__tab\"><span class=\"pv__line\"></span></span>\n <span class=\"pv__tab\"><span class=\"pv__line\"></span></span>\n </div>\n <div class=\"pv__page\">\n <span class=\"pv__title\"></span>\n <div class=\"pv__cards\">\n @for (n of [1, 2, 3]; track n) {\n <span class=\"pv__card\"><span class=\"pv__num\"></span><span class=\"pv__line\"></span></span>\n }\n </div>\n <div class=\"pv__table\">\n <span class=\"pv__row pv__row--head\"></span>\n @for (n of [1, 2, 3, 4]; track n) {\n <span class=\"pv__row\"><span class=\"pv__line\"></span><span class=\"pv__line pv__line--short\"></span></span>\n }\n </div>\n <div class=\"pv__buttons\">\n <span class=\"pv__btn pv__btn--ghost\"></span>\n <span class=\"pv__btn\"></span>\n </div>\n </div>\n </div>\n </div>\n </div>\n </figure>\n </div>\n } @else {\n <div class=\"setup__body setup__body--essentials\">\n <section class=\"setup__essentials\">\n <h1 #heading class=\"setup__title\" tabindex=\"-1\">{{ t.essentialsTitle }}</h1>\n <p class=\"setup__intro\">{{ t.essentialsIntro }}</p>\n\n <ul class=\"setup__cards\">\n @for (card of essentials; track card.id) {\n <li class=\"setup__card\">\n <span class=\"setup__card-icon\"><hm-icon [shape]=\"card.icon\" /></span>\n <h2 class=\"setup__card-title\">{{ card.title }}</h2>\n <p class=\"setup__card-text\">\n {{ card.before }}@if (card.keys) {<span class=\"setup__keys\">@for (step of card.keys; track $index) {@for (key of step; track $index) {<kbd>{{ key.label }}</kbd>}}</span>}{{ card.after }}\n </p>\n </li>\n }\n </ul>\n\n <div class=\"setup__actions\">\n @if (setup.mode() === 'full') {\n <hm-button emphasis=\"medium\" icon=\"arrow-left\" (clicked)=\"setup.back()\">{{ t.back }}</hm-button>\n <hm-button emphasis=\"high\" (clicked)=\"setup.finish()\">{{ t.finish }}</hm-button>\n } @else {\n <hm-button emphasis=\"high\" (clicked)=\"setup.finish()\">{{ t.close }}</hm-button>\n }\n </div>\n </section>\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:host{position:fixed;inset:0;z-index:var(--hm-z-overlay);display:block;overflow:auto;background:var(--hm-surface);color:var(--hm-text)}.setup{display:flex;flex-direction:column;min-height:100%;max-width:76rem;margin:0 auto;padding:var(--hm-space-lg) var(--hm-space-xl) var(--hm-space-2xl);box-sizing:border-box}.setup__bar{display:flex;align-items:center;gap:var(--hm-space-md);min-height:var(--hm-control-height, 40px)}.setup__step{color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.setup__dots{display:inline-flex;gap:6px}.setup__dot{width:24px;height:4px;border-radius:var(--hm-radius-pill);background:var(--hm-border)}.setup__dot--on{background:var(--hm-accent)}.setup__skip{margin-left:auto}.setup__body{flex:1;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);gap:clamp(var(--hm-space-xl),5vw,5rem);align-items:center;padding-top:var(--hm-space-xl)}.setup__body--essentials{grid-template-columns:minmax(0,1fr);justify-items:center}.setup__title{margin:0;font-size:var(--hm-font-size-xxl);font-weight:var(--hm-font-weight-semibold);line-height:1.2;letter-spacing:-.01em;outline:none}.setup__intro{margin:var(--hm-space-sm) 0 0;max-width:34rem;color:var(--hm-muted);line-height:1.5}.setup__fields{display:flex;flex-direction:column;gap:var(--hm-space-lg);margin-top:var(--hm-space-xl)}.setup__field{display:flex;flex-direction:column;align-items:flex-start;gap:var(--hm-space-xs)}.setup__field--wide{align-items:stretch}.setup__label{font-size:var(--hm-font-size-sm);font-weight:var(--hm-font-weight-semibold)}.setup__actions{display:flex;gap:var(--hm-space-sm);margin-top:var(--hm-space-xl)}.setup__preview{margin:0;display:flex;flex-direction:column;gap:var(--hm-space-sm)}.setup__preview-label{color:var(--hm-muted);font-size:var(--hm-font-size-xs);font-weight:var(--hm-font-weight-semibold);letter-spacing:.06em;text-transform:uppercase}.pv{display:flex;flex-direction:column;aspect-ratio:16/11;overflow:hidden;border:1px solid var(--hm-border);border-radius:14px;background:var(--hm-surface);box-shadow:var(--hm-shadow-lg)}.pv__header{display:flex;align-items:center;gap:10px;height:34px;padding:0 10px;background:var(--hm-navbar-surface);color:var(--hm-navbar-text);flex:none}.pv__brand{display:flex;align-items:center;height:18px;font-size:var(--hm-font-size-xs);pointer-events:none}.pv__brand ::ng-deep img{height:18px;width:auto}.pv__search{flex:0 1 36%;height:16px;margin-left:auto;border-radius:var(--hm-radius-pill);background:color-mix(in srgb,var(--hm-navbar-text) 16%,transparent)}.pv__avatar{width:18px;height:18px;border-radius:50%;background:color-mix(in srgb,var(--hm-navbar-text) 30%,transparent)}.pv__body{flex:1;display:flex;min-height:0}.pv__side{display:flex;flex-direction:column;gap:8px;width:22%;padding:12px 10px;background:var(--hm-sidebar-bg);border-right:1px solid var(--hm-border);box-sizing:border-box}.pv__item{height:9px;border-radius:4px;background:color-mix(in srgb,var(--hm-text) 14%,transparent)}.pv__item--on{background:var(--hm-accent)}.pv__item--short{width:60%}.pv__main{flex:1;display:flex;flex-direction:column;min-width:0}.pv__tabs{display:flex;align-items:flex-end;gap:4px;height:26px;padding:0 8px;background:var(--hm-shell-tab-strip-bg);flex:none}.pv__tab{display:flex;align-items:center;width:64px;height:20px;padding:0 8px;border-radius:7px 7px 0 0;box-sizing:border-box;font-size:var(--hm-font-size-3xs);color:var(--hm-muted)}.pv__tab--on{background:var(--hm-surface-raised);color:var(--hm-text);font-weight:var(--hm-font-weight-semibold)}.pv__page{flex:1;display:flex;flex-direction:column;gap:10px;padding:12px 14px;background:var(--hm-surface-raised);min-height:0}.pv__title{width:38%;height:11px;border-radius:4px;background:color-mix(in srgb,var(--hm-text) 55%,transparent)}.pv__cards{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}.pv__card{display:flex;flex-direction:column;gap:6px;padding:8px;border:1px solid var(--hm-border);border-radius:8px;background:var(--hm-surface)}.pv__num{width:40%;height:10px;border-radius:3px;background:var(--hm-accent)}.pv__line{display:block;width:70%;height:6px;border-radius:3px;background:color-mix(in srgb,var(--hm-text) 18%,transparent)}.pv__line--short{width:30%}.pv__table{display:flex;flex-direction:column;overflow:hidden;border:1px solid var(--hm-border);border-radius:8px}.pv__row{display:flex;align-items:center;justify-content:space-between;gap:8px;height:calc(16px * var(--hm-text-scale, 1));padding:0 8px;background:var(--hm-surface)}.pv__row:nth-child(odd):not(.pv__row--head){background:color-mix(in srgb,var(--hm-accent) 5%,var(--hm-surface))}:host-context([data-density=compact]) .pv__row{height:calc(12px * var(--hm-text-scale, 1))}.pv__row--head{background:color-mix(in srgb,var(--hm-accent) 20%,var(--hm-surface-raised))}.pv__buttons{display:flex;justify-content:flex-end;gap:6px;margin-top:auto}.pv__btn{width:52px;height:16px;border-radius:var(--hm-radius-control);background:var(--hm-action)}.pv__btn--ghost{background:transparent;border:1px solid var(--hm-border)}.setup__essentials{width:100%;max-width:56rem}.setup__cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(13rem,1fr));gap:var(--hm-space-md);margin:var(--hm-space-xl) 0 0;padding:0;list-style:none}.setup__card{display:flex;flex-direction:column;gap:var(--hm-space-xs);padding:var(--hm-space-lg);border:1px solid var(--hm-border);border-radius:12px;background:var(--hm-surface-raised)}.setup__card-icon{display:inline-grid;place-items:center;width:36px;height:36px;margin-bottom:var(--hm-space-xs);border-radius:10px;background:var(--hm-accent-subtle);color:var(--hm-accent)}.setup__card-title{margin:0;font-size:var(--hm-font-size-md);font-weight:var(--hm-font-weight-semibold)}.setup__card-text{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-sm);line-height:1.5}.setup__keys{display:inline-flex;gap:3px;vertical-align:baseline}.setup__keys kbd{padding:0 5px;border:1px solid var(--hm-border);border-bottom-width:2px;border-radius:5px;background:var(--hm-surface);color:var(--hm-text);font:inherit;font-size:var(--hm-font-size-xs);font-weight:var(--hm-font-weight-semibold)}@media(max-width:860px){.setup{padding:var(--hm-space-md)}.setup__body{grid-template-columns:minmax(0,1fr);align-items:start}.setup__preview{display:none}}\n"], dependencies: [{ kind: "component", type: ButtonComponent, selector: "hm-button", inputs: ["emphasis", "intent", "size", "type", "icon", "iconDirection", "iconEnd", "disabled", "loading", "loadingState", "block", "link", "newTab", "caret", "inMenu", "toggle", "pressed"], outputs: ["loadingStateChange", "pressedChange", "clicked"] }, { kind: "component", type: IconComponent, selector: "hm-icon", inputs: ["shape", "direction", "size", "solid", "badge", "status", "flip", "inverse", "label"] }, { kind: "component", type: SegmentedControlComponent, selector: "hm-segmented-control", inputs: ["options", "value", "label", "size", "emphasis"], outputs: ["valueChange"] }, { kind: "component", type: ThemePickerComponent, selector: "hm-theme-picker", inputs: ["families", "family", "theme", "showMode"], outputs: ["familyChosen", "themeChosen"] }, { kind: "component", type: SpineBrandComponent, selector: "spine-brand", inputs: ["homeRoute", "label"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2906
2992
|
}
|
|
2907
2993
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: SpineInitialSetupComponent, decorators: [{
|
|
2908
2994
|
type: Component,
|
|
2909
|
-
args: [{ selector: 'spine-initial-setup', imports: [ButtonComponent, IconComponent, SegmentedControlComponent, ThemePickerComponent, SpineBrandComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"setup\" role=\"dialog\" aria-modal=\"true\" [attr.aria-label]=\"t.label\">\n <div class=\"setup__bar\">\n @if (stepTotal() > 1) {\n <span class=\"setup__step\">{{ fmt(t.step, { current: stepNumber(), total: stepTotal() }) }}</span>\n <span class=\"setup__dots\" aria-hidden=\"true\">\n <span class=\"setup__dot\" [class.setup__dot--on]=\"stepNumber() >= 1\"></span>\n <span class=\"setup__dot\" [class.setup__dot--on]=\"stepNumber() >= 2\"></span>\n </span>\n }\n @if (setup.mode() === 'full') {\n <hm-button class=\"setup__skip\" emphasis=\"minimal\" (clicked)=\"setup.finish()\">{{ t.skip }}</hm-button>\n }\n </div>\n\n @if (setup.step() === 'appearance') {\n <div class=\"setup__body\">\n <section class=\"setup__form\">\n <h1 #heading class=\"setup__title\" tabindex=\"-1\">{{ greeting }}</h1>\n <p class=\"setup__intro\">{{ t.appearanceIntro }}</p>\n\n <div class=\"setup__fields\">\n <div class=\"setup__field\">\n <span class=\"setup__label\">{{ s.theme }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"s.theme\" [options]=\"themeOptions\" [value]=\"themeMode()\" (valueChange)=\"setThemeMode($event)\" />\n </div>\n\n <div class=\"setup__field setup__field--wide\">\n <span class=\"setup__label\">{{ s.accent }}</span>\n <hm-theme-picker\n [families]=\"families\"\n [family]=\"family()\"\n [theme]=\"appliedTheme()\"\n [showMode]=\"false\"\n (familyChosen)=\"setFamily($event)\"\n />\n </div>\n\n <div class=\"setup__field\">\n <span class=\"setup__label\">{{ s.density }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"s.density\" [options]=\"densityOptions\" [value]=\"densityValue()\" (valueChange)=\"setDensity($event)\" />\n </div>\n\n <div class=\"setup__field\">\n <span class=\"setup__label\">{{ s.textSize }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"s.textSize\" [options]=\"textSizeOptions()\" [value]=\"textSizeValue()\" (valueChange)=\"setTextSize($event)\" />\n </div>\n\n @if (fontOptions.length > 1) {\n <div class=\"setup__field\">\n <span class=\"setup__label\">{{ s.font }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"s.font\" [options]=\"fontOptions\" [value]=\"fontValue()\" (valueChange)=\"setFont($event)\" />\n </div>\n }\n\n <div class=\"setup__field\">\n <span class=\"setup__label\">{{ s.motion }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"s.motion\" [options]=\"motionOptions\" [value]=\"preferences.motion()\" (valueChange)=\"setMotion($event)\" />\n </div>\n </div>\n\n <div class=\"setup__actions\">\n <hm-button emphasis=\"high\" iconEnd=\"arrow-right\" (clicked)=\"setup.next()\">{{ t.next }}</hm-button>\n </div>\n </section>\n\n <!-- Pr\u00E9via: um shell em miniatura pintado com os tokens do tema, ent\u00E3o acompanha cada escolha. Decorativa. -->\n <figure class=\"setup__preview\">\n <figcaption class=\"setup__preview-label\">{{ t.preview }}</figcaption>\n <div class=\"pv\" aria-hidden=\"true\">\n <div class=\"pv__header\">\n <spine-brand class=\"pv__brand\" [label]=\"appName\" />\n <span class=\"pv__search\"></span>\n <span class=\"pv__avatar\"></span>\n </div>\n <div class=\"pv__body\">\n <div class=\"pv__side\">\n <span class=\"pv__item pv__item--on\"></span>\n <span class=\"pv__item\"></span>\n <span class=\"pv__item\"></span>\n <span class=\"pv__item\"></span>\n <span class=\"pv__item pv__item--short\"></span>\n </div>\n <div class=\"pv__main\">\n <div class=\"pv__tabs\">\n <span class=\"pv__tab pv__tab--on\">{{ t.previewPage }}</span>\n <span class=\"pv__tab\"><span class=\"pv__line\"></span></span>\n <span class=\"pv__tab\"><span class=\"pv__line\"></span></span>\n </div>\n <div class=\"pv__page\">\n <span class=\"pv__title\"></span>\n <div class=\"pv__cards\">\n @for (n of [1, 2, 3]; track n) {\n <span class=\"pv__card\"><span class=\"pv__num\"></span><span class=\"pv__line\"></span></span>\n }\n </div>\n <div class=\"pv__table\">\n <span class=\"pv__row pv__row--head\"></span>\n @for (n of [1, 2, 3, 4]; track n) {\n <span class=\"pv__row\"><span class=\"pv__line\"></span><span class=\"pv__line pv__line--short\"></span></span>\n }\n </div>\n <div class=\"pv__buttons\">\n <span class=\"pv__btn pv__btn--ghost\"></span>\n <span class=\"pv__btn\"></span>\n </div>\n </div>\n </div>\n </div>\n </div>\n </figure>\n </div>\n } @else {\n <div class=\"setup__body setup__body--essentials\">\n <section class=\"setup__essentials\">\n <h1 #heading class=\"setup__title\" tabindex=\"-1\">{{ t.essentialsTitle }}</h1>\n <p class=\"setup__intro\">{{ t.essentialsIntro }}</p>\n\n <ul class=\"setup__cards\">\n @for (card of essentials; track card.id) {\n <li class=\"setup__card\">\n <span class=\"setup__card-icon\"><hm-icon [shape]=\"card.icon\" /></span>\n <h2 class=\"setup__card-title\">{{ card.title }}</h2>\n <p class=\"setup__card-text\">\n {{ card.before }}@if (card.keys) {<span class=\"setup__keys\">@for (step of card.keys; track $index) {@for (key of step; track $index) {<kbd>{{ key.label }}</kbd>}}</span>}{{ card.after }}\n </p>\n </li>\n }\n </ul>\n\n <div class=\"setup__actions\">\n @if (setup.mode() === 'full') {\n <hm-button emphasis=\"medium\" icon=\"arrow-left\" (clicked)=\"setup.back()\">{{ t.back }}</hm-button>\n <hm-button emphasis=\"high\" (clicked)=\"setup.finish()\">{{ t.finish }}</hm-button>\n } @else {\n <hm-button emphasis=\"high\" (clicked)=\"setup.finish()\">{{ t.close }}</hm-button>\n }\n </div>\n </section>\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:host{position:fixed;inset:0;z-index:var(--hm-z-overlay);display:block;overflow:auto;background:var(--hm-surface);color:var(--hm-text)}.setup{display:flex;flex-direction:column;min-height:100%;max-width:76rem;margin:0 auto;padding:var(--hm-space-lg) var(--hm-space-xl) var(--hm-space-2xl);box-sizing:border-box}.setup__bar{display:flex;align-items:center;gap:var(--hm-space-md);min-height:var(--hm-control-height, 40px)}.setup__step{color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.setup__dots{display:inline-flex;gap:6px}.setup__dot{width:24px;height:4px;border-radius:var(--hm-radius-pill);background:var(--hm-border)}.setup__dot--on{background:var(--hm-accent)}.setup__skip{margin-left:auto}.setup__body{flex:1;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);gap:clamp(var(--hm-space-xl),5vw,5rem);align-items:center;padding-top:var(--hm-space-xl)}.setup__body--essentials{grid-template-columns:minmax(0,1fr);justify-items:center}.setup__title{margin:0;font-size:var(--hm-font-size-xxl);font-weight:650;line-height:1.2;letter-spacing:-.01em;outline:none}.setup__intro{margin:var(--hm-space-sm) 0 0;max-width:34rem;color:var(--hm-muted);line-height:1.5}.setup__fields{display:flex;flex-direction:column;gap:var(--hm-space-lg);margin-top:var(--hm-space-xl)}.setup__field{display:flex;flex-direction:column;align-items:flex-start;gap:var(--hm-space-xs)}.setup__field--wide{align-items:stretch}.setup__label{font-size:var(--hm-font-size-sm);font-weight:600}.setup__actions{display:flex;gap:var(--hm-space-sm);margin-top:var(--hm-space-xl)}.setup__preview{margin:0;display:flex;flex-direction:column;gap:var(--hm-space-sm)}.setup__preview-label{color:var(--hm-muted);font-size:var(--hm-font-size-xs);font-weight:600;letter-spacing:.06em;text-transform:uppercase}.pv{display:flex;flex-direction:column;aspect-ratio:16/11;overflow:hidden;border:1px solid var(--hm-border);border-radius:14px;background:var(--hm-surface);box-shadow:var(--hm-shadow-lg)}.pv__header{display:flex;align-items:center;gap:10px;height:34px;padding:0 10px;background:var(--hm-navbar-surface);color:var(--hm-navbar-text);flex:none}.pv__brand{display:flex;align-items:center;height:18px;font-size:11px;pointer-events:none}.pv__brand ::ng-deep img{height:18px;width:auto}.pv__search{flex:0 1 36%;height:16px;margin-left:auto;border-radius:var(--hm-radius-pill);background:color-mix(in srgb,var(--hm-navbar-text) 16%,transparent)}.pv__avatar{width:18px;height:18px;border-radius:50%;background:color-mix(in srgb,var(--hm-navbar-text) 30%,transparent)}.pv__body{flex:1;display:flex;min-height:0}.pv__side{display:flex;flex-direction:column;gap:8px;width:22%;padding:12px 10px;background:var(--hm-sidebar-bg);border-right:1px solid var(--hm-border);box-sizing:border-box}.pv__item{height:9px;border-radius:4px;background:color-mix(in srgb,var(--hm-text) 14%,transparent)}.pv__item--on{background:var(--hm-accent)}.pv__item--short{width:60%}.pv__main{flex:1;display:flex;flex-direction:column;min-width:0}.pv__tabs{display:flex;align-items:flex-end;gap:4px;height:26px;padding:0 8px;background:var(--hm-shell-tab-strip-bg);flex:none}.pv__tab{display:flex;align-items:center;width:64px;height:20px;padding:0 8px;border-radius:7px 7px 0 0;box-sizing:border-box;font-size:9px;color:var(--hm-muted)}.pv__tab--on{background:var(--hm-surface-raised);color:var(--hm-text);font-weight:600}.pv__page{flex:1;display:flex;flex-direction:column;gap:10px;padding:12px 14px;background:var(--hm-surface-raised);min-height:0}.pv__title{width:38%;height:11px;border-radius:4px;background:color-mix(in srgb,var(--hm-text) 55%,transparent)}.pv__cards{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}.pv__card{display:flex;flex-direction:column;gap:6px;padding:8px;border:1px solid var(--hm-border);border-radius:8px;background:var(--hm-surface)}.pv__num{width:40%;height:10px;border-radius:3px;background:var(--hm-accent)}.pv__line{display:block;width:70%;height:6px;border-radius:3px;background:color-mix(in srgb,var(--hm-text) 18%,transparent)}.pv__line--short{width:30%}.pv__table{display:flex;flex-direction:column;overflow:hidden;border:1px solid var(--hm-border);border-radius:8px}.pv__row{display:flex;align-items:center;justify-content:space-between;gap:8px;height:calc(16px * var(--hm-text-scale, 1));padding:0 8px;background:var(--hm-surface)}.pv__row:nth-child(odd):not(.pv__row--head){background:color-mix(in srgb,var(--hm-accent) 5%,var(--hm-surface))}:host-context([data-density=compact]) .pv__row{height:calc(12px * var(--hm-text-scale, 1))}.pv__row--head{background:color-mix(in srgb,var(--hm-accent) 20%,var(--hm-surface-raised))}.pv__buttons{display:flex;justify-content:flex-end;gap:6px;margin-top:auto}.pv__btn{width:52px;height:16px;border-radius:var(--hm-radius-control);background:var(--hm-action)}.pv__btn--ghost{background:transparent;border:1px solid var(--hm-border)}.setup__essentials{width:100%;max-width:56rem}.setup__cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(13rem,1fr));gap:var(--hm-space-md);margin:var(--hm-space-xl) 0 0;padding:0;list-style:none}.setup__card{display:flex;flex-direction:column;gap:var(--hm-space-xs);padding:var(--hm-space-lg);border:1px solid var(--hm-border);border-radius:12px;background:var(--hm-surface-raised)}.setup__card-icon{display:inline-grid;place-items:center;width:36px;height:36px;margin-bottom:var(--hm-space-xs);border-radius:10px;background:var(--hm-accent-subtle);color:var(--hm-accent)}.setup__card-title{margin:0;font-size:var(--hm-font-size-md);font-weight:600}.setup__card-text{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-sm);line-height:1.5}.setup__keys{display:inline-flex;gap:3px;vertical-align:baseline}.setup__keys kbd{padding:0 5px;border:1px solid var(--hm-border);border-bottom-width:2px;border-radius:5px;background:var(--hm-surface);color:var(--hm-text);font:inherit;font-size:var(--hm-font-size-xs);font-weight:600}@media(max-width:860px){.setup{padding:var(--hm-space-md)}.setup__body{grid-template-columns:minmax(0,1fr);align-items:start}.setup__preview{display:none}}\n"] }]
|
|
2995
|
+
args: [{ selector: 'spine-initial-setup', imports: [ButtonComponent, IconComponent, SegmentedControlComponent, ThemePickerComponent, SpineBrandComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"setup\" role=\"dialog\" aria-modal=\"true\" [attr.aria-label]=\"t.label\">\n <div class=\"setup__bar\">\n @if (stepTotal() > 1) {\n <span class=\"setup__step\">{{ fmt(t.step, { current: stepNumber(), total: stepTotal() }) }}</span>\n <span class=\"setup__dots\" aria-hidden=\"true\">\n <span class=\"setup__dot\" [class.setup__dot--on]=\"stepNumber() >= 1\"></span>\n <span class=\"setup__dot\" [class.setup__dot--on]=\"stepNumber() >= 2\"></span>\n </span>\n }\n @if (setup.mode() === 'full') {\n <hm-button class=\"setup__skip\" emphasis=\"minimal\" (clicked)=\"setup.finish()\">{{ t.skip }}</hm-button>\n }\n </div>\n\n @if (setup.step() === 'appearance') {\n <div class=\"setup__body\">\n <section class=\"setup__form\">\n <h1 #heading class=\"setup__title\" tabindex=\"-1\">{{ greeting }}</h1>\n <p class=\"setup__intro\">{{ t.appearanceIntro }}</p>\n\n <div class=\"setup__fields\">\n <div class=\"setup__field\">\n <span class=\"setup__label\">{{ s.theme }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"s.theme\" [options]=\"themeOptions\" [value]=\"themeMode()\" (valueChange)=\"setThemeMode($event)\" />\n </div>\n\n <div class=\"setup__field setup__field--wide\">\n <span class=\"setup__label\">{{ s.accent }}</span>\n <hm-theme-picker\n [families]=\"families\"\n [family]=\"family()\"\n [theme]=\"appliedTheme()\"\n [showMode]=\"false\"\n (familyChosen)=\"setFamily($event)\"\n />\n </div>\n\n <div class=\"setup__field\">\n <span class=\"setup__label\">{{ s.density }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"s.density\" [options]=\"densityOptions\" [value]=\"densityValue()\" (valueChange)=\"setDensity($event)\" />\n </div>\n\n <div class=\"setup__field\">\n <span class=\"setup__label\">{{ s.textSize }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"s.textSize\" [options]=\"textSizeOptions()\" [value]=\"textSizeValue()\" (valueChange)=\"setTextSize($event)\" />\n </div>\n\n @if (fontOptions.length > 1) {\n <div class=\"setup__field\">\n <span class=\"setup__label\">{{ s.font }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"s.font\" [options]=\"fontOptions\" [value]=\"fontValue()\" (valueChange)=\"setFont($event)\" />\n </div>\n }\n\n <div class=\"setup__field\">\n <span class=\"setup__label\">{{ s.motion }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"s.motion\" [options]=\"motionOptions\" [value]=\"preferences.motion()\" (valueChange)=\"setMotion($event)\" />\n </div>\n </div>\n\n <div class=\"setup__actions\">\n <hm-button emphasis=\"high\" iconEnd=\"arrow-right\" (clicked)=\"setup.next()\">{{ t.next }}</hm-button>\n </div>\n </section>\n\n <!-- Pr\u00E9via: um shell em miniatura pintado com os tokens do tema, ent\u00E3o acompanha cada escolha. Decorativa. -->\n <figure class=\"setup__preview\">\n <figcaption class=\"setup__preview-label\">{{ t.preview }}</figcaption>\n <div class=\"pv\" aria-hidden=\"true\">\n <div class=\"pv__header\">\n <spine-brand class=\"pv__brand\" [label]=\"appName\" />\n <span class=\"pv__search\"></span>\n <span class=\"pv__avatar\"></span>\n </div>\n <div class=\"pv__body\">\n <div class=\"pv__side\">\n <span class=\"pv__item pv__item--on\"></span>\n <span class=\"pv__item\"></span>\n <span class=\"pv__item\"></span>\n <span class=\"pv__item\"></span>\n <span class=\"pv__item pv__item--short\"></span>\n </div>\n <div class=\"pv__main\">\n <div class=\"pv__tabs\">\n <span class=\"pv__tab pv__tab--on\">{{ t.previewPage }}</span>\n <span class=\"pv__tab\"><span class=\"pv__line\"></span></span>\n <span class=\"pv__tab\"><span class=\"pv__line\"></span></span>\n </div>\n <div class=\"pv__page\">\n <span class=\"pv__title\"></span>\n <div class=\"pv__cards\">\n @for (n of [1, 2, 3]; track n) {\n <span class=\"pv__card\"><span class=\"pv__num\"></span><span class=\"pv__line\"></span></span>\n }\n </div>\n <div class=\"pv__table\">\n <span class=\"pv__row pv__row--head\"></span>\n @for (n of [1, 2, 3, 4]; track n) {\n <span class=\"pv__row\"><span class=\"pv__line\"></span><span class=\"pv__line pv__line--short\"></span></span>\n }\n </div>\n <div class=\"pv__buttons\">\n <span class=\"pv__btn pv__btn--ghost\"></span>\n <span class=\"pv__btn\"></span>\n </div>\n </div>\n </div>\n </div>\n </div>\n </figure>\n </div>\n } @else {\n <div class=\"setup__body setup__body--essentials\">\n <section class=\"setup__essentials\">\n <h1 #heading class=\"setup__title\" tabindex=\"-1\">{{ t.essentialsTitle }}</h1>\n <p class=\"setup__intro\">{{ t.essentialsIntro }}</p>\n\n <ul class=\"setup__cards\">\n @for (card of essentials; track card.id) {\n <li class=\"setup__card\">\n <span class=\"setup__card-icon\"><hm-icon [shape]=\"card.icon\" /></span>\n <h2 class=\"setup__card-title\">{{ card.title }}</h2>\n <p class=\"setup__card-text\">\n {{ card.before }}@if (card.keys) {<span class=\"setup__keys\">@for (step of card.keys; track $index) {@for (key of step; track $index) {<kbd>{{ key.label }}</kbd>}}</span>}{{ card.after }}\n </p>\n </li>\n }\n </ul>\n\n <div class=\"setup__actions\">\n @if (setup.mode() === 'full') {\n <hm-button emphasis=\"medium\" icon=\"arrow-left\" (clicked)=\"setup.back()\">{{ t.back }}</hm-button>\n <hm-button emphasis=\"high\" (clicked)=\"setup.finish()\">{{ t.finish }}</hm-button>\n } @else {\n <hm-button emphasis=\"high\" (clicked)=\"setup.finish()\">{{ t.close }}</hm-button>\n }\n </div>\n </section>\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:host{position:fixed;inset:0;z-index:var(--hm-z-overlay);display:block;overflow:auto;background:var(--hm-surface);color:var(--hm-text)}.setup{display:flex;flex-direction:column;min-height:100%;max-width:76rem;margin:0 auto;padding:var(--hm-space-lg) var(--hm-space-xl) var(--hm-space-2xl);box-sizing:border-box}.setup__bar{display:flex;align-items:center;gap:var(--hm-space-md);min-height:var(--hm-control-height, 40px)}.setup__step{color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.setup__dots{display:inline-flex;gap:6px}.setup__dot{width:24px;height:4px;border-radius:var(--hm-radius-pill);background:var(--hm-border)}.setup__dot--on{background:var(--hm-accent)}.setup__skip{margin-left:auto}.setup__body{flex:1;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);gap:clamp(var(--hm-space-xl),5vw,5rem);align-items:center;padding-top:var(--hm-space-xl)}.setup__body--essentials{grid-template-columns:minmax(0,1fr);justify-items:center}.setup__title{margin:0;font-size:var(--hm-font-size-xxl);font-weight:var(--hm-font-weight-semibold);line-height:1.2;letter-spacing:-.01em;outline:none}.setup__intro{margin:var(--hm-space-sm) 0 0;max-width:34rem;color:var(--hm-muted);line-height:1.5}.setup__fields{display:flex;flex-direction:column;gap:var(--hm-space-lg);margin-top:var(--hm-space-xl)}.setup__field{display:flex;flex-direction:column;align-items:flex-start;gap:var(--hm-space-xs)}.setup__field--wide{align-items:stretch}.setup__label{font-size:var(--hm-font-size-sm);font-weight:var(--hm-font-weight-semibold)}.setup__actions{display:flex;gap:var(--hm-space-sm);margin-top:var(--hm-space-xl)}.setup__preview{margin:0;display:flex;flex-direction:column;gap:var(--hm-space-sm)}.setup__preview-label{color:var(--hm-muted);font-size:var(--hm-font-size-xs);font-weight:var(--hm-font-weight-semibold);letter-spacing:.06em;text-transform:uppercase}.pv{display:flex;flex-direction:column;aspect-ratio:16/11;overflow:hidden;border:1px solid var(--hm-border);border-radius:14px;background:var(--hm-surface);box-shadow:var(--hm-shadow-lg)}.pv__header{display:flex;align-items:center;gap:10px;height:34px;padding:0 10px;background:var(--hm-navbar-surface);color:var(--hm-navbar-text);flex:none}.pv__brand{display:flex;align-items:center;height:18px;font-size:var(--hm-font-size-xs);pointer-events:none}.pv__brand ::ng-deep img{height:18px;width:auto}.pv__search{flex:0 1 36%;height:16px;margin-left:auto;border-radius:var(--hm-radius-pill);background:color-mix(in srgb,var(--hm-navbar-text) 16%,transparent)}.pv__avatar{width:18px;height:18px;border-radius:50%;background:color-mix(in srgb,var(--hm-navbar-text) 30%,transparent)}.pv__body{flex:1;display:flex;min-height:0}.pv__side{display:flex;flex-direction:column;gap:8px;width:22%;padding:12px 10px;background:var(--hm-sidebar-bg);border-right:1px solid var(--hm-border);box-sizing:border-box}.pv__item{height:9px;border-radius:4px;background:color-mix(in srgb,var(--hm-text) 14%,transparent)}.pv__item--on{background:var(--hm-accent)}.pv__item--short{width:60%}.pv__main{flex:1;display:flex;flex-direction:column;min-width:0}.pv__tabs{display:flex;align-items:flex-end;gap:4px;height:26px;padding:0 8px;background:var(--hm-shell-tab-strip-bg);flex:none}.pv__tab{display:flex;align-items:center;width:64px;height:20px;padding:0 8px;border-radius:7px 7px 0 0;box-sizing:border-box;font-size:var(--hm-font-size-3xs);color:var(--hm-muted)}.pv__tab--on{background:var(--hm-surface-raised);color:var(--hm-text);font-weight:var(--hm-font-weight-semibold)}.pv__page{flex:1;display:flex;flex-direction:column;gap:10px;padding:12px 14px;background:var(--hm-surface-raised);min-height:0}.pv__title{width:38%;height:11px;border-radius:4px;background:color-mix(in srgb,var(--hm-text) 55%,transparent)}.pv__cards{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}.pv__card{display:flex;flex-direction:column;gap:6px;padding:8px;border:1px solid var(--hm-border);border-radius:8px;background:var(--hm-surface)}.pv__num{width:40%;height:10px;border-radius:3px;background:var(--hm-accent)}.pv__line{display:block;width:70%;height:6px;border-radius:3px;background:color-mix(in srgb,var(--hm-text) 18%,transparent)}.pv__line--short{width:30%}.pv__table{display:flex;flex-direction:column;overflow:hidden;border:1px solid var(--hm-border);border-radius:8px}.pv__row{display:flex;align-items:center;justify-content:space-between;gap:8px;height:calc(16px * var(--hm-text-scale, 1));padding:0 8px;background:var(--hm-surface)}.pv__row:nth-child(odd):not(.pv__row--head){background:color-mix(in srgb,var(--hm-accent) 5%,var(--hm-surface))}:host-context([data-density=compact]) .pv__row{height:calc(12px * var(--hm-text-scale, 1))}.pv__row--head{background:color-mix(in srgb,var(--hm-accent) 20%,var(--hm-surface-raised))}.pv__buttons{display:flex;justify-content:flex-end;gap:6px;margin-top:auto}.pv__btn{width:52px;height:16px;border-radius:var(--hm-radius-control);background:var(--hm-action)}.pv__btn--ghost{background:transparent;border:1px solid var(--hm-border)}.setup__essentials{width:100%;max-width:56rem}.setup__cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(13rem,1fr));gap:var(--hm-space-md);margin:var(--hm-space-xl) 0 0;padding:0;list-style:none}.setup__card{display:flex;flex-direction:column;gap:var(--hm-space-xs);padding:var(--hm-space-lg);border:1px solid var(--hm-border);border-radius:12px;background:var(--hm-surface-raised)}.setup__card-icon{display:inline-grid;place-items:center;width:36px;height:36px;margin-bottom:var(--hm-space-xs);border-radius:10px;background:var(--hm-accent-subtle);color:var(--hm-accent)}.setup__card-title{margin:0;font-size:var(--hm-font-size-md);font-weight:var(--hm-font-weight-semibold)}.setup__card-text{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-sm);line-height:1.5}.setup__keys{display:inline-flex;gap:3px;vertical-align:baseline}.setup__keys kbd{padding:0 5px;border:1px solid var(--hm-border);border-bottom-width:2px;border-radius:5px;background:var(--hm-surface);color:var(--hm-text);font:inherit;font-size:var(--hm-font-size-xs);font-weight:var(--hm-font-weight-semibold)}@media(max-width:860px){.setup{padding:var(--hm-space-md)}.setup__body{grid-template-columns:minmax(0,1fr);align-items:start}.setup__preview{display:none}}\n"] }]
|
|
2910
2996
|
}], ctorParameters: () => [], propDecorators: { heading: [{ type: i0.ViewChild, args: ['heading', { isSignal: true }] }] } });
|
|
2911
2997
|
|
|
2912
2998
|
/** Novidades por chamada ao servidor: o painel lê as páginas em sequência até ter tudo (ou o teto). */
|
|
@@ -3328,7 +3414,7 @@ class SpineNewsComponent {
|
|
|
3328
3414
|
</ng-container>
|
|
3329
3415
|
</hm-modal>
|
|
3330
3416
|
}
|
|
3331
|
-
`, isInline: true, styles: [".news-state{display:flex;flex-direction:column;align-items:flex-start;gap:var(--hm-space-sm);margin:0}.news-state--muted{color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.news-tools{display:flex;flex-direction:column;gap:var(--hm-space-sm);margin-block-end:var(--hm-space-md)}.news-filters{display:flex;flex-wrap:wrap;gap:var(--hm-space-xs)}.news-filter{display:inline-flex;align-items:center;gap:var(--hm-space-xs);padding:var(--hm-space-micro) var(--hm-space-sm);border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius-pill);background:transparent;color:var(--hm-text);font:inherit;font-size:var(--hm-font-size-sm);cursor:pointer}.news-filter:hover{background:var(--hm-hover)}.news-filter:focus-visible,.news-item:focus-visible,.news-fav:focus-visible{outline:var(--hm-border-thin) solid var(--hm-accent);outline-offset:2px}.news-filter--on{border-color:var(--hm-accent);background:var(--hm-accent-subtle);color:var(--hm-accent);font-weight:var(--hm-font-weight-semibold)}.news-filter__count{font-size:var(--hm-font-size-xs);opacity:.8}.news-groups{display:flex;flex-direction:column;gap:var(--hm-space-md)}.news-groups[aria-busy=true]{opacity:.8}.news-month{display:flex;flex-direction:column;gap:var(--hm-space-xs)}.news-month .news-list{border-block-start:var(--hm-border-hairline) solid var(--hm-border)}.news-pages{margin-inline-end:auto}.news-month__title{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-xs);font-weight:var(--hm-font-weight-semibold);letter-spacing:.06em;text-transform:uppercase}.news-list{display:flex;flex-direction:column;margin:0;padding:0;list-style:none}.news-row{position:relative;display:flex;align-items:flex-start;gap:var(--hm-space-xs);border-block-end:var(--hm-border-hairline) solid var(--hm-border)}.news-row:last-child{border-block-end:0}.news-row--selected{background:var(--hm-accent-subtle)}.news-row--selected:before{content:\"\";position:absolute;inset-block:var(--hm-space-xs);inset-inline-start:0;inline-size:3px;border-radius:var(--hm-radius-pill);background:var(--hm-accent)}.news-item{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--hm-space-micro);min-inline-size:0;padding:var(--hm-space-sm) var(--hm-space-xs) var(--hm-space-sm) var(--hm-space-sm);border:0;border-radius:0;background:transparent;color:inherit;font:inherit;text-align:start;cursor:pointer}.news-item:hover{background:var(--hm-hover)}.news-item__meta{display:flex;align-items:center;gap:var(--hm-space-xs)}.news-item__date{color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.news-item__badge{padding:var(--hm-space-nano) var(--hm-space-xs);border-radius:var(--hm-radius-pill);background:var(--hm-accent-subtle);color:var(--hm-accent);font-size:var(--hm-font-size-3xs);font-weight:var(--hm-font-weight-semibold);letter-spacing:.04em;text-transform:uppercase}.news-item__title{color:var(--hm-text);font-size:var(--hm-font-size-md);font-weight:var(--hm-font-weight-bold);line-height:var(--hm-line-height-tight)}.news-item__summary{display:-webkit-box;overflow:hidden;color:var(--hm-muted);font-size:var(--hm-font-size-sm);line-height:var(--hm-line-height-normal);-webkit-box-orient:vertical;-webkit-line-clamp:2}.news-item__author{display:inline-flex;align-items:center;gap:var(--hm-space-xs);color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.news-fav{display:grid;flex:none;place-items:center;inline-size:var(--hm-control-height);block-size:var(--hm-control-height);margin-block-start:var(--hm-space-sm);border:0;border-radius:var(--hm-radius-control);background:transparent;color:var(--hm-muted);cursor:pointer}.news-fav:hover{background:var(--hm-hover);color:var(--hm-text)}.news-fav--on{color:var(--hm-accent)}:host ::ng-deep .hm-modal__window:has(>.hm-modal__body>.news-read)>.hm-modal__header{position:absolute;z-index:1;inset-block-start:0;inset-inline-end:0;border:0;padding:var(--hm-space-sm)}:host ::ng-deep .hm-modal__window:has(>.hm-modal__body>.news-read) .hm-modal__heading{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.news-read{display:flex;flex-direction:column;gap:var(--hm-space-sm);padding-block-start:var(--hm-space-xs)}.news-read__head{display:flex;flex-direction:column;gap:var(--hm-space-xs);padding-inline-end:calc(var(--hm-control-height) + var(--hm-space-sm));padding-block-end:var(--hm-space-md);border-block-end:var(--hm-border-hairline) solid var(--hm-divider)}.news-read__title-row{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs) var(--hm-space-sm)}.news-read__title{color:var(--hm-text);font-size:var(--hm-font-size-xxl);font-weight:var(--hm-font-weight-bold);line-height:var(--hm-line-height-tight)}.news-read__meta{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs) var(--hm-space-md);color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.news-read__meta-part{display:inline-flex;align-items:center;gap:var(--hm-space-xs)}.news-read__tag{display:inline-flex;align-items:center;gap:var(--hm-space-micro);padding:var(--hm-space-nano) var(--hm-space-xs);border:var(--hm-border-hairline) solid var(--hm-divider);border-radius:var(--hm-radius-pill);background:var(--hm-surface-muted);color:var(--hm-text);font-size:var(--hm-font-size-xs)}.news-read__lead{margin:0;color:var(--hm-text);font-size:var(--hm-font-size-lg);line-height:var(--hm-line-height-snug)}.news-read__section{display:flex;flex-direction:column;gap:var(--hm-space-sm)}.news-read__section-title,.news-compare__title{margin:0;color:var(--hm-text);font-size:var(--hm-font-size-lg);font-weight:var(--hm-font-weight-bold)}.news-changes{display:flex;flex-direction:column;gap:var(--hm-space-xs);margin:0;padding:0;list-style:none}.news-changes__item{display:flex;align-items:flex-start;gap:var(--hm-space-xs);color:var(--hm-text);font-size:var(--hm-font-size-sm);line-height:var(--hm-line-height-normal)}.news-changes__icon{flex:none;margin-block-start:2px;color:var(--hm-success)}.news-compare{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,16rem),1fr));gap:var(--hm-space-md)}.news-compare__side{display:flex;flex-direction:column;gap:var(--hm-space-xs);min-inline-size:0;padding:var(--hm-space-md);border:var(--hm-border-hairline) solid var(--hm-divider);border-inline-start-width:var(--hm-border-thin);border-radius:var(--hm-radius)}.news-compare__side--before{border-inline-start-color:var(--hm-muted);background:var(--hm-surface-muted)}.news-compare__side--after{border-inline-start-color:var(--hm-success);background:var(--hm-surface-raised)}.news-compare__side--after .news-compare__title{color:var(--hm-success)}.news-read__edited{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs);margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.news-read__unread{margin-inline-end:auto}.news-read__body ::ng-deep .hm-rich-text__frame{border:0;background:transparent}.news-read__body ::ng-deep .hm-rich-text__area{padding:0;min-block-size:0}.news-read__body ::ng-deep .hm-prose>:last-child{margin-block-end:0}.news-read__body ::ng-deep :is(h2,h3){color:var(--hm-text);font-weight:var(--hm-font-weight-bold)}\n"], dependencies: [{ kind: "component", type: AccountAvatarComponent, selector: "hm-account-avatar", inputs: ["name", "imageUrl", "size", "loading"] }, { kind: "component", type: AlertComponent, selector: "hm-alert", inputs: ["variant", "appearance", "heading", "closable", "size", "showIcon", "link", "linkLabel", "linkTarget", "dismissKey", "duration"], outputs: ["closed"] }, { kind: "component", type: BreadcrumbComponent, selector: "hm-breadcrumb", inputs: ["items", "maxItems", "itemsBeforeCollapse", "itemsAfterCollapse", "label", "loading"], outputs: ["itemClick"] }, { kind: "component", type: ButtonComponent, selector: "hm-button", inputs: ["emphasis", "intent", "size", "type", "icon", "iconDirection", "iconEnd", "disabled", "loading", "loadingState", "block", "link", "newTab", "caret", "inMenu", "toggle", "pressed"], outputs: ["loadingStateChange", "pressedChange", "clicked"] }, { kind: "component", type: DrawerComponent, selector: "hm-drawer", inputs: ["open", "heading", "size", "position", "pinned", "closeLabel", "closable", "beforeClose"], outputs: ["openChange", "closed"] }, { kind: "component", type: IconComponent, selector: "hm-icon", inputs: ["shape", "direction", "size", "solid", "badge", "status", "flip", "inverse", "label"] }, { kind: "component", type: ModalComponent, selector: "hm-modal", inputs: ["open", "heading", "size", "closeLabel", "closable", "beforeClose"], outputs: ["openChange", "closed"] }, { kind: "component", type: PaginatorComponent, selector: "hm-paginator", inputs: ["state", "totalItems", "variant", "label", "showPage", "hasNext", "hasPrevious", "sizes", "maxNumbers"], outputs: ["stateChanged", "nextPage", "previousPage"] }, { kind: "component", type: RichTextComponent, selector: "hm-rich-text", inputs: ["value", "label", "labelHidden", "hint", "placeholder", "readonly", "loading", "tools", "headingLevels", "hideToolbar", "rows", "maxRows", "maxLength", "showCounter", "pasteMode", "linkProtocols", "allowRelativeLinks", "spellcheck"], outputs: ["valueChange", "focusChange"] }, { kind: "component", type: SearchFieldComponent, selector: "hm-search-field", inputs: ["value", "label", "labelHidden", "placeholder", "hint", "size", "debounce", "landmark", "loading"], outputs: ["valueChange", "search", "cleared"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3417
|
+
`, isInline: true, styles: [".news-state{display:flex;flex-direction:column;align-items:flex-start;gap:var(--hm-space-sm);margin:0}.news-state--muted{color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.news-tools{display:flex;flex-direction:column;gap:var(--hm-space-sm);margin-block-end:var(--hm-space-md)}.news-filters{display:flex;flex-wrap:wrap;gap:var(--hm-space-xs)}.news-filter{display:inline-flex;align-items:center;gap:var(--hm-space-xs);padding:var(--hm-space-micro) var(--hm-space-sm);border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius-pill);background:transparent;color:var(--hm-text);font:inherit;font-size:var(--hm-font-size-sm);cursor:pointer}.news-filter:hover{background:var(--hm-hover)}.news-filter:focus-visible,.news-item:focus-visible,.news-fav:focus-visible{outline:var(--hm-border-thin) solid var(--hm-accent);outline-offset:2px}.news-filter--on{border-color:var(--hm-accent);background:var(--hm-accent-subtle);color:var(--hm-accent);font-weight:var(--hm-font-weight-semibold)}.news-filter__count{font-size:var(--hm-font-size-xs);opacity:.8}.news-groups{display:flex;flex-direction:column;gap:var(--hm-space-md)}.news-groups[aria-busy=true]{opacity:.8}.news-month{display:flex;flex-direction:column;gap:var(--hm-space-xs)}.news-month .news-list{border-block-start:var(--hm-border-hairline) solid var(--hm-border)}.news-pages{margin-inline-end:auto}.news-month__title{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-xs);font-weight:var(--hm-font-weight-semibold);letter-spacing:.06em;text-transform:uppercase}.news-list{display:flex;flex-direction:column;margin:0;padding:0;list-style:none}.news-row{position:relative;display:flex;align-items:flex-start;gap:var(--hm-space-xs);border-block-end:var(--hm-border-hairline) solid var(--hm-border)}.news-row:last-child{border-block-end:0}.news-row--selected{background:var(--hm-accent-subtle)}.news-row--selected:before{content:\"\";position:absolute;inset-block:var(--hm-space-xs);inset-inline-start:0;inline-size:3px;border-radius:var(--hm-radius-pill);background:var(--hm-accent)}.news-item{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--hm-space-micro);min-inline-size:0;padding:var(--hm-space-sm) var(--hm-space-xs) var(--hm-space-sm) var(--hm-space-sm);border:0;border-radius:0;background:transparent;color:inherit;font:inherit;text-align:start;cursor:pointer}.news-item:hover{background:var(--hm-hover)}.news-item__meta{display:flex;align-items:center;gap:var(--hm-space-xs)}.news-item__date{color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.news-item__badge{padding:var(--hm-space-nano) var(--hm-space-xs);border-radius:var(--hm-radius-pill);background:var(--hm-accent-subtle);color:var(--hm-accent);font-size:var(--hm-font-size-3xs);font-weight:var(--hm-font-weight-semibold);letter-spacing:.04em;text-transform:uppercase}.news-item__title{color:var(--hm-text);font-size:var(--hm-font-size-md);font-weight:var(--hm-font-weight-bold);line-height:var(--hm-line-height-tight)}.news-item__summary{display:-webkit-box;overflow:hidden;color:var(--hm-muted);font-size:var(--hm-font-size-sm);line-height:var(--hm-line-height-normal);-webkit-box-orient:vertical;-webkit-line-clamp:2}.news-item__author{display:inline-flex;align-items:center;gap:var(--hm-space-xs);color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.news-fav{display:grid;flex:none;place-items:center;inline-size:var(--hm-control-height);block-size:var(--hm-control-height);margin-block-start:var(--hm-space-sm);border:0;border-radius:var(--hm-radius-control);background:transparent;color:var(--hm-muted);cursor:pointer}.news-fav:hover{background:var(--hm-hover);color:var(--hm-text)}.news-fav--on{color:var(--hm-accent)}:host ::ng-deep .hm-modal__window:has(>.hm-modal__body>.news-read)>.hm-modal__header{position:absolute;z-index:1;inset-block-start:0;inset-inline-end:0;border:0;padding:var(--hm-space-sm)}:host ::ng-deep .hm-modal__window:has(>.hm-modal__body>.news-read) .hm-modal__heading{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.news-read{display:flex;flex-direction:column;gap:var(--hm-space-sm);padding-block-start:var(--hm-space-xs)}.news-read__head{display:flex;flex-direction:column;gap:var(--hm-space-xs);padding-inline-end:calc(var(--hm-control-height) + var(--hm-space-sm));padding-block-end:var(--hm-space-md);border-block-end:var(--hm-border-hairline) solid var(--hm-divider)}.news-read__title-row{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs) var(--hm-space-sm)}.news-read__title{color:var(--hm-text);font-size:var(--hm-font-size-xxl);font-weight:var(--hm-font-weight-bold);line-height:var(--hm-line-height-tight)}.news-read__meta{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs) var(--hm-space-md);color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.news-read__meta-part{display:inline-flex;align-items:center;gap:var(--hm-space-xs)}.news-read__tag{display:inline-flex;align-items:center;gap:var(--hm-space-micro);padding:var(--hm-space-nano) var(--hm-space-xs);border:var(--hm-border-hairline) solid var(--hm-divider);border-radius:var(--hm-radius-pill);background:var(--hm-surface-muted);color:var(--hm-text);font-size:var(--hm-font-size-xs)}.news-read__lead{margin:0;color:var(--hm-text);font-size:var(--hm-font-size-lg);line-height:var(--hm-line-height-snug)}.news-read__section{display:flex;flex-direction:column;gap:var(--hm-space-sm)}.news-read__section-title,.news-compare__title{margin:0;color:var(--hm-text);font-size:var(--hm-font-size-lg);font-weight:var(--hm-font-weight-bold)}.news-changes{display:flex;flex-direction:column;gap:var(--hm-space-xs);margin:0;padding:0;list-style:none}.news-changes__item{display:flex;align-items:flex-start;gap:var(--hm-space-xs);color:var(--hm-text);font-size:var(--hm-font-size-sm);line-height:var(--hm-line-height-normal)}.news-changes__icon{flex:none;margin-block-start:2px;color:var(--hm-success)}.news-compare{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,16rem),1fr));gap:var(--hm-space-md)}.news-compare__side{display:flex;flex-direction:column;gap:var(--hm-space-xs);min-inline-size:0;padding:var(--hm-space-md);border:var(--hm-border-hairline) solid var(--hm-divider);border-inline-start-width:var(--hm-border-thin);border-radius:var(--hm-radius)}.news-compare__side--before{border-inline-start-color:var(--hm-muted);background:var(--hm-surface-muted)}.news-compare__side--after{border-inline-start-color:var(--hm-success);background:var(--hm-surface-raised)}.news-compare__side--after .news-compare__title{color:var(--hm-success)}.news-read__edited{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs);margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.news-read__unread{margin-inline-end:auto}.news-read__body ::ng-deep .hm-rich-text__frame{border:0;background:transparent}.news-read__body ::ng-deep .hm-rich-text__area{padding:0;min-block-size:0}.news-read__body ::ng-deep .hm-prose>:last-child{margin-block-end:0}.news-read__body ::ng-deep :is(h2,h3){color:var(--hm-text);font-weight:var(--hm-font-weight-bold)}\n"], dependencies: [{ kind: "component", type: AccountAvatarComponent, selector: "hm-account-avatar", inputs: ["name", "imageUrl", "size", "loading", "presence", "texts"] }, { kind: "component", type: AlertComponent, selector: "hm-alert", inputs: ["variant", "appearance", "heading", "closable", "size", "showIcon", "link", "linkLabel", "linkTarget", "dismissKey", "duration"], outputs: ["closed"] }, { kind: "component", type: BreadcrumbComponent, selector: "hm-breadcrumb", inputs: ["items", "maxItems", "itemsBeforeCollapse", "itemsAfterCollapse", "label", "loading"], outputs: ["itemClick"] }, { kind: "component", type: ButtonComponent, selector: "hm-button", inputs: ["emphasis", "intent", "size", "type", "icon", "iconDirection", "iconEnd", "disabled", "loading", "loadingState", "block", "link", "newTab", "caret", "inMenu", "toggle", "pressed"], outputs: ["loadingStateChange", "pressedChange", "clicked"] }, { kind: "component", type: DrawerComponent, selector: "hm-drawer", inputs: ["open", "heading", "size", "position", "pinned", "closeLabel", "closable", "closeOnBackdrop", "beforeClose"], outputs: ["openChange", "closed"] }, { kind: "component", type: IconComponent, selector: "hm-icon", inputs: ["shape", "direction", "size", "solid", "badge", "status", "flip", "inverse", "label"] }, { kind: "component", type: ModalComponent, selector: "hm-modal", inputs: ["open", "heading", "size", "closeLabel", "closable", "beforeClose"], outputs: ["openChange", "closed"] }, { kind: "component", type: PaginatorComponent, selector: "hm-paginator", inputs: ["state", "totalItems", "variant", "label", "showPage", "hasNext", "hasPrevious", "sizes", "maxNumbers"], outputs: ["stateChanged", "nextPage", "previousPage"] }, { kind: "component", type: RichTextComponent, selector: "hm-rich-text", inputs: ["value", "label", "labelHidden", "hint", "placeholder", "readonly", "loading", "tools", "headingLevels", "hideToolbar", "rows", "maxRows", "maxLength", "showCounter", "pasteMode", "linkProtocols", "allowRelativeLinks", "spellcheck"], outputs: ["valueChange", "focusChange"] }, { kind: "component", type: SearchFieldComponent, selector: "hm-search-field", inputs: ["value", "label", "labelHidden", "placeholder", "hint", "size", "debounce", "landmark", "loading"], outputs: ["valueChange", "search", "cleared"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3332
3418
|
}
|
|
3333
3419
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: SpineNewsComponent, decorators: [{
|
|
3334
3420
|
type: Component,
|
|
@@ -5390,6 +5476,114 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImpo
|
|
|
5390
5476
|
args: [{ selector: 'spine-app-tokens', imports: [ReactiveFormsModule, ButtonComponent, InputComponent, IconComponent, SegmentedControlComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (!available) {\n <p class=\"sp-account__note\">{{ text.unavailable }}</p>\n} @else {\n <!-- Token rec\u00E9m-criado: \u00FAnica vez em que o valor aparece. -->\n @if (created(); as c) {\n <section class=\"sp-account__panel sp-account__panel--success\" role=\"status\" [attr.aria-labelledby]=\"ids + '-created'\">\n <div class=\"sp-account__panel-head\">\n <hm-icon shape=\"check-circle\" />\n <div class=\"sp-account__panel-text\">\n <h4 class=\"sp-account__title\" [id]=\"ids + '-created'\">{{ fmt(text.created, { name: c.name }) }}</h4>\n <p class=\"sp-account__note\" [innerHTML]=\"fmtHtml(text.sendHeader, { date: formatDate(c.expiresAt) })\"></p>\n </div>\n </div>\n <code class=\"sp-account__secret sp-account__secret--block\">{{ c.token }}</code>\n <div class=\"sp-account__actions\">\n <hm-button emphasis=\"high\" icon=\"copy\" (clicked)=\"copyCreated()\">{{ text.copyToken }}</hm-button>\n <hm-button emphasis=\"medium\" (clicked)=\"dismissCreated()\">{{ text.saved }}</hm-button>\n </div>\n </section>\n }\n\n @if (loading()) {\n <p class=\"sp-account__note\" role=\"status\">{{ text.loading }}</p>\n } @else if (loadError()) {\n <p class=\"sp-account__note sp-account__note--error\">{{ loadError() }}</p>\n } @else {\n <div class=\"sp-account__list\">\n <ul class=\"sp-account__items\">\n @for (t of tokens(); track t.id) {\n <li class=\"sp-account__item\" [class.sp-account__item--muted]=\"t.expired\">\n <span class=\"sp-account__icon\" [class.sp-account__icon--accent]=\"!t.expired\"><hm-icon shape=\"key\" /></span>\n <span class=\"sp-account__item-main\">\n <span class=\"sp-account__item-title\"><strong>{{ t.name }}</strong></span>\n <span class=\"sp-account__meta\">{{ t.badge_name }} \u00B7 <code>{{ t.prefix }}</code></span>\n <span class=\"sp-account__meta\">\n @if (t.expired) { <span class=\"sp-account__meta--danger\">{{ fmt(text.expiredOn, { date: formatDate(t.expires_at) }) }}</span> }\n @else { {{ fmt(text.expiresOn, { date: formatDate(t.expires_at) }) }} }\n \u00B7 {{ fmt(text.lastUsed, { date: formatDate(t.last_used_at) }) }}\n </span>\n </span>\n <span class=\"sp-account__item-actions\">\n @if (confirmingRevoke() === t.id) {\n <hm-button size=\"small\" emphasis=\"medium\" (clicked)=\"cancelRevoke()\">{{ text.cancel }}</hm-button>\n }\n <hm-button size=\"small\" [emphasis]=\"confirmingRevoke() === t.id ? 'high' : 'medium'\" intent=\"danger\" (clicked)=\"revoke(t)\">\n {{ confirmingRevoke() === t.id ? text.confirmRevoke : text.revoke }}\n </hm-button>\n </span>\n </li>\n } @empty {\n <li class=\"sp-account__item sp-account__item--empty\">{{ text.empty }}</li>\n }\n </ul>\n\n @if (!creating()) {\n <div class=\"sp-account__list-footer\">\n <hm-button size=\"small\" emphasis=\"medium\" icon=\"plus\" [disabled]=\"atLimit()\" (clicked)=\"startCreate()\">{{ text.newToken }}</hm-button>\n <span class=\"sp-account__note\">{{ atLimit() ? text.limit : fmt(text.validCount, { valid: validCount(), max: maxActive() }) }}</span>\n </div>\n }\n </div>\n\n @if (creating()) {\n <section class=\"sp-account__panel\" [attr.aria-labelledby]=\"ids + '-new'\">\n <div class=\"sp-account__panel-head\">\n <hm-icon shape=\"key\" />\n <div class=\"sp-account__panel-text\">\n <h4 class=\"sp-account__title\" [id]=\"ids + '-new'\">{{ text.newToken }}</h4>\n @if (clientName()) {\n <p class=\"sp-account__note\" [innerHTML]=\"fmtHtml(text.appOnly, { name: clientName() })\"></p>\n }\n </div>\n </div>\n <form class=\"sp-account__form\" (submit)=\"$event.preventDefault(); submit()\">\n @if (!badges().length) {\n <p class=\"sp-account__note\">{{ text.noBadges }}</p>\n } @else {\n @if (badgeOptions().length > 1) {\n <div class=\"sp-account__field\">\n <span class=\"sp-account__label\">{{ text.accessLevel }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"text.accessLevel\" [options]=\"badgeOptions()\" [value]=\"badgeId()\" (valueChange)=\"badgeId.set($event)\" />\n </div>\n }\n <hm-input [label]=\"text.name\" [placeholder]=\"text.namePlaceholder\" [formControl]=\"nameControl\" [messages]=\"{ required: text.nameRequired, maxlength: text.nameMax }\" />\n <div class=\"sp-account__field\">\n <span class=\"sp-account__label\">{{ text.validity }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"text.validity\" [options]=\"validityOptions()\" [value]=\"validity()\" (valueChange)=\"validity.set($event)\" />\n </div>\n }\n <div class=\"sp-account__actions\">\n @if (badges().length) {\n <hm-button type=\"submit\" emphasis=\"high\" icon=\"key\" [disabled]=\"!canSubmit()\" [loading]=\"submitting()\">{{ text.create }}</hm-button>\n }\n <hm-button emphasis=\"medium\" (clicked)=\"cancelCreate()\">{{ text.cancel }}</hm-button>\n </div>\n </form>\n </section>\n }\n }\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;gap:var(--hm-space-xs);width:100%;min-width:0}.sp-account__note{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-xs);line-height:1.45}.sp-account__note--error{color:var(--hm-danger)}.sp-account__note code{font-family:var(--hm-font-mono)}.sp-account__list{display:flex;flex-direction:column;min-width:0;margin:0;padding:0;list-style:none;overflow:hidden;border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius);background:var(--hm-surface)}.sp-account__items{display:flex;flex-direction:column;min-width:0;margin:0;padding:0;list-style:none}.sp-account__item{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs) var(--hm-space-sm);padding:var(--hm-space-sm)}.sp-account__item+.sp-account__item{border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-account__item--empty{color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.sp-account__item--muted .sp-account__item-title strong{color:var(--hm-muted)}.sp-account__icon{display:inline-flex;flex:none;align-items:center;justify-content:center;width:var(--hm-control-height-large);height:var(--hm-control-height-large);border-radius:var(--hm-radius-control);background:var(--hm-hover);color:var(--hm-muted)}.sp-account__icon--accent{background:var(--hm-accent-subtle);color:var(--hm-accent-strong)}.sp-account__item-main{display:flex;min-width:0;flex:1 1 14rem;flex-direction:column;gap:var(--hm-space-micro);color:var(--hm-text);font-size:var(--hm-font-size-sm);overflow-wrap:anywhere}.sp-account__item-title{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-nano)}.sp-account__item-title strong{font-weight:var(--hm-font-weight-semibold)}.sp-account__meta{color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.sp-account__meta code{font-family:var(--hm-font-mono)}.sp-account__meta--danger{color:var(--hm-danger)}.sp-account__item-actions,.sp-account__actions{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs)}.sp-account__item-actions{margin-inline-start:auto}.sp-account__list-footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--hm-space-xs) var(--hm-space-sm);padding:var(--hm-space-xs) var(--hm-space-sm);border-top:var(--hm-border-hairline) solid var(--hm-divider);background:var(--hm-surface-raised)}.sp-account__list-footer:first-child{border-top:0}.sp-account__panel{display:flex;flex-direction:column;gap:var(--hm-space-sm);min-width:0;padding:var(--hm-space-sm) var(--hm-space-md) var(--hm-space-md);border:var(--hm-border-hairline) solid var(--hm-border);border-inline-start:var(--hm-border-thin) solid var(--hm-accent);border-radius:var(--hm-radius);background:var(--hm-surface-raised)}.sp-account__panel--success{border-color:var(--hm-success);background:var(--hm-success-bg)}.sp-account__panel--success .sp-account__panel-head hm-icon{color:var(--hm-success)}.sp-account__panel--danger{border-inline-start-color:var(--hm-danger)}.sp-account__panel--danger .sp-account__panel-head hm-icon{color:var(--hm-danger)}.sp-account__panel-head{display:flex;align-items:flex-start;gap:var(--hm-space-xs)}.sp-account__panel-head hm-icon{flex:none;margin-block-start:var(--hm-space-micro);color:var(--hm-accent-strong)}.sp-account__panel-text{display:flex;min-width:0;flex-direction:column;gap:var(--hm-space-micro)}.sp-account__title{margin:0;color:var(--hm-text);font-size:var(--hm-font-size-sm);font-weight:var(--hm-font-weight-semibold)}.sp-account__form,.sp-account__code,.sp-account__field{display:flex;flex-direction:column;gap:var(--hm-space-xs);min-width:0}.sp-account__form{gap:var(--hm-space-sm)}.sp-account__label{color:var(--hm-text);font-size:var(--hm-font-size-sm);font-weight:var(--hm-font-weight-semibold)}.sp-account__qr{align-self:flex-start;padding:var(--hm-space-xxxs);border-radius:var(--hm-radius-control);background:var(--hm-surface)}.sp-account__qr img{display:block;width:10rem;max-width:100%;height:auto}.sp-account__secret,.sp-account__codes code{font-family:var(--hm-font-mono);overflow-wrap:anywhere}.sp-account__secret{-webkit-user-select:all;user-select:all}.sp-account__secret--block{display:block;padding:var(--hm-space-xs) var(--hm-space-xxxs);border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius-control);background:var(--hm-surface);color:var(--hm-text);font-size:var(--hm-font-size-xs)}.sp-account__codes{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(9rem,100%),1fr));gap:var(--hm-space-nano) var(--hm-space-sm);margin:0;padding:var(--hm-space-xxxs) var(--hm-space-xs) var(--hm-space-xxxs) var(--hm-space-md);border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius-control);background:var(--hm-surface);color:var(--hm-text);font-size:var(--hm-font-size-sm)}@media(forced-colors:active){.sp-account__panel{border-inline-start-color:Highlight}.sp-account__icon{border:var(--hm-border-hairline) solid CanvasText}}.sp-account__toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs)}.sp-account__choices{display:flex;flex-direction:column;gap:var(--hm-space-xs);min-width:0;margin:0;padding:0;border:0}\n"] }]
|
|
5391
5477
|
}], ctorParameters: () => [] });
|
|
5392
5478
|
|
|
5479
|
+
// Mesma peça de argos admin/ui src/shared/members-loader.ts (o painel central usa a dele). Interna deste ponto de
|
|
5480
|
+
// entrada: não vai no public-api.
|
|
5481
|
+
/** Membros por página pedidos ao servidor: o teto das rotas `GET …/members` do argos-admin. */
|
|
5482
|
+
const MEMBERS_PAGE_LIMIT = 200;
|
|
5483
|
+
/**
|
|
5484
|
+
* Lista inteira de membros carregada aos poucos: o servidor pagina (nunca monta o grupo inteiro em memória) e a tela
|
|
5485
|
+
* pede as páginas uma depois da outra, acrescentando conforme chegam, até ter o `total` (ou vir uma página vazia). A
|
|
5486
|
+
* lista já aparece e funciona com a primeira página; `loading` diz que ainda há páginas a caminho.
|
|
5487
|
+
*
|
|
5488
|
+
* `cancel()` desfaz a inscrição da requisição pendente (o HttpClient a cancela); chame ao fechar a tela ou trocar de
|
|
5489
|
+
* grupo. Falha numa página para em `error`, com o que já chegou intacto; `retry()` continua da página que falhou.
|
|
5490
|
+
*/
|
|
5491
|
+
class MembersLoader {
|
|
5492
|
+
constructor(fetchPage, idOf) {
|
|
5493
|
+
this.fetchPage = fetchPage;
|
|
5494
|
+
this.idOf = idOf;
|
|
5495
|
+
this.items = signal([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
5496
|
+
/** Total do servidor (o grupo inteiro). */
|
|
5497
|
+
this.total = signal(0, ...(ngDevMode ? [{ debugName: "total" }] : /* istanbul ignore next */ []));
|
|
5498
|
+
/** Ainda pedindo páginas. */
|
|
5499
|
+
this.loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
5500
|
+
/** A primeira página já chegou (antes dela a tela mostra o estado de carregando). */
|
|
5501
|
+
this.ready = signal(false, ...(ngDevMode ? [{ debugName: "ready" }] : /* istanbul ignore next */ []));
|
|
5502
|
+
this.error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
|
|
5503
|
+
this.loaded = computed(() => this.items().length, ...(ngDevMode ? [{ debugName: "loaded" }] : /* istanbul ignore next */ []));
|
|
5504
|
+
this.current = null;
|
|
5505
|
+
this.nextPage = 1;
|
|
5506
|
+
this.ids = new Set();
|
|
5507
|
+
}
|
|
5508
|
+
/** Recomeça do zero (cancela o que estava a caminho). */
|
|
5509
|
+
start() {
|
|
5510
|
+
this.cancel();
|
|
5511
|
+
this.items.set([]);
|
|
5512
|
+
this.ids.clear();
|
|
5513
|
+
this.total.set(0);
|
|
5514
|
+
this.ready.set(false);
|
|
5515
|
+
this.error.set(null);
|
|
5516
|
+
this.nextPage = 1;
|
|
5517
|
+
this.fetchNext();
|
|
5518
|
+
}
|
|
5519
|
+
/** Depois de uma falha: continua da página que falhou, sem perder o que já chegou. */
|
|
5520
|
+
retry() {
|
|
5521
|
+
if (this.loading())
|
|
5522
|
+
return;
|
|
5523
|
+
this.error.set(null);
|
|
5524
|
+
this.fetchNext();
|
|
5525
|
+
}
|
|
5526
|
+
cancel() {
|
|
5527
|
+
this.current?.unsubscribe();
|
|
5528
|
+
this.current = null;
|
|
5529
|
+
this.loading.set(false);
|
|
5530
|
+
}
|
|
5531
|
+
/**
|
|
5532
|
+
* Mudança feita pela própria tela depois de gravar (incluir, remover, trocar função), sem reler: `totalDelta` mantém o
|
|
5533
|
+
* total coerente com a lista.
|
|
5534
|
+
*/
|
|
5535
|
+
patch(change, totalDelta = 0) {
|
|
5536
|
+
const next = change(this.items());
|
|
5537
|
+
this.ids.clear();
|
|
5538
|
+
for (const item of next)
|
|
5539
|
+
this.ids.add(this.idOf(item));
|
|
5540
|
+
this.items.set(next);
|
|
5541
|
+
this.total.update((n) => Math.max(next.length, n + totalDelta));
|
|
5542
|
+
}
|
|
5543
|
+
fetchNext() {
|
|
5544
|
+
this.loading.set(true);
|
|
5545
|
+
// A continuação (próxima página) roda no `complete`; com uma resposta síncrona ela começa antes do `subscribe`
|
|
5546
|
+
// devolver, por isso a inscrição vai num contêiner criado antes.
|
|
5547
|
+
const holder = new Subscription();
|
|
5548
|
+
this.current = holder;
|
|
5549
|
+
let more = false;
|
|
5550
|
+
holder.add(this.fetchPage(this.nextPage).subscribe({
|
|
5551
|
+
next: (res) => {
|
|
5552
|
+
const page = res.members ?? [];
|
|
5553
|
+
const fresh = page.filter((item) => !this.ids.has(this.idOf(item)));
|
|
5554
|
+
for (const item of fresh)
|
|
5555
|
+
this.ids.add(this.idOf(item));
|
|
5556
|
+
if (fresh.length)
|
|
5557
|
+
this.items.update((list) => [...list, ...fresh]);
|
|
5558
|
+
this.total.set(Math.max(res.total ?? 0, this.items().length));
|
|
5559
|
+
this.ready.set(true);
|
|
5560
|
+
this.nextPage += 1;
|
|
5561
|
+
// Página vazia, ou só com quem já chegou (o servidor mudou no meio), encerra: sem isso a carga não teria fim.
|
|
5562
|
+
more = fresh.length > 0 && this.items().length < this.total();
|
|
5563
|
+
},
|
|
5564
|
+
error: (err) => {
|
|
5565
|
+
if (this.current !== holder)
|
|
5566
|
+
return;
|
|
5567
|
+
this.current = null;
|
|
5568
|
+
this.error.set(err);
|
|
5569
|
+
this.ready.set(true);
|
|
5570
|
+
this.loading.set(false);
|
|
5571
|
+
},
|
|
5572
|
+
complete: () => {
|
|
5573
|
+
if (this.current !== holder)
|
|
5574
|
+
return;
|
|
5575
|
+
if (more) {
|
|
5576
|
+
this.fetchNext();
|
|
5577
|
+
}
|
|
5578
|
+
else {
|
|
5579
|
+
this.current = null;
|
|
5580
|
+
this.loading.set(false);
|
|
5581
|
+
}
|
|
5582
|
+
},
|
|
5583
|
+
}));
|
|
5584
|
+
}
|
|
5585
|
+
}
|
|
5586
|
+
|
|
5393
5587
|
/**
|
|
5394
5588
|
* Grupos de que a pessoa é membro e o que a função dela permite — `argos-admin /me/groups`. Sempre da aplicação LOGADA (o
|
|
5395
5589
|
* servidor tira o client do access-token da sessão) e sempre com o token da sessão (o servidor recusa x-app-token).
|
|
@@ -5425,8 +5619,19 @@ class SpineMyGroupsService {
|
|
|
5425
5619
|
this.groups.set([]);
|
|
5426
5620
|
}
|
|
5427
5621
|
}
|
|
5428
|
-
|
|
5429
|
-
|
|
5622
|
+
/**
|
|
5623
|
+
* Uma página dos membros, pela ordem do login. Observable (não Promise): a tela pede as páginas até o fim e cancela a
|
|
5624
|
+
* pendente ao sair.
|
|
5625
|
+
*/
|
|
5626
|
+
members(groupId, query = {}) {
|
|
5627
|
+
let params = new HttpParams();
|
|
5628
|
+
if (query.page)
|
|
5629
|
+
params = params.set('page', query.page);
|
|
5630
|
+
if (query.limit)
|
|
5631
|
+
params = params.set('limit', query.limit);
|
|
5632
|
+
if (query.search?.trim())
|
|
5633
|
+
params = params.set('search', query.search.trim());
|
|
5634
|
+
return this.http.get(`${this.baseUrl}${urlPath `/${groupId}/members`}`, { headers: this.headers, params });
|
|
5430
5635
|
}
|
|
5431
5636
|
searchUsers(search, limit = 10) {
|
|
5432
5637
|
return firstValueFrom(this.http.get(`${this.baseUrl}/users`, {
|
|
@@ -5470,6 +5675,9 @@ function groupRoleLabel(text, role) {
|
|
|
5470
5675
|
* Membros; Membro só vê. "Incluir membro" fica acima da lista. Cada ação vale na hora (como os tokens e as sessões do
|
|
5471
5676
|
* painel); remover pede confirmação. A regra é do servidor: os botões só aparecem onde ele aceitaria, e um 403/409 que
|
|
5472
5677
|
* venha mesmo assim vira aviso.
|
|
5678
|
+
*
|
|
5679
|
+
* A lista inteira vem do servidor em páginas, uma depois da outra (`MembersLoader`), e já funciona com a primeira; a
|
|
5680
|
+
* busca é local e instantânea sobre o que já chegou.
|
|
5473
5681
|
*/
|
|
5474
5682
|
class MyGroupComponent {
|
|
5475
5683
|
constructor() {
|
|
@@ -5481,16 +5689,39 @@ class MyGroupComponent {
|
|
|
5481
5689
|
this.i18n = inject(HermesI18nService);
|
|
5482
5690
|
this.auth = inject(AuthorizationService);
|
|
5483
5691
|
this.ids = `sp-group-${++sequence$1}`;
|
|
5484
|
-
|
|
5485
|
-
this.
|
|
5486
|
-
|
|
5692
|
+
/** Todos os membros, carregados aos poucos (o servidor pagina; aqui se pede até o fim). */
|
|
5693
|
+
this.loader = new MembersLoader((page) => this.service.members(this.group().id, { page, limit: MEMBERS_PAGE_LIMIT }), (m) => m.user_id.toLowerCase());
|
|
5694
|
+
/** Busca na lista: local e instantânea (nome, login, e-mail). */
|
|
5695
|
+
this.filterControl = new FormControl('', { nonNullable: true });
|
|
5696
|
+
this.filter = toSignal(this.filterControl.valueChanges, { initialValue: '' });
|
|
5487
5697
|
/** Membro com a remoção aguardando confirmação (segundo clique). */
|
|
5488
5698
|
this.confirmingRemove = signal(null, ...(ngDevMode ? [{ debugName: "confirmingRemove" }] : /* istanbul ignore next */ []));
|
|
5489
5699
|
/** Membro com uma troca de função ou remoção em andamento. */
|
|
5490
5700
|
this.busy = signal(null, ...(ngDevMode ? [{ debugName: "busy" }] : /* istanbul ignore next */ []));
|
|
5491
5701
|
/** `sub` da sessão, para marcar "você" e não oferecer ações sobre si mesmo. */
|
|
5492
5702
|
this.me = (tokenSub(this.auth.getToken()) ?? '').toLowerCase();
|
|
5493
|
-
this.
|
|
5703
|
+
this.members = computed(() => {
|
|
5704
|
+
const term = this.filter().trim().toLowerCase();
|
|
5705
|
+
const all = this.loader.items();
|
|
5706
|
+
if (!term)
|
|
5707
|
+
return all;
|
|
5708
|
+
return all.filter((m) => [m.name, m.username, m.email].some((v) => (v ?? '').toLowerCase().includes(term)));
|
|
5709
|
+
}, ...(ngDevMode ? [{ debugName: "members" }] : /* istanbul ignore next */ []));
|
|
5710
|
+
this.countLabel = computed(() => {
|
|
5711
|
+
const locale = this.i18n.formatLocale();
|
|
5712
|
+
return this.filter().trim()
|
|
5713
|
+
? pluralMessage(this.text.matchesCount, this.members().length, locale)
|
|
5714
|
+
: pluralMessage(this.text.membersCount, this.loader.total(), locale);
|
|
5715
|
+
}, ...(ngDevMode ? [{ debugName: "countLabel" }] : /* istanbul ignore next */ []));
|
|
5716
|
+
/** "Carregando membros… 400 de 1.250". */
|
|
5717
|
+
this.progressLabel = computed(() => {
|
|
5718
|
+
const number = new Intl.NumberFormat(this.i18n.formatLocale());
|
|
5719
|
+
return formatMessage(this.text.loadingProgress, { loaded: number.format(this.loader.loaded()), total: number.format(this.loader.total()) });
|
|
5720
|
+
}, ...(ngDevMode ? [{ debugName: "progressLabel" }] : /* istanbul ignore next */ []));
|
|
5721
|
+
this.incompleteLabel = computed(() => {
|
|
5722
|
+
const number = new Intl.NumberFormat(this.i18n.formatLocale());
|
|
5723
|
+
return formatMessage(this.text.loadIncomplete, { loaded: number.format(this.loader.loaded()), total: number.format(this.loader.total()) });
|
|
5724
|
+
}, ...(ngDevMode ? [{ debugName: "incompleteLabel" }] : /* istanbul ignore next */ []));
|
|
5494
5725
|
/** Funções que o Administrador escolhe (seletor de cada membro e inclusão): Membro, Editor, Administrador. */
|
|
5495
5726
|
this.roleOptions = computed(() => [
|
|
5496
5727
|
{ value: MEMBER, label: this.text.roleMember },
|
|
@@ -5505,13 +5736,16 @@ class MyGroupComponent {
|
|
|
5505
5736
|
this.selected = signal(null, ...(ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []));
|
|
5506
5737
|
this.newRole = signal(MEMBER, ...(ngDevMode ? [{ debugName: "newRole" }] : /* istanbul ignore next */ []));
|
|
5507
5738
|
this.submitting = signal(false, ...(ngDevMode ? [{ debugName: "submitting" }] : /* istanbul ignore next */ []));
|
|
5508
|
-
this.memberIds = computed(() => new Set(this.
|
|
5739
|
+
this.memberIds = computed(() => new Set(this.loader.items().map((m) => m.user_id.toLowerCase())), ...(ngDevMode ? [{ debugName: "memberIds" }] : /* istanbul ignore next */ []));
|
|
5740
|
+
const destroyRef = inject(DestroyRef);
|
|
5509
5741
|
this.searchControl.valueChanges
|
|
5510
|
-
.pipe(debounceTime(300), distinctUntilChanged(), takeUntilDestroyed(
|
|
5742
|
+
.pipe(debounceTime(300), distinctUntilChanged(), takeUntilDestroyed(destroyRef))
|
|
5511
5743
|
.subscribe((value) => void this.search(value));
|
|
5744
|
+
// Sair da tela (voltar aos grupos, fechar o painel) cancela a página que estiver a caminho.
|
|
5745
|
+
destroyRef.onDestroy(() => this.loader.cancel());
|
|
5512
5746
|
}
|
|
5513
5747
|
ngOnInit() {
|
|
5514
|
-
|
|
5748
|
+
this.loader.start();
|
|
5515
5749
|
}
|
|
5516
5750
|
roleLabel(role) {
|
|
5517
5751
|
return groupRoleLabel(this.text, role);
|
|
@@ -5519,6 +5753,7 @@ class MyGroupComponent {
|
|
|
5519
5753
|
isMe(member) {
|
|
5520
5754
|
return member.user_id.toLowerCase() === this.me;
|
|
5521
5755
|
}
|
|
5756
|
+
/** Já é membro? Com a lista ainda carregando, quem não chegou passa (e o servidor responde "já é membro"). */
|
|
5522
5757
|
isMember(user) {
|
|
5523
5758
|
return this.memberIds().has(user.id.toLowerCase());
|
|
5524
5759
|
}
|
|
@@ -5532,21 +5767,15 @@ class MyGroupComponent {
|
|
|
5532
5767
|
canChangeRole(member) {
|
|
5533
5768
|
return this.group().can_change_roles && !this.isMe(member);
|
|
5534
5769
|
}
|
|
5535
|
-
/**
|
|
5536
|
-
|
|
5537
|
-
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
|
|
5542
|
-
|
|
5543
|
-
|
|
5544
|
-
catch (err) {
|
|
5545
|
-
this.loadError.set(errorText(err, this.text.loadError));
|
|
5546
|
-
}
|
|
5547
|
-
finally {
|
|
5548
|
-
this.loading.set(false);
|
|
5549
|
-
}
|
|
5770
|
+
/**
|
|
5771
|
+
* Depois de gravar: muda a lista na tela, sem reler. Inclusão e remoção deslocam as páginas do servidor, então com a
|
|
5772
|
+
* carga ainda em andamento ela recomeça do zero (senão alguém ficaria de fora ou repetido).
|
|
5773
|
+
*/
|
|
5774
|
+
afterWrite(change, totalDelta) {
|
|
5775
|
+
if (totalDelta !== 0 && this.loader.loading())
|
|
5776
|
+
this.loader.start();
|
|
5777
|
+
else
|
|
5778
|
+
this.loader.patch(change, totalDelta);
|
|
5550
5779
|
}
|
|
5551
5780
|
async changeRole(member, value) {
|
|
5552
5781
|
const role = (value || null);
|
|
@@ -5555,12 +5784,12 @@ class MyGroupComponent {
|
|
|
5555
5784
|
this.busy.set(member.user_id);
|
|
5556
5785
|
try {
|
|
5557
5786
|
await this.service.updateRole(this.group().id, member.user_id, role);
|
|
5558
|
-
this.
|
|
5787
|
+
this.afterWrite((list) => list.map((m) => (m.user_id === member.user_id ? { ...m, role } : m)), 0);
|
|
5559
5788
|
this.toast.success(formatMessage(this.text.roleChanged, { name: displayName(member), role: this.roleLabel(role) }));
|
|
5560
5789
|
}
|
|
5561
5790
|
catch (err) {
|
|
5562
5791
|
this.toast.error(errorText(err, this.text.roleError));
|
|
5563
|
-
|
|
5792
|
+
this.loader.start();
|
|
5564
5793
|
}
|
|
5565
5794
|
finally {
|
|
5566
5795
|
this.busy.set(null);
|
|
@@ -5575,12 +5804,12 @@ class MyGroupComponent {
|
|
|
5575
5804
|
this.busy.set(member.user_id);
|
|
5576
5805
|
try {
|
|
5577
5806
|
await this.service.removeMember(this.group().id, member.user_id);
|
|
5578
|
-
this.
|
|
5807
|
+
this.afterWrite((list) => list.filter((m) => m.user_id !== member.user_id), -1);
|
|
5579
5808
|
this.toast.success(formatMessage(this.text.removed, { name: displayName(member) }));
|
|
5580
5809
|
}
|
|
5581
5810
|
catch (err) {
|
|
5582
5811
|
this.toast.error(errorText(err, this.text.removeError));
|
|
5583
|
-
|
|
5812
|
+
this.loader.start();
|
|
5584
5813
|
}
|
|
5585
5814
|
finally {
|
|
5586
5815
|
this.busy.set(null);
|
|
@@ -5638,7 +5867,12 @@ class MyGroupComponent {
|
|
|
5638
5867
|
await this.service.addMember(this.group().id, user.id, role);
|
|
5639
5868
|
this.toast.success(formatMessage(this.text.added, { name: user.name || user.username }));
|
|
5640
5869
|
this.adding.set(false);
|
|
5641
|
-
|
|
5870
|
+
const added = {
|
|
5871
|
+
user_id: user.id, username: user.username, email: user.email, name: user.name, enabled: user.enabled, role,
|
|
5872
|
+
picture: user.picture ?? null, joined_at: new Date().toISOString(), added_by_username: null,
|
|
5873
|
+
};
|
|
5874
|
+
// Entra na posição do login, como o servidor ordena.
|
|
5875
|
+
this.afterWrite((list) => [...list, added].sort((a, b) => a.username.localeCompare(b.username)), 1);
|
|
5642
5876
|
}
|
|
5643
5877
|
catch (err) {
|
|
5644
5878
|
this.toast.error(errorText(err, this.text.addError));
|
|
@@ -5648,14 +5882,14 @@ class MyGroupComponent {
|
|
|
5648
5882
|
}
|
|
5649
5883
|
}
|
|
5650
5884
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: MyGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5651
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: MyGroupComponent, isStandalone: true, selector: "spine-my-group", inputs: { group: { classPropertyName: "group", publicName: "group", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<!-- Incluir membro fica acima da lista: o bot\u00E3o, ou o painel de inclus\u00E3o aberto no lugar dele. -->\n@if (group().can_add) {\n @if (adding()) {\n <section class=\"sp-account__panel\" [attr.aria-labelledby]=\"ids + '-add'\">\n <div class=\"sp-account__panel-head\">\n <hm-icon shape=\"assign-user\" />\n <div class=\"sp-account__panel-text\">\n <h4 class=\"sp-account__title\" [id]=\"ids + '-add'\">{{ fmt(text.addHeading, { group: group().name }) }}</h4>\n @if (!group().can_change_roles) {\n <p class=\"sp-account__note\">{{ text.editorAddsMembers }}</p>\n }\n </div>\n </div>\n <form class=\"sp-account__form\" (submit)=\"$event.preventDefault(); submitAdd()\">\n <hm-input\n icon=\"search\"\n autocomplete=\"off\"\n [label]=\"text.search\"\n [placeholder]=\"text.searchPlaceholder\"\n [hint]=\"text.searchHint\"\n [formControl]=\"searchControl\"\n />\n\n @if (searching()) {\n <p class=\"sp-account__note\" role=\"status\">{{ text.searching }}</p>\n } @else if (searchError()) {\n <p class=\"sp-account__note sp-account__note--error\">{{ searchError() }}</p>\n } @else if (results(); as list) {\n @if (list.length) {\n <ul class=\"sp-account__list sp-group__results\" [attr.aria-label]=\"text.search\">\n @for (u of list; track u.id) {\n <li>\n <button\n type=\"button\"\n class=\"sp-group__result\"\n [class.sp-group__result--selected]=\"selected()?.id === u.id\"\n [attr.aria-pressed]=\"selected()?.id === u.id\"\n [disabled]=\"isMember(u)\"\n (click)=\"pick(u)\"\n >\n <strong>{{ u.name || u.username }}</strong>\n <span class=\"sp-account__meta\">{{ u.username }}@if (u.email) { \u00B7 {{ u.email }} }@if (isMember(u)) { \u00B7 {{ text.alreadyMember }} }</span>\n </button>\n </li>\n }\n </ul>\n } @else {\n <p class=\"sp-account__note\" role=\"status\">{{ text.noResults }}</p>\n }\n }\n\n @if (group().can_change_roles) {\n <div class=\"sp-account__field\">\n <span class=\"sp-account__label\">{{ text.role }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"text.role\" [options]=\"roleOptions()\" [value]=\"newRole()\" (valueChange)=\"newRole.set($event)\" />\n </div>\n }\n\n <div class=\"sp-account__actions\">\n <hm-button type=\"submit\" emphasis=\"high\" icon=\"plus\" [disabled]=\"!selected()\" [loading]=\"submitting()\">{{ text.add }}</hm-button>\n <hm-button emphasis=\"medium\" (clicked)=\"cancelAdd()\">{{ text.cancel }}</hm-button>\n </div>\n </form>\n </section>\n } @else {\n <div class=\"sp-account__actions\">\n <hm-button size=\"small\" emphasis=\"medium\" icon=\"plus\" (clicked)=\"startAdd()\">{{ text.addMember }}</hm-button>\n </div>\n }\n} @else {\n <p class=\"sp-account__note\">{{ text.readOnly }}</p>\n}\n\n@if (loading()) {\n <p class=\"sp-account__note\" role=\"status\">{{ text.loading }}</p>\n} @else if (loadError()) {\n <p class=\"sp-account__note sp-account__note--error\">{{ loadError() }}</p>\n} @else {\n <div class=\"sp-account__list\">\n <ul class=\"sp-account__items\" [attr.aria-label]=\"group().name\">\n @for (m of members(); track m.user_id) {\n <li class=\"sp-account__item\" [class.sp-account__item--muted]=\"!m.enabled\">\n <hm-account-avatar class=\"sp-group__avatar\" [name]=\"m.name || m.username\" [imageUrl]=\"m.picture\" />\n <span class=\"sp-account__item-main\">\n <span class=\"sp-account__item-title\">\n <strong>{{ m.name || m.username }}</strong>\n @if (isMe(m)) { <hm-tag color=\"info\" [name]=\"text.you\" /> }\n </span>\n <span class=\"sp-account__meta\">{{ m.username }}@if (m.email) { \u00B7 {{ m.email }} }</span>\n @if (!canChangeRole(m)) {\n <span class=\"sp-account__meta\">{{ roleLabel(m.role) }}</span>\n }\n </span>\n @if (canChangeRole(m) || canRemove(m)) {\n <span class=\"sp-account__item-actions\">\n <!-- Confirmando a remo\u00E7\u00E3o, a linha mostra s\u00F3 Cancelar e Confirmar (a fun\u00E7\u00E3o n\u00E3o importa mais). -->\n @if (canChangeRole(m) && confirmingRemove() !== m.user_id) {\n <hm-select\n class=\"sp-group__role\"\n [label]=\"fmt(text.roleOf, { name: m.name || m.username })\"\n [labelHidden]=\"true\"\n [value]=\"m.role ?? ''\"\n [disabled]=\"busy() === m.user_id\"\n (valueChange)=\"changeRole(m, $event)\"\n >\n @for (option of roleOptions(); track option.value) {\n <option [value]=\"option.value\">{{ option.label }}</option>\n }\n </hm-select>\n }\n @if (canRemove(m)) {\n @if (confirmingRemove() === m.user_id) {\n <hm-button emphasis=\"medium\" (clicked)=\"cancelRemove()\">{{ text.cancel }}</hm-button>\n }\n <hm-button\n intent=\"danger\"\n [emphasis]=\"confirmingRemove() === m.user_id ? 'high' : 'medium'\"\n [loading]=\"busy() === m.user_id\"\n (clicked)=\"remove(m)\"\n >{{ confirmingRemove() === m.user_id ? text.confirmRemove : text.remove }}</hm-button>\n }\n </span>\n }\n </li>\n } @empty {\n <li class=\"sp-account__item sp-account__item--empty\">{{ text.empty }}</li>\n }\n </ul>\n <div class=\"sp-account__list-footer\">\n <span class=\"sp-account__note\">{{ countLabel() }}</span>\n </div>\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;gap:var(--hm-space-xs);width:100%;min-width:0}.sp-account__note{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-xs);line-height:1.45}.sp-account__note--error{color:var(--hm-danger)}.sp-account__note code{font-family:var(--hm-font-mono)}.sp-account__list{display:flex;flex-direction:column;min-width:0;margin:0;padding:0;list-style:none;overflow:hidden;border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius);background:var(--hm-surface)}.sp-account__items{display:flex;flex-direction:column;min-width:0;margin:0;padding:0;list-style:none}.sp-account__item{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs) var(--hm-space-sm);padding:var(--hm-space-sm)}.sp-account__item+.sp-account__item{border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-account__item--empty{color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.sp-account__item--muted .sp-account__item-title strong{color:var(--hm-muted)}.sp-account__icon{display:inline-flex;flex:none;align-items:center;justify-content:center;width:var(--hm-control-height-large);height:var(--hm-control-height-large);border-radius:var(--hm-radius-control);background:var(--hm-hover);color:var(--hm-muted)}.sp-account__icon--accent{background:var(--hm-accent-subtle);color:var(--hm-accent-strong)}.sp-account__item-main{display:flex;min-width:0;flex:1 1 14rem;flex-direction:column;gap:var(--hm-space-micro);color:var(--hm-text);font-size:var(--hm-font-size-sm);overflow-wrap:anywhere}.sp-account__item-title{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-nano)}.sp-account__item-title strong{font-weight:var(--hm-font-weight-semibold)}.sp-account__meta{color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.sp-account__meta code{font-family:var(--hm-font-mono)}.sp-account__meta--danger{color:var(--hm-danger)}.sp-account__item-actions,.sp-account__actions{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs)}.sp-account__item-actions{margin-inline-start:auto}.sp-account__list-footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--hm-space-xs) var(--hm-space-sm);padding:var(--hm-space-xs) var(--hm-space-sm);border-top:var(--hm-border-hairline) solid var(--hm-divider);background:var(--hm-surface-raised)}.sp-account__list-footer:first-child{border-top:0}.sp-account__panel{display:flex;flex-direction:column;gap:var(--hm-space-sm);min-width:0;padding:var(--hm-space-sm) var(--hm-space-md) var(--hm-space-md);border:var(--hm-border-hairline) solid var(--hm-border);border-inline-start:var(--hm-border-thin) solid var(--hm-accent);border-radius:var(--hm-radius);background:var(--hm-surface-raised)}.sp-account__panel--success{border-color:var(--hm-success);background:var(--hm-success-bg)}.sp-account__panel--success .sp-account__panel-head hm-icon{color:var(--hm-success)}.sp-account__panel--danger{border-inline-start-color:var(--hm-danger)}.sp-account__panel--danger .sp-account__panel-head hm-icon{color:var(--hm-danger)}.sp-account__panel-head{display:flex;align-items:flex-start;gap:var(--hm-space-xs)}.sp-account__panel-head hm-icon{flex:none;margin-block-start:var(--hm-space-micro);color:var(--hm-accent-strong)}.sp-account__panel-text{display:flex;min-width:0;flex-direction:column;gap:var(--hm-space-micro)}.sp-account__title{margin:0;color:var(--hm-text);font-size:var(--hm-font-size-sm);font-weight:var(--hm-font-weight-semibold)}.sp-account__form,.sp-account__code,.sp-account__field{display:flex;flex-direction:column;gap:var(--hm-space-xs);min-width:0}.sp-account__form{gap:var(--hm-space-sm)}.sp-account__label{color:var(--hm-text);font-size:var(--hm-font-size-sm);font-weight:var(--hm-font-weight-semibold)}.sp-account__qr{align-self:flex-start;padding:var(--hm-space-xxxs);border-radius:var(--hm-radius-control);background:var(--hm-surface)}.sp-account__qr img{display:block;width:10rem;max-width:100%;height:auto}.sp-account__secret,.sp-account__codes code{font-family:var(--hm-font-mono);overflow-wrap:anywhere}.sp-account__secret{-webkit-user-select:all;user-select:all}.sp-account__secret--block{display:block;padding:var(--hm-space-xs) var(--hm-space-xxxs);border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius-control);background:var(--hm-surface);color:var(--hm-text);font-size:var(--hm-font-size-xs)}.sp-account__codes{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(9rem,100%),1fr));gap:var(--hm-space-nano) var(--hm-space-sm);margin:0;padding:var(--hm-space-xxxs) var(--hm-space-xs) var(--hm-space-xxxs) var(--hm-space-md);border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius-control);background:var(--hm-surface);color:var(--hm-text);font-size:var(--hm-font-size-sm)}@media(forced-colors:active){.sp-account__panel{border-inline-start-color:Highlight}.sp-account__icon{border:var(--hm-border-hairline) solid CanvasText}}.sp-account__toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs)}.sp-account__choices{display:flex;flex-direction:column;gap:var(--hm-space-xs);min-width:0;margin:0;padding:0;border:0}\n", "@charset \"UTF-8\";.sp-group__avatar{flex:none}.sp-group__role{min-width:10rem}.sp-group__results{max-height:16rem;overflow-y:auto}.sp-group__results li+li{border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-group__result{display:flex;flex-direction:column;align-items:flex-start;gap:var(--hm-space-micro);width:100%;min-width:0;padding:var(--hm-space-xs) var(--hm-space-sm);border:0;background:transparent;color:var(--hm-text);font:inherit;font-size:var(--hm-font-size-sm);text-align:start;overflow-wrap:anywhere;cursor:pointer}.sp-group__result:hover:not(:disabled){background:var(--hm-hover)}.sp-group__result:focus-visible{outline:var(--hm-border-thin) solid var(--hm-accent);outline-offset:calc(var(--hm-border-thin) * -1)}.sp-group__result--selected{background:var(--hm-accent-subtle)}.sp-group__result:disabled{color:var(--hm-muted);cursor:default}.sp-groups__item{display:flex;align-items:center;gap:var(--hm-space-xs) var(--hm-space-sm);width:100%;min-width:0;padding:var(--hm-space-sm);border:0;background:transparent;color:var(--hm-text);font:inherit;text-align:start;cursor:pointer}li+li .sp-groups__item{border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-groups__item:hover{background:var(--hm-hover)}.sp-groups__item:focus-visible{outline:var(--hm-border-thin) solid var(--hm-accent);outline-offset:calc(var(--hm-border-thin) * -1)}.sp-groups__faces{flex:none;margin-inline-start:auto}.sp-groups__chevron{flex:none;color:var(--hm-muted)}.sp-groups__back{display:flex}.sp-groups__heading{margin-block-end:var(--hm-space-xxxs)}@media(forced-colors:active){.sp-group__result--selected{outline:var(--hm-border-thin) solid Highlight;outline-offset:calc(var(--hm-border-thin) * -1)}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: AccountAvatarComponent, selector: "hm-account-avatar", inputs: ["name", "imageUrl", "size", "loading"] }, { kind: "component", type: ButtonComponent, selector: "hm-button", inputs: ["emphasis", "intent", "size", "type", "icon", "iconDirection", "iconEnd", "disabled", "loading", "loadingState", "block", "link", "newTab", "caret", "inMenu", "toggle", "pressed"], outputs: ["loadingStateChange", "pressedChange", "clicked"] }, { kind: "component", type: IconComponent, selector: "hm-icon", inputs: ["shape", "direction", "size", "solid", "badge", "status", "flip", "inverse", "label"] }, { kind: "component", type: InputComponent, selector: "hm-input", inputs: ["value", "label", "type", "placeholder", "icon", "labelHidden", "hint", "prefix", "suffix", "prefixIcon", "mask", "maskValue", "min", "max", "step", "stepButtons", "maxLength", "autocomplete", "inputMode"], outputs: ["valueChange"] }, { kind: "component", type: SegmentedControlComponent, selector: "hm-segmented-control", inputs: ["options", "value", "label", "size", "emphasis"], outputs: ["valueChange"] }, { kind: "component", type: SelectComponent, selector: "hm-select", inputs: ["value", "label", "labelHidden", "hint"], outputs: ["valueChange"] }, { kind: "component", type: TagComponent, selector: "hm-tag", inputs: ["name", "color", "compact"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
5885
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: MyGroupComponent, isStandalone: true, selector: "spine-my-group", inputs: { group: { classPropertyName: "group", publicName: "group", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<!-- Incluir membro fica acima da lista: o bot\u00E3o, ou o painel de inclus\u00E3o aberto no lugar dele. -->\n@if (group().can_add) {\n @if (adding()) {\n <section class=\"sp-account__panel\" [attr.aria-labelledby]=\"ids + '-add'\">\n <div class=\"sp-account__panel-head\">\n <hm-icon shape=\"assign-user\" />\n <div class=\"sp-account__panel-text\">\n <h4 class=\"sp-account__title\" [id]=\"ids + '-add'\">{{ fmt(text.addHeading, { group: group().name }) }}</h4>\n @if (!group().can_change_roles) {\n <p class=\"sp-account__note\">{{ text.editorAddsMembers }}</p>\n }\n </div>\n </div>\n <form class=\"sp-account__form\" (submit)=\"$event.preventDefault(); submitAdd()\">\n <hm-input\n icon=\"search\"\n autocomplete=\"off\"\n [label]=\"text.search\"\n [placeholder]=\"text.searchPlaceholder\"\n [hint]=\"text.searchHint\"\n [formControl]=\"searchControl\"\n />\n\n @if (searching()) {\n <p class=\"sp-account__note\" role=\"status\">{{ text.searching }}</p>\n } @else if (searchError()) {\n <p class=\"sp-account__note sp-account__note--error\">{{ searchError() }}</p>\n } @else if (results(); as list) {\n @if (list.length) {\n <ul class=\"sp-account__list sp-group__results\" [attr.aria-label]=\"text.search\">\n @for (u of list; track u.id) {\n <li>\n <button\n type=\"button\"\n class=\"sp-group__result\"\n [class.sp-group__result--selected]=\"selected()?.id === u.id\"\n [attr.aria-pressed]=\"selected()?.id === u.id\"\n [disabled]=\"isMember(u)\"\n (click)=\"pick(u)\"\n >\n <strong>{{ u.name || u.username }}</strong>\n <span class=\"sp-account__meta\">{{ u.username }}@if (u.email) { \u00B7 {{ u.email }} }@if (isMember(u)) { \u00B7 {{ text.alreadyMember }} }</span>\n </button>\n </li>\n }\n </ul>\n } @else {\n <p class=\"sp-account__note\" role=\"status\">{{ text.noResults }}</p>\n }\n }\n\n @if (group().can_change_roles) {\n <div class=\"sp-account__field\">\n <span class=\"sp-account__label\">{{ text.role }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"text.role\" [options]=\"roleOptions()\" [value]=\"newRole()\" (valueChange)=\"newRole.set($event)\" />\n </div>\n }\n\n <div class=\"sp-account__actions\">\n <hm-button type=\"submit\" emphasis=\"high\" icon=\"plus\" [disabled]=\"!selected()\" [loading]=\"submitting()\">{{ text.add }}</hm-button>\n <hm-button emphasis=\"medium\" (clicked)=\"cancelAdd()\">{{ text.cancel }}</hm-button>\n </div>\n </form>\n </section>\n } @else {\n <div class=\"sp-account__actions\">\n <hm-button size=\"small\" emphasis=\"medium\" icon=\"plus\" (clicked)=\"startAdd()\">{{ text.addMember }}</hm-button>\n </div>\n }\n} @else {\n <p class=\"sp-account__note\">{{ text.readOnly }}</p>\n}\n\n<!-- Busca na lista: local e instant\u00E2nea sobre o que j\u00E1 chegou. Fica fora do \"carregando\" para n\u00E3o perder o foco. -->\n<hm-input\n class=\"sp-group__filter\"\n icon=\"search\"\n type=\"search\"\n autocomplete=\"off\"\n [label]=\"text.filterMembers\"\n [placeholder]=\"text.searchPlaceholder\"\n [formControl]=\"filterControl\"\n/>\n\n@if (loader.error()) {\n <!-- Falha numa p\u00E1gina: o que j\u00E1 chegou continua na lista; \"Tentar de novo\" segue de onde parou. -->\n <div class=\"sp-group__status\">\n <p class=\"sp-account__note sp-account__note--error\">{{ loader.loaded() ? incompleteLabel() : text.loadError }}</p>\n <hm-button size=\"small\" emphasis=\"medium\" icon=\"refresh\" (clicked)=\"loader.retry()\">{{ text.retry }}</hm-button>\n </div>\n} @else if (loader.loading() && loader.ready()) {\n <p class=\"sp-account__note sp-group__status\" role=\"status\">\n {{ progressLabel() }}@if (filter().trim()) { \u00B7 {{ text.partialResults }} }\n </p>\n}\n\n@if (!loader.ready()) {\n <p class=\"sp-account__note\" role=\"status\">{{ text.loading }}</p>\n} @else if (loader.loaded() || !loader.error()) {\n <div class=\"sp-account__list\">\n <ul class=\"sp-account__items\" [attr.aria-label]=\"group().name\">\n @for (m of members(); track m.user_id) {\n <li class=\"sp-account__item\" [class.sp-account__item--muted]=\"!m.enabled\">\n <hm-account-avatar class=\"sp-group__avatar\" [name]=\"m.name || m.username\" [imageUrl]=\"m.picture\" />\n <span class=\"sp-account__item-main\">\n <span class=\"sp-account__item-title\">\n <strong>{{ m.name || m.username }}</strong>\n @if (isMe(m)) { <hm-tag color=\"info\" [name]=\"text.you\" /> }\n </span>\n <span class=\"sp-account__meta\">{{ m.username }}@if (m.email) { \u00B7 {{ m.email }} }</span>\n @if (!canChangeRole(m)) {\n <span class=\"sp-account__meta\">{{ roleLabel(m.role) }}</span>\n }\n </span>\n @if (canChangeRole(m) || canRemove(m)) {\n <span class=\"sp-account__item-actions\">\n <!-- Confirmando a remo\u00E7\u00E3o, a linha mostra s\u00F3 Cancelar e Confirmar (a fun\u00E7\u00E3o n\u00E3o importa mais). -->\n @if (canChangeRole(m) && confirmingRemove() !== m.user_id) {\n <hm-select\n class=\"sp-group__role\"\n [label]=\"fmt(text.roleOf, { name: m.name || m.username })\"\n [labelHidden]=\"true\"\n [value]=\"m.role ?? ''\"\n [disabled]=\"busy() === m.user_id\"\n (valueChange)=\"changeRole(m, $event)\"\n >\n @for (option of roleOptions(); track option.value) {\n <option [value]=\"option.value\">{{ option.label }}</option>\n }\n </hm-select>\n }\n @if (canRemove(m)) {\n @if (confirmingRemove() === m.user_id) {\n <hm-button emphasis=\"medium\" (clicked)=\"cancelRemove()\">{{ text.cancel }}</hm-button>\n }\n <hm-button\n intent=\"danger\"\n [emphasis]=\"confirmingRemove() === m.user_id ? 'high' : 'medium'\"\n [loading]=\"busy() === m.user_id\"\n (clicked)=\"remove(m)\"\n >{{ confirmingRemove() === m.user_id ? text.confirmRemove : text.remove }}</hm-button>\n }\n </span>\n }\n </li>\n } @empty {\n <li class=\"sp-account__item sp-account__item--empty\">{{ filter().trim() ? text.noMatches : text.empty }}</li>\n }\n </ul>\n <div class=\"sp-account__list-footer\">\n <span class=\"sp-account__note\">{{ countLabel() }}</span>\n </div>\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;gap:var(--hm-space-xs);width:100%;min-width:0}.sp-account__note{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-xs);line-height:1.45}.sp-account__note--error{color:var(--hm-danger)}.sp-account__note code{font-family:var(--hm-font-mono)}.sp-account__list{display:flex;flex-direction:column;min-width:0;margin:0;padding:0;list-style:none;overflow:hidden;border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius);background:var(--hm-surface)}.sp-account__items{display:flex;flex-direction:column;min-width:0;margin:0;padding:0;list-style:none}.sp-account__item{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs) var(--hm-space-sm);padding:var(--hm-space-sm)}.sp-account__item+.sp-account__item{border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-account__item--empty{color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.sp-account__item--muted .sp-account__item-title strong{color:var(--hm-muted)}.sp-account__icon{display:inline-flex;flex:none;align-items:center;justify-content:center;width:var(--hm-control-height-large);height:var(--hm-control-height-large);border-radius:var(--hm-radius-control);background:var(--hm-hover);color:var(--hm-muted)}.sp-account__icon--accent{background:var(--hm-accent-subtle);color:var(--hm-accent-strong)}.sp-account__item-main{display:flex;min-width:0;flex:1 1 14rem;flex-direction:column;gap:var(--hm-space-micro);color:var(--hm-text);font-size:var(--hm-font-size-sm);overflow-wrap:anywhere}.sp-account__item-title{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-nano)}.sp-account__item-title strong{font-weight:var(--hm-font-weight-semibold)}.sp-account__meta{color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.sp-account__meta code{font-family:var(--hm-font-mono)}.sp-account__meta--danger{color:var(--hm-danger)}.sp-account__item-actions,.sp-account__actions{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs)}.sp-account__item-actions{margin-inline-start:auto}.sp-account__list-footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--hm-space-xs) var(--hm-space-sm);padding:var(--hm-space-xs) var(--hm-space-sm);border-top:var(--hm-border-hairline) solid var(--hm-divider);background:var(--hm-surface-raised)}.sp-account__list-footer:first-child{border-top:0}.sp-account__panel{display:flex;flex-direction:column;gap:var(--hm-space-sm);min-width:0;padding:var(--hm-space-sm) var(--hm-space-md) var(--hm-space-md);border:var(--hm-border-hairline) solid var(--hm-border);border-inline-start:var(--hm-border-thin) solid var(--hm-accent);border-radius:var(--hm-radius);background:var(--hm-surface-raised)}.sp-account__panel--success{border-color:var(--hm-success);background:var(--hm-success-bg)}.sp-account__panel--success .sp-account__panel-head hm-icon{color:var(--hm-success)}.sp-account__panel--danger{border-inline-start-color:var(--hm-danger)}.sp-account__panel--danger .sp-account__panel-head hm-icon{color:var(--hm-danger)}.sp-account__panel-head{display:flex;align-items:flex-start;gap:var(--hm-space-xs)}.sp-account__panel-head hm-icon{flex:none;margin-block-start:var(--hm-space-micro);color:var(--hm-accent-strong)}.sp-account__panel-text{display:flex;min-width:0;flex-direction:column;gap:var(--hm-space-micro)}.sp-account__title{margin:0;color:var(--hm-text);font-size:var(--hm-font-size-sm);font-weight:var(--hm-font-weight-semibold)}.sp-account__form,.sp-account__code,.sp-account__field{display:flex;flex-direction:column;gap:var(--hm-space-xs);min-width:0}.sp-account__form{gap:var(--hm-space-sm)}.sp-account__label{color:var(--hm-text);font-size:var(--hm-font-size-sm);font-weight:var(--hm-font-weight-semibold)}.sp-account__qr{align-self:flex-start;padding:var(--hm-space-xxxs);border-radius:var(--hm-radius-control);background:var(--hm-surface)}.sp-account__qr img{display:block;width:10rem;max-width:100%;height:auto}.sp-account__secret,.sp-account__codes code{font-family:var(--hm-font-mono);overflow-wrap:anywhere}.sp-account__secret{-webkit-user-select:all;user-select:all}.sp-account__secret--block{display:block;padding:var(--hm-space-xs) var(--hm-space-xxxs);border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius-control);background:var(--hm-surface);color:var(--hm-text);font-size:var(--hm-font-size-xs)}.sp-account__codes{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(9rem,100%),1fr));gap:var(--hm-space-nano) var(--hm-space-sm);margin:0;padding:var(--hm-space-xxxs) var(--hm-space-xs) var(--hm-space-xxxs) var(--hm-space-md);border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius-control);background:var(--hm-surface);color:var(--hm-text);font-size:var(--hm-font-size-sm)}@media(forced-colors:active){.sp-account__panel{border-inline-start-color:Highlight}.sp-account__icon{border:var(--hm-border-hairline) solid CanvasText}}.sp-account__toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs)}.sp-account__choices{display:flex;flex-direction:column;gap:var(--hm-space-xs);min-width:0;margin:0;padding:0;border:0}\n", "@charset \"UTF-8\";.sp-group__avatar{flex:none}.sp-group__role{min-width:10rem}.sp-group__filter{display:block;margin-block:var(--hm-space-sm)}.sp-group__status{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs);margin-block-end:var(--hm-space-sm)}.sp-group__results{max-height:16rem;overflow-y:auto}.sp-group__results li+li{border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-group__result{display:flex;flex-direction:column;align-items:flex-start;gap:var(--hm-space-micro);width:100%;min-width:0;padding:var(--hm-space-xs) var(--hm-space-sm);border:0;background:transparent;color:var(--hm-text);font:inherit;font-size:var(--hm-font-size-sm);text-align:start;overflow-wrap:anywhere;cursor:pointer}.sp-group__result:hover:not(:disabled){background:var(--hm-hover)}.sp-group__result:focus-visible{outline:var(--hm-border-thin) solid var(--hm-accent);outline-offset:calc(var(--hm-border-thin) * -1)}.sp-group__result--selected{background:var(--hm-accent-subtle)}.sp-group__result:disabled{color:var(--hm-muted);cursor:default}.sp-groups__item{display:flex;align-items:center;gap:var(--hm-space-xs) var(--hm-space-sm);width:100%;min-width:0;padding:var(--hm-space-sm);border:0;background:transparent;color:var(--hm-text);font:inherit;font-size:var(--hm-font-size-sm);text-align:start;cursor:pointer}li+li .sp-groups__item{border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-groups__item:hover{background:var(--hm-hover)}.sp-groups__item:focus-visible{outline:var(--hm-border-thin) solid var(--hm-accent);outline-offset:calc(var(--hm-border-thin) * -1)}.sp-groups__faces{flex:none;margin-inline-start:auto}.sp-groups__chevron{flex:none;color:var(--hm-muted)}.sp-groups__back{display:flex}.sp-groups__heading{margin-block-end:var(--hm-space-xxxs)}@media(forced-colors:active){.sp-group__result--selected{outline:var(--hm-border-thin) solid Highlight;outline-offset:calc(var(--hm-border-thin) * -1)}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: AccountAvatarComponent, selector: "hm-account-avatar", inputs: ["name", "imageUrl", "size", "loading", "presence", "texts"] }, { kind: "component", type: ButtonComponent, selector: "hm-button", inputs: ["emphasis", "intent", "size", "type", "icon", "iconDirection", "iconEnd", "disabled", "loading", "loadingState", "block", "link", "newTab", "caret", "inMenu", "toggle", "pressed"], outputs: ["loadingStateChange", "pressedChange", "clicked"] }, { kind: "component", type: IconComponent, selector: "hm-icon", inputs: ["shape", "direction", "size", "solid", "badge", "status", "flip", "inverse", "label"] }, { kind: "component", type: InputComponent, selector: "hm-input", inputs: ["value", "label", "type", "placeholder", "icon", "labelHidden", "hint", "prefix", "suffix", "prefixIcon", "mask", "maskValue", "min", "max", "step", "stepButtons", "maxLength", "autocomplete", "inputMode"], outputs: ["valueChange"] }, { kind: "component", type: SegmentedControlComponent, selector: "hm-segmented-control", inputs: ["options", "value", "label", "size", "emphasis"], outputs: ["valueChange"] }, { kind: "component", type: SelectComponent, selector: "hm-select", inputs: ["value", "label", "labelHidden", "hint"], outputs: ["valueChange"] }, { kind: "component", type: TagComponent, selector: "hm-tag", inputs: ["name", "color", "compact"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
5652
5886
|
}
|
|
5653
5887
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: MyGroupComponent, decorators: [{
|
|
5654
5888
|
type: Component,
|
|
5655
5889
|
args: [{ selector: 'spine-my-group', imports: [
|
|
5656
5890
|
ReactiveFormsModule, AccountAvatarComponent, ButtonComponent, IconComponent, InputComponent, SegmentedControlComponent,
|
|
5657
5891
|
SelectComponent, TagComponent,
|
|
5658
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Incluir membro fica acima da lista: o bot\u00E3o, ou o painel de inclus\u00E3o aberto no lugar dele. -->\n@if (group().can_add) {\n @if (adding()) {\n <section class=\"sp-account__panel\" [attr.aria-labelledby]=\"ids + '-add'\">\n <div class=\"sp-account__panel-head\">\n <hm-icon shape=\"assign-user\" />\n <div class=\"sp-account__panel-text\">\n <h4 class=\"sp-account__title\" [id]=\"ids + '-add'\">{{ fmt(text.addHeading, { group: group().name }) }}</h4>\n @if (!group().can_change_roles) {\n <p class=\"sp-account__note\">{{ text.editorAddsMembers }}</p>\n }\n </div>\n </div>\n <form class=\"sp-account__form\" (submit)=\"$event.preventDefault(); submitAdd()\">\n <hm-input\n icon=\"search\"\n autocomplete=\"off\"\n [label]=\"text.search\"\n [placeholder]=\"text.searchPlaceholder\"\n [hint]=\"text.searchHint\"\n [formControl]=\"searchControl\"\n />\n\n @if (searching()) {\n <p class=\"sp-account__note\" role=\"status\">{{ text.searching }}</p>\n } @else if (searchError()) {\n <p class=\"sp-account__note sp-account__note--error\">{{ searchError() }}</p>\n } @else if (results(); as list) {\n @if (list.length) {\n <ul class=\"sp-account__list sp-group__results\" [attr.aria-label]=\"text.search\">\n @for (u of list; track u.id) {\n <li>\n <button\n type=\"button\"\n class=\"sp-group__result\"\n [class.sp-group__result--selected]=\"selected()?.id === u.id\"\n [attr.aria-pressed]=\"selected()?.id === u.id\"\n [disabled]=\"isMember(u)\"\n (click)=\"pick(u)\"\n >\n <strong>{{ u.name || u.username }}</strong>\n <span class=\"sp-account__meta\">{{ u.username }}@if (u.email) { \u00B7 {{ u.email }} }@if (isMember(u)) { \u00B7 {{ text.alreadyMember }} }</span>\n </button>\n </li>\n }\n </ul>\n } @else {\n <p class=\"sp-account__note\" role=\"status\">{{ text.noResults }}</p>\n }\n }\n\n @if (group().can_change_roles) {\n <div class=\"sp-account__field\">\n <span class=\"sp-account__label\">{{ text.role }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"text.role\" [options]=\"roleOptions()\" [value]=\"newRole()\" (valueChange)=\"newRole.set($event)\" />\n </div>\n }\n\n <div class=\"sp-account__actions\">\n <hm-button type=\"submit\" emphasis=\"high\" icon=\"plus\" [disabled]=\"!selected()\" [loading]=\"submitting()\">{{ text.add }}</hm-button>\n <hm-button emphasis=\"medium\" (clicked)=\"cancelAdd()\">{{ text.cancel }}</hm-button>\n </div>\n </form>\n </section>\n } @else {\n <div class=\"sp-account__actions\">\n <hm-button size=\"small\" emphasis=\"medium\" icon=\"plus\" (clicked)=\"startAdd()\">{{ text.addMember }}</hm-button>\n </div>\n }\n} @else {\n <p class=\"sp-account__note\">{{ text.readOnly }}</p>\n}\n\n@if (loading()) {\n <p class=\"sp-account__note\" role=\"status\">{{ text.loading }}</p>\n} @else if (loadError()) {\n <p class=\"sp-account__note sp-account__note--error\">{{ loadError() }}</p>\n} @else {\n <div class=\"sp-account__list\">\n <ul class=\"sp-account__items\" [attr.aria-label]=\"group().name\">\n @for (m of members(); track m.user_id) {\n <li class=\"sp-account__item\" [class.sp-account__item--muted]=\"!m.enabled\">\n <hm-account-avatar class=\"sp-group__avatar\" [name]=\"m.name || m.username\" [imageUrl]=\"m.picture\" />\n <span class=\"sp-account__item-main\">\n <span class=\"sp-account__item-title\">\n <strong>{{ m.name || m.username }}</strong>\n @if (isMe(m)) { <hm-tag color=\"info\" [name]=\"text.you\" /> }\n </span>\n <span class=\"sp-account__meta\">{{ m.username }}@if (m.email) { \u00B7 {{ m.email }} }</span>\n @if (!canChangeRole(m)) {\n <span class=\"sp-account__meta\">{{ roleLabel(m.role) }}</span>\n }\n </span>\n @if (canChangeRole(m) || canRemove(m)) {\n <span class=\"sp-account__item-actions\">\n <!-- Confirmando a remo\u00E7\u00E3o, a linha mostra s\u00F3 Cancelar e Confirmar (a fun\u00E7\u00E3o n\u00E3o importa mais). -->\n @if (canChangeRole(m) && confirmingRemove() !== m.user_id) {\n <hm-select\n class=\"sp-group__role\"\n [label]=\"fmt(text.roleOf, { name: m.name || m.username })\"\n [labelHidden]=\"true\"\n [value]=\"m.role ?? ''\"\n [disabled]=\"busy() === m.user_id\"\n (valueChange)=\"changeRole(m, $event)\"\n >\n @for (option of roleOptions(); track option.value) {\n <option [value]=\"option.value\">{{ option.label }}</option>\n }\n </hm-select>\n }\n @if (canRemove(m)) {\n @if (confirmingRemove() === m.user_id) {\n <hm-button emphasis=\"medium\" (clicked)=\"cancelRemove()\">{{ text.cancel }}</hm-button>\n }\n <hm-button\n intent=\"danger\"\n [emphasis]=\"confirmingRemove() === m.user_id ? 'high' : 'medium'\"\n [loading]=\"busy() === m.user_id\"\n (clicked)=\"remove(m)\"\n >{{ confirmingRemove() === m.user_id ? text.confirmRemove : text.remove }}</hm-button>\n }\n </span>\n }\n </li>\n } @empty {\n <li class=\"sp-account__item sp-account__item--empty\">{{ text.empty }}</li>\n }\n </ul>\n <div class=\"sp-account__list-footer\">\n <span class=\"sp-account__note\">{{ countLabel() }}</span>\n </div>\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;gap:var(--hm-space-xs);width:100%;min-width:0}.sp-account__note{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-xs);line-height:1.45}.sp-account__note--error{color:var(--hm-danger)}.sp-account__note code{font-family:var(--hm-font-mono)}.sp-account__list{display:flex;flex-direction:column;min-width:0;margin:0;padding:0;list-style:none;overflow:hidden;border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius);background:var(--hm-surface)}.sp-account__items{display:flex;flex-direction:column;min-width:0;margin:0;padding:0;list-style:none}.sp-account__item{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs) var(--hm-space-sm);padding:var(--hm-space-sm)}.sp-account__item+.sp-account__item{border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-account__item--empty{color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.sp-account__item--muted .sp-account__item-title strong{color:var(--hm-muted)}.sp-account__icon{display:inline-flex;flex:none;align-items:center;justify-content:center;width:var(--hm-control-height-large);height:var(--hm-control-height-large);border-radius:var(--hm-radius-control);background:var(--hm-hover);color:var(--hm-muted)}.sp-account__icon--accent{background:var(--hm-accent-subtle);color:var(--hm-accent-strong)}.sp-account__item-main{display:flex;min-width:0;flex:1 1 14rem;flex-direction:column;gap:var(--hm-space-micro);color:var(--hm-text);font-size:var(--hm-font-size-sm);overflow-wrap:anywhere}.sp-account__item-title{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-nano)}.sp-account__item-title strong{font-weight:var(--hm-font-weight-semibold)}.sp-account__meta{color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.sp-account__meta code{font-family:var(--hm-font-mono)}.sp-account__meta--danger{color:var(--hm-danger)}.sp-account__item-actions,.sp-account__actions{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs)}.sp-account__item-actions{margin-inline-start:auto}.sp-account__list-footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--hm-space-xs) var(--hm-space-sm);padding:var(--hm-space-xs) var(--hm-space-sm);border-top:var(--hm-border-hairline) solid var(--hm-divider);background:var(--hm-surface-raised)}.sp-account__list-footer:first-child{border-top:0}.sp-account__panel{display:flex;flex-direction:column;gap:var(--hm-space-sm);min-width:0;padding:var(--hm-space-sm) var(--hm-space-md) var(--hm-space-md);border:var(--hm-border-hairline) solid var(--hm-border);border-inline-start:var(--hm-border-thin) solid var(--hm-accent);border-radius:var(--hm-radius);background:var(--hm-surface-raised)}.sp-account__panel--success{border-color:var(--hm-success);background:var(--hm-success-bg)}.sp-account__panel--success .sp-account__panel-head hm-icon{color:var(--hm-success)}.sp-account__panel--danger{border-inline-start-color:var(--hm-danger)}.sp-account__panel--danger .sp-account__panel-head hm-icon{color:var(--hm-danger)}.sp-account__panel-head{display:flex;align-items:flex-start;gap:var(--hm-space-xs)}.sp-account__panel-head hm-icon{flex:none;margin-block-start:var(--hm-space-micro);color:var(--hm-accent-strong)}.sp-account__panel-text{display:flex;min-width:0;flex-direction:column;gap:var(--hm-space-micro)}.sp-account__title{margin:0;color:var(--hm-text);font-size:var(--hm-font-size-sm);font-weight:var(--hm-font-weight-semibold)}.sp-account__form,.sp-account__code,.sp-account__field{display:flex;flex-direction:column;gap:var(--hm-space-xs);min-width:0}.sp-account__form{gap:var(--hm-space-sm)}.sp-account__label{color:var(--hm-text);font-size:var(--hm-font-size-sm);font-weight:var(--hm-font-weight-semibold)}.sp-account__qr{align-self:flex-start;padding:var(--hm-space-xxxs);border-radius:var(--hm-radius-control);background:var(--hm-surface)}.sp-account__qr img{display:block;width:10rem;max-width:100%;height:auto}.sp-account__secret,.sp-account__codes code{font-family:var(--hm-font-mono);overflow-wrap:anywhere}.sp-account__secret{-webkit-user-select:all;user-select:all}.sp-account__secret--block{display:block;padding:var(--hm-space-xs) var(--hm-space-xxxs);border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius-control);background:var(--hm-surface);color:var(--hm-text);font-size:var(--hm-font-size-xs)}.sp-account__codes{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(9rem,100%),1fr));gap:var(--hm-space-nano) var(--hm-space-sm);margin:0;padding:var(--hm-space-xxxs) var(--hm-space-xs) var(--hm-space-xxxs) var(--hm-space-md);border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius-control);background:var(--hm-surface);color:var(--hm-text);font-size:var(--hm-font-size-sm)}@media(forced-colors:active){.sp-account__panel{border-inline-start-color:Highlight}.sp-account__icon{border:var(--hm-border-hairline) solid CanvasText}}.sp-account__toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs)}.sp-account__choices{display:flex;flex-direction:column;gap:var(--hm-space-xs);min-width:0;margin:0;padding:0;border:0}\n", "@charset \"UTF-8\";.sp-group__avatar{flex:none}.sp-group__role{min-width:10rem}.sp-group__results{max-height:16rem;overflow-y:auto}.sp-group__results li+li{border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-group__result{display:flex;flex-direction:column;align-items:flex-start;gap:var(--hm-space-micro);width:100%;min-width:0;padding:var(--hm-space-xs) var(--hm-space-sm);border:0;background:transparent;color:var(--hm-text);font:inherit;font-size:var(--hm-font-size-sm);text-align:start;overflow-wrap:anywhere;cursor:pointer}.sp-group__result:hover:not(:disabled){background:var(--hm-hover)}.sp-group__result:focus-visible{outline:var(--hm-border-thin) solid var(--hm-accent);outline-offset:calc(var(--hm-border-thin) * -1)}.sp-group__result--selected{background:var(--hm-accent-subtle)}.sp-group__result:disabled{color:var(--hm-muted);cursor:default}.sp-groups__item{display:flex;align-items:center;gap:var(--hm-space-xs) var(--hm-space-sm);width:100%;min-width:0;padding:var(--hm-space-sm);border:0;background:transparent;color:var(--hm-text);font:inherit;text-align:start;cursor:pointer}li+li .sp-groups__item{border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-groups__item:hover{background:var(--hm-hover)}.sp-groups__item:focus-visible{outline:var(--hm-border-thin) solid var(--hm-accent);outline-offset:calc(var(--hm-border-thin) * -1)}.sp-groups__faces{flex:none;margin-inline-start:auto}.sp-groups__chevron{flex:none;color:var(--hm-muted)}.sp-groups__back{display:flex}.sp-groups__heading{margin-block-end:var(--hm-space-xxxs)}@media(forced-colors:active){.sp-group__result--selected{outline:var(--hm-border-thin) solid Highlight;outline-offset:calc(var(--hm-border-thin) * -1)}}\n"] }]
|
|
5892
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Incluir membro fica acima da lista: o bot\u00E3o, ou o painel de inclus\u00E3o aberto no lugar dele. -->\n@if (group().can_add) {\n @if (adding()) {\n <section class=\"sp-account__panel\" [attr.aria-labelledby]=\"ids + '-add'\">\n <div class=\"sp-account__panel-head\">\n <hm-icon shape=\"assign-user\" />\n <div class=\"sp-account__panel-text\">\n <h4 class=\"sp-account__title\" [id]=\"ids + '-add'\">{{ fmt(text.addHeading, { group: group().name }) }}</h4>\n @if (!group().can_change_roles) {\n <p class=\"sp-account__note\">{{ text.editorAddsMembers }}</p>\n }\n </div>\n </div>\n <form class=\"sp-account__form\" (submit)=\"$event.preventDefault(); submitAdd()\">\n <hm-input\n icon=\"search\"\n autocomplete=\"off\"\n [label]=\"text.search\"\n [placeholder]=\"text.searchPlaceholder\"\n [hint]=\"text.searchHint\"\n [formControl]=\"searchControl\"\n />\n\n @if (searching()) {\n <p class=\"sp-account__note\" role=\"status\">{{ text.searching }}</p>\n } @else if (searchError()) {\n <p class=\"sp-account__note sp-account__note--error\">{{ searchError() }}</p>\n } @else if (results(); as list) {\n @if (list.length) {\n <ul class=\"sp-account__list sp-group__results\" [attr.aria-label]=\"text.search\">\n @for (u of list; track u.id) {\n <li>\n <button\n type=\"button\"\n class=\"sp-group__result\"\n [class.sp-group__result--selected]=\"selected()?.id === u.id\"\n [attr.aria-pressed]=\"selected()?.id === u.id\"\n [disabled]=\"isMember(u)\"\n (click)=\"pick(u)\"\n >\n <strong>{{ u.name || u.username }}</strong>\n <span class=\"sp-account__meta\">{{ u.username }}@if (u.email) { \u00B7 {{ u.email }} }@if (isMember(u)) { \u00B7 {{ text.alreadyMember }} }</span>\n </button>\n </li>\n }\n </ul>\n } @else {\n <p class=\"sp-account__note\" role=\"status\">{{ text.noResults }}</p>\n }\n }\n\n @if (group().can_change_roles) {\n <div class=\"sp-account__field\">\n <span class=\"sp-account__label\">{{ text.role }}</span>\n <hm-segmented-control emphasis=\"action\" [label]=\"text.role\" [options]=\"roleOptions()\" [value]=\"newRole()\" (valueChange)=\"newRole.set($event)\" />\n </div>\n }\n\n <div class=\"sp-account__actions\">\n <hm-button type=\"submit\" emphasis=\"high\" icon=\"plus\" [disabled]=\"!selected()\" [loading]=\"submitting()\">{{ text.add }}</hm-button>\n <hm-button emphasis=\"medium\" (clicked)=\"cancelAdd()\">{{ text.cancel }}</hm-button>\n </div>\n </form>\n </section>\n } @else {\n <div class=\"sp-account__actions\">\n <hm-button size=\"small\" emphasis=\"medium\" icon=\"plus\" (clicked)=\"startAdd()\">{{ text.addMember }}</hm-button>\n </div>\n }\n} @else {\n <p class=\"sp-account__note\">{{ text.readOnly }}</p>\n}\n\n<!-- Busca na lista: local e instant\u00E2nea sobre o que j\u00E1 chegou. Fica fora do \"carregando\" para n\u00E3o perder o foco. -->\n<hm-input\n class=\"sp-group__filter\"\n icon=\"search\"\n type=\"search\"\n autocomplete=\"off\"\n [label]=\"text.filterMembers\"\n [placeholder]=\"text.searchPlaceholder\"\n [formControl]=\"filterControl\"\n/>\n\n@if (loader.error()) {\n <!-- Falha numa p\u00E1gina: o que j\u00E1 chegou continua na lista; \"Tentar de novo\" segue de onde parou. -->\n <div class=\"sp-group__status\">\n <p class=\"sp-account__note sp-account__note--error\">{{ loader.loaded() ? incompleteLabel() : text.loadError }}</p>\n <hm-button size=\"small\" emphasis=\"medium\" icon=\"refresh\" (clicked)=\"loader.retry()\">{{ text.retry }}</hm-button>\n </div>\n} @else if (loader.loading() && loader.ready()) {\n <p class=\"sp-account__note sp-group__status\" role=\"status\">\n {{ progressLabel() }}@if (filter().trim()) { \u00B7 {{ text.partialResults }} }\n </p>\n}\n\n@if (!loader.ready()) {\n <p class=\"sp-account__note\" role=\"status\">{{ text.loading }}</p>\n} @else if (loader.loaded() || !loader.error()) {\n <div class=\"sp-account__list\">\n <ul class=\"sp-account__items\" [attr.aria-label]=\"group().name\">\n @for (m of members(); track m.user_id) {\n <li class=\"sp-account__item\" [class.sp-account__item--muted]=\"!m.enabled\">\n <hm-account-avatar class=\"sp-group__avatar\" [name]=\"m.name || m.username\" [imageUrl]=\"m.picture\" />\n <span class=\"sp-account__item-main\">\n <span class=\"sp-account__item-title\">\n <strong>{{ m.name || m.username }}</strong>\n @if (isMe(m)) { <hm-tag color=\"info\" [name]=\"text.you\" /> }\n </span>\n <span class=\"sp-account__meta\">{{ m.username }}@if (m.email) { \u00B7 {{ m.email }} }</span>\n @if (!canChangeRole(m)) {\n <span class=\"sp-account__meta\">{{ roleLabel(m.role) }}</span>\n }\n </span>\n @if (canChangeRole(m) || canRemove(m)) {\n <span class=\"sp-account__item-actions\">\n <!-- Confirmando a remo\u00E7\u00E3o, a linha mostra s\u00F3 Cancelar e Confirmar (a fun\u00E7\u00E3o n\u00E3o importa mais). -->\n @if (canChangeRole(m) && confirmingRemove() !== m.user_id) {\n <hm-select\n class=\"sp-group__role\"\n [label]=\"fmt(text.roleOf, { name: m.name || m.username })\"\n [labelHidden]=\"true\"\n [value]=\"m.role ?? ''\"\n [disabled]=\"busy() === m.user_id\"\n (valueChange)=\"changeRole(m, $event)\"\n >\n @for (option of roleOptions(); track option.value) {\n <option [value]=\"option.value\">{{ option.label }}</option>\n }\n </hm-select>\n }\n @if (canRemove(m)) {\n @if (confirmingRemove() === m.user_id) {\n <hm-button emphasis=\"medium\" (clicked)=\"cancelRemove()\">{{ text.cancel }}</hm-button>\n }\n <hm-button\n intent=\"danger\"\n [emphasis]=\"confirmingRemove() === m.user_id ? 'high' : 'medium'\"\n [loading]=\"busy() === m.user_id\"\n (clicked)=\"remove(m)\"\n >{{ confirmingRemove() === m.user_id ? text.confirmRemove : text.remove }}</hm-button>\n }\n </span>\n }\n </li>\n } @empty {\n <li class=\"sp-account__item sp-account__item--empty\">{{ filter().trim() ? text.noMatches : text.empty }}</li>\n }\n </ul>\n <div class=\"sp-account__list-footer\">\n <span class=\"sp-account__note\">{{ countLabel() }}</span>\n </div>\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;gap:var(--hm-space-xs);width:100%;min-width:0}.sp-account__note{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-xs);line-height:1.45}.sp-account__note--error{color:var(--hm-danger)}.sp-account__note code{font-family:var(--hm-font-mono)}.sp-account__list{display:flex;flex-direction:column;min-width:0;margin:0;padding:0;list-style:none;overflow:hidden;border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius);background:var(--hm-surface)}.sp-account__items{display:flex;flex-direction:column;min-width:0;margin:0;padding:0;list-style:none}.sp-account__item{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs) var(--hm-space-sm);padding:var(--hm-space-sm)}.sp-account__item+.sp-account__item{border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-account__item--empty{color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.sp-account__item--muted .sp-account__item-title strong{color:var(--hm-muted)}.sp-account__icon{display:inline-flex;flex:none;align-items:center;justify-content:center;width:var(--hm-control-height-large);height:var(--hm-control-height-large);border-radius:var(--hm-radius-control);background:var(--hm-hover);color:var(--hm-muted)}.sp-account__icon--accent{background:var(--hm-accent-subtle);color:var(--hm-accent-strong)}.sp-account__item-main{display:flex;min-width:0;flex:1 1 14rem;flex-direction:column;gap:var(--hm-space-micro);color:var(--hm-text);font-size:var(--hm-font-size-sm);overflow-wrap:anywhere}.sp-account__item-title{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-nano)}.sp-account__item-title strong{font-weight:var(--hm-font-weight-semibold)}.sp-account__meta{color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.sp-account__meta code{font-family:var(--hm-font-mono)}.sp-account__meta--danger{color:var(--hm-danger)}.sp-account__item-actions,.sp-account__actions{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs)}.sp-account__item-actions{margin-inline-start:auto}.sp-account__list-footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--hm-space-xs) var(--hm-space-sm);padding:var(--hm-space-xs) var(--hm-space-sm);border-top:var(--hm-border-hairline) solid var(--hm-divider);background:var(--hm-surface-raised)}.sp-account__list-footer:first-child{border-top:0}.sp-account__panel{display:flex;flex-direction:column;gap:var(--hm-space-sm);min-width:0;padding:var(--hm-space-sm) var(--hm-space-md) var(--hm-space-md);border:var(--hm-border-hairline) solid var(--hm-border);border-inline-start:var(--hm-border-thin) solid var(--hm-accent);border-radius:var(--hm-radius);background:var(--hm-surface-raised)}.sp-account__panel--success{border-color:var(--hm-success);background:var(--hm-success-bg)}.sp-account__panel--success .sp-account__panel-head hm-icon{color:var(--hm-success)}.sp-account__panel--danger{border-inline-start-color:var(--hm-danger)}.sp-account__panel--danger .sp-account__panel-head hm-icon{color:var(--hm-danger)}.sp-account__panel-head{display:flex;align-items:flex-start;gap:var(--hm-space-xs)}.sp-account__panel-head hm-icon{flex:none;margin-block-start:var(--hm-space-micro);color:var(--hm-accent-strong)}.sp-account__panel-text{display:flex;min-width:0;flex-direction:column;gap:var(--hm-space-micro)}.sp-account__title{margin:0;color:var(--hm-text);font-size:var(--hm-font-size-sm);font-weight:var(--hm-font-weight-semibold)}.sp-account__form,.sp-account__code,.sp-account__field{display:flex;flex-direction:column;gap:var(--hm-space-xs);min-width:0}.sp-account__form{gap:var(--hm-space-sm)}.sp-account__label{color:var(--hm-text);font-size:var(--hm-font-size-sm);font-weight:var(--hm-font-weight-semibold)}.sp-account__qr{align-self:flex-start;padding:var(--hm-space-xxxs);border-radius:var(--hm-radius-control);background:var(--hm-surface)}.sp-account__qr img{display:block;width:10rem;max-width:100%;height:auto}.sp-account__secret,.sp-account__codes code{font-family:var(--hm-font-mono);overflow-wrap:anywhere}.sp-account__secret{-webkit-user-select:all;user-select:all}.sp-account__secret--block{display:block;padding:var(--hm-space-xs) var(--hm-space-xxxs);border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius-control);background:var(--hm-surface);color:var(--hm-text);font-size:var(--hm-font-size-xs)}.sp-account__codes{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(9rem,100%),1fr));gap:var(--hm-space-nano) var(--hm-space-sm);margin:0;padding:var(--hm-space-xxxs) var(--hm-space-xs) var(--hm-space-xxxs) var(--hm-space-md);border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius-control);background:var(--hm-surface);color:var(--hm-text);font-size:var(--hm-font-size-sm)}@media(forced-colors:active){.sp-account__panel{border-inline-start-color:Highlight}.sp-account__icon{border:var(--hm-border-hairline) solid CanvasText}}.sp-account__toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs)}.sp-account__choices{display:flex;flex-direction:column;gap:var(--hm-space-xs);min-width:0;margin:0;padding:0;border:0}\n", "@charset \"UTF-8\";.sp-group__avatar{flex:none}.sp-group__role{min-width:10rem}.sp-group__filter{display:block;margin-block:var(--hm-space-sm)}.sp-group__status{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs);margin-block-end:var(--hm-space-sm)}.sp-group__results{max-height:16rem;overflow-y:auto}.sp-group__results li+li{border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-group__result{display:flex;flex-direction:column;align-items:flex-start;gap:var(--hm-space-micro);width:100%;min-width:0;padding:var(--hm-space-xs) var(--hm-space-sm);border:0;background:transparent;color:var(--hm-text);font:inherit;font-size:var(--hm-font-size-sm);text-align:start;overflow-wrap:anywhere;cursor:pointer}.sp-group__result:hover:not(:disabled){background:var(--hm-hover)}.sp-group__result:focus-visible{outline:var(--hm-border-thin) solid var(--hm-accent);outline-offset:calc(var(--hm-border-thin) * -1)}.sp-group__result--selected{background:var(--hm-accent-subtle)}.sp-group__result:disabled{color:var(--hm-muted);cursor:default}.sp-groups__item{display:flex;align-items:center;gap:var(--hm-space-xs) var(--hm-space-sm);width:100%;min-width:0;padding:var(--hm-space-sm);border:0;background:transparent;color:var(--hm-text);font:inherit;font-size:var(--hm-font-size-sm);text-align:start;cursor:pointer}li+li .sp-groups__item{border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-groups__item:hover{background:var(--hm-hover)}.sp-groups__item:focus-visible{outline:var(--hm-border-thin) solid var(--hm-accent);outline-offset:calc(var(--hm-border-thin) * -1)}.sp-groups__faces{flex:none;margin-inline-start:auto}.sp-groups__chevron{flex:none;color:var(--hm-muted)}.sp-groups__back{display:flex}.sp-groups__heading{margin-block-end:var(--hm-space-xxxs)}@media(forced-colors:active){.sp-group__result--selected{outline:var(--hm-border-thin) solid Highlight;outline-offset:calc(var(--hm-border-thin) * -1)}}\n"] }]
|
|
5659
5893
|
}], ctorParameters: () => [], propDecorators: { group: [{ type: i0.Input, args: [{ isSignal: true, alias: "group", required: true }] }] } });
|
|
5660
5894
|
function displayName(member) {
|
|
5661
5895
|
return member.name || member.username;
|
|
@@ -5730,11 +5964,11 @@ class MyGroupsComponent {
|
|
|
5730
5964
|
: formatMessage(settings.groupRoleDisabled, { role });
|
|
5731
5965
|
}
|
|
5732
5966
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: MyGroupsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5733
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: MyGroupsComponent, isStandalone: true, selector: "spine-my-groups", inputs: { groups: { classPropertyName: "groups", publicName: "groups", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { openChange: "openChange" }, ngImport: i0, template: "@if (open(); as group) {\n <!-- Tela de membros de um grupo: voltar no topo, depois o grupo e os membros (com \"Incluir membro\" acima da lista). -->\n <div class=\"sp-groups__back\">\n <hm-button size=\"small\" emphasis=\"minimal\" icon=\"arrow-left\" (clicked)=\"back()\">{{ text.back }}</hm-button>\n </div>\n <div class=\"sp-account__panel-text sp-groups__heading\">\n <h4 class=\"sp-account__title\">{{ group.name }}</h4>\n <p class=\"sp-account__note\">{{ summary(group) }}</p>\n </div>\n <spine-my-group [group]=\"group\" />\n} @else {\n <!-- Lista dos grupos: cada um abre a tela de membros. -->\n <div class=\"sp-account__list\">\n <ul class=\"sp-account__items\" [attr.aria-label]=\"text.listLabel\">\n @for (g of groups(); track g.id) {\n <li>\n <button type=\"button\" class=\"sp-groups__item\" (click)=\"openGroup(g)\">\n <span class=\"sp-account__icon\" [class.sp-account__icon--accent]=\"g.enabled\"><hm-icon shape=\"employee-group\" /></span>\n <span class=\"sp-account__item-main\">\n <span class=\"sp-account__item-title\"><strong>{{ g.name }}</strong></span>\n <span class=\"sp-account__meta\">{{ summary(g) }}</span>\n </span>\n @if (g.members_count) {\n <hm-avatar-group class=\"sp-groups__faces\" size=\"small\" [max]=\"4\" [people]=\"peopleOf(g)\" [total]=\"g.members_count\" [label]=\"membersLabel(g)\" />\n }\n <hm-icon class=\"sp-groups__chevron\" shape=\"angle-right\" />\n </button>\n </li>\n }\n </ul>\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;gap:var(--hm-space-xs);width:100%;min-width:0}.sp-account__note{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-xs);line-height:1.45}.sp-account__note--error{color:var(--hm-danger)}.sp-account__note code{font-family:var(--hm-font-mono)}.sp-account__list{display:flex;flex-direction:column;min-width:0;margin:0;padding:0;list-style:none;overflow:hidden;border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius);background:var(--hm-surface)}.sp-account__items{display:flex;flex-direction:column;min-width:0;margin:0;padding:0;list-style:none}.sp-account__item{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs) var(--hm-space-sm);padding:var(--hm-space-sm)}.sp-account__item+.sp-account__item{border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-account__item--empty{color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.sp-account__item--muted .sp-account__item-title strong{color:var(--hm-muted)}.sp-account__icon{display:inline-flex;flex:none;align-items:center;justify-content:center;width:var(--hm-control-height-large);height:var(--hm-control-height-large);border-radius:var(--hm-radius-control);background:var(--hm-hover);color:var(--hm-muted)}.sp-account__icon--accent{background:var(--hm-accent-subtle);color:var(--hm-accent-strong)}.sp-account__item-main{display:flex;min-width:0;flex:1 1 14rem;flex-direction:column;gap:var(--hm-space-micro);color:var(--hm-text);font-size:var(--hm-font-size-sm);overflow-wrap:anywhere}.sp-account__item-title{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-nano)}.sp-account__item-title strong{font-weight:var(--hm-font-weight-semibold)}.sp-account__meta{color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.sp-account__meta code{font-family:var(--hm-font-mono)}.sp-account__meta--danger{color:var(--hm-danger)}.sp-account__item-actions,.sp-account__actions{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs)}.sp-account__item-actions{margin-inline-start:auto}.sp-account__list-footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--hm-space-xs) var(--hm-space-sm);padding:var(--hm-space-xs) var(--hm-space-sm);border-top:var(--hm-border-hairline) solid var(--hm-divider);background:var(--hm-surface-raised)}.sp-account__list-footer:first-child{border-top:0}.sp-account__panel{display:flex;flex-direction:column;gap:var(--hm-space-sm);min-width:0;padding:var(--hm-space-sm) var(--hm-space-md) var(--hm-space-md);border:var(--hm-border-hairline) solid var(--hm-border);border-inline-start:var(--hm-border-thin) solid var(--hm-accent);border-radius:var(--hm-radius);background:var(--hm-surface-raised)}.sp-account__panel--success{border-color:var(--hm-success);background:var(--hm-success-bg)}.sp-account__panel--success .sp-account__panel-head hm-icon{color:var(--hm-success)}.sp-account__panel--danger{border-inline-start-color:var(--hm-danger)}.sp-account__panel--danger .sp-account__panel-head hm-icon{color:var(--hm-danger)}.sp-account__panel-head{display:flex;align-items:flex-start;gap:var(--hm-space-xs)}.sp-account__panel-head hm-icon{flex:none;margin-block-start:var(--hm-space-micro);color:var(--hm-accent-strong)}.sp-account__panel-text{display:flex;min-width:0;flex-direction:column;gap:var(--hm-space-micro)}.sp-account__title{margin:0;color:var(--hm-text);font-size:var(--hm-font-size-sm);font-weight:var(--hm-font-weight-semibold)}.sp-account__form,.sp-account__code,.sp-account__field{display:flex;flex-direction:column;gap:var(--hm-space-xs);min-width:0}.sp-account__form{gap:var(--hm-space-sm)}.sp-account__label{color:var(--hm-text);font-size:var(--hm-font-size-sm);font-weight:var(--hm-font-weight-semibold)}.sp-account__qr{align-self:flex-start;padding:var(--hm-space-xxxs);border-radius:var(--hm-radius-control);background:var(--hm-surface)}.sp-account__qr img{display:block;width:10rem;max-width:100%;height:auto}.sp-account__secret,.sp-account__codes code{font-family:var(--hm-font-mono);overflow-wrap:anywhere}.sp-account__secret{-webkit-user-select:all;user-select:all}.sp-account__secret--block{display:block;padding:var(--hm-space-xs) var(--hm-space-xxxs);border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius-control);background:var(--hm-surface);color:var(--hm-text);font-size:var(--hm-font-size-xs)}.sp-account__codes{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(9rem,100%),1fr));gap:var(--hm-space-nano) var(--hm-space-sm);margin:0;padding:var(--hm-space-xxxs) var(--hm-space-xs) var(--hm-space-xxxs) var(--hm-space-md);border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius-control);background:var(--hm-surface);color:var(--hm-text);font-size:var(--hm-font-size-sm)}@media(forced-colors:active){.sp-account__panel{border-inline-start-color:Highlight}.sp-account__icon{border:var(--hm-border-hairline) solid CanvasText}}.sp-account__toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs)}.sp-account__choices{display:flex;flex-direction:column;gap:var(--hm-space-xs);min-width:0;margin:0;padding:0;border:0}\n", "@charset \"UTF-8\";.sp-group__avatar{flex:none}.sp-group__role{min-width:10rem}.sp-group__results{max-height:16rem;overflow-y:auto}.sp-group__results li+li{border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-group__result{display:flex;flex-direction:column;align-items:flex-start;gap:var(--hm-space-micro);width:100%;min-width:0;padding:var(--hm-space-xs) var(--hm-space-sm);border:0;background:transparent;color:var(--hm-text);font:inherit;font-size:var(--hm-font-size-sm);text-align:start;overflow-wrap:anywhere;cursor:pointer}.sp-group__result:hover:not(:disabled){background:var(--hm-hover)}.sp-group__result:focus-visible{outline:var(--hm-border-thin) solid var(--hm-accent);outline-offset:calc(var(--hm-border-thin) * -1)}.sp-group__result--selected{background:var(--hm-accent-subtle)}.sp-group__result:disabled{color:var(--hm-muted);cursor:default}.sp-groups__item{display:flex;align-items:center;gap:var(--hm-space-xs) var(--hm-space-sm);width:100%;min-width:0;padding:var(--hm-space-sm);border:0;background:transparent;color:var(--hm-text);font:inherit;text-align:start;cursor:pointer}li+li .sp-groups__item{border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-groups__item:hover{background:var(--hm-hover)}.sp-groups__item:focus-visible{outline:var(--hm-border-thin) solid var(--hm-accent);outline-offset:calc(var(--hm-border-thin) * -1)}.sp-groups__faces{flex:none;margin-inline-start:auto}.sp-groups__chevron{flex:none;color:var(--hm-muted)}.sp-groups__back{display:flex}.sp-groups__heading{margin-block-end:var(--hm-space-xxxs)}@media(forced-colors:active){.sp-group__result--selected{outline:var(--hm-border-thin) solid Highlight;outline-offset:calc(var(--hm-border-thin) * -1)}}\n"], dependencies: [{ kind: "component", type: AvatarGroupComponent, selector: "hm-avatar-group", inputs: ["people", "max", "size", "label", "total"] }, { kind: "component", type: ButtonComponent, selector: "hm-button", inputs: ["emphasis", "intent", "size", "type", "icon", "iconDirection", "iconEnd", "disabled", "loading", "loadingState", "block", "link", "newTab", "caret", "inMenu", "toggle", "pressed"], outputs: ["loadingStateChange", "pressedChange", "clicked"] }, { kind: "component", type: IconComponent, selector: "hm-icon", inputs: ["shape", "direction", "size", "solid", "badge", "status", "flip", "inverse", "label"] }, { kind: "component", type: MyGroupComponent, selector: "spine-my-group", inputs: ["group"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
5967
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: MyGroupsComponent, isStandalone: true, selector: "spine-my-groups", inputs: { groups: { classPropertyName: "groups", publicName: "groups", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { openChange: "openChange" }, ngImport: i0, template: "@if (open(); as group) {\n <!-- Tela de membros de um grupo: voltar no topo, depois o grupo e os membros (com \"Incluir membro\" acima da lista). -->\n <div class=\"sp-groups__back\">\n <hm-button size=\"small\" emphasis=\"minimal\" icon=\"arrow-left\" (clicked)=\"back()\">{{ text.back }}</hm-button>\n </div>\n <div class=\"sp-account__panel-text sp-groups__heading\">\n <h4 class=\"sp-account__title\">{{ group.name }}</h4>\n <p class=\"sp-account__note\">{{ summary(group) }}</p>\n </div>\n <spine-my-group [group]=\"group\" />\n} @else {\n <!-- Lista dos grupos: cada um abre a tela de membros. -->\n <div class=\"sp-account__list\">\n <ul class=\"sp-account__items\" [attr.aria-label]=\"text.listLabel\">\n @for (g of groups(); track g.id) {\n <li>\n <button type=\"button\" class=\"sp-groups__item\" (click)=\"openGroup(g)\">\n <span class=\"sp-account__icon\" [class.sp-account__icon--accent]=\"g.enabled\"><hm-icon shape=\"employee-group\" /></span>\n <span class=\"sp-account__item-main\">\n <span class=\"sp-account__item-title\"><strong>{{ g.name }}</strong></span>\n <span class=\"sp-account__meta\">{{ summary(g) }}</span>\n </span>\n @if (g.members_count) {\n <hm-avatar-group class=\"sp-groups__faces\" size=\"small\" [max]=\"4\" [people]=\"peopleOf(g)\" [total]=\"g.members_count\" [label]=\"membersLabel(g)\" />\n }\n <hm-icon class=\"sp-groups__chevron\" shape=\"angle-right\" />\n </button>\n </li>\n }\n </ul>\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;gap:var(--hm-space-xs);width:100%;min-width:0}.sp-account__note{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-xs);line-height:1.45}.sp-account__note--error{color:var(--hm-danger)}.sp-account__note code{font-family:var(--hm-font-mono)}.sp-account__list{display:flex;flex-direction:column;min-width:0;margin:0;padding:0;list-style:none;overflow:hidden;border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius);background:var(--hm-surface)}.sp-account__items{display:flex;flex-direction:column;min-width:0;margin:0;padding:0;list-style:none}.sp-account__item{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs) var(--hm-space-sm);padding:var(--hm-space-sm)}.sp-account__item+.sp-account__item{border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-account__item--empty{color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.sp-account__item--muted .sp-account__item-title strong{color:var(--hm-muted)}.sp-account__icon{display:inline-flex;flex:none;align-items:center;justify-content:center;width:var(--hm-control-height-large);height:var(--hm-control-height-large);border-radius:var(--hm-radius-control);background:var(--hm-hover);color:var(--hm-muted)}.sp-account__icon--accent{background:var(--hm-accent-subtle);color:var(--hm-accent-strong)}.sp-account__item-main{display:flex;min-width:0;flex:1 1 14rem;flex-direction:column;gap:var(--hm-space-micro);color:var(--hm-text);font-size:var(--hm-font-size-sm);overflow-wrap:anywhere}.sp-account__item-title{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-nano)}.sp-account__item-title strong{font-weight:var(--hm-font-weight-semibold)}.sp-account__meta{color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.sp-account__meta code{font-family:var(--hm-font-mono)}.sp-account__meta--danger{color:var(--hm-danger)}.sp-account__item-actions,.sp-account__actions{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs)}.sp-account__item-actions{margin-inline-start:auto}.sp-account__list-footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--hm-space-xs) var(--hm-space-sm);padding:var(--hm-space-xs) var(--hm-space-sm);border-top:var(--hm-border-hairline) solid var(--hm-divider);background:var(--hm-surface-raised)}.sp-account__list-footer:first-child{border-top:0}.sp-account__panel{display:flex;flex-direction:column;gap:var(--hm-space-sm);min-width:0;padding:var(--hm-space-sm) var(--hm-space-md) var(--hm-space-md);border:var(--hm-border-hairline) solid var(--hm-border);border-inline-start:var(--hm-border-thin) solid var(--hm-accent);border-radius:var(--hm-radius);background:var(--hm-surface-raised)}.sp-account__panel--success{border-color:var(--hm-success);background:var(--hm-success-bg)}.sp-account__panel--success .sp-account__panel-head hm-icon{color:var(--hm-success)}.sp-account__panel--danger{border-inline-start-color:var(--hm-danger)}.sp-account__panel--danger .sp-account__panel-head hm-icon{color:var(--hm-danger)}.sp-account__panel-head{display:flex;align-items:flex-start;gap:var(--hm-space-xs)}.sp-account__panel-head hm-icon{flex:none;margin-block-start:var(--hm-space-micro);color:var(--hm-accent-strong)}.sp-account__panel-text{display:flex;min-width:0;flex-direction:column;gap:var(--hm-space-micro)}.sp-account__title{margin:0;color:var(--hm-text);font-size:var(--hm-font-size-sm);font-weight:var(--hm-font-weight-semibold)}.sp-account__form,.sp-account__code,.sp-account__field{display:flex;flex-direction:column;gap:var(--hm-space-xs);min-width:0}.sp-account__form{gap:var(--hm-space-sm)}.sp-account__label{color:var(--hm-text);font-size:var(--hm-font-size-sm);font-weight:var(--hm-font-weight-semibold)}.sp-account__qr{align-self:flex-start;padding:var(--hm-space-xxxs);border-radius:var(--hm-radius-control);background:var(--hm-surface)}.sp-account__qr img{display:block;width:10rem;max-width:100%;height:auto}.sp-account__secret,.sp-account__codes code{font-family:var(--hm-font-mono);overflow-wrap:anywhere}.sp-account__secret{-webkit-user-select:all;user-select:all}.sp-account__secret--block{display:block;padding:var(--hm-space-xs) var(--hm-space-xxxs);border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius-control);background:var(--hm-surface);color:var(--hm-text);font-size:var(--hm-font-size-xs)}.sp-account__codes{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(9rem,100%),1fr));gap:var(--hm-space-nano) var(--hm-space-sm);margin:0;padding:var(--hm-space-xxxs) var(--hm-space-xs) var(--hm-space-xxxs) var(--hm-space-md);border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius-control);background:var(--hm-surface);color:var(--hm-text);font-size:var(--hm-font-size-sm)}@media(forced-colors:active){.sp-account__panel{border-inline-start-color:Highlight}.sp-account__icon{border:var(--hm-border-hairline) solid CanvasText}}.sp-account__toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs)}.sp-account__choices{display:flex;flex-direction:column;gap:var(--hm-space-xs);min-width:0;margin:0;padding:0;border:0}\n", "@charset \"UTF-8\";.sp-group__avatar{flex:none}.sp-group__role{min-width:10rem}.sp-group__filter{display:block;margin-block:var(--hm-space-sm)}.sp-group__status{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs);margin-block-end:var(--hm-space-sm)}.sp-group__results{max-height:16rem;overflow-y:auto}.sp-group__results li+li{border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-group__result{display:flex;flex-direction:column;align-items:flex-start;gap:var(--hm-space-micro);width:100%;min-width:0;padding:var(--hm-space-xs) var(--hm-space-sm);border:0;background:transparent;color:var(--hm-text);font:inherit;font-size:var(--hm-font-size-sm);text-align:start;overflow-wrap:anywhere;cursor:pointer}.sp-group__result:hover:not(:disabled){background:var(--hm-hover)}.sp-group__result:focus-visible{outline:var(--hm-border-thin) solid var(--hm-accent);outline-offset:calc(var(--hm-border-thin) * -1)}.sp-group__result--selected{background:var(--hm-accent-subtle)}.sp-group__result:disabled{color:var(--hm-muted);cursor:default}.sp-groups__item{display:flex;align-items:center;gap:var(--hm-space-xs) var(--hm-space-sm);width:100%;min-width:0;padding:var(--hm-space-sm);border:0;background:transparent;color:var(--hm-text);font:inherit;font-size:var(--hm-font-size-sm);text-align:start;cursor:pointer}li+li .sp-groups__item{border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-groups__item:hover{background:var(--hm-hover)}.sp-groups__item:focus-visible{outline:var(--hm-border-thin) solid var(--hm-accent);outline-offset:calc(var(--hm-border-thin) * -1)}.sp-groups__faces{flex:none;margin-inline-start:auto}.sp-groups__chevron{flex:none;color:var(--hm-muted)}.sp-groups__back{display:flex}.sp-groups__heading{margin-block-end:var(--hm-space-xxxs)}@media(forced-colors:active){.sp-group__result--selected{outline:var(--hm-border-thin) solid Highlight;outline-offset:calc(var(--hm-border-thin) * -1)}}\n"], dependencies: [{ kind: "component", type: AvatarGroupComponent, selector: "hm-avatar-group", inputs: ["people", "max", "size", "label", "total"] }, { kind: "component", type: ButtonComponent, selector: "hm-button", inputs: ["emphasis", "intent", "size", "type", "icon", "iconDirection", "iconEnd", "disabled", "loading", "loadingState", "block", "link", "newTab", "caret", "inMenu", "toggle", "pressed"], outputs: ["loadingStateChange", "pressedChange", "clicked"] }, { kind: "component", type: IconComponent, selector: "hm-icon", inputs: ["shape", "direction", "size", "solid", "badge", "status", "flip", "inverse", "label"] }, { kind: "component", type: MyGroupComponent, selector: "spine-my-group", inputs: ["group"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
5734
5968
|
}
|
|
5735
5969
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: MyGroupsComponent, decorators: [{
|
|
5736
5970
|
type: Component,
|
|
5737
|
-
args: [{ selector: 'spine-my-groups', imports: [AvatarGroupComponent, ButtonComponent, IconComponent, MyGroupComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (open(); as group) {\n <!-- Tela de membros de um grupo: voltar no topo, depois o grupo e os membros (com \"Incluir membro\" acima da lista). -->\n <div class=\"sp-groups__back\">\n <hm-button size=\"small\" emphasis=\"minimal\" icon=\"arrow-left\" (clicked)=\"back()\">{{ text.back }}</hm-button>\n </div>\n <div class=\"sp-account__panel-text sp-groups__heading\">\n <h4 class=\"sp-account__title\">{{ group.name }}</h4>\n <p class=\"sp-account__note\">{{ summary(group) }}</p>\n </div>\n <spine-my-group [group]=\"group\" />\n} @else {\n <!-- Lista dos grupos: cada um abre a tela de membros. -->\n <div class=\"sp-account__list\">\n <ul class=\"sp-account__items\" [attr.aria-label]=\"text.listLabel\">\n @for (g of groups(); track g.id) {\n <li>\n <button type=\"button\" class=\"sp-groups__item\" (click)=\"openGroup(g)\">\n <span class=\"sp-account__icon\" [class.sp-account__icon--accent]=\"g.enabled\"><hm-icon shape=\"employee-group\" /></span>\n <span class=\"sp-account__item-main\">\n <span class=\"sp-account__item-title\"><strong>{{ g.name }}</strong></span>\n <span class=\"sp-account__meta\">{{ summary(g) }}</span>\n </span>\n @if (g.members_count) {\n <hm-avatar-group class=\"sp-groups__faces\" size=\"small\" [max]=\"4\" [people]=\"peopleOf(g)\" [total]=\"g.members_count\" [label]=\"membersLabel(g)\" />\n }\n <hm-icon class=\"sp-groups__chevron\" shape=\"angle-right\" />\n </button>\n </li>\n }\n </ul>\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;gap:var(--hm-space-xs);width:100%;min-width:0}.sp-account__note{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-xs);line-height:1.45}.sp-account__note--error{color:var(--hm-danger)}.sp-account__note code{font-family:var(--hm-font-mono)}.sp-account__list{display:flex;flex-direction:column;min-width:0;margin:0;padding:0;list-style:none;overflow:hidden;border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius);background:var(--hm-surface)}.sp-account__items{display:flex;flex-direction:column;min-width:0;margin:0;padding:0;list-style:none}.sp-account__item{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs) var(--hm-space-sm);padding:var(--hm-space-sm)}.sp-account__item+.sp-account__item{border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-account__item--empty{color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.sp-account__item--muted .sp-account__item-title strong{color:var(--hm-muted)}.sp-account__icon{display:inline-flex;flex:none;align-items:center;justify-content:center;width:var(--hm-control-height-large);height:var(--hm-control-height-large);border-radius:var(--hm-radius-control);background:var(--hm-hover);color:var(--hm-muted)}.sp-account__icon--accent{background:var(--hm-accent-subtle);color:var(--hm-accent-strong)}.sp-account__item-main{display:flex;min-width:0;flex:1 1 14rem;flex-direction:column;gap:var(--hm-space-micro);color:var(--hm-text);font-size:var(--hm-font-size-sm);overflow-wrap:anywhere}.sp-account__item-title{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-nano)}.sp-account__item-title strong{font-weight:var(--hm-font-weight-semibold)}.sp-account__meta{color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.sp-account__meta code{font-family:var(--hm-font-mono)}.sp-account__meta--danger{color:var(--hm-danger)}.sp-account__item-actions,.sp-account__actions{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs)}.sp-account__item-actions{margin-inline-start:auto}.sp-account__list-footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--hm-space-xs) var(--hm-space-sm);padding:var(--hm-space-xs) var(--hm-space-sm);border-top:var(--hm-border-hairline) solid var(--hm-divider);background:var(--hm-surface-raised)}.sp-account__list-footer:first-child{border-top:0}.sp-account__panel{display:flex;flex-direction:column;gap:var(--hm-space-sm);min-width:0;padding:var(--hm-space-sm) var(--hm-space-md) var(--hm-space-md);border:var(--hm-border-hairline) solid var(--hm-border);border-inline-start:var(--hm-border-thin) solid var(--hm-accent);border-radius:var(--hm-radius);background:var(--hm-surface-raised)}.sp-account__panel--success{border-color:var(--hm-success);background:var(--hm-success-bg)}.sp-account__panel--success .sp-account__panel-head hm-icon{color:var(--hm-success)}.sp-account__panel--danger{border-inline-start-color:var(--hm-danger)}.sp-account__panel--danger .sp-account__panel-head hm-icon{color:var(--hm-danger)}.sp-account__panel-head{display:flex;align-items:flex-start;gap:var(--hm-space-xs)}.sp-account__panel-head hm-icon{flex:none;margin-block-start:var(--hm-space-micro);color:var(--hm-accent-strong)}.sp-account__panel-text{display:flex;min-width:0;flex-direction:column;gap:var(--hm-space-micro)}.sp-account__title{margin:0;color:var(--hm-text);font-size:var(--hm-font-size-sm);font-weight:var(--hm-font-weight-semibold)}.sp-account__form,.sp-account__code,.sp-account__field{display:flex;flex-direction:column;gap:var(--hm-space-xs);min-width:0}.sp-account__form{gap:var(--hm-space-sm)}.sp-account__label{color:var(--hm-text);font-size:var(--hm-font-size-sm);font-weight:var(--hm-font-weight-semibold)}.sp-account__qr{align-self:flex-start;padding:var(--hm-space-xxxs);border-radius:var(--hm-radius-control);background:var(--hm-surface)}.sp-account__qr img{display:block;width:10rem;max-width:100%;height:auto}.sp-account__secret,.sp-account__codes code{font-family:var(--hm-font-mono);overflow-wrap:anywhere}.sp-account__secret{-webkit-user-select:all;user-select:all}.sp-account__secret--block{display:block;padding:var(--hm-space-xs) var(--hm-space-xxxs);border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius-control);background:var(--hm-surface);color:var(--hm-text);font-size:var(--hm-font-size-xs)}.sp-account__codes{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(9rem,100%),1fr));gap:var(--hm-space-nano) var(--hm-space-sm);margin:0;padding:var(--hm-space-xxxs) var(--hm-space-xs) var(--hm-space-xxxs) var(--hm-space-md);border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius-control);background:var(--hm-surface);color:var(--hm-text);font-size:var(--hm-font-size-sm)}@media(forced-colors:active){.sp-account__panel{border-inline-start-color:Highlight}.sp-account__icon{border:var(--hm-border-hairline) solid CanvasText}}.sp-account__toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs)}.sp-account__choices{display:flex;flex-direction:column;gap:var(--hm-space-xs);min-width:0;margin:0;padding:0;border:0}\n", "@charset \"UTF-8\";.sp-group__avatar{flex:none}.sp-group__role{min-width:10rem}.sp-group__results{max-height:16rem;overflow-y:auto}.sp-group__results li+li{border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-group__result{display:flex;flex-direction:column;align-items:flex-start;gap:var(--hm-space-micro);width:100%;min-width:0;padding:var(--hm-space-xs) var(--hm-space-sm);border:0;background:transparent;color:var(--hm-text);font:inherit;font-size:var(--hm-font-size-sm);text-align:start;overflow-wrap:anywhere;cursor:pointer}.sp-group__result:hover:not(:disabled){background:var(--hm-hover)}.sp-group__result:focus-visible{outline:var(--hm-border-thin) solid var(--hm-accent);outline-offset:calc(var(--hm-border-thin) * -1)}.sp-group__result--selected{background:var(--hm-accent-subtle)}.sp-group__result:disabled{color:var(--hm-muted);cursor:default}.sp-groups__item{display:flex;align-items:center;gap:var(--hm-space-xs) var(--hm-space-sm);width:100%;min-width:0;padding:var(--hm-space-sm);border:0;background:transparent;color:var(--hm-text);font:inherit;text-align:start;cursor:pointer}li+li .sp-groups__item{border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-groups__item:hover{background:var(--hm-hover)}.sp-groups__item:focus-visible{outline:var(--hm-border-thin) solid var(--hm-accent);outline-offset:calc(var(--hm-border-thin) * -1)}.sp-groups__faces{flex:none;margin-inline-start:auto}.sp-groups__chevron{flex:none;color:var(--hm-muted)}.sp-groups__back{display:flex}.sp-groups__heading{margin-block-end:var(--hm-space-xxxs)}@media(forced-colors:active){.sp-group__result--selected{outline:var(--hm-border-thin) solid Highlight;outline-offset:calc(var(--hm-border-thin) * -1)}}\n"] }]
|
|
5971
|
+
args: [{ selector: 'spine-my-groups', imports: [AvatarGroupComponent, ButtonComponent, IconComponent, MyGroupComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (open(); as group) {\n <!-- Tela de membros de um grupo: voltar no topo, depois o grupo e os membros (com \"Incluir membro\" acima da lista). -->\n <div class=\"sp-groups__back\">\n <hm-button size=\"small\" emphasis=\"minimal\" icon=\"arrow-left\" (clicked)=\"back()\">{{ text.back }}</hm-button>\n </div>\n <div class=\"sp-account__panel-text sp-groups__heading\">\n <h4 class=\"sp-account__title\">{{ group.name }}</h4>\n <p class=\"sp-account__note\">{{ summary(group) }}</p>\n </div>\n <spine-my-group [group]=\"group\" />\n} @else {\n <!-- Lista dos grupos: cada um abre a tela de membros. -->\n <div class=\"sp-account__list\">\n <ul class=\"sp-account__items\" [attr.aria-label]=\"text.listLabel\">\n @for (g of groups(); track g.id) {\n <li>\n <button type=\"button\" class=\"sp-groups__item\" (click)=\"openGroup(g)\">\n <span class=\"sp-account__icon\" [class.sp-account__icon--accent]=\"g.enabled\"><hm-icon shape=\"employee-group\" /></span>\n <span class=\"sp-account__item-main\">\n <span class=\"sp-account__item-title\"><strong>{{ g.name }}</strong></span>\n <span class=\"sp-account__meta\">{{ summary(g) }}</span>\n </span>\n @if (g.members_count) {\n <hm-avatar-group class=\"sp-groups__faces\" size=\"small\" [max]=\"4\" [people]=\"peopleOf(g)\" [total]=\"g.members_count\" [label]=\"membersLabel(g)\" />\n }\n <hm-icon class=\"sp-groups__chevron\" shape=\"angle-right\" />\n </button>\n </li>\n }\n </ul>\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;gap:var(--hm-space-xs);width:100%;min-width:0}.sp-account__note{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-xs);line-height:1.45}.sp-account__note--error{color:var(--hm-danger)}.sp-account__note code{font-family:var(--hm-font-mono)}.sp-account__list{display:flex;flex-direction:column;min-width:0;margin:0;padding:0;list-style:none;overflow:hidden;border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius);background:var(--hm-surface)}.sp-account__items{display:flex;flex-direction:column;min-width:0;margin:0;padding:0;list-style:none}.sp-account__item{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs) var(--hm-space-sm);padding:var(--hm-space-sm)}.sp-account__item+.sp-account__item{border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-account__item--empty{color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.sp-account__item--muted .sp-account__item-title strong{color:var(--hm-muted)}.sp-account__icon{display:inline-flex;flex:none;align-items:center;justify-content:center;width:var(--hm-control-height-large);height:var(--hm-control-height-large);border-radius:var(--hm-radius-control);background:var(--hm-hover);color:var(--hm-muted)}.sp-account__icon--accent{background:var(--hm-accent-subtle);color:var(--hm-accent-strong)}.sp-account__item-main{display:flex;min-width:0;flex:1 1 14rem;flex-direction:column;gap:var(--hm-space-micro);color:var(--hm-text);font-size:var(--hm-font-size-sm);overflow-wrap:anywhere}.sp-account__item-title{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-nano)}.sp-account__item-title strong{font-weight:var(--hm-font-weight-semibold)}.sp-account__meta{color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.sp-account__meta code{font-family:var(--hm-font-mono)}.sp-account__meta--danger{color:var(--hm-danger)}.sp-account__item-actions,.sp-account__actions{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs)}.sp-account__item-actions{margin-inline-start:auto}.sp-account__list-footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--hm-space-xs) var(--hm-space-sm);padding:var(--hm-space-xs) var(--hm-space-sm);border-top:var(--hm-border-hairline) solid var(--hm-divider);background:var(--hm-surface-raised)}.sp-account__list-footer:first-child{border-top:0}.sp-account__panel{display:flex;flex-direction:column;gap:var(--hm-space-sm);min-width:0;padding:var(--hm-space-sm) var(--hm-space-md) var(--hm-space-md);border:var(--hm-border-hairline) solid var(--hm-border);border-inline-start:var(--hm-border-thin) solid var(--hm-accent);border-radius:var(--hm-radius);background:var(--hm-surface-raised)}.sp-account__panel--success{border-color:var(--hm-success);background:var(--hm-success-bg)}.sp-account__panel--success .sp-account__panel-head hm-icon{color:var(--hm-success)}.sp-account__panel--danger{border-inline-start-color:var(--hm-danger)}.sp-account__panel--danger .sp-account__panel-head hm-icon{color:var(--hm-danger)}.sp-account__panel-head{display:flex;align-items:flex-start;gap:var(--hm-space-xs)}.sp-account__panel-head hm-icon{flex:none;margin-block-start:var(--hm-space-micro);color:var(--hm-accent-strong)}.sp-account__panel-text{display:flex;min-width:0;flex-direction:column;gap:var(--hm-space-micro)}.sp-account__title{margin:0;color:var(--hm-text);font-size:var(--hm-font-size-sm);font-weight:var(--hm-font-weight-semibold)}.sp-account__form,.sp-account__code,.sp-account__field{display:flex;flex-direction:column;gap:var(--hm-space-xs);min-width:0}.sp-account__form{gap:var(--hm-space-sm)}.sp-account__label{color:var(--hm-text);font-size:var(--hm-font-size-sm);font-weight:var(--hm-font-weight-semibold)}.sp-account__qr{align-self:flex-start;padding:var(--hm-space-xxxs);border-radius:var(--hm-radius-control);background:var(--hm-surface)}.sp-account__qr img{display:block;width:10rem;max-width:100%;height:auto}.sp-account__secret,.sp-account__codes code{font-family:var(--hm-font-mono);overflow-wrap:anywhere}.sp-account__secret{-webkit-user-select:all;user-select:all}.sp-account__secret--block{display:block;padding:var(--hm-space-xs) var(--hm-space-xxxs);border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius-control);background:var(--hm-surface);color:var(--hm-text);font-size:var(--hm-font-size-xs)}.sp-account__codes{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(9rem,100%),1fr));gap:var(--hm-space-nano) var(--hm-space-sm);margin:0;padding:var(--hm-space-xxxs) var(--hm-space-xs) var(--hm-space-xxxs) var(--hm-space-md);border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius-control);background:var(--hm-surface);color:var(--hm-text);font-size:var(--hm-font-size-sm)}@media(forced-colors:active){.sp-account__panel{border-inline-start-color:Highlight}.sp-account__icon{border:var(--hm-border-hairline) solid CanvasText}}.sp-account__toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs)}.sp-account__choices{display:flex;flex-direction:column;gap:var(--hm-space-xs);min-width:0;margin:0;padding:0;border:0}\n", "@charset \"UTF-8\";.sp-group__avatar{flex:none}.sp-group__role{min-width:10rem}.sp-group__filter{display:block;margin-block:var(--hm-space-sm)}.sp-group__status{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs);margin-block-end:var(--hm-space-sm)}.sp-group__results{max-height:16rem;overflow-y:auto}.sp-group__results li+li{border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-group__result{display:flex;flex-direction:column;align-items:flex-start;gap:var(--hm-space-micro);width:100%;min-width:0;padding:var(--hm-space-xs) var(--hm-space-sm);border:0;background:transparent;color:var(--hm-text);font:inherit;font-size:var(--hm-font-size-sm);text-align:start;overflow-wrap:anywhere;cursor:pointer}.sp-group__result:hover:not(:disabled){background:var(--hm-hover)}.sp-group__result:focus-visible{outline:var(--hm-border-thin) solid var(--hm-accent);outline-offset:calc(var(--hm-border-thin) * -1)}.sp-group__result--selected{background:var(--hm-accent-subtle)}.sp-group__result:disabled{color:var(--hm-muted);cursor:default}.sp-groups__item{display:flex;align-items:center;gap:var(--hm-space-xs) var(--hm-space-sm);width:100%;min-width:0;padding:var(--hm-space-sm);border:0;background:transparent;color:var(--hm-text);font:inherit;font-size:var(--hm-font-size-sm);text-align:start;cursor:pointer}li+li .sp-groups__item{border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-groups__item:hover{background:var(--hm-hover)}.sp-groups__item:focus-visible{outline:var(--hm-border-thin) solid var(--hm-accent);outline-offset:calc(var(--hm-border-thin) * -1)}.sp-groups__faces{flex:none;margin-inline-start:auto}.sp-groups__chevron{flex:none;color:var(--hm-muted)}.sp-groups__back{display:flex}.sp-groups__heading{margin-block-end:var(--hm-space-xxxs)}@media(forced-colors:active){.sp-group__result--selected{outline:var(--hm-border-thin) solid Highlight;outline-offset:calc(var(--hm-border-thin) * -1)}}\n"] }]
|
|
5738
5972
|
}], ctorParameters: () => [], propDecorators: { groups: [{ type: i0.Input, args: [{ isSignal: true, alias: "groups", required: true }] }], openChange: [{ type: i0.Output, args: ["openChange"] }] } });
|
|
5739
5973
|
|
|
5740
5974
|
/**
|
|
@@ -6134,8 +6368,8 @@ class SettingsPanelComponent {
|
|
|
6134
6368
|
}
|
|
6135
6369
|
/**
|
|
6136
6370
|
* Restaurar preferências (com confirmação): tema (sistema), cor principal (a padrão do app), densidade
|
|
6137
|
-
* (confortável), fonte (a padrão do app), menu lateral (o modo padrão do app),
|
|
6138
|
-
* animações (sistema), formato de hora e primeiro dia da semana (automáticos). Idioma, fuso horário e
|
|
6371
|
+
* (confortável), fonte (a padrão do app), menu lateral (o modo padrão do app), dividir abas (desligado), tamanho do
|
|
6372
|
+
* texto (100%), animações (sistema), formato de hora e primeiro dia da semana (automáticos). Idioma, fuso horário e
|
|
6139
6373
|
* atalhos de tecla única ficam: mudam como a pessoa lê e digita, e não são "aparência".
|
|
6140
6374
|
*/
|
|
6141
6375
|
restorePreferences() {
|
|
@@ -6158,6 +6392,7 @@ class SettingsPanelComponent {
|
|
|
6158
6392
|
if (font)
|
|
6159
6393
|
this.hermesTheme.setFont(font);
|
|
6160
6394
|
this.sidebar.setMode(this.sidebarConfig.defaultMode ?? 'auto');
|
|
6395
|
+
this.preferences.setSplitTabs(false);
|
|
6161
6396
|
this.preferences.setTextScale(1);
|
|
6162
6397
|
this.preferences.setMotion('system');
|
|
6163
6398
|
this.preferences.setHourCycle('');
|
|
@@ -6273,7 +6508,7 @@ class SettingsPanelComponent {
|
|
|
6273
6508
|
this.settings.close();
|
|
6274
6509
|
}
|
|
6275
6510
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: SettingsPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6276
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: SettingsPanelComponent, isStandalone: true, selector: "spine-settings-panel", ngImport: i0, template: "<!-- Montado s\u00F3 enquanto aberto: nada disto (lista de fusos, leitura do token...) custa no\n carregamento de toda p\u00E1gina. -->\n@if (settings.isOpen()) {\n <hm-settings-dialog\n [heading]=\"text.heading\"\n [open]=\"true\"\n (openChange)=\"onOpenChange($event)\"\n [activeSection]=\"activeSection()\"\n (activeSectionChange)=\"settings.section.set($event)\"\n >\n <!-- \u2500\u2500 Conta \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <hm-settings-section [key]=\"keys.account\" [label]=\"text.account\" icon=\"user\" [keywords]=\"text.accountKeywords\">\n <div class=\"sp-settings__profile\">\n <hm-account-avatar [name]=\"profile.name ?? text.user\" [imageUrl]=\"profile.picture\" />\n <span class=\"sp-settings__profile-text\">\n <strong>{{ profile.name ?? text.user }}</strong>\n @if (profile.role) { <span>{{ profile.role }}</span> }\n </span>\n </div>\n\n <!-- S\u00F3 informativo: a troca de n\u00EDvel fica no menu do perfil, perto de onde se trabalha. -->\n @if (badge) {\n <hm-settings-row [label]=\"text.accessLevel\" [keywords]=\"text.accessLevelKeywords\">\n <span class=\"sp-settings__value\">{{ badge.name }}</span>\n </hm-settings-row>\n }\n\n <hm-settings-row [label]=\"text.session\" [description]=\"text.sessionDescription\" [keywords]=\"text.sessionKeywords\">\n <span class=\"sp-settings__value\">{{ sessionExpiry }}</span>\n </hm-settings-row>\n\n <!-- Recursos opcionais (SpineConfig.features): crach\u00E1 padr\u00E3o (Argos), inatividade e tela inicial. -->\n @if (showDefaultBadge) {\n <hm-settings-row [label]=\"featureText.defaultBadge\" [description]=\"featureText.defaultBadgeDescription\" [keywords]=\"featureText.defaultBadgeKeywords\">\n <spine-default-badge />\n </hm-settings-row>\n }\n\n @if (idleOptions().length) {\n <hm-settings-row [label]=\"featureText.idle\" [description]=\"idleHint || featureText.idleDescription\" [keywords]=\"featureText.idleKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"featureText.idle\" [options]=\"idleOptions()\" [value]=\"idleValue()\" (valueChange)=\"setIdle($event)\" />\n </hm-settings-row>\n }\n\n @if (features.startPage) {\n <hm-settings-row [label]=\"featureText.startPage\" [description]=\"quickAccessHasFavorites() ? featureText.startPageDescription : featureText.startPageHint\" [keywords]=\"featureText.startPageKeywords\">\n <hm-select class=\"sp-settings__language\" [label]=\"featureText.startPage\" [labelHidden]=\"true\" [value]=\"startPageValue()\" (valueChange)=\"setStartPage($event ?? 'home')\">\n @for (option of startPageOptions(); track option.value) {\n <option [value]=\"option.value\">{{ option.label }}</option>\n }\n </hm-select>\n </hm-settings-row>\n }\n\n <hm-settings-row [label]=\"text.logout\" [description]=\"text.logoutDescription\" [keywords]=\"text.logoutKeywords\">\n <hm-button emphasis=\"medium\" intent=\"danger\" icon=\"logout\" [loading]=\"logoutPending()\" (clicked)=\"logout()\">{{ text.logout }}</hm-button>\n </hm-settings-row>\n </hm-settings-section>\n\n <!-- \u2500\u2500 MFA \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- API da conta do Argos com o token da sess\u00E3o (Bearer): MFA e c\u00F3digos de recupera\u00E7\u00E3o aqui mesmo, sem\n abrir o Argos. O spineAccountSecurity d\u00E1 \u00E0s linhas o mesmo estado (reautentica\u00E7\u00E3o, cadastro em\n andamento), que morre quando o painel fecha. `?settings=seguranca` (chave antiga) abre esta se\u00E7\u00E3o. -->\n @if (accountSecurity) {\n <hm-settings-section spineAccountSecurity [key]=\"keys.mfa\" [label]=\"text.mfa\" icon=\"shield-check\" [description]=\"text.mfaDescription\" [keywords]=\"text.mfaKeywords\">\n <!-- Realm s\u00F3 pelo nome: o id (UUID) n\u00E3o diz nada a quem l\u00EA, ent\u00E3o some. -->\n @if (accountLogin || accountRealm) {\n <hm-settings-row [label]=\"text.signedInAccount\" [description]=\"accountRealm ? fmt(text.signedInRealm, { realm: accountRealm }) : ''\">\n <span class=\"sp-settings__value\">{{ profile.name ?? text.user }}@if (accountLogin) { <span class=\"sp-settings__muted\"> \u00B7 {{ accountLogin }}</span> }</span>\n </hm-settings-row>\n }\n\n <hm-settings-row [label]=\"text.twoFactor\" [description]=\"text.twoFactorDescription\" [keywords]=\"text.twoFactorKeywords\" [stacked]=\"true\">\n <spine-account-mfa />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.recoveryCodes\" [description]=\"text.recoveryCodesDescription\" [keywords]=\"text.recoveryCodesKeywords\" [stacked]=\"true\">\n <spine-account-recovery-codes />\n </hm-settings-row>\n\n <!-- Entradas e tentativas desta conta (SpineFeatures.accountActivity), \u00FAltimos 90 dias. -->\n @if (features.accountActivity) {\n <hm-settings-row [label]=\"featureText.activity\" [description]=\"featureText.activityDescription\" [keywords]=\"featureText.activityKeywords\" [stacked]=\"true\">\n <spine-account-activity />\n </hm-settings-row>\n }\n </hm-settings-section>\n }\n\n <!-- \u2500\u2500 Sess\u00F5es \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- Os tokens e onde a conta est\u00E1 conectada (a validade desta sess\u00E3o fica em Conta). Cada linha tem a\n pr\u00F3pria condi\u00E7\u00E3o; a se\u00E7\u00E3o some se nenhuma sobrar (hasSessionsSection). -->\n @if (hasSessionsSection) {\n <hm-settings-section [key]=\"keys.sessions\" [label]=\"text.sessionsSection\" icon=\"devices\" [description]=\"text.sessionsSectionDescription\" [keywords]=\"text.sessionsSectionKeywords\">\n <!-- S\u00F3 com SpineConfig.technicalDocs (padr\u00E3o: isDevMode()): token da sess\u00E3o no clipboard \u00E9 ferramenta de dev. -->\n @if (sessionsItems.accessToken) {\n <hm-settings-row [label]=\"text.accessToken\" [description]=\"text.accessTokenDescription\" [keywords]=\"text.accessTokenKeywords\">\n <hm-button emphasis=\"medium\" icon=\"copy\" (clicked)=\"copyToken()\">{{ text.copy }}</hm-button>\n </hm-settings-row>\n }\n\n @if (sessionsItems.appTokens) {\n <hm-settings-row [label]=\"text.appTokens\" [stacked]=\"true\"\n [description]=\"text.appTokensDescription\"\n [keywords]=\"text.appTokensKeywords\">\n <hm-toggletip rowHelp [label]=\"fmt(text.moreAbout, { label: text.appTokens })\" [text]=\"text.appTokensHelp\" />\n <spine-app-tokens />\n </hm-settings-row>\n }\n\n <!-- Token + .mcp.json prontos para um agente de IA (SpineFeatures.aiAgent). -->\n @if (sessionsItems.aiAgent) {\n <hm-settings-row [label]=\"featureText.aiAgent\" [description]=\"featureText.aiAgentDescription\" [keywords]=\"featureText.aiAgentKeywords\" [stacked]=\"true\">\n <hm-toggletip rowHelp [label]=\"fmt(text.moreAbout, { label: featureText.aiAgent })\" [text]=\"featureText.aiAgentHelp\" />\n <spine-ai-agent />\n </hm-settings-row>\n }\n\n <!-- Sess\u00F5es e dispositivos: API da conta do Argos, mesma condi\u00E7\u00E3o da se\u00E7\u00E3o MFA. -->\n @if (sessionsItems.devices) {\n <hm-settings-row [label]=\"text.sessions\" [description]=\"text.sessionsDescription\" [keywords]=\"text.sessionsKeywords\" [stacked]=\"true\">\n <spine-account-sessions />\n </hm-settings-row>\n }\n </hm-settings-section>\n }\n\n <!-- \u2500\u2500 Grupos \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- Os grupos desta aplica\u00E7\u00E3o de que a pessoa \u00E9 membro (argos-admin /me/groups, relidos a cada abertura): a lista,\n e escolhendo um, a tela de membros dele. Sem grupo nenhum, a se\u00E7\u00E3o n\u00E3o aparece. -->\n @if (myGroups().length) {\n <hm-settings-section [key]=\"keys.groups\" [label]=\"text.groups\" icon=\"employee-group\" [keywords]=\"text.groupsKeywords\"\n [class.sp-settings__section--group-open]=\"groupOpen()\" [description]=\"groupOpen() ? '' : text.groupsDescription\">\n <spine-my-groups [groups]=\"myGroups()\" (openChange)=\"groupOpen.set($event)\" />\n </hm-settings-section>\n }\n\n <!-- \u2500\u2500 Apar\u00EAncia \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <hm-settings-section [key]=\"keys.appearance\" [label]=\"text.appearance\" icon=\"color-palette\" [keywords]=\"text.appearanceKeywords\">\n <hm-settings-row [label]=\"text.theme\" [description]=\"text.themeDescription\" [keywords]=\"text.themeKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.theme\" [options]=\"themeOptions()\" [value]=\"themeMode()\" (valueChange)=\"setThemeMode($event)\" />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.accent\" [description]=\"text.accentDescription\" [keywords]=\"text.accentKeywords\" [stacked]=\"true\">\n <hm-theme-picker\n class=\"sp-settings__picker\"\n [families]=\"families\"\n [family]=\"family()\"\n [theme]=\"appliedTheme()\"\n [showMode]=\"false\"\n (familyChosen)=\"setFamily($event)\"\n />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.density\" [description]=\"text.densityDescription\" [keywords]=\"text.densityKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.density\" [options]=\"densityOptions()\" [value]=\"densityValue()\" (valueChange)=\"setDensity($event)\" />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.font\" [description]=\"text.fontDescription\" [keywords]=\"text.fontKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.font\" [options]=\"fontOptions\" [value]=\"fontValue()\" (valueChange)=\"setFont($event)\" />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.sidebar\" [description]=\"text.sidebarDescription\" [keywords]=\"text.sidebarKeywords\">\n <hm-toggletip rowHelp [label]=\"fmt(text.moreAbout, { label: text.sidebar })\" [text]=\"text.sidebarHelp\" />\n <hm-segmented-control emphasis=\"action\" [label]=\"text.sidebar\" [options]=\"sidebarOptions()\" [value]=\"sidebar.mode()\" (valueChange)=\"setSidebarMode($event)\" />\n </hm-settings-row>\n </hm-settings-section>\n\n <!-- \u2500\u2500 Acessibilidade \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- Tamanho do texto (--hm-text-scale no <html>, HermesZoomService) e movimento (data-motion no <html>,\n HermesMotionService), guardados pelo SpinePreferencesService. -->\n <hm-settings-section [key]=\"keys.accessibility\" [label]=\"text.accessibility\" icon=\"accessibility-1\" [keywords]=\"text.accessibilityKeywords\">\n <hm-settings-row [label]=\"text.textSize\" [description]=\"text.textSizeDescription\" [keywords]=\"text.textSizeKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.textSize\" [options]=\"textSizeOptions()\" [value]=\"textSizeValue()\" (valueChange)=\"setTextSize($event)\" />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.motion\" [description]=\"text.motionDescription\" [keywords]=\"text.motionKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.motion\" [options]=\"motionOptions()\" [value]=\"preferences.motion()\" (valueChange)=\"setMotion($event)\" />\n </hm-settings-row>\n </hm-settings-section>\n\n <!-- \u2500\u2500 Regi\u00E3o \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <hm-settings-section [key]=\"keys.region\" [label]=\"text.region\" icon=\"clock\" [keywords]=\"text.regionKeywords\">\n <hm-settings-row [label]=\"text.language\" [description]=\"text.languageDescription\" [keywords]=\"text.languageKeywords\">\n <hm-select\n class=\"sp-settings__language\"\n [label]=\"text.language\"\n [labelHidden]=\"true\"\n [value]=\"preferences.language()\"\n (valueChange)=\"preferences.setLanguage($event ?? '')\"\n >\n @for (option of languageOptions(); track option.value) {\n <option [value]=\"option.value\" [attr.lang]=\"option.value || null\">{{ option.label }}</option>\n }\n </hm-select>\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.timeZone\" [description]=\"fmt(text.timeZoneHint, { now: timeZonePreview() })\" [keywords]=\"text.timeZoneKeywords\">\n <hm-combobox\n class=\"sp-settings__timezone\"\n [label]=\"text.timeZone\"\n [labelHidden]=\"true\"\n icon=\"world\"\n [options]=\"timeZoneOptions()\"\n [value]=\"preferences.timeZone()\"\n (valueChange)=\"preferences.setTimeZone($event)\"\n />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.hourCycle\" [description]=\"fmt(text.hourCycleHint, { now: hourCyclePreview() })\" [keywords]=\"text.hourCycleKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.hourCycle\" [options]=\"hourCycleOptions()\" [value]=\"preferences.hourCycle()\" (valueChange)=\"setHourCycle($event)\" />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.weekStart\" [description]=\"text.weekStartDescription\" [keywords]=\"text.weekStartKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.weekStart\" [options]=\"weekStartOptions()\" [value]=\"weekStartValue()\" (valueChange)=\"setWeekStart($event)\" />\n </hm-settings-row>\n </hm-settings-section>\n\n <!-- \u2500\u2500 Notifica\u00E7\u00F5es (SpineFeatures.notices) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- Os tipos de aviso que o app declarou (SpineNoticesService) e o aviso do navegador com a aba em segundo plano. -->\n @if (notices.enabled) {\n <hm-settings-section [key]=\"keys.notices\" [label]=\"featureText.notices\" icon=\"bell\" [description]=\"featureText.noticesDescription\" [keywords]=\"featureText.noticesKeywords\">\n @for (type of notices.types; track type.id) {\n <hm-settings-row [label]=\"type.label\" [description]=\"type.description ?? ''\">\n <hm-checkbox [label]=\"type.label\" [labelHidden]=\"true\" [checked]=\"notices.isEnabled(type.id)\" (checkedChange)=\"notices.setEnabled(type.id, $event)\" />\n </hm-settings-row>\n }\n <hm-settings-row [label]=\"featureText.browserNotices\" [description]=\"notices.permission() === 'denied' ? featureText.browserNoticesDenied : notices.permission() === 'unsupported' ? featureText.browserNoticesUnsupported : featureText.browserNoticesDescription\">\n <hm-checkbox [label]=\"featureText.browserNotices\" [labelHidden]=\"true\" [checked]=\"notices.browserActive()\" (checkedChange)=\"setBrowserNotices($event)\" />\n </hm-settings-row>\n </hm-settings-section>\n }\n\n <!-- \u2500\u2500 Atalhos \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <hm-settings-section [key]=\"keys.shortcuts\" [label]=\"text.shortcuts\" icon=\"keyboard\" [description]=\"text.shortcutsDescription\" [keywords]=\"text.shortcutsKeywords\">\n <!-- Mesma lista do painel \"?\", sem busca (a do di\u00E1logo de configura\u00E7\u00F5es j\u00E1 cobre a se\u00E7\u00E3o);\n o interruptor de tecla \u00FAnica (WCAG 2.1.4) persiste no SpinePreferencesService. -->\n <hm-shortcut-list class=\"sp-settings__shortcuts\" characterKeysToggle [registered]=\"false\" [items]=\"shortcutItems()\" [headingLevel]=\"4\" />\n </hm-settings-section>\n\n <!-- \u2500\u2500 Dados do navegador \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- Listas por usu\u00E1rio do SpineUserStorage e as prefer\u00EAncias deste painel. Destrutivo: o 1\u00BA clique pede\n confirma\u00E7\u00E3o (bot\u00E3o vira \"Confirmar\" + Cancelar), como nas listas de tokens e sess\u00F5es. -->\n <hm-settings-section [key]=\"keys.data\" [label]=\"text.browserData\" icon=\"browser-setting\" [description]=\"text.browserDataDescription\" [keywords]=\"text.browserDataKeywords\">\n <!-- SpineFeatures.accountPreferences: as prefer\u00EAncias tamb\u00E9m na conta do Argos (as telas acima n\u00E3o mudam). -->\n @if (features.accountPreferences) {\n <hm-settings-row [label]=\"featureText.sync\" [description]=\"syncStatus() || featureText.syncDescription\" [keywords]=\"featureText.syncKeywords\">\n <hm-toggletip rowHelp [label]=\"fmt(text.moreAbout, { label: featureText.sync })\" [text]=\"featureText.syncDescription\" />\n <hm-button emphasis=\"medium\" icon=\"refresh\" [disabled]=\"accountPreferences.status() === 'local'\" [loading]=\"accountPreferences.status() === 'saving' || accountPreferences.status() === 'loading'\" (clicked)=\"syncNow()\">{{ featureText.syncNow }}</hm-button>\n </hm-settings-row>\n }\n @for (list of browserLists(); track list.id) {\n <hm-settings-row [label]=\"list.label\" [description]=\"list.count\" [keywords]=\"list.keywords\">\n <span class=\"sp-settings__actions\">\n @if (confirming() === list.id) {\n <hm-button emphasis=\"medium\" (clicked)=\"cancelConfirm()\">{{ text.cancel }}</hm-button>\n }\n <hm-button\n [emphasis]=\"confirming() === list.id ? 'high' : 'medium'\"\n intent=\"danger\"\n [disabled]=\"list.empty && confirming() !== list.id\"\n (clicked)=\"clearList(list.id)\"\n >{{ confirming() === list.id ? text.confirmClear : text.clear }}</hm-button>\n </span>\n </hm-settings-row>\n }\n\n <hm-settings-row [label]=\"text.restorePreferences\" [description]=\"text.restorePreferencesDescription\" [keywords]=\"text.restorePreferencesKeywords\">\n <hm-toggletip rowHelp [label]=\"fmt(text.moreAbout, { label: text.restorePreferences })\" [text]=\"text.restorePreferencesHelp\" />\n <span class=\"sp-settings__actions\">\n @if (confirming() === 'preferences') {\n <hm-button emphasis=\"medium\" (clicked)=\"cancelConfirm()\">{{ text.cancel }}</hm-button>\n }\n <hm-button [emphasis]=\"confirming() === 'preferences' ? 'high' : 'medium'\" intent=\"danger\" (clicked)=\"restorePreferences()\">\n {{ confirming() === 'preferences' ? text.confirmRestore : text.restore }}\n </hm-button>\n </span>\n </hm-settings-row>\n </hm-settings-section>\n\n <!-- \u2500\u2500 Ajuda \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- Novidades (s\u00F3 com alguma vigente), configura\u00E7\u00E3o inicial e o essencial: fecham o painel antes de abrir. -->\n <hm-settings-section [key]=\"keys.help\" [label]=\"text.help\" icon=\"help\" [keywords]=\"text.helpKeywords\">\n @if (hasNews()) {\n <hm-settings-row [label]=\"text.news\" [description]=\"text.newsDescription\" [keywords]=\"text.newsKeywords\">\n <hm-button emphasis=\"medium\" icon=\"star\" (clicked)=\"showNews()\">{{ text.showNews }}</hm-button>\n </hm-settings-row>\n }\n @if (setupEnabled) {\n <hm-settings-row [label]=\"text.setup\" [description]=\"text.setupDescription\" [keywords]=\"text.setupKeywords\">\n <hm-button emphasis=\"medium\" icon=\"color-palette\" (clicked)=\"redoSetup()\">{{ text.redoSetup }}</hm-button>\n </hm-settings-row>\n }\n <hm-settings-row [label]=\"text.essentials\" [description]=\"text.essentialsDescription\" [keywords]=\"text.essentialsKeywords\">\n <hm-button emphasis=\"medium\" icon=\"help\" (clicked)=\"showEssentials()\">{{ text.showEssentials }}</hm-button>\n </hm-settings-row>\n </hm-settings-section>\n\n <!-- \u2500\u2500 Se\u00E7\u00F5es do app (provideSettingsSection) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @for (s of appSections; track s.key) {\n <hm-settings-section [key]=\"s.key\" [label]=\"s.label\" [icon]=\"s.icon ?? 'cog'\" [description]=\"s.description ?? ''\" [keywords]=\"s.keywords ?? ''\">\n <ng-container *ngComponentOutlet=\"s.component\" />\n </hm-settings-section>\n }\n\n <!-- \u2500\u2500 Sobre \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <hm-settings-section [key]=\"keys.about\" [label]=\"text.about\" icon=\"info-circle\" [keywords]=\"text.aboutKeywords\">\n <hm-settings-row [label]=\"text.application\">\n <span class=\"sp-settings__value\">{{ appName }}@if (packageInfo.name) { <span class=\"sp-settings__muted\"> \u00B7 {{ packageInfo.name }}</span> }</span>\n </hm-settings-row>\n <!-- M\u00E9dia da ferramenta (SpineFeatures.ratings) e \"Avaliar\", que abre o di\u00E1logo da estrela do cabe\u00E7alho. -->\n @if (ratingsEnabled) {\n <hm-settings-row [label]=\"ratingText.aboutRating\" [keywords]=\"ratingText.aboutRatingKeywords\">\n <spine-app-rating-summary />\n </hm-settings-row>\n }\n <hm-settings-row [label]=\"text.version\" [keywords]=\"text.versionKeywords\">\n <span class=\"sp-settings__value sp-settings__mono\">{{ packageInfo.version ?? '\u2014' }}</span>\n </hm-settings-row>\n @if (buildDate) {\n <hm-settings-row [label]=\"text.buildDate\">\n <span class=\"sp-settings__value\">{{ buildDate }}</span>\n </hm-settings-row>\n }\n @if (packageInfo.environment) {\n <hm-settings-row [label]=\"text.environment\" [keywords]=\"text.environmentKeywords\">\n <span class=\"sp-settings__value\">{{ packageInfo.environment }}</span>\n </hm-settings-row>\n }\n @if (packageInfo.repository?.url || packageInfo.docs || packageInfo.issues) {\n <hm-settings-row [label]=\"text.links\" [keywords]=\"text.linksKeywords\">\n <span class=\"sp-settings__links\">\n @if (packageInfo.docs) { <hm-button emphasis=\"medium\" icon=\"book\" [link]=\"packageInfo.docs\" [newTab]=\"true\">{{ text.docs }}</hm-button> }\n @if (packageInfo.issues) { <hm-button emphasis=\"medium\" icon=\"bug\" [link]=\"packageInfo.issues\" [newTab]=\"true\">{{ text.reportIssue }}</hm-button> }\n @if (packageInfo.repository?.url) { <hm-button emphasis=\"medium\" icon=\"link\" [link]=\"packageInfo.repository!.url!\" [newTab]=\"true\">{{ text.repository }}</hm-button> }\n </span>\n </hm-settings-row>\n }\n @if (dependencies.length) {\n <hm-settings-row [label]=\"text.dependencies\" [description]=\"text.dependenciesDescription\" [keywords]=\"text.dependenciesKeywords\" [stacked]=\"true\">\n <dl class=\"sp-settings__deps\">\n @for (d of dependencies; track d.name) {\n <div><dt>{{ d.label }}</dt><dd class=\"sp-settings__mono\">{{ d.version }}</dd></div>\n }\n </dl>\n </hm-settings-row>\n }\n <hm-settings-row [label]=\"text.supportInfo\" [description]=\"text.supportInfoDescription\" [keywords]=\"text.supportInfoKeywords\">\n <hm-button emphasis=\"medium\" icon=\"clipboard\" (clicked)=\"copySupportInfo()\">{{ text.copy }}</hm-button>\n </hm-settings-row>\n </hm-settings-section>\n </hm-settings-dialog>\n}\n", styles: ["@charset \"UTF-8\";.sp-settings__timezone{display:block;width:min(320px,100%)}.sp-settings__profile{display:flex;align-items:center;gap:var(--hm-space-sm);padding:var(--hm-space-xs) 0 var(--hm-space-sm)}.sp-settings__profile-text{display:flex;min-width:0;flex-direction:column;gap:var(--hm-space-micro);color:var(--hm-text);overflow-wrap:anywhere}.sp-settings__profile-text span{color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.sp-settings__value{color:var(--hm-text);font-size:var(--hm-font-size-sm);text-align:end;overflow-wrap:anywhere}.sp-settings__muted{color:var(--hm-muted)}.sp-settings__mono{font-family:var(--hm-font-mono)}.sp-settings__shortcuts{display:block;padding-block:var(--hm-space-xxxs);border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-settings__links,.sp-settings__actions{display:inline-flex;flex-wrap:wrap;justify-content:flex-end;gap:var(--hm-space-xs)}.sp-settings__section--group-open ::ng-deep .hm-settings-section__heading{position:absolute;inline-size:1px;block-size:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.sp-settings__picker ::ng-deep .hm-theme-picker__title{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.sp-settings__deps{display:grid;flex:1;min-width:0;grid-template-columns:repeat(auto-fill,minmax(min(12rem,100%),1fr));margin:0;overflow:hidden;border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius);background:var(--hm-surface)}.sp-settings__deps div{display:flex;justify-content:space-between;gap:var(--hm-space-xs);margin-block-start:calc(-1 * var(--hm-border-hairline));margin-inline-start:calc(-1 * var(--hm-border-hairline));padding:var(--hm-space-xs) var(--hm-space-sm);border-top:var(--hm-border-hairline) solid var(--hm-divider);border-inline-start:var(--hm-border-hairline) solid var(--hm-divider)}.sp-settings__deps dt{color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.sp-settings__deps dd{margin:0;color:var(--hm-text);font-size:var(--hm-font-size-xs)}\n"], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: AppTokensComponent, selector: "spine-app-tokens" }, { kind: "component", type: MyGroupsComponent, selector: "spine-my-groups", inputs: ["groups"], outputs: ["openChange"] }, { kind: "component", type: AiAgentComponent, selector: "spine-ai-agent" }, { kind: "component", type: AccountActivityComponent, selector: "spine-account-activity" }, { kind: "component", type: DefaultBadgeComponent, selector: "spine-default-badge" }, { kind: "component", type: CheckboxComponent, selector: "hm-checkbox", inputs: ["label", "labelHidden", "checked", "indeterminate"], outputs: ["checkedChange"] }, { kind: "component", type: AccountMfaComponent, selector: "spine-account-mfa" }, { kind: "component", type: AccountRecoveryCodesComponent, selector: "spine-account-recovery-codes" }, { kind: "component", type: AccountSessionsComponent, selector: "spine-account-sessions" }, { kind: "directive", type: SpineAccountSecurityScopeDirective, selector: "[spineAccountSecurity]" }, { kind: "component", type: AccountAvatarComponent, selector: "hm-account-avatar", inputs: ["name", "imageUrl", "size", "loading"] }, { kind: "component", type: ButtonComponent, selector: "hm-button", inputs: ["emphasis", "intent", "size", "type", "icon", "iconDirection", "iconEnd", "disabled", "loading", "loadingState", "block", "link", "newTab", "caret", "inMenu", "toggle", "pressed"], outputs: ["loadingStateChange", "pressedChange", "clicked"] }, { kind: "component", type: ComboboxComponent, selector: "hm-combobox", inputs: ["label", "options", "value", "placeholder", "icon", "hint", "size", "labelHidden", "clearable", "loading", "allowCustomValue"], outputs: ["valueChange"] }, { kind: "component", type: SegmentedControlComponent, selector: "hm-segmented-control", inputs: ["options", "value", "label", "size", "emphasis"], outputs: ["valueChange"] }, { kind: "component", type: SettingsDialogComponent, selector: "hm-settings-dialog", inputs: ["open", "heading", "activeSection", "closeHandler", "actions", "submitLabel", "cancelLabel"], outputs: ["openChange", "activeSectionChange", "closed", "submitted"] }, { kind: "component", type: SettingsRowComponent, selector: "hm-settings-row", inputs: ["label", "description", "keywords", "stacked"] }, { kind: "component", type: SettingsSectionComponent, selector: "hm-settings-section", inputs: ["key", "label", "icon", "description", "keywords", "control", "invalid"] }, { kind: "component", type: SelectComponent, selector: "hm-select", inputs: ["value", "label", "labelHidden", "hint"], outputs: ["valueChange"] }, { kind: "component", type: ShortcutListComponent, selector: "hm-shortcut-list", inputs: ["items", "registered", "searchable", "characterKeysToggle", "headingLevel"] }, { kind: "component", type: ThemePickerComponent, selector: "hm-theme-picker", inputs: ["families", "family", "theme", "showMode"], outputs: ["familyChosen", "themeChosen"] }, { kind: "component", type: ToggletipComponent, selector: "hm-toggletip", inputs: ["label", "text", "side", "intent", "icon"] }, { kind: "component", type: SpineAppRatingSummaryComponent, selector: "spine-app-rating-summary" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
6511
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: SettingsPanelComponent, isStandalone: true, selector: "spine-settings-panel", ngImport: i0, template: "<!-- Montado s\u00F3 enquanto aberto: nada disto (lista de fusos, leitura do token...) custa no\n carregamento de toda p\u00E1gina. -->\n@if (settings.isOpen()) {\n <hm-settings-dialog\n [heading]=\"text.heading\"\n [open]=\"true\"\n (openChange)=\"onOpenChange($event)\"\n [activeSection]=\"activeSection()\"\n (activeSectionChange)=\"settings.section.set($event)\"\n >\n <!-- \u2500\u2500 Conta \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <hm-settings-section [key]=\"keys.account\" [label]=\"text.account\" icon=\"user\" [keywords]=\"text.accountKeywords\">\n <div class=\"sp-settings__profile\">\n <hm-account-avatar [name]=\"profile.name ?? text.user\" [imageUrl]=\"profile.picture\" />\n <span class=\"sp-settings__profile-text\">\n <strong>{{ profile.name ?? text.user }}</strong>\n @if (profile.role) { <span>{{ profile.role }}</span> }\n </span>\n </div>\n\n <!-- S\u00F3 informativo: a troca de n\u00EDvel fica no menu do perfil, perto de onde se trabalha. -->\n @if (badge) {\n <hm-settings-row [label]=\"text.accessLevel\" [keywords]=\"text.accessLevelKeywords\">\n <span class=\"sp-settings__value\">{{ badge.name }}</span>\n </hm-settings-row>\n }\n\n <hm-settings-row [label]=\"text.session\" [description]=\"text.sessionDescription\" [keywords]=\"text.sessionKeywords\">\n <span class=\"sp-settings__value\">{{ sessionExpiry }}</span>\n </hm-settings-row>\n\n <!-- Recursos opcionais (SpineConfig.features): crach\u00E1 padr\u00E3o (Argos), inatividade e tela inicial. -->\n @if (showDefaultBadge) {\n <hm-settings-row [label]=\"featureText.defaultBadge\" [description]=\"featureText.defaultBadgeDescription\" [keywords]=\"featureText.defaultBadgeKeywords\">\n <spine-default-badge />\n </hm-settings-row>\n }\n\n @if (idleOptions().length) {\n <hm-settings-row [label]=\"featureText.idle\" [description]=\"idleHint || featureText.idleDescription\" [keywords]=\"featureText.idleKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"featureText.idle\" [options]=\"idleOptions()\" [value]=\"idleValue()\" (valueChange)=\"setIdle($event)\" />\n </hm-settings-row>\n }\n\n @if (features.startPage) {\n <hm-settings-row [label]=\"featureText.startPage\" [description]=\"quickAccessHasFavorites() ? featureText.startPageDescription : featureText.startPageHint\" [keywords]=\"featureText.startPageKeywords\">\n <hm-select class=\"sp-settings__language\" [label]=\"featureText.startPage\" [labelHidden]=\"true\" [value]=\"startPageValue()\" (valueChange)=\"setStartPage($event ?? 'home')\">\n @for (option of startPageOptions(); track option.value) {\n <option [value]=\"option.value\">{{ option.label }}</option>\n }\n </hm-select>\n </hm-settings-row>\n }\n\n <hm-settings-row [label]=\"text.logout\" [description]=\"text.logoutDescription\" [keywords]=\"text.logoutKeywords\">\n <hm-button emphasis=\"medium\" intent=\"danger\" icon=\"logout\" [loading]=\"logoutPending()\" (clicked)=\"logout()\">{{ text.logout }}</hm-button>\n </hm-settings-row>\n </hm-settings-section>\n\n <!-- \u2500\u2500 MFA \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- API da conta do Argos com o token da sess\u00E3o (Bearer): MFA e c\u00F3digos de recupera\u00E7\u00E3o aqui mesmo, sem\n abrir o Argos. O spineAccountSecurity d\u00E1 \u00E0s linhas o mesmo estado (reautentica\u00E7\u00E3o, cadastro em\n andamento), que morre quando o painel fecha. `?settings=seguranca` (chave antiga) abre esta se\u00E7\u00E3o. -->\n @if (accountSecurity) {\n <hm-settings-section spineAccountSecurity [key]=\"keys.mfa\" [label]=\"text.mfa\" icon=\"shield-check\" [description]=\"text.mfaDescription\" [keywords]=\"text.mfaKeywords\">\n <!-- Realm s\u00F3 pelo nome: o id (UUID) n\u00E3o diz nada a quem l\u00EA, ent\u00E3o some. -->\n @if (accountLogin || accountRealm) {\n <hm-settings-row [label]=\"text.signedInAccount\" [description]=\"accountRealm ? fmt(text.signedInRealm, { realm: accountRealm }) : ''\">\n <span class=\"sp-settings__value\">{{ profile.name ?? text.user }}@if (accountLogin) { <span class=\"sp-settings__muted\"> \u00B7 {{ accountLogin }}</span> }</span>\n </hm-settings-row>\n }\n\n <hm-settings-row [label]=\"text.twoFactor\" [description]=\"text.twoFactorDescription\" [keywords]=\"text.twoFactorKeywords\" [stacked]=\"true\">\n <spine-account-mfa />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.recoveryCodes\" [description]=\"text.recoveryCodesDescription\" [keywords]=\"text.recoveryCodesKeywords\" [stacked]=\"true\">\n <spine-account-recovery-codes />\n </hm-settings-row>\n\n <!-- Entradas e tentativas desta conta (SpineFeatures.accountActivity), \u00FAltimos 90 dias. -->\n @if (features.accountActivity) {\n <hm-settings-row [label]=\"featureText.activity\" [description]=\"featureText.activityDescription\" [keywords]=\"featureText.activityKeywords\" [stacked]=\"true\">\n <spine-account-activity />\n </hm-settings-row>\n }\n </hm-settings-section>\n }\n\n <!-- \u2500\u2500 Sess\u00F5es \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- Os tokens e onde a conta est\u00E1 conectada (a validade desta sess\u00E3o fica em Conta). Cada linha tem a\n pr\u00F3pria condi\u00E7\u00E3o; a se\u00E7\u00E3o some se nenhuma sobrar (hasSessionsSection). -->\n @if (hasSessionsSection) {\n <hm-settings-section [key]=\"keys.sessions\" [label]=\"text.sessionsSection\" icon=\"devices\" [description]=\"text.sessionsSectionDescription\" [keywords]=\"text.sessionsSectionKeywords\">\n <!-- S\u00F3 com SpineConfig.technicalDocs (padr\u00E3o: isDevMode()): token da sess\u00E3o no clipboard \u00E9 ferramenta de dev. -->\n @if (sessionsItems.accessToken) {\n <hm-settings-row [label]=\"text.accessToken\" [description]=\"text.accessTokenDescription\" [keywords]=\"text.accessTokenKeywords\">\n <hm-button emphasis=\"medium\" icon=\"copy\" (clicked)=\"copyToken()\">{{ text.copy }}</hm-button>\n </hm-settings-row>\n }\n\n @if (sessionsItems.appTokens) {\n <hm-settings-row [label]=\"text.appTokens\" [stacked]=\"true\"\n [description]=\"text.appTokensDescription\"\n [keywords]=\"text.appTokensKeywords\">\n <hm-toggletip rowHelp [label]=\"fmt(text.moreAbout, { label: text.appTokens })\" [text]=\"text.appTokensHelp\" />\n <spine-app-tokens />\n </hm-settings-row>\n }\n\n <!-- Token + .mcp.json prontos para um agente de IA (SpineFeatures.aiAgent). -->\n @if (sessionsItems.aiAgent) {\n <hm-settings-row [label]=\"featureText.aiAgent\" [description]=\"featureText.aiAgentDescription\" [keywords]=\"featureText.aiAgentKeywords\" [stacked]=\"true\">\n <hm-toggletip rowHelp [label]=\"fmt(text.moreAbout, { label: featureText.aiAgent })\" [text]=\"featureText.aiAgentHelp\" />\n <spine-ai-agent />\n </hm-settings-row>\n }\n\n <!-- Sess\u00F5es e dispositivos: API da conta do Argos, mesma condi\u00E7\u00E3o da se\u00E7\u00E3o MFA. -->\n @if (sessionsItems.devices) {\n <hm-settings-row [label]=\"text.sessions\" [description]=\"text.sessionsDescription\" [keywords]=\"text.sessionsKeywords\" [stacked]=\"true\">\n <spine-account-sessions />\n </hm-settings-row>\n }\n </hm-settings-section>\n }\n\n <!-- \u2500\u2500 Grupos \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- Os grupos desta aplica\u00E7\u00E3o de que a pessoa \u00E9 membro (argos-admin /me/groups, relidos a cada abertura): a lista,\n e escolhendo um, a tela de membros dele. Sem grupo nenhum, a se\u00E7\u00E3o n\u00E3o aparece. -->\n @if (myGroups().length) {\n <hm-settings-section [key]=\"keys.groups\" [label]=\"text.groups\" icon=\"employee-group\" [keywords]=\"text.groupsKeywords\"\n [class.sp-settings__section--group-open]=\"groupOpen()\" [description]=\"groupOpen() ? '' : text.groupsDescription\">\n <spine-my-groups [groups]=\"myGroups()\" (openChange)=\"groupOpen.set($event)\" />\n </hm-settings-section>\n }\n\n <!-- \u2500\u2500 Apar\u00EAncia \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <hm-settings-section [key]=\"keys.appearance\" [label]=\"text.appearance\" icon=\"color-palette\" [keywords]=\"text.appearanceKeywords\">\n <hm-settings-row [label]=\"text.theme\" [description]=\"text.themeDescription\" [keywords]=\"text.themeKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.theme\" [options]=\"themeOptions()\" [value]=\"themeMode()\" (valueChange)=\"setThemeMode($event)\" />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.accent\" [description]=\"text.accentDescription\" [keywords]=\"text.accentKeywords\" [stacked]=\"true\">\n <hm-theme-picker\n class=\"sp-settings__picker\"\n [families]=\"families\"\n [family]=\"family()\"\n [theme]=\"appliedTheme()\"\n [showMode]=\"false\"\n (familyChosen)=\"setFamily($event)\"\n />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.density\" [description]=\"text.densityDescription\" [keywords]=\"text.densityKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.density\" [options]=\"densityOptions()\" [value]=\"densityValue()\" (valueChange)=\"setDensity($event)\" />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.font\" [description]=\"text.fontDescription\" [keywords]=\"text.fontKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.font\" [options]=\"fontOptions\" [value]=\"fontValue()\" (valueChange)=\"setFont($event)\" />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.sidebar\" [description]=\"text.sidebarDescription\" [keywords]=\"text.sidebarKeywords\">\n <hm-toggletip rowHelp [label]=\"fmt(text.moreAbout, { label: text.sidebar })\" [text]=\"text.sidebarHelp\" />\n <hm-segmented-control emphasis=\"action\" [label]=\"text.sidebar\" [options]=\"sidebarOptions()\" [value]=\"sidebar.mode()\" (valueChange)=\"setSidebarMode($event)\" />\n </hm-settings-row>\n\n <!-- Dividir abas: com ela desligada (o padr\u00E3o) a \u00E1rea de abas fica num painel s\u00F3 (SpineWorkspaceNavService). -->\n <hm-settings-row [label]=\"text.splitTabs\" [description]=\"text.splitTabsDescription\" [keywords]=\"text.splitTabsKeywords\">\n <hm-checkbox [label]=\"text.splitTabs\" [labelHidden]=\"true\" [checked]=\"preferences.splitTabs()\" (checkedChange)=\"preferences.setSplitTabs($event)\" />\n </hm-settings-row>\n </hm-settings-section>\n\n <!-- \u2500\u2500 Acessibilidade \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- Tamanho do texto (--hm-text-scale no <html>, HermesZoomService) e movimento (data-motion no <html>,\n HermesMotionService), guardados pelo SpinePreferencesService. -->\n <hm-settings-section [key]=\"keys.accessibility\" [label]=\"text.accessibility\" icon=\"accessibility-1\" [keywords]=\"text.accessibilityKeywords\">\n <hm-settings-row [label]=\"text.textSize\" [description]=\"text.textSizeDescription\" [keywords]=\"text.textSizeKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.textSize\" [options]=\"textSizeOptions()\" [value]=\"textSizeValue()\" (valueChange)=\"setTextSize($event)\" />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.motion\" [description]=\"text.motionDescription\" [keywords]=\"text.motionKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.motion\" [options]=\"motionOptions()\" [value]=\"preferences.motion()\" (valueChange)=\"setMotion($event)\" />\n </hm-settings-row>\n </hm-settings-section>\n\n <!-- \u2500\u2500 Regi\u00E3o \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <hm-settings-section [key]=\"keys.region\" [label]=\"text.region\" icon=\"clock\" [keywords]=\"text.regionKeywords\">\n <hm-settings-row [label]=\"text.language\" [description]=\"text.languageDescription\" [keywords]=\"text.languageKeywords\">\n <hm-select\n class=\"sp-settings__language\"\n [label]=\"text.language\"\n [labelHidden]=\"true\"\n [value]=\"preferences.language()\"\n (valueChange)=\"preferences.setLanguage($event ?? '')\"\n >\n @for (option of languageOptions(); track option.value) {\n <option [value]=\"option.value\" [attr.lang]=\"option.value || null\">{{ option.label }}</option>\n }\n </hm-select>\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.timeZone\" [description]=\"fmt(text.timeZoneHint, { now: timeZonePreview() })\" [keywords]=\"text.timeZoneKeywords\">\n <hm-combobox\n class=\"sp-settings__timezone\"\n [label]=\"text.timeZone\"\n [labelHidden]=\"true\"\n icon=\"world\"\n [options]=\"timeZoneOptions()\"\n [value]=\"preferences.timeZone()\"\n (valueChange)=\"preferences.setTimeZone($event)\"\n />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.hourCycle\" [description]=\"fmt(text.hourCycleHint, { now: hourCyclePreview() })\" [keywords]=\"text.hourCycleKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.hourCycle\" [options]=\"hourCycleOptions()\" [value]=\"preferences.hourCycle()\" (valueChange)=\"setHourCycle($event)\" />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.weekStart\" [description]=\"text.weekStartDescription\" [keywords]=\"text.weekStartKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.weekStart\" [options]=\"weekStartOptions()\" [value]=\"weekStartValue()\" (valueChange)=\"setWeekStart($event)\" />\n </hm-settings-row>\n </hm-settings-section>\n\n <!-- \u2500\u2500 Notifica\u00E7\u00F5es (SpineFeatures.notices) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- Os tipos de aviso que o app declarou (SpineNoticesService) e o aviso do navegador com a aba em segundo plano. -->\n @if (notices.enabled) {\n <hm-settings-section [key]=\"keys.notices\" [label]=\"featureText.notices\" icon=\"bell\" [description]=\"featureText.noticesDescription\" [keywords]=\"featureText.noticesKeywords\">\n @for (type of notices.types; track type.id) {\n <hm-settings-row [label]=\"type.label\" [description]=\"type.description ?? ''\">\n <hm-checkbox [label]=\"type.label\" [labelHidden]=\"true\" [checked]=\"notices.isEnabled(type.id)\" (checkedChange)=\"notices.setEnabled(type.id, $event)\" />\n </hm-settings-row>\n }\n <hm-settings-row [label]=\"featureText.browserNotices\" [description]=\"notices.permission() === 'denied' ? featureText.browserNoticesDenied : notices.permission() === 'unsupported' ? featureText.browserNoticesUnsupported : featureText.browserNoticesDescription\">\n <hm-checkbox [label]=\"featureText.browserNotices\" [labelHidden]=\"true\" [checked]=\"notices.browserActive()\" (checkedChange)=\"setBrowserNotices($event)\" />\n </hm-settings-row>\n </hm-settings-section>\n }\n\n <!-- \u2500\u2500 Atalhos \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <hm-settings-section [key]=\"keys.shortcuts\" [label]=\"text.shortcuts\" icon=\"keyboard\" [description]=\"text.shortcutsDescription\" [keywords]=\"text.shortcutsKeywords\">\n <!-- Mesma lista do painel \"?\", sem busca (a do di\u00E1logo de configura\u00E7\u00F5es j\u00E1 cobre a se\u00E7\u00E3o);\n o interruptor de tecla \u00FAnica (WCAG 2.1.4) persiste no SpinePreferencesService. -->\n <hm-shortcut-list class=\"sp-settings__shortcuts\" characterKeysToggle [registered]=\"false\" [items]=\"shortcutItems()\" [headingLevel]=\"4\" />\n </hm-settings-section>\n\n <!-- \u2500\u2500 Dados do navegador \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- Listas por usu\u00E1rio do SpineUserStorage e as prefer\u00EAncias deste painel. Destrutivo: o 1\u00BA clique pede\n confirma\u00E7\u00E3o (bot\u00E3o vira \"Confirmar\" + Cancelar), como nas listas de tokens e sess\u00F5es. -->\n <hm-settings-section [key]=\"keys.data\" [label]=\"text.browserData\" icon=\"browser-setting\" [description]=\"text.browserDataDescription\" [keywords]=\"text.browserDataKeywords\">\n <!-- SpineFeatures.accountPreferences: as prefer\u00EAncias tamb\u00E9m na conta do Argos (as telas acima n\u00E3o mudam). -->\n @if (features.accountPreferences) {\n <hm-settings-row [label]=\"featureText.sync\" [description]=\"syncStatus() || featureText.syncDescription\" [keywords]=\"featureText.syncKeywords\">\n <hm-toggletip rowHelp [label]=\"fmt(text.moreAbout, { label: featureText.sync })\" [text]=\"featureText.syncDescription\" />\n <hm-button emphasis=\"medium\" icon=\"refresh\" [disabled]=\"accountPreferences.status() === 'local'\" [loading]=\"accountPreferences.status() === 'saving' || accountPreferences.status() === 'loading'\" (clicked)=\"syncNow()\">{{ featureText.syncNow }}</hm-button>\n </hm-settings-row>\n }\n @for (list of browserLists(); track list.id) {\n <hm-settings-row [label]=\"list.label\" [description]=\"list.count\" [keywords]=\"list.keywords\">\n <span class=\"sp-settings__actions\">\n @if (confirming() === list.id) {\n <hm-button emphasis=\"medium\" (clicked)=\"cancelConfirm()\">{{ text.cancel }}</hm-button>\n }\n <hm-button\n [emphasis]=\"confirming() === list.id ? 'high' : 'medium'\"\n intent=\"danger\"\n [disabled]=\"list.empty && confirming() !== list.id\"\n (clicked)=\"clearList(list.id)\"\n >{{ confirming() === list.id ? text.confirmClear : text.clear }}</hm-button>\n </span>\n </hm-settings-row>\n }\n\n <hm-settings-row [label]=\"text.restorePreferences\" [description]=\"text.restorePreferencesDescription\" [keywords]=\"text.restorePreferencesKeywords\">\n <hm-toggletip rowHelp [label]=\"fmt(text.moreAbout, { label: text.restorePreferences })\" [text]=\"text.restorePreferencesHelp\" />\n <span class=\"sp-settings__actions\">\n @if (confirming() === 'preferences') {\n <hm-button emphasis=\"medium\" (clicked)=\"cancelConfirm()\">{{ text.cancel }}</hm-button>\n }\n <hm-button [emphasis]=\"confirming() === 'preferences' ? 'high' : 'medium'\" intent=\"danger\" (clicked)=\"restorePreferences()\">\n {{ confirming() === 'preferences' ? text.confirmRestore : text.restore }}\n </hm-button>\n </span>\n </hm-settings-row>\n </hm-settings-section>\n\n <!-- \u2500\u2500 Ajuda \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- Novidades (s\u00F3 com alguma vigente), configura\u00E7\u00E3o inicial e o essencial: fecham o painel antes de abrir. -->\n <hm-settings-section [key]=\"keys.help\" [label]=\"text.help\" icon=\"help\" [keywords]=\"text.helpKeywords\">\n @if (hasNews()) {\n <hm-settings-row [label]=\"text.news\" [description]=\"text.newsDescription\" [keywords]=\"text.newsKeywords\">\n <hm-button emphasis=\"medium\" icon=\"star\" (clicked)=\"showNews()\">{{ text.showNews }}</hm-button>\n </hm-settings-row>\n }\n @if (setupEnabled) {\n <hm-settings-row [label]=\"text.setup\" [description]=\"text.setupDescription\" [keywords]=\"text.setupKeywords\">\n <hm-button emphasis=\"medium\" icon=\"color-palette\" (clicked)=\"redoSetup()\">{{ text.redoSetup }}</hm-button>\n </hm-settings-row>\n }\n <hm-settings-row [label]=\"text.essentials\" [description]=\"text.essentialsDescription\" [keywords]=\"text.essentialsKeywords\">\n <hm-button emphasis=\"medium\" icon=\"help\" (clicked)=\"showEssentials()\">{{ text.showEssentials }}</hm-button>\n </hm-settings-row>\n </hm-settings-section>\n\n <!-- \u2500\u2500 Se\u00E7\u00F5es do app (provideSettingsSection) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @for (s of appSections; track s.key) {\n <hm-settings-section [key]=\"s.key\" [label]=\"s.label\" [icon]=\"s.icon ?? 'cog'\" [description]=\"s.description ?? ''\" [keywords]=\"s.keywords ?? ''\">\n <ng-container *ngComponentOutlet=\"s.component\" />\n </hm-settings-section>\n }\n\n <!-- \u2500\u2500 Sobre \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <hm-settings-section [key]=\"keys.about\" [label]=\"text.about\" icon=\"info-circle\" [keywords]=\"text.aboutKeywords\">\n <hm-settings-row [label]=\"text.application\">\n <span class=\"sp-settings__value\">{{ appName }}@if (packageInfo.name) { <span class=\"sp-settings__muted\"> \u00B7 {{ packageInfo.name }}</span> }</span>\n </hm-settings-row>\n <!-- M\u00E9dia da ferramenta (SpineFeatures.ratings) e \"Avaliar\", que abre o di\u00E1logo da estrela do cabe\u00E7alho. -->\n @if (ratingsEnabled) {\n <hm-settings-row [label]=\"ratingText.aboutRating\" [keywords]=\"ratingText.aboutRatingKeywords\">\n <spine-app-rating-summary />\n </hm-settings-row>\n }\n <hm-settings-row [label]=\"text.version\" [keywords]=\"text.versionKeywords\">\n <span class=\"sp-settings__value sp-settings__mono\">{{ packageInfo.version ?? '\u2014' }}</span>\n </hm-settings-row>\n @if (buildDate) {\n <hm-settings-row [label]=\"text.buildDate\">\n <span class=\"sp-settings__value\">{{ buildDate }}</span>\n </hm-settings-row>\n }\n @if (packageInfo.environment) {\n <hm-settings-row [label]=\"text.environment\" [keywords]=\"text.environmentKeywords\">\n <span class=\"sp-settings__value\">{{ packageInfo.environment }}</span>\n </hm-settings-row>\n }\n @if (packageInfo.repository?.url || packageInfo.docs || packageInfo.issues) {\n <hm-settings-row [label]=\"text.links\" [keywords]=\"text.linksKeywords\">\n <span class=\"sp-settings__links\">\n @if (packageInfo.docs) { <hm-button emphasis=\"medium\" icon=\"book\" [link]=\"packageInfo.docs\" [newTab]=\"true\">{{ text.docs }}</hm-button> }\n @if (packageInfo.issues) { <hm-button emphasis=\"medium\" icon=\"bug\" [link]=\"packageInfo.issues\" [newTab]=\"true\">{{ text.reportIssue }}</hm-button> }\n @if (packageInfo.repository?.url) { <hm-button emphasis=\"medium\" icon=\"link\" [link]=\"packageInfo.repository!.url!\" [newTab]=\"true\">{{ text.repository }}</hm-button> }\n </span>\n </hm-settings-row>\n }\n @if (dependencies.length) {\n <hm-settings-row [label]=\"text.dependencies\" [description]=\"text.dependenciesDescription\" [keywords]=\"text.dependenciesKeywords\" [stacked]=\"true\">\n <dl class=\"sp-settings__deps\">\n @for (d of dependencies; track d.name) {\n <div><dt>{{ d.label }}</dt><dd class=\"sp-settings__mono\">{{ d.version }}</dd></div>\n }\n </dl>\n </hm-settings-row>\n }\n <hm-settings-row [label]=\"text.supportInfo\" [description]=\"text.supportInfoDescription\" [keywords]=\"text.supportInfoKeywords\">\n <hm-button emphasis=\"medium\" icon=\"clipboard\" (clicked)=\"copySupportInfo()\">{{ text.copy }}</hm-button>\n </hm-settings-row>\n </hm-settings-section>\n </hm-settings-dialog>\n}\n", styles: ["@charset \"UTF-8\";.sp-settings__timezone{display:block;width:min(320px,100%)}.sp-settings__profile{display:flex;align-items:center;gap:var(--hm-space-sm);padding:var(--hm-space-xs) 0 var(--hm-space-sm)}.sp-settings__profile-text{display:flex;min-width:0;flex-direction:column;gap:var(--hm-space-micro);color:var(--hm-text);overflow-wrap:anywhere}.sp-settings__profile-text span{color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.sp-settings__value{color:var(--hm-text);font-size:var(--hm-font-size-sm);text-align:end;overflow-wrap:anywhere}.sp-settings__muted{color:var(--hm-muted)}.sp-settings__mono{font-family:var(--hm-font-mono)}.sp-settings__shortcuts{display:block;padding-block:var(--hm-space-xxxs);border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-settings__links,.sp-settings__actions{display:inline-flex;flex-wrap:wrap;justify-content:flex-end;gap:var(--hm-space-xs)}.sp-settings__section--group-open ::ng-deep .hm-settings-section__heading{position:absolute;inline-size:1px;block-size:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.sp-settings__picker ::ng-deep .hm-theme-picker__title{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.sp-settings__deps{display:grid;flex:1;min-width:0;grid-template-columns:repeat(auto-fill,minmax(min(12rem,100%),1fr));margin:0;overflow:hidden;border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius);background:var(--hm-surface)}.sp-settings__deps div{display:flex;justify-content:space-between;gap:var(--hm-space-xs);margin-block-start:calc(-1 * var(--hm-border-hairline));margin-inline-start:calc(-1 * var(--hm-border-hairline));padding:var(--hm-space-xs) var(--hm-space-sm);border-top:var(--hm-border-hairline) solid var(--hm-divider);border-inline-start:var(--hm-border-hairline) solid var(--hm-divider)}.sp-settings__deps dt{color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.sp-settings__deps dd{margin:0;color:var(--hm-text);font-size:var(--hm-font-size-xs)}\n"], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: AppTokensComponent, selector: "spine-app-tokens" }, { kind: "component", type: MyGroupsComponent, selector: "spine-my-groups", inputs: ["groups"], outputs: ["openChange"] }, { kind: "component", type: AiAgentComponent, selector: "spine-ai-agent" }, { kind: "component", type: AccountActivityComponent, selector: "spine-account-activity" }, { kind: "component", type: DefaultBadgeComponent, selector: "spine-default-badge" }, { kind: "component", type: CheckboxComponent, selector: "hm-checkbox", inputs: ["label", "labelHidden", "checked", "indeterminate"], outputs: ["checkedChange"] }, { kind: "component", type: AccountMfaComponent, selector: "spine-account-mfa" }, { kind: "component", type: AccountRecoveryCodesComponent, selector: "spine-account-recovery-codes" }, { kind: "component", type: AccountSessionsComponent, selector: "spine-account-sessions" }, { kind: "directive", type: SpineAccountSecurityScopeDirective, selector: "[spineAccountSecurity]" }, { kind: "component", type: AccountAvatarComponent, selector: "hm-account-avatar", inputs: ["name", "imageUrl", "size", "loading", "presence", "texts"] }, { kind: "component", type: ButtonComponent, selector: "hm-button", inputs: ["emphasis", "intent", "size", "type", "icon", "iconDirection", "iconEnd", "disabled", "loading", "loadingState", "block", "link", "newTab", "caret", "inMenu", "toggle", "pressed"], outputs: ["loadingStateChange", "pressedChange", "clicked"] }, { kind: "component", type: ComboboxComponent, selector: "hm-combobox", inputs: ["label", "options", "value", "placeholder", "icon", "hint", "size", "labelHidden", "clearable", "loading", "allowCustomValue"], outputs: ["valueChange"] }, { kind: "component", type: SegmentedControlComponent, selector: "hm-segmented-control", inputs: ["options", "value", "label", "size", "emphasis"], outputs: ["valueChange"] }, { kind: "component", type: SettingsDialogComponent, selector: "hm-settings-dialog", inputs: ["open", "heading", "activeSection", "closeHandler", "actions", "submitLabel", "cancelLabel"], outputs: ["openChange", "activeSectionChange", "closed", "submitted"] }, { kind: "component", type: SettingsRowComponent, selector: "hm-settings-row", inputs: ["label", "description", "keywords", "stacked"] }, { kind: "component", type: SettingsSectionComponent, selector: "hm-settings-section", inputs: ["key", "label", "icon", "description", "keywords", "control", "invalid"] }, { kind: "component", type: SelectComponent, selector: "hm-select", inputs: ["value", "label", "labelHidden", "hint"], outputs: ["valueChange"] }, { kind: "component", type: ShortcutListComponent, selector: "hm-shortcut-list", inputs: ["items", "registered", "searchable", "characterKeysToggle", "headingLevel"] }, { kind: "component", type: ThemePickerComponent, selector: "hm-theme-picker", inputs: ["families", "family", "theme", "showMode"], outputs: ["familyChosen", "themeChosen"] }, { kind: "component", type: ToggletipComponent, selector: "hm-toggletip", inputs: ["label", "text", "side", "intent", "icon"] }, { kind: "component", type: SpineAppRatingSummaryComponent, selector: "spine-app-rating-summary" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
6277
6512
|
}
|
|
6278
6513
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: SettingsPanelComponent, decorators: [{
|
|
6279
6514
|
type: Component,
|
|
@@ -6283,7 +6518,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImpo
|
|
|
6283
6518
|
AccountAvatarComponent, ButtonComponent, ComboboxComponent,
|
|
6284
6519
|
SegmentedControlComponent, SettingsDialogComponent, SettingsRowComponent, SettingsSectionComponent,
|
|
6285
6520
|
SelectComponent, ShortcutListComponent, ThemePickerComponent, ToggletipComponent, SpineAppRatingSummaryComponent,
|
|
6286
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Montado s\u00F3 enquanto aberto: nada disto (lista de fusos, leitura do token...) custa no\n carregamento de toda p\u00E1gina. -->\n@if (settings.isOpen()) {\n <hm-settings-dialog\n [heading]=\"text.heading\"\n [open]=\"true\"\n (openChange)=\"onOpenChange($event)\"\n [activeSection]=\"activeSection()\"\n (activeSectionChange)=\"settings.section.set($event)\"\n >\n <!-- \u2500\u2500 Conta \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <hm-settings-section [key]=\"keys.account\" [label]=\"text.account\" icon=\"user\" [keywords]=\"text.accountKeywords\">\n <div class=\"sp-settings__profile\">\n <hm-account-avatar [name]=\"profile.name ?? text.user\" [imageUrl]=\"profile.picture\" />\n <span class=\"sp-settings__profile-text\">\n <strong>{{ profile.name ?? text.user }}</strong>\n @if (profile.role) { <span>{{ profile.role }}</span> }\n </span>\n </div>\n\n <!-- S\u00F3 informativo: a troca de n\u00EDvel fica no menu do perfil, perto de onde se trabalha. -->\n @if (badge) {\n <hm-settings-row [label]=\"text.accessLevel\" [keywords]=\"text.accessLevelKeywords\">\n <span class=\"sp-settings__value\">{{ badge.name }}</span>\n </hm-settings-row>\n }\n\n <hm-settings-row [label]=\"text.session\" [description]=\"text.sessionDescription\" [keywords]=\"text.sessionKeywords\">\n <span class=\"sp-settings__value\">{{ sessionExpiry }}</span>\n </hm-settings-row>\n\n <!-- Recursos opcionais (SpineConfig.features): crach\u00E1 padr\u00E3o (Argos), inatividade e tela inicial. -->\n @if (showDefaultBadge) {\n <hm-settings-row [label]=\"featureText.defaultBadge\" [description]=\"featureText.defaultBadgeDescription\" [keywords]=\"featureText.defaultBadgeKeywords\">\n <spine-default-badge />\n </hm-settings-row>\n }\n\n @if (idleOptions().length) {\n <hm-settings-row [label]=\"featureText.idle\" [description]=\"idleHint || featureText.idleDescription\" [keywords]=\"featureText.idleKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"featureText.idle\" [options]=\"idleOptions()\" [value]=\"idleValue()\" (valueChange)=\"setIdle($event)\" />\n </hm-settings-row>\n }\n\n @if (features.startPage) {\n <hm-settings-row [label]=\"featureText.startPage\" [description]=\"quickAccessHasFavorites() ? featureText.startPageDescription : featureText.startPageHint\" [keywords]=\"featureText.startPageKeywords\">\n <hm-select class=\"sp-settings__language\" [label]=\"featureText.startPage\" [labelHidden]=\"true\" [value]=\"startPageValue()\" (valueChange)=\"setStartPage($event ?? 'home')\">\n @for (option of startPageOptions(); track option.value) {\n <option [value]=\"option.value\">{{ option.label }}</option>\n }\n </hm-select>\n </hm-settings-row>\n }\n\n <hm-settings-row [label]=\"text.logout\" [description]=\"text.logoutDescription\" [keywords]=\"text.logoutKeywords\">\n <hm-button emphasis=\"medium\" intent=\"danger\" icon=\"logout\" [loading]=\"logoutPending()\" (clicked)=\"logout()\">{{ text.logout }}</hm-button>\n </hm-settings-row>\n </hm-settings-section>\n\n <!-- \u2500\u2500 MFA \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- API da conta do Argos com o token da sess\u00E3o (Bearer): MFA e c\u00F3digos de recupera\u00E7\u00E3o aqui mesmo, sem\n abrir o Argos. O spineAccountSecurity d\u00E1 \u00E0s linhas o mesmo estado (reautentica\u00E7\u00E3o, cadastro em\n andamento), que morre quando o painel fecha. `?settings=seguranca` (chave antiga) abre esta se\u00E7\u00E3o. -->\n @if (accountSecurity) {\n <hm-settings-section spineAccountSecurity [key]=\"keys.mfa\" [label]=\"text.mfa\" icon=\"shield-check\" [description]=\"text.mfaDescription\" [keywords]=\"text.mfaKeywords\">\n <!-- Realm s\u00F3 pelo nome: o id (UUID) n\u00E3o diz nada a quem l\u00EA, ent\u00E3o some. -->\n @if (accountLogin || accountRealm) {\n <hm-settings-row [label]=\"text.signedInAccount\" [description]=\"accountRealm ? fmt(text.signedInRealm, { realm: accountRealm }) : ''\">\n <span class=\"sp-settings__value\">{{ profile.name ?? text.user }}@if (accountLogin) { <span class=\"sp-settings__muted\"> \u00B7 {{ accountLogin }}</span> }</span>\n </hm-settings-row>\n }\n\n <hm-settings-row [label]=\"text.twoFactor\" [description]=\"text.twoFactorDescription\" [keywords]=\"text.twoFactorKeywords\" [stacked]=\"true\">\n <spine-account-mfa />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.recoveryCodes\" [description]=\"text.recoveryCodesDescription\" [keywords]=\"text.recoveryCodesKeywords\" [stacked]=\"true\">\n <spine-account-recovery-codes />\n </hm-settings-row>\n\n <!-- Entradas e tentativas desta conta (SpineFeatures.accountActivity), \u00FAltimos 90 dias. -->\n @if (features.accountActivity) {\n <hm-settings-row [label]=\"featureText.activity\" [description]=\"featureText.activityDescription\" [keywords]=\"featureText.activityKeywords\" [stacked]=\"true\">\n <spine-account-activity />\n </hm-settings-row>\n }\n </hm-settings-section>\n }\n\n <!-- \u2500\u2500 Sess\u00F5es \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- Os tokens e onde a conta est\u00E1 conectada (a validade desta sess\u00E3o fica em Conta). Cada linha tem a\n pr\u00F3pria condi\u00E7\u00E3o; a se\u00E7\u00E3o some se nenhuma sobrar (hasSessionsSection). -->\n @if (hasSessionsSection) {\n <hm-settings-section [key]=\"keys.sessions\" [label]=\"text.sessionsSection\" icon=\"devices\" [description]=\"text.sessionsSectionDescription\" [keywords]=\"text.sessionsSectionKeywords\">\n <!-- S\u00F3 com SpineConfig.technicalDocs (padr\u00E3o: isDevMode()): token da sess\u00E3o no clipboard \u00E9 ferramenta de dev. -->\n @if (sessionsItems.accessToken) {\n <hm-settings-row [label]=\"text.accessToken\" [description]=\"text.accessTokenDescription\" [keywords]=\"text.accessTokenKeywords\">\n <hm-button emphasis=\"medium\" icon=\"copy\" (clicked)=\"copyToken()\">{{ text.copy }}</hm-button>\n </hm-settings-row>\n }\n\n @if (sessionsItems.appTokens) {\n <hm-settings-row [label]=\"text.appTokens\" [stacked]=\"true\"\n [description]=\"text.appTokensDescription\"\n [keywords]=\"text.appTokensKeywords\">\n <hm-toggletip rowHelp [label]=\"fmt(text.moreAbout, { label: text.appTokens })\" [text]=\"text.appTokensHelp\" />\n <spine-app-tokens />\n </hm-settings-row>\n }\n\n <!-- Token + .mcp.json prontos para um agente de IA (SpineFeatures.aiAgent). -->\n @if (sessionsItems.aiAgent) {\n <hm-settings-row [label]=\"featureText.aiAgent\" [description]=\"featureText.aiAgentDescription\" [keywords]=\"featureText.aiAgentKeywords\" [stacked]=\"true\">\n <hm-toggletip rowHelp [label]=\"fmt(text.moreAbout, { label: featureText.aiAgent })\" [text]=\"featureText.aiAgentHelp\" />\n <spine-ai-agent />\n </hm-settings-row>\n }\n\n <!-- Sess\u00F5es e dispositivos: API da conta do Argos, mesma condi\u00E7\u00E3o da se\u00E7\u00E3o MFA. -->\n @if (sessionsItems.devices) {\n <hm-settings-row [label]=\"text.sessions\" [description]=\"text.sessionsDescription\" [keywords]=\"text.sessionsKeywords\" [stacked]=\"true\">\n <spine-account-sessions />\n </hm-settings-row>\n }\n </hm-settings-section>\n }\n\n <!-- \u2500\u2500 Grupos \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- Os grupos desta aplica\u00E7\u00E3o de que a pessoa \u00E9 membro (argos-admin /me/groups, relidos a cada abertura): a lista,\n e escolhendo um, a tela de membros dele. Sem grupo nenhum, a se\u00E7\u00E3o n\u00E3o aparece. -->\n @if (myGroups().length) {\n <hm-settings-section [key]=\"keys.groups\" [label]=\"text.groups\" icon=\"employee-group\" [keywords]=\"text.groupsKeywords\"\n [class.sp-settings__section--group-open]=\"groupOpen()\" [description]=\"groupOpen() ? '' : text.groupsDescription\">\n <spine-my-groups [groups]=\"myGroups()\" (openChange)=\"groupOpen.set($event)\" />\n </hm-settings-section>\n }\n\n <!-- \u2500\u2500 Apar\u00EAncia \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <hm-settings-section [key]=\"keys.appearance\" [label]=\"text.appearance\" icon=\"color-palette\" [keywords]=\"text.appearanceKeywords\">\n <hm-settings-row [label]=\"text.theme\" [description]=\"text.themeDescription\" [keywords]=\"text.themeKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.theme\" [options]=\"themeOptions()\" [value]=\"themeMode()\" (valueChange)=\"setThemeMode($event)\" />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.accent\" [description]=\"text.accentDescription\" [keywords]=\"text.accentKeywords\" [stacked]=\"true\">\n <hm-theme-picker\n class=\"sp-settings__picker\"\n [families]=\"families\"\n [family]=\"family()\"\n [theme]=\"appliedTheme()\"\n [showMode]=\"false\"\n (familyChosen)=\"setFamily($event)\"\n />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.density\" [description]=\"text.densityDescription\" [keywords]=\"text.densityKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.density\" [options]=\"densityOptions()\" [value]=\"densityValue()\" (valueChange)=\"setDensity($event)\" />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.font\" [description]=\"text.fontDescription\" [keywords]=\"text.fontKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.font\" [options]=\"fontOptions\" [value]=\"fontValue()\" (valueChange)=\"setFont($event)\" />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.sidebar\" [description]=\"text.sidebarDescription\" [keywords]=\"text.sidebarKeywords\">\n <hm-toggletip rowHelp [label]=\"fmt(text.moreAbout, { label: text.sidebar })\" [text]=\"text.sidebarHelp\" />\n <hm-segmented-control emphasis=\"action\" [label]=\"text.sidebar\" [options]=\"sidebarOptions()\" [value]=\"sidebar.mode()\" (valueChange)=\"setSidebarMode($event)\" />\n </hm-settings-row>\n </hm-settings-section>\n\n <!-- \u2500\u2500 Acessibilidade \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- Tamanho do texto (--hm-text-scale no <html>, HermesZoomService) e movimento (data-motion no <html>,\n HermesMotionService), guardados pelo SpinePreferencesService. -->\n <hm-settings-section [key]=\"keys.accessibility\" [label]=\"text.accessibility\" icon=\"accessibility-1\" [keywords]=\"text.accessibilityKeywords\">\n <hm-settings-row [label]=\"text.textSize\" [description]=\"text.textSizeDescription\" [keywords]=\"text.textSizeKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.textSize\" [options]=\"textSizeOptions()\" [value]=\"textSizeValue()\" (valueChange)=\"setTextSize($event)\" />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.motion\" [description]=\"text.motionDescription\" [keywords]=\"text.motionKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.motion\" [options]=\"motionOptions()\" [value]=\"preferences.motion()\" (valueChange)=\"setMotion($event)\" />\n </hm-settings-row>\n </hm-settings-section>\n\n <!-- \u2500\u2500 Regi\u00E3o \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <hm-settings-section [key]=\"keys.region\" [label]=\"text.region\" icon=\"clock\" [keywords]=\"text.regionKeywords\">\n <hm-settings-row [label]=\"text.language\" [description]=\"text.languageDescription\" [keywords]=\"text.languageKeywords\">\n <hm-select\n class=\"sp-settings__language\"\n [label]=\"text.language\"\n [labelHidden]=\"true\"\n [value]=\"preferences.language()\"\n (valueChange)=\"preferences.setLanguage($event ?? '')\"\n >\n @for (option of languageOptions(); track option.value) {\n <option [value]=\"option.value\" [attr.lang]=\"option.value || null\">{{ option.label }}</option>\n }\n </hm-select>\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.timeZone\" [description]=\"fmt(text.timeZoneHint, { now: timeZonePreview() })\" [keywords]=\"text.timeZoneKeywords\">\n <hm-combobox\n class=\"sp-settings__timezone\"\n [label]=\"text.timeZone\"\n [labelHidden]=\"true\"\n icon=\"world\"\n [options]=\"timeZoneOptions()\"\n [value]=\"preferences.timeZone()\"\n (valueChange)=\"preferences.setTimeZone($event)\"\n />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.hourCycle\" [description]=\"fmt(text.hourCycleHint, { now: hourCyclePreview() })\" [keywords]=\"text.hourCycleKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.hourCycle\" [options]=\"hourCycleOptions()\" [value]=\"preferences.hourCycle()\" (valueChange)=\"setHourCycle($event)\" />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.weekStart\" [description]=\"text.weekStartDescription\" [keywords]=\"text.weekStartKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.weekStart\" [options]=\"weekStartOptions()\" [value]=\"weekStartValue()\" (valueChange)=\"setWeekStart($event)\" />\n </hm-settings-row>\n </hm-settings-section>\n\n <!-- \u2500\u2500 Notifica\u00E7\u00F5es (SpineFeatures.notices) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- Os tipos de aviso que o app declarou (SpineNoticesService) e o aviso do navegador com a aba em segundo plano. -->\n @if (notices.enabled) {\n <hm-settings-section [key]=\"keys.notices\" [label]=\"featureText.notices\" icon=\"bell\" [description]=\"featureText.noticesDescription\" [keywords]=\"featureText.noticesKeywords\">\n @for (type of notices.types; track type.id) {\n <hm-settings-row [label]=\"type.label\" [description]=\"type.description ?? ''\">\n <hm-checkbox [label]=\"type.label\" [labelHidden]=\"true\" [checked]=\"notices.isEnabled(type.id)\" (checkedChange)=\"notices.setEnabled(type.id, $event)\" />\n </hm-settings-row>\n }\n <hm-settings-row [label]=\"featureText.browserNotices\" [description]=\"notices.permission() === 'denied' ? featureText.browserNoticesDenied : notices.permission() === 'unsupported' ? featureText.browserNoticesUnsupported : featureText.browserNoticesDescription\">\n <hm-checkbox [label]=\"featureText.browserNotices\" [labelHidden]=\"true\" [checked]=\"notices.browserActive()\" (checkedChange)=\"setBrowserNotices($event)\" />\n </hm-settings-row>\n </hm-settings-section>\n }\n\n <!-- \u2500\u2500 Atalhos \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <hm-settings-section [key]=\"keys.shortcuts\" [label]=\"text.shortcuts\" icon=\"keyboard\" [description]=\"text.shortcutsDescription\" [keywords]=\"text.shortcutsKeywords\">\n <!-- Mesma lista do painel \"?\", sem busca (a do di\u00E1logo de configura\u00E7\u00F5es j\u00E1 cobre a se\u00E7\u00E3o);\n o interruptor de tecla \u00FAnica (WCAG 2.1.4) persiste no SpinePreferencesService. -->\n <hm-shortcut-list class=\"sp-settings__shortcuts\" characterKeysToggle [registered]=\"false\" [items]=\"shortcutItems()\" [headingLevel]=\"4\" />\n </hm-settings-section>\n\n <!-- \u2500\u2500 Dados do navegador \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- Listas por usu\u00E1rio do SpineUserStorage e as prefer\u00EAncias deste painel. Destrutivo: o 1\u00BA clique pede\n confirma\u00E7\u00E3o (bot\u00E3o vira \"Confirmar\" + Cancelar), como nas listas de tokens e sess\u00F5es. -->\n <hm-settings-section [key]=\"keys.data\" [label]=\"text.browserData\" icon=\"browser-setting\" [description]=\"text.browserDataDescription\" [keywords]=\"text.browserDataKeywords\">\n <!-- SpineFeatures.accountPreferences: as prefer\u00EAncias tamb\u00E9m na conta do Argos (as telas acima n\u00E3o mudam). -->\n @if (features.accountPreferences) {\n <hm-settings-row [label]=\"featureText.sync\" [description]=\"syncStatus() || featureText.syncDescription\" [keywords]=\"featureText.syncKeywords\">\n <hm-toggletip rowHelp [label]=\"fmt(text.moreAbout, { label: featureText.sync })\" [text]=\"featureText.syncDescription\" />\n <hm-button emphasis=\"medium\" icon=\"refresh\" [disabled]=\"accountPreferences.status() === 'local'\" [loading]=\"accountPreferences.status() === 'saving' || accountPreferences.status() === 'loading'\" (clicked)=\"syncNow()\">{{ featureText.syncNow }}</hm-button>\n </hm-settings-row>\n }\n @for (list of browserLists(); track list.id) {\n <hm-settings-row [label]=\"list.label\" [description]=\"list.count\" [keywords]=\"list.keywords\">\n <span class=\"sp-settings__actions\">\n @if (confirming() === list.id) {\n <hm-button emphasis=\"medium\" (clicked)=\"cancelConfirm()\">{{ text.cancel }}</hm-button>\n }\n <hm-button\n [emphasis]=\"confirming() === list.id ? 'high' : 'medium'\"\n intent=\"danger\"\n [disabled]=\"list.empty && confirming() !== list.id\"\n (clicked)=\"clearList(list.id)\"\n >{{ confirming() === list.id ? text.confirmClear : text.clear }}</hm-button>\n </span>\n </hm-settings-row>\n }\n\n <hm-settings-row [label]=\"text.restorePreferences\" [description]=\"text.restorePreferencesDescription\" [keywords]=\"text.restorePreferencesKeywords\">\n <hm-toggletip rowHelp [label]=\"fmt(text.moreAbout, { label: text.restorePreferences })\" [text]=\"text.restorePreferencesHelp\" />\n <span class=\"sp-settings__actions\">\n @if (confirming() === 'preferences') {\n <hm-button emphasis=\"medium\" (clicked)=\"cancelConfirm()\">{{ text.cancel }}</hm-button>\n }\n <hm-button [emphasis]=\"confirming() === 'preferences' ? 'high' : 'medium'\" intent=\"danger\" (clicked)=\"restorePreferences()\">\n {{ confirming() === 'preferences' ? text.confirmRestore : text.restore }}\n </hm-button>\n </span>\n </hm-settings-row>\n </hm-settings-section>\n\n <!-- \u2500\u2500 Ajuda \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- Novidades (s\u00F3 com alguma vigente), configura\u00E7\u00E3o inicial e o essencial: fecham o painel antes de abrir. -->\n <hm-settings-section [key]=\"keys.help\" [label]=\"text.help\" icon=\"help\" [keywords]=\"text.helpKeywords\">\n @if (hasNews()) {\n <hm-settings-row [label]=\"text.news\" [description]=\"text.newsDescription\" [keywords]=\"text.newsKeywords\">\n <hm-button emphasis=\"medium\" icon=\"star\" (clicked)=\"showNews()\">{{ text.showNews }}</hm-button>\n </hm-settings-row>\n }\n @if (setupEnabled) {\n <hm-settings-row [label]=\"text.setup\" [description]=\"text.setupDescription\" [keywords]=\"text.setupKeywords\">\n <hm-button emphasis=\"medium\" icon=\"color-palette\" (clicked)=\"redoSetup()\">{{ text.redoSetup }}</hm-button>\n </hm-settings-row>\n }\n <hm-settings-row [label]=\"text.essentials\" [description]=\"text.essentialsDescription\" [keywords]=\"text.essentialsKeywords\">\n <hm-button emphasis=\"medium\" icon=\"help\" (clicked)=\"showEssentials()\">{{ text.showEssentials }}</hm-button>\n </hm-settings-row>\n </hm-settings-section>\n\n <!-- \u2500\u2500 Se\u00E7\u00F5es do app (provideSettingsSection) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @for (s of appSections; track s.key) {\n <hm-settings-section [key]=\"s.key\" [label]=\"s.label\" [icon]=\"s.icon ?? 'cog'\" [description]=\"s.description ?? ''\" [keywords]=\"s.keywords ?? ''\">\n <ng-container *ngComponentOutlet=\"s.component\" />\n </hm-settings-section>\n }\n\n <!-- \u2500\u2500 Sobre \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <hm-settings-section [key]=\"keys.about\" [label]=\"text.about\" icon=\"info-circle\" [keywords]=\"text.aboutKeywords\">\n <hm-settings-row [label]=\"text.application\">\n <span class=\"sp-settings__value\">{{ appName }}@if (packageInfo.name) { <span class=\"sp-settings__muted\"> \u00B7 {{ packageInfo.name }}</span> }</span>\n </hm-settings-row>\n <!-- M\u00E9dia da ferramenta (SpineFeatures.ratings) e \"Avaliar\", que abre o di\u00E1logo da estrela do cabe\u00E7alho. -->\n @if (ratingsEnabled) {\n <hm-settings-row [label]=\"ratingText.aboutRating\" [keywords]=\"ratingText.aboutRatingKeywords\">\n <spine-app-rating-summary />\n </hm-settings-row>\n }\n <hm-settings-row [label]=\"text.version\" [keywords]=\"text.versionKeywords\">\n <span class=\"sp-settings__value sp-settings__mono\">{{ packageInfo.version ?? '\u2014' }}</span>\n </hm-settings-row>\n @if (buildDate) {\n <hm-settings-row [label]=\"text.buildDate\">\n <span class=\"sp-settings__value\">{{ buildDate }}</span>\n </hm-settings-row>\n }\n @if (packageInfo.environment) {\n <hm-settings-row [label]=\"text.environment\" [keywords]=\"text.environmentKeywords\">\n <span class=\"sp-settings__value\">{{ packageInfo.environment }}</span>\n </hm-settings-row>\n }\n @if (packageInfo.repository?.url || packageInfo.docs || packageInfo.issues) {\n <hm-settings-row [label]=\"text.links\" [keywords]=\"text.linksKeywords\">\n <span class=\"sp-settings__links\">\n @if (packageInfo.docs) { <hm-button emphasis=\"medium\" icon=\"book\" [link]=\"packageInfo.docs\" [newTab]=\"true\">{{ text.docs }}</hm-button> }\n @if (packageInfo.issues) { <hm-button emphasis=\"medium\" icon=\"bug\" [link]=\"packageInfo.issues\" [newTab]=\"true\">{{ text.reportIssue }}</hm-button> }\n @if (packageInfo.repository?.url) { <hm-button emphasis=\"medium\" icon=\"link\" [link]=\"packageInfo.repository!.url!\" [newTab]=\"true\">{{ text.repository }}</hm-button> }\n </span>\n </hm-settings-row>\n }\n @if (dependencies.length) {\n <hm-settings-row [label]=\"text.dependencies\" [description]=\"text.dependenciesDescription\" [keywords]=\"text.dependenciesKeywords\" [stacked]=\"true\">\n <dl class=\"sp-settings__deps\">\n @for (d of dependencies; track d.name) {\n <div><dt>{{ d.label }}</dt><dd class=\"sp-settings__mono\">{{ d.version }}</dd></div>\n }\n </dl>\n </hm-settings-row>\n }\n <hm-settings-row [label]=\"text.supportInfo\" [description]=\"text.supportInfoDescription\" [keywords]=\"text.supportInfoKeywords\">\n <hm-button emphasis=\"medium\" icon=\"clipboard\" (clicked)=\"copySupportInfo()\">{{ text.copy }}</hm-button>\n </hm-settings-row>\n </hm-settings-section>\n </hm-settings-dialog>\n}\n", styles: ["@charset \"UTF-8\";.sp-settings__timezone{display:block;width:min(320px,100%)}.sp-settings__profile{display:flex;align-items:center;gap:var(--hm-space-sm);padding:var(--hm-space-xs) 0 var(--hm-space-sm)}.sp-settings__profile-text{display:flex;min-width:0;flex-direction:column;gap:var(--hm-space-micro);color:var(--hm-text);overflow-wrap:anywhere}.sp-settings__profile-text span{color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.sp-settings__value{color:var(--hm-text);font-size:var(--hm-font-size-sm);text-align:end;overflow-wrap:anywhere}.sp-settings__muted{color:var(--hm-muted)}.sp-settings__mono{font-family:var(--hm-font-mono)}.sp-settings__shortcuts{display:block;padding-block:var(--hm-space-xxxs);border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-settings__links,.sp-settings__actions{display:inline-flex;flex-wrap:wrap;justify-content:flex-end;gap:var(--hm-space-xs)}.sp-settings__section--group-open ::ng-deep .hm-settings-section__heading{position:absolute;inline-size:1px;block-size:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.sp-settings__picker ::ng-deep .hm-theme-picker__title{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.sp-settings__deps{display:grid;flex:1;min-width:0;grid-template-columns:repeat(auto-fill,minmax(min(12rem,100%),1fr));margin:0;overflow:hidden;border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius);background:var(--hm-surface)}.sp-settings__deps div{display:flex;justify-content:space-between;gap:var(--hm-space-xs);margin-block-start:calc(-1 * var(--hm-border-hairline));margin-inline-start:calc(-1 * var(--hm-border-hairline));padding:var(--hm-space-xs) var(--hm-space-sm);border-top:var(--hm-border-hairline) solid var(--hm-divider);border-inline-start:var(--hm-border-hairline) solid var(--hm-divider)}.sp-settings__deps dt{color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.sp-settings__deps dd{margin:0;color:var(--hm-text);font-size:var(--hm-font-size-xs)}\n"] }]
|
|
6521
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Montado s\u00F3 enquanto aberto: nada disto (lista de fusos, leitura do token...) custa no\n carregamento de toda p\u00E1gina. -->\n@if (settings.isOpen()) {\n <hm-settings-dialog\n [heading]=\"text.heading\"\n [open]=\"true\"\n (openChange)=\"onOpenChange($event)\"\n [activeSection]=\"activeSection()\"\n (activeSectionChange)=\"settings.section.set($event)\"\n >\n <!-- \u2500\u2500 Conta \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <hm-settings-section [key]=\"keys.account\" [label]=\"text.account\" icon=\"user\" [keywords]=\"text.accountKeywords\">\n <div class=\"sp-settings__profile\">\n <hm-account-avatar [name]=\"profile.name ?? text.user\" [imageUrl]=\"profile.picture\" />\n <span class=\"sp-settings__profile-text\">\n <strong>{{ profile.name ?? text.user }}</strong>\n @if (profile.role) { <span>{{ profile.role }}</span> }\n </span>\n </div>\n\n <!-- S\u00F3 informativo: a troca de n\u00EDvel fica no menu do perfil, perto de onde se trabalha. -->\n @if (badge) {\n <hm-settings-row [label]=\"text.accessLevel\" [keywords]=\"text.accessLevelKeywords\">\n <span class=\"sp-settings__value\">{{ badge.name }}</span>\n </hm-settings-row>\n }\n\n <hm-settings-row [label]=\"text.session\" [description]=\"text.sessionDescription\" [keywords]=\"text.sessionKeywords\">\n <span class=\"sp-settings__value\">{{ sessionExpiry }}</span>\n </hm-settings-row>\n\n <!-- Recursos opcionais (SpineConfig.features): crach\u00E1 padr\u00E3o (Argos), inatividade e tela inicial. -->\n @if (showDefaultBadge) {\n <hm-settings-row [label]=\"featureText.defaultBadge\" [description]=\"featureText.defaultBadgeDescription\" [keywords]=\"featureText.defaultBadgeKeywords\">\n <spine-default-badge />\n </hm-settings-row>\n }\n\n @if (idleOptions().length) {\n <hm-settings-row [label]=\"featureText.idle\" [description]=\"idleHint || featureText.idleDescription\" [keywords]=\"featureText.idleKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"featureText.idle\" [options]=\"idleOptions()\" [value]=\"idleValue()\" (valueChange)=\"setIdle($event)\" />\n </hm-settings-row>\n }\n\n @if (features.startPage) {\n <hm-settings-row [label]=\"featureText.startPage\" [description]=\"quickAccessHasFavorites() ? featureText.startPageDescription : featureText.startPageHint\" [keywords]=\"featureText.startPageKeywords\">\n <hm-select class=\"sp-settings__language\" [label]=\"featureText.startPage\" [labelHidden]=\"true\" [value]=\"startPageValue()\" (valueChange)=\"setStartPage($event ?? 'home')\">\n @for (option of startPageOptions(); track option.value) {\n <option [value]=\"option.value\">{{ option.label }}</option>\n }\n </hm-select>\n </hm-settings-row>\n }\n\n <hm-settings-row [label]=\"text.logout\" [description]=\"text.logoutDescription\" [keywords]=\"text.logoutKeywords\">\n <hm-button emphasis=\"medium\" intent=\"danger\" icon=\"logout\" [loading]=\"logoutPending()\" (clicked)=\"logout()\">{{ text.logout }}</hm-button>\n </hm-settings-row>\n </hm-settings-section>\n\n <!-- \u2500\u2500 MFA \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- API da conta do Argos com o token da sess\u00E3o (Bearer): MFA e c\u00F3digos de recupera\u00E7\u00E3o aqui mesmo, sem\n abrir o Argos. O spineAccountSecurity d\u00E1 \u00E0s linhas o mesmo estado (reautentica\u00E7\u00E3o, cadastro em\n andamento), que morre quando o painel fecha. `?settings=seguranca` (chave antiga) abre esta se\u00E7\u00E3o. -->\n @if (accountSecurity) {\n <hm-settings-section spineAccountSecurity [key]=\"keys.mfa\" [label]=\"text.mfa\" icon=\"shield-check\" [description]=\"text.mfaDescription\" [keywords]=\"text.mfaKeywords\">\n <!-- Realm s\u00F3 pelo nome: o id (UUID) n\u00E3o diz nada a quem l\u00EA, ent\u00E3o some. -->\n @if (accountLogin || accountRealm) {\n <hm-settings-row [label]=\"text.signedInAccount\" [description]=\"accountRealm ? fmt(text.signedInRealm, { realm: accountRealm }) : ''\">\n <span class=\"sp-settings__value\">{{ profile.name ?? text.user }}@if (accountLogin) { <span class=\"sp-settings__muted\"> \u00B7 {{ accountLogin }}</span> }</span>\n </hm-settings-row>\n }\n\n <hm-settings-row [label]=\"text.twoFactor\" [description]=\"text.twoFactorDescription\" [keywords]=\"text.twoFactorKeywords\" [stacked]=\"true\">\n <spine-account-mfa />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.recoveryCodes\" [description]=\"text.recoveryCodesDescription\" [keywords]=\"text.recoveryCodesKeywords\" [stacked]=\"true\">\n <spine-account-recovery-codes />\n </hm-settings-row>\n\n <!-- Entradas e tentativas desta conta (SpineFeatures.accountActivity), \u00FAltimos 90 dias. -->\n @if (features.accountActivity) {\n <hm-settings-row [label]=\"featureText.activity\" [description]=\"featureText.activityDescription\" [keywords]=\"featureText.activityKeywords\" [stacked]=\"true\">\n <spine-account-activity />\n </hm-settings-row>\n }\n </hm-settings-section>\n }\n\n <!-- \u2500\u2500 Sess\u00F5es \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- Os tokens e onde a conta est\u00E1 conectada (a validade desta sess\u00E3o fica em Conta). Cada linha tem a\n pr\u00F3pria condi\u00E7\u00E3o; a se\u00E7\u00E3o some se nenhuma sobrar (hasSessionsSection). -->\n @if (hasSessionsSection) {\n <hm-settings-section [key]=\"keys.sessions\" [label]=\"text.sessionsSection\" icon=\"devices\" [description]=\"text.sessionsSectionDescription\" [keywords]=\"text.sessionsSectionKeywords\">\n <!-- S\u00F3 com SpineConfig.technicalDocs (padr\u00E3o: isDevMode()): token da sess\u00E3o no clipboard \u00E9 ferramenta de dev. -->\n @if (sessionsItems.accessToken) {\n <hm-settings-row [label]=\"text.accessToken\" [description]=\"text.accessTokenDescription\" [keywords]=\"text.accessTokenKeywords\">\n <hm-button emphasis=\"medium\" icon=\"copy\" (clicked)=\"copyToken()\">{{ text.copy }}</hm-button>\n </hm-settings-row>\n }\n\n @if (sessionsItems.appTokens) {\n <hm-settings-row [label]=\"text.appTokens\" [stacked]=\"true\"\n [description]=\"text.appTokensDescription\"\n [keywords]=\"text.appTokensKeywords\">\n <hm-toggletip rowHelp [label]=\"fmt(text.moreAbout, { label: text.appTokens })\" [text]=\"text.appTokensHelp\" />\n <spine-app-tokens />\n </hm-settings-row>\n }\n\n <!-- Token + .mcp.json prontos para um agente de IA (SpineFeatures.aiAgent). -->\n @if (sessionsItems.aiAgent) {\n <hm-settings-row [label]=\"featureText.aiAgent\" [description]=\"featureText.aiAgentDescription\" [keywords]=\"featureText.aiAgentKeywords\" [stacked]=\"true\">\n <hm-toggletip rowHelp [label]=\"fmt(text.moreAbout, { label: featureText.aiAgent })\" [text]=\"featureText.aiAgentHelp\" />\n <spine-ai-agent />\n </hm-settings-row>\n }\n\n <!-- Sess\u00F5es e dispositivos: API da conta do Argos, mesma condi\u00E7\u00E3o da se\u00E7\u00E3o MFA. -->\n @if (sessionsItems.devices) {\n <hm-settings-row [label]=\"text.sessions\" [description]=\"text.sessionsDescription\" [keywords]=\"text.sessionsKeywords\" [stacked]=\"true\">\n <spine-account-sessions />\n </hm-settings-row>\n }\n </hm-settings-section>\n }\n\n <!-- \u2500\u2500 Grupos \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- Os grupos desta aplica\u00E7\u00E3o de que a pessoa \u00E9 membro (argos-admin /me/groups, relidos a cada abertura): a lista,\n e escolhendo um, a tela de membros dele. Sem grupo nenhum, a se\u00E7\u00E3o n\u00E3o aparece. -->\n @if (myGroups().length) {\n <hm-settings-section [key]=\"keys.groups\" [label]=\"text.groups\" icon=\"employee-group\" [keywords]=\"text.groupsKeywords\"\n [class.sp-settings__section--group-open]=\"groupOpen()\" [description]=\"groupOpen() ? '' : text.groupsDescription\">\n <spine-my-groups [groups]=\"myGroups()\" (openChange)=\"groupOpen.set($event)\" />\n </hm-settings-section>\n }\n\n <!-- \u2500\u2500 Apar\u00EAncia \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <hm-settings-section [key]=\"keys.appearance\" [label]=\"text.appearance\" icon=\"color-palette\" [keywords]=\"text.appearanceKeywords\">\n <hm-settings-row [label]=\"text.theme\" [description]=\"text.themeDescription\" [keywords]=\"text.themeKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.theme\" [options]=\"themeOptions()\" [value]=\"themeMode()\" (valueChange)=\"setThemeMode($event)\" />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.accent\" [description]=\"text.accentDescription\" [keywords]=\"text.accentKeywords\" [stacked]=\"true\">\n <hm-theme-picker\n class=\"sp-settings__picker\"\n [families]=\"families\"\n [family]=\"family()\"\n [theme]=\"appliedTheme()\"\n [showMode]=\"false\"\n (familyChosen)=\"setFamily($event)\"\n />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.density\" [description]=\"text.densityDescription\" [keywords]=\"text.densityKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.density\" [options]=\"densityOptions()\" [value]=\"densityValue()\" (valueChange)=\"setDensity($event)\" />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.font\" [description]=\"text.fontDescription\" [keywords]=\"text.fontKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.font\" [options]=\"fontOptions\" [value]=\"fontValue()\" (valueChange)=\"setFont($event)\" />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.sidebar\" [description]=\"text.sidebarDescription\" [keywords]=\"text.sidebarKeywords\">\n <hm-toggletip rowHelp [label]=\"fmt(text.moreAbout, { label: text.sidebar })\" [text]=\"text.sidebarHelp\" />\n <hm-segmented-control emphasis=\"action\" [label]=\"text.sidebar\" [options]=\"sidebarOptions()\" [value]=\"sidebar.mode()\" (valueChange)=\"setSidebarMode($event)\" />\n </hm-settings-row>\n\n <!-- Dividir abas: com ela desligada (o padr\u00E3o) a \u00E1rea de abas fica num painel s\u00F3 (SpineWorkspaceNavService). -->\n <hm-settings-row [label]=\"text.splitTabs\" [description]=\"text.splitTabsDescription\" [keywords]=\"text.splitTabsKeywords\">\n <hm-checkbox [label]=\"text.splitTabs\" [labelHidden]=\"true\" [checked]=\"preferences.splitTabs()\" (checkedChange)=\"preferences.setSplitTabs($event)\" />\n </hm-settings-row>\n </hm-settings-section>\n\n <!-- \u2500\u2500 Acessibilidade \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- Tamanho do texto (--hm-text-scale no <html>, HermesZoomService) e movimento (data-motion no <html>,\n HermesMotionService), guardados pelo SpinePreferencesService. -->\n <hm-settings-section [key]=\"keys.accessibility\" [label]=\"text.accessibility\" icon=\"accessibility-1\" [keywords]=\"text.accessibilityKeywords\">\n <hm-settings-row [label]=\"text.textSize\" [description]=\"text.textSizeDescription\" [keywords]=\"text.textSizeKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.textSize\" [options]=\"textSizeOptions()\" [value]=\"textSizeValue()\" (valueChange)=\"setTextSize($event)\" />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.motion\" [description]=\"text.motionDescription\" [keywords]=\"text.motionKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.motion\" [options]=\"motionOptions()\" [value]=\"preferences.motion()\" (valueChange)=\"setMotion($event)\" />\n </hm-settings-row>\n </hm-settings-section>\n\n <!-- \u2500\u2500 Regi\u00E3o \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <hm-settings-section [key]=\"keys.region\" [label]=\"text.region\" icon=\"clock\" [keywords]=\"text.regionKeywords\">\n <hm-settings-row [label]=\"text.language\" [description]=\"text.languageDescription\" [keywords]=\"text.languageKeywords\">\n <hm-select\n class=\"sp-settings__language\"\n [label]=\"text.language\"\n [labelHidden]=\"true\"\n [value]=\"preferences.language()\"\n (valueChange)=\"preferences.setLanguage($event ?? '')\"\n >\n @for (option of languageOptions(); track option.value) {\n <option [value]=\"option.value\" [attr.lang]=\"option.value || null\">{{ option.label }}</option>\n }\n </hm-select>\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.timeZone\" [description]=\"fmt(text.timeZoneHint, { now: timeZonePreview() })\" [keywords]=\"text.timeZoneKeywords\">\n <hm-combobox\n class=\"sp-settings__timezone\"\n [label]=\"text.timeZone\"\n [labelHidden]=\"true\"\n icon=\"world\"\n [options]=\"timeZoneOptions()\"\n [value]=\"preferences.timeZone()\"\n (valueChange)=\"preferences.setTimeZone($event)\"\n />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.hourCycle\" [description]=\"fmt(text.hourCycleHint, { now: hourCyclePreview() })\" [keywords]=\"text.hourCycleKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.hourCycle\" [options]=\"hourCycleOptions()\" [value]=\"preferences.hourCycle()\" (valueChange)=\"setHourCycle($event)\" />\n </hm-settings-row>\n\n <hm-settings-row [label]=\"text.weekStart\" [description]=\"text.weekStartDescription\" [keywords]=\"text.weekStartKeywords\">\n <hm-segmented-control emphasis=\"action\" [label]=\"text.weekStart\" [options]=\"weekStartOptions()\" [value]=\"weekStartValue()\" (valueChange)=\"setWeekStart($event)\" />\n </hm-settings-row>\n </hm-settings-section>\n\n <!-- \u2500\u2500 Notifica\u00E7\u00F5es (SpineFeatures.notices) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- Os tipos de aviso que o app declarou (SpineNoticesService) e o aviso do navegador com a aba em segundo plano. -->\n @if (notices.enabled) {\n <hm-settings-section [key]=\"keys.notices\" [label]=\"featureText.notices\" icon=\"bell\" [description]=\"featureText.noticesDescription\" [keywords]=\"featureText.noticesKeywords\">\n @for (type of notices.types; track type.id) {\n <hm-settings-row [label]=\"type.label\" [description]=\"type.description ?? ''\">\n <hm-checkbox [label]=\"type.label\" [labelHidden]=\"true\" [checked]=\"notices.isEnabled(type.id)\" (checkedChange)=\"notices.setEnabled(type.id, $event)\" />\n </hm-settings-row>\n }\n <hm-settings-row [label]=\"featureText.browserNotices\" [description]=\"notices.permission() === 'denied' ? featureText.browserNoticesDenied : notices.permission() === 'unsupported' ? featureText.browserNoticesUnsupported : featureText.browserNoticesDescription\">\n <hm-checkbox [label]=\"featureText.browserNotices\" [labelHidden]=\"true\" [checked]=\"notices.browserActive()\" (checkedChange)=\"setBrowserNotices($event)\" />\n </hm-settings-row>\n </hm-settings-section>\n }\n\n <!-- \u2500\u2500 Atalhos \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <hm-settings-section [key]=\"keys.shortcuts\" [label]=\"text.shortcuts\" icon=\"keyboard\" [description]=\"text.shortcutsDescription\" [keywords]=\"text.shortcutsKeywords\">\n <!-- Mesma lista do painel \"?\", sem busca (a do di\u00E1logo de configura\u00E7\u00F5es j\u00E1 cobre a se\u00E7\u00E3o);\n o interruptor de tecla \u00FAnica (WCAG 2.1.4) persiste no SpinePreferencesService. -->\n <hm-shortcut-list class=\"sp-settings__shortcuts\" characterKeysToggle [registered]=\"false\" [items]=\"shortcutItems()\" [headingLevel]=\"4\" />\n </hm-settings-section>\n\n <!-- \u2500\u2500 Dados do navegador \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- Listas por usu\u00E1rio do SpineUserStorage e as prefer\u00EAncias deste painel. Destrutivo: o 1\u00BA clique pede\n confirma\u00E7\u00E3o (bot\u00E3o vira \"Confirmar\" + Cancelar), como nas listas de tokens e sess\u00F5es. -->\n <hm-settings-section [key]=\"keys.data\" [label]=\"text.browserData\" icon=\"browser-setting\" [description]=\"text.browserDataDescription\" [keywords]=\"text.browserDataKeywords\">\n <!-- SpineFeatures.accountPreferences: as prefer\u00EAncias tamb\u00E9m na conta do Argos (as telas acima n\u00E3o mudam). -->\n @if (features.accountPreferences) {\n <hm-settings-row [label]=\"featureText.sync\" [description]=\"syncStatus() || featureText.syncDescription\" [keywords]=\"featureText.syncKeywords\">\n <hm-toggletip rowHelp [label]=\"fmt(text.moreAbout, { label: featureText.sync })\" [text]=\"featureText.syncDescription\" />\n <hm-button emphasis=\"medium\" icon=\"refresh\" [disabled]=\"accountPreferences.status() === 'local'\" [loading]=\"accountPreferences.status() === 'saving' || accountPreferences.status() === 'loading'\" (clicked)=\"syncNow()\">{{ featureText.syncNow }}</hm-button>\n </hm-settings-row>\n }\n @for (list of browserLists(); track list.id) {\n <hm-settings-row [label]=\"list.label\" [description]=\"list.count\" [keywords]=\"list.keywords\">\n <span class=\"sp-settings__actions\">\n @if (confirming() === list.id) {\n <hm-button emphasis=\"medium\" (clicked)=\"cancelConfirm()\">{{ text.cancel }}</hm-button>\n }\n <hm-button\n [emphasis]=\"confirming() === list.id ? 'high' : 'medium'\"\n intent=\"danger\"\n [disabled]=\"list.empty && confirming() !== list.id\"\n (clicked)=\"clearList(list.id)\"\n >{{ confirming() === list.id ? text.confirmClear : text.clear }}</hm-button>\n </span>\n </hm-settings-row>\n }\n\n <hm-settings-row [label]=\"text.restorePreferences\" [description]=\"text.restorePreferencesDescription\" [keywords]=\"text.restorePreferencesKeywords\">\n <hm-toggletip rowHelp [label]=\"fmt(text.moreAbout, { label: text.restorePreferences })\" [text]=\"text.restorePreferencesHelp\" />\n <span class=\"sp-settings__actions\">\n @if (confirming() === 'preferences') {\n <hm-button emphasis=\"medium\" (clicked)=\"cancelConfirm()\">{{ text.cancel }}</hm-button>\n }\n <hm-button [emphasis]=\"confirming() === 'preferences' ? 'high' : 'medium'\" intent=\"danger\" (clicked)=\"restorePreferences()\">\n {{ confirming() === 'preferences' ? text.confirmRestore : text.restore }}\n </hm-button>\n </span>\n </hm-settings-row>\n </hm-settings-section>\n\n <!-- \u2500\u2500 Ajuda \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <!-- Novidades (s\u00F3 com alguma vigente), configura\u00E7\u00E3o inicial e o essencial: fecham o painel antes de abrir. -->\n <hm-settings-section [key]=\"keys.help\" [label]=\"text.help\" icon=\"help\" [keywords]=\"text.helpKeywords\">\n @if (hasNews()) {\n <hm-settings-row [label]=\"text.news\" [description]=\"text.newsDescription\" [keywords]=\"text.newsKeywords\">\n <hm-button emphasis=\"medium\" icon=\"star\" (clicked)=\"showNews()\">{{ text.showNews }}</hm-button>\n </hm-settings-row>\n }\n @if (setupEnabled) {\n <hm-settings-row [label]=\"text.setup\" [description]=\"text.setupDescription\" [keywords]=\"text.setupKeywords\">\n <hm-button emphasis=\"medium\" icon=\"color-palette\" (clicked)=\"redoSetup()\">{{ text.redoSetup }}</hm-button>\n </hm-settings-row>\n }\n <hm-settings-row [label]=\"text.essentials\" [description]=\"text.essentialsDescription\" [keywords]=\"text.essentialsKeywords\">\n <hm-button emphasis=\"medium\" icon=\"help\" (clicked)=\"showEssentials()\">{{ text.showEssentials }}</hm-button>\n </hm-settings-row>\n </hm-settings-section>\n\n <!-- \u2500\u2500 Se\u00E7\u00F5es do app (provideSettingsSection) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @for (s of appSections; track s.key) {\n <hm-settings-section [key]=\"s.key\" [label]=\"s.label\" [icon]=\"s.icon ?? 'cog'\" [description]=\"s.description ?? ''\" [keywords]=\"s.keywords ?? ''\">\n <ng-container *ngComponentOutlet=\"s.component\" />\n </hm-settings-section>\n }\n\n <!-- \u2500\u2500 Sobre \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <hm-settings-section [key]=\"keys.about\" [label]=\"text.about\" icon=\"info-circle\" [keywords]=\"text.aboutKeywords\">\n <hm-settings-row [label]=\"text.application\">\n <span class=\"sp-settings__value\">{{ appName }}@if (packageInfo.name) { <span class=\"sp-settings__muted\"> \u00B7 {{ packageInfo.name }}</span> }</span>\n </hm-settings-row>\n <!-- M\u00E9dia da ferramenta (SpineFeatures.ratings) e \"Avaliar\", que abre o di\u00E1logo da estrela do cabe\u00E7alho. -->\n @if (ratingsEnabled) {\n <hm-settings-row [label]=\"ratingText.aboutRating\" [keywords]=\"ratingText.aboutRatingKeywords\">\n <spine-app-rating-summary />\n </hm-settings-row>\n }\n <hm-settings-row [label]=\"text.version\" [keywords]=\"text.versionKeywords\">\n <span class=\"sp-settings__value sp-settings__mono\">{{ packageInfo.version ?? '\u2014' }}</span>\n </hm-settings-row>\n @if (buildDate) {\n <hm-settings-row [label]=\"text.buildDate\">\n <span class=\"sp-settings__value\">{{ buildDate }}</span>\n </hm-settings-row>\n }\n @if (packageInfo.environment) {\n <hm-settings-row [label]=\"text.environment\" [keywords]=\"text.environmentKeywords\">\n <span class=\"sp-settings__value\">{{ packageInfo.environment }}</span>\n </hm-settings-row>\n }\n @if (packageInfo.repository?.url || packageInfo.docs || packageInfo.issues) {\n <hm-settings-row [label]=\"text.links\" [keywords]=\"text.linksKeywords\">\n <span class=\"sp-settings__links\">\n @if (packageInfo.docs) { <hm-button emphasis=\"medium\" icon=\"book\" [link]=\"packageInfo.docs\" [newTab]=\"true\">{{ text.docs }}</hm-button> }\n @if (packageInfo.issues) { <hm-button emphasis=\"medium\" icon=\"bug\" [link]=\"packageInfo.issues\" [newTab]=\"true\">{{ text.reportIssue }}</hm-button> }\n @if (packageInfo.repository?.url) { <hm-button emphasis=\"medium\" icon=\"link\" [link]=\"packageInfo.repository!.url!\" [newTab]=\"true\">{{ text.repository }}</hm-button> }\n </span>\n </hm-settings-row>\n }\n @if (dependencies.length) {\n <hm-settings-row [label]=\"text.dependencies\" [description]=\"text.dependenciesDescription\" [keywords]=\"text.dependenciesKeywords\" [stacked]=\"true\">\n <dl class=\"sp-settings__deps\">\n @for (d of dependencies; track d.name) {\n <div><dt>{{ d.label }}</dt><dd class=\"sp-settings__mono\">{{ d.version }}</dd></div>\n }\n </dl>\n </hm-settings-row>\n }\n <hm-settings-row [label]=\"text.supportInfo\" [description]=\"text.supportInfoDescription\" [keywords]=\"text.supportInfoKeywords\">\n <hm-button emphasis=\"medium\" icon=\"clipboard\" (clicked)=\"copySupportInfo()\">{{ text.copy }}</hm-button>\n </hm-settings-row>\n </hm-settings-section>\n </hm-settings-dialog>\n}\n", styles: ["@charset \"UTF-8\";.sp-settings__timezone{display:block;width:min(320px,100%)}.sp-settings__profile{display:flex;align-items:center;gap:var(--hm-space-sm);padding:var(--hm-space-xs) 0 var(--hm-space-sm)}.sp-settings__profile-text{display:flex;min-width:0;flex-direction:column;gap:var(--hm-space-micro);color:var(--hm-text);overflow-wrap:anywhere}.sp-settings__profile-text span{color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.sp-settings__value{color:var(--hm-text);font-size:var(--hm-font-size-sm);text-align:end;overflow-wrap:anywhere}.sp-settings__muted{color:var(--hm-muted)}.sp-settings__mono{font-family:var(--hm-font-mono)}.sp-settings__shortcuts{display:block;padding-block:var(--hm-space-xxxs);border-top:var(--hm-border-hairline) solid var(--hm-divider)}.sp-settings__links,.sp-settings__actions{display:inline-flex;flex-wrap:wrap;justify-content:flex-end;gap:var(--hm-space-xs)}.sp-settings__section--group-open ::ng-deep .hm-settings-section__heading{position:absolute;inline-size:1px;block-size:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.sp-settings__picker ::ng-deep .hm-theme-picker__title{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.sp-settings__deps{display:grid;flex:1;min-width:0;grid-template-columns:repeat(auto-fill,minmax(min(12rem,100%),1fr));margin:0;overflow:hidden;border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius);background:var(--hm-surface)}.sp-settings__deps div{display:flex;justify-content:space-between;gap:var(--hm-space-xs);margin-block-start:calc(-1 * var(--hm-border-hairline));margin-inline-start:calc(-1 * var(--hm-border-hairline));padding:var(--hm-space-xs) var(--hm-space-sm);border-top:var(--hm-border-hairline) solid var(--hm-divider);border-inline-start:var(--hm-border-hairline) solid var(--hm-divider)}.sp-settings__deps dt{color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.sp-settings__deps dd{margin:0;color:var(--hm-text);font-size:var(--hm-font-size-xs)}\n"] }]
|
|
6287
6522
|
}], ctorParameters: () => [] });
|
|
6288
6523
|
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
6289
6524
|
/** "UTC−03:00" para um fuso IANA. */
|
|
@@ -6761,7 +6996,7 @@ function registerPage() {
|
|
|
6761
6996
|
route_redirect: SPINE_SUGGESTIONS_PAGE_PATH,
|
|
6762
6997
|
description: text.description,
|
|
6763
6998
|
},
|
|
6764
|
-
load: () => import('./trismegisto-spine-layout-suggestions-page.component-
|
|
6999
|
+
load: () => import('./trismegisto-spine-layout-suggestions-page.component-CEKMqera.mjs').then((m) => m.SpineSuggestionsPageComponent),
|
|
6765
7000
|
});
|
|
6766
7001
|
});
|
|
6767
7002
|
}
|
|
@@ -7459,7 +7694,7 @@ class SpinePagePanelComponent {
|
|
|
7459
7694
|
</div>
|
|
7460
7695
|
}
|
|
7461
7696
|
</div>
|
|
7462
|
-
`, isInline: true, styles: [":host{display:flex;flex-direction:column;block-size:100%;min-block-size:0}.spine-page-panel__content{flex:1;min-block-size:0;display:flex;flex-direction:column;padding:var(--hm-space-lg, 1.5rem) var(--hm-space-md, 1rem)}.spine-page-panel__loading{display:flex;flex:1;align-items:center;justify-content:center;min-block-size:50vh;padding:var(--hm-space-xl)}.spine-page-panel__empty{display:flex;flex:1;flex-direction:column;align-items:center;justify-content:center;gap:var(--hm-space-sm);padding:var(--hm-space-xl);text-align:center;color:var(--hm-muted)}.spine-page-panel__empty hm-icon{color:var(--hm-muted)}.spine-page-panel__empty-title{margin:0;color:var(--hm-text);font-size:var(--hm-font-size-lg, 18px);font-weight:
|
|
7697
|
+
`, isInline: true, styles: [":host{display:flex;flex-direction:column;block-size:100%;min-block-size:0}.spine-page-panel__content{flex:1;min-block-size:0;display:flex;flex-direction:column;padding:var(--hm-space-lg, 1.5rem) var(--hm-space-md, 1rem)}.spine-page-panel__loading{display:flex;flex:1;align-items:center;justify-content:center;min-block-size:50vh;padding:var(--hm-space-xl)}.spine-page-panel__empty{display:flex;flex:1;flex-direction:column;align-items:center;justify-content:center;gap:var(--hm-space-sm);padding:var(--hm-space-xl);text-align:center;color:var(--hm-muted)}.spine-page-panel__empty hm-icon{color:var(--hm-muted)}.spine-page-panel__empty-title{margin:0;color:var(--hm-text);font-size:var(--hm-font-size-lg, 18px);font-weight:var(--hm-font-weight-semibold)}.spine-page-panel__empty-description{margin:0;max-inline-size:32ch;font-size:var(--hm-font-size-sm, 14px)}\n"], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: LoadingSquareComponent, selector: "hm-loading-square" }, { kind: "component", type: IconComponent, selector: "hm-icon", inputs: ["shape", "direction", "size", "solid", "badge", "status", "flip", "inverse", "label"] }, { kind: "component", type: SpinePageBarComponent, selector: "spine-page-bar", inputs: ["chain", "recordRecent"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
7463
7698
|
}
|
|
7464
7699
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: SpinePagePanelComponent, decorators: [{
|
|
7465
7700
|
type: Component,
|
|
@@ -7478,7 +7713,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImpo
|
|
|
7478
7713
|
</div>
|
|
7479
7714
|
}
|
|
7480
7715
|
</div>
|
|
7481
|
-
`, styles: [":host{display:flex;flex-direction:column;block-size:100%;min-block-size:0}.spine-page-panel__content{flex:1;min-block-size:0;display:flex;flex-direction:column;padding:var(--hm-space-lg, 1.5rem) var(--hm-space-md, 1rem)}.spine-page-panel__loading{display:flex;flex:1;align-items:center;justify-content:center;min-block-size:50vh;padding:var(--hm-space-xl)}.spine-page-panel__empty{display:flex;flex:1;flex-direction:column;align-items:center;justify-content:center;gap:var(--hm-space-sm);padding:var(--hm-space-xl);text-align:center;color:var(--hm-muted)}.spine-page-panel__empty hm-icon{color:var(--hm-muted)}.spine-page-panel__empty-title{margin:0;color:var(--hm-text);font-size:var(--hm-font-size-lg, 18px);font-weight:
|
|
7716
|
+
`, styles: [":host{display:flex;flex-direction:column;block-size:100%;min-block-size:0}.spine-page-panel__content{flex:1;min-block-size:0;display:flex;flex-direction:column;padding:var(--hm-space-lg, 1.5rem) var(--hm-space-md, 1rem)}.spine-page-panel__loading{display:flex;flex:1;align-items:center;justify-content:center;min-block-size:50vh;padding:var(--hm-space-xl)}.spine-page-panel__empty{display:flex;flex:1;flex-direction:column;align-items:center;justify-content:center;gap:var(--hm-space-sm);padding:var(--hm-space-xl);text-align:center;color:var(--hm-muted)}.spine-page-panel__empty hm-icon{color:var(--hm-muted)}.spine-page-panel__empty-title{margin:0;color:var(--hm-text);font-size:var(--hm-font-size-lg, 18px);font-weight:var(--hm-font-weight-semibold)}.spine-page-panel__empty-description{margin:0;max-inline-size:32ch;font-size:var(--hm-font-size-sm, 14px)}\n"] }]
|
|
7482
7717
|
}], ctorParameters: () => [], propDecorators: { url: [{ type: i0.Input, args: [{ isSignal: true, alias: "url", required: true }] }], isFocusedPanel: [{ type: i0.Input, args: [{ isSignal: true, alias: "isFocusedPanel", required: false }] }], tabId: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabId", required: false }] }], panelId: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelId", required: false }] }] } });
|
|
7483
7718
|
|
|
7484
7719
|
/**
|
|
@@ -7909,6 +8144,79 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImpo
|
|
|
7909
8144
|
`, styles: [".sp-idle__text{margin:0}.sp-idle__actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:var(--hm-space-sm)}\n"] }]
|
|
7910
8145
|
}] });
|
|
7911
8146
|
|
|
8147
|
+
/**
|
|
8148
|
+
* Registra a verificação de alterações da tela, presa à aba do workspace em que ela está (`SPINE_TAB`):
|
|
8149
|
+
* com `SpineFeatures.unsavedChanges` ligado, fechar ESSA aba (ou o painel dela, ou "fechar as outras") e
|
|
8150
|
+
* trocar de tela dentro dela pergunta antes. Chame num contexto de injeção (campo da tela); a verificação
|
|
8151
|
+
* sai sozinha quando a tela é destruída.
|
|
8152
|
+
*
|
|
8153
|
+
* ```ts
|
|
8154
|
+
* readonly #unsaved = registerSpineUnsavedChanges(() => this.form.dirty);
|
|
8155
|
+
* ```
|
|
8156
|
+
*
|
|
8157
|
+
* Sem o recurso ligado, continua registrando no `HermesUnsavedChangesService` (o `hermesUnsavedChangesGuard`
|
|
8158
|
+
* de uma rota do app enxerga), mas o shell não pergunta nada.
|
|
8159
|
+
*/
|
|
8160
|
+
function registerSpineUnsavedChanges(check) {
|
|
8161
|
+
const tab = inject(SPINE_TAB, { optional: true });
|
|
8162
|
+
return registerUnsavedChanges(check, tab ? { scope: () => tab.id() } : {});
|
|
8163
|
+
}
|
|
8164
|
+
/**
|
|
8165
|
+
* O lado do shell do aviso de alterações não salvas (`SpineFeatures.unsavedChanges`, desligado por padrão).
|
|
8166
|
+
* Ligado: o `hm-workspace` recebe um store que pergunta antes de fechar aba com alteração; trocar de tela
|
|
8167
|
+
* dentro da aba pergunta também; e o navegador avisa ao recarregar/fechar a página. Desligado: `store` é o
|
|
8168
|
+
* mesmo do `SpineWorkspaceNavService` e nada muda.
|
|
8169
|
+
*/
|
|
8170
|
+
class SpineUnsavedChangesService {
|
|
8171
|
+
constructor() {
|
|
8172
|
+
this.config = inject(SPINE_CONFIG, { optional: true });
|
|
8173
|
+
this.unsaved = inject(HermesUnsavedChangesService);
|
|
8174
|
+
this.nav = inject(SpineWorkspaceNavService);
|
|
8175
|
+
/** O recurso está ligado no app. */
|
|
8176
|
+
this.enabled = !!this.config?.features?.unsavedChanges;
|
|
8177
|
+
/** O store que o shell passa para o `hm-workspace`. */
|
|
8178
|
+
this.store = this.enabled ? this.guard(this.nav.store) : this.nav.store;
|
|
8179
|
+
}
|
|
8180
|
+
/** Liga o aviso do navegador (só com o recurso ligado). Devolve a função que desliga. */
|
|
8181
|
+
start() {
|
|
8182
|
+
return this.enabled ? this.unsaved.warnBeforeUnload() : () => { };
|
|
8183
|
+
}
|
|
8184
|
+
/** Pode trocar a tela da aba ativa do painel? Sem o recurso ou sem alteração nela, `true` na hora. */
|
|
8185
|
+
canReplaceActive(panelId) {
|
|
8186
|
+
if (!this.enabled)
|
|
8187
|
+
return true;
|
|
8188
|
+
const active = findPanelTabs$1(this.nav.store.getState().root, panelId)?.activeId;
|
|
8189
|
+
return active && this.unsaved.hasUnsavedChanges(active) ? this.unsaved.confirmDiscard() : true;
|
|
8190
|
+
}
|
|
8191
|
+
guard(store) {
|
|
8192
|
+
const tabsOf = (panelId) => findPanelTabs$1(store.getState().root, panelId)?.tabs.map((t) => t.id) ?? [];
|
|
8193
|
+
// Sem alteração em nenhuma das abas, fecha na hora (mesmo comportamento de antes); com alteração, pergunta.
|
|
8194
|
+
const closing = (ids, close) => {
|
|
8195
|
+
if (!ids.some((id) => this.unsaved.hasUnsavedChanges(id))) {
|
|
8196
|
+
close();
|
|
8197
|
+
return;
|
|
8198
|
+
}
|
|
8199
|
+
void this.unsaved.confirmDiscard().then((leave) => leave && close());
|
|
8200
|
+
};
|
|
8201
|
+
return {
|
|
8202
|
+
...store,
|
|
8203
|
+
closeTab: (panelId, tabId) => closing([tabId], () => store.closeTab(panelId, tabId)),
|
|
8204
|
+
closePanel: (panelId) => closing(tabsOf(panelId), () => store.closePanel(panelId)),
|
|
8205
|
+
closeOtherTabs: (panelId, tabId) => closing(tabsOf(panelId).filter((id) => id !== tabId), () => store.closeOtherTabs(panelId, tabId)),
|
|
8206
|
+
closeTabsToTheRight: (panelId, tabId) => {
|
|
8207
|
+
const ids = tabsOf(panelId);
|
|
8208
|
+
closing(ids.slice(ids.indexOf(tabId) + 1), () => store.closeTabsToTheRight(panelId, tabId));
|
|
8209
|
+
},
|
|
8210
|
+
};
|
|
8211
|
+
}
|
|
8212
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: SpineUnsavedChangesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
8213
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: SpineUnsavedChangesService, providedIn: 'root' }); }
|
|
8214
|
+
}
|
|
8215
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: SpineUnsavedChangesService, decorators: [{
|
|
8216
|
+
type: Injectable,
|
|
8217
|
+
args: [{ providedIn: 'root' }]
|
|
8218
|
+
}] });
|
|
8219
|
+
|
|
7912
8220
|
/**
|
|
7913
8221
|
* Shell do spine — MESMA estrutura do `docs/website`'s `app.component.html`/`.scss` (decisão de
|
|
7914
8222
|
* 2026-09-28, ver `hefesto-migration-plan.md`): `.shell` com altura de viewport de verdade
|
|
@@ -7939,13 +8247,19 @@ class LayoutComponent {
|
|
|
7939
8247
|
this.preferences = inject(SpinePreferencesService);
|
|
7940
8248
|
this.workspace = inject(SpineWorkspaceNavService);
|
|
7941
8249
|
this.settings = inject(SpineSettingsService);
|
|
8250
|
+
this.sidebar = inject(HermesSidebarService$1);
|
|
7942
8251
|
/** Também liga, uma vez, o aviso de falha do logout (`logoutFailed$` do `@orfeu/angular`). */
|
|
7943
|
-
this.
|
|
8252
|
+
this.logoutNotice = inject(SpineLogoutService);
|
|
7944
8253
|
/** Recursos opcionais (`SpineConfig.features`): cada serviço não faz nada com o seu recurso desligado. */
|
|
7945
8254
|
this.idle = inject(SpineIdleService);
|
|
7946
8255
|
this.startPage = inject(SpineStartPageService);
|
|
7947
8256
|
this.accountPreferences = inject(SpineAccountPreferencesService);
|
|
7948
8257
|
this.setup = inject(SpineInitialSetupService);
|
|
8258
|
+
/** Aviso de alterações não salvas (SpineFeatures.unsavedChanges): sem o recurso, `unsaved.store` é o próprio `workspace.store`. */
|
|
8259
|
+
this.unsaved = inject(SpineUnsavedChangesService);
|
|
8260
|
+
/** SpineFeatures.skipLink. */
|
|
8261
|
+
this.skipLink = !!inject(SPINE_CONFIG, { optional: true })?.features?.skipLink;
|
|
8262
|
+
this.destroyRef = inject(DestroyRef);
|
|
7949
8263
|
this.isNoPermission = this.matchesNoPermission(this.router.url);
|
|
7950
8264
|
this.router.events.pipe(filter((e) => e instanceof NavigationEnd), takeUntilDestroyed())
|
|
7951
8265
|
.subscribe(e => { this.isNoPermission = this.matchesNoPermission(e.urlAfterRedirects); });
|
|
@@ -7958,13 +8272,13 @@ class LayoutComponent {
|
|
|
7958
8272
|
void this.accountPreferences.start();
|
|
7959
8273
|
this.idle.start();
|
|
7960
8274
|
this.startPage.track();
|
|
8275
|
+
this.destroyRef.onDestroy(this.unsaved.start());
|
|
7961
8276
|
// Liga os atalhos de teclado globais às ações reais do sistema.
|
|
7962
8277
|
this.shortcuts.setActions({
|
|
7963
8278
|
navigate: (url) => this.router.navigateByUrl(url),
|
|
7964
8279
|
toggleTheme: () => this.theme.setTheme(this.theme.current === 'light' ? 'dark' : 'light'),
|
|
7965
|
-
toggleFullscreen: () => this.toggleFullscreen(),
|
|
7966
|
-
logout: () => void this.logoutService.logout(),
|
|
7967
8280
|
openSettings: () => this.settings.toggle(),
|
|
8281
|
+
toggleSidebar: () => this.toggleSidebar(),
|
|
7968
8282
|
});
|
|
7969
8283
|
// Link direto pra uma seção do painel de configurações: `?settings=aparencia` (ou só
|
|
7970
8284
|
// `?settings`). Tira o parâmetro da URL depois de abrir — senão ele volta a abrir o painel a
|
|
@@ -7979,19 +8293,33 @@ class LayoutComponent {
|
|
|
7979
8293
|
// Novidades do app (argos-admin /me/news): um aviso discreto, uma vez por novidade, depois da configuração inicial.
|
|
7980
8294
|
void this.news.announceOnEntry();
|
|
7981
8295
|
}
|
|
7982
|
-
|
|
7983
|
-
|
|
8296
|
+
/**
|
|
8297
|
+
* `Mod+B`. Tela estreita: a gaveta. Fixo e compacto: troca um pelo outro (é a preferência da pessoa, fica gravada).
|
|
8298
|
+
* Automático: a coluna abre por cima e fica até o próximo `Mod+B`, sem mudar a preferência.
|
|
8299
|
+
*/
|
|
8300
|
+
toggleSidebar() {
|
|
8301
|
+
if (this.isNoPermission)
|
|
8302
|
+
return;
|
|
8303
|
+
if (window.matchMedia?.('(max-width: 767.98px)').matches)
|
|
8304
|
+
this.sidebar.toggleMobile();
|
|
8305
|
+
else if (this.sidebar.mode() === 'auto')
|
|
8306
|
+
this.sidebar.holdOpen(!this.sidebar.expanded());
|
|
8307
|
+
else
|
|
8308
|
+
this.sidebar.setMode(this.sidebar.mode() === 'fixed' ? 'compact' : 'fixed');
|
|
7984
8309
|
}
|
|
7985
|
-
|
|
7986
|
-
|
|
7987
|
-
|
|
7988
|
-
|
|
7989
|
-
else
|
|
7990
|
-
|
|
7991
|
-
}
|
|
8310
|
+
onLocalNavigate(panelId, href) {
|
|
8311
|
+
const allowed = this.unsaved.canReplaceActive(panelId);
|
|
8312
|
+
if (allowed === true)
|
|
8313
|
+
this.workspace.navigateLocally(panelId, href);
|
|
8314
|
+
else
|
|
8315
|
+
void Promise.resolve(allowed).then((ok) => ok && this.workspace.navigateLocally(panelId, href));
|
|
7992
8316
|
}
|
|
7993
8317
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: LayoutComponent, deps: [{ token: i3.Router }, { token: i2$1.ThemeService }, { token: ShortcutService }, { token: SpineNewsService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7994
8318
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: LayoutComponent, isStandalone: true, selector: "spine-layout", ngImport: i0, template: `
|
|
8319
|
+
<!-- "Pular para o conteúdo" (SpineFeatures.skipLink): primeira parada do Tab. -->
|
|
8320
|
+
@if (skipLink) {
|
|
8321
|
+
<hm-skip-link target="spine-main" />
|
|
8322
|
+
}
|
|
7995
8323
|
<div class="shell" [attr.inert]="setup.isOpen() ? '' : null">
|
|
7996
8324
|
<spine-header></spine-header>
|
|
7997
8325
|
<!-- Aviso de conexão do @orfeu/angular (offline/reconectando/reautorizando): faixa entre o header e o corpo. -->
|
|
@@ -8000,9 +8328,10 @@ class LayoutComponent {
|
|
|
8000
8328
|
@if (!isNoPermission) {
|
|
8001
8329
|
<spine-sidebar class="sidebar"></spine-sidebar>
|
|
8002
8330
|
}
|
|
8003
|
-
<div class="main" role="main">
|
|
8331
|
+
<div class="main" role="main" [attr.id]="skipLink ? 'spine-main' : null">
|
|
8004
8332
|
<div [hidden]="isNoPermission" class="workspace-area">
|
|
8005
|
-
|
|
8333
|
+
<!-- Dividir em painéis só com a preferência "Dividir abas" ligada (desligada por padrão), até 2 × 2. -->
|
|
8334
|
+
<hm-workspace [keepAlive]="true" [split]="workspace.split()" [maxColumns]="workspace.limits.maxColumns ?? null" [maxRows]="workspace.limits.maxRows ?? null" [providedStore]="unsaved.store" (newTabRequested)="workspace.openNewTab($event)">
|
|
8006
8335
|
<ng-template #content let-tab let-panelId="panelId" let-active="active">
|
|
8007
8336
|
<div
|
|
8008
8337
|
class="panel-content"
|
|
@@ -8034,7 +8363,7 @@ class LayoutComponent {
|
|
|
8034
8363
|
}
|
|
8035
8364
|
<!-- Aviso de "Encerrar por inatividade" (SpineFeatures.idleTimeout): só desenha quando abre. -->
|
|
8036
8365
|
<spine-idle-warning />
|
|
8037
|
-
`, isInline: true, styles: [":host{display:block}.shell{display:flex;flex-direction:column;height:100vh;height:100dvh;background:var(--hm-surface);color:var(--hm-text)}.body{position:relative;display:flex;flex:1;min-height:0;overflow:hidden}.main{display:flex;flex:1;min-width:0;flex-direction:column}.workspace-area{flex:1;min-height:0;display:flex;flex-direction:column;--hm-tab-strip-bg: var(--hm-shell-tab-strip-bg);--hm-tab-active-bg: var(--hm-surface-raised)}hm-workspace{flex:1;min-height:0}.panel-content{display:flex;flex-direction:column;height:100%;min-height:0}\n"], dependencies: [{ kind: "component", type: SpineNewsComponent, selector: "spine-news" }, { kind: "component", type: SpineDocsComponent, selector: "spine-docs" }, { kind: "component", type: HeaderComponent, selector: "spine-header" }, { kind: "component", type: SidebarComponent, selector: "spine-sidebar" }, { kind: "component", type: SpineConnectionBannerComponent, selector: "spine-connection-banner" }, { kind: "component", type: SpinePagePanelComponent, selector: "spine-page-panel", inputs: ["url", "isFocusedPanel", "tabId", "panelId"] }, { kind: "directive", type: PanelLocalLinkDirective, selector: "[appPanelLocalLink]", inputs: ["appPanelLocalLink"], outputs: ["localNavigate"] }, { kind: "component", type: WorkspaceComponent, selector: "hm-workspace", inputs: ["initialTabs", "initialActiveId", "keepAlive", "label", "providedStore"], outputs: ["stateChange", "newTabRequested"] }, { kind: "component", type: ToastStackComponent, selector: "hm-toast-stack", inputs: ["position", "expand", "visibleToasts"] }, { kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: ModalComponent$1, selector: "spine-modal" }, { kind: "component", type: SidePanelComponent, selector: "spine-side-panel" }, { kind: "component", type: SpineInitialSetupComponent, selector: "spine-initial-setup" }, { kind: "component", type: ShortcutsCheatsheetComponent, selector: "spine-shortcuts-cheatsheet" }, { kind: "component", type: SettingsPanelComponent, selector: "spine-settings-panel" }, { kind: "component", type: SpineIdleWarningComponent, selector: "spine-idle-warning" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
8366
|
+
`, isInline: true, styles: [":host{display:block}.shell{display:flex;flex-direction:column;height:100vh;height:100dvh;background:var(--hm-surface);color:var(--hm-text)}.body{position:relative;display:flex;flex:1;min-height:0;overflow:hidden}.main{display:flex;flex:1;min-width:0;flex-direction:column}.workspace-area{flex:1;min-height:0;display:flex;flex-direction:column;--hm-tab-strip-bg: var(--hm-shell-tab-strip-bg);--hm-tab-active-bg: var(--hm-surface-raised)}hm-workspace{flex:1;min-height:0}.panel-content{display:flex;flex-direction:column;height:100%;min-height:0}\n"], dependencies: [{ kind: "component", type: SpineNewsComponent, selector: "spine-news" }, { kind: "component", type: SpineDocsComponent, selector: "spine-docs" }, { kind: "component", type: HeaderComponent, selector: "spine-header" }, { kind: "component", type: SidebarComponent, selector: "spine-sidebar" }, { kind: "component", type: SpineConnectionBannerComponent, selector: "spine-connection-banner" }, { kind: "component", type: SpinePagePanelComponent, selector: "spine-page-panel", inputs: ["url", "isFocusedPanel", "tabId", "panelId"] }, { kind: "directive", type: PanelLocalLinkDirective, selector: "[appPanelLocalLink]", inputs: ["appPanelLocalLink"], outputs: ["localNavigate"] }, { kind: "component", type: WorkspaceComponent, selector: "hm-workspace", inputs: ["initialTabs", "initialActiveId", "keepAlive", "split", "maxColumns", "maxRows", "label", "providedStore"], outputs: ["stateChange", "newTabRequested"] }, { kind: "component", type: ToastStackComponent, selector: "hm-toast-stack", inputs: ["position", "expand", "visibleToasts"] }, { kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: ModalComponent$1, selector: "spine-modal" }, { kind: "component", type: SidePanelComponent, selector: "spine-side-panel" }, { kind: "component", type: SpineInitialSetupComponent, selector: "spine-initial-setup" }, { kind: "component", type: ShortcutsCheatsheetComponent, selector: "spine-shortcuts-cheatsheet" }, { kind: "component", type: SettingsPanelComponent, selector: "spine-settings-panel" }, { kind: "component", type: SpineIdleWarningComponent, selector: "spine-idle-warning" }, { kind: "component", type: SkipLinkComponent, selector: "hm-skip-link", inputs: ["target", "label", "texts"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
8038
8367
|
}
|
|
8039
8368
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: LayoutComponent, decorators: [{
|
|
8040
8369
|
type: Component,
|
|
@@ -8055,7 +8384,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImpo
|
|
|
8055
8384
|
ShortcutsCheatsheetComponent,
|
|
8056
8385
|
SettingsPanelComponent,
|
|
8057
8386
|
SpineIdleWarningComponent,
|
|
8387
|
+
SkipLinkComponent,
|
|
8058
8388
|
], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
8389
|
+
<!-- "Pular para o conteúdo" (SpineFeatures.skipLink): primeira parada do Tab. -->
|
|
8390
|
+
@if (skipLink) {
|
|
8391
|
+
<hm-skip-link target="spine-main" />
|
|
8392
|
+
}
|
|
8059
8393
|
<div class="shell" [attr.inert]="setup.isOpen() ? '' : null">
|
|
8060
8394
|
<spine-header></spine-header>
|
|
8061
8395
|
<!-- Aviso de conexão do @orfeu/angular (offline/reconectando/reautorizando): faixa entre o header e o corpo. -->
|
|
@@ -8064,9 +8398,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImpo
|
|
|
8064
8398
|
@if (!isNoPermission) {
|
|
8065
8399
|
<spine-sidebar class="sidebar"></spine-sidebar>
|
|
8066
8400
|
}
|
|
8067
|
-
<div class="main" role="main">
|
|
8401
|
+
<div class="main" role="main" [attr.id]="skipLink ? 'spine-main' : null">
|
|
8068
8402
|
<div [hidden]="isNoPermission" class="workspace-area">
|
|
8069
|
-
|
|
8403
|
+
<!-- Dividir em painéis só com a preferência "Dividir abas" ligada (desligada por padrão), até 2 × 2. -->
|
|
8404
|
+
<hm-workspace [keepAlive]="true" [split]="workspace.split()" [maxColumns]="workspace.limits.maxColumns ?? null" [maxRows]="workspace.limits.maxRows ?? null" [providedStore]="unsaved.store" (newTabRequested)="workspace.openNewTab($event)">
|
|
8070
8405
|
<ng-template #content let-tab let-panelId="panelId" let-active="active">
|
|
8071
8406
|
<div
|
|
8072
8407
|
class="panel-content"
|
|
@@ -8261,7 +8596,7 @@ class SpineSuggestionChatComponent {
|
|
|
8261
8596
|
<ng-content select="[spineChatReadOnly]" />
|
|
8262
8597
|
}
|
|
8263
8598
|
</div>
|
|
8264
|
-
`, isInline: true, styles: [":host{display:block;min-inline-size:0}.spine-chat{display:flex;flex-direction:column;block-size:var(--spine-chat-height, min(70dvh, 44rem));overflow:hidden;border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius);background:var(--hm-surface)}.spine-chat__scroller{flex:1 1 auto;min-block-size:0}.spine-chat__text{white-space:pre-line;overflow-wrap:anywhere}.spine-chat__tags{display:inline-flex;flex-wrap:wrap;gap:var(--hm-space-xxxs)}.spine-chat__internal{display:inline-flex;margin-inline-end:var(--hm-space-micro);color:var(--hm-warning);vertical-align:-.125em}.spine-chat__internal hm-icon{--hm-icon-size: .875rem}.spine-chat__sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}.spine-chat__empty{margin:auto;padding:var(--hm-space-md);color:var(--hm-muted);font-size:var(--hm-font-size-sm);text-align:center}.spine-chat__composer{display:flex;flex-wrap:wrap;align-items:flex-end;gap:var(--hm-space-xs);padding:var(--hm-space-xs) var(--hm-space-sm);border-block-start:var(--hm-border-hairline) solid var(--hm-border)}.spine-chat__field{flex:1 1 16rem;min-inline-size:0}.spine-chat__actions{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:var(--hm-space-sm)}\n"], dependencies: [{ kind: "component", type: BubbleComponent, selector: "hm-bubble", inputs: ["variant", "reactions", "typing"], outputs: ["reactionToggle"] }, { kind: "component", type: ButtonComponent, selector: "hm-button", inputs: ["emphasis", "intent", "size", "type", "icon", "iconDirection", "iconEnd", "disabled", "loading", "loadingState", "block", "link", "newTab", "caret", "inMenu", "toggle", "pressed"], outputs: ["loadingStateChange", "pressedChange", "clicked"] }, { kind: "component", type: IconComponent, selector: "hm-icon", inputs: ["shape", "direction", "size", "solid", "badge", "status", "flip", "inverse", "label"] }, { kind: "directive", type: TooltipDirective, selector: "[hmTooltip]", inputs: ["hmTooltip", "hmTooltipSide", "hmTooltipDisabled", "hmTooltipShowDelay", "hmTooltipHideDelay"] }, { kind: "component", type: MessageComponent, selector: "hm-message", inputs: ["author", "avatarUrl", "time", "timeFormat", "align", "grouped", "showAvatar", "status", "announce"], outputs: ["retry"] }, { kind: "component", type: MessageDividerComponent, selector: "hm-message-divider", inputs: ["label", "icon", "variant"] }, { kind: "component", type: MessageScrollerComponent, selector: "hm-message-scroller", inputs: ["label", "hasMoreHistory", "loadingHistory", "autoLoadHistory", "live", "itemSelector", "threshold"], outputs: ["loadHistory", "atEndChange"] }, { kind: "component", type: TagComponent, selector: "hm-tag", inputs: ["name", "color", "compact"] }, { kind: "component", type: TextareaComponent, selector: "hm-textarea", inputs: ["value", "label", "hint", "placeholder", "maxLength", "rows", "autoGrow", "labelHidden", "loading", "maxRows", "submitKey"], outputs: ["valueChange", "submitted"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
8599
|
+
`, isInline: true, styles: [":host{display:block;min-inline-size:0}.spine-chat{display:flex;flex-direction:column;block-size:var(--spine-chat-height, min(70dvh, 44rem));overflow:hidden;border:var(--hm-border-hairline) solid var(--hm-border);border-radius:var(--hm-radius);background:var(--hm-surface)}.spine-chat__scroller{flex:1 1 auto;min-block-size:0}.spine-chat__text{white-space:pre-line;overflow-wrap:anywhere}.spine-chat__tags{display:inline-flex;flex-wrap:wrap;gap:var(--hm-space-xxxs)}.spine-chat__internal{display:inline-flex;margin-inline-end:var(--hm-space-micro);color:var(--hm-warning);vertical-align:-.125em}.spine-chat__internal hm-icon{--hm-icon-size: .875rem}.spine-chat__sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}.spine-chat__empty{margin:auto;padding:var(--hm-space-md);color:var(--hm-muted);font-size:var(--hm-font-size-sm);text-align:center}.spine-chat__composer{display:flex;flex-wrap:wrap;align-items:flex-end;gap:var(--hm-space-xs);padding:var(--hm-space-xs) var(--hm-space-sm);border-block-start:var(--hm-border-hairline) solid var(--hm-border)}.spine-chat__field{flex:1 1 16rem;min-inline-size:0}.spine-chat__actions{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:var(--hm-space-sm)}\n"], dependencies: [{ kind: "component", type: BubbleComponent, selector: "hm-bubble", inputs: ["variant", "reactions", "typing"], outputs: ["reactionToggle"] }, { kind: "component", type: ButtonComponent, selector: "hm-button", inputs: ["emphasis", "intent", "size", "type", "icon", "iconDirection", "iconEnd", "disabled", "loading", "loadingState", "block", "link", "newTab", "caret", "inMenu", "toggle", "pressed"], outputs: ["loadingStateChange", "pressedChange", "clicked"] }, { kind: "component", type: IconComponent, selector: "hm-icon", inputs: ["shape", "direction", "size", "solid", "badge", "status", "flip", "inverse", "label"] }, { kind: "directive", type: TooltipDirective, selector: "[hmTooltip]", inputs: ["hmTooltip", "hmTooltipSide", "hmTooltipDisabled", "hmTooltipShowDelay", "hmTooltipHideDelay"] }, { kind: "component", type: MessageComponent, selector: "hm-message", inputs: ["author", "avatarUrl", "time", "timeFormat", "align", "grouped", "showAvatar", "status", "announce", "reactions", "reactionChoices", "texts"], outputs: ["retry", "reactionToggle"] }, { kind: "component", type: MessageDividerComponent, selector: "hm-message-divider", inputs: ["label", "icon", "variant"] }, { kind: "component", type: MessageScrollerComponent, selector: "hm-message-scroller", inputs: ["label", "hasMoreHistory", "loadingHistory", "autoLoadHistory", "live", "itemSelector", "threshold"], outputs: ["loadHistory", "atEndChange"] }, { kind: "component", type: TagComponent, selector: "hm-tag", inputs: ["name", "color", "compact"] }, { kind: "component", type: TextareaComponent, selector: "hm-textarea", inputs: ["value", "label", "hint", "placeholder", "maxLength", "rows", "autoGrow", "labelHidden", "loading", "maxRows", "submitKey", "mentionCandidates", "mentionTrigger", "texts"], outputs: ["valueChange", "submitted", "mentioned"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
8265
8600
|
}
|
|
8266
8601
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: SpineSuggestionChatComponent, decorators: [{
|
|
8267
8602
|
type: Component,
|
|
@@ -8425,5 +8760,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImpo
|
|
|
8425
8760
|
* Generated bundle index. Do not edit.
|
|
8426
8761
|
*/
|
|
8427
8762
|
|
|
8428
|
-
export {
|
|
8429
|
-
//# sourceMappingURL=trismegisto-spine-layout-trismegisto-spine-layout-
|
|
8763
|
+
export { SpineConnectionBannerComponent as $, AiAgentComponent as A, SPINE_INBOX_SOURCES as B, SPINE_MARKDOWN_PURIFY_CONFIG as C, SPINE_PREFERENCES_SAVE_DELAY_MS as D, SPINE_RATING_COMMENT_MAX as E, SPINE_RATING_SCORE_MAX as F, SPINE_SETTINGS_ALIASES as G, HeaderComponent as H, SPINE_SETTINGS_KEYS as I, SPINE_SETTINGS_SECTIONS as J, SPINE_SUGGESTIONS_PAGE_ID as K, LayoutComponent as L, SPINE_SUGGESTION_LIMITS as M, NEW_SCREEN_VALUE as N, SPINE_SUGGESTION_PUBLIC_SORTS as O, SPINE_SUGGESTION_PUBLIC_STATUSES as P, SPINE_SUGGESTION_STATUS_ICONS as Q, SPINE_WORKSPACE_LIMITS as R, SpineSuggestionsService as S, SettingsPanelComponent as T, ShortcutService as U, ShortcutsCheatsheetComponent as V, SidebarComponent as W, SpineAccountPreferencesService as X, SpineAccountSecurityService as Y, SpineAppTokensService as Z, SpineBrandComponent as _, SpineInboxService as a, SpineDocsComponent as a0, SpineDocsService as a1, SpineIdleService as a2, SpineIdleWarningComponent as a3, SpineInboxButtonComponent as a4, SpineInitialSetupComponent as a5, SpineInitialSetupService as a6, SpineLogoutService as a7, SpineMarkdownComponent as a8, SpineMyGroupsService as a9, spinePathOf as aA, spineScoreBand as aB, spineStarFills as aC, spineSuggestionsEnabled as aD, spineTagColor as aE, stable as aF, SpineNewsComponent as aa, SpineNewsService as ab, SpineNoticesService as ac, SpinePageActionsDirective as ad, SpinePageActionsSlot as ae, SpineRatingStarsComponent as af, SpineRatingsService as ag, SpineSettingsService as ah, SpineStartPageService as ai, SpineUnsavedChangesService as aj, SpineWorkspaceNavService as ak, accountErrorCode as al, argosAccountApi as am, buildMcpConfig as an, effectiveIdleMinutes as ao, idleLimits as ap, isInternalPath as aq, provideSettingsSection as ar, provideSpineInboxSource as as, provideSpineSuggestionsPage as at, ratingTargetKey as au, registerSpineUnsavedChanges as av, resolveSettingsSection as aw, sanitizeSpineMarkdownHtml as ax, spineNormalizeUrl as ay, spineParamsOf as az, SpineSuggestionChatComponent as b, SPINE_SUGGESTION_STATUS_COLORS as c, SPINE_SUGGESTION_KIND_COLORS as d, SPINE_SUGGESTION_KIND_ICONS as e, SPINE_SUGGESTION_WAITING_COLORS as f, SPINE_SUGGESTION_VISIBLE_SORTS as g, SPINE_SUGGESTION_REASONS as h, SPINE_SUGGESTION_STATUSES as i, SPINE_SUGGESTION_KINDS as j, SPINE_SUGGESTION_WAITING as k, SPINE_TAB as l, SPINE_SUGGESTION_PAGE_PARAM as m, SPINE_SUGGESTION_TAB_PARAM as n, SPINE_SUGGESTION_TAB_CONVERSATION as o, screenName as p, screenModule as q, SPINE_SUGGESTIONS_PAGE_PATH as r, suggestionScreens as s, SpineSuggestionsDialogComponent as t, SpineTagRowComponent as u, AppLauncherComponent as v, SPINE_BRAND as w, SPINE_GLOBAL_PREFERENCE_KEYS as x, SPINE_IDLE_WARNING_SECONDS as y, SPINE_INBOX_POLL_MS as z };
|
|
8764
|
+
//# sourceMappingURL=trismegisto-spine-layout-trismegisto-spine-layout-DiAfxIGP.mjs.map
|