valtech-components 2.0.810 → 2.0.812
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/faq/faq.component.mjs +65 -25
- package/esm2022/lib/config/company-footer.config.mjs +4 -2
- package/esm2022/lib/version.mjs +2 -2
- package/fesm2022/valtech-components.mjs +367 -327
- package/fesm2022/valtech-components.mjs.map +1 -1
- package/lib/components/organisms/faq/faq.component.d.ts +17 -9
- package/lib/version.d.ts +1 -1
- package/package.json +1 -1
|
@@ -53,7 +53,7 @@ import 'prismjs/components/prism-json';
|
|
|
53
53
|
* Current version of valtech-components.
|
|
54
54
|
* This is automatically updated during the publish process.
|
|
55
55
|
*/
|
|
56
|
-
const VERSION = '2.0.
|
|
56
|
+
const VERSION = '2.0.812';
|
|
57
57
|
|
|
58
58
|
/**
|
|
59
59
|
* Servicio para gestionar presets de componentes.
|
|
@@ -35849,6 +35849,308 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
35849
35849
|
type: Input
|
|
35850
35850
|
}] } });
|
|
35851
35851
|
|
|
35852
|
+
/** Built-in label sets for the three platform locales. */
|
|
35853
|
+
const CALLOUT_LABELS = {
|
|
35854
|
+
es: {
|
|
35855
|
+
NOTE: 'Nota',
|
|
35856
|
+
TIP: 'Tip',
|
|
35857
|
+
INFO: 'Info',
|
|
35858
|
+
IMPORTANT: 'Importante',
|
|
35859
|
+
WARNING: 'Atención',
|
|
35860
|
+
CAUTION: 'Precaución',
|
|
35861
|
+
},
|
|
35862
|
+
en: {
|
|
35863
|
+
NOTE: 'Note',
|
|
35864
|
+
TIP: 'Tip',
|
|
35865
|
+
INFO: 'Info',
|
|
35866
|
+
IMPORTANT: 'Important',
|
|
35867
|
+
WARNING: 'Warning',
|
|
35868
|
+
CAUTION: 'Caution',
|
|
35869
|
+
},
|
|
35870
|
+
pt: {
|
|
35871
|
+
NOTE: 'Nota',
|
|
35872
|
+
TIP: 'Dica',
|
|
35873
|
+
INFO: 'Info',
|
|
35874
|
+
IMPORTANT: 'Importante',
|
|
35875
|
+
WARNING: 'Atenção',
|
|
35876
|
+
CAUTION: 'Cuidado',
|
|
35877
|
+
},
|
|
35878
|
+
};
|
|
35879
|
+
/**
|
|
35880
|
+
* Per-callout-kind color (Ionic semantic color). Fixed across locales since
|
|
35881
|
+
* red = danger no matter what language you speak.
|
|
35882
|
+
*/
|
|
35883
|
+
const CALLOUT_COLORS = {
|
|
35884
|
+
NOTE: 'primary',
|
|
35885
|
+
TIP: 'success',
|
|
35886
|
+
INFO: 'tertiary',
|
|
35887
|
+
IMPORTANT: 'warning',
|
|
35888
|
+
WARNING: 'warning',
|
|
35889
|
+
CAUTION: 'danger',
|
|
35890
|
+
};
|
|
35891
|
+
const BOX_DRAWING = /[┌┐└┘├┤┬┴┼─│╔╗╚╝═║]/;
|
|
35892
|
+
const CALLOUT_RE = /^>\s*\[!(NOTE|TIP|INFO|WARNING|CAUTION|IMPORTANT)\]\s*(.*)$/i;
|
|
35893
|
+
const FENCE_RE = /^```([\w-]*)\s*$/;
|
|
35894
|
+
const HEADING_RE = /^(#{1,6})\s+(.+)$/;
|
|
35895
|
+
const SEPARATOR_RE = /^\s*(?:-{3,}|\*{3,}|_{3,})\s*$/;
|
|
35896
|
+
const UNORDERED_RE = /^\s*[-*+]\s+(.+)$/;
|
|
35897
|
+
const CHECKLIST_RE = /^\s*[-*+]\s+\[([ xX])\]\s+(.+)$/;
|
|
35898
|
+
const ORDERED_RE = /^\s*\d+\.\s+(.+)$/;
|
|
35899
|
+
const TABLE_DIVIDER_RE = /^\s*\|?[\s:|-]+\|?\s*$/;
|
|
35900
|
+
const TABLE_ROW_RE = /^\s*\|(.+)\|\s*$/;
|
|
35901
|
+
/**
|
|
35902
|
+
* Pure Markdown → ArticleMetadata parser. No Angular deps — usable from Node scripts
|
|
35903
|
+
* (build-time generation) and from the Angular `MarkdownArticleParserService` wrapper.
|
|
35904
|
+
*
|
|
35905
|
+
* Supported syntax:
|
|
35906
|
+
* - Headings (#, ##, ### …) → title / subtitle
|
|
35907
|
+
* - Paragraphs → paragraph (with `processLinks` + `allowPartialBold`)
|
|
35908
|
+
* - Lists (-, *, 1.) → unordered / ordered list (- [ ] / - [x] for checklist)
|
|
35909
|
+
* - Blockquotes (>) → quote, with GitHub callouts `> [!NOTE|TIP|INFO|WARNING|CAUTION|IMPORTANT]` mapped to notes
|
|
35910
|
+
* - Code fences (```lang) → code
|
|
35911
|
+
* - Box-drawing ASCII art (┌┐└┘│─) auto-wrapped as code
|
|
35912
|
+
* - Tables → flattened into paragraphs with bold keys
|
|
35913
|
+
* - Horizontal rules (---, ***, ___) → separator
|
|
35914
|
+
*/
|
|
35915
|
+
function parseMarkdownArticle(markdown, options) {
|
|
35916
|
+
const lines = normalize(markdown).split('\n');
|
|
35917
|
+
const elements = [];
|
|
35918
|
+
const labels = options?.calloutLabels ??
|
|
35919
|
+
(options?.locale ? CALLOUT_LABELS[options.locale] : CALLOUT_LABELS.es);
|
|
35920
|
+
let i = 0;
|
|
35921
|
+
while (i < lines.length) {
|
|
35922
|
+
const line = lines[i];
|
|
35923
|
+
if (line.trim() === '') {
|
|
35924
|
+
i++;
|
|
35925
|
+
continue;
|
|
35926
|
+
}
|
|
35927
|
+
const fence = line.match(FENCE_RE);
|
|
35928
|
+
if (fence) {
|
|
35929
|
+
const lang = fence[1] || undefined;
|
|
35930
|
+
const body = [];
|
|
35931
|
+
i++;
|
|
35932
|
+
while (i < lines.length && !FENCE_RE.test(lines[i])) {
|
|
35933
|
+
body.push(lines[i]);
|
|
35934
|
+
i++;
|
|
35935
|
+
}
|
|
35936
|
+
i++;
|
|
35937
|
+
elements.push({
|
|
35938
|
+
type: 'code',
|
|
35939
|
+
props: { code: body.join('\n'), language: lang, theme: 'dark' },
|
|
35940
|
+
});
|
|
35941
|
+
continue;
|
|
35942
|
+
}
|
|
35943
|
+
if (BOX_DRAWING.test(line)) {
|
|
35944
|
+
const body = [];
|
|
35945
|
+
while (i < lines.length && (lines[i].trim() === '' || BOX_DRAWING.test(lines[i]))) {
|
|
35946
|
+
body.push(lines[i]);
|
|
35947
|
+
i++;
|
|
35948
|
+
}
|
|
35949
|
+
while (body.length && body[body.length - 1].trim() === '')
|
|
35950
|
+
body.pop();
|
|
35951
|
+
elements.push({
|
|
35952
|
+
type: 'code',
|
|
35953
|
+
props: { code: body.join('\n'), language: 'text', theme: 'dark' },
|
|
35954
|
+
});
|
|
35955
|
+
continue;
|
|
35956
|
+
}
|
|
35957
|
+
if (SEPARATOR_RE.test(line)) {
|
|
35958
|
+
elements.push({ type: 'separator', props: { style: 'line' } });
|
|
35959
|
+
i++;
|
|
35960
|
+
continue;
|
|
35961
|
+
}
|
|
35962
|
+
const heading = line.match(HEADING_RE);
|
|
35963
|
+
if (heading) {
|
|
35964
|
+
elements.push(makeHeading(heading[1].length, heading[2].trim()));
|
|
35965
|
+
i++;
|
|
35966
|
+
continue;
|
|
35967
|
+
}
|
|
35968
|
+
if (line.startsWith('>')) {
|
|
35969
|
+
const block = [];
|
|
35970
|
+
while (i < lines.length && lines[i].startsWith('>')) {
|
|
35971
|
+
block.push(lines[i]);
|
|
35972
|
+
i++;
|
|
35973
|
+
}
|
|
35974
|
+
elements.push(makeQuoteOrCallout(block, labels));
|
|
35975
|
+
continue;
|
|
35976
|
+
}
|
|
35977
|
+
if (TABLE_ROW_RE.test(line)) {
|
|
35978
|
+
const rows = [];
|
|
35979
|
+
while (i < lines.length && TABLE_ROW_RE.test(lines[i])) {
|
|
35980
|
+
rows.push(lines[i]);
|
|
35981
|
+
i++;
|
|
35982
|
+
}
|
|
35983
|
+
elements.push(...makeTable(rows));
|
|
35984
|
+
continue;
|
|
35985
|
+
}
|
|
35986
|
+
if (CHECKLIST_RE.test(line) || UNORDERED_RE.test(line) || ORDERED_RE.test(line)) {
|
|
35987
|
+
const listType = CHECKLIST_RE.test(line)
|
|
35988
|
+
? 'checklist'
|
|
35989
|
+
: ORDERED_RE.test(line)
|
|
35990
|
+
? 'ordered'
|
|
35991
|
+
: 'unordered';
|
|
35992
|
+
const items = [];
|
|
35993
|
+
while (i < lines.length && lines[i].trim() !== '') {
|
|
35994
|
+
const cur = lines[i];
|
|
35995
|
+
const check = cur.match(CHECKLIST_RE);
|
|
35996
|
+
const unord = cur.match(UNORDERED_RE);
|
|
35997
|
+
const ord = cur.match(ORDERED_RE);
|
|
35998
|
+
if (check)
|
|
35999
|
+
items.push({ text: check[2].trim() });
|
|
36000
|
+
else if (ord && listType === 'ordered')
|
|
36001
|
+
items.push({ text: ord[1].trim() });
|
|
36002
|
+
else if (unord && listType !== 'ordered')
|
|
36003
|
+
items.push({ text: unord[1].trim() });
|
|
36004
|
+
else
|
|
36005
|
+
break;
|
|
36006
|
+
i++;
|
|
36007
|
+
}
|
|
36008
|
+
elements.push({ type: 'list', props: { items, listType } });
|
|
36009
|
+
continue;
|
|
36010
|
+
}
|
|
36011
|
+
const paragraph = [];
|
|
36012
|
+
while (i < lines.length && lines[i].trim() !== '' && !startsNewBlock(lines[i])) {
|
|
36013
|
+
paragraph.push(lines[i]);
|
|
36014
|
+
i++;
|
|
36015
|
+
}
|
|
36016
|
+
const text = paragraph.join(' ').trim();
|
|
36017
|
+
if (text) {
|
|
36018
|
+
elements.push({
|
|
36019
|
+
type: 'paragraph',
|
|
36020
|
+
props: {
|
|
36021
|
+
content: text,
|
|
36022
|
+
size: 'medium',
|
|
36023
|
+
color: 'dark',
|
|
36024
|
+
bold: false,
|
|
36025
|
+
processLinks: true,
|
|
36026
|
+
allowPartialBold: true,
|
|
36027
|
+
},
|
|
36028
|
+
});
|
|
36029
|
+
}
|
|
36030
|
+
}
|
|
36031
|
+
// Strip parser-only options before merging into ArticleMetadata
|
|
36032
|
+
const { locale: _l, calloutLabels: _c, ...metadataOverrides } = options ?? {};
|
|
36033
|
+
return {
|
|
36034
|
+
elements,
|
|
36035
|
+
maxWidth: '900px',
|
|
36036
|
+
centered: true,
|
|
36037
|
+
theme: 'auto',
|
|
36038
|
+
...metadataOverrides,
|
|
36039
|
+
};
|
|
36040
|
+
}
|
|
36041
|
+
function normalize(md) {
|
|
36042
|
+
return md.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
|
36043
|
+
}
|
|
36044
|
+
function startsNewBlock(line) {
|
|
36045
|
+
return (HEADING_RE.test(line) ||
|
|
36046
|
+
FENCE_RE.test(line) ||
|
|
36047
|
+
SEPARATOR_RE.test(line) ||
|
|
36048
|
+
TABLE_ROW_RE.test(line) ||
|
|
36049
|
+
UNORDERED_RE.test(line) ||
|
|
36050
|
+
ORDERED_RE.test(line) ||
|
|
36051
|
+
CHECKLIST_RE.test(line) ||
|
|
36052
|
+
line.startsWith('>') ||
|
|
36053
|
+
BOX_DRAWING.test(line));
|
|
36054
|
+
}
|
|
36055
|
+
function makeHeading(level, content) {
|
|
36056
|
+
if (level === 1) {
|
|
36057
|
+
return {
|
|
36058
|
+
type: 'title',
|
|
36059
|
+
props: { content, size: 'xlarge', color: 'dark', bold: true },
|
|
36060
|
+
};
|
|
36061
|
+
}
|
|
36062
|
+
const size = level === 2 ? 'large' : level === 3 ? 'medium' : 'small';
|
|
36063
|
+
return {
|
|
36064
|
+
type: 'subtitle',
|
|
36065
|
+
props: { content, size, color: 'dark', bold: true },
|
|
36066
|
+
};
|
|
36067
|
+
}
|
|
36068
|
+
function makeQuoteOrCallout(block, labels) {
|
|
36069
|
+
const first = block[0];
|
|
36070
|
+
const callout = first.match(CALLOUT_RE);
|
|
36071
|
+
const lines = block.map(l => l.replace(/^>\s?/, ''));
|
|
36072
|
+
if (callout) {
|
|
36073
|
+
const type = callout[1].toUpperCase();
|
|
36074
|
+
const firstLineRest = callout[2] || '';
|
|
36075
|
+
const rest = lines.slice(1).join(' ').trim();
|
|
36076
|
+
const text = [firstLineRest, rest].filter(Boolean).join(' ').trim();
|
|
36077
|
+
return makeNote(type, text, labels);
|
|
36078
|
+
}
|
|
36079
|
+
const text = lines.join(' ').trim();
|
|
36080
|
+
return {
|
|
36081
|
+
type: 'quote',
|
|
36082
|
+
props: {
|
|
36083
|
+
content: text,
|
|
36084
|
+
size: 'medium',
|
|
36085
|
+
color: 'medium',
|
|
36086
|
+
bold: false,
|
|
36087
|
+
showQuoteMark: true,
|
|
36088
|
+
alignment: 'left',
|
|
36089
|
+
},
|
|
36090
|
+
};
|
|
36091
|
+
}
|
|
36092
|
+
function makeNote(kind, text, labels) {
|
|
36093
|
+
return {
|
|
36094
|
+
type: 'note',
|
|
36095
|
+
props: {
|
|
36096
|
+
text,
|
|
36097
|
+
prefix: `${labels[kind]}:`,
|
|
36098
|
+
color: CALLOUT_COLORS[kind],
|
|
36099
|
+
textColor: 'dark',
|
|
36100
|
+
size: 'medium',
|
|
36101
|
+
rounded: true,
|
|
36102
|
+
allowPartialBold: true,
|
|
36103
|
+
processLinks: true,
|
|
36104
|
+
},
|
|
36105
|
+
};
|
|
36106
|
+
}
|
|
36107
|
+
function makeTable(rows) {
|
|
36108
|
+
const parsed = rows
|
|
36109
|
+
.filter(r => !TABLE_DIVIDER_RE.test(r))
|
|
36110
|
+
.map(r => r
|
|
36111
|
+
.trim()
|
|
36112
|
+
.replace(/^\|/, '')
|
|
36113
|
+
.replace(/\|$/, '')
|
|
36114
|
+
.split('|')
|
|
36115
|
+
.map(c => c.trim()));
|
|
36116
|
+
if (parsed.length === 0)
|
|
36117
|
+
return [];
|
|
36118
|
+
const header = parsed[0];
|
|
36119
|
+
const dataRows = parsed.slice(1);
|
|
36120
|
+
if (dataRows.length === 0) {
|
|
36121
|
+
return [
|
|
36122
|
+
{
|
|
36123
|
+
type: 'paragraph',
|
|
36124
|
+
props: {
|
|
36125
|
+
content: header.join(' · '),
|
|
36126
|
+
size: 'medium',
|
|
36127
|
+
color: 'dark',
|
|
36128
|
+
bold: false,
|
|
36129
|
+
processLinks: true,
|
|
36130
|
+
allowPartialBold: true,
|
|
36131
|
+
},
|
|
36132
|
+
},
|
|
36133
|
+
];
|
|
36134
|
+
}
|
|
36135
|
+
return dataRows.map(row => {
|
|
36136
|
+
const pairs = row.map((cell, idx) => {
|
|
36137
|
+
const key = header[idx] ?? '';
|
|
36138
|
+
return key ? `**${key}:** ${cell}` : cell;
|
|
36139
|
+
});
|
|
36140
|
+
return {
|
|
36141
|
+
type: 'paragraph',
|
|
36142
|
+
props: {
|
|
36143
|
+
content: pairs.join(' · '),
|
|
36144
|
+
size: 'medium',
|
|
36145
|
+
color: 'dark',
|
|
36146
|
+
bold: false,
|
|
36147
|
+
processLinks: true,
|
|
36148
|
+
allowPartialBold: true,
|
|
36149
|
+
},
|
|
36150
|
+
};
|
|
36151
|
+
});
|
|
36152
|
+
}
|
|
36153
|
+
|
|
35852
36154
|
/**
|
|
35853
36155
|
* `val-faq`
|
|
35854
36156
|
*
|
|
@@ -35857,7 +36159,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
35857
36159
|
* reusar la misma data (`FaqMetadata.categories`) para emitir el structured
|
|
35858
36160
|
* data `FAQPage` (JSON-LD) y ganar rich results en buscadores.
|
|
35859
36161
|
*
|
|
35860
|
-
*
|
|
36162
|
+
* Las respuestas (`FaqItem.answer`) son **Markdown** — se parsean con
|
|
36163
|
+
* `parseMarkdownArticle` y se renderizan vía `val-article`. Soportan links,
|
|
36164
|
+
* listas, negritas, tablas, etc.
|
|
35861
36165
|
*
|
|
35862
36166
|
* @example
|
|
35863
36167
|
* ```html
|
|
@@ -35867,12 +36171,26 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
35867
36171
|
class FaqComponent {
|
|
35868
36172
|
constructor() {
|
|
35869
36173
|
this.props_ = signal({ categories: [] });
|
|
35870
|
-
/** Término de búsqueda actual
|
|
36174
|
+
/** Término de búsqueda actual. */
|
|
35871
36175
|
this.query = signal('');
|
|
35872
36176
|
/**
|
|
35873
|
-
*
|
|
35874
|
-
*
|
|
35875
|
-
*
|
|
36177
|
+
* Cache de respuestas parseadas (Markdown → ArticleMetadata). Se reconstruye
|
|
36178
|
+
* solo cuando cambian las categorías — el parseo NO corre por keystroke.
|
|
36179
|
+
* Keyed por id de item (los ids son únicos en toda la FAQ).
|
|
36180
|
+
*/
|
|
36181
|
+
this.parsedAnswers = computed(() => {
|
|
36182
|
+
const map = new Map();
|
|
36183
|
+
for (const cat of this.props_().categories ?? []) {
|
|
36184
|
+
for (const item of cat.items) {
|
|
36185
|
+
map.set(item.id, parseMarkdownArticle(item.answer));
|
|
36186
|
+
}
|
|
36187
|
+
}
|
|
36188
|
+
return map;
|
|
36189
|
+
});
|
|
36190
|
+
/**
|
|
36191
|
+
* Categorías visibles tras el filtro. Una categoría desaparece si ninguna
|
|
36192
|
+
* de sus preguntas matchea. Match sobre pregunta + respuesta (raw markdown),
|
|
36193
|
+
* case-insensitive.
|
|
35876
36194
|
*/
|
|
35877
36195
|
this.visibleCategories = computed(() => {
|
|
35878
36196
|
const q = this.query().trim().toLowerCase();
|
|
@@ -35901,17 +36219,9 @@ class FaqComponent {
|
|
|
35901
36219
|
get props() {
|
|
35902
36220
|
return this.props_();
|
|
35903
36221
|
}
|
|
35904
|
-
/**
|
|
35905
|
-
|
|
35906
|
-
return {
|
|
35907
|
-
multiple: this.props_().multiple ?? false,
|
|
35908
|
-
expandIconSlot: 'end',
|
|
35909
|
-
items: cat.items.map(it => ({
|
|
35910
|
-
value: it.id,
|
|
35911
|
-
header: it.question,
|
|
35912
|
-
content: it.answer,
|
|
35913
|
-
})),
|
|
35914
|
-
};
|
|
36222
|
+
/** Respuesta parseada de un item — desde el cache. */
|
|
36223
|
+
answerOf(item) {
|
|
36224
|
+
return this.parsedAnswers().get(item.id) ?? { elements: [] };
|
|
35915
36225
|
}
|
|
35916
36226
|
onSearch(term) {
|
|
35917
36227
|
this.query.set(term ?? '');
|
|
@@ -35932,23 +36242,38 @@ class FaqComponent {
|
|
|
35932
36242
|
}
|
|
35933
36243
|
|
|
35934
36244
|
@if (visibleCategories().length === 0) {
|
|
35935
|
-
<p class="val-faq__empty">
|
|
36245
|
+
<p class="val-faq__empty">
|
|
36246
|
+
{{ props.noResultsText || 'Sin resultados' }}
|
|
36247
|
+
</p>
|
|
35936
36248
|
} @else {
|
|
35937
36249
|
@for (cat of visibleCategories(); track cat.id) {
|
|
35938
36250
|
<section class="val-faq__category">
|
|
35939
36251
|
@if (showCategoryLabel()) {
|
|
35940
36252
|
<h3 class="val-faq__category-label">{{ cat.label }}</h3>
|
|
35941
36253
|
}
|
|
35942
|
-
<
|
|
36254
|
+
<ion-accordion-group [multiple]="props.multiple ?? false">
|
|
36255
|
+
@for (item of cat.items; track item.id) {
|
|
36256
|
+
<ion-accordion [value]="item.id" class="val-faq__item">
|
|
36257
|
+
<ion-item slot="header" lines="none" class="val-faq__q">
|
|
36258
|
+
<ion-label class="val-faq__q-label">
|
|
36259
|
+
{{ item.question }}
|
|
36260
|
+
</ion-label>
|
|
36261
|
+
</ion-item>
|
|
36262
|
+
<div slot="content" class="val-faq__a">
|
|
36263
|
+
<val-article [props]="answerOf(item)" />
|
|
36264
|
+
</div>
|
|
36265
|
+
</ion-accordion>
|
|
36266
|
+
}
|
|
36267
|
+
</ion-accordion-group>
|
|
35943
36268
|
</section>
|
|
35944
36269
|
}
|
|
35945
36270
|
}
|
|
35946
36271
|
</div>
|
|
35947
|
-
`, isInline: true, styles: [":host{display:block;width:100%}.val-faq__search{margin-bottom:16px}.val-faq__category+.val-faq__category{margin-top:24px}.val-faq__category-label{font-size:.8rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--ion-color-medium, #92949c);margin:0 0 8px;padding-inline:4px}.val-faq__empty{text-align:center;padding:32px 16px;color:var(--ion-color-medium, #92949c);font-size:.95rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type:
|
|
36272
|
+
`, isInline: true, styles: [":host{display:block;width:100%}.val-faq__search{margin-bottom:16px}.val-faq__category+.val-faq__category{margin-top:24px}.val-faq__category-label{font-size:.8rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--ion-color-medium, #92949c);margin:0 0 8px;padding-inline:4px}ion-accordion-group{display:flex;flex-direction:column;gap:8px}.val-faq__item{border-radius:12px;overflow:hidden;background:var(--ion-color-light, #f4f5f8)}.val-faq__q{--background: transparent;--min-height: 56px}.val-faq__q-label{font-weight:600;white-space:normal}.val-faq__a{padding:4px 16px 16px}.val-faq__empty{text-align:center;padding:32px 16px;color:var(--ion-color-medium, #92949c);font-size:.95rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonAccordion, selector: "ion-accordion", inputs: ["disabled", "mode", "readonly", "toggleIcon", "toggleIconSlot", "value"] }, { kind: "component", type: IonAccordionGroup, selector: "ion-accordion-group", inputs: ["animated", "disabled", "expand", "mode", "multiple", "readonly", "value"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: SearchbarComponent, selector: "val-searchbar", inputs: ["preset", "props"], outputs: ["filterEvent", "focusEvent", "blurEvent"] }, { kind: "component", type: ArticleComponent, selector: "val-article", inputs: ["props"] }] }); }
|
|
35948
36273
|
}
|
|
35949
36274
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FaqComponent, decorators: [{
|
|
35950
36275
|
type: Component,
|
|
35951
|
-
args: [{ selector: 'val-faq', standalone: true, imports: [CommonModule,
|
|
36276
|
+
args: [{ selector: 'val-faq', standalone: true, imports: [CommonModule, IonAccordion, IonAccordionGroup, IonItem, IonLabel, SearchbarComponent, ArticleComponent], template: `
|
|
35952
36277
|
<div class="val-faq">
|
|
35953
36278
|
@if (props.searchable !== false) {
|
|
35954
36279
|
<div class="val-faq__search">
|
|
@@ -35963,19 +36288,34 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
35963
36288
|
}
|
|
35964
36289
|
|
|
35965
36290
|
@if (visibleCategories().length === 0) {
|
|
35966
|
-
<p class="val-faq__empty">
|
|
36291
|
+
<p class="val-faq__empty">
|
|
36292
|
+
{{ props.noResultsText || 'Sin resultados' }}
|
|
36293
|
+
</p>
|
|
35967
36294
|
} @else {
|
|
35968
36295
|
@for (cat of visibleCategories(); track cat.id) {
|
|
35969
36296
|
<section class="val-faq__category">
|
|
35970
36297
|
@if (showCategoryLabel()) {
|
|
35971
36298
|
<h3 class="val-faq__category-label">{{ cat.label }}</h3>
|
|
35972
36299
|
}
|
|
35973
|
-
<
|
|
36300
|
+
<ion-accordion-group [multiple]="props.multiple ?? false">
|
|
36301
|
+
@for (item of cat.items; track item.id) {
|
|
36302
|
+
<ion-accordion [value]="item.id" class="val-faq__item">
|
|
36303
|
+
<ion-item slot="header" lines="none" class="val-faq__q">
|
|
36304
|
+
<ion-label class="val-faq__q-label">
|
|
36305
|
+
{{ item.question }}
|
|
36306
|
+
</ion-label>
|
|
36307
|
+
</ion-item>
|
|
36308
|
+
<div slot="content" class="val-faq__a">
|
|
36309
|
+
<val-article [props]="answerOf(item)" />
|
|
36310
|
+
</div>
|
|
36311
|
+
</ion-accordion>
|
|
36312
|
+
}
|
|
36313
|
+
</ion-accordion-group>
|
|
35974
36314
|
</section>
|
|
35975
36315
|
}
|
|
35976
36316
|
}
|
|
35977
36317
|
</div>
|
|
35978
|
-
`, styles: [":host{display:block;width:100%}.val-faq__search{margin-bottom:16px}.val-faq__category+.val-faq__category{margin-top:24px}.val-faq__category-label{font-size:.8rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--ion-color-medium, #92949c);margin:0 0 8px;padding-inline:4px}.val-faq__empty{text-align:center;padding:32px 16px;color:var(--ion-color-medium, #92949c);font-size:.95rem}\n"] }]
|
|
36318
|
+
`, styles: [":host{display:block;width:100%}.val-faq__search{margin-bottom:16px}.val-faq__category+.val-faq__category{margin-top:24px}.val-faq__category-label{font-size:.8rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--ion-color-medium, #92949c);margin:0 0 8px;padding-inline:4px}ion-accordion-group{display:flex;flex-direction:column;gap:8px}.val-faq__item{border-radius:12px;overflow:hidden;background:var(--ion-color-light, #f4f5f8)}.val-faq__q{--background: transparent;--min-height: 56px}.val-faq__q-label{font-weight:600;white-space:normal}.val-faq__a{padding:4px 16px 16px}.val-faq__empty{text-align:center;padding:32px 16px;color:var(--ion-color-medium, #92949c);font-size:.95rem}\n"] }]
|
|
35979
36319
|
}], propDecorators: { props: [{
|
|
35980
36320
|
type: Input
|
|
35981
36321
|
}] } });
|
|
@@ -37555,308 +37895,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
37555
37895
|
}]
|
|
37556
37896
|
}] });
|
|
37557
37897
|
|
|
37558
|
-
/** Built-in label sets for the three platform locales. */
|
|
37559
|
-
const CALLOUT_LABELS = {
|
|
37560
|
-
es: {
|
|
37561
|
-
NOTE: 'Nota',
|
|
37562
|
-
TIP: 'Tip',
|
|
37563
|
-
INFO: 'Info',
|
|
37564
|
-
IMPORTANT: 'Importante',
|
|
37565
|
-
WARNING: 'Atención',
|
|
37566
|
-
CAUTION: 'Precaución',
|
|
37567
|
-
},
|
|
37568
|
-
en: {
|
|
37569
|
-
NOTE: 'Note',
|
|
37570
|
-
TIP: 'Tip',
|
|
37571
|
-
INFO: 'Info',
|
|
37572
|
-
IMPORTANT: 'Important',
|
|
37573
|
-
WARNING: 'Warning',
|
|
37574
|
-
CAUTION: 'Caution',
|
|
37575
|
-
},
|
|
37576
|
-
pt: {
|
|
37577
|
-
NOTE: 'Nota',
|
|
37578
|
-
TIP: 'Dica',
|
|
37579
|
-
INFO: 'Info',
|
|
37580
|
-
IMPORTANT: 'Importante',
|
|
37581
|
-
WARNING: 'Atenção',
|
|
37582
|
-
CAUTION: 'Cuidado',
|
|
37583
|
-
},
|
|
37584
|
-
};
|
|
37585
|
-
/**
|
|
37586
|
-
* Per-callout-kind color (Ionic semantic color). Fixed across locales since
|
|
37587
|
-
* red = danger no matter what language you speak.
|
|
37588
|
-
*/
|
|
37589
|
-
const CALLOUT_COLORS = {
|
|
37590
|
-
NOTE: 'primary',
|
|
37591
|
-
TIP: 'success',
|
|
37592
|
-
INFO: 'tertiary',
|
|
37593
|
-
IMPORTANT: 'warning',
|
|
37594
|
-
WARNING: 'warning',
|
|
37595
|
-
CAUTION: 'danger',
|
|
37596
|
-
};
|
|
37597
|
-
const BOX_DRAWING = /[┌┐└┘├┤┬┴┼─│╔╗╚╝═║]/;
|
|
37598
|
-
const CALLOUT_RE = /^>\s*\[!(NOTE|TIP|INFO|WARNING|CAUTION|IMPORTANT)\]\s*(.*)$/i;
|
|
37599
|
-
const FENCE_RE = /^```([\w-]*)\s*$/;
|
|
37600
|
-
const HEADING_RE = /^(#{1,6})\s+(.+)$/;
|
|
37601
|
-
const SEPARATOR_RE = /^\s*(?:-{3,}|\*{3,}|_{3,})\s*$/;
|
|
37602
|
-
const UNORDERED_RE = /^\s*[-*+]\s+(.+)$/;
|
|
37603
|
-
const CHECKLIST_RE = /^\s*[-*+]\s+\[([ xX])\]\s+(.+)$/;
|
|
37604
|
-
const ORDERED_RE = /^\s*\d+\.\s+(.+)$/;
|
|
37605
|
-
const TABLE_DIVIDER_RE = /^\s*\|?[\s:|-]+\|?\s*$/;
|
|
37606
|
-
const TABLE_ROW_RE = /^\s*\|(.+)\|\s*$/;
|
|
37607
|
-
/**
|
|
37608
|
-
* Pure Markdown → ArticleMetadata parser. No Angular deps — usable from Node scripts
|
|
37609
|
-
* (build-time generation) and from the Angular `MarkdownArticleParserService` wrapper.
|
|
37610
|
-
*
|
|
37611
|
-
* Supported syntax:
|
|
37612
|
-
* - Headings (#, ##, ### …) → title / subtitle
|
|
37613
|
-
* - Paragraphs → paragraph (with `processLinks` + `allowPartialBold`)
|
|
37614
|
-
* - Lists (-, *, 1.) → unordered / ordered list (- [ ] / - [x] for checklist)
|
|
37615
|
-
* - Blockquotes (>) → quote, with GitHub callouts `> [!NOTE|TIP|INFO|WARNING|CAUTION|IMPORTANT]` mapped to notes
|
|
37616
|
-
* - Code fences (```lang) → code
|
|
37617
|
-
* - Box-drawing ASCII art (┌┐└┘│─) auto-wrapped as code
|
|
37618
|
-
* - Tables → flattened into paragraphs with bold keys
|
|
37619
|
-
* - Horizontal rules (---, ***, ___) → separator
|
|
37620
|
-
*/
|
|
37621
|
-
function parseMarkdownArticle(markdown, options) {
|
|
37622
|
-
const lines = normalize(markdown).split('\n');
|
|
37623
|
-
const elements = [];
|
|
37624
|
-
const labels = options?.calloutLabels ??
|
|
37625
|
-
(options?.locale ? CALLOUT_LABELS[options.locale] : CALLOUT_LABELS.es);
|
|
37626
|
-
let i = 0;
|
|
37627
|
-
while (i < lines.length) {
|
|
37628
|
-
const line = lines[i];
|
|
37629
|
-
if (line.trim() === '') {
|
|
37630
|
-
i++;
|
|
37631
|
-
continue;
|
|
37632
|
-
}
|
|
37633
|
-
const fence = line.match(FENCE_RE);
|
|
37634
|
-
if (fence) {
|
|
37635
|
-
const lang = fence[1] || undefined;
|
|
37636
|
-
const body = [];
|
|
37637
|
-
i++;
|
|
37638
|
-
while (i < lines.length && !FENCE_RE.test(lines[i])) {
|
|
37639
|
-
body.push(lines[i]);
|
|
37640
|
-
i++;
|
|
37641
|
-
}
|
|
37642
|
-
i++;
|
|
37643
|
-
elements.push({
|
|
37644
|
-
type: 'code',
|
|
37645
|
-
props: { code: body.join('\n'), language: lang, theme: 'dark' },
|
|
37646
|
-
});
|
|
37647
|
-
continue;
|
|
37648
|
-
}
|
|
37649
|
-
if (BOX_DRAWING.test(line)) {
|
|
37650
|
-
const body = [];
|
|
37651
|
-
while (i < lines.length && (lines[i].trim() === '' || BOX_DRAWING.test(lines[i]))) {
|
|
37652
|
-
body.push(lines[i]);
|
|
37653
|
-
i++;
|
|
37654
|
-
}
|
|
37655
|
-
while (body.length && body[body.length - 1].trim() === '')
|
|
37656
|
-
body.pop();
|
|
37657
|
-
elements.push({
|
|
37658
|
-
type: 'code',
|
|
37659
|
-
props: { code: body.join('\n'), language: 'text', theme: 'dark' },
|
|
37660
|
-
});
|
|
37661
|
-
continue;
|
|
37662
|
-
}
|
|
37663
|
-
if (SEPARATOR_RE.test(line)) {
|
|
37664
|
-
elements.push({ type: 'separator', props: { style: 'line' } });
|
|
37665
|
-
i++;
|
|
37666
|
-
continue;
|
|
37667
|
-
}
|
|
37668
|
-
const heading = line.match(HEADING_RE);
|
|
37669
|
-
if (heading) {
|
|
37670
|
-
elements.push(makeHeading(heading[1].length, heading[2].trim()));
|
|
37671
|
-
i++;
|
|
37672
|
-
continue;
|
|
37673
|
-
}
|
|
37674
|
-
if (line.startsWith('>')) {
|
|
37675
|
-
const block = [];
|
|
37676
|
-
while (i < lines.length && lines[i].startsWith('>')) {
|
|
37677
|
-
block.push(lines[i]);
|
|
37678
|
-
i++;
|
|
37679
|
-
}
|
|
37680
|
-
elements.push(makeQuoteOrCallout(block, labels));
|
|
37681
|
-
continue;
|
|
37682
|
-
}
|
|
37683
|
-
if (TABLE_ROW_RE.test(line)) {
|
|
37684
|
-
const rows = [];
|
|
37685
|
-
while (i < lines.length && TABLE_ROW_RE.test(lines[i])) {
|
|
37686
|
-
rows.push(lines[i]);
|
|
37687
|
-
i++;
|
|
37688
|
-
}
|
|
37689
|
-
elements.push(...makeTable(rows));
|
|
37690
|
-
continue;
|
|
37691
|
-
}
|
|
37692
|
-
if (CHECKLIST_RE.test(line) || UNORDERED_RE.test(line) || ORDERED_RE.test(line)) {
|
|
37693
|
-
const listType = CHECKLIST_RE.test(line)
|
|
37694
|
-
? 'checklist'
|
|
37695
|
-
: ORDERED_RE.test(line)
|
|
37696
|
-
? 'ordered'
|
|
37697
|
-
: 'unordered';
|
|
37698
|
-
const items = [];
|
|
37699
|
-
while (i < lines.length && lines[i].trim() !== '') {
|
|
37700
|
-
const cur = lines[i];
|
|
37701
|
-
const check = cur.match(CHECKLIST_RE);
|
|
37702
|
-
const unord = cur.match(UNORDERED_RE);
|
|
37703
|
-
const ord = cur.match(ORDERED_RE);
|
|
37704
|
-
if (check)
|
|
37705
|
-
items.push({ text: check[2].trim() });
|
|
37706
|
-
else if (ord && listType === 'ordered')
|
|
37707
|
-
items.push({ text: ord[1].trim() });
|
|
37708
|
-
else if (unord && listType !== 'ordered')
|
|
37709
|
-
items.push({ text: unord[1].trim() });
|
|
37710
|
-
else
|
|
37711
|
-
break;
|
|
37712
|
-
i++;
|
|
37713
|
-
}
|
|
37714
|
-
elements.push({ type: 'list', props: { items, listType } });
|
|
37715
|
-
continue;
|
|
37716
|
-
}
|
|
37717
|
-
const paragraph = [];
|
|
37718
|
-
while (i < lines.length && lines[i].trim() !== '' && !startsNewBlock(lines[i])) {
|
|
37719
|
-
paragraph.push(lines[i]);
|
|
37720
|
-
i++;
|
|
37721
|
-
}
|
|
37722
|
-
const text = paragraph.join(' ').trim();
|
|
37723
|
-
if (text) {
|
|
37724
|
-
elements.push({
|
|
37725
|
-
type: 'paragraph',
|
|
37726
|
-
props: {
|
|
37727
|
-
content: text,
|
|
37728
|
-
size: 'medium',
|
|
37729
|
-
color: 'dark',
|
|
37730
|
-
bold: false,
|
|
37731
|
-
processLinks: true,
|
|
37732
|
-
allowPartialBold: true,
|
|
37733
|
-
},
|
|
37734
|
-
});
|
|
37735
|
-
}
|
|
37736
|
-
}
|
|
37737
|
-
// Strip parser-only options before merging into ArticleMetadata
|
|
37738
|
-
const { locale: _l, calloutLabels: _c, ...metadataOverrides } = options ?? {};
|
|
37739
|
-
return {
|
|
37740
|
-
elements,
|
|
37741
|
-
maxWidth: '900px',
|
|
37742
|
-
centered: true,
|
|
37743
|
-
theme: 'auto',
|
|
37744
|
-
...metadataOverrides,
|
|
37745
|
-
};
|
|
37746
|
-
}
|
|
37747
|
-
function normalize(md) {
|
|
37748
|
-
return md.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
|
37749
|
-
}
|
|
37750
|
-
function startsNewBlock(line) {
|
|
37751
|
-
return (HEADING_RE.test(line) ||
|
|
37752
|
-
FENCE_RE.test(line) ||
|
|
37753
|
-
SEPARATOR_RE.test(line) ||
|
|
37754
|
-
TABLE_ROW_RE.test(line) ||
|
|
37755
|
-
UNORDERED_RE.test(line) ||
|
|
37756
|
-
ORDERED_RE.test(line) ||
|
|
37757
|
-
CHECKLIST_RE.test(line) ||
|
|
37758
|
-
line.startsWith('>') ||
|
|
37759
|
-
BOX_DRAWING.test(line));
|
|
37760
|
-
}
|
|
37761
|
-
function makeHeading(level, content) {
|
|
37762
|
-
if (level === 1) {
|
|
37763
|
-
return {
|
|
37764
|
-
type: 'title',
|
|
37765
|
-
props: { content, size: 'xlarge', color: 'dark', bold: true },
|
|
37766
|
-
};
|
|
37767
|
-
}
|
|
37768
|
-
const size = level === 2 ? 'large' : level === 3 ? 'medium' : 'small';
|
|
37769
|
-
return {
|
|
37770
|
-
type: 'subtitle',
|
|
37771
|
-
props: { content, size, color: 'dark', bold: true },
|
|
37772
|
-
};
|
|
37773
|
-
}
|
|
37774
|
-
function makeQuoteOrCallout(block, labels) {
|
|
37775
|
-
const first = block[0];
|
|
37776
|
-
const callout = first.match(CALLOUT_RE);
|
|
37777
|
-
const lines = block.map(l => l.replace(/^>\s?/, ''));
|
|
37778
|
-
if (callout) {
|
|
37779
|
-
const type = callout[1].toUpperCase();
|
|
37780
|
-
const firstLineRest = callout[2] || '';
|
|
37781
|
-
const rest = lines.slice(1).join(' ').trim();
|
|
37782
|
-
const text = [firstLineRest, rest].filter(Boolean).join(' ').trim();
|
|
37783
|
-
return makeNote(type, text, labels);
|
|
37784
|
-
}
|
|
37785
|
-
const text = lines.join(' ').trim();
|
|
37786
|
-
return {
|
|
37787
|
-
type: 'quote',
|
|
37788
|
-
props: {
|
|
37789
|
-
content: text,
|
|
37790
|
-
size: 'medium',
|
|
37791
|
-
color: 'medium',
|
|
37792
|
-
bold: false,
|
|
37793
|
-
showQuoteMark: true,
|
|
37794
|
-
alignment: 'left',
|
|
37795
|
-
},
|
|
37796
|
-
};
|
|
37797
|
-
}
|
|
37798
|
-
function makeNote(kind, text, labels) {
|
|
37799
|
-
return {
|
|
37800
|
-
type: 'note',
|
|
37801
|
-
props: {
|
|
37802
|
-
text,
|
|
37803
|
-
prefix: `${labels[kind]}:`,
|
|
37804
|
-
color: CALLOUT_COLORS[kind],
|
|
37805
|
-
textColor: 'dark',
|
|
37806
|
-
size: 'medium',
|
|
37807
|
-
rounded: true,
|
|
37808
|
-
allowPartialBold: true,
|
|
37809
|
-
processLinks: true,
|
|
37810
|
-
},
|
|
37811
|
-
};
|
|
37812
|
-
}
|
|
37813
|
-
function makeTable(rows) {
|
|
37814
|
-
const parsed = rows
|
|
37815
|
-
.filter(r => !TABLE_DIVIDER_RE.test(r))
|
|
37816
|
-
.map(r => r
|
|
37817
|
-
.trim()
|
|
37818
|
-
.replace(/^\|/, '')
|
|
37819
|
-
.replace(/\|$/, '')
|
|
37820
|
-
.split('|')
|
|
37821
|
-
.map(c => c.trim()));
|
|
37822
|
-
if (parsed.length === 0)
|
|
37823
|
-
return [];
|
|
37824
|
-
const header = parsed[0];
|
|
37825
|
-
const dataRows = parsed.slice(1);
|
|
37826
|
-
if (dataRows.length === 0) {
|
|
37827
|
-
return [
|
|
37828
|
-
{
|
|
37829
|
-
type: 'paragraph',
|
|
37830
|
-
props: {
|
|
37831
|
-
content: header.join(' · '),
|
|
37832
|
-
size: 'medium',
|
|
37833
|
-
color: 'dark',
|
|
37834
|
-
bold: false,
|
|
37835
|
-
processLinks: true,
|
|
37836
|
-
allowPartialBold: true,
|
|
37837
|
-
},
|
|
37838
|
-
},
|
|
37839
|
-
];
|
|
37840
|
-
}
|
|
37841
|
-
return dataRows.map(row => {
|
|
37842
|
-
const pairs = row.map((cell, idx) => {
|
|
37843
|
-
const key = header[idx] ?? '';
|
|
37844
|
-
return key ? `**${key}:** ${cell}` : cell;
|
|
37845
|
-
});
|
|
37846
|
-
return {
|
|
37847
|
-
type: 'paragraph',
|
|
37848
|
-
props: {
|
|
37849
|
-
content: pairs.join(' · '),
|
|
37850
|
-
size: 'medium',
|
|
37851
|
-
color: 'dark',
|
|
37852
|
-
bold: false,
|
|
37853
|
-
processLinks: true,
|
|
37854
|
-
allowPartialBold: true,
|
|
37855
|
-
},
|
|
37856
|
-
};
|
|
37857
|
-
});
|
|
37858
|
-
}
|
|
37859
|
-
|
|
37860
37898
|
/**
|
|
37861
37899
|
* Angular service wrapper for the pure {@link parseMarkdownArticle} function.
|
|
37862
37900
|
* Provided in root so it can be injected anywhere. The actual parsing logic lives in
|
|
@@ -45600,7 +45638,9 @@ const VALTECH_COMPANY_LINKS = {
|
|
|
45600
45638
|
],
|
|
45601
45639
|
support: [
|
|
45602
45640
|
{ key: 'contactSupport', url: '/contact', kind: 'support', external: false },
|
|
45603
|
-
|
|
45641
|
+
// FAQ — página dedicada `/faq` (kind 'site': vive en el sitio corporativo;
|
|
45642
|
+
// en apps satellite se reescribe al main site vía LegalLinkService).
|
|
45643
|
+
{ key: 'faq', url: '/faq', kind: 'site', external: false },
|
|
45604
45644
|
{ key: 'feedback', url: '/feedback', kind: 'support', external: false },
|
|
45605
45645
|
],
|
|
45606
45646
|
};
|