valtech-components 4.0.970 → 4.0.972
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/organisms/page-block/page-block.component.mjs +254 -0
- package/esm2022/lib/components/organisms/page-block/types.mjs +20 -0
- package/esm2022/lib/components/organisms/rich-editor/article-to-tiptap.mjs +110 -0
- package/esm2022/lib/components/organisms/rich-editor/rich-editor.component.mjs +287 -0
- package/esm2022/lib/components/organisms/rich-editor/rich-editor.i18n.mjs +27 -0
- package/esm2022/lib/components/organisms/rich-editor/tiptap-to-article.mjs +136 -0
- package/esm2022/lib/components/organisms/rich-editor/types.mjs +2 -0
- package/esm2022/lib/components/organisms/video-player/types.mjs +12 -0
- package/esm2022/lib/components/organisms/video-player/video-player.component.mjs +235 -0
- package/esm2022/lib/version.mjs +2 -2
- package/esm2022/public-api.mjs +13 -1
- package/fesm2022/valtech-components.mjs +1060 -3
- package/fesm2022/valtech-components.mjs.map +1 -1
- package/lib/components/organisms/page-block/page-block.component.d.ts +65 -0
- package/lib/components/organisms/page-block/types.d.ts +102 -0
- package/lib/components/organisms/rich-editor/article-to-tiptap.d.ts +3 -0
- package/lib/components/organisms/rich-editor/rich-editor.component.d.ts +46 -0
- package/lib/components/organisms/rich-editor/rich-editor.i18n.d.ts +26 -0
- package/lib/components/organisms/rich-editor/tiptap-to-article.d.ts +38 -0
- package/lib/components/organisms/rich-editor/types.d.ts +21 -0
- package/lib/components/organisms/video-player/types.d.ts +45 -0
- package/lib/components/organisms/video-player/video-player.component.d.ts +42 -0
- package/lib/version.d.ts +1 -1
- package/package.json +5 -1
- package/public-api.d.ts +8 -0
|
@@ -27,7 +27,7 @@ import * as i1$5 from '@ionic/angular/standalone';
|
|
|
27
27
|
import { IonText, IonHeader, IonToolbar, IonButtons, IonButton, IonContent, IonFooter, IonSpinner, AlertController, IonAvatar, IonCard, IonIcon, IonModal, IonTitle, IonProgressBar, IonSkeletonText, IonFab, IonFabButton, IonFabList, IonLabel, IonCardContent, IonCardHeader, IonCardTitle, IonCardSubtitle, IonCheckbox, IonRadio, IonRadioGroup, IonTextarea, IonDatetime, IonInput, IonSelect, IonSelectOption, IonPopover, IonList, IonItem, IonChip, IonRange, IonSearchbar, IonSegment, IonSegmentButton, IonToggle, IonRippleEffect, IonAccordion, IonAccordionGroup, IonTabBar, IonTabButton, IonBadge, IonBreadcrumb, IonBreadcrumbs, IonInfiniteScroll, IonInfiniteScrollContent, IonNote, IonDatetimeButton, ToastController as ToastController$1, IonCol, IonRow, IonRefresher, IonRefresherContent, IonMenuButton, IonListHeader, IonGrid, MenuController, IonMenu, IonMenuToggle, IonSplitPane, IonAlert } from '@ionic/angular/standalone';
|
|
28
28
|
import { Browser } from '@capacitor/browser';
|
|
29
29
|
import { addIcons } from 'ionicons';
|
|
30
|
-
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, chevronBackCircleOutline, chevronForwardCircleOutline, helpCircleOutline, logInOutline, chatbubbleEllipsesOutline, listOutline, folderOutline, pricetagOutline, starOutline, gameControllerOutline, checkmarkOutline, clipboardOutline, copyOutline, filterOutline, locationOutline, calendarOutline, businessOutline, logoTwitter, logoInstagram, logoLinkedin, logoYoutube, logoTiktok, logoFacebook, logoGoogle, mailOutline, qrCodeOutline, sendOutline, createOutline, trashOutline, playOutline, peopleOutline, phonePortraitOutline, refreshOutline, documentTextOutline, lockClosedOutline, cloudUploadOutline, textOutline, informationCircleOutline, logoNpm, removeOutline, optionsOutline, personOutline, shieldCheckmarkOutline, keyOutline, desktopOutline, logOutOutline, cloudDownloadOutline, cloudOutline, gitBranchOutline, layersOutline, serverOutline, warningOutline, bulbOutline, lockOpenOutline, diamondOutline, newspaperOutline, add, close, share, create, trash, star, camera, mic, send, downloadOutline, reorderThreeOutline, chevronDown, language, globeOutline, checkmark, sunnyOutline, moonOutline, list, grid, apps, menu, search, person, helpCircle, informationCircle, documentText, mail, calendar, folder, chevronForward, ellipsisHorizontal, chevronBack, playBack, playForward, ellipse, 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, chevronDownCircleOutline, closeCircle, alertCircle, logoApple, logoMicrosoft, linkOutline, unlinkOutline, attachOutline, cameraOutline, closeCircleOutline, documentOutline, imageOutline, cloudOfflineOutline, printOutline, chevronBackOutline, swapVerticalOutline, chevronUpOutline, searchOutline, cartOutline, chatbubble, compass, compassOutline, gridOutline, documents, documentsOutline, statsChart, statsChartOutline, laptopOutline, swapHorizontalOutline, codeSlashOutline, appsOutline, notificationsOffOutline, alarmOutline, chatboxEllipsesOutline, checkmarkDoneOutline, cogOutline, shareSocialOutline, sparklesOutline, trophyOutline, musicalNotesOutline, volumeHighOutline, volumeMuteOutline, menuOutline, flashlight, flashlightOutline, stopCircleOutline, videocamOffOutline, keypadOutline, checkmarkDone, arrowUndoOutline, micOutline, pulseOutline, arrowUpOutline } from 'ionicons/icons';
|
|
30
|
+
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, chevronBackCircleOutline, chevronForwardCircleOutline, helpCircleOutline, logInOutline, chatbubbleEllipsesOutline, listOutline, folderOutline, pricetagOutline, starOutline, gameControllerOutline, checkmarkOutline, clipboardOutline, copyOutline, filterOutline, locationOutline, calendarOutline, businessOutline, logoTwitter, logoInstagram, logoLinkedin, logoYoutube, logoTiktok, logoFacebook, logoGoogle, mailOutline, qrCodeOutline, sendOutline, createOutline, trashOutline, playOutline, peopleOutline, phonePortraitOutline, refreshOutline, documentTextOutline, lockClosedOutline, cloudUploadOutline, textOutline, informationCircleOutline, logoNpm, removeOutline, optionsOutline, personOutline, shieldCheckmarkOutline, keyOutline, desktopOutline, logOutOutline, cloudDownloadOutline, cloudOutline, gitBranchOutline, layersOutline, serverOutline, warningOutline, bulbOutline, lockOpenOutline, diamondOutline, newspaperOutline, add, close, share, create, trash, star, camera, mic, send, downloadOutline, reorderThreeOutline, chevronDown, language, globeOutline, checkmark, sunnyOutline, moonOutline, list, grid, apps, menu, search, person, helpCircle, informationCircle, documentText, mail, calendar, folder, chevronForward, ellipsisHorizontal, chevronBack, playBack, playForward, ellipse, 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, chevronDownCircleOutline, closeCircle, alertCircle, logoApple, logoMicrosoft, linkOutline, unlinkOutline, attachOutline, cameraOutline, closeCircleOutline, documentOutline, imageOutline, cloudOfflineOutline, chatboxOutline, printOutline, chevronBackOutline, swapVerticalOutline, chevronUpOutline, searchOutline, cartOutline, chatbubble, compass, compassOutline, gridOutline, documents, documentsOutline, statsChart, statsChartOutline, laptopOutline, swapHorizontalOutline, codeSlashOutline, appsOutline, notificationsOffOutline, alarmOutline, chatboxEllipsesOutline, checkmarkDoneOutline, cogOutline, shareSocialOutline, sparklesOutline, trophyOutline, musicalNotesOutline, volumeHighOutline, volumeMuteOutline, menuOutline, flashlight, flashlightOutline, stopCircleOutline, videocamOffOutline, keypadOutline, checkmarkDone, arrowUndoOutline, micOutline, pulseOutline, arrowUpOutline } from 'ionicons/icons';
|
|
31
31
|
import * as i1$7 from '@angular/platform-browser';
|
|
32
32
|
import { DomSanitizer, Meta, Title } from '@angular/platform-browser';
|
|
33
33
|
import QRCodeStyling from 'qr-code-styling';
|
|
@@ -57,6 +57,9 @@ import { Capacitor } from '@capacitor/core';
|
|
|
57
57
|
import { Calendar } from 'vanilla-calendar-pro';
|
|
58
58
|
import Compressor from 'compressorjs';
|
|
59
59
|
import { ImageCropperComponent } from 'ngx-image-cropper';
|
|
60
|
+
import { Editor } from '@tiptap/core';
|
|
61
|
+
import StarterKit from '@tiptap/starter-kit';
|
|
62
|
+
import Image$1 from '@tiptap/extension-image';
|
|
60
63
|
import { trigger, transition, style, animate } from '@angular/animations';
|
|
61
64
|
import 'prismjs/components/prism-scss';
|
|
62
65
|
import 'prismjs/components/prism-json';
|
|
@@ -67,7 +70,7 @@ import fixWebmDuration from 'fix-webm-duration';
|
|
|
67
70
|
* Current version of valtech-components.
|
|
68
71
|
* This is automatically updated during the publish process.
|
|
69
72
|
*/
|
|
70
|
-
const VERSION = '4.0.
|
|
73
|
+
const VERSION = '4.0.972';
|
|
71
74
|
|
|
72
75
|
function evaluateValtechAccess(rule, context, features = {}, visitedFeatures = new Set()) {
|
|
73
76
|
if (rule == null)
|
|
@@ -39403,6 +39406,553 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
39403
39406
|
type: Input
|
|
39404
39407
|
}] } });
|
|
39405
39408
|
|
|
39409
|
+
/**
|
|
39410
|
+
* Defaults i18n (es/en) del `val-rich-editor`. Auto-registrados en el
|
|
39411
|
+
* constructor (namespace `RichEditor`) — el consumer nunca los registra.
|
|
39412
|
+
*/
|
|
39413
|
+
const RICH_EDITOR_I18N = {
|
|
39414
|
+
es: {
|
|
39415
|
+
bold: 'Negrita',
|
|
39416
|
+
italic: 'Cursiva',
|
|
39417
|
+
heading2: 'Título',
|
|
39418
|
+
heading3: 'Subtítulo',
|
|
39419
|
+
bulletList: 'Lista con viñetas',
|
|
39420
|
+
orderedList: 'Lista numerada',
|
|
39421
|
+
quote: 'Cita',
|
|
39422
|
+
separator: 'Separador',
|
|
39423
|
+
},
|
|
39424
|
+
en: {
|
|
39425
|
+
bold: 'Bold',
|
|
39426
|
+
italic: 'Italic',
|
|
39427
|
+
heading2: 'Heading',
|
|
39428
|
+
heading3: 'Subheading',
|
|
39429
|
+
bulletList: 'Bullet list',
|
|
39430
|
+
orderedList: 'Numbered list',
|
|
39431
|
+
quote: 'Quote',
|
|
39432
|
+
separator: 'Separator',
|
|
39433
|
+
},
|
|
39434
|
+
};
|
|
39435
|
+
|
|
39436
|
+
/** Texto inline con marks bold/italic convertidas a <strong>/<em> — mismo
|
|
39437
|
+
* criterio que `allowPartialBold` en ArticleTextElement/ArticleNoteElement:
|
|
39438
|
+
* el elemento consumer debe setear `allowPartialBold: true` para que se
|
|
39439
|
+
* rendericen (si no, val-text/val-note escapan el HTML a propósito). */
|
|
39440
|
+
function inlineText(node) {
|
|
39441
|
+
if (node.type === 'text') {
|
|
39442
|
+
let text = node.text ?? '';
|
|
39443
|
+
for (const mark of node.marks ?? []) {
|
|
39444
|
+
if (mark.type === 'bold')
|
|
39445
|
+
text = `<strong>${text}</strong>`;
|
|
39446
|
+
if (mark.type === 'italic')
|
|
39447
|
+
text = `<em>${text}</em>`;
|
|
39448
|
+
if (mark.type === 'code')
|
|
39449
|
+
text = `<code>${text}</code>`;
|
|
39450
|
+
}
|
|
39451
|
+
return text;
|
|
39452
|
+
}
|
|
39453
|
+
return (node.content ?? []).map(inlineText).join('');
|
|
39454
|
+
}
|
|
39455
|
+
function hasBold(node) {
|
|
39456
|
+
if (node.type === 'text') {
|
|
39457
|
+
return (node.marks ?? []).some(m => m.type === 'bold' || m.type === 'code');
|
|
39458
|
+
}
|
|
39459
|
+
return (node.content ?? []).some(hasBold);
|
|
39460
|
+
}
|
|
39461
|
+
function paragraphText(node) {
|
|
39462
|
+
return (node.content ?? []).map(inlineText).join('');
|
|
39463
|
+
}
|
|
39464
|
+
function listItemsFrom(node) {
|
|
39465
|
+
return (node.content ?? []).map(li => ({
|
|
39466
|
+
text: (li.content ?? []).map(paragraphText).join(' '),
|
|
39467
|
+
}));
|
|
39468
|
+
}
|
|
39469
|
+
/**
|
|
39470
|
+
* Convierte un doc de TipTap a `ArticleElement[]`. Función pura — sin
|
|
39471
|
+
* Angular DI, usable también desde Node (mismo criterio que
|
|
39472
|
+
* `parseMarkdownArticle`).
|
|
39473
|
+
*/
|
|
39474
|
+
function tiptapDocToArticleElements(doc) {
|
|
39475
|
+
const elements = [];
|
|
39476
|
+
for (const node of doc.content ?? []) {
|
|
39477
|
+
switch (node.type) {
|
|
39478
|
+
case 'heading': {
|
|
39479
|
+
const level = node.attrs?.['level'] ?? 2;
|
|
39480
|
+
elements.push({
|
|
39481
|
+
type: level <= 2 ? 'title' : 'subtitle',
|
|
39482
|
+
props: {
|
|
39483
|
+
content: paragraphText(node),
|
|
39484
|
+
size: level === 1 ? 'large' : level === 2 ? 'medium' : 'small',
|
|
39485
|
+
color: 'dark',
|
|
39486
|
+
bold: true,
|
|
39487
|
+
},
|
|
39488
|
+
});
|
|
39489
|
+
break;
|
|
39490
|
+
}
|
|
39491
|
+
case 'paragraph': {
|
|
39492
|
+
const content = paragraphText(node);
|
|
39493
|
+
if (!content.trim())
|
|
39494
|
+
break; // párrafo vacío (Enter suelto) — no genera elemento
|
|
39495
|
+
elements.push({
|
|
39496
|
+
type: 'text',
|
|
39497
|
+
props: {
|
|
39498
|
+
content,
|
|
39499
|
+
size: 'medium',
|
|
39500
|
+
color: 'dark',
|
|
39501
|
+
bold: false,
|
|
39502
|
+
allowPartialBold: hasBold(node),
|
|
39503
|
+
},
|
|
39504
|
+
});
|
|
39505
|
+
break;
|
|
39506
|
+
}
|
|
39507
|
+
case 'bulletList':
|
|
39508
|
+
case 'orderedList': {
|
|
39509
|
+
elements.push({
|
|
39510
|
+
type: 'list',
|
|
39511
|
+
props: {
|
|
39512
|
+
items: listItemsFrom(node),
|
|
39513
|
+
listType: node.type === 'orderedList' ? 'ordered' : 'unordered',
|
|
39514
|
+
},
|
|
39515
|
+
});
|
|
39516
|
+
break;
|
|
39517
|
+
}
|
|
39518
|
+
case 'blockquote': {
|
|
39519
|
+
elements.push({
|
|
39520
|
+
type: 'quote',
|
|
39521
|
+
props: {
|
|
39522
|
+
content: (node.content ?? []).map(paragraphText).join(' '),
|
|
39523
|
+
size: 'medium',
|
|
39524
|
+
color: 'dark',
|
|
39525
|
+
bold: false,
|
|
39526
|
+
showQuoteMark: true,
|
|
39527
|
+
},
|
|
39528
|
+
});
|
|
39529
|
+
break;
|
|
39530
|
+
}
|
|
39531
|
+
case 'codeBlock': {
|
|
39532
|
+
elements.push({
|
|
39533
|
+
type: 'code',
|
|
39534
|
+
props: {
|
|
39535
|
+
code: (node.content ?? []).map(n => n.text ?? '').join('\n'),
|
|
39536
|
+
language: node.attrs?.['language'] ?? undefined,
|
|
39537
|
+
},
|
|
39538
|
+
});
|
|
39539
|
+
break;
|
|
39540
|
+
}
|
|
39541
|
+
case 'horizontalRule': {
|
|
39542
|
+
elements.push({ type: 'separator', props: { style: 'line' } });
|
|
39543
|
+
break;
|
|
39544
|
+
}
|
|
39545
|
+
case 'image': {
|
|
39546
|
+
const src = node.attrs?.['src'] ?? '';
|
|
39547
|
+
if (!src)
|
|
39548
|
+
break; // sin src no hay nada que renderizar
|
|
39549
|
+
elements.push({
|
|
39550
|
+
type: 'image',
|
|
39551
|
+
props: {
|
|
39552
|
+
src,
|
|
39553
|
+
alt: node.attrs?.['alt'] ?? '',
|
|
39554
|
+
title: node.attrs?.['title'] ?? undefined,
|
|
39555
|
+
},
|
|
39556
|
+
});
|
|
39557
|
+
break;
|
|
39558
|
+
}
|
|
39559
|
+
default:
|
|
39560
|
+
break; // nodo no soportado todavía — se omite, no rompe el resto
|
|
39561
|
+
}
|
|
39562
|
+
}
|
|
39563
|
+
return elements;
|
|
39564
|
+
}
|
|
39565
|
+
function tiptapDocToArticle(doc, config) {
|
|
39566
|
+
return {
|
|
39567
|
+
...config,
|
|
39568
|
+
elements: tiptapDocToArticleElements(doc),
|
|
39569
|
+
};
|
|
39570
|
+
}
|
|
39571
|
+
|
|
39572
|
+
/**
|
|
39573
|
+
* Conversión inversa de `tiptapDocToArticle` — hidrata `val-rich-editor` con
|
|
39574
|
+
* contenido ya guardado como `ArticleMetadata` (ej. una receta existente que
|
|
39575
|
+
* se vuelve a editar). No es un round-trip perfecto: `ArticleElement` cubre
|
|
39576
|
+
* tipos que TipTap no tiene nodo nativo para editar (`note`, `diagram`,
|
|
39577
|
+
* `command`, `highlight`, `button`, `video`, `custom`) — esos se degradan a
|
|
39578
|
+
* un párrafo de texto plano, editable pero sin su formato especial. Es
|
|
39579
|
+
* intencional: mejor mostrar el contenido (aunque simplificado) que perderlo
|
|
39580
|
+
* o que el editor rechace abrir el documento.
|
|
39581
|
+
*/
|
|
39582
|
+
const STRONG_OR_EM = /<(strong|b|em|i|code)>(.*?)<\/\1>/g;
|
|
39583
|
+
/** Extrae marks (bold/italic/code) de un string con <strong>/<em>/<code>
|
|
39584
|
+
* embebido — el inverso de `inlineText` en tiptap-to-article.ts. Simplifica
|
|
39585
|
+
* a un solo nivel de anidación (suficiente para lo que el editor produce). */
|
|
39586
|
+
function textToTiptapInline(html) {
|
|
39587
|
+
if (!html)
|
|
39588
|
+
return [];
|
|
39589
|
+
const nodes = [];
|
|
39590
|
+
let lastIndex = 0;
|
|
39591
|
+
STRONG_OR_EM.lastIndex = 0;
|
|
39592
|
+
let match;
|
|
39593
|
+
const markFor = (tag) => {
|
|
39594
|
+
if (tag === 'strong' || tag === 'b')
|
|
39595
|
+
return { type: 'bold' };
|
|
39596
|
+
if (tag === 'em' || tag === 'i')
|
|
39597
|
+
return { type: 'italic' };
|
|
39598
|
+
return { type: 'code' };
|
|
39599
|
+
};
|
|
39600
|
+
while ((match = STRONG_OR_EM.exec(html)) !== null) {
|
|
39601
|
+
if (match.index > lastIndex) {
|
|
39602
|
+
nodes.push({ type: 'text', text: html.slice(lastIndex, match.index) });
|
|
39603
|
+
}
|
|
39604
|
+
nodes.push({ type: 'text', text: match[2], marks: [markFor(match[1])] });
|
|
39605
|
+
lastIndex = match.index + match[0].length;
|
|
39606
|
+
}
|
|
39607
|
+
if (lastIndex < html.length) {
|
|
39608
|
+
nodes.push({ type: 'text', text: html.slice(lastIndex) });
|
|
39609
|
+
}
|
|
39610
|
+
return nodes.length ? nodes : [{ type: 'text', text: html }];
|
|
39611
|
+
}
|
|
39612
|
+
function paragraph(text) {
|
|
39613
|
+
return { type: 'paragraph', content: textToTiptapInline(text) };
|
|
39614
|
+
}
|
|
39615
|
+
function elementToTiptapNodes(el) {
|
|
39616
|
+
switch (el.type) {
|
|
39617
|
+
case 'title':
|
|
39618
|
+
case 'subtitle': {
|
|
39619
|
+
const level = el.type === 'title' ? (el.props.size === 'large' ? 1 : 2) : 3;
|
|
39620
|
+
return [
|
|
39621
|
+
{
|
|
39622
|
+
type: 'heading',
|
|
39623
|
+
attrs: { level },
|
|
39624
|
+
content: textToTiptapInline(el.props.content ?? ''),
|
|
39625
|
+
},
|
|
39626
|
+
];
|
|
39627
|
+
}
|
|
39628
|
+
case 'text':
|
|
39629
|
+
case 'paragraph':
|
|
39630
|
+
return [paragraph(el.props.content ?? '')];
|
|
39631
|
+
case 'list':
|
|
39632
|
+
return [
|
|
39633
|
+
{
|
|
39634
|
+
type: el.props.listType === 'ordered' ? 'orderedList' : 'bulletList',
|
|
39635
|
+
content: el.props.items.map(item => ({
|
|
39636
|
+
type: 'listItem',
|
|
39637
|
+
content: [paragraph(item.text)],
|
|
39638
|
+
})),
|
|
39639
|
+
},
|
|
39640
|
+
];
|
|
39641
|
+
case 'quote':
|
|
39642
|
+
return [
|
|
39643
|
+
{
|
|
39644
|
+
type: 'blockquote',
|
|
39645
|
+
content: [paragraph(el.props.content ?? '')],
|
|
39646
|
+
},
|
|
39647
|
+
];
|
|
39648
|
+
case 'code':
|
|
39649
|
+
return [
|
|
39650
|
+
{
|
|
39651
|
+
type: 'codeBlock',
|
|
39652
|
+
attrs: el.props.language ? { language: el.props.language } : undefined,
|
|
39653
|
+
content: el.props.code ? [{ type: 'text', text: el.props.code }] : [],
|
|
39654
|
+
},
|
|
39655
|
+
];
|
|
39656
|
+
case 'separator':
|
|
39657
|
+
return [{ type: 'horizontalRule' }];
|
|
39658
|
+
case 'image':
|
|
39659
|
+
return [
|
|
39660
|
+
{
|
|
39661
|
+
type: 'image',
|
|
39662
|
+
attrs: { src: el.props.src, alt: el.props.alt, title: el.props.title },
|
|
39663
|
+
},
|
|
39664
|
+
];
|
|
39665
|
+
// Sin nodo TipTap nativo — se degrada a párrafo de texto plano (ver
|
|
39666
|
+
// comentario del módulo). El contenido nunca se pierde, solo su formato.
|
|
39667
|
+
case 'note':
|
|
39668
|
+
return [paragraph(el.props.text ?? '')];
|
|
39669
|
+
case 'highlight':
|
|
39670
|
+
return [paragraph(el.props.content ?? '')];
|
|
39671
|
+
default:
|
|
39672
|
+
return [];
|
|
39673
|
+
}
|
|
39674
|
+
}
|
|
39675
|
+
function articleToTiptapDoc(article) {
|
|
39676
|
+
return {
|
|
39677
|
+
type: 'doc',
|
|
39678
|
+
content: article.elements.flatMap(elementToTiptapNodes),
|
|
39679
|
+
};
|
|
39680
|
+
}
|
|
39681
|
+
|
|
39682
|
+
// Íconos de la toolbar. B/I/H2/H3 no tienen ícono Ionicons dedicado — se
|
|
39683
|
+
// renderizan como texto ("B", "I", "H2", "H3") directo en el botón, mismo
|
|
39684
|
+
// criterio que un editor de texto rico convencional (Google Docs, Notion).
|
|
39685
|
+
addIcons({ listOutline, chatboxOutline, removeOutline });
|
|
39686
|
+
/**
|
|
39687
|
+
* val-rich-editor
|
|
39688
|
+
*
|
|
39689
|
+
* Organism: editor WYSIWYG reusable para toda la plataforma, sobre TipTap.
|
|
39690
|
+
* Emite `ArticleMetadata` — el mismo contrato que `val-article` renderiza,
|
|
39691
|
+
* que también producen Markdown (`parseMarkdownArticle`) y (a futuro) el
|
|
39692
|
+
* page builder. El consumer nunca toca TipTap directamente.
|
|
39693
|
+
*
|
|
39694
|
+
* Cobertura de la toolbar v1: negrita, cursiva, título (H2), subtítulo (H3),
|
|
39695
|
+
* lista con/sin viñetas, cita, separador, imagen. Ver `tiptap-to-article.ts`
|
|
39696
|
+
* para qué tipos de `ArticleElement` puede producir el editor hoy.
|
|
39697
|
+
*
|
|
39698
|
+
* @example
|
|
39699
|
+
* ```html
|
|
39700
|
+
* <val-rich-editor
|
|
39701
|
+
* [props]="{ initialValue: recipe.descriptionArticle, placeholder: 'Escribe la preparación...' }"
|
|
39702
|
+
* (articleChange)="onArticleChange($event)"
|
|
39703
|
+
* />
|
|
39704
|
+
* ```
|
|
39705
|
+
*/
|
|
39706
|
+
class RichEditorComponent {
|
|
39707
|
+
constructor() {
|
|
39708
|
+
this.props = {};
|
|
39709
|
+
this.articleChange = new EventEmitter();
|
|
39710
|
+
this.i18n = inject(I18nService);
|
|
39711
|
+
/** Se recalcula en cada `onUpdate`/`onSelectionUpdate` para reflejar el
|
|
39712
|
+
* mark/nodo activo bajo el cursor (ej. el botón "B" resaltado si el
|
|
39713
|
+
* cursor está dentro de texto en negrita). */
|
|
39714
|
+
this._toolbarTick = signal(0);
|
|
39715
|
+
this.toolbarButtons = signal([]);
|
|
39716
|
+
this.i18n.registerDefaults('RichEditor', RICH_EDITOR_I18N);
|
|
39717
|
+
}
|
|
39718
|
+
t(key) {
|
|
39719
|
+
return this.i18n.t(key, 'RichEditor');
|
|
39720
|
+
}
|
|
39721
|
+
ngAfterViewInit() {
|
|
39722
|
+
this.editor = new Editor({
|
|
39723
|
+
element: this.editorHost.nativeElement,
|
|
39724
|
+
extensions: [StarterKit, Image$1],
|
|
39725
|
+
editable: !this.props.disabled,
|
|
39726
|
+
content: this.props.initialValue
|
|
39727
|
+
? articleToTiptapDoc(this.props.initialValue)
|
|
39728
|
+
: '',
|
|
39729
|
+
editorProps: {
|
|
39730
|
+
attributes: {
|
|
39731
|
+
'data-placeholder': this.props.placeholder ?? '',
|
|
39732
|
+
},
|
|
39733
|
+
},
|
|
39734
|
+
onUpdate: ({ editor }) => {
|
|
39735
|
+
this.emitArticle(editor.getJSON());
|
|
39736
|
+
this.refreshToolbar();
|
|
39737
|
+
},
|
|
39738
|
+
onSelectionUpdate: () => this.refreshToolbar(),
|
|
39739
|
+
});
|
|
39740
|
+
this.refreshToolbar();
|
|
39741
|
+
}
|
|
39742
|
+
ngOnChanges(changes) {
|
|
39743
|
+
if (changes['props']?.currentValue && this.editor) {
|
|
39744
|
+
this.editor.setEditable(!this.props.disabled);
|
|
39745
|
+
}
|
|
39746
|
+
}
|
|
39747
|
+
emitArticle(doc) {
|
|
39748
|
+
this.articleChange.emit(tiptapDocToArticle(doc));
|
|
39749
|
+
}
|
|
39750
|
+
refreshToolbar() {
|
|
39751
|
+
const editor = this.editor;
|
|
39752
|
+
if (!editor)
|
|
39753
|
+
return;
|
|
39754
|
+
this.toolbarButtons.set([
|
|
39755
|
+
{
|
|
39756
|
+
token: 'bold',
|
|
39757
|
+
icon: '',
|
|
39758
|
+
label: this.t('bold'),
|
|
39759
|
+
isActive: editor.isActive('bold'),
|
|
39760
|
+
disabled: false,
|
|
39761
|
+
},
|
|
39762
|
+
{
|
|
39763
|
+
token: 'italic',
|
|
39764
|
+
icon: '',
|
|
39765
|
+
label: this.t('italic'),
|
|
39766
|
+
isActive: editor.isActive('italic'),
|
|
39767
|
+
disabled: false,
|
|
39768
|
+
},
|
|
39769
|
+
{
|
|
39770
|
+
token: 'heading2',
|
|
39771
|
+
icon: '',
|
|
39772
|
+
label: this.t('heading2'),
|
|
39773
|
+
isActive: editor.isActive('heading', { level: 2 }),
|
|
39774
|
+
disabled: false,
|
|
39775
|
+
},
|
|
39776
|
+
{
|
|
39777
|
+
token: 'heading3',
|
|
39778
|
+
icon: '',
|
|
39779
|
+
label: this.t('heading3'),
|
|
39780
|
+
isActive: editor.isActive('heading', { level: 3 }),
|
|
39781
|
+
disabled: false,
|
|
39782
|
+
},
|
|
39783
|
+
{
|
|
39784
|
+
token: 'bulletList',
|
|
39785
|
+
icon: 'list-outline',
|
|
39786
|
+
label: this.t('bulletList'),
|
|
39787
|
+
isActive: editor.isActive('bulletList'),
|
|
39788
|
+
disabled: false,
|
|
39789
|
+
},
|
|
39790
|
+
{
|
|
39791
|
+
token: 'orderedList',
|
|
39792
|
+
icon: 'list-outline',
|
|
39793
|
+
label: this.t('orderedList'),
|
|
39794
|
+
isActive: editor.isActive('orderedList'),
|
|
39795
|
+
disabled: false,
|
|
39796
|
+
},
|
|
39797
|
+
{
|
|
39798
|
+
token: 'quote',
|
|
39799
|
+
icon: 'chatbox-outline',
|
|
39800
|
+
label: this.t('quote'),
|
|
39801
|
+
isActive: editor.isActive('blockquote'),
|
|
39802
|
+
disabled: false,
|
|
39803
|
+
},
|
|
39804
|
+
{
|
|
39805
|
+
token: 'separator',
|
|
39806
|
+
icon: 'remove-outline',
|
|
39807
|
+
label: this.t('separator'),
|
|
39808
|
+
isActive: false,
|
|
39809
|
+
disabled: false,
|
|
39810
|
+
},
|
|
39811
|
+
]);
|
|
39812
|
+
}
|
|
39813
|
+
runCommand(token) {
|
|
39814
|
+
const editor = this.editor;
|
|
39815
|
+
if (!editor)
|
|
39816
|
+
return;
|
|
39817
|
+
const chain = editor.chain().focus();
|
|
39818
|
+
switch (token) {
|
|
39819
|
+
case 'bold':
|
|
39820
|
+
chain.toggleBold().run();
|
|
39821
|
+
break;
|
|
39822
|
+
case 'italic':
|
|
39823
|
+
chain.toggleItalic().run();
|
|
39824
|
+
break;
|
|
39825
|
+
case 'heading2':
|
|
39826
|
+
chain.toggleHeading({ level: 2 }).run();
|
|
39827
|
+
break;
|
|
39828
|
+
case 'heading3':
|
|
39829
|
+
chain.toggleHeading({ level: 3 }).run();
|
|
39830
|
+
break;
|
|
39831
|
+
case 'bulletList':
|
|
39832
|
+
chain.toggleBulletList().run();
|
|
39833
|
+
break;
|
|
39834
|
+
case 'orderedList':
|
|
39835
|
+
chain.toggleOrderedList().run();
|
|
39836
|
+
break;
|
|
39837
|
+
case 'quote':
|
|
39838
|
+
chain.toggleBlockquote().run();
|
|
39839
|
+
break;
|
|
39840
|
+
case 'separator':
|
|
39841
|
+
chain.setHorizontalRule().run();
|
|
39842
|
+
break;
|
|
39843
|
+
}
|
|
39844
|
+
this.refreshToolbar();
|
|
39845
|
+
}
|
|
39846
|
+
ngOnDestroy() {
|
|
39847
|
+
this.editor?.destroy();
|
|
39848
|
+
}
|
|
39849
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RichEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
39850
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: RichEditorComponent, isStandalone: true, selector: "val-rich-editor", inputs: { props: "props" }, outputs: { articleChange: "articleChange" }, viewQueries: [{ propertyName: "editorHost", first: true, predicate: ["editorHost"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
39851
|
+
<div class="rich-editor" [class.rich-editor--disabled]="props.disabled">
|
|
39852
|
+
@if (!props.disabled) {
|
|
39853
|
+
<div class="rich-editor__toolbar" role="toolbar">
|
|
39854
|
+
@for (btn of toolbarButtons(); track btn.token) {
|
|
39855
|
+
<ion-button
|
|
39856
|
+
fill="clear"
|
|
39857
|
+
size="small"
|
|
39858
|
+
[class.rich-editor__btn--active]="btn.isActive"
|
|
39859
|
+
[disabled]="btn.disabled"
|
|
39860
|
+
[attr.aria-label]="btn.label"
|
|
39861
|
+
[attr.aria-pressed]="btn.isActive"
|
|
39862
|
+
(click)="runCommand(btn.token)"
|
|
39863
|
+
>
|
|
39864
|
+
@switch (btn.token) {
|
|
39865
|
+
@case ('bold') {
|
|
39866
|
+
<strong>B</strong>
|
|
39867
|
+
}
|
|
39868
|
+
@case ('italic') {
|
|
39869
|
+
<em>I</em>
|
|
39870
|
+
}
|
|
39871
|
+
@case ('heading2') {
|
|
39872
|
+
<strong>H2</strong>
|
|
39873
|
+
}
|
|
39874
|
+
@case ('heading3') {
|
|
39875
|
+
<strong>H3</strong>
|
|
39876
|
+
}
|
|
39877
|
+
@case ('bulletList') {
|
|
39878
|
+
<ion-icon name="list-outline" slot="icon-only" />
|
|
39879
|
+
}
|
|
39880
|
+
@case ('orderedList') {
|
|
39881
|
+
<ion-icon name="list-outline" slot="icon-only" />
|
|
39882
|
+
}
|
|
39883
|
+
@case ('quote') {
|
|
39884
|
+
<ion-icon name="chatbox-outline" slot="icon-only" />
|
|
39885
|
+
}
|
|
39886
|
+
@case ('separator') {
|
|
39887
|
+
<ion-icon name="remove-outline" slot="icon-only" />
|
|
39888
|
+
}
|
|
39889
|
+
}
|
|
39890
|
+
</ion-button>
|
|
39891
|
+
}
|
|
39892
|
+
</div>
|
|
39893
|
+
}
|
|
39894
|
+
<div #editorHost class="rich-editor__surface"></div>
|
|
39895
|
+
</div>
|
|
39896
|
+
`, isInline: true, styles: [".rich-editor{display:flex;flex-direction:column;gap:8px;border:1px solid var(--ion-border-color, rgba(0, 0, 0, .1));border-radius:8px;overflow:hidden}.rich-editor--disabled{opacity:.7}.rich-editor__toolbar{display:flex;flex-wrap:wrap;gap:2px;padding:6px 8px;border-bottom:1px solid var(--ion-border-color, rgba(0, 0, 0, .1));background:var(--ion-color-light, #f4f5f8)}.rich-editor__toolbar ion-button{--padding-start: 8px;--padding-end: 8px;margin:0;font-size:.8125rem;min-width:32px}.rich-editor__btn--active{--background: rgba(var(--ion-color-primary-rgb), .14);--color: var(--ion-color-primary);border-radius:6px}.rich-editor__surface{padding:12px 16px;min-height:160px}.rich-editor__surface ::ng-deep .ProseMirror{outline:none;min-height:140px;color:var(--ion-text-color, #000);font-size:.9375rem;line-height:1.5}.rich-editor__surface ::ng-deep .ProseMirror p.is-editor-empty:first-child:before{content:attr(data-placeholder);color:var(--ion-color-medium, #92949c);float:left;height:0;pointer-events:none}.rich-editor__surface ::ng-deep .ProseMirror p{margin:0 0 .75em}.rich-editor__surface ::ng-deep .ProseMirror h1,.rich-editor__surface ::ng-deep .ProseMirror h2,.rich-editor__surface ::ng-deep .ProseMirror h3{margin:0 0 .5em;color:var(--ion-text-color, #000)}.rich-editor__surface ::ng-deep .ProseMirror blockquote{margin:0 0 .75em;padding-left:12px;border-left:3px solid var(--ion-color-primary, #3880ff);color:var(--ion-color-medium, #92949c)}.rich-editor__surface ::ng-deep .ProseMirror ul,.rich-editor__surface ::ng-deep .ProseMirror ol{margin:0 0 .75em;padding-left:24px}.rich-editor__surface ::ng-deep .ProseMirror img{max-width:100%;border-radius:8px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }] }); }
|
|
39897
|
+
}
|
|
39898
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RichEditorComponent, decorators: [{
|
|
39899
|
+
type: Component,
|
|
39900
|
+
args: [{ selector: 'val-rich-editor', standalone: true, imports: [CommonModule, IonButton, IonIcon], template: `
|
|
39901
|
+
<div class="rich-editor" [class.rich-editor--disabled]="props.disabled">
|
|
39902
|
+
@if (!props.disabled) {
|
|
39903
|
+
<div class="rich-editor__toolbar" role="toolbar">
|
|
39904
|
+
@for (btn of toolbarButtons(); track btn.token) {
|
|
39905
|
+
<ion-button
|
|
39906
|
+
fill="clear"
|
|
39907
|
+
size="small"
|
|
39908
|
+
[class.rich-editor__btn--active]="btn.isActive"
|
|
39909
|
+
[disabled]="btn.disabled"
|
|
39910
|
+
[attr.aria-label]="btn.label"
|
|
39911
|
+
[attr.aria-pressed]="btn.isActive"
|
|
39912
|
+
(click)="runCommand(btn.token)"
|
|
39913
|
+
>
|
|
39914
|
+
@switch (btn.token) {
|
|
39915
|
+
@case ('bold') {
|
|
39916
|
+
<strong>B</strong>
|
|
39917
|
+
}
|
|
39918
|
+
@case ('italic') {
|
|
39919
|
+
<em>I</em>
|
|
39920
|
+
}
|
|
39921
|
+
@case ('heading2') {
|
|
39922
|
+
<strong>H2</strong>
|
|
39923
|
+
}
|
|
39924
|
+
@case ('heading3') {
|
|
39925
|
+
<strong>H3</strong>
|
|
39926
|
+
}
|
|
39927
|
+
@case ('bulletList') {
|
|
39928
|
+
<ion-icon name="list-outline" slot="icon-only" />
|
|
39929
|
+
}
|
|
39930
|
+
@case ('orderedList') {
|
|
39931
|
+
<ion-icon name="list-outline" slot="icon-only" />
|
|
39932
|
+
}
|
|
39933
|
+
@case ('quote') {
|
|
39934
|
+
<ion-icon name="chatbox-outline" slot="icon-only" />
|
|
39935
|
+
}
|
|
39936
|
+
@case ('separator') {
|
|
39937
|
+
<ion-icon name="remove-outline" slot="icon-only" />
|
|
39938
|
+
}
|
|
39939
|
+
}
|
|
39940
|
+
</ion-button>
|
|
39941
|
+
}
|
|
39942
|
+
</div>
|
|
39943
|
+
}
|
|
39944
|
+
<div #editorHost class="rich-editor__surface"></div>
|
|
39945
|
+
</div>
|
|
39946
|
+
`, styles: [".rich-editor{display:flex;flex-direction:column;gap:8px;border:1px solid var(--ion-border-color, rgba(0, 0, 0, .1));border-radius:8px;overflow:hidden}.rich-editor--disabled{opacity:.7}.rich-editor__toolbar{display:flex;flex-wrap:wrap;gap:2px;padding:6px 8px;border-bottom:1px solid var(--ion-border-color, rgba(0, 0, 0, .1));background:var(--ion-color-light, #f4f5f8)}.rich-editor__toolbar ion-button{--padding-start: 8px;--padding-end: 8px;margin:0;font-size:.8125rem;min-width:32px}.rich-editor__btn--active{--background: rgba(var(--ion-color-primary-rgb), .14);--color: var(--ion-color-primary);border-radius:6px}.rich-editor__surface{padding:12px 16px;min-height:160px}.rich-editor__surface ::ng-deep .ProseMirror{outline:none;min-height:140px;color:var(--ion-text-color, #000);font-size:.9375rem;line-height:1.5}.rich-editor__surface ::ng-deep .ProseMirror p.is-editor-empty:first-child:before{content:attr(data-placeholder);color:var(--ion-color-medium, #92949c);float:left;height:0;pointer-events:none}.rich-editor__surface ::ng-deep .ProseMirror p{margin:0 0 .75em}.rich-editor__surface ::ng-deep .ProseMirror h1,.rich-editor__surface ::ng-deep .ProseMirror h2,.rich-editor__surface ::ng-deep .ProseMirror h3{margin:0 0 .5em;color:var(--ion-text-color, #000)}.rich-editor__surface ::ng-deep .ProseMirror blockquote{margin:0 0 .75em;padding-left:12px;border-left:3px solid var(--ion-color-primary, #3880ff);color:var(--ion-color-medium, #92949c)}.rich-editor__surface ::ng-deep .ProseMirror ul,.rich-editor__surface ::ng-deep .ProseMirror ol{margin:0 0 .75em;padding-left:24px}.rich-editor__surface ::ng-deep .ProseMirror img{max-width:100%;border-radius:8px}\n"] }]
|
|
39947
|
+
}], ctorParameters: () => [], propDecorators: { props: [{
|
|
39948
|
+
type: Input
|
|
39949
|
+
}], articleChange: [{
|
|
39950
|
+
type: Output
|
|
39951
|
+
}], editorHost: [{
|
|
39952
|
+
type: ViewChild,
|
|
39953
|
+
args: ['editorHost', { static: true }]
|
|
39954
|
+
}] } });
|
|
39955
|
+
|
|
39406
39956
|
/**
|
|
39407
39957
|
* val-banner
|
|
39408
39958
|
*
|
|
@@ -89861,6 +90411,513 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
89861
90411
|
}]
|
|
89862
90412
|
}] });
|
|
89863
90413
|
|
|
90414
|
+
/**
|
|
90415
|
+
* `val-page-block`
|
|
90416
|
+
*
|
|
90417
|
+
* Organism que renderiza UN bloque del constructor de páginas de plataforma
|
|
90418
|
+
* (ADR-077, `services/page` en el backend). Es el punto de la lib donde el
|
|
90419
|
+
* catálogo de bloques (`hero`, `text`, `gallery`, `cta`, `faq`) mapea 1:1 a
|
|
90420
|
+
* componentes reales — la razón de ser del ADR: "un rediseño de la lib
|
|
90421
|
+
* mejora todas las páginas publicadas sin tocar sus datos".
|
|
90422
|
+
*
|
|
90423
|
+
* Presentacional puro: recibe `props` ya tipados (espejo exacto del `Block`
|
|
90424
|
+
* del backend), sin llamadas HTTP propias ni conocimiento de a qué app
|
|
90425
|
+
* pertenece la página. El bloque `cta` NO navega — emite `(ctaAction)` con
|
|
90426
|
+
* la intención cruda (`{ action }`) para que el consumidor (la app) la
|
|
90427
|
+
* resuelva contra su propio routing (ADR-077: "el CTA guarda una intención,
|
|
90428
|
+
* nunca una URL").
|
|
90429
|
+
*
|
|
90430
|
+
* El caller típico itera `Page.Blocks` y renderiza uno de estos por bloque:
|
|
90431
|
+
*
|
|
90432
|
+
* @example
|
|
90433
|
+
* ```html
|
|
90434
|
+
* @for (block of page().blocks; track $index) {
|
|
90435
|
+
* <val-page-block [props]="block" (ctaAction)="onCtaAction($event)" />
|
|
90436
|
+
* }
|
|
90437
|
+
* ```
|
|
90438
|
+
*/
|
|
90439
|
+
class PageBlockComponent {
|
|
90440
|
+
constructor() {
|
|
90441
|
+
/**
|
|
90442
|
+
* Emite la intención cruda del CTA al hacer click (`{ action }`, nunca una
|
|
90443
|
+
* URL — ver comentario de clase). El consumidor decide qué hacer con
|
|
90444
|
+
* `action`; este componente no la interpreta.
|
|
90445
|
+
*/
|
|
90446
|
+
this.ctaAction = new EventEmitter();
|
|
90447
|
+
/** Fallback de imagen rota (convención de la lib) — un slot, una signal. */
|
|
90448
|
+
this.heroImageFailed = signal(false);
|
|
90449
|
+
/** Índices de `gallery.images` cuya carga falló (`error` del `<img>`). */
|
|
90450
|
+
this.failedGalleryImages = signal(new Set());
|
|
90451
|
+
}
|
|
90452
|
+
get hero() {
|
|
90453
|
+
return this.props.props;
|
|
90454
|
+
}
|
|
90455
|
+
get text() {
|
|
90456
|
+
return this.props.props;
|
|
90457
|
+
}
|
|
90458
|
+
get gallery() {
|
|
90459
|
+
return this.props.props;
|
|
90460
|
+
}
|
|
90461
|
+
get cta() {
|
|
90462
|
+
return this.props.props;
|
|
90463
|
+
}
|
|
90464
|
+
get faq() {
|
|
90465
|
+
return this.props.props;
|
|
90466
|
+
}
|
|
90467
|
+
/**
|
|
90468
|
+
* `text.body` es texto plano (no markdown — a diferencia de
|
|
90469
|
+
* `val-article`/`val-faq`, `blocks_validate.go` solo exige un string no
|
|
90470
|
+
* vacío). Partido por línea para que `val-text` (un `<p>` por línea)
|
|
90471
|
+
* respete los saltos que el autor escribió, sin interpretar sintaxis.
|
|
90472
|
+
*/
|
|
90473
|
+
textParagraphs() {
|
|
90474
|
+
return this.text.body.split('\n').filter(line => line.trim().length > 0);
|
|
90475
|
+
}
|
|
90476
|
+
/**
|
|
90477
|
+
* `val-faq` agrupa por categoría; el bloque `faq` de `services/page` no
|
|
90478
|
+
* tiene categorías (solo `items` planos) — se envuelve en una única
|
|
90479
|
+
* categoría sin label (`hideSingleCategoryLabel` default `true` la oculta).
|
|
90480
|
+
*/
|
|
90481
|
+
faqCategories() {
|
|
90482
|
+
return [
|
|
90483
|
+
{
|
|
90484
|
+
id: 'page-faq',
|
|
90485
|
+
label: '',
|
|
90486
|
+
items: this.faq.items.map((item, index) => ({
|
|
90487
|
+
id: `page-faq-${index}`,
|
|
90488
|
+
question: item.question,
|
|
90489
|
+
answer: item.answer,
|
|
90490
|
+
})),
|
|
90491
|
+
},
|
|
90492
|
+
];
|
|
90493
|
+
}
|
|
90494
|
+
onCtaClick() {
|
|
90495
|
+
this.ctaAction.emit(this.cta.intent);
|
|
90496
|
+
}
|
|
90497
|
+
onGalleryImageError(index) {
|
|
90498
|
+
const next = new Set(this.failedGalleryImages());
|
|
90499
|
+
next.add(index);
|
|
90500
|
+
this.failedGalleryImages.set(next);
|
|
90501
|
+
}
|
|
90502
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PageBlockComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
90503
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: PageBlockComponent, isStandalone: true, selector: "val-page-block", inputs: { props: "props" }, outputs: { ctaAction: "ctaAction" }, ngImport: i0, template: `
|
|
90504
|
+
@switch (props.type) {
|
|
90505
|
+
@case ('hero') {
|
|
90506
|
+
<section class="page-block page-block--hero" [class]="'align-' + (hero.align || 'center')">
|
|
90507
|
+
@if (hero.image && !heroImageFailed()) {
|
|
90508
|
+
<img
|
|
90509
|
+
class="page-block__hero-image"
|
|
90510
|
+
[src]="hero.image"
|
|
90511
|
+
[alt]="hero.title"
|
|
90512
|
+
loading="lazy"
|
|
90513
|
+
(error)="heroImageFailed.set(true)"
|
|
90514
|
+
/>
|
|
90515
|
+
}
|
|
90516
|
+
<div class="page-block__hero-copy">
|
|
90517
|
+
<val-display [props]="{ size: 'large', color: 'dark', content: hero.title }" />
|
|
90518
|
+
@if (hero.subtitle) {
|
|
90519
|
+
<val-text [props]="{ size: 'large', color: 'medium', bold: false, content: hero.subtitle }" />
|
|
90520
|
+
}
|
|
90521
|
+
</div>
|
|
90522
|
+
</section>
|
|
90523
|
+
}
|
|
90524
|
+
@case ('text') {
|
|
90525
|
+
<section class="page-block page-block--text">
|
|
90526
|
+
@if (text.heading) {
|
|
90527
|
+
<val-title [props]="{ size: 'large', color: 'dark', bold: false, content: text.heading }" />
|
|
90528
|
+
}
|
|
90529
|
+
@for (paragraph of textParagraphs(); track $index) {
|
|
90530
|
+
<val-text [props]="{ size: 'medium', color: 'dark', bold: false, content: paragraph }" />
|
|
90531
|
+
}
|
|
90532
|
+
</section>
|
|
90533
|
+
}
|
|
90534
|
+
@case ('gallery') {
|
|
90535
|
+
<section class="page-block page-block--gallery">
|
|
90536
|
+
<div class="page-block__gallery-grid">
|
|
90537
|
+
@for (image of gallery.images; track $index) {
|
|
90538
|
+
@if (!failedGalleryImages().has($index)) {
|
|
90539
|
+
<!-- Sin alt descriptivo: el backend no modela texto alternativo
|
|
90540
|
+
por imagen (services/page/blocks_validate.go, gallery.images
|
|
90541
|
+
es solo un arreglo de strings). Se marca decorativa a
|
|
90542
|
+
propósito, no un olvido de a11y. -->
|
|
90543
|
+
<img
|
|
90544
|
+
class="page-block__gallery-image"
|
|
90545
|
+
[src]="image"
|
|
90546
|
+
alt=""
|
|
90547
|
+
loading="lazy"
|
|
90548
|
+
(error)="onGalleryImageError($index)"
|
|
90549
|
+
/>
|
|
90550
|
+
}
|
|
90551
|
+
}
|
|
90552
|
+
</div>
|
|
90553
|
+
</section>
|
|
90554
|
+
}
|
|
90555
|
+
@case ('cta') {
|
|
90556
|
+
<section class="page-block page-block--cta">
|
|
90557
|
+
<val-button
|
|
90558
|
+
[props]="{
|
|
90559
|
+
text: cta.label,
|
|
90560
|
+
color: 'primary',
|
|
90561
|
+
fill: 'solid',
|
|
90562
|
+
shape: 'round',
|
|
90563
|
+
type: 'button',
|
|
90564
|
+
state: 'ENABLED',
|
|
90565
|
+
}"
|
|
90566
|
+
(onClick)="onCtaClick()"
|
|
90567
|
+
/>
|
|
90568
|
+
</section>
|
|
90569
|
+
}
|
|
90570
|
+
@case ('faq') {
|
|
90571
|
+
<section class="page-block page-block--faq">
|
|
90572
|
+
<val-faq [props]="{ categories: faqCategories(), searchable: false }" />
|
|
90573
|
+
</section>
|
|
90574
|
+
}
|
|
90575
|
+
}
|
|
90576
|
+
`, isInline: true, styles: [".page-block{display:block;width:100%}.page-block--hero{display:flex;flex-direction:column;gap:16px;text-align:center;align-items:center}.page-block--hero.align-left{text-align:left;align-items:flex-start}.page-block--hero.align-right{text-align:right;align-items:flex-end}.page-block__hero-image{width:100%;max-height:360px;object-fit:cover;border-radius:12px}.page-block__hero-copy{display:flex;flex-direction:column;gap:8px;max-width:640px}.page-block--text{display:flex;flex-direction:column;gap:8px}.page-block__gallery-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:8px}@media (min-width: 768px){.page-block__gallery-grid{grid-template-columns:repeat(3,1fr);gap:12px}}@media (min-width: 992px){.page-block__gallery-grid{grid-template-columns:repeat(4,1fr)}}.page-block__gallery-image{width:100%;aspect-ratio:1/1;object-fit:cover;border-radius:8px}.page-block--cta{display:flex;justify-content:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }, { kind: "component", type: TitleComponent, selector: "val-title", inputs: ["props"] }, { kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }, { kind: "component", type: ButtonComponent, selector: "val-button", inputs: ["preset", "props"], outputs: ["onClick"] }, { kind: "component", type: FaqComponent, selector: "val-faq", inputs: ["props"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
90577
|
+
}
|
|
90578
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PageBlockComponent, decorators: [{
|
|
90579
|
+
type: Component,
|
|
90580
|
+
args: [{ selector: 'val-page-block', standalone: true, imports: [CommonModule, DisplayComponent, TitleComponent, TextComponent, ButtonComponent, FaqComponent], template: `
|
|
90581
|
+
@switch (props.type) {
|
|
90582
|
+
@case ('hero') {
|
|
90583
|
+
<section class="page-block page-block--hero" [class]="'align-' + (hero.align || 'center')">
|
|
90584
|
+
@if (hero.image && !heroImageFailed()) {
|
|
90585
|
+
<img
|
|
90586
|
+
class="page-block__hero-image"
|
|
90587
|
+
[src]="hero.image"
|
|
90588
|
+
[alt]="hero.title"
|
|
90589
|
+
loading="lazy"
|
|
90590
|
+
(error)="heroImageFailed.set(true)"
|
|
90591
|
+
/>
|
|
90592
|
+
}
|
|
90593
|
+
<div class="page-block__hero-copy">
|
|
90594
|
+
<val-display [props]="{ size: 'large', color: 'dark', content: hero.title }" />
|
|
90595
|
+
@if (hero.subtitle) {
|
|
90596
|
+
<val-text [props]="{ size: 'large', color: 'medium', bold: false, content: hero.subtitle }" />
|
|
90597
|
+
}
|
|
90598
|
+
</div>
|
|
90599
|
+
</section>
|
|
90600
|
+
}
|
|
90601
|
+
@case ('text') {
|
|
90602
|
+
<section class="page-block page-block--text">
|
|
90603
|
+
@if (text.heading) {
|
|
90604
|
+
<val-title [props]="{ size: 'large', color: 'dark', bold: false, content: text.heading }" />
|
|
90605
|
+
}
|
|
90606
|
+
@for (paragraph of textParagraphs(); track $index) {
|
|
90607
|
+
<val-text [props]="{ size: 'medium', color: 'dark', bold: false, content: paragraph }" />
|
|
90608
|
+
}
|
|
90609
|
+
</section>
|
|
90610
|
+
}
|
|
90611
|
+
@case ('gallery') {
|
|
90612
|
+
<section class="page-block page-block--gallery">
|
|
90613
|
+
<div class="page-block__gallery-grid">
|
|
90614
|
+
@for (image of gallery.images; track $index) {
|
|
90615
|
+
@if (!failedGalleryImages().has($index)) {
|
|
90616
|
+
<!-- Sin alt descriptivo: el backend no modela texto alternativo
|
|
90617
|
+
por imagen (services/page/blocks_validate.go, gallery.images
|
|
90618
|
+
es solo un arreglo de strings). Se marca decorativa a
|
|
90619
|
+
propósito, no un olvido de a11y. -->
|
|
90620
|
+
<img
|
|
90621
|
+
class="page-block__gallery-image"
|
|
90622
|
+
[src]="image"
|
|
90623
|
+
alt=""
|
|
90624
|
+
loading="lazy"
|
|
90625
|
+
(error)="onGalleryImageError($index)"
|
|
90626
|
+
/>
|
|
90627
|
+
}
|
|
90628
|
+
}
|
|
90629
|
+
</div>
|
|
90630
|
+
</section>
|
|
90631
|
+
}
|
|
90632
|
+
@case ('cta') {
|
|
90633
|
+
<section class="page-block page-block--cta">
|
|
90634
|
+
<val-button
|
|
90635
|
+
[props]="{
|
|
90636
|
+
text: cta.label,
|
|
90637
|
+
color: 'primary',
|
|
90638
|
+
fill: 'solid',
|
|
90639
|
+
shape: 'round',
|
|
90640
|
+
type: 'button',
|
|
90641
|
+
state: 'ENABLED',
|
|
90642
|
+
}"
|
|
90643
|
+
(onClick)="onCtaClick()"
|
|
90644
|
+
/>
|
|
90645
|
+
</section>
|
|
90646
|
+
}
|
|
90647
|
+
@case ('faq') {
|
|
90648
|
+
<section class="page-block page-block--faq">
|
|
90649
|
+
<val-faq [props]="{ categories: faqCategories(), searchable: false }" />
|
|
90650
|
+
</section>
|
|
90651
|
+
}
|
|
90652
|
+
}
|
|
90653
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".page-block{display:block;width:100%}.page-block--hero{display:flex;flex-direction:column;gap:16px;text-align:center;align-items:center}.page-block--hero.align-left{text-align:left;align-items:flex-start}.page-block--hero.align-right{text-align:right;align-items:flex-end}.page-block__hero-image{width:100%;max-height:360px;object-fit:cover;border-radius:12px}.page-block__hero-copy{display:flex;flex-direction:column;gap:8px;max-width:640px}.page-block--text{display:flex;flex-direction:column;gap:8px}.page-block__gallery-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:8px}@media (min-width: 768px){.page-block__gallery-grid{grid-template-columns:repeat(3,1fr);gap:12px}}@media (min-width: 992px){.page-block__gallery-grid{grid-template-columns:repeat(4,1fr)}}.page-block__gallery-image{width:100%;aspect-ratio:1/1;object-fit:cover;border-radius:8px}.page-block--cta{display:flex;justify-content:center}\n"] }]
|
|
90654
|
+
}], propDecorators: { props: [{
|
|
90655
|
+
type: Input
|
|
90656
|
+
}], ctaAction: [{
|
|
90657
|
+
type: Output
|
|
90658
|
+
}] } });
|
|
90659
|
+
|
|
90660
|
+
/**
|
|
90661
|
+
* Tipos del organism `val-page-block` — constructor de páginas de plataforma
|
|
90662
|
+
* (ADR-077: `docs/adr/077-constructor-de-paginas-de-plataforma.md`, primera
|
|
90663
|
+
* aplicación real en Eklesee, Bloque 4:
|
|
90664
|
+
* `docs/eklesee/03-roadmap-y-abiertos.md`).
|
|
90665
|
+
*
|
|
90666
|
+
* Espejo 1:1 de `Block`/`Props` en `backend/go/services/page/types.go` +
|
|
90667
|
+
* `backend/go/services/page/blocks_validate.go` — la forma de cada `props`
|
|
90668
|
+
* sale de ahí, no se inventa acá. El catálogo de esta primera pasada son 5
|
|
90669
|
+
* tipos (`hero`, `text`, `gallery`, `cta`, `faq`); `countdown`/`sponsors`/
|
|
90670
|
+
* `progress` (catálogo completo del ADR) quedan fuera hasta que Bingo migre.
|
|
90671
|
+
*
|
|
90672
|
+
* El componente es i18n-agnóstico y agnóstico al dominio a propósito (mismo
|
|
90673
|
+
* criterio que `val-faq`/`val-article`): recibe `props` ya resueltos, sin
|
|
90674
|
+
* llamadas HTTP propias ni conocimiento de rutas de ninguna app. La app que
|
|
90675
|
+
* lo consume (Eklesee) resuelve `PageCTAIntent.action` a una ruta real —
|
|
90676
|
+
* este organism solo la emite via `(ctaAction)`.
|
|
90677
|
+
*/
|
|
90678
|
+
|
|
90679
|
+
const VIDEO_PLAYER_I18N = {
|
|
90680
|
+
es: {
|
|
90681
|
+
uploadingTitle: 'Subiendo video',
|
|
90682
|
+
uploadingBody: 'La subida está en curso. Vuelve en un momento.',
|
|
90683
|
+
processingTitle: 'Video en proceso',
|
|
90684
|
+
processingBody: 'Estamos preparando este video. Vuelve en unos minutos.',
|
|
90685
|
+
rejectedTitle: 'Este video no se pudo publicar',
|
|
90686
|
+
failedTitle: 'No pudimos procesar este video',
|
|
90687
|
+
unsupportedLink: 'Este enlace no se puede reproducir aquí.',
|
|
90688
|
+
},
|
|
90689
|
+
en: {
|
|
90690
|
+
uploadingTitle: 'Uploading video',
|
|
90691
|
+
uploadingBody: 'The upload is in progress. Check back in a moment.',
|
|
90692
|
+
processingTitle: 'Video processing',
|
|
90693
|
+
processingBody: "We're getting this video ready. Check back in a few minutes.",
|
|
90694
|
+
rejectedTitle: "This video couldn't be published",
|
|
90695
|
+
failedTitle: "We couldn't process this video",
|
|
90696
|
+
unsupportedLink: "This link can't be played here.",
|
|
90697
|
+
},
|
|
90698
|
+
};
|
|
90699
|
+
/**
|
|
90700
|
+
* `val-video-player` — reproductor de video de plataforma (ADR-087, "Fase 1 —
|
|
90701
|
+
* Reproducción"). Presentacional/dumb: recibe un `VideoPlayerAsset` YA
|
|
90702
|
+
* RESUELTO por el backend de turno y decide el render, sin fetch propio.
|
|
90703
|
+
*
|
|
90704
|
+
* - `source:'upload'` + `status:'ready'` → `<video>` nativo (`preload="none"`
|
|
90705
|
+
* + portada — ADR-087 §8, cero bytes de video hasta que alguien le da play).
|
|
90706
|
+
* - `source:'upload'` + `uploading|processing` → portada (si hay) + mensaje.
|
|
90707
|
+
* - `source:'upload'` + `failed|rejected` → mensaje legible con `failReason`
|
|
90708
|
+
* (texto ya resuelto por el backend, se muestra tal cual).
|
|
90709
|
+
* - `source:'link'` → iframe **siempre** contra un patrón fijo por proveedor
|
|
90710
|
+
* conocido (`youtube-nocookie.com/embed/{id}` · `player.vimeo.com/video/{id}`),
|
|
90711
|
+
* nunca un `src` armado con datos crudos del usuario. Proveedor no
|
|
90712
|
+
* reconocido → mensaje, nunca un iframe "por si acaso".
|
|
90713
|
+
*
|
|
90714
|
+
* @example
|
|
90715
|
+
* <val-video-player [video]="doc.video" />
|
|
90716
|
+
*/
|
|
90717
|
+
class VideoPlayerComponent {
|
|
90718
|
+
constructor() {
|
|
90719
|
+
this.i18n = inject(I18nService);
|
|
90720
|
+
this.sanitizer = inject(DomSanitizer);
|
|
90721
|
+
/** El `VideoAsset` ya resuelto por el backend. `null`/`undefined` → no renderiza nada. */
|
|
90722
|
+
this.video = input(null);
|
|
90723
|
+
this.asset = computed(() => this.video() ?? null);
|
|
90724
|
+
this.thumbFailed = signal(false);
|
|
90725
|
+
/**
|
|
90726
|
+
* Arma el embed SIEMPRE contra un patrón fijo por proveedor conocido — el
|
|
90727
|
+
* `externalId` es el único dato del backend que entra en el `src`. Un
|
|
90728
|
+
* proveedor no reconocido devuelve `null` (el template cae al mensaje, no a
|
|
90729
|
+
* un iframe "por si acaso"). `bypassSecurityTrustResourceUrl` es seguro acá
|
|
90730
|
+
* porque el string completo lo arma este componente, nunca el usuario.
|
|
90731
|
+
*/
|
|
90732
|
+
this.embedUrl = computed(() => {
|
|
90733
|
+
const v = this.asset();
|
|
90734
|
+
if (!v || v.source !== 'link' || !v.externalId)
|
|
90735
|
+
return null;
|
|
90736
|
+
const raw = this.buildEmbedUrl(v.provider, v.externalId);
|
|
90737
|
+
return raw ? this.sanitizer.bypassSecurityTrustResourceUrl(raw) : null;
|
|
90738
|
+
});
|
|
90739
|
+
if (!this.i18n.hasNamespace('VideoPlayer')) {
|
|
90740
|
+
this.i18n.registerContent('VideoPlayer', VIDEO_PLAYER_I18N);
|
|
90741
|
+
}
|
|
90742
|
+
}
|
|
90743
|
+
buildEmbedUrl(provider, externalId) {
|
|
90744
|
+
switch (provider) {
|
|
90745
|
+
case 'youtube':
|
|
90746
|
+
return `https://www.youtube-nocookie.com/embed/${encodeURIComponent(externalId)}`;
|
|
90747
|
+
case 'vimeo':
|
|
90748
|
+
return `https://player.vimeo.com/video/${encodeURIComponent(externalId)}`;
|
|
90749
|
+
default:
|
|
90750
|
+
return null;
|
|
90751
|
+
}
|
|
90752
|
+
}
|
|
90753
|
+
t(key) {
|
|
90754
|
+
return this.i18n.t(key, 'VideoPlayer');
|
|
90755
|
+
}
|
|
90756
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: VideoPlayerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
90757
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: VideoPlayerComponent, isStandalone: true, selector: "val-video-player", inputs: { video: { classPropertyName: "video", publicName: "video", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
90758
|
+
@if (asset(); as v) {
|
|
90759
|
+
@if (v.source === 'upload') {
|
|
90760
|
+
@if (v.status === 'ready' && v.url) {
|
|
90761
|
+
<video
|
|
90762
|
+
class="val-video-player__video"
|
|
90763
|
+
[src]="v.url"
|
|
90764
|
+
[poster]="v.thumbnail || undefined"
|
|
90765
|
+
controls
|
|
90766
|
+
preload="none"
|
|
90767
|
+
playsinline
|
|
90768
|
+
></video>
|
|
90769
|
+
} @else if (v.status === 'rejected' || v.status === 'failed') {
|
|
90770
|
+
<div class="val-video-player__state val-video-player__state--error">
|
|
90771
|
+
@if (v.thumbnail && !thumbFailed()) {
|
|
90772
|
+
<img
|
|
90773
|
+
class="val-video-player__poster"
|
|
90774
|
+
[src]="v.thumbnail"
|
|
90775
|
+
alt=""
|
|
90776
|
+
loading="lazy"
|
|
90777
|
+
(error)="thumbFailed.set(true)"
|
|
90778
|
+
/>
|
|
90779
|
+
}
|
|
90780
|
+
<div class="val-video-player__overlay">
|
|
90781
|
+
<strong>{{ v.status === 'rejected' ? t('rejectedTitle') : t('failedTitle') }}</strong>
|
|
90782
|
+
@if (v.failReason) {
|
|
90783
|
+
<span>{{ v.failReason }}</span>
|
|
90784
|
+
}
|
|
90785
|
+
</div>
|
|
90786
|
+
</div>
|
|
90787
|
+
} @else {
|
|
90788
|
+
<!-- uploading | processing -->
|
|
90789
|
+
<div class="val-video-player__state" aria-live="polite">
|
|
90790
|
+
@if (v.thumbnail && !thumbFailed()) {
|
|
90791
|
+
<img
|
|
90792
|
+
class="val-video-player__poster"
|
|
90793
|
+
[src]="v.thumbnail"
|
|
90794
|
+
alt=""
|
|
90795
|
+
loading="lazy"
|
|
90796
|
+
(error)="thumbFailed.set(true)"
|
|
90797
|
+
/>
|
|
90798
|
+
}
|
|
90799
|
+
<div class="val-video-player__overlay">
|
|
90800
|
+
<span class="val-video-player__spinner" aria-hidden="true"></span>
|
|
90801
|
+
<strong>{{ v.status === 'uploading' ? t('uploadingTitle') : t('processingTitle') }}</strong>
|
|
90802
|
+
<span>{{ v.status === 'uploading' ? t('uploadingBody') : t('processingBody') }}</span>
|
|
90803
|
+
</div>
|
|
90804
|
+
</div>
|
|
90805
|
+
}
|
|
90806
|
+
} @else {
|
|
90807
|
+
<!-- source: link -->
|
|
90808
|
+
@if (embedUrl(); as src) {
|
|
90809
|
+
<div class="val-video-player__embed-wrap">
|
|
90810
|
+
<iframe
|
|
90811
|
+
class="val-video-player__embed"
|
|
90812
|
+
[src]="src"
|
|
90813
|
+
title="video"
|
|
90814
|
+
frameborder="0"
|
|
90815
|
+
referrerpolicy="strict-origin-when-cross-origin"
|
|
90816
|
+
allow="accelerometer; encrypted-media; gyroscope; picture-in-picture"
|
|
90817
|
+
allowfullscreen
|
|
90818
|
+
loading="lazy"
|
|
90819
|
+
></iframe>
|
|
90820
|
+
</div>
|
|
90821
|
+
} @else {
|
|
90822
|
+
<div class="val-video-player__state">
|
|
90823
|
+
<div class="val-video-player__overlay">
|
|
90824
|
+
<span>{{ t('unsupportedLink') }}</span>
|
|
90825
|
+
</div>
|
|
90826
|
+
</div>
|
|
90827
|
+
}
|
|
90828
|
+
}
|
|
90829
|
+
}
|
|
90830
|
+
`, isInline: true, styles: [":host{display:block}.val-video-player__video{display:block;width:100%;max-height:70vh;border-radius:12px;background:#000}.val-video-player__embed-wrap{position:relative;width:100%;padding-top:56.25%;border-radius:12px;overflow:hidden;background:#000}.val-video-player__embed{position:absolute;inset:0;width:100%;height:100%;border:0}.val-video-player__state{position:relative;width:100%;aspect-ratio:16 / 9;border-radius:12px;overflow:hidden;background:var(--ion-color-light, rgba(0, 0, 0, .06));display:flex;align-items:flex-end}.val-video-player__poster{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:.55}.val-video-player__overlay{position:relative;z-index:1;display:flex;flex-direction:column;gap:4px;width:100%;padding:14px 16px;color:var(--ion-text-color, #000);background:linear-gradient(to top,rgba(0,0,0,.08),transparent)}.val-video-player__state--error .val-video-player__overlay{color:var(--ion-color-danger, #eb445a)}.val-video-player__overlay strong{font-size:.9375rem}.val-video-player__overlay span{font-size:.8125rem;opacity:.85}.val-video-player__spinner{width:18px;height:18px;border-radius:50%;border:2px solid rgba(127,127,127,.35);border-top-color:var(--ion-color-dark, #313131);animation:val-video-player-spin .8s linear infinite}@keyframes val-video-player-spin{to{transform:rotate(360deg)}}\n"] }); }
|
|
90831
|
+
}
|
|
90832
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: VideoPlayerComponent, decorators: [{
|
|
90833
|
+
type: Component,
|
|
90834
|
+
args: [{ selector: 'val-video-player', standalone: true, imports: [], template: `
|
|
90835
|
+
@if (asset(); as v) {
|
|
90836
|
+
@if (v.source === 'upload') {
|
|
90837
|
+
@if (v.status === 'ready' && v.url) {
|
|
90838
|
+
<video
|
|
90839
|
+
class="val-video-player__video"
|
|
90840
|
+
[src]="v.url"
|
|
90841
|
+
[poster]="v.thumbnail || undefined"
|
|
90842
|
+
controls
|
|
90843
|
+
preload="none"
|
|
90844
|
+
playsinline
|
|
90845
|
+
></video>
|
|
90846
|
+
} @else if (v.status === 'rejected' || v.status === 'failed') {
|
|
90847
|
+
<div class="val-video-player__state val-video-player__state--error">
|
|
90848
|
+
@if (v.thumbnail && !thumbFailed()) {
|
|
90849
|
+
<img
|
|
90850
|
+
class="val-video-player__poster"
|
|
90851
|
+
[src]="v.thumbnail"
|
|
90852
|
+
alt=""
|
|
90853
|
+
loading="lazy"
|
|
90854
|
+
(error)="thumbFailed.set(true)"
|
|
90855
|
+
/>
|
|
90856
|
+
}
|
|
90857
|
+
<div class="val-video-player__overlay">
|
|
90858
|
+
<strong>{{ v.status === 'rejected' ? t('rejectedTitle') : t('failedTitle') }}</strong>
|
|
90859
|
+
@if (v.failReason) {
|
|
90860
|
+
<span>{{ v.failReason }}</span>
|
|
90861
|
+
}
|
|
90862
|
+
</div>
|
|
90863
|
+
</div>
|
|
90864
|
+
} @else {
|
|
90865
|
+
<!-- uploading | processing -->
|
|
90866
|
+
<div class="val-video-player__state" aria-live="polite">
|
|
90867
|
+
@if (v.thumbnail && !thumbFailed()) {
|
|
90868
|
+
<img
|
|
90869
|
+
class="val-video-player__poster"
|
|
90870
|
+
[src]="v.thumbnail"
|
|
90871
|
+
alt=""
|
|
90872
|
+
loading="lazy"
|
|
90873
|
+
(error)="thumbFailed.set(true)"
|
|
90874
|
+
/>
|
|
90875
|
+
}
|
|
90876
|
+
<div class="val-video-player__overlay">
|
|
90877
|
+
<span class="val-video-player__spinner" aria-hidden="true"></span>
|
|
90878
|
+
<strong>{{ v.status === 'uploading' ? t('uploadingTitle') : t('processingTitle') }}</strong>
|
|
90879
|
+
<span>{{ v.status === 'uploading' ? t('uploadingBody') : t('processingBody') }}</span>
|
|
90880
|
+
</div>
|
|
90881
|
+
</div>
|
|
90882
|
+
}
|
|
90883
|
+
} @else {
|
|
90884
|
+
<!-- source: link -->
|
|
90885
|
+
@if (embedUrl(); as src) {
|
|
90886
|
+
<div class="val-video-player__embed-wrap">
|
|
90887
|
+
<iframe
|
|
90888
|
+
class="val-video-player__embed"
|
|
90889
|
+
[src]="src"
|
|
90890
|
+
title="video"
|
|
90891
|
+
frameborder="0"
|
|
90892
|
+
referrerpolicy="strict-origin-when-cross-origin"
|
|
90893
|
+
allow="accelerometer; encrypted-media; gyroscope; picture-in-picture"
|
|
90894
|
+
allowfullscreen
|
|
90895
|
+
loading="lazy"
|
|
90896
|
+
></iframe>
|
|
90897
|
+
</div>
|
|
90898
|
+
} @else {
|
|
90899
|
+
<div class="val-video-player__state">
|
|
90900
|
+
<div class="val-video-player__overlay">
|
|
90901
|
+
<span>{{ t('unsupportedLink') }}</span>
|
|
90902
|
+
</div>
|
|
90903
|
+
</div>
|
|
90904
|
+
}
|
|
90905
|
+
}
|
|
90906
|
+
}
|
|
90907
|
+
`, styles: [":host{display:block}.val-video-player__video{display:block;width:100%;max-height:70vh;border-radius:12px;background:#000}.val-video-player__embed-wrap{position:relative;width:100%;padding-top:56.25%;border-radius:12px;overflow:hidden;background:#000}.val-video-player__embed{position:absolute;inset:0;width:100%;height:100%;border:0}.val-video-player__state{position:relative;width:100%;aspect-ratio:16 / 9;border-radius:12px;overflow:hidden;background:var(--ion-color-light, rgba(0, 0, 0, .06));display:flex;align-items:flex-end}.val-video-player__poster{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:.55}.val-video-player__overlay{position:relative;z-index:1;display:flex;flex-direction:column;gap:4px;width:100%;padding:14px 16px;color:var(--ion-text-color, #000);background:linear-gradient(to top,rgba(0,0,0,.08),transparent)}.val-video-player__state--error .val-video-player__overlay{color:var(--ion-color-danger, #eb445a)}.val-video-player__overlay strong{font-size:.9375rem}.val-video-player__overlay span{font-size:.8125rem;opacity:.85}.val-video-player__spinner{width:18px;height:18px;border-radius:50%;border:2px solid rgba(127,127,127,.35);border-top-color:var(--ion-color-dark, #313131);animation:val-video-player-spin .8s linear infinite}@keyframes val-video-player-spin{to{transform:rotate(360deg)}}\n"] }]
|
|
90908
|
+
}], ctorParameters: () => [] });
|
|
90909
|
+
|
|
90910
|
+
/**
|
|
90911
|
+
* Tipos de `val-video-player` (ADR-087 — video como servicio de plataforma).
|
|
90912
|
+
*
|
|
90913
|
+
* Espejo agnóstico al dominio de `content.VideoAsset` (backend Go,
|
|
90914
|
+
* `backend/go/services/content/video.go`) — mismos nombres de campo en
|
|
90915
|
+
* camelCase. Cualquier app pasa acá el `VideoAsset` que le devuelve SU propio
|
|
90916
|
+
* backend (sermón en Eklesee, receta en Okhelia, animal en Chesed, artículo de
|
|
90917
|
+
* ayuda) con un mapeo trivial; el componente no conoce ni le importa de qué
|
|
90918
|
+
* dominio viene.
|
|
90919
|
+
*/
|
|
90920
|
+
|
|
89864
90921
|
/*
|
|
89865
90922
|
* Public API Surface of valtech-components
|
|
89866
90923
|
*/
|
|
@@ -89870,5 +90927,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
89870
90927
|
* Generated bundle index. Do not edit.
|
|
89871
90928
|
*/
|
|
89872
90929
|
|
|
89873
|
-
export { ACCESS_REQUEST_TYPE, ACCESS_REQUEST_VIEW_I18N, ACTION_CARD_DEFAULTS, AD_SIZE_MAP, API_TABLE_COLUMN_LABELS, APP_VERSION_PLATFORM_PLUGIN, APP_VERSION_REMOTE_PLUGIN, ARTICLE_CARD_DEFAULTS, ARTICLE_SPACING, ARTICLE_STRIP_DEFAULTS, AUTH_CTA_DEFAULTS, AVATAR_UPLOAD_DEFAULTS, AboutViewComponent, AccessControlService, AccessRequestViewComponent, AccordionComponent, AccountViewComponent, ActionCardComponent, ActionHeaderComponent, ActionType, AdSlotComponent, AdsLoaderService, AdsService, AlertBoxComponent, AnalyticsErrorHandler, AnalyticsRouterTracker, AnalyticsService, AnimalCardComponent, AnimatedTerminalComponent, ApiKeyCreateModalComponent, ApiKeyService, ApiKeysModalComponent, ApiKeysViewComponent, AppConfigService, AppVersionService, ArticleBuilder, ArticleCardComponent, ArticleComponent, ArticleStripComponent, AttachmentUploaderComponent, AuthBackgroundComponent, AuthCtaComponent, AuthService, AuthStateService, AuthStorageService, AuthSyncService, AvatarComponent, AvatarUploadComponent, BOTTOM_NAV_DEFAULTS, BackButtonComponent, BannerComponent, BlogPostBuilder, BottomNavComponent, BoxComponent, BreadcrumbComponent, BubbleBlitzGameComponent, ButtonComponent, ButtonGroupComponent, CALLOUT_LABELS, CHEV_KEYS, CIRCLE_KEYS, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CORNER_KEYS, CTA_CARD_DEFAULTS, CURRENCY_INFO, CanAccessDirective, CardComponent, CardSection, CardType, CardsCarouselComponent, ChangeEmailModalComponent, ChangePasswordModalComponent, ChatComposerComponent, ChatInputComponent, ChatWindowComponent, CheckInputComponent, CheckboxRadioInputComponent, ChipGroupComponent, ChipSelectComponent, ClientTelemetryService, CodeDisplayComponent, CodeValidatorComponent, CollectionsService, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CommsPreferencesService, CommsPreferencesSettingsComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ConfirmationDialogV2Component, ContainerComponent, ContentLoaderComponent, ContentReactionComponent, ContentReactionModalComponent, ContentService, ContentTransformer, ConversationListItemComponent, ConversationService, CookieBannerComponent, CookieSettingsComponent, CountdownComponent, CreateOrgModalComponent, CtaCardComponent, CurrencyInputComponent, DEFAULT_ADS_CONFIG, DEFAULT_APP_CONFIG_SERVICE_CONFIG, DEFAULT_APP_VERSION_SERVICE_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_BACK_HEADER, DEFAULT_BUTTON_PRESETS, DEFAULT_CANCEL_BUTTON, DEFAULT_CANONICAL_FIELD_ALIASES, 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_LOGIN_LOGO, DEFAULT_MODAL_CANCEL_BUTTON, DEFAULT_MODAL_CONFIRM_BUTTON, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLATFORMS, DEFAULT_POST_UPDATE_GRACE_MS, DEFAULT_PRESETS, DEFAULT_REFRESHER_METADATA, DEFAULT_SKELETON_CONFIG, DEFAULT_SPLASH_SCREEN_CONFIG, DangerSectionComponent, DataTableComponent, DatasetPaginationService, DateInputComponent, DatePickerComponent, DateRangeInputComponent, DebugConsoleComponent, DeleteAccountModalComponent, DetailSkeletonComponent, DeviceService, DisplayComponent, DividerComponent, DocsApiTableComponent, DocsBreadcrumbComponent, DocsBuilder, DocsCalloutComponent, DocsCodeExampleComponent, DocsLayoutComponent, DocsNavLinksComponent, DocsNavigationService, DocsPageComponent, DocsSearchComponent, DocsSectionComponent, DocsShellComponent, DocsSidebarComponent, DocsTocComponent, DonationService, DownloadService, EXPECTED_NOT_FOUND, EditOrgModalComponent, EmptyStateComponent, EntityCardComponent, EntityFeedService, EntradaSerializada, ExpandableTextComponent, ExternalBrowserService, FEATURES_LIST_DEFAULTS, FUN_MODAL_DEFAULTS, FabComponent, FaqComponent, FeatureControlService, FeatureGuardDirective, FeaturesListComponent, FeedbackFormComponent, FeedbackService, FieldListComponent, FieldOptionsEditorComponent, FileInputComponent, FirebaseService, FirestoreCollectionFactory, FirestoreService, FolderTabsComponent, FontSizeOption, FontSizeSelectorComponent, FontSizeService, FooterComponent, FooterLinksComponent, FormComponent, FormFieldComponent, FormSchemaBuilderService, FormSkeletonComponent, FunHeaderComponent, FunModalComponent, GAME_AVATAR_CATALOG_SIZE_PER_STYLE, GameAvatarComponent, GameProfileService, GlassComponent, GlowCardComponent, GlowComponent, GridSkeletonComponent, GroupMembersComponent, GroupPickerComponent, GroupsService, HANDOFF_ROUTE_PARAM, HANDOFF_TOKEN_PARAM, HandleService, HandoffService, HapticsService, HasPermissionDirective, HeaderActionsService, HeaderComponent, HintComponent, HorizontalScrollComponent, HrefComponent, HtmlViewerModalComponent, I18nService, IMAGE_DEFAULTS, INITIAL_AUTH_STATE, INITIAL_MFA_STATE, INVITATION_CARD_DEFAULTS, IONIC_COLORS$5 as IONIC_COLORS, Icon, IconComponent, IconService, ImageComponent, ImageCropComponent, ImageService, InAppBrowserService, InfiniteListComponent, InfoComponent, InputI18nHelper, InputType, InvitationCardComponent, InviteMemberModalComponent, ItemListComponent, KNOWN_ROUTES, LANG_STORAGE_KEY$1 as LANG_STORAGE_KEY, LEGAL_CONTENT_CONFIG, LOGGED_IN_HINT_COOKIE, LOGIN_DEFAULTS, LandingSplitComponent, LandingStepsComponent, LanguageSelectorComponent, LanguageSelectorV2Component, LayeredCardComponent, LegalContentService, LegalLinkService, LightRippleDirective, LinkComponent, LinkProcessorService, LinkedProvidersComponent, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LiveReadFallbackService, LoadMoreComponent, LoadingDirective, LocalStorageService, LocaleService, LoginAttemptModalComponent, LoginComponent, MEDIA_OBJECT_DEFAULTS, MEMBER_CARD_DEFAULTS, METADATA_LIST_DEFAULTS, META_SCHEMA_VERSION, METRIC_CARD_DEFAULTS, MINI_GAMES_I18N, MINI_GAME_PLAYER_AVATARS, MINI_GAME_PLAYER_COLORS, MODAL_SIZES, MOTIF_KEYS, MOTION, MaintenancePageComponent, MarkdownArticleParserService, MediaObjectComponent, MediaViewerModalComponent, MemberCardComponent, MemberDetailModalComponent, MemberImportModalComponent, MemoryGameComponent, MenuComponent, MessageBubbleComponent, MessagingService, MetaService, MetadataListComponent, MeteringService, MetricCardComponent, MfaModalComponent, MiniGameCalloutComponent, MiniGamePlayerProfileService, MiniGameScorePopComponent, MiniGamesMenuComponent, ModalLayoutComponent, ModalService, ModalShellComponent, MultiSelectSearchComponent, NUM_KEYS, NavigationService, NetworkBannerComponent, NetworkStatusService, NewsBuilder, NoContentComponent, NotesBoxComponent, NoticeComponent, NotificationActionService, NotificationPreferencesViewComponent, NotificationsService, NotificationsViewComponent, NumberFromToComponent, NumberPickerComponent, NumberStepperComponent, OAUTH_PROVIDERS_INFO, OAuthCallbackComponent, OAuthService, OperationReferenceComponent, OptionCardsComponent, OptionSheetComponent, OptionSheetService, OrgInfoSheetComponent, OrgService, OrgSwitchService, OrganizationViewComponent, PATTERN_MOTIFS, PATTERN_PALETTES, PATTERN_STYLE_CONFIGS, PERSONA_CONFIG, PLATFORM_CONFIGS, POST_UPDATE_TS_KEY, PageContentComponent, PageLinksComponent, PageRefreshService, PageTemplateComponent, PageWavesComponent, PageWrapperComponent, PaginationComponent, PaginationService, PasswordInputComponent, PatternComponent, PdfService, PermissionCatalogService, PermissionSelectorComponent, PermissionsModalComponent, PermissionsViewComponent, PersonaService, PhoneDisplayComponent, PhoneFormatService, PhoneInputComponent, PickerV2Component, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PreferencesService, PreferencesViewComponent, PresetService, PriceTagComponent, PricingTableComponent, ProcessLinksPipe, ProfileCardComponent, ProfileContentComponent, ProfileModalComponent, ProfileSkeletonComponent, ProfileViewComponent, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrBrandValidationError, QrCodeComponent, QrGeneratorService, QrScannerComponent, QueryBuilder, QuoteBoxComponent, REQUEST_STATUSES, RadioInputComponent, RangeInputComponent, RatingComponent, RbacService, ReactionBarComponent, ReactionsService, RefresherComponent, RequestFirestoreService, RequestFormBuilderService, RequestFormComponent, RequestModalComponent, RequestReviewPanelComponent, RequestService, RetroAudioService, RightsFooterComponent, RoleManagerComponent, 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, SectionHeaderComponent, SecurityViewComponent, SegmentControlComponent, SelectSearchComponent, SelectSearchPickerModalComponent, SessionListModalComponent, SessionService, SessionTransitionOverlayComponent, SettingsHubComponent, ShareButtonsComponent, ShareProfileModalComponent, SimonGameComponent, SimpleComponent, SkeletonComponent, SkeletonLayoutComponent, SkeletonService, SplashComponent, SplashScreenService, StatsBarComponent, StatsCardComponent, StepperComponent, StorageService, SupportTicketCtaComponent, SwipeCarouselComponent, SwitchOrgModalComponent, TRI_KEYS, TabbedContentComponent, TableSkeletonComponent, TabsComponent, Terminal404Component, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeSelectorComponent, ThemeService, ThreadPanelComponent, TicketCardComponent, TicketCardImageService, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, TokenService, ToolbarActionType, ToolbarComponent, TransferOwnershipModalComponent, TranslatePipe, TypedCollection, TypingIndicatorComponent, UPDATE_BANNER_DEFAULT_CONTENT, UPDATE_BANNER_I18N_NAMESPACE, UpdateBannerComponent, UsageMetersComponent, UsageService, UserAvatarComponent, UsernameInputComponent, VALTECH_ACCESS_FEATURES, VALTECH_ADS_CONFIG, VALTECH_APP_CONFIG, VALTECH_APP_VERSION, VALTECH_AUTH_CONFIG, VALTECH_CHAT_CONFIG, VALTECH_COLLECTIONS_CONFIG, VALTECH_COMMS_PREFERENCES_CONFIG, VALTECH_COMPANY_LINKS, VALTECH_CONTENT_CONFIG, VALTECH_COPYRIGHT_TEMPLATE, VALTECH_DEBUG_CONSOLE, VALTECH_DEFAULT_CONTENT, VALTECH_DIAGRAMS, VALTECH_DONATION_CONFIG, VALTECH_FEEDBACK_CONFIG, VALTECH_FIREBASE_CONFIG, VALTECH_FOOTER_I18N, VALTECH_FOOTER_LOGO, VALTECH_LANGUAGE_SELECTOR, VALTECH_LEGAL_CONFIG, VALTECH_LEGAL_ENTITY, VALTECH_MENU_I18N, VALTECH_NETWORK_ERROR_KEY, VALTECH_REACTIONS_CONFIG, VALTECH_SETTINGS_MENU_LINKS, VALTECH_SITE_PATHS, VALTECH_SOCIAL_LINKS, VALTECH_SPLASH_SCREEN, VALTECH_WEB_BASE_URLS, VALTECH_WHATSAPP_CONFIG, VAL_REGISTERED_ICONS, VERSION, ValCommentThreadComponent, ValQuotaWarningComponent, ValtechErrorService, VerifyViewComponent, WhatsappFabComponent, WhatsappService, WizardComponent, WizardFooterComponent, WorkflowService, accessGuard, accessGuardFromRoute, applyDefaultValueToControl, authGuard, authInterceptor, authPasswordValidator, beautifyLegalArticle, blogPost, buildCompanyFooterProps, buildFooterLinks, buildLegalLinkResolver, buildPath, buildPlatformMenu, buildSettingsCards, buildSideNavItemsFromBottomNav, button, canSubmitRequestType, classifyChip, collections, connectPageRefresh, createErrorStateProps, createFirebaseConfig, createGameAvatarCatalog, createGameAvatarProps, createGlowCardProps, createInitialDatasetState, createInitialPaginationState, createNumberFromToField, createPageState, createPermissionLabeler, createRefreshableStream, createTitleProps, datasetPageFromLegacyCursor, defaultQrBrand, docs, errorLoggingInterceptor, evaluateValtechAccess, extractPathParams, firmaDeSesionDeCustomToken, formatClockTime, formatDateSeparator, formatRelativeTime, gameAvatarCatalogEntryToMetadata, gameAvatarDataUri, generatePatternTiles, generateRandomTile, getAppInfo, getAppVersion, getCollectionPath, getDocumentId, getTimeOfDayKey, goToTop, groupPermissionsByScope, guestGuard, hasEmulators, iconButton, interpretError, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isIonicColor, isKnownRoute, isValidPath, joinPath, maxLength, mulberry32, news, parseMarkdownArticle, permissionGuard, permissionGuardFromRoute, provideLegalContent, providePersona, provideSplashScreen, provideValtechAboutRoutes, provideValtechAccessFeatures, provideValtechAccountRoutes, provideValtechAds, provideValtechApiKeysRoutes, provideValtechAppConfig, provideValtechAppVersion, provideValtechAppVersionHttp, provideValtechAuth, provideValtechAuthInterceptor, provideValtechChat, provideValtechCollections, provideValtechCommsPreferences, provideValtechContent, provideValtechDebugConsole, provideValtechDiagrams, provideValtechDonations, provideValtechErrorHandling, provideValtechFeedback, provideValtechFirebase, provideValtechI18n, provideValtechLegal, provideValtechNotificationClickActions, provideValtechNotificationPreferencesRoutes, provideValtechNotificationsRoutes, provideValtechOrganizationRoutes, provideValtechPermissionsRoutes, provideValtechPreferencesRoutes, provideValtechPresets, provideValtechProfileRoutes, provideValtechReactions, provideValtechSecurityRoutes, provideValtechSettingsRoutes, provideValtechSite, provideValtechSkeleton, provideValtechWhatsapp, qrContrastRatio, qrErrorCorrectionFor, query, rbacGuard, renderGameAvatarSvg, renderPatternSvgInner, replaceSpecialChars, requestSubmitMode, resolveColor, resolveCopyrightTemplate, resolveInputDefaultValue, resolveIonicColor, resolveWebBaseUrl, roleGuard, roleOf, selectableRequestTypes, storagePaths, suggestEmailFix, superAdminGuard, supportedGameAvatarStyles, toArticle, validateQrBrand, validateRoutes };
|
|
90930
|
+
export { ACCESS_REQUEST_TYPE, ACCESS_REQUEST_VIEW_I18N, ACTION_CARD_DEFAULTS, AD_SIZE_MAP, API_TABLE_COLUMN_LABELS, APP_VERSION_PLATFORM_PLUGIN, APP_VERSION_REMOTE_PLUGIN, ARTICLE_CARD_DEFAULTS, ARTICLE_SPACING, ARTICLE_STRIP_DEFAULTS, AUTH_CTA_DEFAULTS, AVATAR_UPLOAD_DEFAULTS, AboutViewComponent, AccessControlService, AccessRequestViewComponent, AccordionComponent, AccountViewComponent, ActionCardComponent, ActionHeaderComponent, ActionType, AdSlotComponent, AdsLoaderService, AdsService, AlertBoxComponent, AnalyticsErrorHandler, AnalyticsRouterTracker, AnalyticsService, AnimalCardComponent, AnimatedTerminalComponent, ApiKeyCreateModalComponent, ApiKeyService, ApiKeysModalComponent, ApiKeysViewComponent, AppConfigService, AppVersionService, ArticleBuilder, ArticleCardComponent, ArticleComponent, ArticleStripComponent, AttachmentUploaderComponent, AuthBackgroundComponent, AuthCtaComponent, AuthService, AuthStateService, AuthStorageService, AuthSyncService, AvatarComponent, AvatarUploadComponent, BOTTOM_NAV_DEFAULTS, BackButtonComponent, BannerComponent, BlogPostBuilder, BottomNavComponent, BoxComponent, BreadcrumbComponent, BubbleBlitzGameComponent, ButtonComponent, ButtonGroupComponent, CALLOUT_LABELS, CHEV_KEYS, CIRCLE_KEYS, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CORNER_KEYS, CTA_CARD_DEFAULTS, CURRENCY_INFO, CanAccessDirective, CardComponent, CardSection, CardType, CardsCarouselComponent, ChangeEmailModalComponent, ChangePasswordModalComponent, ChatComposerComponent, ChatInputComponent, ChatWindowComponent, CheckInputComponent, CheckboxRadioInputComponent, ChipGroupComponent, ChipSelectComponent, ClientTelemetryService, CodeDisplayComponent, CodeValidatorComponent, CollectionsService, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CommsPreferencesService, CommsPreferencesSettingsComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ConfirmationDialogV2Component, ContainerComponent, ContentLoaderComponent, ContentReactionComponent, ContentReactionModalComponent, ContentService, ContentTransformer, ConversationListItemComponent, ConversationService, CookieBannerComponent, CookieSettingsComponent, CountdownComponent, CreateOrgModalComponent, CtaCardComponent, CurrencyInputComponent, DEFAULT_ADS_CONFIG, DEFAULT_APP_CONFIG_SERVICE_CONFIG, DEFAULT_APP_VERSION_SERVICE_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_BACK_HEADER, DEFAULT_BUTTON_PRESETS, DEFAULT_CANCEL_BUTTON, DEFAULT_CANONICAL_FIELD_ALIASES, 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_LOGIN_LOGO, DEFAULT_MODAL_CANCEL_BUTTON, DEFAULT_MODAL_CONFIRM_BUTTON, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLATFORMS, DEFAULT_POST_UPDATE_GRACE_MS, DEFAULT_PRESETS, DEFAULT_REFRESHER_METADATA, DEFAULT_SKELETON_CONFIG, DEFAULT_SPLASH_SCREEN_CONFIG, DangerSectionComponent, DataTableComponent, DatasetPaginationService, DateInputComponent, DatePickerComponent, DateRangeInputComponent, DebugConsoleComponent, DeleteAccountModalComponent, DetailSkeletonComponent, DeviceService, DisplayComponent, DividerComponent, DocsApiTableComponent, DocsBreadcrumbComponent, DocsBuilder, DocsCalloutComponent, DocsCodeExampleComponent, DocsLayoutComponent, DocsNavLinksComponent, DocsNavigationService, DocsPageComponent, DocsSearchComponent, DocsSectionComponent, DocsShellComponent, DocsSidebarComponent, DocsTocComponent, DonationService, DownloadService, EXPECTED_NOT_FOUND, EditOrgModalComponent, EmptyStateComponent, EntityCardComponent, EntityFeedService, EntradaSerializada, ExpandableTextComponent, ExternalBrowserService, FEATURES_LIST_DEFAULTS, FUN_MODAL_DEFAULTS, FabComponent, FaqComponent, FeatureControlService, FeatureGuardDirective, FeaturesListComponent, FeedbackFormComponent, FeedbackService, FieldListComponent, FieldOptionsEditorComponent, FileInputComponent, FirebaseService, FirestoreCollectionFactory, FirestoreService, FolderTabsComponent, FontSizeOption, FontSizeSelectorComponent, FontSizeService, FooterComponent, FooterLinksComponent, FormComponent, FormFieldComponent, FormSchemaBuilderService, FormSkeletonComponent, FunHeaderComponent, FunModalComponent, GAME_AVATAR_CATALOG_SIZE_PER_STYLE, GameAvatarComponent, GameProfileService, GlassComponent, GlowCardComponent, GlowComponent, GridSkeletonComponent, GroupMembersComponent, GroupPickerComponent, GroupsService, HANDOFF_ROUTE_PARAM, HANDOFF_TOKEN_PARAM, HandleService, HandoffService, HapticsService, HasPermissionDirective, HeaderActionsService, HeaderComponent, HintComponent, HorizontalScrollComponent, HrefComponent, HtmlViewerModalComponent, I18nService, IMAGE_DEFAULTS, INITIAL_AUTH_STATE, INITIAL_MFA_STATE, INVITATION_CARD_DEFAULTS, IONIC_COLORS$5 as IONIC_COLORS, Icon, IconComponent, IconService, ImageComponent, ImageCropComponent, ImageService, InAppBrowserService, InfiniteListComponent, InfoComponent, InputI18nHelper, InputType, InvitationCardComponent, InviteMemberModalComponent, ItemListComponent, KNOWN_ROUTES, LANG_STORAGE_KEY$1 as LANG_STORAGE_KEY, LEGAL_CONTENT_CONFIG, LOGGED_IN_HINT_COOKIE, LOGIN_DEFAULTS, LandingSplitComponent, LandingStepsComponent, LanguageSelectorComponent, LanguageSelectorV2Component, LayeredCardComponent, LegalContentService, LegalLinkService, LightRippleDirective, LinkComponent, LinkProcessorService, LinkedProvidersComponent, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LiveReadFallbackService, LoadMoreComponent, LoadingDirective, LocalStorageService, LocaleService, LoginAttemptModalComponent, LoginComponent, MEDIA_OBJECT_DEFAULTS, MEMBER_CARD_DEFAULTS, METADATA_LIST_DEFAULTS, META_SCHEMA_VERSION, METRIC_CARD_DEFAULTS, MINI_GAMES_I18N, MINI_GAME_PLAYER_AVATARS, MINI_GAME_PLAYER_COLORS, MODAL_SIZES, MOTIF_KEYS, MOTION, MaintenancePageComponent, MarkdownArticleParserService, MediaObjectComponent, MediaViewerModalComponent, MemberCardComponent, MemberDetailModalComponent, MemberImportModalComponent, MemoryGameComponent, MenuComponent, MessageBubbleComponent, MessagingService, MetaService, MetadataListComponent, MeteringService, MetricCardComponent, MfaModalComponent, MiniGameCalloutComponent, MiniGamePlayerProfileService, MiniGameScorePopComponent, MiniGamesMenuComponent, ModalLayoutComponent, ModalService, ModalShellComponent, MultiSelectSearchComponent, NUM_KEYS, NavigationService, NetworkBannerComponent, NetworkStatusService, NewsBuilder, NoContentComponent, NotesBoxComponent, NoticeComponent, NotificationActionService, NotificationPreferencesViewComponent, NotificationsService, NotificationsViewComponent, NumberFromToComponent, NumberPickerComponent, NumberStepperComponent, OAUTH_PROVIDERS_INFO, OAuthCallbackComponent, OAuthService, OperationReferenceComponent, OptionCardsComponent, OptionSheetComponent, OptionSheetService, OrgInfoSheetComponent, OrgService, OrgSwitchService, OrganizationViewComponent, PATTERN_MOTIFS, PATTERN_PALETTES, PATTERN_STYLE_CONFIGS, PERSONA_CONFIG, PLATFORM_CONFIGS, POST_UPDATE_TS_KEY, PageBlockComponent, PageContentComponent, PageLinksComponent, PageRefreshService, PageTemplateComponent, PageWavesComponent, PageWrapperComponent, PaginationComponent, PaginationService, PasswordInputComponent, PatternComponent, PdfService, PermissionCatalogService, PermissionSelectorComponent, PermissionsModalComponent, PermissionsViewComponent, PersonaService, PhoneDisplayComponent, PhoneFormatService, PhoneInputComponent, PickerV2Component, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PreferencesService, PreferencesViewComponent, PresetService, PriceTagComponent, PricingTableComponent, ProcessLinksPipe, ProfileCardComponent, ProfileContentComponent, ProfileModalComponent, ProfileSkeletonComponent, ProfileViewComponent, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrBrandValidationError, QrCodeComponent, QrGeneratorService, QrScannerComponent, QueryBuilder, QuoteBoxComponent, REQUEST_STATUSES, RadioInputComponent, RangeInputComponent, RatingComponent, RbacService, ReactionBarComponent, ReactionsService, RefresherComponent, RequestFirestoreService, RequestFormBuilderService, RequestFormComponent, RequestModalComponent, RequestReviewPanelComponent, RequestService, RetroAudioService, RichEditorComponent, RightsFooterComponent, RoleManagerComponent, 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, SectionHeaderComponent, SecurityViewComponent, SegmentControlComponent, SelectSearchComponent, SelectSearchPickerModalComponent, SessionListModalComponent, SessionService, SessionTransitionOverlayComponent, SettingsHubComponent, ShareButtonsComponent, ShareProfileModalComponent, SimonGameComponent, SimpleComponent, SkeletonComponent, SkeletonLayoutComponent, SkeletonService, SplashComponent, SplashScreenService, StatsBarComponent, StatsCardComponent, StepperComponent, StorageService, SupportTicketCtaComponent, SwipeCarouselComponent, SwitchOrgModalComponent, TRI_KEYS, TabbedContentComponent, TableSkeletonComponent, TabsComponent, Terminal404Component, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeSelectorComponent, ThemeService, ThreadPanelComponent, TicketCardComponent, TicketCardImageService, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, TokenService, ToolbarActionType, ToolbarComponent, TransferOwnershipModalComponent, TranslatePipe, TypedCollection, TypingIndicatorComponent, UPDATE_BANNER_DEFAULT_CONTENT, UPDATE_BANNER_I18N_NAMESPACE, UpdateBannerComponent, UsageMetersComponent, UsageService, UserAvatarComponent, UsernameInputComponent, VALTECH_ACCESS_FEATURES, VALTECH_ADS_CONFIG, VALTECH_APP_CONFIG, VALTECH_APP_VERSION, VALTECH_AUTH_CONFIG, VALTECH_CHAT_CONFIG, VALTECH_COLLECTIONS_CONFIG, VALTECH_COMMS_PREFERENCES_CONFIG, VALTECH_COMPANY_LINKS, VALTECH_CONTENT_CONFIG, VALTECH_COPYRIGHT_TEMPLATE, VALTECH_DEBUG_CONSOLE, VALTECH_DEFAULT_CONTENT, VALTECH_DIAGRAMS, VALTECH_DONATION_CONFIG, VALTECH_FEEDBACK_CONFIG, VALTECH_FIREBASE_CONFIG, VALTECH_FOOTER_I18N, VALTECH_FOOTER_LOGO, VALTECH_LANGUAGE_SELECTOR, VALTECH_LEGAL_CONFIG, VALTECH_LEGAL_ENTITY, VALTECH_MENU_I18N, VALTECH_NETWORK_ERROR_KEY, VALTECH_REACTIONS_CONFIG, VALTECH_SETTINGS_MENU_LINKS, VALTECH_SITE_PATHS, VALTECH_SOCIAL_LINKS, VALTECH_SPLASH_SCREEN, VALTECH_WEB_BASE_URLS, VALTECH_WHATSAPP_CONFIG, VAL_REGISTERED_ICONS, VERSION, ValCommentThreadComponent, ValQuotaWarningComponent, ValtechErrorService, VerifyViewComponent, VideoPlayerComponent, WhatsappFabComponent, WhatsappService, WizardComponent, WizardFooterComponent, WorkflowService, accessGuard, accessGuardFromRoute, applyDefaultValueToControl, articleToTiptapDoc, authGuard, authInterceptor, authPasswordValidator, beautifyLegalArticle, blogPost, buildCompanyFooterProps, buildFooterLinks, buildLegalLinkResolver, buildPath, buildPlatformMenu, buildSettingsCards, buildSideNavItemsFromBottomNav, button, canSubmitRequestType, classifyChip, collections, connectPageRefresh, createErrorStateProps, createFirebaseConfig, createGameAvatarCatalog, createGameAvatarProps, createGlowCardProps, createInitialDatasetState, createInitialPaginationState, createNumberFromToField, createPageState, createPermissionLabeler, createRefreshableStream, createTitleProps, datasetPageFromLegacyCursor, defaultQrBrand, docs, errorLoggingInterceptor, evaluateValtechAccess, extractPathParams, firmaDeSesionDeCustomToken, formatClockTime, formatDateSeparator, formatRelativeTime, gameAvatarCatalogEntryToMetadata, gameAvatarDataUri, generatePatternTiles, generateRandomTile, getAppInfo, getAppVersion, getCollectionPath, getDocumentId, getTimeOfDayKey, goToTop, groupPermissionsByScope, guestGuard, hasEmulators, iconButton, interpretError, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isIonicColor, isKnownRoute, isValidPath, joinPath, maxLength, mulberry32, news, parseMarkdownArticle, permissionGuard, permissionGuardFromRoute, provideLegalContent, providePersona, provideSplashScreen, provideValtechAboutRoutes, provideValtechAccessFeatures, provideValtechAccountRoutes, provideValtechAds, provideValtechApiKeysRoutes, provideValtechAppConfig, provideValtechAppVersion, provideValtechAppVersionHttp, provideValtechAuth, provideValtechAuthInterceptor, provideValtechChat, provideValtechCollections, provideValtechCommsPreferences, provideValtechContent, provideValtechDebugConsole, provideValtechDiagrams, provideValtechDonations, provideValtechErrorHandling, provideValtechFeedback, provideValtechFirebase, provideValtechI18n, provideValtechLegal, provideValtechNotificationClickActions, provideValtechNotificationPreferencesRoutes, provideValtechNotificationsRoutes, provideValtechOrganizationRoutes, provideValtechPermissionsRoutes, provideValtechPreferencesRoutes, provideValtechPresets, provideValtechProfileRoutes, provideValtechReactions, provideValtechSecurityRoutes, provideValtechSettingsRoutes, provideValtechSite, provideValtechSkeleton, provideValtechWhatsapp, qrContrastRatio, qrErrorCorrectionFor, query, rbacGuard, renderGameAvatarSvg, renderPatternSvgInner, replaceSpecialChars, requestSubmitMode, resolveColor, resolveCopyrightTemplate, resolveInputDefaultValue, resolveIonicColor, resolveWebBaseUrl, roleGuard, roleOf, selectableRequestTypes, storagePaths, suggestEmailFix, superAdminGuard, supportedGameAvatarStyles, tiptapDocToArticle, tiptapDocToArticleElements, toArticle, validateQrBrand, validateRoutes };
|
|
89874
90931
|
//# sourceMappingURL=valtech-components.mjs.map
|