valtech-components 2.0.1006 → 2.0.1008
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/esm2022/lib/components/molecules/comment/comment.component.mjs +3 -3
- package/esm2022/lib/components/organisms/profile-view/profile-view.component.mjs +6 -16
- package/esm2022/lib/components/templates/auth-background/auth-background.component.mjs +19 -17
- package/esm2022/lib/services/preferences/preferences.service.mjs +36 -11
- package/esm2022/lib/version.mjs +2 -2
- package/esm2022/public-api.mjs +1 -4
- package/fesm2022/valtech-components.mjs +368 -885
- package/fesm2022/valtech-components.mjs.map +1 -1
- package/lib/components/templates/auth-background/auth-background.component.d.ts +2 -2
- package/lib/version.d.ts +1 -1
- package/package.json +1 -1
- package/public-api.d.ts +0 -3
- package/esm2022/lib/components/organisms/about-view/about-view.component.mjs +0 -436
- package/esm2022/lib/components/organisms/about-view/about-view.i18n.mjs +0 -61
- package/esm2022/lib/components/organisms/about-view/about.routes.mjs +0 -36
- package/esm2022/lib/components/organisms/about-view/types.mjs +0 -19
- package/lib/components/organisms/about-view/about-view.component.d.ts +0 -88
- package/lib/components/organisms/about-view/about-view.i18n.d.ts +0 -14
- package/lib/components/organisms/about-view/about.routes.d.ts +0 -31
- package/lib/components/organisms/about-view/types.d.ts +0 -76
|
@@ -25,7 +25,7 @@ import { getApps, getApp, initializeApp as initializeApp$1 } from 'firebase/app'
|
|
|
25
25
|
import * as i2$1 from '@ionic/angular/standalone';
|
|
26
26
|
import { AlertController, IonAvatar, IonCard, IonIcon, IonButton, IonSpinner, IonText, IonModal, IonHeader, IonToolbar, IonContent, IonButtons, IonTitle, IonProgressBar, IonSkeletonText, IonFab, IonFabButton, IonFabList, IonLabel, IonCardContent, IonCardHeader, IonCardTitle, IonCardSubtitle, IonCheckbox, IonTextarea, IonDatetime, IonInput, IonSelect, IonSelectOption, IonPopover, IonList, IonItem, IonRadioGroup, IonRadio, IonRange, IonSearchbar, IonSegment, IonSegmentButton, IonToggle, IonRippleEffect, IonAccordion, IonAccordionGroup, IonTabBar, IonTabButton, IonBadge, IonBreadcrumb, IonBreadcrumbs, IonChip, IonNote, IonDatetimeButton, ToastController as ToastController$1, IonCol, IonRow, IonRefresher, IonRefresherContent, IonMenuButton, IonFooter, IonListHeader, IonInfiniteScroll, IonInfiniteScrollContent, IonGrid, MenuController, IonMenu, IonMenuToggle, IonSplitPane } from '@ionic/angular/standalone';
|
|
27
27
|
import { addIcons } from 'ionicons';
|
|
28
|
-
import { addOutline, addCircleOutline, alertOutline, alertCircleOutline, arrowBackOutline, arrowForwardOutline, arrowDownOutline, settings, settingsOutline, checkmarkCircleOutline, ellipsisHorizontalOutline, notifications, notificationsOutline, openOutline, closeOutline, chatbubblesOutline, shareOutline, heart, heartOutline, home, homeOutline, eyeOffOutline, eyeOutline, scanOutline, chevronDownOutline, chevronForwardOutline, checkmarkOutline, clipboardOutline, copyOutline, filterOutline, locationOutline, calendarOutline, businessOutline, logoTwitter, logoInstagram, logoLinkedin, logoYoutube, logoTiktok, logoFacebook, logoGoogle, createOutline, trashOutline, playOutline, peopleOutline, phonePortraitOutline, refreshOutline, documentTextOutline, lockClosedOutline, informationCircleOutline, logoNpm, removeOutline, optionsOutline, personOutline, shieldCheckmarkOutline, keyOutline, desktopOutline, logOutOutline, cloudDownloadOutline, cloudOutline, gitBranchOutline, layersOutline, serverOutline, warningOutline, bulbOutline, lockOpenOutline, diamondOutline, add, close, share, create, trash, star, camera, mic, send, downloadOutline, chevronDown, language, globeOutline, checkmark, list, grid, apps, menu, search, person, helpCircle, informationCircle, documentText, mail, calendar, folder, chevronForward, ellipsisHorizontal, chevronBack, playBack, playForward, ellipse, starOutline, starHalf, heartHalf, checkmarkCircle, timeOutline, flag, trendingUp, trendingDown, remove, analytics, people, cash, cart, eye, chatbubbleOutline, thumbsUpOutline, thumbsUp, happyOutline, happy, sadOutline, sad, chevronUp, pin, pencil, callOutline, logoWhatsapp, paperPlaneOutline, mailOutline, chevronDownCircleOutline, closeCircle, alertCircle, logoApple, logoMicrosoft, linkOutline, unlinkOutline, cloudOfflineOutline, documentOutline, attachOutline, cameraOutline, closeCircleOutline, imageOutline, chevronBackOutline, sendOutline, chatbubbleEllipsesOutline, swapVerticalOutline, chevronUpOutline, searchOutline, cartOutline, chatbubble, compass, compassOutline, gridOutline, listOutline, folderOutline, documents, documentsOutline, statsChart, statsChartOutline, laptopOutline, swapHorizontalOutline, notificationsOffOutline, alarmOutline, chatboxEllipsesOutline, checkmarkDoneOutline, cogOutline,
|
|
28
|
+
import { addOutline, addCircleOutline, alertOutline, alertCircleOutline, arrowBackOutline, arrowForwardOutline, arrowDownOutline, settings, settingsOutline, checkmarkCircleOutline, ellipsisHorizontalOutline, notifications, notificationsOutline, openOutline, closeOutline, chatbubblesOutline, shareOutline, heart, heartOutline, home, homeOutline, eyeOffOutline, eyeOutline, scanOutline, chevronDownOutline, chevronForwardOutline, checkmarkOutline, clipboardOutline, copyOutline, filterOutline, locationOutline, calendarOutline, businessOutline, logoTwitter, logoInstagram, logoLinkedin, logoYoutube, logoTiktok, logoFacebook, logoGoogle, createOutline, trashOutline, playOutline, peopleOutline, phonePortraitOutline, refreshOutline, documentTextOutline, lockClosedOutline, informationCircleOutline, logoNpm, removeOutline, optionsOutline, personOutline, shieldCheckmarkOutline, keyOutline, desktopOutline, logOutOutline, cloudDownloadOutline, cloudOutline, gitBranchOutline, layersOutline, serverOutline, warningOutline, bulbOutline, lockOpenOutline, diamondOutline, add, close, share, create, trash, star, camera, mic, send, downloadOutline, chevronDown, language, globeOutline, checkmark, list, grid, apps, menu, search, person, helpCircle, informationCircle, documentText, mail, calendar, folder, chevronForward, ellipsisHorizontal, chevronBack, playBack, playForward, ellipse, starOutline, starHalf, heartHalf, checkmarkCircle, timeOutline, flag, trendingUp, trendingDown, remove, analytics, people, cash, cart, eye, chatbubbleOutline, thumbsUpOutline, thumbsUp, happyOutline, happy, sadOutline, sad, chevronUp, pin, pencil, callOutline, logoWhatsapp, paperPlaneOutline, mailOutline, chevronDownCircleOutline, closeCircle, alertCircle, logoApple, logoMicrosoft, linkOutline, unlinkOutline, cloudOfflineOutline, documentOutline, attachOutline, cameraOutline, closeCircleOutline, imageOutline, chevronBackOutline, sendOutline, chatbubbleEllipsesOutline, swapVerticalOutline, chevronUpOutline, searchOutline, cartOutline, chatbubble, compass, compassOutline, gridOutline, listOutline, folderOutline, documents, documentsOutline, statsChart, statsChartOutline, laptopOutline, swapHorizontalOutline, notificationsOffOutline, alarmOutline, chatboxEllipsesOutline, checkmarkDoneOutline, cogOutline, menuOutline } from 'ionicons/icons';
|
|
29
29
|
import { Browser } from '@capacitor/browser';
|
|
30
30
|
import * as i1$6 from '@angular/platform-browser';
|
|
31
31
|
import { DomSanitizer, Meta, Title } from '@angular/platform-browser';
|
|
@@ -54,7 +54,7 @@ import 'prismjs/components/prism-json';
|
|
|
54
54
|
* Current version of valtech-components.
|
|
55
55
|
* This is automatically updated during the publish process.
|
|
56
56
|
*/
|
|
57
|
-
const VERSION = '2.0.
|
|
57
|
+
const VERSION = '2.0.1008';
|
|
58
58
|
|
|
59
59
|
// Control de estado de refresco (singleton a nivel de módulo)
|
|
60
60
|
let isRefreshing = false;
|
|
@@ -21657,7 +21657,7 @@ class CommentComponent {
|
|
|
21657
21657
|
</div>
|
|
21658
21658
|
}
|
|
21659
21659
|
</div>
|
|
21660
|
-
`, isInline: true, styles: [":host{display:block}.comment{--indent-size: 24px;--max-indent: 72px;padding:12px 0}.comment.highlighted{background-color:rgba(var(--ion-color-primary-rgb),.08);border-radius:8px;padding:12px;margin:-4px}.comment.pinned{border-left:3px solid var(--ion-color-primary);padding-left:12px}.comment.collapsed{opacity:.7}.pinned-indicator{display:flex;align-items:center;gap:4px;font-size:.75rem;color:var(--ion-color-primary);margin-bottom:8px;padding-left:44px}.pinned-indicator ion-icon{font-size:.875rem}.comment-main{display:flex;gap:12px}.comment-avatar{flex-shrink:0;cursor:pointer}.comment-avatar val-avatar{--size: 36px}.comment-avatar .avatar-placeholder{width:36px;height:36px;border-radius:50%;background:linear-gradient(135deg,var(--ion-color-primary),var(--ion-color-secondary));display:flex;align-items:center;justify-content:center;color:#fff;font-size:.875rem;font-weight:600}.comment-body{flex:1;min-width:0}.comment-header{display:flex;align-items:center;flex-wrap:wrap;gap:6px;margin-bottom:4px}.author-info{display:flex;align-items:center;gap:4px;cursor:pointer}.author-info:hover .author-name{text-decoration:underline}.author-name{font-weight:600;font-size:.875rem;color:var(--ion-text-color)}.verified-badge{color:var(--ion-color-primary);font-size:1rem}.author-username{font-size:.8125rem;color:var(--ion-color-medium)}.comment-meta{display:flex;align-items:center;gap:6px;margin-left:auto}.timestamp{font-size:.75rem;color:var(--ion-color-medium)}.edited-label{font-size:.6875rem;color:var(--ion-color-medium);font-style:italic}.more-button{--padding-start: 4px;--padding-end: 4px;margin:0;height:28px}.more-button ion-icon{font-size:1.125rem;color:var(--ion-color-medium)}.menu-divider{height:1px;background-color:var(--ion-color-light);margin:4px 0}.comment-content{font-size:.875rem;line-height:1.5;color:var(--ion-text-color);word-wrap:break-word;overflow-wrap:break-word}.comment-content :global(.comment-link){color:var(--ion-color-primary);text-decoration:none}.comment-content :global(.comment-link):hover{text-decoration:underline}.comment-content :global(.comment-mention){color:var(--ion-color-primary);font-weight:500;cursor:pointer}.comment-content :global(.comment-mention):hover{text-decoration:underline}.comment-content :global(.comment-hashtag){color:var(--ion-color-primary);cursor:pointer}.comment-content :global(.comment-hashtag):hover{text-decoration:underline}.comment-reactions{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}.reaction-button{display:flex;align-items:center;gap:4px;background:none;border:none;padding:4px 8px;border-radius:16px;cursor:pointer;font-size:.8125rem;color:var(--reaction-color, var(--ion-color-medium));transition:all .2s ease;background-color:transparent}.reaction-button:hover{background-color:rgba(var(--ion-color-medium-rgb),.1)}.reaction-button.active{background-color:rgba(var(--ion-color-primary-rgb),.1)}.reaction-button.active ion-icon{transform:scale(1.1)}.reaction-button ion-icon{font-size:1.125rem;transition:transform .2s ease}.reaction-button .reaction-count{font-weight:500}.comment-actions{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px;margin-left:-8px}.comment-actions ion-button{--padding-start: 8px;--padding-end: 8px;font-size:.8125rem;height:32px;text-transform:none;font-weight:500}.expand-button,.collapse-button,.load-more-button,.view-replies-button{display:flex;align-items:center;gap:6px;background:none;border:none;padding:8px 12px;cursor:pointer;font-size:.8125rem;color:var(--ion-color-primary);border-radius:8px;transition:background-color .2s}.expand-button:hover,.collapse-button:hover,.load-more-button:hover,.view-replies-button:hover{background-color:rgba(var(--ion-color-primary-rgb),.1)}.expand-button ion-icon,.collapse-button ion-icon,.load-more-button ion-icon,.view-replies-button ion-icon{font-size:1rem}.expand-button{margin-top:4px;color:var(--ion-color-medium)}.comment-children{margin-top:12px;padding-left:min(var(--indent-size),var(--max-indent));border-left:2px solid var(--ion-color-light-shade)}.comment-children val-comment{display:block}.comment-children val-comment:first-of-type .comment{padding-top:0}.load-more-button,.view-replies-button{margin-top:8px;margin-left:0}ion-popover{--width: 200px}ion-popover ion-list{padding:4px 0}ion-popover ion-item{--min-height: 40px;--padding-start: 12px;font-size:.875rem}ion-popover ion-item ion-icon{font-size:1.125rem;margin-right:8px}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 2px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 2px);height:max(28px,36px - 2px);font-size:max(11px,14px - 1px)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 4px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 4px);height:max(28px,36px - 4px);font-size:max(11px,14px - 2px)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 6px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 6px);height:max(28px,36px - 6px);font-size:max(11px,14px - 3px)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 8px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 8px);height:max(28px,36px - 8px);font-size:max(11px,14px - 4px)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 10px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 10px);height:max(28px,36px - 10px);font-size:max(11px,14px - 5px)}:host-context(.dark) .comment.highlighted,:host-context(.ion-palette-dark) .comment.highlighted,:host-context(html.ion-palette-dark) .comment.highlighted,:host-context(body.dark) .comment.highlighted,:host-context([data-theme=dark]) .comment.highlighted{background-color:rgba(var(--ion-color-primary-rgb),.12)}:host-context(.dark) .avatar-placeholder,:host-context(.ion-palette-dark) .avatar-placeholder,:host-context(html.ion-palette-dark) .avatar-placeholder,:host-context(body.dark) .avatar-placeholder,:host-context([data-theme=dark]) .avatar-placeholder{background:linear-gradient(135deg,var(--ion-color-primary-shade),var(--ion-color-secondary-shade))}\n"], dependencies: [{ kind: "component", type: CommentComponent, selector: "val-comment", inputs: ["props"], outputs: ["authorClick", "reactionClick", "actionClick", "menuItemClick", "loadMoreClick", "collapseToggle"] }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonPopover, selector: "ion-popover" }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: AvatarComponent, selector: "val-avatar", inputs: ["preset", "props"], outputs: ["onClick"] }] }); }
|
|
21660
|
+
`, isInline: true, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}:host{display:block}.comment{--indent-size: 24px;--max-indent: 72px;padding:12px 0}.comment.highlighted{background-color:rgba(var(--ion-color-primary-rgb),.08);border-radius:8px;padding:12px;margin:-4px}.comment.pinned{border-left:3px solid var(--ion-color-primary);padding-left:12px}.comment.collapsed{opacity:.7}.pinned-indicator{display:flex;align-items:center;gap:4px;font-size:.75rem;color:var(--ion-color-primary);margin-bottom:8px;padding-left:44px}.pinned-indicator ion-icon{font-size:.875rem}.comment-main{display:flex;gap:12px}.comment-avatar{flex-shrink:0;cursor:pointer}.comment-avatar val-avatar{--size: 36px}.comment-avatar .avatar-placeholder{width:36px;height:36px;border-radius:50%;background:linear-gradient(135deg,var(--ion-color-primary),var(--ion-color-secondary));display:flex;align-items:center;justify-content:center;color:#fff;font-size:.875rem;font-weight:600}.comment-body{flex:1;min-width:0}.comment-header{display:flex;align-items:center;flex-wrap:wrap;gap:6px;margin-bottom:4px}.author-info{display:flex;align-items:center;gap:4px;cursor:pointer}.author-info:hover .author-name{text-decoration:underline}.author-name{font-weight:600;font-size:.875rem;color:var(--ion-text-color)}.verified-badge{color:var(--ion-color-primary);font-size:1rem}.author-username{font-size:.8125rem;color:var(--ion-color-medium)}.comment-meta{display:flex;align-items:center;gap:6px;margin-left:auto}.timestamp{font-size:.75rem;color:var(--ion-color-medium)}.edited-label{font-size:.6875rem;color:var(--ion-color-medium);font-style:italic}.more-button{--padding-start: 4px;--padding-end: 4px;margin:0;height:28px}.more-button ion-icon{font-size:1.125rem;color:var(--ion-color-medium)}.menu-divider{height:1px;background-color:var(--ion-color-light);margin:4px 0}.comment-content{font-size:.875rem;line-height:1.5;color:var(--ion-text-color);word-wrap:break-word;overflow-wrap:break-word}.comment-content :global(.comment-link){color:var(--ion-color-primary);text-decoration:none}.comment-content :global(.comment-link):hover{text-decoration:underline}.comment-content :global(.comment-mention){color:var(--ion-color-primary);font-weight:500;cursor:pointer}.comment-content :global(.comment-mention):hover{text-decoration:underline}.comment-content :global(.comment-hashtag){color:var(--ion-color-primary);cursor:pointer}.comment-content :global(.comment-hashtag):hover{text-decoration:underline}.comment-reactions{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}.reaction-button{display:flex;align-items:center;gap:4px;background:none;border:none;padding:4px 8px;border-radius:16px;cursor:pointer;font-size:.8125rem;color:var(--reaction-color, var(--ion-color-medium));transition:all .2s ease;background-color:transparent}.reaction-button:hover{background-color:rgba(var(--ion-color-medium-rgb),.1)}.reaction-button.active{background-color:rgba(var(--ion-color-primary-rgb),.1)}.reaction-button.active ion-icon{transform:scale(1.1)}.reaction-button ion-icon{font-size:1.125rem;transition:transform .2s ease}.reaction-button .reaction-count{font-weight:500}.comment-actions{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px;margin-left:-8px}.comment-actions ion-button{--padding-start: 8px;--padding-end: 8px;font-size:.8125rem;height:32px;text-transform:none;font-weight:500}.expand-button,.collapse-button,.load-more-button,.view-replies-button{display:flex;align-items:center;gap:6px;background:none;border:none;padding:8px 12px;cursor:pointer;font-size:.8125rem;color:var(--ion-color-primary);border-radius:8px;transition:background-color .2s}.expand-button:hover,.collapse-button:hover,.load-more-button:hover,.view-replies-button:hover{background-color:rgba(var(--ion-color-primary-rgb),.1)}.expand-button ion-icon,.collapse-button ion-icon,.load-more-button ion-icon,.view-replies-button ion-icon{font-size:1rem}.expand-button{margin-top:4px;color:var(--ion-color-medium)}.comment-children{margin-top:12px;padding-left:min(var(--indent-size),var(--max-indent));border-left:2px solid var(--ion-color-light-shade)}.comment-children val-comment{display:block}.comment-children val-comment:first-of-type .comment{padding-top:0}.load-more-button,.view-replies-button{margin-top:8px;margin-left:0}ion-popover{--width: 200px}ion-popover ion-list{padding:4px 0}ion-popover ion-item{--min-height: 40px;--padding-start: 12px;font-size:.875rem}ion-popover ion-item ion-icon{font-size:1.125rem;margin-right:8px}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 2px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 2px);height:max(28px,36px - 2px);font-size:max(.6875rem,.8125rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 4px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 4px);height:max(28px,36px - 4px);font-size:max(.6875rem,.75rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 6px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 6px);height:max(28px,36px - 6px);font-size:max(.6875rem,.6875rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 8px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 8px);height:max(28px,36px - 8px);font-size:max(.6875rem,.625rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 10px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 10px);height:max(28px,36px - 10px);font-size:max(.6875rem,.5625rem)}:host-context(.dark) .comment.highlighted,:host-context(.ion-palette-dark) .comment.highlighted,:host-context(html.ion-palette-dark) .comment.highlighted,:host-context(body.dark) .comment.highlighted,:host-context([data-theme=dark]) .comment.highlighted{background-color:rgba(var(--ion-color-primary-rgb),.12)}:host-context(.dark) .avatar-placeholder,:host-context(.ion-palette-dark) .avatar-placeholder,:host-context(html.ion-palette-dark) .avatar-placeholder,:host-context(body.dark) .avatar-placeholder,:host-context([data-theme=dark]) .avatar-placeholder{background:linear-gradient(135deg,var(--ion-color-primary-shade),var(--ion-color-secondary-shade))}\n"], dependencies: [{ kind: "component", type: CommentComponent, selector: "val-comment", inputs: ["props"], outputs: ["authorClick", "reactionClick", "actionClick", "menuItemClick", "loadMoreClick", "collapseToggle"] }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonPopover, selector: "ion-popover" }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: AvatarComponent, selector: "val-avatar", inputs: ["preset", "props"], outputs: ["onClick"] }] }); }
|
|
21661
21661
|
}
|
|
21662
21662
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CommentComponent, decorators: [{
|
|
21663
21663
|
type: Component,
|
|
@@ -21847,7 +21847,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
21847
21847
|
</div>
|
|
21848
21848
|
}
|
|
21849
21849
|
</div>
|
|
21850
|
-
`, styles: [":host{display:block}.comment{--indent-size: 24px;--max-indent: 72px;padding:12px 0}.comment.highlighted{background-color:rgba(var(--ion-color-primary-rgb),.08);border-radius:8px;padding:12px;margin:-4px}.comment.pinned{border-left:3px solid var(--ion-color-primary);padding-left:12px}.comment.collapsed{opacity:.7}.pinned-indicator{display:flex;align-items:center;gap:4px;font-size:.75rem;color:var(--ion-color-primary);margin-bottom:8px;padding-left:44px}.pinned-indicator ion-icon{font-size:.875rem}.comment-main{display:flex;gap:12px}.comment-avatar{flex-shrink:0;cursor:pointer}.comment-avatar val-avatar{--size: 36px}.comment-avatar .avatar-placeholder{width:36px;height:36px;border-radius:50%;background:linear-gradient(135deg,var(--ion-color-primary),var(--ion-color-secondary));display:flex;align-items:center;justify-content:center;color:#fff;font-size:.875rem;font-weight:600}.comment-body{flex:1;min-width:0}.comment-header{display:flex;align-items:center;flex-wrap:wrap;gap:6px;margin-bottom:4px}.author-info{display:flex;align-items:center;gap:4px;cursor:pointer}.author-info:hover .author-name{text-decoration:underline}.author-name{font-weight:600;font-size:.875rem;color:var(--ion-text-color)}.verified-badge{color:var(--ion-color-primary);font-size:1rem}.author-username{font-size:.8125rem;color:var(--ion-color-medium)}.comment-meta{display:flex;align-items:center;gap:6px;margin-left:auto}.timestamp{font-size:.75rem;color:var(--ion-color-medium)}.edited-label{font-size:.6875rem;color:var(--ion-color-medium);font-style:italic}.more-button{--padding-start: 4px;--padding-end: 4px;margin:0;height:28px}.more-button ion-icon{font-size:1.125rem;color:var(--ion-color-medium)}.menu-divider{height:1px;background-color:var(--ion-color-light);margin:4px 0}.comment-content{font-size:.875rem;line-height:1.5;color:var(--ion-text-color);word-wrap:break-word;overflow-wrap:break-word}.comment-content :global(.comment-link){color:var(--ion-color-primary);text-decoration:none}.comment-content :global(.comment-link):hover{text-decoration:underline}.comment-content :global(.comment-mention){color:var(--ion-color-primary);font-weight:500;cursor:pointer}.comment-content :global(.comment-mention):hover{text-decoration:underline}.comment-content :global(.comment-hashtag){color:var(--ion-color-primary);cursor:pointer}.comment-content :global(.comment-hashtag):hover{text-decoration:underline}.comment-reactions{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}.reaction-button{display:flex;align-items:center;gap:4px;background:none;border:none;padding:4px 8px;border-radius:16px;cursor:pointer;font-size:.8125rem;color:var(--reaction-color, var(--ion-color-medium));transition:all .2s ease;background-color:transparent}.reaction-button:hover{background-color:rgba(var(--ion-color-medium-rgb),.1)}.reaction-button.active{background-color:rgba(var(--ion-color-primary-rgb),.1)}.reaction-button.active ion-icon{transform:scale(1.1)}.reaction-button ion-icon{font-size:1.125rem;transition:transform .2s ease}.reaction-button .reaction-count{font-weight:500}.comment-actions{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px;margin-left:-8px}.comment-actions ion-button{--padding-start: 8px;--padding-end: 8px;font-size:.8125rem;height:32px;text-transform:none;font-weight:500}.expand-button,.collapse-button,.load-more-button,.view-replies-button{display:flex;align-items:center;gap:6px;background:none;border:none;padding:8px 12px;cursor:pointer;font-size:.8125rem;color:var(--ion-color-primary);border-radius:8px;transition:background-color .2s}.expand-button:hover,.collapse-button:hover,.load-more-button:hover,.view-replies-button:hover{background-color:rgba(var(--ion-color-primary-rgb),.1)}.expand-button ion-icon,.collapse-button ion-icon,.load-more-button ion-icon,.view-replies-button ion-icon{font-size:1rem}.expand-button{margin-top:4px;color:var(--ion-color-medium)}.comment-children{margin-top:12px;padding-left:min(var(--indent-size),var(--max-indent));border-left:2px solid var(--ion-color-light-shade)}.comment-children val-comment{display:block}.comment-children val-comment:first-of-type .comment{padding-top:0}.load-more-button,.view-replies-button{margin-top:8px;margin-left:0}ion-popover{--width: 200px}ion-popover ion-list{padding:4px 0}ion-popover ion-item{--min-height: 40px;--padding-start: 12px;font-size:.875rem}ion-popover ion-item ion-icon{font-size:1.125rem;margin-right:8px}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 2px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 2px);height:max(28px,36px - 2px);font-size:max(
|
|
21850
|
+
`, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}:host{display:block}.comment{--indent-size: 24px;--max-indent: 72px;padding:12px 0}.comment.highlighted{background-color:rgba(var(--ion-color-primary-rgb),.08);border-radius:8px;padding:12px;margin:-4px}.comment.pinned{border-left:3px solid var(--ion-color-primary);padding-left:12px}.comment.collapsed{opacity:.7}.pinned-indicator{display:flex;align-items:center;gap:4px;font-size:.75rem;color:var(--ion-color-primary);margin-bottom:8px;padding-left:44px}.pinned-indicator ion-icon{font-size:.875rem}.comment-main{display:flex;gap:12px}.comment-avatar{flex-shrink:0;cursor:pointer}.comment-avatar val-avatar{--size: 36px}.comment-avatar .avatar-placeholder{width:36px;height:36px;border-radius:50%;background:linear-gradient(135deg,var(--ion-color-primary),var(--ion-color-secondary));display:flex;align-items:center;justify-content:center;color:#fff;font-size:.875rem;font-weight:600}.comment-body{flex:1;min-width:0}.comment-header{display:flex;align-items:center;flex-wrap:wrap;gap:6px;margin-bottom:4px}.author-info{display:flex;align-items:center;gap:4px;cursor:pointer}.author-info:hover .author-name{text-decoration:underline}.author-name{font-weight:600;font-size:.875rem;color:var(--ion-text-color)}.verified-badge{color:var(--ion-color-primary);font-size:1rem}.author-username{font-size:.8125rem;color:var(--ion-color-medium)}.comment-meta{display:flex;align-items:center;gap:6px;margin-left:auto}.timestamp{font-size:.75rem;color:var(--ion-color-medium)}.edited-label{font-size:.6875rem;color:var(--ion-color-medium);font-style:italic}.more-button{--padding-start: 4px;--padding-end: 4px;margin:0;height:28px}.more-button ion-icon{font-size:1.125rem;color:var(--ion-color-medium)}.menu-divider{height:1px;background-color:var(--ion-color-light);margin:4px 0}.comment-content{font-size:.875rem;line-height:1.5;color:var(--ion-text-color);word-wrap:break-word;overflow-wrap:break-word}.comment-content :global(.comment-link){color:var(--ion-color-primary);text-decoration:none}.comment-content :global(.comment-link):hover{text-decoration:underline}.comment-content :global(.comment-mention){color:var(--ion-color-primary);font-weight:500;cursor:pointer}.comment-content :global(.comment-mention):hover{text-decoration:underline}.comment-content :global(.comment-hashtag){color:var(--ion-color-primary);cursor:pointer}.comment-content :global(.comment-hashtag):hover{text-decoration:underline}.comment-reactions{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}.reaction-button{display:flex;align-items:center;gap:4px;background:none;border:none;padding:4px 8px;border-radius:16px;cursor:pointer;font-size:.8125rem;color:var(--reaction-color, var(--ion-color-medium));transition:all .2s ease;background-color:transparent}.reaction-button:hover{background-color:rgba(var(--ion-color-medium-rgb),.1)}.reaction-button.active{background-color:rgba(var(--ion-color-primary-rgb),.1)}.reaction-button.active ion-icon{transform:scale(1.1)}.reaction-button ion-icon{font-size:1.125rem;transition:transform .2s ease}.reaction-button .reaction-count{font-weight:500}.comment-actions{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px;margin-left:-8px}.comment-actions ion-button{--padding-start: 8px;--padding-end: 8px;font-size:.8125rem;height:32px;text-transform:none;font-weight:500}.expand-button,.collapse-button,.load-more-button,.view-replies-button{display:flex;align-items:center;gap:6px;background:none;border:none;padding:8px 12px;cursor:pointer;font-size:.8125rem;color:var(--ion-color-primary);border-radius:8px;transition:background-color .2s}.expand-button:hover,.collapse-button:hover,.load-more-button:hover,.view-replies-button:hover{background-color:rgba(var(--ion-color-primary-rgb),.1)}.expand-button ion-icon,.collapse-button ion-icon,.load-more-button ion-icon,.view-replies-button ion-icon{font-size:1rem}.expand-button{margin-top:4px;color:var(--ion-color-medium)}.comment-children{margin-top:12px;padding-left:min(var(--indent-size),var(--max-indent));border-left:2px solid var(--ion-color-light-shade)}.comment-children val-comment{display:block}.comment-children val-comment:first-of-type .comment{padding-top:0}.load-more-button,.view-replies-button{margin-top:8px;margin-left:0}ion-popover{--width: 200px}ion-popover ion-list{padding:4px 0}ion-popover ion-item{--min-height: 40px;--padding-start: 12px;font-size:.875rem}ion-popover ion-item ion-icon{font-size:1.125rem;margin-right:8px}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 2px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 2px);height:max(28px,36px - 2px);font-size:max(.6875rem,.8125rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 4px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 4px);height:max(28px,36px - 4px);font-size:max(.6875rem,.75rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 6px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 6px);height:max(28px,36px - 6px);font-size:max(.6875rem,.6875rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 8px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 8px);height:max(28px,36px - 8px);font-size:max(.6875rem,.625rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 10px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 10px);height:max(28px,36px - 10px);font-size:max(.6875rem,.5625rem)}:host-context(.dark) .comment.highlighted,:host-context(.ion-palette-dark) .comment.highlighted,:host-context(html.ion-palette-dark) .comment.highlighted,:host-context(body.dark) .comment.highlighted,:host-context([data-theme=dark]) .comment.highlighted{background-color:rgba(var(--ion-color-primary-rgb),.12)}:host-context(.dark) .avatar-placeholder,:host-context(.ion-palette-dark) .avatar-placeholder,:host-context(html.ion-palette-dark) .avatar-placeholder,:host-context(body.dark) .avatar-placeholder,:host-context([data-theme=dark]) .avatar-placeholder{background:linear-gradient(135deg,var(--ion-color-primary-shade),var(--ion-color-secondary-shade))}\n"] }]
|
|
21851
21851
|
}], propDecorators: { props: [{
|
|
21852
21852
|
type: Input
|
|
21853
21853
|
}], authorClick: [{
|
|
@@ -41737,7 +41737,7 @@ const PROFILE_VIEW_I18N = {
|
|
|
41737
41737
|
const HANDLE_PATTERN = /^[a-z_][a-z0-9_]*$/;
|
|
41738
41738
|
const HANDLE_MIN = 3;
|
|
41739
41739
|
const HANDLE_MAX = 20;
|
|
41740
|
-
const DEFAULT_NAMESPACE$
|
|
41740
|
+
const DEFAULT_NAMESPACE$f = 'Settings.Profile';
|
|
41741
41741
|
/**
|
|
41742
41742
|
* `val-profile-view` — vista Perfil full-feature autocontenida (organism).
|
|
41743
41743
|
*
|
|
@@ -41787,7 +41787,7 @@ class ProfileViewComponent {
|
|
|
41787
41787
|
showPhone: merged.showPhone ?? true,
|
|
41788
41788
|
showShareCta: merged.showShareCta ?? true,
|
|
41789
41789
|
profileBaseUrl: merged.profileBaseUrl ?? '',
|
|
41790
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$
|
|
41790
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$f,
|
|
41791
41791
|
onSaved: merged.onSaved,
|
|
41792
41792
|
onAvatarUploaded: merged.onAvatarUploaded,
|
|
41793
41793
|
};
|
|
@@ -42263,17 +42263,12 @@ class ProfileViewComponent {
|
|
|
42263
42263
|
|
|
42264
42264
|
<val-form #form [props]="formMeta" (onSubmit)="onSubmit($event)" />
|
|
42265
42265
|
|
|
42266
|
-
|
|
42267
|
-
|
|
42268
|
-
<val-cta-card [props]="shareCta()" (onAction)="shareOpen.set(true)" />
|
|
42269
|
-
</section>
|
|
42270
|
-
}
|
|
42266
|
+
<!-- Card de compartir + modal QR removidos temporalmente (se retoman luego).
|
|
42267
|
+
Wiring intacto: shareCta(), shareModal(), shareOpen, showShareCta. -->
|
|
42271
42268
|
}
|
|
42272
42269
|
}
|
|
42273
42270
|
</div>
|
|
42274
|
-
|
|
42275
|
-
<val-share-profile-modal [isOpen]="shareOpen()" [props]="shareModal()" (dismissed)="shareOpen.set(false)" />
|
|
42276
|
-
`, isInline: true, styles: [".page{padding:16px 0;max-width:720px;margin:0 auto}.page-header{margin-bottom:16px}.page-header h1{font-size:22px;font-weight:700;margin:0 0 4px}.hint{font-size:13px;opacity:.7;margin:0 0 12px}.settings-section{padding:16px 0}.settings-section+.settings-section{border-top:1px solid var(--val-border-color, rgba(0, 0, 0, .08))}.avatar-section{display:flex;align-items:center;gap:16px}.avatar-meta{display:flex;flex-direction:column;gap:2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: AvatarUploadComponent, selector: "val-avatar-upload", inputs: ["props"], outputs: ["uploaded", "error", "uploadStart"] }, { kind: "component", type: EmptyStateComponent, selector: "val-empty-state", inputs: ["props"] }, { kind: "component", type: FormComponent, selector: "val-form", inputs: ["props"], outputs: ["onSubmit", "onInvalid", "onSelectChange"] }, { kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }, { kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }, { kind: "component", type: TitleComponent, selector: "val-title", inputs: ["props"] }, { kind: "component", type: SkeletonLayoutComponent, selector: "val-skeleton-layout", inputs: ["props"] }, { kind: "component", type: CtaCardComponent, selector: "val-cta-card", inputs: ["props"], outputs: ["onAction"] }, { kind: "component", type: ShareProfileModalComponent, selector: "val-share-profile-modal", inputs: ["isOpen", "props"], outputs: ["dismissed", "shared"] }] }); }
|
|
42271
|
+
`, isInline: true, styles: [".page{padding:16px 0;max-width:720px;margin:0 auto}.page-header{margin-bottom:16px}.page-header h1{font-size:22px;font-weight:700;margin:0 0 4px}.hint{font-size:13px;opacity:.7;margin:0 0 12px}.settings-section{padding:16px 0}.settings-section+.settings-section{border-top:1px solid var(--val-border-color, rgba(0, 0, 0, .08))}.avatar-section{display:flex;align-items:center;gap:16px}.avatar-meta{display:flex;flex-direction:column;gap:2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: AvatarUploadComponent, selector: "val-avatar-upload", inputs: ["props"], outputs: ["uploaded", "error", "uploadStart"] }, { kind: "component", type: EmptyStateComponent, selector: "val-empty-state", inputs: ["props"] }, { kind: "component", type: FormComponent, selector: "val-form", inputs: ["props"], outputs: ["onSubmit", "onInvalid", "onSelectChange"] }, { kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }, { kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }, { kind: "component", type: TitleComponent, selector: "val-title", inputs: ["props"] }, { kind: "component", type: SkeletonLayoutComponent, selector: "val-skeleton-layout", inputs: ["props"] }] }); }
|
|
42277
42272
|
}
|
|
42278
42273
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ProfileViewComponent, decorators: [{
|
|
42279
42274
|
type: Component,
|
|
@@ -42349,16 +42344,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
42349
42344
|
|
|
42350
42345
|
<val-form #form [props]="formMeta" (onSubmit)="onSubmit($event)" />
|
|
42351
42346
|
|
|
42352
|
-
|
|
42353
|
-
|
|
42354
|
-
<val-cta-card [props]="shareCta()" (onAction)="shareOpen.set(true)" />
|
|
42355
|
-
</section>
|
|
42356
|
-
}
|
|
42347
|
+
<!-- Card de compartir + modal QR removidos temporalmente (se retoman luego).
|
|
42348
|
+
Wiring intacto: shareCta(), shareModal(), shareOpen, showShareCta. -->
|
|
42357
42349
|
}
|
|
42358
42350
|
}
|
|
42359
42351
|
</div>
|
|
42360
|
-
|
|
42361
|
-
<val-share-profile-modal [isOpen]="shareOpen()" [props]="shareModal()" (dismissed)="shareOpen.set(false)" />
|
|
42362
42352
|
`, styles: [".page{padding:16px 0;max-width:720px;margin:0 auto}.page-header{margin-bottom:16px}.page-header h1{font-size:22px;font-weight:700;margin:0 0 4px}.hint{font-size:13px;opacity:.7;margin:0 0 12px}.settings-section{padding:16px 0}.settings-section+.settings-section{border-top:1px solid var(--val-border-color, rgba(0, 0, 0, .08))}.avatar-section{display:flex;align-items:center;gap:16px}.avatar-meta{display:flex;flex-direction:column;gap:2px}\n"] }]
|
|
42363
42353
|
}], ctorParameters: () => [], propDecorators: { config: [{
|
|
42364
42354
|
type: Input
|
|
@@ -42489,6 +42479,21 @@ class PreferencesService {
|
|
|
42489
42479
|
this._updateInFlight = false;
|
|
42490
42480
|
const destroyRef = inject(DestroyRef);
|
|
42491
42481
|
destroyRef.onDestroy(() => this.unbind());
|
|
42482
|
+
// Seed `_fontSize` con el valor que FontSizeService ya restauró desde
|
|
42483
|
+
// localStorage en su constructor (providedIn root → ya corrió al inyectarlo
|
|
42484
|
+
// acá). Sin esto, el signal arranca en 'medium' y el effect de abajo —que
|
|
42485
|
+
// dispara al marcarse `synced`— forzaría 'medium' pisando el tamaño
|
|
42486
|
+
// restaurado cuando el snapshot Firestore NO trae `fontSize` (user sin ese
|
|
42487
|
+
// campo en el mirror). Bug: cambias el tamaño, refrescas y se pierde.
|
|
42488
|
+
if (this.fontSizeService) {
|
|
42489
|
+
this._fontSize.set(this.fontSizeService.size());
|
|
42490
|
+
}
|
|
42491
|
+
// Mismo seed para theme — ThemeService aplica su valor de localStorage en
|
|
42492
|
+
// bootstrap (`currentOption`). Necesario para desgatear el effect de theme
|
|
42493
|
+
// (abajo) sin que el default 'auto' pise el tema restaurado.
|
|
42494
|
+
if (this.themeService) {
|
|
42495
|
+
this._theme.set(this.themeService.currentOption);
|
|
42496
|
+
}
|
|
42492
42497
|
// Auto-bind al user actual. effect() corre en injection context (constructor OK).
|
|
42493
42498
|
// allowSignalWrites: bindToUser/unbind escriben `_synced` (señal interna sin
|
|
42494
42499
|
// dependencias del propio effect) → seguro y necesario.
|
|
@@ -42501,14 +42506,18 @@ class PreferencesService {
|
|
|
42501
42506
|
this.unbind();
|
|
42502
42507
|
}
|
|
42503
42508
|
}, { allowSignalWrites: true });
|
|
42504
|
-
// Side-effect: aplicar theme
|
|
42505
|
-
//
|
|
42506
|
-
//
|
|
42507
|
-
//
|
|
42508
|
-
//
|
|
42509
|
+
// Side-effect: aplicar theme. SIN gate `_synced` (local-first, igual que
|
|
42510
|
+
// fontSize): ThemeService/localStorage es la verdad del dispositivo y
|
|
42511
|
+
// `_theme` viene seedeado arriba. Aplicar siempre que cambie da apply
|
|
42512
|
+
// optimista al instante; el sync cross-device también aplica vía snapshot.
|
|
42513
|
+
// Gatearlo en `_synced` hacía que el primer cambio de un user nuevo (sin doc
|
|
42514
|
+
// Firestore aún) no se aplicara: el selector mostraba "Dark" pero el tema no
|
|
42515
|
+
// cambiaba. (El selector de idioma no sufre esto porque val-language-selector
|
|
42516
|
+
// llama i18n.setLanguage directo; el de theme depende solo de este effect.)
|
|
42517
|
+
// OJO: usar `toggleUserPreference()` y NO el setter `Theme =`. El setter solo
|
|
42518
|
+
// persiste localStorage + emite el BehaviorSubject; no aplica las clases
|
|
42519
|
+
// `body.dark`/`html.ion-palette-dark` que el palette de Ionic necesita.
|
|
42509
42520
|
effect(() => {
|
|
42510
|
-
if (!this._synced())
|
|
42511
|
-
return;
|
|
42512
42521
|
const t = this._theme();
|
|
42513
42522
|
if (this.themeService) {
|
|
42514
42523
|
this.themeService.toggleUserPreference(t);
|
|
@@ -42523,11 +42532,17 @@ class PreferencesService {
|
|
|
42523
42532
|
this.i18n.setLanguage(l);
|
|
42524
42533
|
}
|
|
42525
42534
|
});
|
|
42526
|
-
// Side-effect: aplicar fontSize
|
|
42535
|
+
// Side-effect: aplicar fontSize.
|
|
42536
|
+
// SIN gate `_synced` (igual que theme): el tamaño es una
|
|
42537
|
+
// preferencia local-first — FontSizeService/localStorage es la verdad del
|
|
42538
|
+
// dispositivo y `_fontSize` ya viene seedeado de ahí arriba. Aplicar siempre
|
|
42539
|
+
// que cambie permite que el cambio del usuario surta efecto al instante
|
|
42540
|
+
// (optimista, sin esperar el round-trip a Firestore) y que el sync
|
|
42541
|
+
// cross-device también aplique al llegar el snapshot. Gatearlo en `_synced`
|
|
42542
|
+
// hacía que el primer cambio de un user nuevo (sin doc Firestore aún) no se
|
|
42543
|
+
// aplicara: el selector mostraba "Grande" pero el font-size no cambiaba.
|
|
42527
42544
|
// allowSignalWrites: fontSizeService.setSize() escribe this._size (signal).
|
|
42528
42545
|
effect(() => {
|
|
42529
|
-
if (!this._synced())
|
|
42530
|
-
return;
|
|
42531
42546
|
const fs = this._fontSize();
|
|
42532
42547
|
if (this.fontSizeService) {
|
|
42533
42548
|
this.fontSizeService.setSize(fs);
|
|
@@ -42703,7 +42718,7 @@ const PREFERENCES_VIEW_I18N = {
|
|
|
42703
42718
|
},
|
|
42704
42719
|
};
|
|
42705
42720
|
|
|
42706
|
-
const DEFAULT_NAMESPACE$
|
|
42721
|
+
const DEFAULT_NAMESPACE$e = 'Settings.General';
|
|
42707
42722
|
const DEFAULT_LANGUAGES = ['es', 'en'];
|
|
42708
42723
|
/**
|
|
42709
42724
|
* `val-preferences-view` — vista de preferencias de UI cross-app (tema +
|
|
@@ -42740,7 +42755,7 @@ class PreferencesViewComponent {
|
|
|
42740
42755
|
showLanguage: merged.showLanguage ?? true,
|
|
42741
42756
|
showFontSize: merged.showFontSize ?? true,
|
|
42742
42757
|
supportedLanguages: merged.supportedLanguages ?? DEFAULT_LANGUAGES,
|
|
42743
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$
|
|
42758
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$e,
|
|
42744
42759
|
onThemeChanged: merged.onThemeChanged,
|
|
42745
42760
|
onLanguageChanged: merged.onLanguageChanged,
|
|
42746
42761
|
onFontSizeChanged: merged.onFontSizeChanged,
|
|
@@ -44496,7 +44511,7 @@ const SECURITY_VIEW_I18N = {
|
|
|
44496
44511
|
};
|
|
44497
44512
|
|
|
44498
44513
|
addIcons({ laptopOutline, phonePortraitOutline });
|
|
44499
|
-
const DEFAULT_NAMESPACE$
|
|
44514
|
+
const DEFAULT_NAMESPACE$d = 'Settings.Security';
|
|
44500
44515
|
/**
|
|
44501
44516
|
* `val-security-view` — vista Seguridad full-feature autocontenida (organism).
|
|
44502
44517
|
*
|
|
@@ -44545,7 +44560,7 @@ class SecurityViewComponent {
|
|
|
44545
44560
|
showChangeEmail: merged.showChangeEmail ?? true,
|
|
44546
44561
|
showMfa: merged.showMfa ?? true,
|
|
44547
44562
|
showPolicies: merged.showPolicies ?? true,
|
|
44548
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$
|
|
44563
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$d,
|
|
44549
44564
|
handleDeepLinks: merged.handleDeepLinks ?? true,
|
|
44550
44565
|
homeRoute: merged.homeRoute ?? '/app/home',
|
|
44551
44566
|
onMfaCompleted: merged.onMfaCompleted,
|
|
@@ -45451,7 +45466,7 @@ const CREATE_ORG_MODAL_I18N = {
|
|
|
45451
45466
|
},
|
|
45452
45467
|
};
|
|
45453
45468
|
|
|
45454
|
-
const DEFAULT_NAMESPACE$
|
|
45469
|
+
const DEFAULT_NAMESPACE$c = 'CreateOrgModal';
|
|
45455
45470
|
/**
|
|
45456
45471
|
* `val-create-org-modal` — modal de creación de organización (organism
|
|
45457
45472
|
* compartido). Promovido desde `showcase` bajo el proceso de ADR-021. Reusado por
|
|
@@ -45477,10 +45492,10 @@ class CreateOrgModalComponent {
|
|
|
45477
45492
|
this.toast = inject(ToastService);
|
|
45478
45493
|
this.errors = inject(ValtechErrorService);
|
|
45479
45494
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
45480
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
45495
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$c;
|
|
45481
45496
|
this._busy = signal(false);
|
|
45482
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
45483
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
45497
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$c)) {
|
|
45498
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$c, CREATE_ORG_MODAL_I18N);
|
|
45484
45499
|
}
|
|
45485
45500
|
this.formMeta = signal(this.buildFormMeta());
|
|
45486
45501
|
effect(() => {
|
|
@@ -45716,7 +45731,7 @@ const DELETE_ACCOUNT_MODAL_I18N = {
|
|
|
45716
45731
|
},
|
|
45717
45732
|
};
|
|
45718
45733
|
|
|
45719
|
-
const DEFAULT_NAMESPACE$
|
|
45734
|
+
const DEFAULT_NAMESPACE$b = 'Settings.DeleteAccount';
|
|
45720
45735
|
/**
|
|
45721
45736
|
* `val-delete-account-modal` — modal de eliminación de cuenta (organism,
|
|
45722
45737
|
* cuenta-específico). Promovido desde `showcase` bajo el proceso de ADR-021.
|
|
@@ -45742,7 +45757,7 @@ class DeleteAccountModalComponent {
|
|
|
45742
45757
|
this.i18n = inject(I18nService);
|
|
45743
45758
|
this.toast = inject(ToastService);
|
|
45744
45759
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
45745
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
45760
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$b;
|
|
45746
45761
|
this.hasPassword = signal(null);
|
|
45747
45762
|
this.codeSent = signal(false);
|
|
45748
45763
|
this.formState = signal(ComponentStates.ENABLED);
|
|
@@ -45809,8 +45824,8 @@ class DeleteAccountModalComponent {
|
|
|
45809
45824
|
],
|
|
45810
45825
|
actions: this.submitBtn('delete-code-submit', 'confirmCta'),
|
|
45811
45826
|
}));
|
|
45812
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
45813
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
45827
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$b)) {
|
|
45828
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$b, DELETE_ACCOUNT_MODAL_I18N);
|
|
45814
45829
|
}
|
|
45815
45830
|
}
|
|
45816
45831
|
ngOnInit() {
|
|
@@ -46011,7 +46026,7 @@ const ORG_INFO_SHEET_I18N = {
|
|
|
46011
46026
|
},
|
|
46012
46027
|
};
|
|
46013
46028
|
|
|
46014
|
-
const DEFAULT_NAMESPACE$
|
|
46029
|
+
const DEFAULT_NAMESPACE$a = 'OrgInfoSheet';
|
|
46015
46030
|
/**
|
|
46016
46031
|
* `val-org-info-sheet` — sheet informativo "¿Qué son las organizaciones?".
|
|
46017
46032
|
* Extraído del `OrgInfoSheetComponent` inline de `AccountPage` bajo el proceso de
|
|
@@ -46056,15 +46071,15 @@ class OrgInfoSheetComponent {
|
|
|
46056
46071
|
text: this.closeProps.text || this.resolvedCloseLabel(),
|
|
46057
46072
|
}));
|
|
46058
46073
|
addIcons({ peopleOutline, swapHorizontalOutline, mailOutline });
|
|
46059
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
46060
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
46074
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$a)) {
|
|
46075
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$a, ORG_INFO_SHEET_I18N);
|
|
46061
46076
|
}
|
|
46062
46077
|
}
|
|
46063
46078
|
dismiss() {
|
|
46064
46079
|
this._modalRef?.dismiss(null, 'cancel');
|
|
46065
46080
|
}
|
|
46066
46081
|
tt(key) {
|
|
46067
|
-
return this.i18n.t(key, DEFAULT_NAMESPACE$
|
|
46082
|
+
return this.i18n.t(key, DEFAULT_NAMESPACE$a);
|
|
46068
46083
|
}
|
|
46069
46084
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: OrgInfoSheetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
46070
46085
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: OrgInfoSheetComponent, isStandalone: true, selector: "val-org-info-sheet", inputs: { title: "title", subtitle: "subtitle", body: "body", closeLabel: "closeLabel", closeProps: "closeProps", _modalRef: "_modalRef" }, ngImport: i0, template: `
|
|
@@ -46231,7 +46246,7 @@ const SWITCH_ORG_MODAL_I18N = {
|
|
|
46231
46246
|
},
|
|
46232
46247
|
};
|
|
46233
46248
|
|
|
46234
|
-
const DEFAULT_NAMESPACE$
|
|
46249
|
+
const DEFAULT_NAMESPACE$9 = 'Settings.SwitchOrg';
|
|
46235
46250
|
addIcons({ businessOutline, checkmarkCircleOutline });
|
|
46236
46251
|
/**
|
|
46237
46252
|
* `val-switch-org-modal` — modal de cambio de organización activa (organism
|
|
@@ -46257,7 +46272,7 @@ class SwitchOrgModalComponent {
|
|
|
46257
46272
|
this.orgSwitch = inject(OrgSwitchService);
|
|
46258
46273
|
this.errors = inject(ValtechErrorService);
|
|
46259
46274
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
46260
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
46275
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$9;
|
|
46261
46276
|
this.orgs = signal([]);
|
|
46262
46277
|
this.loading = signal(false);
|
|
46263
46278
|
this.query = signal('');
|
|
@@ -46273,8 +46288,8 @@ class SwitchOrgModalComponent {
|
|
|
46273
46288
|
return list;
|
|
46274
46289
|
return list.filter(o => o.name.toLowerCase().includes(q));
|
|
46275
46290
|
});
|
|
46276
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
46277
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
46291
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$9)) {
|
|
46292
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$9, SWITCH_ORG_MODAL_I18N);
|
|
46278
46293
|
}
|
|
46279
46294
|
this.loadOrgs();
|
|
46280
46295
|
}
|
|
@@ -46592,7 +46607,7 @@ const ACCOUNT_VIEW_I18N = {
|
|
|
46592
46607
|
};
|
|
46593
46608
|
|
|
46594
46609
|
addIcons({ peopleOutline, businessOutline, chevronForwardOutline, swapHorizontalOutline, mailOutline });
|
|
46595
|
-
const DEFAULT_NAMESPACE$
|
|
46610
|
+
const DEFAULT_NAMESPACE$8 = 'Settings.Account';
|
|
46596
46611
|
const DEFAULT_MANAGE_ORG_ROUTE = '/app/settings/organization';
|
|
46597
46612
|
/**
|
|
46598
46613
|
* `val-account-view` — vista Cuenta full-feature autocontenida (organism).
|
|
@@ -46633,7 +46648,7 @@ class AccountViewComponent {
|
|
|
46633
46648
|
showNewOrgCta: merged.showNewOrgCta ?? true,
|
|
46634
46649
|
showLogout: merged.showLogout ?? true,
|
|
46635
46650
|
showDeleteAccount: merged.showDeleteAccount ?? true,
|
|
46636
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$
|
|
46651
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$8,
|
|
46637
46652
|
manageOrgRoute: merged.manageOrgRoute ?? DEFAULT_MANAGE_ORG_ROUTE,
|
|
46638
46653
|
onOrgSwitched: merged.onOrgSwitched,
|
|
46639
46654
|
onOrgCreated: merged.onOrgCreated,
|
|
@@ -47358,7 +47373,7 @@ const EDIT_ORG_MODAL_I18N = {
|
|
|
47358
47373
|
},
|
|
47359
47374
|
};
|
|
47360
47375
|
|
|
47361
|
-
const DEFAULT_NAMESPACE$
|
|
47376
|
+
const DEFAULT_NAMESPACE$7 = 'EditOrgModal';
|
|
47362
47377
|
/**
|
|
47363
47378
|
* `val-edit-org-modal` — modal de edición de organización (nombre + descripción).
|
|
47364
47379
|
* Promovido desde `showcase` bajo el proceso de ADR-021. Reusado por la vista de
|
|
@@ -47385,10 +47400,10 @@ class EditOrgModalComponent {
|
|
|
47385
47400
|
/** Organización a editar (pasada por `componentProps`). */
|
|
47386
47401
|
this.org = null;
|
|
47387
47402
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
47388
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
47403
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$7;
|
|
47389
47404
|
this.saving = signal(false);
|
|
47390
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
47391
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
47405
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$7)) {
|
|
47406
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$7, EDIT_ORG_MODAL_I18N);
|
|
47392
47407
|
}
|
|
47393
47408
|
this.formMeta = signal(this.buildFormMeta());
|
|
47394
47409
|
effect(() => {
|
|
@@ -47626,7 +47641,7 @@ const INVITE_MEMBER_MODAL_I18N = {
|
|
|
47626
47641
|
},
|
|
47627
47642
|
};
|
|
47628
47643
|
|
|
47629
|
-
const DEFAULT_NAMESPACE$
|
|
47644
|
+
const DEFAULT_NAMESPACE$6 = 'InviteModal';
|
|
47630
47645
|
addIcons({ personOutline, mailOutline, closeOutline, checkmarkCircleOutline });
|
|
47631
47646
|
/**
|
|
47632
47647
|
* `val-invite-member-modal` — invitación de miembros a una organización.
|
|
@@ -47657,7 +47672,7 @@ class InviteMemberModalComponent {
|
|
|
47657
47672
|
/** Ids de miembros ya existentes (excluidos de los resultados). */
|
|
47658
47673
|
this.existingMemberIds = [];
|
|
47659
47674
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
47660
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
47675
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$6;
|
|
47661
47676
|
this.query = signal('');
|
|
47662
47677
|
this.searching = signal(false);
|
|
47663
47678
|
this.searchResults = signal([]);
|
|
@@ -47704,8 +47719,8 @@ class InviteMemberModalComponent {
|
|
|
47704
47719
|
state: this.sending() ? ComponentStates.WORKING : ComponentStates.ENABLED,
|
|
47705
47720
|
}));
|
|
47706
47721
|
this.searchSubject = new Subject();
|
|
47707
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
47708
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
47722
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$6)) {
|
|
47723
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$6, INVITE_MEMBER_MODAL_I18N);
|
|
47709
47724
|
}
|
|
47710
47725
|
this.loadRoles();
|
|
47711
47726
|
this.roleSub = this.roleControl.valueChanges.subscribe(v => {
|
|
@@ -48194,7 +48209,7 @@ const MEMBER_DETAIL_MODAL_I18N = {
|
|
|
48194
48209
|
},
|
|
48195
48210
|
};
|
|
48196
48211
|
|
|
48197
|
-
const DEFAULT_NAMESPACE$
|
|
48212
|
+
const DEFAULT_NAMESPACE$5 = 'Settings.MemberDetail';
|
|
48198
48213
|
/**
|
|
48199
48214
|
* `val-member-detail-modal` — detalle de miembro de organización: perfil, rol y
|
|
48200
48215
|
* permisos. Promovido desde `showcase` bajo el proceso de ADR-021.
|
|
@@ -48231,7 +48246,7 @@ class MemberDetailModalComponent {
|
|
|
48231
48246
|
{ id: 'admin', name: 'admin' },
|
|
48232
48247
|
];
|
|
48233
48248
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
48234
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
48249
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$5;
|
|
48235
48250
|
this.working = signal(false);
|
|
48236
48251
|
this.currentRole = signal('');
|
|
48237
48252
|
this.roleControl = new FormControl('');
|
|
@@ -48271,8 +48286,8 @@ class MemberDetailModalComponent {
|
|
|
48271
48286
|
type: 'button',
|
|
48272
48287
|
state: this.working() ? ComponentStates.WORKING : ComponentStates.ENABLED,
|
|
48273
48288
|
}));
|
|
48274
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
48275
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
48289
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$5)) {
|
|
48290
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$5, MEMBER_DETAIL_MODAL_I18N);
|
|
48276
48291
|
}
|
|
48277
48292
|
}
|
|
48278
48293
|
ngOnInit() {
|
|
@@ -48609,7 +48624,7 @@ const TRANSFER_OWNERSHIP_MODAL_I18N = {
|
|
|
48609
48624
|
},
|
|
48610
48625
|
};
|
|
48611
48626
|
|
|
48612
|
-
const DEFAULT_NAMESPACE$
|
|
48627
|
+
const DEFAULT_NAMESPACE$4 = 'Settings.TransferModal';
|
|
48613
48628
|
/**
|
|
48614
48629
|
* `val-transfer-ownership-modal` — selector de miembro para transferir la
|
|
48615
48630
|
* propiedad de la organización. Promovido desde `showcase` bajo el proceso de
|
|
@@ -48633,7 +48648,7 @@ class TransferOwnershipModalComponent {
|
|
|
48633
48648
|
/** Lista de miembros transferibles (todos excepto el owner actual). */
|
|
48634
48649
|
this.members = [];
|
|
48635
48650
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
48636
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
48651
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$4;
|
|
48637
48652
|
this.query = signal('');
|
|
48638
48653
|
this.selectedId = signal('');
|
|
48639
48654
|
this.filtered = computed(() => {
|
|
@@ -48645,8 +48660,8 @@ class TransferOwnershipModalComponent {
|
|
|
48645
48660
|
m.userId.toLowerCase().includes(q));
|
|
48646
48661
|
});
|
|
48647
48662
|
this.noResultsLabel = computed(() => `${this.t('noResults')} "${this.query()}"`);
|
|
48648
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
48649
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
48663
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$4)) {
|
|
48664
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$4, TRANSFER_OWNERSHIP_MODAL_I18N);
|
|
48650
48665
|
}
|
|
48651
48666
|
}
|
|
48652
48667
|
ngOnInit() {
|
|
@@ -48979,7 +48994,7 @@ const ORGANIZATION_VIEW_I18N = {
|
|
|
48979
48994
|
},
|
|
48980
48995
|
};
|
|
48981
48996
|
|
|
48982
|
-
const DEFAULT_NAMESPACE$
|
|
48997
|
+
const DEFAULT_NAMESPACE$3 = 'Settings.Organization';
|
|
48983
48998
|
const DEFAULT_VIEW_PERMISSIONS_ROUTE = '/app/settings/permissions';
|
|
48984
48999
|
const DEFAULT_LEAVE_REDIRECT_ROUTE = '/app/settings/account';
|
|
48985
49000
|
/**
|
|
@@ -49036,7 +49051,7 @@ class OrganizationViewComponent {
|
|
|
49036
49051
|
showInvite: merged.showInvite ?? true,
|
|
49037
49052
|
showTransferOwnership: merged.showTransferOwnership ?? true,
|
|
49038
49053
|
showLeave: merged.showLeave ?? true,
|
|
49039
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$
|
|
49054
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$3,
|
|
49040
49055
|
viewPermissionsRoute: merged.viewPermissionsRoute ?? DEFAULT_VIEW_PERMISSIONS_ROUTE,
|
|
49041
49056
|
leaveRedirectRoute: merged.leaveRedirectRoute ?? DEFAULT_LEAVE_REDIRECT_ROUTE,
|
|
49042
49057
|
onOrgEdited: merged.onOrgEdited,
|
|
@@ -50123,7 +50138,7 @@ addIcons({
|
|
|
50123
50138
|
notificationsOutline,
|
|
50124
50139
|
refreshOutline,
|
|
50125
50140
|
});
|
|
50126
|
-
const DEFAULT_NAMESPACE$
|
|
50141
|
+
const DEFAULT_NAMESPACE$2 = 'Settings.Notifications';
|
|
50127
50142
|
/**
|
|
50128
50143
|
* `val-notification-preferences-view` — **preferencias de notificaciones push**
|
|
50129
50144
|
* (FCM) full-feature autocontenida (organism). Promovida desde `showcase` bajo el
|
|
@@ -50166,7 +50181,7 @@ class NotificationPreferencesViewComponent {
|
|
|
50166
50181
|
const merged = { ...fromRoute, ...(this.config ?? {}) };
|
|
50167
50182
|
return {
|
|
50168
50183
|
showDetails: merged.showDetails ?? true,
|
|
50169
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$
|
|
50184
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$2,
|
|
50170
50185
|
onPushEnabled: merged.onPushEnabled,
|
|
50171
50186
|
onPushDisabled: merged.onPushDisabled,
|
|
50172
50187
|
};
|
|
@@ -50937,7 +50952,7 @@ const PERMISSIONS_VIEW_I18N = {
|
|
|
50937
50952
|
},
|
|
50938
50953
|
};
|
|
50939
50954
|
|
|
50940
|
-
const DEFAULT_NAMESPACE$
|
|
50955
|
+
const DEFAULT_NAMESPACE$1 = 'Settings.Permissions';
|
|
50941
50956
|
/**
|
|
50942
50957
|
* `val-permissions-view` — vista Permisos full-feature autocontenida (organism).
|
|
50943
50958
|
* Visor RBAC de solo lectura: muestra los roles del sistema (Visor/Editor/Admin +
|
|
@@ -50977,7 +50992,7 @@ class PermissionsViewComponent {
|
|
|
50977
50992
|
return {
|
|
50978
50993
|
showSystemRoles: merged.showSystemRoles ?? true,
|
|
50979
50994
|
showCustomRoles: merged.showCustomRoles ?? true,
|
|
50980
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$
|
|
50995
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$1,
|
|
50981
50996
|
};
|
|
50982
50997
|
});
|
|
50983
50998
|
this.loading = signal(false);
|
|
@@ -51754,7 +51769,7 @@ addIcons({
|
|
|
51754
51769
|
openOutline,
|
|
51755
51770
|
personOutline,
|
|
51756
51771
|
});
|
|
51757
|
-
const DEFAULT_NAMESPACE
|
|
51772
|
+
const DEFAULT_NAMESPACE = 'Notifications';
|
|
51758
51773
|
const DEFAULT_SETTINGS_PATH = '/app/settings/notifications';
|
|
51759
51774
|
const DEFAULT_PAGE_SIZE = 10;
|
|
51760
51775
|
const DEFAULT_MAX_LOAD = 50;
|
|
@@ -51814,7 +51829,7 @@ class NotificationsViewComponent {
|
|
|
51814
51829
|
showPushOffCta: merged.showPushOffCta ?? true,
|
|
51815
51830
|
enableMarkAll: merged.enableMarkAll ?? true,
|
|
51816
51831
|
settingsNotificationsPath: merged.settingsNotificationsPath ?? DEFAULT_SETTINGS_PATH,
|
|
51817
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE
|
|
51832
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE,
|
|
51818
51833
|
pageSize: merged.pageSize ?? DEFAULT_PAGE_SIZE,
|
|
51819
51834
|
maxLoad: merged.maxLoad ?? DEFAULT_MAX_LOAD,
|
|
51820
51835
|
onNotificationOpen: merged.onNotificationOpen,
|
|
@@ -52482,797 +52497,6 @@ function provideValtechNotificationsRoutes(opts) {
|
|
|
52482
52497
|
];
|
|
52483
52498
|
}
|
|
52484
52499
|
|
|
52485
|
-
/**
|
|
52486
|
-
* Defaults i18n del componente (es/en). El componente los auto-registra en su
|
|
52487
|
-
* constructor si el consumer no proveyó el namespace `ContentReaction`. Esto
|
|
52488
|
-
* garantiza que NUNCA haya una key faltante: una key faltante se evalúa en el
|
|
52489
|
-
* template por cada change-detection → `console.warn` por CD → con el
|
|
52490
|
-
* `val-debug-console` activo (espeja console.* a un signal) se dispara un loop
|
|
52491
|
-
* infinito que congela el navegador en dev. Auto-registrar lo elimina de raíz.
|
|
52492
|
-
*/
|
|
52493
|
-
const CONTENT_REACTION_I18N = {
|
|
52494
|
-
es: {
|
|
52495
|
-
question: '¿Te resultó útil este contenido?',
|
|
52496
|
-
commentPlaceholder: 'Cuéntanos más (opcional)...',
|
|
52497
|
-
submit: 'Enviar opinión',
|
|
52498
|
-
update: 'Actualizar opinión',
|
|
52499
|
-
thankYou: '¡Gracias por tu opinión!',
|
|
52500
|
-
submitted: 'Tu opinión ha sido registrada',
|
|
52501
|
-
errorSubmitting: 'Error al enviar. Intenta de nuevo.',
|
|
52502
|
-
positiveLabel: 'Sí, mucho',
|
|
52503
|
-
negativeLabel: 'No tanto',
|
|
52504
|
-
negativeFeedbackTitle: '¿Cuéntanos qué no te gustó?',
|
|
52505
|
-
},
|
|
52506
|
-
en: {
|
|
52507
|
-
question: 'Was this content helpful?',
|
|
52508
|
-
commentPlaceholder: 'Tell us more (optional)...',
|
|
52509
|
-
submit: 'Send feedback',
|
|
52510
|
-
update: 'Update feedback',
|
|
52511
|
-
thankYou: 'Thanks for your feedback!',
|
|
52512
|
-
submitted: 'Your feedback has been recorded',
|
|
52513
|
-
errorSubmitting: 'Failed to send. Please try again.',
|
|
52514
|
-
positiveLabel: 'Yes, a lot',
|
|
52515
|
-
negativeLabel: 'Not really',
|
|
52516
|
-
negativeFeedbackTitle: "Tell us what you didn't like?",
|
|
52517
|
-
},
|
|
52518
|
-
};
|
|
52519
|
-
/**
|
|
52520
|
-
* Componente para reacciones de contenido con emojis.
|
|
52521
|
-
*
|
|
52522
|
-
* @example
|
|
52523
|
-
* ```html
|
|
52524
|
-
* <val-content-reaction
|
|
52525
|
-
* [props]="{
|
|
52526
|
-
* entityRef: { entityType: 'article', entityId: 'art-123' },
|
|
52527
|
-
* question: '¿Te fue útil este artículo?'
|
|
52528
|
-
* }"
|
|
52529
|
-
* (reactionSubmit)="onReactionSubmit($event)"
|
|
52530
|
-
* />
|
|
52531
|
-
* ```
|
|
52532
|
-
*/
|
|
52533
|
-
class ContentReactionComponent {
|
|
52534
|
-
constructor() {
|
|
52535
|
-
this.feedbackService = inject(FeedbackService);
|
|
52536
|
-
this.toast = inject(ToastService);
|
|
52537
|
-
this.i18n = inject(I18nService);
|
|
52538
|
-
this.auth = inject(AuthService, { optional: true });
|
|
52539
|
-
this.isConfigured = computed(() => this.feedbackService.isConfigured());
|
|
52540
|
-
this.props = {};
|
|
52541
|
-
this.reactionSubmit = new EventEmitter();
|
|
52542
|
-
this.reactionChange = new EventEmitter();
|
|
52543
|
-
// Estado reactivo
|
|
52544
|
-
this.state = signal({
|
|
52545
|
-
selectedValue: null,
|
|
52546
|
-
comment: '',
|
|
52547
|
-
isLoading: false,
|
|
52548
|
-
isSubmitted: false,
|
|
52549
|
-
hadPreviousReaction: false,
|
|
52550
|
-
error: null,
|
|
52551
|
-
});
|
|
52552
|
-
// Valores por defecto
|
|
52553
|
-
this.defaultEmojis = ['😞', '😐', '😊'];
|
|
52554
|
-
this.defaultLabels = ['No me ayudó', 'Regular', 'Muy útil'];
|
|
52555
|
-
// Computed properties
|
|
52556
|
-
this.resolvedProps = computed(() => ({
|
|
52557
|
-
entityRef: this.props.entityRef,
|
|
52558
|
-
question: this.props.question || this.t('question'),
|
|
52559
|
-
showComment: this.props.showComment ?? true,
|
|
52560
|
-
commentOnValues: this.props.commentOnValues,
|
|
52561
|
-
commentPlaceholder: this.props.commentPlaceholder || this.t('commentPlaceholder'),
|
|
52562
|
-
maxCommentLength: this.props.maxCommentLength ?? 500,
|
|
52563
|
-
emojis: this.props.emojis || this.defaultEmojis,
|
|
52564
|
-
emojiLabels: this.props.emojiLabels || this.defaultLabels,
|
|
52565
|
-
showThankYou: this.props.showThankYou ?? true,
|
|
52566
|
-
thankYouMessage: this.props.thankYouMessage || this.t('thankYou'),
|
|
52567
|
-
disabled: this.props.disabled ?? false,
|
|
52568
|
-
readonly: this.props.readonly ?? false,
|
|
52569
|
-
// Variante: 'emoji' cuando se declara explícitamente o cuando se pasan emojis custom.
|
|
52570
|
-
variant: this.props.variant ?? (this.props.emojis ? 'emoji' : 'buttons'),
|
|
52571
|
-
}));
|
|
52572
|
-
this.activeReactionValues = computed(() => this.resolvedProps().emojis.length === 2 ? ['negative', 'positive'] : ['negative', 'neutral', 'positive']);
|
|
52573
|
-
this.showCommentField = computed(() => {
|
|
52574
|
-
const sel = this.state().selectedValue;
|
|
52575
|
-
if (!sel)
|
|
52576
|
-
return false;
|
|
52577
|
-
const commentOn = this.resolvedProps().commentOnValues;
|
|
52578
|
-
if (commentOn !== undefined)
|
|
52579
|
-
return commentOn.includes(sel);
|
|
52580
|
-
return this.resolvedProps().showComment;
|
|
52581
|
-
});
|
|
52582
|
-
this.canSubmit = computed(() => this.state().selectedValue !== null && !this.state().isLoading);
|
|
52583
|
-
// Auto-registro de defaults i18n (es/en) si el consumer no proveyó el
|
|
52584
|
-
// namespace. Garantiza que `t()` nunca caiga en key faltante. Ver
|
|
52585
|
-
// CONTENT_REACTION_I18N. Idempotente: solo la 1ª instancia registra.
|
|
52586
|
-
if (!this.i18n.hasNamespace('ContentReaction')) {
|
|
52587
|
-
this.i18n.registerContent('ContentReaction', CONTENT_REACTION_I18N);
|
|
52588
|
-
}
|
|
52589
|
-
}
|
|
52590
|
-
ngOnInit() {
|
|
52591
|
-
this.loadPreviousReaction();
|
|
52592
|
-
}
|
|
52593
|
-
ngOnChanges(changes) {
|
|
52594
|
-
if (changes['props'] && !changes['props'].firstChange) {
|
|
52595
|
-
this.loadPreviousReaction();
|
|
52596
|
-
}
|
|
52597
|
-
}
|
|
52598
|
-
async loadPreviousReaction() {
|
|
52599
|
-
if (!this.props.entityRef)
|
|
52600
|
-
return;
|
|
52601
|
-
// Si hay initialValue, usarlo directamente sin consultar
|
|
52602
|
-
if (this.props.initialValue) {
|
|
52603
|
-
this.state.update(s => ({
|
|
52604
|
-
...s,
|
|
52605
|
-
selectedValue: this.props.initialValue,
|
|
52606
|
-
hadPreviousReaction: true,
|
|
52607
|
-
isLoading: false,
|
|
52608
|
-
isSubmitted: true,
|
|
52609
|
-
}));
|
|
52610
|
-
return;
|
|
52611
|
-
}
|
|
52612
|
-
// Si skipInitialCheck está activo, no consultar
|
|
52613
|
-
if (this.props.skipInitialCheck) {
|
|
52614
|
-
return;
|
|
52615
|
-
}
|
|
52616
|
-
this.state.update(s => ({ ...s, isLoading: true, error: null }));
|
|
52617
|
-
try {
|
|
52618
|
-
const check = await this.feedbackService.checkFeedback(this.props.entityRef.entityType, this.props.entityRef.entityId);
|
|
52619
|
-
if (check.hasFeedback && check.reactionValue) {
|
|
52620
|
-
this.state.update(s => ({
|
|
52621
|
-
...s,
|
|
52622
|
-
selectedValue: check.reactionValue,
|
|
52623
|
-
hadPreviousReaction: true,
|
|
52624
|
-
isLoading: false,
|
|
52625
|
-
isSubmitted: true,
|
|
52626
|
-
}));
|
|
52627
|
-
}
|
|
52628
|
-
else {
|
|
52629
|
-
this.state.update(s => ({ ...s, isLoading: false }));
|
|
52630
|
-
}
|
|
52631
|
-
}
|
|
52632
|
-
catch (error) {
|
|
52633
|
-
console.error('Error loading previous reaction:', error);
|
|
52634
|
-
this.state.update(s => ({ ...s, isLoading: false }));
|
|
52635
|
-
}
|
|
52636
|
-
}
|
|
52637
|
-
selectReaction(value) {
|
|
52638
|
-
if (this.resolvedProps().disabled || this.resolvedProps().readonly)
|
|
52639
|
-
return;
|
|
52640
|
-
const previousValue = this.state().selectedValue;
|
|
52641
|
-
this.state.update(s => ({
|
|
52642
|
-
...s,
|
|
52643
|
-
selectedValue: value,
|
|
52644
|
-
isSubmitted: false,
|
|
52645
|
-
error: null,
|
|
52646
|
-
}));
|
|
52647
|
-
this.reactionChange.emit({ value, previousValue });
|
|
52648
|
-
}
|
|
52649
|
-
async submitReaction() {
|
|
52650
|
-
const currentState = this.state();
|
|
52651
|
-
const props = this.resolvedProps();
|
|
52652
|
-
if (!currentState.selectedValue || props.disabled)
|
|
52653
|
-
return;
|
|
52654
|
-
this.state.update(s => ({ ...s, isLoading: true, error: null }));
|
|
52655
|
-
try {
|
|
52656
|
-
// Determinar si usar endpoint anónimo o autenticado
|
|
52657
|
-
const isAuthenticated = this.auth?.isAuthenticated() ?? false;
|
|
52658
|
-
const useAnonymous = this.props.allowAnonymous && !isAuthenticated;
|
|
52659
|
-
if (useAnonymous) {
|
|
52660
|
-
// Usar endpoint anónimo (público)
|
|
52661
|
-
await this.feedbackService.createAnonymousReaction(props.entityRef, currentState.selectedValue, currentState.comment || undefined);
|
|
52662
|
-
}
|
|
52663
|
-
else {
|
|
52664
|
-
// Usar endpoint autenticado
|
|
52665
|
-
await this.feedbackService.createReaction(props.entityRef, currentState.selectedValue, currentState.comment || undefined);
|
|
52666
|
-
}
|
|
52667
|
-
this.state.update(s => ({
|
|
52668
|
-
...s,
|
|
52669
|
-
isLoading: false,
|
|
52670
|
-
isSubmitted: true,
|
|
52671
|
-
comment: '',
|
|
52672
|
-
hadPreviousReaction: !useAnonymous, // Solo para autenticados
|
|
52673
|
-
}));
|
|
52674
|
-
this.reactionSubmit.emit({
|
|
52675
|
-
value: currentState.selectedValue,
|
|
52676
|
-
comment: currentState.comment || undefined,
|
|
52677
|
-
entityRef: props.entityRef,
|
|
52678
|
-
isUpdate: currentState.hadPreviousReaction,
|
|
52679
|
-
});
|
|
52680
|
-
if (props.showThankYou) {
|
|
52681
|
-
this.toast.show({
|
|
52682
|
-
message: props.thankYouMessage,
|
|
52683
|
-
duration: 2000,
|
|
52684
|
-
});
|
|
52685
|
-
}
|
|
52686
|
-
}
|
|
52687
|
-
catch (error) {
|
|
52688
|
-
console.error('Error submitting reaction:', error);
|
|
52689
|
-
this.state.update(s => ({
|
|
52690
|
-
...s,
|
|
52691
|
-
isLoading: false,
|
|
52692
|
-
error: this.t('errorSubmitting'),
|
|
52693
|
-
}));
|
|
52694
|
-
this.toast.show({
|
|
52695
|
-
message: this.t('errorSubmitting'),
|
|
52696
|
-
duration: 3000,
|
|
52697
|
-
});
|
|
52698
|
-
}
|
|
52699
|
-
}
|
|
52700
|
-
updateComment(event) {
|
|
52701
|
-
const value = event.detail.value || '';
|
|
52702
|
-
this.state.update(s => ({ ...s, comment: value }));
|
|
52703
|
-
}
|
|
52704
|
-
getEmoji(index) {
|
|
52705
|
-
return this.resolvedProps().emojis[index];
|
|
52706
|
-
}
|
|
52707
|
-
getEmojiLabel(index) {
|
|
52708
|
-
return this.resolvedProps().emojiLabels[index];
|
|
52709
|
-
}
|
|
52710
|
-
isSelected(value) {
|
|
52711
|
-
return this.state().selectedValue === value;
|
|
52712
|
-
}
|
|
52713
|
-
t(key) {
|
|
52714
|
-
const translations = {
|
|
52715
|
-
question: '¿Te resultó útil este contenido?',
|
|
52716
|
-
commentPlaceholder: 'Cuéntanos más (opcional)...',
|
|
52717
|
-
submit: 'Enviar opinión',
|
|
52718
|
-
update: 'Actualizar opinión',
|
|
52719
|
-
thankYou: '¡Gracias por tu opinión!',
|
|
52720
|
-
submitted: 'Tu opinión ha sido registrada',
|
|
52721
|
-
errorSubmitting: 'Error al enviar. Intenta de nuevo.',
|
|
52722
|
-
positiveLabel: 'Sí, mucho',
|
|
52723
|
-
negativeLabel: 'No tanto',
|
|
52724
|
-
negativeFeedbackTitle: '¿Cuéntanos qué no te gustó?',
|
|
52725
|
-
};
|
|
52726
|
-
return this.i18n.t(key, 'ContentReaction') || translations[key] || key;
|
|
52727
|
-
}
|
|
52728
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ContentReactionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
52729
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ContentReactionComponent, isStandalone: true, selector: "val-content-reaction", inputs: { props: "props" }, outputs: { reactionSubmit: "reactionSubmit", reactionChange: "reactionChange" }, usesOnChanges: true, ngImport: i0, template: "@if (isConfigured()) {\n<div class=\"content-reaction\" [class.disabled]=\"resolvedProps().disabled\" [class.readonly]=\"resolvedProps().readonly\">\n <!-- Loading inicial -->\n @if (state().isLoading && !state().selectedValue) {\n <div class=\"loading-container\">\n <ion-spinner name=\"crescent\"></ion-spinner>\n </div>\n } @else {\n <!-- Pregunta -->\n <p class=\"question\">\n {{ state().selectedValue === 'negative' ? t('negativeFeedbackTitle') : resolvedProps().question }}\n </p>\n\n <!-- Botones de reacci\u00F3n \u2014 variante emoji (caras, estrellas, thumbs, \u2026) -->\n @if (resolvedProps().variant === 'emoji') {\n <div class=\"reaction-buttons reaction-buttons--emoji\">\n @for (value of activeReactionValues(); track value; let i = $index) {\n <ion-button\n fill=\"clear\"\n shape=\"round\"\n [class.selected]=\"isSelected(value)\"\n [attr.aria-label]=\"resolvedProps().emojiLabels[i]\"\n [attr.aria-pressed]=\"isSelected(value)\"\n [disabled]=\"resolvedProps().disabled || resolvedProps().readonly\"\n (click)=\"selectReaction(value)\"\n >\n <span class=\"emoji-btn\">{{ resolvedProps().emojis[i] }}</span>\n </ion-button>\n }\n </div>\n } @else {\n <!-- Botones de reacci\u00F3n \u2014 variante texto (default) -->\n <div class=\"reaction-buttons\">\n <ion-button\n [fill]=\"isSelected('positive') ? 'solid' : 'outline'\"\n shape=\"round\"\n color=\"dark\"\n [attr.aria-pressed]=\"isSelected('positive')\"\n [disabled]=\"resolvedProps().disabled || resolvedProps().readonly\"\n (click)=\"selectReaction('positive')\"\n >\n {{ t('positiveLabel') }}\n </ion-button>\n <ion-button\n [fill]=\"isSelected('negative') ? 'solid' : 'outline'\"\n shape=\"round\"\n color=\"dark\"\n [attr.aria-pressed]=\"isSelected('negative')\"\n [disabled]=\"resolvedProps().disabled || resolvedProps().readonly\"\n (click)=\"selectReaction('negative')\"\n >\n {{ t('negativeLabel') }}\n </ion-button>\n </div>\n }\n\n <!-- Campo de comentario (solo si hay selecci\u00F3n) -->\n @if (showCommentField()) {\n <div class=\"comment-section\">\n <ion-textarea\n [value]=\"state().comment\"\n [placeholder]=\"resolvedProps().commentPlaceholder\"\n [maxlength]=\"resolvedProps().maxCommentLength\"\n [disabled]=\"resolvedProps().disabled\"\n [rows]=\"3\"\n class=\"comment-textarea\"\n (ionInput)=\"updateComment($event)\"\n ></ion-textarea>\n <span class=\"char-count\"> {{ state().comment.length }}/{{ resolvedProps().maxCommentLength }} </span>\n </div>\n }\n\n <!-- Bot\u00F3n de env\u00EDo -->\n @if (state().selectedValue && !state().isSubmitted) {\n <ion-button expand=\"block\" shape=\"round\" [disabled]=\"!canSubmit()\" (click)=\"submitReaction()\" class=\"submit-button\">\n @if (state().isLoading) {\n <ion-spinner name=\"crescent\"></ion-spinner>\n } @else { {{ state().hadPreviousReaction ? t('update') : t('submit') }} }\n </ion-button>\n }\n\n <!-- Mensaje de confirmaci\u00F3n -->\n @if (state().isSubmitted) {\n <p class=\"submitted-message\">{{ t('thankYou') }}</p>\n }\n\n <!-- Error -->\n @if (state().error) {\n <p class=\"error-message\">{{ state().error }}</p>\n } }\n</div>\n}\n", styles: [":host{display:block}.content-reaction{padding:16px;text-align:center}.content-reaction.disabled{opacity:.6;pointer-events:none}.content-reaction.readonly{pointer-events:none}.question{font-size:1.0625rem;font-weight:700;color:var(--ion-color-dark);margin:0 0 16px}.reaction-buttons{display:flex;justify-content:center;gap:12px;margin-bottom:20px}.reaction-buttons--emoji{gap:8px}.reaction-buttons--emoji ion-button{--padding-start: 4px;--padding-end: 4px;transition:transform .15s ease}.reaction-buttons--emoji ion-button.selected{transform:scale(1.25)}.reaction-buttons--emoji ion-button:not(.selected):not([disabled]){opacity:.55}.reaction-buttons--emoji ion-button:not(.selected):not([disabled]):hover{opacity:1}.emoji-btn{font-size:2rem;line-height:1;display:block}.comment-section{margin-top:16px;animation:slideIn .3s ease-out}.comment-section .comment-textarea{--background: transparent;--border-radius: 8px;--padding-start: 12px;--padding-end: 12px;width:100%}.comment-section .char-count{display:block;text-align:right;font-size:.75rem;color:var(--ion-color-medium);margin-top:4px}.submit-button{margin-top:16px}.submitted-message{margin-top:16px;color:var(--ion-color-success);font-weight:500;animation:fadeIn .3s ease-out}.error-message{margin-top:8px;color:var(--ion-color-danger);font-size:.875rem}.loading-container{display:flex;justify-content:center;padding:20px}@keyframes slideIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: IonTextarea, selector: "ion-textarea", inputs: ["autoGrow", "autocapitalize", "autofocus", "clearOnEdit", "color", "cols", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "maxlength", "minlength", "mode", "name", "placeholder", "readonly", "required", "rows", "shape", "spellcheck", "value", "wrap"] }] }); }
|
|
52730
|
-
}
|
|
52731
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ContentReactionComponent, decorators: [{
|
|
52732
|
-
type: Component,
|
|
52733
|
-
args: [{ selector: 'val-content-reaction', standalone: true, imports: [CommonModule, FormsModule, IonButton, IonSpinner, IonTextarea], template: "@if (isConfigured()) {\n<div class=\"content-reaction\" [class.disabled]=\"resolvedProps().disabled\" [class.readonly]=\"resolvedProps().readonly\">\n <!-- Loading inicial -->\n @if (state().isLoading && !state().selectedValue) {\n <div class=\"loading-container\">\n <ion-spinner name=\"crescent\"></ion-spinner>\n </div>\n } @else {\n <!-- Pregunta -->\n <p class=\"question\">\n {{ state().selectedValue === 'negative' ? t('negativeFeedbackTitle') : resolvedProps().question }}\n </p>\n\n <!-- Botones de reacci\u00F3n \u2014 variante emoji (caras, estrellas, thumbs, \u2026) -->\n @if (resolvedProps().variant === 'emoji') {\n <div class=\"reaction-buttons reaction-buttons--emoji\">\n @for (value of activeReactionValues(); track value; let i = $index) {\n <ion-button\n fill=\"clear\"\n shape=\"round\"\n [class.selected]=\"isSelected(value)\"\n [attr.aria-label]=\"resolvedProps().emojiLabels[i]\"\n [attr.aria-pressed]=\"isSelected(value)\"\n [disabled]=\"resolvedProps().disabled || resolvedProps().readonly\"\n (click)=\"selectReaction(value)\"\n >\n <span class=\"emoji-btn\">{{ resolvedProps().emojis[i] }}</span>\n </ion-button>\n }\n </div>\n } @else {\n <!-- Botones de reacci\u00F3n \u2014 variante texto (default) -->\n <div class=\"reaction-buttons\">\n <ion-button\n [fill]=\"isSelected('positive') ? 'solid' : 'outline'\"\n shape=\"round\"\n color=\"dark\"\n [attr.aria-pressed]=\"isSelected('positive')\"\n [disabled]=\"resolvedProps().disabled || resolvedProps().readonly\"\n (click)=\"selectReaction('positive')\"\n >\n {{ t('positiveLabel') }}\n </ion-button>\n <ion-button\n [fill]=\"isSelected('negative') ? 'solid' : 'outline'\"\n shape=\"round\"\n color=\"dark\"\n [attr.aria-pressed]=\"isSelected('negative')\"\n [disabled]=\"resolvedProps().disabled || resolvedProps().readonly\"\n (click)=\"selectReaction('negative')\"\n >\n {{ t('negativeLabel') }}\n </ion-button>\n </div>\n }\n\n <!-- Campo de comentario (solo si hay selecci\u00F3n) -->\n @if (showCommentField()) {\n <div class=\"comment-section\">\n <ion-textarea\n [value]=\"state().comment\"\n [placeholder]=\"resolvedProps().commentPlaceholder\"\n [maxlength]=\"resolvedProps().maxCommentLength\"\n [disabled]=\"resolvedProps().disabled\"\n [rows]=\"3\"\n class=\"comment-textarea\"\n (ionInput)=\"updateComment($event)\"\n ></ion-textarea>\n <span class=\"char-count\"> {{ state().comment.length }}/{{ resolvedProps().maxCommentLength }} </span>\n </div>\n }\n\n <!-- Bot\u00F3n de env\u00EDo -->\n @if (state().selectedValue && !state().isSubmitted) {\n <ion-button expand=\"block\" shape=\"round\" [disabled]=\"!canSubmit()\" (click)=\"submitReaction()\" class=\"submit-button\">\n @if (state().isLoading) {\n <ion-spinner name=\"crescent\"></ion-spinner>\n } @else { {{ state().hadPreviousReaction ? t('update') : t('submit') }} }\n </ion-button>\n }\n\n <!-- Mensaje de confirmaci\u00F3n -->\n @if (state().isSubmitted) {\n <p class=\"submitted-message\">{{ t('thankYou') }}</p>\n }\n\n <!-- Error -->\n @if (state().error) {\n <p class=\"error-message\">{{ state().error }}</p>\n } }\n</div>\n}\n", styles: [":host{display:block}.content-reaction{padding:16px;text-align:center}.content-reaction.disabled{opacity:.6;pointer-events:none}.content-reaction.readonly{pointer-events:none}.question{font-size:1.0625rem;font-weight:700;color:var(--ion-color-dark);margin:0 0 16px}.reaction-buttons{display:flex;justify-content:center;gap:12px;margin-bottom:20px}.reaction-buttons--emoji{gap:8px}.reaction-buttons--emoji ion-button{--padding-start: 4px;--padding-end: 4px;transition:transform .15s ease}.reaction-buttons--emoji ion-button.selected{transform:scale(1.25)}.reaction-buttons--emoji ion-button:not(.selected):not([disabled]){opacity:.55}.reaction-buttons--emoji ion-button:not(.selected):not([disabled]):hover{opacity:1}.emoji-btn{font-size:2rem;line-height:1;display:block}.comment-section{margin-top:16px;animation:slideIn .3s ease-out}.comment-section .comment-textarea{--background: transparent;--border-radius: 8px;--padding-start: 12px;--padding-end: 12px;width:100%}.comment-section .char-count{display:block;text-align:right;font-size:.75rem;color:var(--ion-color-medium);margin-top:4px}.submit-button{margin-top:16px}.submitted-message{margin-top:16px;color:var(--ion-color-success);font-weight:500;animation:fadeIn .3s ease-out}.error-message{margin-top:8px;color:var(--ion-color-danger);font-size:.875rem}.loading-container{display:flex;justify-content:center;padding:20px}@keyframes slideIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}\n"] }]
|
|
52734
|
-
}], ctorParameters: () => [], propDecorators: { props: [{
|
|
52735
|
-
type: Input
|
|
52736
|
-
}], reactionSubmit: [{
|
|
52737
|
-
type: Output
|
|
52738
|
-
}], reactionChange: [{
|
|
52739
|
-
type: Output
|
|
52740
|
-
}] } });
|
|
52741
|
-
|
|
52742
|
-
/**
|
|
52743
|
-
* Defaults i18n (es/en) embebidos en `val-about-view`. Auto-registrados en el
|
|
52744
|
-
* constructor del componente si el consumer no proveyó el namespace
|
|
52745
|
-
* (`Settings.About` por default). SOLO incluye las keys que la vista usa.
|
|
52746
|
-
*
|
|
52747
|
-
* Textos portados EXACTOS del override `Settings.About` de showcase
|
|
52748
|
-
* (`frontend/showcase/src/i18n/index.ts`). Las keys de las acciones
|
|
52749
|
-
* showcase-specific (`feedback*`, `share*`, `faq*`, `donate*`) NO se incluyen:
|
|
52750
|
-
* esas acciones se modelan ahora como `actions[]` de la config (el consumer
|
|
52751
|
-
* aporta sus propios textos). `copyrightText` se incluye aquí (antes salía del
|
|
52752
|
-
* namespace `Layout`) para que la vista sea autocontenida.
|
|
52753
|
-
*/
|
|
52754
|
-
const ABOUT_VIEW_I18N = {
|
|
52755
|
-
es: {
|
|
52756
|
-
pageTitle: 'Acerca de',
|
|
52757
|
-
pageDescription: 'Demo del factory Valtech',
|
|
52758
|
-
tagline: 'App de demo — explora las funcionalidades en vivo',
|
|
52759
|
-
descTitle: 'Acerca de Showcase',
|
|
52760
|
-
descBody: 'Showcase es la app de referencia del factory Valtech. Aquí puedes explorar el flujo completo en vivo: autenticación, perfil, organizaciones, notificaciones y ajustes de cuenta.',
|
|
52761
|
-
actionsTitle: 'Acciones',
|
|
52762
|
-
rateTitle: 'Calificar la app',
|
|
52763
|
-
rateDesc: 'Cuéntanos qué te ha parecido la experiencia.',
|
|
52764
|
-
rateModalTitle: 'Tu opinión',
|
|
52765
|
-
rateQuestion: '¿Qué te ha parecido la experiencia hasta ahora?',
|
|
52766
|
-
rateComment: 'Cuéntanos más (opcional)…',
|
|
52767
|
-
rateThanks: '¡Gracias por tu opinión!',
|
|
52768
|
-
rateClose: 'Cerrar',
|
|
52769
|
-
rateBad: 'No tanto',
|
|
52770
|
-
rateMid: 'Bien',
|
|
52771
|
-
rateGood: '¡Me encanta!',
|
|
52772
|
-
socialTitle: 'Síguenos',
|
|
52773
|
-
socialDesc: 'Estamos en redes sociales.',
|
|
52774
|
-
versionLabel: 'Versión',
|
|
52775
|
-
versionCopied: 'v{v} copiado',
|
|
52776
|
-
copyrightText: '© {year}, Soluciones Valtech Ltda. o sus afiliados. Todos los derechos reservados.',
|
|
52777
|
-
},
|
|
52778
|
-
en: {
|
|
52779
|
-
pageTitle: 'About',
|
|
52780
|
-
pageDescription: 'Valtech factory demo',
|
|
52781
|
-
tagline: 'Demo app — explore features live',
|
|
52782
|
-
descTitle: 'About Showcase',
|
|
52783
|
-
descBody: 'Showcase is the reference app for the Valtech factory. Explore the full flow live: authentication, profile, organizations, notifications and account settings.',
|
|
52784
|
-
actionsTitle: 'Actions',
|
|
52785
|
-
rateTitle: 'Rate the app',
|
|
52786
|
-
rateDesc: 'Tell us how your experience has been.',
|
|
52787
|
-
rateModalTitle: 'Your feedback',
|
|
52788
|
-
rateQuestion: 'How has your experience been so far?',
|
|
52789
|
-
rateComment: 'Tell us more (optional)…',
|
|
52790
|
-
rateThanks: 'Thanks for your feedback!',
|
|
52791
|
-
rateClose: 'Close',
|
|
52792
|
-
rateBad: 'Not great',
|
|
52793
|
-
rateMid: 'Good',
|
|
52794
|
-
rateGood: 'Love it!',
|
|
52795
|
-
socialTitle: 'Follow us',
|
|
52796
|
-
socialDesc: "We're on social media.",
|
|
52797
|
-
versionLabel: 'Version',
|
|
52798
|
-
versionCopied: 'v{v} copied',
|
|
52799
|
-
copyrightText: '© {year}, Soluciones Valtech Ltda. or its affiliates. All rights reserved.',
|
|
52800
|
-
},
|
|
52801
|
-
};
|
|
52802
|
-
|
|
52803
|
-
addIcons({
|
|
52804
|
-
copyOutline,
|
|
52805
|
-
starOutline,
|
|
52806
|
-
chatbubbleEllipsesOutline,
|
|
52807
|
-
shareSocialOutline,
|
|
52808
|
-
helpCircleOutline,
|
|
52809
|
-
logoFacebook,
|
|
52810
|
-
logoInstagram,
|
|
52811
|
-
logoLinkedin,
|
|
52812
|
-
logoTwitter,
|
|
52813
|
-
logoYoutube,
|
|
52814
|
-
logoTiktok,
|
|
52815
|
-
});
|
|
52816
|
-
const DEFAULT_NAMESPACE = 'Settings.About';
|
|
52817
|
-
const DEFAULT_BRAND_NAME = 'Valtech';
|
|
52818
|
-
const DEFAULT_LOGO_SRC = 'assets/images/main-icon.png';
|
|
52819
|
-
const DEFAULT_RATING_ENTITY_ID = 'experience';
|
|
52820
|
-
/**
|
|
52821
|
-
* `val-about-view` — vista About full-feature autocontenida (organism).
|
|
52822
|
-
* Promovida desde `showcase` bajo el proceso de ADR-021. Reúne:
|
|
52823
|
-
* - **HERO** — logo + nombre de marca + tagline + pill de versión (copiable).
|
|
52824
|
-
* - **Descripción** — título + cuerpo.
|
|
52825
|
-
* - **Acciones** — action-card de rating built-in (abre `val-content-reaction`
|
|
52826
|
-
* DIRECTAMENTE vía `ModalService`, sin wrapper local — decisión CTO) + las
|
|
52827
|
-
* acciones genéricas que el consumer aporte por `config.actions`.
|
|
52828
|
-
* - **Redes** — links sociales (`config.socialLinks`); sección oculta si vacía.
|
|
52829
|
-
* - **Footer** — copyright con el año actual.
|
|
52830
|
-
*
|
|
52831
|
-
* Lo app-specific (logo, nombre, versión, redes, acciones share/faq) viaja como
|
|
52832
|
-
* DATA de config — NO como slots (ADR-021). La versión la pasa el consumer
|
|
52833
|
-
* (`config.version` = su `APP_VERSION`); la lib NO importa el `version.ts` de la
|
|
52834
|
-
* app. Si no se pasa versión, el pill se oculta.
|
|
52835
|
-
*
|
|
52836
|
-
* NO renderiza ion-content — vive dentro de val-page-wrapper. `ActivatedRoute`
|
|
52837
|
-
* se inyecta `{ optional: true }` solo para leer el route data de config.
|
|
52838
|
-
*
|
|
52839
|
-
* Auto-registra sus defaults i18n (es/en) en el constructor si el consumer no
|
|
52840
|
-
* proveyó el namespace configurado (default `Settings.About`).
|
|
52841
|
-
*
|
|
52842
|
-
* GOTCHA i18n ContentReaction: `val-content-reaction` exige su namespace
|
|
52843
|
-
* `ContentReaction` registrado donde se use (key faltante en binding + CD =
|
|
52844
|
-
* navegador congelado en dev). `ContentReactionComponent` se auto-registra ese
|
|
52845
|
-
* namespace en SU constructor, y como se abre vía `ModalService` ese constructor
|
|
52846
|
-
* corre antes de que su template binde — queda cubierto. Igual lo importamos
|
|
52847
|
-
* como dependencia explícita de esta vista para que la garantía sea local.
|
|
52848
|
-
*/
|
|
52849
|
-
class AboutViewComponent {
|
|
52850
|
-
/** Namespace i18n resuelto (capturado para llamadas no-reactivas). */
|
|
52851
|
-
get ns() {
|
|
52852
|
-
return this.resolvedConfig().i18nNamespace;
|
|
52853
|
-
}
|
|
52854
|
-
constructor() {
|
|
52855
|
-
this.nav = inject(NavigationService);
|
|
52856
|
-
this.i18n = inject(I18nService);
|
|
52857
|
-
this.modalService = inject(ModalService);
|
|
52858
|
-
this.toast = inject(ToastService);
|
|
52859
|
-
this.route = inject(ActivatedRoute, { optional: true });
|
|
52860
|
-
this.resolvedConfig = computed(() => {
|
|
52861
|
-
const fromRoute = (this.route?.snapshot.data['aboutConfig'] ?? {});
|
|
52862
|
-
const merged = { ...fromRoute, ...(this.config ?? {}) };
|
|
52863
|
-
return {
|
|
52864
|
-
brand: {
|
|
52865
|
-
name: merged.brand?.name ?? DEFAULT_BRAND_NAME,
|
|
52866
|
-
logoSrc: merged.brand?.logoSrc ?? DEFAULT_LOGO_SRC,
|
|
52867
|
-
},
|
|
52868
|
-
version: merged.version ?? '',
|
|
52869
|
-
socialLinks: merged.socialLinks ?? [],
|
|
52870
|
-
showRating: merged.showRating ?? true,
|
|
52871
|
-
ratingEntityId: merged.ratingEntityId ?? DEFAULT_RATING_ENTITY_ID,
|
|
52872
|
-
actions: merged.actions ?? [],
|
|
52873
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE,
|
|
52874
|
-
onRated: merged.onRated,
|
|
52875
|
-
};
|
|
52876
|
-
});
|
|
52877
|
-
this.brandName = computed(() => this.resolvedConfig().brand.name);
|
|
52878
|
-
this.logoSrc = computed(() => this.resolvedConfig().brand.logoSrc);
|
|
52879
|
-
this.version = computed(() => this.resolvedConfig().version);
|
|
52880
|
-
this.socialLinks = computed(() => this.resolvedConfig().socialLinks);
|
|
52881
|
-
this.showRating = computed(() => this.resolvedConfig().showRating);
|
|
52882
|
-
this.actions = computed(() => this.resolvedConfig().actions);
|
|
52883
|
-
/** Copyright del footer — año actual interpolado en `copyrightText`. */
|
|
52884
|
-
this.copyright = computed(() => {
|
|
52885
|
-
this.i18n.lang();
|
|
52886
|
-
const year = String(new Date().getFullYear());
|
|
52887
|
-
return this.tt('copyrightText').replace('{year}', year);
|
|
52888
|
-
});
|
|
52889
|
-
/** Title metadata para secciones — bold + size small. */
|
|
52890
|
-
this.rateActionCard = computed(() => {
|
|
52891
|
-
this.i18n.lang();
|
|
52892
|
-
return {
|
|
52893
|
-
icon: { ionicon: 'star-outline', color: 'primary' },
|
|
52894
|
-
title: this.tt('rateTitle'),
|
|
52895
|
-
description: this.tt('rateDesc'),
|
|
52896
|
-
size: 'medium',
|
|
52897
|
-
bordered: false,
|
|
52898
|
-
shadowed: false,
|
|
52899
|
-
};
|
|
52900
|
-
});
|
|
52901
|
-
const ns = this.ns;
|
|
52902
|
-
if (!this.i18n.hasNamespace(ns)) {
|
|
52903
|
-
this.i18n.registerContent(ns, ABOUT_VIEW_I18N);
|
|
52904
|
-
}
|
|
52905
|
-
this.nav.setBackHeader('pageTitle', ns, { withMenu: true });
|
|
52906
|
-
}
|
|
52907
|
-
/** Helper i18n bound al namespace resuelto. Reactivo vía `lang()`. */
|
|
52908
|
-
tt(key) {
|
|
52909
|
-
this.i18n.lang();
|
|
52910
|
-
return this.i18n.t(key, this.ns);
|
|
52911
|
-
}
|
|
52912
|
-
/** Title metadata para secciones — bold + size small. */
|
|
52913
|
-
sectionTitle(key) {
|
|
52914
|
-
this.i18n.lang();
|
|
52915
|
-
return {
|
|
52916
|
-
content: this.tt(key),
|
|
52917
|
-
size: 'small',
|
|
52918
|
-
color: 'dark',
|
|
52919
|
-
bold: true,
|
|
52920
|
-
};
|
|
52921
|
-
}
|
|
52922
|
-
/** ActionCardMetadata para una acción genérica del consumer. */
|
|
52923
|
-
extraActionCard(action) {
|
|
52924
|
-
return {
|
|
52925
|
-
icon: { ionicon: action.icon ?? 'chatbubble-ellipses-outline', color: 'primary' },
|
|
52926
|
-
title: action.label,
|
|
52927
|
-
description: action.description,
|
|
52928
|
-
size: 'medium',
|
|
52929
|
-
bordered: false,
|
|
52930
|
-
shadowed: false,
|
|
52931
|
-
};
|
|
52932
|
-
}
|
|
52933
|
-
/** Copia la versión al portapapeles + toast (color dark). */
|
|
52934
|
-
async copyVersion() {
|
|
52935
|
-
const v = this.version();
|
|
52936
|
-
if (!v)
|
|
52937
|
-
return;
|
|
52938
|
-
try {
|
|
52939
|
-
await navigator.clipboard.writeText(v);
|
|
52940
|
-
this.toast.show({
|
|
52941
|
-
message: this.tt('versionCopied').replace('{v}', v),
|
|
52942
|
-
color: 'dark',
|
|
52943
|
-
duration: 1500,
|
|
52944
|
-
});
|
|
52945
|
-
}
|
|
52946
|
-
catch {
|
|
52947
|
-
// clipboard no disponible — silencioso
|
|
52948
|
-
}
|
|
52949
|
-
}
|
|
52950
|
-
/** Abre una URL externa en nueva tab. `mailto:` queda en la misma tab. */
|
|
52951
|
-
openUrl(url) {
|
|
52952
|
-
if (url.startsWith('mailto:')) {
|
|
52953
|
-
window.location.href = url;
|
|
52954
|
-
return;
|
|
52955
|
-
}
|
|
52956
|
-
window.open(url, '_blank', 'noopener,noreferrer');
|
|
52957
|
-
}
|
|
52958
|
-
/**
|
|
52959
|
-
* "Calificar la app" — abre `val-content-reaction` DIRECTAMENTE como sheet
|
|
52960
|
-
* modal (sin wrapper local — decisión CTO). El componente persiste la reacción
|
|
52961
|
-
* contra el backend de feedback y muestra su propio estado de "gracias"; el
|
|
52962
|
-
* sheet se cierra arrastrando (breakpoint 0). El namespace i18n
|
|
52963
|
-
* `ContentReaction` lo auto-registra `ContentReactionComponent` en su
|
|
52964
|
-
* constructor, que corre al crear el modal — sin riesgo de key faltante.
|
|
52965
|
-
*
|
|
52966
|
-
* Sheet (bottom sheet): el contenido scrollea dentro y el botón "Enviar" queda
|
|
52967
|
-
* siempre alcanzable, también en viewports chicos.
|
|
52968
|
-
*/
|
|
52969
|
-
async openRating() {
|
|
52970
|
-
const reactionProps = {
|
|
52971
|
-
// entityType "app" distingue esta reacción de las de artículos/FAQs.
|
|
52972
|
-
entityRef: { entityType: 'app', entityId: this.resolvedConfig().ratingEntityId },
|
|
52973
|
-
question: this.tt('rateQuestion'),
|
|
52974
|
-
commentPlaceholder: this.tt('rateComment'),
|
|
52975
|
-
thankYouMessage: this.tt('rateThanks'),
|
|
52976
|
-
showComment: true,
|
|
52977
|
-
showThankYou: true,
|
|
52978
|
-
// Modal one-shot: NO bloquear el render con el check de rating previo.
|
|
52979
|
-
skipInitialCheck: true,
|
|
52980
|
-
emojis: ['😕', '🙂', '😍'],
|
|
52981
|
-
emojiLabels: [this.tt('rateBad'), this.tt('rateMid'), this.tt('rateGood')],
|
|
52982
|
-
};
|
|
52983
|
-
await this.modalService.open({
|
|
52984
|
-
component: ContentReactionComponent,
|
|
52985
|
-
componentProps: { props: reactionProps },
|
|
52986
|
-
breakpoints: {
|
|
52987
|
-
initialBreakpoint: 0.9,
|
|
52988
|
-
breakpoints: [0, 0.9, 1],
|
|
52989
|
-
showHandle: true,
|
|
52990
|
-
handleBehavior: 'cycle',
|
|
52991
|
-
},
|
|
52992
|
-
});
|
|
52993
|
-
this.resolvedConfig().onRated?.();
|
|
52994
|
-
}
|
|
52995
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AboutViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
52996
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: AboutViewComponent, isStandalone: true, selector: "val-about-view", inputs: { config: "config" }, ngImport: i0, template: `
|
|
52997
|
-
<ion-grid class="about-grid">
|
|
52998
|
-
<!-- HERO: logo + name + version -->
|
|
52999
|
-
<div class="about-hero">
|
|
53000
|
-
<img class="about-hero__logo" [src]="logoSrc()" [alt]="brandName()" />
|
|
53001
|
-
<val-title
|
|
53002
|
-
[props]="{
|
|
53003
|
-
content: brandName(),
|
|
53004
|
-
size: 'xlarge',
|
|
53005
|
-
color: 'dark',
|
|
53006
|
-
bold: true,
|
|
53007
|
-
}"
|
|
53008
|
-
/>
|
|
53009
|
-
<val-text
|
|
53010
|
-
[props]="{
|
|
53011
|
-
content: tt('tagline'),
|
|
53012
|
-
size: 'medium',
|
|
53013
|
-
color: 'dark',
|
|
53014
|
-
bold: false,
|
|
53015
|
-
}"
|
|
53016
|
-
/>
|
|
53017
|
-
@if (version()) {
|
|
53018
|
-
<div
|
|
53019
|
-
class="version-row"
|
|
53020
|
-
(click)="copyVersion()"
|
|
53021
|
-
role="button"
|
|
53022
|
-
[attr.aria-label]="tt('versionLabel') + ' ' + version()"
|
|
53023
|
-
>
|
|
53024
|
-
<val-pill
|
|
53025
|
-
[props]="{
|
|
53026
|
-
label: tt('versionLabel') + ' ' + version(),
|
|
53027
|
-
color: 'dark',
|
|
53028
|
-
weight: 'bold',
|
|
53029
|
-
size: 'small',
|
|
53030
|
-
}"
|
|
53031
|
-
/>
|
|
53032
|
-
<ion-icon name="copy-outline" class="version-copy-icon" />
|
|
53033
|
-
</div>
|
|
53034
|
-
}
|
|
53035
|
-
</div>
|
|
53036
|
-
|
|
53037
|
-
<!-- DESCRIPTION -->
|
|
53038
|
-
<section class="about-section">
|
|
53039
|
-
<val-title [props]="sectionTitle('descTitle')" />
|
|
53040
|
-
<val-text
|
|
53041
|
-
[props]="{
|
|
53042
|
-
content: tt('descBody'),
|
|
53043
|
-
size: 'medium',
|
|
53044
|
-
color: 'dark',
|
|
53045
|
-
bold: false,
|
|
53046
|
-
}"
|
|
53047
|
-
/>
|
|
53048
|
-
</section>
|
|
53049
|
-
|
|
53050
|
-
<!-- ACTIONS — rating built-in + acciones del consumer. -->
|
|
53051
|
-
@if (showRating() || actions().length > 0) {
|
|
53052
|
-
<section class="about-section about-section--reviews">
|
|
53053
|
-
<val-title [props]="sectionTitle('actionsTitle')" />
|
|
53054
|
-
<div class="about-actions">
|
|
53055
|
-
@if (showRating()) {
|
|
53056
|
-
<val-action-card [props]="rateActionCard()" (onClick)="openRating()" />
|
|
53057
|
-
}
|
|
53058
|
-
@for (action of actions(); track action.label) {
|
|
53059
|
-
<val-action-card [props]="extraActionCard(action)" (onClick)="action.onClick()" />
|
|
53060
|
-
}
|
|
53061
|
-
</div>
|
|
53062
|
-
</section>
|
|
53063
|
-
}
|
|
53064
|
-
|
|
53065
|
-
<!-- SOCIAL — penúltimo, justo antes del footer de derechos. -->
|
|
53066
|
-
@if (socialLinks().length > 0) {
|
|
53067
|
-
<section class="about-section">
|
|
53068
|
-
<val-title [props]="sectionTitle('socialTitle')" />
|
|
53069
|
-
<val-text
|
|
53070
|
-
[props]="{
|
|
53071
|
-
content: tt('socialDesc'),
|
|
53072
|
-
size: 'medium',
|
|
53073
|
-
color: 'dark',
|
|
53074
|
-
bold: false,
|
|
53075
|
-
}"
|
|
53076
|
-
/>
|
|
53077
|
-
<div class="about-social">
|
|
53078
|
-
@for (s of socialLinks(); track s.url) {
|
|
53079
|
-
<ion-button
|
|
53080
|
-
fill="clear"
|
|
53081
|
-
size="small"
|
|
53082
|
-
class="social-btn"
|
|
53083
|
-
[attr.aria-label]="s.label"
|
|
53084
|
-
(click)="openUrl(s.url)"
|
|
53085
|
-
>
|
|
53086
|
-
<ion-icon [name]="s.icon" slot="icon-only" />
|
|
53087
|
-
</ion-button>
|
|
53088
|
-
}
|
|
53089
|
-
</div>
|
|
53090
|
-
</section>
|
|
53091
|
-
}
|
|
53092
|
-
|
|
53093
|
-
<!-- FOOTER -->
|
|
53094
|
-
<footer class="about-footer">
|
|
53095
|
-
<val-text
|
|
53096
|
-
[props]="{
|
|
53097
|
-
content: copyright(),
|
|
53098
|
-
size: 'small',
|
|
53099
|
-
color: 'dark',
|
|
53100
|
-
bold: false,
|
|
53101
|
-
}"
|
|
53102
|
-
/>
|
|
53103
|
-
</footer>
|
|
53104
|
-
</ion-grid>
|
|
53105
|
-
`, isInline: true, styles: [":host{display:block}.about-grid{padding:16px 0;max-width:720px;margin:0 auto}.about-hero{display:flex;flex-direction:column;align-items:center;gap:8px;padding:24px 0 16px;text-align:center}.about-hero__logo{height:96px;width:auto;display:block}.version-row{display:flex;align-items:center;gap:6px;cursor:pointer;opacity:.85;transition:opacity .15s ease}.version-row:hover{opacity:1}.version-copy-icon{font-size:14px;color:var(--ion-color-medium)}.about-section{padding:16px 0 8px;display:flex;flex-direction:column;gap:8px}.about-actions{display:flex;flex-direction:column;gap:8px}.about-section--reviews val-action-card{display:block}.about-section--reviews val-action-card ::ng-deep .action-card{background:var(--ion-color-light, #f4f5f8);box-shadow:none}.about-section--reviews val-action-card ::ng-deep .action-card__description{color:var(--ion-color-dark);opacity:.7}.about-social{display:flex;flex-wrap:wrap;gap:10px;padding-top:8px}.about-social .social-btn{--border-radius: 50%;--background: var(--ion-color-light, #f4f5f8);--color: var(--ion-color-dark);--padding-start: 0;--padding-end: 0;width:48px;height:48px;margin:0;transition:transform .15s ease}.about-social .social-btn:hover{--background: var(--ion-color-primary-tint, #8a4ce5);--color: #fff;transform:translateY(-2px)}.about-social .social-btn ion-icon{font-size:22px}.about-footer{display:flex;flex-direction:column;align-items:center;gap:4px;padding:24px 0;text-align:center}:host-context(body.dark) val-action-card ::ng-deep .action-card,:host-context(html.ion-palette-dark) val-action-card ::ng-deep .action-card,:host-context([data-theme=\"dark\"]) val-action-card ::ng-deep .action-card{background:#ffffff0a}:host-context(body.dark) .about-section--reviews val-action-card ::ng-deep .action-card:hover,:host-context(html.ion-palette-dark) .about-section--reviews val-action-card ::ng-deep .action-card:hover,:host-context([data-theme=\"dark\"]) .about-section--reviews val-action-card ::ng-deep .action-card:hover{background:#ffffff14}:host-context(body.dark) .about-social .social-btn,:host-context(html.ion-palette-dark) .about-social .social-btn,:host-context([data-theme=\"dark\"]) .about-social .social-btn{--background: rgba(255, 255, 255, .04)}\n"], dependencies: [{ kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: PillComponent, selector: "val-pill", inputs: ["preset", "props"], outputs: ["pillClick", "pillAction"] }, { kind: "component", type: TitleComponent, selector: "val-title", inputs: ["props"] }, { kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }, { kind: "component", type: ActionCardComponent, selector: "val-action-card", inputs: ["props"], outputs: ["onClick"] }] }); }
|
|
53106
|
-
}
|
|
53107
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AboutViewComponent, decorators: [{
|
|
53108
|
-
type: Component,
|
|
53109
|
-
args: [{ selector: 'val-about-view', standalone: true, imports: [IonButton, IonGrid, IonIcon, PillComponent, TitleComponent, TextComponent, ActionCardComponent], template: `
|
|
53110
|
-
<ion-grid class="about-grid">
|
|
53111
|
-
<!-- HERO: logo + name + version -->
|
|
53112
|
-
<div class="about-hero">
|
|
53113
|
-
<img class="about-hero__logo" [src]="logoSrc()" [alt]="brandName()" />
|
|
53114
|
-
<val-title
|
|
53115
|
-
[props]="{
|
|
53116
|
-
content: brandName(),
|
|
53117
|
-
size: 'xlarge',
|
|
53118
|
-
color: 'dark',
|
|
53119
|
-
bold: true,
|
|
53120
|
-
}"
|
|
53121
|
-
/>
|
|
53122
|
-
<val-text
|
|
53123
|
-
[props]="{
|
|
53124
|
-
content: tt('tagline'),
|
|
53125
|
-
size: 'medium',
|
|
53126
|
-
color: 'dark',
|
|
53127
|
-
bold: false,
|
|
53128
|
-
}"
|
|
53129
|
-
/>
|
|
53130
|
-
@if (version()) {
|
|
53131
|
-
<div
|
|
53132
|
-
class="version-row"
|
|
53133
|
-
(click)="copyVersion()"
|
|
53134
|
-
role="button"
|
|
53135
|
-
[attr.aria-label]="tt('versionLabel') + ' ' + version()"
|
|
53136
|
-
>
|
|
53137
|
-
<val-pill
|
|
53138
|
-
[props]="{
|
|
53139
|
-
label: tt('versionLabel') + ' ' + version(),
|
|
53140
|
-
color: 'dark',
|
|
53141
|
-
weight: 'bold',
|
|
53142
|
-
size: 'small',
|
|
53143
|
-
}"
|
|
53144
|
-
/>
|
|
53145
|
-
<ion-icon name="copy-outline" class="version-copy-icon" />
|
|
53146
|
-
</div>
|
|
53147
|
-
}
|
|
53148
|
-
</div>
|
|
53149
|
-
|
|
53150
|
-
<!-- DESCRIPTION -->
|
|
53151
|
-
<section class="about-section">
|
|
53152
|
-
<val-title [props]="sectionTitle('descTitle')" />
|
|
53153
|
-
<val-text
|
|
53154
|
-
[props]="{
|
|
53155
|
-
content: tt('descBody'),
|
|
53156
|
-
size: 'medium',
|
|
53157
|
-
color: 'dark',
|
|
53158
|
-
bold: false,
|
|
53159
|
-
}"
|
|
53160
|
-
/>
|
|
53161
|
-
</section>
|
|
53162
|
-
|
|
53163
|
-
<!-- ACTIONS — rating built-in + acciones del consumer. -->
|
|
53164
|
-
@if (showRating() || actions().length > 0) {
|
|
53165
|
-
<section class="about-section about-section--reviews">
|
|
53166
|
-
<val-title [props]="sectionTitle('actionsTitle')" />
|
|
53167
|
-
<div class="about-actions">
|
|
53168
|
-
@if (showRating()) {
|
|
53169
|
-
<val-action-card [props]="rateActionCard()" (onClick)="openRating()" />
|
|
53170
|
-
}
|
|
53171
|
-
@for (action of actions(); track action.label) {
|
|
53172
|
-
<val-action-card [props]="extraActionCard(action)" (onClick)="action.onClick()" />
|
|
53173
|
-
}
|
|
53174
|
-
</div>
|
|
53175
|
-
</section>
|
|
53176
|
-
}
|
|
53177
|
-
|
|
53178
|
-
<!-- SOCIAL — penúltimo, justo antes del footer de derechos. -->
|
|
53179
|
-
@if (socialLinks().length > 0) {
|
|
53180
|
-
<section class="about-section">
|
|
53181
|
-
<val-title [props]="sectionTitle('socialTitle')" />
|
|
53182
|
-
<val-text
|
|
53183
|
-
[props]="{
|
|
53184
|
-
content: tt('socialDesc'),
|
|
53185
|
-
size: 'medium',
|
|
53186
|
-
color: 'dark',
|
|
53187
|
-
bold: false,
|
|
53188
|
-
}"
|
|
53189
|
-
/>
|
|
53190
|
-
<div class="about-social">
|
|
53191
|
-
@for (s of socialLinks(); track s.url) {
|
|
53192
|
-
<ion-button
|
|
53193
|
-
fill="clear"
|
|
53194
|
-
size="small"
|
|
53195
|
-
class="social-btn"
|
|
53196
|
-
[attr.aria-label]="s.label"
|
|
53197
|
-
(click)="openUrl(s.url)"
|
|
53198
|
-
>
|
|
53199
|
-
<ion-icon [name]="s.icon" slot="icon-only" />
|
|
53200
|
-
</ion-button>
|
|
53201
|
-
}
|
|
53202
|
-
</div>
|
|
53203
|
-
</section>
|
|
53204
|
-
}
|
|
53205
|
-
|
|
53206
|
-
<!-- FOOTER -->
|
|
53207
|
-
<footer class="about-footer">
|
|
53208
|
-
<val-text
|
|
53209
|
-
[props]="{
|
|
53210
|
-
content: copyright(),
|
|
53211
|
-
size: 'small',
|
|
53212
|
-
color: 'dark',
|
|
53213
|
-
bold: false,
|
|
53214
|
-
}"
|
|
53215
|
-
/>
|
|
53216
|
-
</footer>
|
|
53217
|
-
</ion-grid>
|
|
53218
|
-
`, styles: [":host{display:block}.about-grid{padding:16px 0;max-width:720px;margin:0 auto}.about-hero{display:flex;flex-direction:column;align-items:center;gap:8px;padding:24px 0 16px;text-align:center}.about-hero__logo{height:96px;width:auto;display:block}.version-row{display:flex;align-items:center;gap:6px;cursor:pointer;opacity:.85;transition:opacity .15s ease}.version-row:hover{opacity:1}.version-copy-icon{font-size:14px;color:var(--ion-color-medium)}.about-section{padding:16px 0 8px;display:flex;flex-direction:column;gap:8px}.about-actions{display:flex;flex-direction:column;gap:8px}.about-section--reviews val-action-card{display:block}.about-section--reviews val-action-card ::ng-deep .action-card{background:var(--ion-color-light, #f4f5f8);box-shadow:none}.about-section--reviews val-action-card ::ng-deep .action-card__description{color:var(--ion-color-dark);opacity:.7}.about-social{display:flex;flex-wrap:wrap;gap:10px;padding-top:8px}.about-social .social-btn{--border-radius: 50%;--background: var(--ion-color-light, #f4f5f8);--color: var(--ion-color-dark);--padding-start: 0;--padding-end: 0;width:48px;height:48px;margin:0;transition:transform .15s ease}.about-social .social-btn:hover{--background: var(--ion-color-primary-tint, #8a4ce5);--color: #fff;transform:translateY(-2px)}.about-social .social-btn ion-icon{font-size:22px}.about-footer{display:flex;flex-direction:column;align-items:center;gap:4px;padding:24px 0;text-align:center}:host-context(body.dark) val-action-card ::ng-deep .action-card,:host-context(html.ion-palette-dark) val-action-card ::ng-deep .action-card,:host-context([data-theme=\"dark\"]) val-action-card ::ng-deep .action-card{background:#ffffff0a}:host-context(body.dark) .about-section--reviews val-action-card ::ng-deep .action-card:hover,:host-context(html.ion-palette-dark) .about-section--reviews val-action-card ::ng-deep .action-card:hover,:host-context([data-theme=\"dark\"]) .about-section--reviews val-action-card ::ng-deep .action-card:hover{background:#ffffff14}:host-context(body.dark) .about-social .social-btn,:host-context(html.ion-palette-dark) .about-social .social-btn,:host-context([data-theme=\"dark\"]) .about-social .social-btn{--background: rgba(255, 255, 255, .04)}\n"] }]
|
|
53219
|
-
}], ctorParameters: () => [], propDecorators: { config: [{
|
|
53220
|
-
type: Input
|
|
53221
|
-
}] } });
|
|
53222
|
-
|
|
53223
|
-
/**
|
|
53224
|
-
* Configuración acotada de `val-about-view` (object-first). La vista About es
|
|
53225
|
-
* app-specific por naturaleza (logo, nombre, versión, redes, acciones extra),
|
|
53226
|
-
* así que lo propio de cada app se parametriza como **DATA de config** — NO como
|
|
53227
|
-
* slots arbitrarios (ADR-021: una vista full-feature no abre slots; si falta
|
|
53228
|
-
* algo, se promueve un nuevo punto de extensión).
|
|
53229
|
-
*
|
|
53230
|
-
* Ejes de variación permitidos:
|
|
53231
|
-
* - **branding** — `brand.name` / `brand.logoSrc` (qué muestra el HERO).
|
|
53232
|
-
* - **versión** — `version` la pasa el consumer (la lib NO puede importar el
|
|
53233
|
-
* `version.ts` de la app). Si no se pasa, se oculta el pill de versión.
|
|
53234
|
-
* - **redes** — `socialLinks`; si está vacío se oculta la sección social.
|
|
53235
|
-
* - **rating** — `showRating` + `ratingEntityId` + `onRated`.
|
|
53236
|
-
* - **acciones extra** — `actions[]` genéricas que el consumer agrega junto a
|
|
53237
|
-
* la acción de rating built-in.
|
|
53238
|
-
* - **branding i18n** — `i18nNamespace` (default `'Settings.About'`).
|
|
53239
|
-
*/
|
|
53240
|
-
|
|
53241
|
-
/**
|
|
53242
|
-
* Helper para montar la vista About (`val-about-view`) como ruta en una app del
|
|
53243
|
-
* factory. El `config` se pasa por route `data` (`aboutConfig`) y el componente
|
|
53244
|
-
* lo lee como fallback de su `@Input() config` (el `@Input` gana).
|
|
53245
|
-
*
|
|
53246
|
-
* @example
|
|
53247
|
-
* ```ts
|
|
53248
|
-
* // settings.routes.ts
|
|
53249
|
-
* import { APP_VERSION } from '../version';
|
|
53250
|
-
*
|
|
53251
|
-
* export const settingsRoutes: Routes = [
|
|
53252
|
-
* ...provideValtechAboutRoutes({ config: { version: APP_VERSION } }), // → /app/about
|
|
53253
|
-
* { path: 'preferences', loadComponent: () => ... },
|
|
53254
|
-
* ];
|
|
53255
|
-
*
|
|
53256
|
-
* // con redes y acciones extra:
|
|
53257
|
-
* ...provideValtechAboutRoutes({
|
|
53258
|
-
* config: {
|
|
53259
|
-
* version: APP_VERSION,
|
|
53260
|
-
* socialLinks: VALTECH_SOCIAL_LINKS.map(s => ({ icon: s.icon, url: s.url, label: s.name })),
|
|
53261
|
-
* actions: [{ label: 'Compartir', icon: 'share-social-outline', onClick: () => share() }],
|
|
53262
|
-
* },
|
|
53263
|
-
* }),
|
|
53264
|
-
* ```
|
|
53265
|
-
*/
|
|
53266
|
-
function provideValtechAboutRoutes(opts) {
|
|
53267
|
-
return [
|
|
53268
|
-
{
|
|
53269
|
-
path: opts?.path ?? 'about',
|
|
53270
|
-
component: AboutViewComponent,
|
|
53271
|
-
data: { aboutConfig: opts?.config },
|
|
53272
|
-
},
|
|
53273
|
-
];
|
|
53274
|
-
}
|
|
53275
|
-
|
|
53276
52500
|
/** Built-in label sets for the three platform locales. */
|
|
53277
52501
|
const CALLOUT_LABELS = {
|
|
53278
52502
|
es: {
|
|
@@ -54829,11 +54053,15 @@ class AuthBackgroundComponent {
|
|
|
54829
54053
|
const isThick = i % 5 === 0;
|
|
54830
54054
|
const isMedium = i % 3 === 0 && !isThick;
|
|
54831
54055
|
const amplitude = 10 + Math.random() * 20;
|
|
54832
|
-
|
|
54056
|
+
// Frecuencia ENTERA (ciclos completos sobre el ancho 1440). Imprescindible
|
|
54057
|
+
// para el loop seamless: con freq entero, path(x) === path(x ± 1440), así
|
|
54058
|
+
// el translateX de una vuelta (1440px) calza exacto y NO hay salto/corte.
|
|
54059
|
+
const frequency = 1 + Math.floor(Math.random() * 3); // 1 | 2 | 3
|
|
54833
54060
|
const phase = Math.random() * Math.PI * 2;
|
|
54834
|
-
// Path extendido
|
|
54835
|
-
|
|
54836
|
-
|
|
54061
|
+
// Path extendido a -1480 .. 2920 (≥ una vuelta de bleed a cada lado) para
|
|
54062
|
+
// que el desplazamiento de ±1440px nunca deje el viewBox sin onda.
|
|
54063
|
+
let path = `M-1480,${y}`;
|
|
54064
|
+
for (let x = -1480; x <= 2920; x += 40) {
|
|
54837
54065
|
const waveY = y + amplitude * Math.sin((x / 1440) * Math.PI * frequency * 2 + phase);
|
|
54838
54066
|
path += ` L${x},${waveY.toFixed(1)}`;
|
|
54839
54067
|
}
|
|
@@ -54844,12 +54072,12 @@ class AuthBackgroundComponent {
|
|
|
54844
54072
|
color,
|
|
54845
54073
|
thickness: isThick ? 1.2 : isMedium ? 0.7 : 0.3,
|
|
54846
54074
|
opacity: isThick ? 0.5 : isMedium ? 0.4 : 0.3,
|
|
54847
|
-
//
|
|
54848
|
-
|
|
54849
|
-
|
|
54850
|
-
//
|
|
54851
|
-
travelDuration:
|
|
54852
|
-
travelDelay: -Math.random() *
|
|
54075
|
+
// Drift vertical sutil (no "equalizer"): da vida sin saltos.
|
|
54076
|
+
bob: 4 + Math.random() * 10,
|
|
54077
|
+
// Flujo horizontal continuo. Duraciones variadas = parallax/profundidad.
|
|
54078
|
+
// delay negativo desincroniza el arranque de cada capa.
|
|
54079
|
+
travelDuration: 14 + Math.random() * 22,
|
|
54080
|
+
travelDelay: -Math.random() * 30,
|
|
54853
54081
|
travelDirection: i % 2 === 0 ? 'right' : 'left',
|
|
54854
54082
|
};
|
|
54855
54083
|
});
|
|
@@ -54874,8 +54102,7 @@ class AuthBackgroundComponent {
|
|
|
54874
54102
|
[class.travel-left]="wave.travelDirection === 'left'"
|
|
54875
54103
|
[class.travel-right]="wave.travelDirection === 'right'"
|
|
54876
54104
|
[style.opacity]="wave.opacity"
|
|
54877
|
-
[style.--
|
|
54878
|
-
[style.--pulse-delay]="wave.pulseDelay + 's'"
|
|
54105
|
+
[style.--bob]="wave.bob + 'px'"
|
|
54879
54106
|
[style.--travel-duration]="wave.travelDuration + 's'"
|
|
54880
54107
|
[style.--travel-delay]="wave.travelDelay + 's'"
|
|
54881
54108
|
/>
|
|
@@ -54887,7 +54114,7 @@ class AuthBackgroundComponent {
|
|
|
54887
54114
|
<ng-content></ng-content>
|
|
54888
54115
|
</div>
|
|
54889
54116
|
</section>
|
|
54890
|
-
`, isInline: true, styles: [":host{display:block;--auth-bg-start: #ffffff;--auth-bg-mid: #f8f9fa;--auth-bg-end: #f0f0f0;--auth-glass-bg: rgba(255, 255, 255, .3);--auth-grain-opacity: .035;--auth-wave-color: var(--ion-color-primary, #6366f1)}:host-context(body.dark),:host-context(.dark),:host-context(.ion-palette-dark),:host-context(html.ion-palette-dark),:host-context([data-theme=\"dark\"]){--auth-bg-start: #0f0f1a;--auth-bg-mid: #1a1a2e;--auth-bg-end: #16213e;--auth-glass-bg: rgba(0, 0, 0, .3);--auth-grain-opacity: .05;--auth-wave-color: var(--ion-color-primary, #818cf8)}.auth-background{position:relative;display:flex;align-items:center;padding:0;background:linear-gradient(135deg,var(--auth-bg-start) 0%,var(--auth-bg-mid) 50%,var(--auth-bg-end) 100%);overflow:hidden}.grain{position:absolute;inset:0;pointer-events:none;z-index:0;opacity:var(--auth-grain-opacity);background-image:url(\"data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.5' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E\")}.glass-layer{position:absolute;inset:0;pointer-events:none;z-index:1;background:var(--auth-glass-bg);backdrop-filter:blur(3px) saturate(120%);-webkit-backdrop-filter:blur(3px) saturate(120%)}.wave-bg{position:absolute;inset:0;pointer-events:none;z-index:0;transition:filter .3s ease}:host-context(body.dark) .wave-bg,:host-context(.dark) .wave-bg,:host-context(.ion-palette-dark) .wave-bg,:host-context(html.ion-palette-dark) .wave-bg,:host-context([data-theme=\"dark\"]) .wave-bg{filter:invert(1) opacity(.6)}.waves{width:100%;height:100%;overflow:visible}.waves path{fill:none;
|
|
54117
|
+
`, isInline: true, styles: [":host{display:block;--auth-bg-start: #ffffff;--auth-bg-mid: #f8f9fa;--auth-bg-end: #f0f0f0;--auth-glass-bg: rgba(255, 255, 255, .3);--auth-grain-opacity: .035;--auth-wave-color: var(--ion-color-primary, #6366f1)}:host-context(body.dark),:host-context(.dark),:host-context(.ion-palette-dark),:host-context(html.ion-palette-dark),:host-context([data-theme=\"dark\"]){--auth-bg-start: #0f0f1a;--auth-bg-mid: #1a1a2e;--auth-bg-end: #16213e;--auth-glass-bg: rgba(0, 0, 0, .3);--auth-grain-opacity: .05;--auth-wave-color: var(--ion-color-primary, #818cf8)}.auth-background{position:relative;display:flex;align-items:center;padding:0;background:linear-gradient(135deg,var(--auth-bg-start) 0%,var(--auth-bg-mid) 50%,var(--auth-bg-end) 100%);overflow:hidden}.grain{position:absolute;inset:0;pointer-events:none;z-index:0;opacity:var(--auth-grain-opacity);background-image:url(\"data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.5' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E\")}.glass-layer{position:absolute;inset:0;pointer-events:none;z-index:1;background:var(--auth-glass-bg);backdrop-filter:blur(3px) saturate(120%);-webkit-backdrop-filter:blur(3px) saturate(120%)}.wave-bg{position:absolute;inset:0;pointer-events:none;z-index:0;transition:filter .3s ease}:host-context(body.dark) .wave-bg,:host-context(.dark) .wave-bg,:host-context(.ion-palette-dark) .wave-bg,:host-context(html.ion-palette-dark) .wave-bg,:host-context([data-theme=\"dark\"]) .wave-bg{filter:invert(1) opacity(.6)}.waves{width:100%;height:100%;overflow:visible}.waves path{fill:none;will-change:transform;animation:wave-flow-right var(--travel-duration, 18s) linear var(--travel-delay, 0s) infinite}.waves path.travel-left{animation:wave-flow-left var(--travel-duration, 18s) linear var(--travel-delay, 0s) infinite}@keyframes wave-flow-right{0%{transform:translate(0)}25%{transform:translate(-360px,calc(var(--bob, 0px) * -1))}50%{transform:translate(-720px)}75%{transform:translate(-1080px,var(--bob, 0px))}to{transform:translate(-1440px)}}@keyframes wave-flow-left{0%{transform:translate(0)}25%{transform:translate(360px,var(--bob, 0px))}50%{transform:translate(720px)}75%{transform:translate(1080px,calc(var(--bob, 0px) * -1))}to{transform:translate(1440px)}}@media (prefers-reduced-motion: reduce){.waves path{animation:none}}.content-layer{position:relative;z-index:2;width:100%;height:100%;display:flex;align-items:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] }); }
|
|
54891
54118
|
}
|
|
54892
54119
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AuthBackgroundComponent, decorators: [{
|
|
54893
54120
|
type: Component,
|
|
@@ -54909,8 +54136,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
54909
54136
|
[class.travel-left]="wave.travelDirection === 'left'"
|
|
54910
54137
|
[class.travel-right]="wave.travelDirection === 'right'"
|
|
54911
54138
|
[style.opacity]="wave.opacity"
|
|
54912
|
-
[style.--
|
|
54913
|
-
[style.--pulse-delay]="wave.pulseDelay + 's'"
|
|
54139
|
+
[style.--bob]="wave.bob + 'px'"
|
|
54914
54140
|
[style.--travel-duration]="wave.travelDuration + 's'"
|
|
54915
54141
|
[style.--travel-delay]="wave.travelDelay + 's'"
|
|
54916
54142
|
/>
|
|
@@ -54922,7 +54148,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
54922
54148
|
<ng-content></ng-content>
|
|
54923
54149
|
</div>
|
|
54924
54150
|
</section>
|
|
54925
|
-
`, styles: [":host{display:block;--auth-bg-start: #ffffff;--auth-bg-mid: #f8f9fa;--auth-bg-end: #f0f0f0;--auth-glass-bg: rgba(255, 255, 255, .3);--auth-grain-opacity: .035;--auth-wave-color: var(--ion-color-primary, #6366f1)}:host-context(body.dark),:host-context(.dark),:host-context(.ion-palette-dark),:host-context(html.ion-palette-dark),:host-context([data-theme=\"dark\"]){--auth-bg-start: #0f0f1a;--auth-bg-mid: #1a1a2e;--auth-bg-end: #16213e;--auth-glass-bg: rgba(0, 0, 0, .3);--auth-grain-opacity: .05;--auth-wave-color: var(--ion-color-primary, #818cf8)}.auth-background{position:relative;display:flex;align-items:center;padding:0;background:linear-gradient(135deg,var(--auth-bg-start) 0%,var(--auth-bg-mid) 50%,var(--auth-bg-end) 100%);overflow:hidden}.grain{position:absolute;inset:0;pointer-events:none;z-index:0;opacity:var(--auth-grain-opacity);background-image:url(\"data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.5' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E\")}.glass-layer{position:absolute;inset:0;pointer-events:none;z-index:1;background:var(--auth-glass-bg);backdrop-filter:blur(3px) saturate(120%);-webkit-backdrop-filter:blur(3px) saturate(120%)}.wave-bg{position:absolute;inset:0;pointer-events:none;z-index:0;transition:filter .3s ease}:host-context(body.dark) .wave-bg,:host-context(.dark) .wave-bg,:host-context(.ion-palette-dark) .wave-bg,:host-context(html.ion-palette-dark) .wave-bg,:host-context([data-theme=\"dark\"]) .wave-bg{filter:invert(1) opacity(.6)}.waves{width:100%;height:100%;overflow:visible}.waves path{fill:none;
|
|
54151
|
+
`, styles: [":host{display:block;--auth-bg-start: #ffffff;--auth-bg-mid: #f8f9fa;--auth-bg-end: #f0f0f0;--auth-glass-bg: rgba(255, 255, 255, .3);--auth-grain-opacity: .035;--auth-wave-color: var(--ion-color-primary, #6366f1)}:host-context(body.dark),:host-context(.dark),:host-context(.ion-palette-dark),:host-context(html.ion-palette-dark),:host-context([data-theme=\"dark\"]){--auth-bg-start: #0f0f1a;--auth-bg-mid: #1a1a2e;--auth-bg-end: #16213e;--auth-glass-bg: rgba(0, 0, 0, .3);--auth-grain-opacity: .05;--auth-wave-color: var(--ion-color-primary, #818cf8)}.auth-background{position:relative;display:flex;align-items:center;padding:0;background:linear-gradient(135deg,var(--auth-bg-start) 0%,var(--auth-bg-mid) 50%,var(--auth-bg-end) 100%);overflow:hidden}.grain{position:absolute;inset:0;pointer-events:none;z-index:0;opacity:var(--auth-grain-opacity);background-image:url(\"data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.5' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E\")}.glass-layer{position:absolute;inset:0;pointer-events:none;z-index:1;background:var(--auth-glass-bg);backdrop-filter:blur(3px) saturate(120%);-webkit-backdrop-filter:blur(3px) saturate(120%)}.wave-bg{position:absolute;inset:0;pointer-events:none;z-index:0;transition:filter .3s ease}:host-context(body.dark) .wave-bg,:host-context(.dark) .wave-bg,:host-context(.ion-palette-dark) .wave-bg,:host-context(html.ion-palette-dark) .wave-bg,:host-context([data-theme=\"dark\"]) .wave-bg{filter:invert(1) opacity(.6)}.waves{width:100%;height:100%;overflow:visible}.waves path{fill:none;will-change:transform;animation:wave-flow-right var(--travel-duration, 18s) linear var(--travel-delay, 0s) infinite}.waves path.travel-left{animation:wave-flow-left var(--travel-duration, 18s) linear var(--travel-delay, 0s) infinite}@keyframes wave-flow-right{0%{transform:translate(0)}25%{transform:translate(-360px,calc(var(--bob, 0px) * -1))}50%{transform:translate(-720px)}75%{transform:translate(-1080px,var(--bob, 0px))}to{transform:translate(-1440px)}}@keyframes wave-flow-left{0%{transform:translate(0)}25%{transform:translate(360px,var(--bob, 0px))}50%{transform:translate(720px)}75%{transform:translate(1080px,calc(var(--bob, 0px) * -1))}to{transform:translate(1440px)}}@media (prefers-reduced-motion: reduce){.waves path{animation:none}}.content-layer{position:relative;z-index:2;width:100%;height:100%;display:flex;align-items:center}\n"] }]
|
|
54926
54152
|
}], ctorParameters: () => [], propDecorators: { props: [{
|
|
54927
54153
|
type: Input
|
|
54928
54154
|
}] } });
|
|
@@ -59370,6 +58596,263 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
59370
58596
|
type: Output
|
|
59371
58597
|
}] } });
|
|
59372
58598
|
|
|
58599
|
+
/**
|
|
58600
|
+
* Defaults i18n del componente (es/en). El componente los auto-registra en su
|
|
58601
|
+
* constructor si el consumer no proveyó el namespace `ContentReaction`. Esto
|
|
58602
|
+
* garantiza que NUNCA haya una key faltante: una key faltante se evalúa en el
|
|
58603
|
+
* template por cada change-detection → `console.warn` por CD → con el
|
|
58604
|
+
* `val-debug-console` activo (espeja console.* a un signal) se dispara un loop
|
|
58605
|
+
* infinito que congela el navegador en dev. Auto-registrar lo elimina de raíz.
|
|
58606
|
+
*/
|
|
58607
|
+
const CONTENT_REACTION_I18N = {
|
|
58608
|
+
es: {
|
|
58609
|
+
question: '¿Te resultó útil este contenido?',
|
|
58610
|
+
commentPlaceholder: 'Cuéntanos más (opcional)...',
|
|
58611
|
+
submit: 'Enviar opinión',
|
|
58612
|
+
update: 'Actualizar opinión',
|
|
58613
|
+
thankYou: '¡Gracias por tu opinión!',
|
|
58614
|
+
submitted: 'Tu opinión ha sido registrada',
|
|
58615
|
+
errorSubmitting: 'Error al enviar. Intenta de nuevo.',
|
|
58616
|
+
positiveLabel: 'Sí, mucho',
|
|
58617
|
+
negativeLabel: 'No tanto',
|
|
58618
|
+
negativeFeedbackTitle: '¿Cuéntanos qué no te gustó?',
|
|
58619
|
+
},
|
|
58620
|
+
en: {
|
|
58621
|
+
question: 'Was this content helpful?',
|
|
58622
|
+
commentPlaceholder: 'Tell us more (optional)...',
|
|
58623
|
+
submit: 'Send feedback',
|
|
58624
|
+
update: 'Update feedback',
|
|
58625
|
+
thankYou: 'Thanks for your feedback!',
|
|
58626
|
+
submitted: 'Your feedback has been recorded',
|
|
58627
|
+
errorSubmitting: 'Failed to send. Please try again.',
|
|
58628
|
+
positiveLabel: 'Yes, a lot',
|
|
58629
|
+
negativeLabel: 'Not really',
|
|
58630
|
+
negativeFeedbackTitle: "Tell us what you didn't like?",
|
|
58631
|
+
},
|
|
58632
|
+
};
|
|
58633
|
+
/**
|
|
58634
|
+
* Componente para reacciones de contenido con emojis.
|
|
58635
|
+
*
|
|
58636
|
+
* @example
|
|
58637
|
+
* ```html
|
|
58638
|
+
* <val-content-reaction
|
|
58639
|
+
* [props]="{
|
|
58640
|
+
* entityRef: { entityType: 'article', entityId: 'art-123' },
|
|
58641
|
+
* question: '¿Te fue útil este artículo?'
|
|
58642
|
+
* }"
|
|
58643
|
+
* (reactionSubmit)="onReactionSubmit($event)"
|
|
58644
|
+
* />
|
|
58645
|
+
* ```
|
|
58646
|
+
*/
|
|
58647
|
+
class ContentReactionComponent {
|
|
58648
|
+
constructor() {
|
|
58649
|
+
this.feedbackService = inject(FeedbackService);
|
|
58650
|
+
this.toast = inject(ToastService);
|
|
58651
|
+
this.i18n = inject(I18nService);
|
|
58652
|
+
this.auth = inject(AuthService, { optional: true });
|
|
58653
|
+
this.isConfigured = computed(() => this.feedbackService.isConfigured());
|
|
58654
|
+
this.props = {};
|
|
58655
|
+
this.reactionSubmit = new EventEmitter();
|
|
58656
|
+
this.reactionChange = new EventEmitter();
|
|
58657
|
+
// Estado reactivo
|
|
58658
|
+
this.state = signal({
|
|
58659
|
+
selectedValue: null,
|
|
58660
|
+
comment: '',
|
|
58661
|
+
isLoading: false,
|
|
58662
|
+
isSubmitted: false,
|
|
58663
|
+
hadPreviousReaction: false,
|
|
58664
|
+
error: null,
|
|
58665
|
+
});
|
|
58666
|
+
// Valores por defecto
|
|
58667
|
+
this.defaultEmojis = ['😞', '😐', '😊'];
|
|
58668
|
+
this.defaultLabels = ['No me ayudó', 'Regular', 'Muy útil'];
|
|
58669
|
+
// Computed properties
|
|
58670
|
+
this.resolvedProps = computed(() => ({
|
|
58671
|
+
entityRef: this.props.entityRef,
|
|
58672
|
+
question: this.props.question || this.t('question'),
|
|
58673
|
+
showComment: this.props.showComment ?? true,
|
|
58674
|
+
commentOnValues: this.props.commentOnValues,
|
|
58675
|
+
commentPlaceholder: this.props.commentPlaceholder || this.t('commentPlaceholder'),
|
|
58676
|
+
maxCommentLength: this.props.maxCommentLength ?? 500,
|
|
58677
|
+
emojis: this.props.emojis || this.defaultEmojis,
|
|
58678
|
+
emojiLabels: this.props.emojiLabels || this.defaultLabels,
|
|
58679
|
+
showThankYou: this.props.showThankYou ?? true,
|
|
58680
|
+
thankYouMessage: this.props.thankYouMessage || this.t('thankYou'),
|
|
58681
|
+
disabled: this.props.disabled ?? false,
|
|
58682
|
+
readonly: this.props.readonly ?? false,
|
|
58683
|
+
// Variante: 'emoji' cuando se declara explícitamente o cuando se pasan emojis custom.
|
|
58684
|
+
variant: this.props.variant ?? (this.props.emojis ? 'emoji' : 'buttons'),
|
|
58685
|
+
}));
|
|
58686
|
+
this.activeReactionValues = computed(() => this.resolvedProps().emojis.length === 2 ? ['negative', 'positive'] : ['negative', 'neutral', 'positive']);
|
|
58687
|
+
this.showCommentField = computed(() => {
|
|
58688
|
+
const sel = this.state().selectedValue;
|
|
58689
|
+
if (!sel)
|
|
58690
|
+
return false;
|
|
58691
|
+
const commentOn = this.resolvedProps().commentOnValues;
|
|
58692
|
+
if (commentOn !== undefined)
|
|
58693
|
+
return commentOn.includes(sel);
|
|
58694
|
+
return this.resolvedProps().showComment;
|
|
58695
|
+
});
|
|
58696
|
+
this.canSubmit = computed(() => this.state().selectedValue !== null && !this.state().isLoading);
|
|
58697
|
+
// Auto-registro de defaults i18n (es/en) si el consumer no proveyó el
|
|
58698
|
+
// namespace. Garantiza que `t()` nunca caiga en key faltante. Ver
|
|
58699
|
+
// CONTENT_REACTION_I18N. Idempotente: solo la 1ª instancia registra.
|
|
58700
|
+
if (!this.i18n.hasNamespace('ContentReaction')) {
|
|
58701
|
+
this.i18n.registerContent('ContentReaction', CONTENT_REACTION_I18N);
|
|
58702
|
+
}
|
|
58703
|
+
}
|
|
58704
|
+
ngOnInit() {
|
|
58705
|
+
this.loadPreviousReaction();
|
|
58706
|
+
}
|
|
58707
|
+
ngOnChanges(changes) {
|
|
58708
|
+
if (changes['props'] && !changes['props'].firstChange) {
|
|
58709
|
+
this.loadPreviousReaction();
|
|
58710
|
+
}
|
|
58711
|
+
}
|
|
58712
|
+
async loadPreviousReaction() {
|
|
58713
|
+
if (!this.props.entityRef)
|
|
58714
|
+
return;
|
|
58715
|
+
// Si hay initialValue, usarlo directamente sin consultar
|
|
58716
|
+
if (this.props.initialValue) {
|
|
58717
|
+
this.state.update(s => ({
|
|
58718
|
+
...s,
|
|
58719
|
+
selectedValue: this.props.initialValue,
|
|
58720
|
+
hadPreviousReaction: true,
|
|
58721
|
+
isLoading: false,
|
|
58722
|
+
isSubmitted: true,
|
|
58723
|
+
}));
|
|
58724
|
+
return;
|
|
58725
|
+
}
|
|
58726
|
+
// Si skipInitialCheck está activo, no consultar
|
|
58727
|
+
if (this.props.skipInitialCheck) {
|
|
58728
|
+
return;
|
|
58729
|
+
}
|
|
58730
|
+
this.state.update(s => ({ ...s, isLoading: true, error: null }));
|
|
58731
|
+
try {
|
|
58732
|
+
const check = await this.feedbackService.checkFeedback(this.props.entityRef.entityType, this.props.entityRef.entityId);
|
|
58733
|
+
if (check.hasFeedback && check.reactionValue) {
|
|
58734
|
+
this.state.update(s => ({
|
|
58735
|
+
...s,
|
|
58736
|
+
selectedValue: check.reactionValue,
|
|
58737
|
+
hadPreviousReaction: true,
|
|
58738
|
+
isLoading: false,
|
|
58739
|
+
isSubmitted: true,
|
|
58740
|
+
}));
|
|
58741
|
+
}
|
|
58742
|
+
else {
|
|
58743
|
+
this.state.update(s => ({ ...s, isLoading: false }));
|
|
58744
|
+
}
|
|
58745
|
+
}
|
|
58746
|
+
catch (error) {
|
|
58747
|
+
console.error('Error loading previous reaction:', error);
|
|
58748
|
+
this.state.update(s => ({ ...s, isLoading: false }));
|
|
58749
|
+
}
|
|
58750
|
+
}
|
|
58751
|
+
selectReaction(value) {
|
|
58752
|
+
if (this.resolvedProps().disabled || this.resolvedProps().readonly)
|
|
58753
|
+
return;
|
|
58754
|
+
const previousValue = this.state().selectedValue;
|
|
58755
|
+
this.state.update(s => ({
|
|
58756
|
+
...s,
|
|
58757
|
+
selectedValue: value,
|
|
58758
|
+
isSubmitted: false,
|
|
58759
|
+
error: null,
|
|
58760
|
+
}));
|
|
58761
|
+
this.reactionChange.emit({ value, previousValue });
|
|
58762
|
+
}
|
|
58763
|
+
async submitReaction() {
|
|
58764
|
+
const currentState = this.state();
|
|
58765
|
+
const props = this.resolvedProps();
|
|
58766
|
+
if (!currentState.selectedValue || props.disabled)
|
|
58767
|
+
return;
|
|
58768
|
+
this.state.update(s => ({ ...s, isLoading: true, error: null }));
|
|
58769
|
+
try {
|
|
58770
|
+
// Determinar si usar endpoint anónimo o autenticado
|
|
58771
|
+
const isAuthenticated = this.auth?.isAuthenticated() ?? false;
|
|
58772
|
+
const useAnonymous = this.props.allowAnonymous && !isAuthenticated;
|
|
58773
|
+
if (useAnonymous) {
|
|
58774
|
+
// Usar endpoint anónimo (público)
|
|
58775
|
+
await this.feedbackService.createAnonymousReaction(props.entityRef, currentState.selectedValue, currentState.comment || undefined);
|
|
58776
|
+
}
|
|
58777
|
+
else {
|
|
58778
|
+
// Usar endpoint autenticado
|
|
58779
|
+
await this.feedbackService.createReaction(props.entityRef, currentState.selectedValue, currentState.comment || undefined);
|
|
58780
|
+
}
|
|
58781
|
+
this.state.update(s => ({
|
|
58782
|
+
...s,
|
|
58783
|
+
isLoading: false,
|
|
58784
|
+
isSubmitted: true,
|
|
58785
|
+
comment: '',
|
|
58786
|
+
hadPreviousReaction: !useAnonymous, // Solo para autenticados
|
|
58787
|
+
}));
|
|
58788
|
+
this.reactionSubmit.emit({
|
|
58789
|
+
value: currentState.selectedValue,
|
|
58790
|
+
comment: currentState.comment || undefined,
|
|
58791
|
+
entityRef: props.entityRef,
|
|
58792
|
+
isUpdate: currentState.hadPreviousReaction,
|
|
58793
|
+
});
|
|
58794
|
+
if (props.showThankYou) {
|
|
58795
|
+
this.toast.show({
|
|
58796
|
+
message: props.thankYouMessage,
|
|
58797
|
+
duration: 2000,
|
|
58798
|
+
});
|
|
58799
|
+
}
|
|
58800
|
+
}
|
|
58801
|
+
catch (error) {
|
|
58802
|
+
console.error('Error submitting reaction:', error);
|
|
58803
|
+
this.state.update(s => ({
|
|
58804
|
+
...s,
|
|
58805
|
+
isLoading: false,
|
|
58806
|
+
error: this.t('errorSubmitting'),
|
|
58807
|
+
}));
|
|
58808
|
+
this.toast.show({
|
|
58809
|
+
message: this.t('errorSubmitting'),
|
|
58810
|
+
duration: 3000,
|
|
58811
|
+
});
|
|
58812
|
+
}
|
|
58813
|
+
}
|
|
58814
|
+
updateComment(event) {
|
|
58815
|
+
const value = event.detail.value || '';
|
|
58816
|
+
this.state.update(s => ({ ...s, comment: value }));
|
|
58817
|
+
}
|
|
58818
|
+
getEmoji(index) {
|
|
58819
|
+
return this.resolvedProps().emojis[index];
|
|
58820
|
+
}
|
|
58821
|
+
getEmojiLabel(index) {
|
|
58822
|
+
return this.resolvedProps().emojiLabels[index];
|
|
58823
|
+
}
|
|
58824
|
+
isSelected(value) {
|
|
58825
|
+
return this.state().selectedValue === value;
|
|
58826
|
+
}
|
|
58827
|
+
t(key) {
|
|
58828
|
+
const translations = {
|
|
58829
|
+
question: '¿Te resultó útil este contenido?',
|
|
58830
|
+
commentPlaceholder: 'Cuéntanos más (opcional)...',
|
|
58831
|
+
submit: 'Enviar opinión',
|
|
58832
|
+
update: 'Actualizar opinión',
|
|
58833
|
+
thankYou: '¡Gracias por tu opinión!',
|
|
58834
|
+
submitted: 'Tu opinión ha sido registrada',
|
|
58835
|
+
errorSubmitting: 'Error al enviar. Intenta de nuevo.',
|
|
58836
|
+
positiveLabel: 'Sí, mucho',
|
|
58837
|
+
negativeLabel: 'No tanto',
|
|
58838
|
+
negativeFeedbackTitle: '¿Cuéntanos qué no te gustó?',
|
|
58839
|
+
};
|
|
58840
|
+
return this.i18n.t(key, 'ContentReaction') || translations[key] || key;
|
|
58841
|
+
}
|
|
58842
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ContentReactionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
58843
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ContentReactionComponent, isStandalone: true, selector: "val-content-reaction", inputs: { props: "props" }, outputs: { reactionSubmit: "reactionSubmit", reactionChange: "reactionChange" }, usesOnChanges: true, ngImport: i0, template: "@if (isConfigured()) {\n<div class=\"content-reaction\" [class.disabled]=\"resolvedProps().disabled\" [class.readonly]=\"resolvedProps().readonly\">\n <!-- Loading inicial -->\n @if (state().isLoading && !state().selectedValue) {\n <div class=\"loading-container\">\n <ion-spinner name=\"crescent\"></ion-spinner>\n </div>\n } @else {\n <!-- Pregunta -->\n <p class=\"question\">\n {{ state().selectedValue === 'negative' ? t('negativeFeedbackTitle') : resolvedProps().question }}\n </p>\n\n <!-- Botones de reacci\u00F3n \u2014 variante emoji (caras, estrellas, thumbs, \u2026) -->\n @if (resolvedProps().variant === 'emoji') {\n <div class=\"reaction-buttons reaction-buttons--emoji\">\n @for (value of activeReactionValues(); track value; let i = $index) {\n <ion-button\n fill=\"clear\"\n shape=\"round\"\n [class.selected]=\"isSelected(value)\"\n [attr.aria-label]=\"resolvedProps().emojiLabels[i]\"\n [attr.aria-pressed]=\"isSelected(value)\"\n [disabled]=\"resolvedProps().disabled || resolvedProps().readonly\"\n (click)=\"selectReaction(value)\"\n >\n <span class=\"emoji-btn\">{{ resolvedProps().emojis[i] }}</span>\n </ion-button>\n }\n </div>\n } @else {\n <!-- Botones de reacci\u00F3n \u2014 variante texto (default) -->\n <div class=\"reaction-buttons\">\n <ion-button\n [fill]=\"isSelected('positive') ? 'solid' : 'outline'\"\n shape=\"round\"\n color=\"dark\"\n [attr.aria-pressed]=\"isSelected('positive')\"\n [disabled]=\"resolvedProps().disabled || resolvedProps().readonly\"\n (click)=\"selectReaction('positive')\"\n >\n {{ t('positiveLabel') }}\n </ion-button>\n <ion-button\n [fill]=\"isSelected('negative') ? 'solid' : 'outline'\"\n shape=\"round\"\n color=\"dark\"\n [attr.aria-pressed]=\"isSelected('negative')\"\n [disabled]=\"resolvedProps().disabled || resolvedProps().readonly\"\n (click)=\"selectReaction('negative')\"\n >\n {{ t('negativeLabel') }}\n </ion-button>\n </div>\n }\n\n <!-- Campo de comentario (solo si hay selecci\u00F3n) -->\n @if (showCommentField()) {\n <div class=\"comment-section\">\n <ion-textarea\n [value]=\"state().comment\"\n [placeholder]=\"resolvedProps().commentPlaceholder\"\n [maxlength]=\"resolvedProps().maxCommentLength\"\n [disabled]=\"resolvedProps().disabled\"\n [rows]=\"3\"\n class=\"comment-textarea\"\n (ionInput)=\"updateComment($event)\"\n ></ion-textarea>\n <span class=\"char-count\"> {{ state().comment.length }}/{{ resolvedProps().maxCommentLength }} </span>\n </div>\n }\n\n <!-- Bot\u00F3n de env\u00EDo -->\n @if (state().selectedValue && !state().isSubmitted) {\n <ion-button expand=\"block\" shape=\"round\" [disabled]=\"!canSubmit()\" (click)=\"submitReaction()\" class=\"submit-button\">\n @if (state().isLoading) {\n <ion-spinner name=\"crescent\"></ion-spinner>\n } @else { {{ state().hadPreviousReaction ? t('update') : t('submit') }} }\n </ion-button>\n }\n\n <!-- Mensaje de confirmaci\u00F3n -->\n @if (state().isSubmitted) {\n <p class=\"submitted-message\">{{ t('thankYou') }}</p>\n }\n\n <!-- Error -->\n @if (state().error) {\n <p class=\"error-message\">{{ state().error }}</p>\n } }\n</div>\n}\n", styles: [":host{display:block}.content-reaction{padding:16px;text-align:center}.content-reaction.disabled{opacity:.6;pointer-events:none}.content-reaction.readonly{pointer-events:none}.question{font-size:1.0625rem;font-weight:700;color:var(--ion-color-dark);margin:0 0 16px}.reaction-buttons{display:flex;justify-content:center;gap:12px;margin-bottom:20px}.reaction-buttons--emoji{gap:8px}.reaction-buttons--emoji ion-button{--padding-start: 4px;--padding-end: 4px;transition:transform .15s ease}.reaction-buttons--emoji ion-button.selected{transform:scale(1.25)}.reaction-buttons--emoji ion-button:not(.selected):not([disabled]){opacity:.55}.reaction-buttons--emoji ion-button:not(.selected):not([disabled]):hover{opacity:1}.emoji-btn{font-size:2rem;line-height:1;display:block}.comment-section{margin-top:16px;animation:slideIn .3s ease-out}.comment-section .comment-textarea{--background: transparent;--border-radius: 8px;--padding-start: 12px;--padding-end: 12px;width:100%}.comment-section .char-count{display:block;text-align:right;font-size:.75rem;color:var(--ion-color-medium);margin-top:4px}.submit-button{margin-top:16px}.submitted-message{margin-top:16px;color:var(--ion-color-success);font-weight:500;animation:fadeIn .3s ease-out}.error-message{margin-top:8px;color:var(--ion-color-danger);font-size:.875rem}.loading-container{display:flex;justify-content:center;padding:20px}@keyframes slideIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: IonTextarea, selector: "ion-textarea", inputs: ["autoGrow", "autocapitalize", "autofocus", "clearOnEdit", "color", "cols", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "maxlength", "minlength", "mode", "name", "placeholder", "readonly", "required", "rows", "shape", "spellcheck", "value", "wrap"] }] }); }
|
|
58844
|
+
}
|
|
58845
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ContentReactionComponent, decorators: [{
|
|
58846
|
+
type: Component,
|
|
58847
|
+
args: [{ selector: 'val-content-reaction', standalone: true, imports: [CommonModule, FormsModule, IonButton, IonSpinner, IonTextarea], template: "@if (isConfigured()) {\n<div class=\"content-reaction\" [class.disabled]=\"resolvedProps().disabled\" [class.readonly]=\"resolvedProps().readonly\">\n <!-- Loading inicial -->\n @if (state().isLoading && !state().selectedValue) {\n <div class=\"loading-container\">\n <ion-spinner name=\"crescent\"></ion-spinner>\n </div>\n } @else {\n <!-- Pregunta -->\n <p class=\"question\">\n {{ state().selectedValue === 'negative' ? t('negativeFeedbackTitle') : resolvedProps().question }}\n </p>\n\n <!-- Botones de reacci\u00F3n \u2014 variante emoji (caras, estrellas, thumbs, \u2026) -->\n @if (resolvedProps().variant === 'emoji') {\n <div class=\"reaction-buttons reaction-buttons--emoji\">\n @for (value of activeReactionValues(); track value; let i = $index) {\n <ion-button\n fill=\"clear\"\n shape=\"round\"\n [class.selected]=\"isSelected(value)\"\n [attr.aria-label]=\"resolvedProps().emojiLabels[i]\"\n [attr.aria-pressed]=\"isSelected(value)\"\n [disabled]=\"resolvedProps().disabled || resolvedProps().readonly\"\n (click)=\"selectReaction(value)\"\n >\n <span class=\"emoji-btn\">{{ resolvedProps().emojis[i] }}</span>\n </ion-button>\n }\n </div>\n } @else {\n <!-- Botones de reacci\u00F3n \u2014 variante texto (default) -->\n <div class=\"reaction-buttons\">\n <ion-button\n [fill]=\"isSelected('positive') ? 'solid' : 'outline'\"\n shape=\"round\"\n color=\"dark\"\n [attr.aria-pressed]=\"isSelected('positive')\"\n [disabled]=\"resolvedProps().disabled || resolvedProps().readonly\"\n (click)=\"selectReaction('positive')\"\n >\n {{ t('positiveLabel') }}\n </ion-button>\n <ion-button\n [fill]=\"isSelected('negative') ? 'solid' : 'outline'\"\n shape=\"round\"\n color=\"dark\"\n [attr.aria-pressed]=\"isSelected('negative')\"\n [disabled]=\"resolvedProps().disabled || resolvedProps().readonly\"\n (click)=\"selectReaction('negative')\"\n >\n {{ t('negativeLabel') }}\n </ion-button>\n </div>\n }\n\n <!-- Campo de comentario (solo si hay selecci\u00F3n) -->\n @if (showCommentField()) {\n <div class=\"comment-section\">\n <ion-textarea\n [value]=\"state().comment\"\n [placeholder]=\"resolvedProps().commentPlaceholder\"\n [maxlength]=\"resolvedProps().maxCommentLength\"\n [disabled]=\"resolvedProps().disabled\"\n [rows]=\"3\"\n class=\"comment-textarea\"\n (ionInput)=\"updateComment($event)\"\n ></ion-textarea>\n <span class=\"char-count\"> {{ state().comment.length }}/{{ resolvedProps().maxCommentLength }} </span>\n </div>\n }\n\n <!-- Bot\u00F3n de env\u00EDo -->\n @if (state().selectedValue && !state().isSubmitted) {\n <ion-button expand=\"block\" shape=\"round\" [disabled]=\"!canSubmit()\" (click)=\"submitReaction()\" class=\"submit-button\">\n @if (state().isLoading) {\n <ion-spinner name=\"crescent\"></ion-spinner>\n } @else { {{ state().hadPreviousReaction ? t('update') : t('submit') }} }\n </ion-button>\n }\n\n <!-- Mensaje de confirmaci\u00F3n -->\n @if (state().isSubmitted) {\n <p class=\"submitted-message\">{{ t('thankYou') }}</p>\n }\n\n <!-- Error -->\n @if (state().error) {\n <p class=\"error-message\">{{ state().error }}</p>\n } }\n</div>\n}\n", styles: [":host{display:block}.content-reaction{padding:16px;text-align:center}.content-reaction.disabled{opacity:.6;pointer-events:none}.content-reaction.readonly{pointer-events:none}.question{font-size:1.0625rem;font-weight:700;color:var(--ion-color-dark);margin:0 0 16px}.reaction-buttons{display:flex;justify-content:center;gap:12px;margin-bottom:20px}.reaction-buttons--emoji{gap:8px}.reaction-buttons--emoji ion-button{--padding-start: 4px;--padding-end: 4px;transition:transform .15s ease}.reaction-buttons--emoji ion-button.selected{transform:scale(1.25)}.reaction-buttons--emoji ion-button:not(.selected):not([disabled]){opacity:.55}.reaction-buttons--emoji ion-button:not(.selected):not([disabled]):hover{opacity:1}.emoji-btn{font-size:2rem;line-height:1;display:block}.comment-section{margin-top:16px;animation:slideIn .3s ease-out}.comment-section .comment-textarea{--background: transparent;--border-radius: 8px;--padding-start: 12px;--padding-end: 12px;width:100%}.comment-section .char-count{display:block;text-align:right;font-size:.75rem;color:var(--ion-color-medium);margin-top:4px}.submit-button{margin-top:16px}.submitted-message{margin-top:16px;color:var(--ion-color-success);font-weight:500;animation:fadeIn .3s ease-out}.error-message{margin-top:8px;color:var(--ion-color-danger);font-size:.875rem}.loading-container{display:flex;justify-content:center;padding:20px}@keyframes slideIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}\n"] }]
|
|
58848
|
+
}], ctorParameters: () => [], propDecorators: { props: [{
|
|
58849
|
+
type: Input
|
|
58850
|
+
}], reactionSubmit: [{
|
|
58851
|
+
type: Output
|
|
58852
|
+
}], reactionChange: [{
|
|
58853
|
+
type: Output
|
|
58854
|
+
}] } });
|
|
58855
|
+
|
|
59373
58856
|
const DEFAULT_SPLASH_SCREEN_CONFIG = {
|
|
59374
58857
|
fadeOutDuration: 300,
|
|
59375
58858
|
};
|
|
@@ -63222,5 +62705,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
63222
62705
|
* Generated bundle index. Do not edit.
|
|
63223
62706
|
*/
|
|
63224
62707
|
|
|
63225
|
-
export { ACTION_CARD_DEFAULTS, AD_SIZE_MAP, API_TABLE_COLUMN_LABELS, ARTICLE_CARD_DEFAULTS, ARTICLE_SPACING, ARTICLE_STRIP_DEFAULTS, AUTH_CTA_DEFAULTS, AVATAR_UPLOAD_DEFAULTS, AboutViewComponent, AccordionComponent, AccountViewComponent, ActionCardComponent, ActionHeaderComponent, ActionType, AdSlotComponent, AdsLoaderService, AdsService, AlertBoxComponent, AnalyticsErrorHandler, AnalyticsRouterTracker, AnalyticsService, AnimatedTerminalComponent, AppConfigService, AppVersionService, ArticleBuilder, ArticleCardComponent, ArticleComponent, ArticleStripComponent, AttachmentUploaderComponent, AuthBackgroundComponent, AuthCtaComponent, AuthService, AuthStateService, AuthStorageService, AuthSyncService, AvatarComponent, AvatarUploadComponent, BOTTOM_NAV_DEFAULTS, BannerComponent, BaseDefault, BlogPostBuilder, BottomNavComponent, BoxComponent, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, CALLOUT_LABELS, CHEV_KEYS, CIRCLE_KEYS, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CONTENT_CARD_DEFAULTS, CORNER_KEYS, CTA_CARD_DEFAULTS, CURRENCY_INFO, CardComponent, CardSection, CardType, CardsCarouselComponent, ChangeEmailModalComponent, ChangePasswordModalComponent, CheckInputComponent, CheckboxRadioInputComponent, ChipGroupComponent, ClearDefault, ClearDefaultBlock, ClearDefaultFull, ClearDefaultRound, ClearDefaultRoundBlock, ClearDefaultRoundFull, CodeDisplayComponent, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ContainerComponent, ContentCardComponent, ContentLoaderComponent, ContentReactionComponent, ContentService, ContentTransformer, CookieBannerComponent, CountdownComponent, CreateOrgModalComponent, CtaCardComponent, CurrencyInputComponent, DEFAULT_ADS_CONFIG, DEFAULT_APP_CONFIG_SERVICE_CONFIG, DEFAULT_APP_VERSION_SERVICE_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_BACK_HEADER, DEFAULT_CANCEL_BUTTON, DEFAULT_CHECK_INTERVAL_MS, DEFAULT_CONFIRM_BUTTON, DEFAULT_COUNTDOWN_LABELS, DEFAULT_COUNTDOWN_LABELS_EN, DEFAULT_DEBUG_CONSOLE_CONFIG, DEFAULT_DONATION_CONFIG, DEFAULT_EMPTY_STATE, DEFAULT_EMULATOR_CONFIG, DEFAULT_FEEDBACK_CONFIG, DEFAULT_FEEDBACK_TYPE_OPTIONS, DEFAULT_HOME_HEADER, DEFAULT_INFINITE_LIST_METADATA, DEFAULT_MODAL_CANCEL_BUTTON, DEFAULT_MODAL_CONFIRM_BUTTON, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLATFORMS, DEFAULT_REFRESHER_METADATA, DEFAULT_SKELETON_CONFIG, DEFAULT_SPLASH_SCREEN_CONFIG, DataTableComponent, DateInputComponent, DateRangeInputComponent, DebugConsoleComponent, DeleteAccountModalComponent, DetailSkeletonComponent, DeviceService, DisplayComponent, DividerComponent, DocsApiTableComponent, DocsBreadcrumbComponent, DocsBuilder, DocsCalloutComponent, DocsCodeExampleComponent, DocsLayoutComponent, DocsNavLinksComponent, DocsNavigationService, DocsPageComponent, DocsSearchComponent, DocsSectionComponent, DocsShellComponent, DocsSidebarComponent, DocsTocComponent, DonationService, DownloadService, EditOrgModalComponent, EmailInputComponent, EmptyStateComponent, ExpandableTextComponent, FEATURES_LIST_DEFAULTS, FUN_MODAL_DEFAULTS, FabComponent, FaqComponent, FeaturesListComponent, FeedbackFormComponent, FeedbackService, FileInputComponent, FirebaseService, FirestoreCollectionFactory, FirestoreService, FontSizeOption, FontSizeService, FooterComponent, FooterLinksComponent, FormComponent, FormSkeletonComponent, FunHeaderComponent, FunModalComponent, GlassComponent, GlowCardComponent, GlowComponent, GridSkeletonComponent, HANDOFF_ROUTE_PARAM, HANDOFF_TOKEN_PARAM, HandoffService, HasPermissionDirective, HeaderComponent, HintComponent, HorizontalScrollComponent, HourInputComponent, HrefComponent, I18nService, IMAGE_DEFAULTS, INFO_CARD_DEFAULTS, INITIAL_AUTH_STATE, INITIAL_MFA_STATE, INVITATION_CARD_DEFAULTS, Icon, IconComponent, IconService, ImageComponent, ImageCropComponent, ImageService, InAppBrowserService, InfiniteListComponent, InfoCardComponent, InfoComponent, InputI18nHelper, InputType, InvitationCardComponent, InviteMemberModalComponent, ItemListComponent, LANG_STORAGE_KEY$1 as LANG_STORAGE_KEY, LEGAL_CONTENT_CONFIG, LOGIN_DEFAULTS, LandingSplitComponent, LandingStepsComponent, LanguageSelectorComponent, LayeredCardComponent, LegalContentService, LegalLinkService, LinkComponent, LinkProcessorService, LinkedProvidersComponent, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LoadingDirective, LocalStorageService, LocaleService, LoginAttemptModalComponent, LoginComponent, MEDIA_OBJECT_DEFAULTS, MEMBER_CARD_DEFAULTS, METRIC_CARD_DEFAULTS, MODAL_SIZES, MOTIF_KEYS, MOTION, MaintenancePageComponent, MarkdownArticleParserService, MediaObjectComponent, MemberCardComponent, MemberDetailModalComponent, MenuComponent, MessagingService, MetaService, MetricCardComponent, MfaModalComponent, ModalService, ModalShellComponent, MultiSelectSearchComponent, NUM_KEYS, NavigationService, NetworkBannerComponent, NetworkStatusService, NewsBuilder, NoContentComponent, NotesBoxComponent, NotificationActionService, NotificationPreferencesViewComponent, NotificationsService, NotificationsViewComponent, NumberFromToComponent, NumberInputComponent, NumberStepperComponent, OAUTH_PROVIDERS_INFO, OAuthCallbackComponent, OAuthService, OrgInfoSheetComponent, OrgService, OrgSwitchService, OrganizationViewComponent, OutlineDefault, OutlineDefaultBlock, OutlineDefaultFull, OutlineDefaultRound, OutlineDefaultRoundBlock, OutlineDefaultRoundFull, PATTERN_MOTIFS, PATTERN_PALETTES, PATTERN_STYLE_CONFIGS, PLATFORM_CONFIGS, PageContentComponent, PageLinksComponent, PageRefreshService, PageTemplateComponent, PageWavesComponent, PageWrapperComponent, PaginationComponent, PaginationService, PasswordInputComponent, PatternComponent, PermissionCatalogService, PermissionsViewComponent, PhoneInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PreferencesService, PreferencesViewComponent, PresetService, PriceTagComponent, PrimarySolidBlockButton, PrimarySolidBlockHrefButton, PrimarySolidBlockIconButton, PrimarySolidBlockIconHrefButton, PrimarySolidDefaultRoundButton, PrimarySolidDefaultRoundHrefButton, PrimarySolidDefaultRoundIconButton, PrimarySolidDefaultRoundIconHrefButton, PrimarySolidFullButton, PrimarySolidFullHrefButton, PrimarySolidFullIconButton, PrimarySolidFullIconHrefButton, PrimarySolidLargeRoundButton, PrimarySolidLargeRoundHrefButton, PrimarySolidLargeRoundIconButton, PrimarySolidLargeRoundIconHrefButton, PrimarySolidSmallRoundButton, PrimarySolidSmallRoundHrefButton, PrimarySolidSmallRoundIconButton, PrimarySolidSmallRoundIconHrefButton, ProcessLinksPipe, ProfileSkeletonComponent, ProfileViewComponent, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrCodeComponent, QrGeneratorService, QueryBuilder, QuoteBoxComponent, REQUEST_STATUSES, RadioInputComponent, RangeInputComponent, RatingComponent, RefresherComponent, RequestFirestoreService, RequestFormBuilderService, RequestService, RightsFooterComponent, RotatingTextComponent, SEARCH_HEADER_DEFAULTS, SETTINGS_SECTIONS_CATALOG, SHAPE_KEYS, SHARE_PROFILE_MODAL_DEFAULTS, SKELETON_LAYOUT_DEFAULT_ROWS, SKELETON_PRESETS, SOLID_KEYS, STATS_BAR_DEFAULTS, STROKE_KEYS, SearchHeaderComponent, SearchSelectorComponent, SearchbarComponent, SecondarySolidBlockButton, SecondarySolidBlockHrefButton, SecondarySolidBlockIconButton, SecondarySolidBlockIconHrefButton, SecondarySolidDefaultRoundButton, SecondarySolidDefaultRoundHrefButton, SecondarySolidDefaultRoundIconButton, SecondarySolidDefaultRoundIconHrefButton, SecondarySolidFullButton, SecondarySolidFullHrefButton, SecondarySolidFullIconButton, SecondarySolidFullIconHrefButton, SecondarySolidLargeRoundButton, SecondarySolidLargeRoundHrefButton, SecondarySolidLargeRoundIconButton, SecondarySolidLargeRoundIconHrefButton, SecondarySolidSmallRoundButton, SecondarySolidSmallRoundHrefButton, SecondarySolidSmallRoundIconButton, SecondarySolidSmallRoundIconHrefButton, SecurityViewComponent, SegmentControlComponent, SelectSearchComponent, SessionListModalComponent, SessionService, SettingsHubComponent, ShareButtonsComponent, ShareProfileModalComponent, SimpleComponent, SkeletonComponent, SkeletonLayoutComponent, SkeletonService, SolidBlockButton, SolidDefault, SolidDefaultBlock, SolidDefaultButton, SolidDefaultFull, SolidDefaultRound, SolidDefaultRoundBlock, SolidDefaultRoundButton, SolidDefaultRoundFull, SolidFullButton, SolidLargeButton, SolidLargeRoundButton, SolidSmallButton, SolidSmallRoundButton, SplashScreenService, StatsBarComponent, StatsCardComponent, StepperComponent, StorageService, SwipeCarouselComponent, SwitchOrgModalComponent, TRI_KEYS, TabbedContentComponent, TableSkeletonComponent, TabsComponent, Terminal404Component, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeService, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, TokenService, ToolbarActionType, ToolbarComponent, TransferOwnershipModalComponent, TranslatePipe, TypedCollection, UPDATE_BANNER_DEFAULT_CONTENT, UPDATE_BANNER_I18N_NAMESPACE, UpdateBannerComponent, UserAvatarComponent, UsernameInputComponent, VALTECH_ADS_CONFIG, VALTECH_APP_CONFIG, VALTECH_APP_VERSION, VALTECH_AUTH_CONFIG, VALTECH_COMPANY_LINKS, VALTECH_CONTENT_CONFIG, VALTECH_DEBUG_CONSOLE, VALTECH_DEFAULT_CONTENT, VALTECH_DONATION_CONFIG, VALTECH_FEEDBACK_CONFIG, VALTECH_FIREBASE_CONFIG, VALTECH_FOOTER_I18N, VALTECH_FOOTER_LOGO, VALTECH_LANGUAGE_SELECTOR, VALTECH_LEGAL_CONFIG, VALTECH_NETWORK_ERROR_KEY, VALTECH_SITE_PATHS, VALTECH_SOCIAL_LINKS, VALTECH_SPLASH_SCREEN, VALTECH_WEB_BASE_URLS, VERSION, ValtechErrorService, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, authGuard, authInterceptor, authPasswordValidator, beautifyLegalArticle, blogPost, buildCompanyFooterProps, buildFooterLinks, buildLegalLinkResolver, buildPath, buildSettingsCards, collections, connectPageRefresh, createErrorStateProps, createFirebaseConfig, createGlowCardProps, createInitialPaginationState, createNumberFromToField, createRefreshableStream, createTitleProps, docs, errorLoggingInterceptor, extractPathParams, generatePatternTiles, generateRandomTile, getAppInfo, getAppVersion, getCollectionPath, getDocumentId, getTimeOfDayKey, goToTop, guestGuard, hasEmulators, interpretError, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isValidPath, joinPath, maxLength, mulberry32, news, parseMarkdownArticle, permissionGuard, permissionGuardFromRoute, provideLegalContent, provideSplashScreen, provideValtechAboutRoutes, provideValtechAccountRoutes, provideValtechAds, provideValtechAppConfig, provideValtechAppVersion, provideValtechAuth, provideValtechAuthInterceptor, provideValtechContent, provideValtechDebugConsole, provideValtechDonations, provideValtechErrorHandling, provideValtechFeedback, provideValtechFirebase, provideValtechI18n, provideValtechLegal, provideValtechNotificationPreferencesRoutes, provideValtechNotificationsRoutes, provideValtechOrganizationRoutes, provideValtechPermissionsRoutes, provideValtechPreferencesRoutes, provideValtechPresets, provideValtechProfileRoutes, provideValtechSecurityRoutes, provideValtechSettingsRoutes, provideValtechSite, provideValtechSkeleton, query, renderPatternSvgInner, replaceSpecialChars, resolveColor$1 as resolveColor, resolveInputDefaultValue, resolveWebBaseUrl, roleGuard, storagePaths, superAdminGuard, toArticle };
|
|
62708
|
+
export { ACTION_CARD_DEFAULTS, AD_SIZE_MAP, API_TABLE_COLUMN_LABELS, ARTICLE_CARD_DEFAULTS, ARTICLE_SPACING, ARTICLE_STRIP_DEFAULTS, AUTH_CTA_DEFAULTS, AVATAR_UPLOAD_DEFAULTS, AccordionComponent, AccountViewComponent, ActionCardComponent, ActionHeaderComponent, ActionType, AdSlotComponent, AdsLoaderService, AdsService, AlertBoxComponent, AnalyticsErrorHandler, AnalyticsRouterTracker, AnalyticsService, AnimatedTerminalComponent, AppConfigService, AppVersionService, ArticleBuilder, ArticleCardComponent, ArticleComponent, ArticleStripComponent, AttachmentUploaderComponent, AuthBackgroundComponent, AuthCtaComponent, AuthService, AuthStateService, AuthStorageService, AuthSyncService, AvatarComponent, AvatarUploadComponent, BOTTOM_NAV_DEFAULTS, BannerComponent, BaseDefault, BlogPostBuilder, BottomNavComponent, BoxComponent, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, CALLOUT_LABELS, CHEV_KEYS, CIRCLE_KEYS, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CONTENT_CARD_DEFAULTS, CORNER_KEYS, CTA_CARD_DEFAULTS, CURRENCY_INFO, CardComponent, CardSection, CardType, CardsCarouselComponent, ChangeEmailModalComponent, ChangePasswordModalComponent, CheckInputComponent, CheckboxRadioInputComponent, ChipGroupComponent, ClearDefault, ClearDefaultBlock, ClearDefaultFull, ClearDefaultRound, ClearDefaultRoundBlock, ClearDefaultRoundFull, CodeDisplayComponent, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ContainerComponent, ContentCardComponent, ContentLoaderComponent, ContentReactionComponent, ContentService, ContentTransformer, CookieBannerComponent, CountdownComponent, CreateOrgModalComponent, CtaCardComponent, CurrencyInputComponent, DEFAULT_ADS_CONFIG, DEFAULT_APP_CONFIG_SERVICE_CONFIG, DEFAULT_APP_VERSION_SERVICE_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_BACK_HEADER, DEFAULT_CANCEL_BUTTON, DEFAULT_CHECK_INTERVAL_MS, DEFAULT_CONFIRM_BUTTON, DEFAULT_COUNTDOWN_LABELS, DEFAULT_COUNTDOWN_LABELS_EN, DEFAULT_DEBUG_CONSOLE_CONFIG, DEFAULT_DONATION_CONFIG, DEFAULT_EMPTY_STATE, DEFAULT_EMULATOR_CONFIG, DEFAULT_FEEDBACK_CONFIG, DEFAULT_FEEDBACK_TYPE_OPTIONS, DEFAULT_HOME_HEADER, DEFAULT_INFINITE_LIST_METADATA, DEFAULT_MODAL_CANCEL_BUTTON, DEFAULT_MODAL_CONFIRM_BUTTON, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLATFORMS, DEFAULT_REFRESHER_METADATA, DEFAULT_SKELETON_CONFIG, DEFAULT_SPLASH_SCREEN_CONFIG, DataTableComponent, DateInputComponent, DateRangeInputComponent, DebugConsoleComponent, DeleteAccountModalComponent, DetailSkeletonComponent, DeviceService, DisplayComponent, DividerComponent, DocsApiTableComponent, DocsBreadcrumbComponent, DocsBuilder, DocsCalloutComponent, DocsCodeExampleComponent, DocsLayoutComponent, DocsNavLinksComponent, DocsNavigationService, DocsPageComponent, DocsSearchComponent, DocsSectionComponent, DocsShellComponent, DocsSidebarComponent, DocsTocComponent, DonationService, DownloadService, EditOrgModalComponent, EmailInputComponent, EmptyStateComponent, ExpandableTextComponent, FEATURES_LIST_DEFAULTS, FUN_MODAL_DEFAULTS, FabComponent, FaqComponent, FeaturesListComponent, FeedbackFormComponent, FeedbackService, FileInputComponent, FirebaseService, FirestoreCollectionFactory, FirestoreService, FontSizeOption, FontSizeService, FooterComponent, FooterLinksComponent, FormComponent, FormSkeletonComponent, FunHeaderComponent, FunModalComponent, GlassComponent, GlowCardComponent, GlowComponent, GridSkeletonComponent, HANDOFF_ROUTE_PARAM, HANDOFF_TOKEN_PARAM, HandoffService, HasPermissionDirective, HeaderComponent, HintComponent, HorizontalScrollComponent, HourInputComponent, HrefComponent, I18nService, IMAGE_DEFAULTS, INFO_CARD_DEFAULTS, INITIAL_AUTH_STATE, INITIAL_MFA_STATE, INVITATION_CARD_DEFAULTS, Icon, IconComponent, IconService, ImageComponent, ImageCropComponent, ImageService, InAppBrowserService, InfiniteListComponent, InfoCardComponent, InfoComponent, InputI18nHelper, InputType, InvitationCardComponent, InviteMemberModalComponent, ItemListComponent, LANG_STORAGE_KEY$1 as LANG_STORAGE_KEY, LEGAL_CONTENT_CONFIG, LOGIN_DEFAULTS, LandingSplitComponent, LandingStepsComponent, LanguageSelectorComponent, LayeredCardComponent, LegalContentService, LegalLinkService, LinkComponent, LinkProcessorService, LinkedProvidersComponent, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LoadingDirective, LocalStorageService, LocaleService, LoginAttemptModalComponent, LoginComponent, MEDIA_OBJECT_DEFAULTS, MEMBER_CARD_DEFAULTS, METRIC_CARD_DEFAULTS, MODAL_SIZES, MOTIF_KEYS, MOTION, MaintenancePageComponent, MarkdownArticleParserService, MediaObjectComponent, MemberCardComponent, MemberDetailModalComponent, MenuComponent, MessagingService, MetaService, MetricCardComponent, MfaModalComponent, ModalService, ModalShellComponent, MultiSelectSearchComponent, NUM_KEYS, NavigationService, NetworkBannerComponent, NetworkStatusService, NewsBuilder, NoContentComponent, NotesBoxComponent, NotificationActionService, NotificationPreferencesViewComponent, NotificationsService, NotificationsViewComponent, NumberFromToComponent, NumberInputComponent, NumberStepperComponent, OAUTH_PROVIDERS_INFO, OAuthCallbackComponent, OAuthService, OrgInfoSheetComponent, OrgService, OrgSwitchService, OrganizationViewComponent, OutlineDefault, OutlineDefaultBlock, OutlineDefaultFull, OutlineDefaultRound, OutlineDefaultRoundBlock, OutlineDefaultRoundFull, PATTERN_MOTIFS, PATTERN_PALETTES, PATTERN_STYLE_CONFIGS, PLATFORM_CONFIGS, PageContentComponent, PageLinksComponent, PageRefreshService, PageTemplateComponent, PageWavesComponent, PageWrapperComponent, PaginationComponent, PaginationService, PasswordInputComponent, PatternComponent, PermissionCatalogService, PermissionsViewComponent, PhoneInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PreferencesService, PreferencesViewComponent, PresetService, PriceTagComponent, PrimarySolidBlockButton, PrimarySolidBlockHrefButton, PrimarySolidBlockIconButton, PrimarySolidBlockIconHrefButton, PrimarySolidDefaultRoundButton, PrimarySolidDefaultRoundHrefButton, PrimarySolidDefaultRoundIconButton, PrimarySolidDefaultRoundIconHrefButton, PrimarySolidFullButton, PrimarySolidFullHrefButton, PrimarySolidFullIconButton, PrimarySolidFullIconHrefButton, PrimarySolidLargeRoundButton, PrimarySolidLargeRoundHrefButton, PrimarySolidLargeRoundIconButton, PrimarySolidLargeRoundIconHrefButton, PrimarySolidSmallRoundButton, PrimarySolidSmallRoundHrefButton, PrimarySolidSmallRoundIconButton, PrimarySolidSmallRoundIconHrefButton, ProcessLinksPipe, ProfileSkeletonComponent, ProfileViewComponent, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrCodeComponent, QrGeneratorService, QueryBuilder, QuoteBoxComponent, REQUEST_STATUSES, RadioInputComponent, RangeInputComponent, RatingComponent, RefresherComponent, RequestFirestoreService, RequestFormBuilderService, RequestService, RightsFooterComponent, RotatingTextComponent, SEARCH_HEADER_DEFAULTS, SETTINGS_SECTIONS_CATALOG, SHAPE_KEYS, SHARE_PROFILE_MODAL_DEFAULTS, SKELETON_LAYOUT_DEFAULT_ROWS, SKELETON_PRESETS, SOLID_KEYS, STATS_BAR_DEFAULTS, STROKE_KEYS, SearchHeaderComponent, SearchSelectorComponent, SearchbarComponent, SecondarySolidBlockButton, SecondarySolidBlockHrefButton, SecondarySolidBlockIconButton, SecondarySolidBlockIconHrefButton, SecondarySolidDefaultRoundButton, SecondarySolidDefaultRoundHrefButton, SecondarySolidDefaultRoundIconButton, SecondarySolidDefaultRoundIconHrefButton, SecondarySolidFullButton, SecondarySolidFullHrefButton, SecondarySolidFullIconButton, SecondarySolidFullIconHrefButton, SecondarySolidLargeRoundButton, SecondarySolidLargeRoundHrefButton, SecondarySolidLargeRoundIconButton, SecondarySolidLargeRoundIconHrefButton, SecondarySolidSmallRoundButton, SecondarySolidSmallRoundHrefButton, SecondarySolidSmallRoundIconButton, SecondarySolidSmallRoundIconHrefButton, SecurityViewComponent, SegmentControlComponent, SelectSearchComponent, SessionListModalComponent, SessionService, SettingsHubComponent, ShareButtonsComponent, ShareProfileModalComponent, SimpleComponent, SkeletonComponent, SkeletonLayoutComponent, SkeletonService, SolidBlockButton, SolidDefault, SolidDefaultBlock, SolidDefaultButton, SolidDefaultFull, SolidDefaultRound, SolidDefaultRoundBlock, SolidDefaultRoundButton, SolidDefaultRoundFull, SolidFullButton, SolidLargeButton, SolidLargeRoundButton, SolidSmallButton, SolidSmallRoundButton, SplashScreenService, StatsBarComponent, StatsCardComponent, StepperComponent, StorageService, SwipeCarouselComponent, SwitchOrgModalComponent, TRI_KEYS, TabbedContentComponent, TableSkeletonComponent, TabsComponent, Terminal404Component, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeService, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, TokenService, ToolbarActionType, ToolbarComponent, TransferOwnershipModalComponent, TranslatePipe, TypedCollection, UPDATE_BANNER_DEFAULT_CONTENT, UPDATE_BANNER_I18N_NAMESPACE, UpdateBannerComponent, UserAvatarComponent, UsernameInputComponent, VALTECH_ADS_CONFIG, VALTECH_APP_CONFIG, VALTECH_APP_VERSION, VALTECH_AUTH_CONFIG, VALTECH_COMPANY_LINKS, VALTECH_CONTENT_CONFIG, VALTECH_DEBUG_CONSOLE, VALTECH_DEFAULT_CONTENT, VALTECH_DONATION_CONFIG, VALTECH_FEEDBACK_CONFIG, VALTECH_FIREBASE_CONFIG, VALTECH_FOOTER_I18N, VALTECH_FOOTER_LOGO, VALTECH_LANGUAGE_SELECTOR, VALTECH_LEGAL_CONFIG, VALTECH_NETWORK_ERROR_KEY, VALTECH_SITE_PATHS, VALTECH_SOCIAL_LINKS, VALTECH_SPLASH_SCREEN, VALTECH_WEB_BASE_URLS, VERSION, ValtechErrorService, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, authGuard, authInterceptor, authPasswordValidator, beautifyLegalArticle, blogPost, buildCompanyFooterProps, buildFooterLinks, buildLegalLinkResolver, buildPath, buildSettingsCards, collections, connectPageRefresh, createErrorStateProps, createFirebaseConfig, createGlowCardProps, createInitialPaginationState, createNumberFromToField, createRefreshableStream, createTitleProps, docs, errorLoggingInterceptor, extractPathParams, generatePatternTiles, generateRandomTile, getAppInfo, getAppVersion, getCollectionPath, getDocumentId, getTimeOfDayKey, goToTop, guestGuard, hasEmulators, interpretError, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isValidPath, joinPath, maxLength, mulberry32, news, parseMarkdownArticle, permissionGuard, permissionGuardFromRoute, provideLegalContent, provideSplashScreen, provideValtechAccountRoutes, provideValtechAds, provideValtechAppConfig, provideValtechAppVersion, provideValtechAuth, provideValtechAuthInterceptor, provideValtechContent, provideValtechDebugConsole, provideValtechDonations, provideValtechErrorHandling, provideValtechFeedback, provideValtechFirebase, provideValtechI18n, provideValtechLegal, provideValtechNotificationPreferencesRoutes, provideValtechNotificationsRoutes, provideValtechOrganizationRoutes, provideValtechPermissionsRoutes, provideValtechPreferencesRoutes, provideValtechPresets, provideValtechProfileRoutes, provideValtechSecurityRoutes, provideValtechSettingsRoutes, provideValtechSite, provideValtechSkeleton, query, renderPatternSvgInner, replaceSpecialChars, resolveColor$1 as resolveColor, resolveInputDefaultValue, resolveWebBaseUrl, roleGuard, storagePaths, superAdminGuard, toArticle };
|
|
63226
62709
|
//# sourceMappingURL=valtech-components.mjs.map
|