@noirmd/previewer 2.1.4 → 2.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/NReditor.cjs +153 -161
- package/dist/NReditor.cjs.map +1 -1
- package/dist/NReditor.js +153 -161
- package/dist/NReditor.js.map +1 -1
- package/dist/button.css +6 -0
- package/dist/card.css +5 -5
- package/dist/core.cjs +31 -20
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +1 -0
- package/dist/core.d.ts +1 -0
- package/dist/core.js +31 -20
- package/dist/core.js.map +1 -1
- package/dist/hover3d.css +1 -1
- package/dist/index.cjs +151 -159
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +151 -159
- package/dist/index.js.map +1 -1
- package/dist/modal.css +7 -1
- package/dist/react.cjs +153 -161
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -0
- package/dist/react.d.ts +1 -0
- package/dist/react.js +153 -161
- package/dist/react.js.map +1 -1
- package/dist/vanilla.cjs +151 -159
- package/dist/vanilla.cjs.map +1 -1
- package/dist/vanilla.d.cts +1 -0
- package/dist/vanilla.d.ts +1 -0
- package/dist/vanilla.js +151 -159
- package/dist/vanilla.js.map +1 -1
- package/dist/vue.cjs +151 -159
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.d.cts +1 -0
- package/dist/vue.d.ts +1 -0
- package/dist/vue.js +151 -159
- package/dist/vue.js.map +1 -1
- package/package.json +1 -1
package/dist/NReditor.js
CHANGED
|
@@ -531,6 +531,22 @@ function parseHtmlAttrs(attrsString) {
|
|
|
531
531
|
}
|
|
532
532
|
|
|
533
533
|
// core/parser.ts
|
|
534
|
+
var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
535
|
+
"area",
|
|
536
|
+
"base",
|
|
537
|
+
"br",
|
|
538
|
+
"col",
|
|
539
|
+
"embed",
|
|
540
|
+
"hr",
|
|
541
|
+
"img",
|
|
542
|
+
"input",
|
|
543
|
+
"link",
|
|
544
|
+
"meta",
|
|
545
|
+
"param",
|
|
546
|
+
"source",
|
|
547
|
+
"track",
|
|
548
|
+
"wbr"
|
|
549
|
+
]);
|
|
534
550
|
function parseMarkdown(markdown2) {
|
|
535
551
|
if (!markdown2) return [];
|
|
536
552
|
const lines = markdown2.replace(/\r\n/g, "\n").replace(/\r/g, "").split("\n");
|
|
@@ -544,8 +560,19 @@ function parseMarkdown(markdown2) {
|
|
|
544
560
|
if (match = trimmed.match(/^(#{1,6})\s+(.+)$/)) {
|
|
545
561
|
const level = match[1].length;
|
|
546
562
|
const rawText = match[2];
|
|
547
|
-
const { text:
|
|
548
|
-
|
|
563
|
+
const { text: rawParsedText, classes: classes2, id: customId } = extractAttributes(rawText);
|
|
564
|
+
let text2 = rawParsedText;
|
|
565
|
+
let align;
|
|
566
|
+
const alignCenter = text2.match(/^->\s*(.+?)\s*<-\s*$/);
|
|
567
|
+
const alignRight = text2.match(/^->\s*(.+?)\s*->\s*$/);
|
|
568
|
+
if (alignCenter) {
|
|
569
|
+
text2 = alignCenter[1];
|
|
570
|
+
align = "center";
|
|
571
|
+
} else if (alignRight) {
|
|
572
|
+
text2 = alignRight[1];
|
|
573
|
+
align = "right";
|
|
574
|
+
}
|
|
575
|
+
const baseId = customId || generateId(text2);
|
|
549
576
|
let id2 = baseId;
|
|
550
577
|
let n = 1;
|
|
551
578
|
while (usedIds.has(id2)) {
|
|
@@ -553,7 +580,7 @@ function parseMarkdown(markdown2) {
|
|
|
553
580
|
id2 = `${baseId}-${n}`;
|
|
554
581
|
}
|
|
555
582
|
usedIds.add(id2);
|
|
556
|
-
result.push({ type: "header", level, text: text2, id: id2, classes: classes2 || void 0 });
|
|
583
|
+
result.push({ type: "header", level, text: text2, id: id2, classes: classes2 || void 0, align });
|
|
557
584
|
i++;
|
|
558
585
|
continue;
|
|
559
586
|
}
|
|
@@ -729,29 +756,13 @@ function parseMarkdown(markdown2) {
|
|
|
729
756
|
let tagStartMatch = trimmed.match(/^<([a-zA-Z][\w-]*)/);
|
|
730
757
|
if (tagStartMatch) {
|
|
731
758
|
const tagName = tagStartMatch[1].toLowerCase();
|
|
732
|
-
const voidElements = /* @__PURE__ */ new Set([
|
|
733
|
-
"area",
|
|
734
|
-
"base",
|
|
735
|
-
"br",
|
|
736
|
-
"col",
|
|
737
|
-
"embed",
|
|
738
|
-
"hr",
|
|
739
|
-
"img",
|
|
740
|
-
"input",
|
|
741
|
-
"link",
|
|
742
|
-
"meta",
|
|
743
|
-
"param",
|
|
744
|
-
"source",
|
|
745
|
-
"track",
|
|
746
|
-
"wbr"
|
|
747
|
-
]);
|
|
748
759
|
const remainingText = lines.slice(i).join("\n");
|
|
749
760
|
const openTagRegex = new RegExp(`^\\s*<${tagName}\\b([^>]*?)>`, "i");
|
|
750
761
|
const openTagMatch = remainingText.match(openTagRegex);
|
|
751
762
|
if (openTagMatch) {
|
|
752
763
|
const fullOpenTag = openTagMatch[0];
|
|
753
764
|
const attrs = openTagMatch[1].replace(/\s+/g, " ").trim();
|
|
754
|
-
const isSelfClosing = fullOpenTag.endsWith("/>") ||
|
|
765
|
+
const isSelfClosing = fullOpenTag.endsWith("/>") || VOID_ELEMENTS.has(tagName);
|
|
755
766
|
if (isSelfClosing) {
|
|
756
767
|
const blockText = remainingText.substring(0, openTagMatch.index + fullOpenTag.length);
|
|
757
768
|
const consumedLines = blockText.split("\n").length;
|
|
@@ -1274,11 +1285,77 @@ function parseInlinePart(part) {
|
|
|
1274
1285
|
return document.createTextNode(part);
|
|
1275
1286
|
}
|
|
1276
1287
|
|
|
1288
|
+
// vanilla/utils.ts
|
|
1289
|
+
var THEME_TOKENS = /* @__PURE__ */ new Set([
|
|
1290
|
+
"primary",
|
|
1291
|
+
"secondary",
|
|
1292
|
+
"accent",
|
|
1293
|
+
"neutral",
|
|
1294
|
+
"info",
|
|
1295
|
+
"success",
|
|
1296
|
+
"warning",
|
|
1297
|
+
"error"
|
|
1298
|
+
]);
|
|
1299
|
+
function isThemeToken(color) {
|
|
1300
|
+
return !!color && THEME_TOKENS.has(color);
|
|
1301
|
+
}
|
|
1302
|
+
function isArbitraryColor(value) {
|
|
1303
|
+
if (THEME_TOKENS.has(value)) return false;
|
|
1304
|
+
if (/^(#|rgb|hsl|oklch|oklab|lab|lch|color\()/i.test(value)) return true;
|
|
1305
|
+
if (/^[a-zA-Z]+$/.test(value)) return true;
|
|
1306
|
+
return false;
|
|
1307
|
+
}
|
|
1308
|
+
function applyBaseProps(el, props) {
|
|
1309
|
+
if (props.class) {
|
|
1310
|
+
el.classList.add(...props.class.split(/\s+/).filter(Boolean));
|
|
1311
|
+
}
|
|
1312
|
+
if (props.style) {
|
|
1313
|
+
const styles = parseCssString(props.style);
|
|
1314
|
+
for (const [key, value] of Object.entries(styles)) {
|
|
1315
|
+
el.style.setProperty(key, String(value));
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
function applyFloatStyle(el, float, width) {
|
|
1320
|
+
if (!float) return;
|
|
1321
|
+
if (float === "left" || float === "right") {
|
|
1322
|
+
el.style.float = float;
|
|
1323
|
+
if (!width) el.style.maxWidth = "50%";
|
|
1324
|
+
el.style.marginInlineStart = float === "right" ? "1rem" : "";
|
|
1325
|
+
el.style.marginInlineEnd = float === "left" ? "1rem" : "";
|
|
1326
|
+
} else if (float === "center") {
|
|
1327
|
+
el.style.marginInline = "auto";
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
function applyColor(el, color, classSuffix) {
|
|
1331
|
+
if (!color) return "";
|
|
1332
|
+
if (isThemeToken(color)) {
|
|
1333
|
+
return ` ${classSuffix}--${color}`;
|
|
1334
|
+
}
|
|
1335
|
+
if (isArbitraryColor(color)) {
|
|
1336
|
+
el.style.background = color;
|
|
1337
|
+
el.style.color = "white";
|
|
1338
|
+
}
|
|
1339
|
+
return "";
|
|
1340
|
+
}
|
|
1341
|
+
function openModal(dialog) {
|
|
1342
|
+
if (!dialog.open) {
|
|
1343
|
+
document.body.appendChild(dialog);
|
|
1344
|
+
dialog.showModal();
|
|
1345
|
+
dialog.addEventListener("close", () => dialog.remove(), { once: true });
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
var IMG_RE = /!\[([^\]]*)\]\(([^)]+)\)/g;
|
|
1349
|
+
function parseIntProp(value, defaultValue) {
|
|
1350
|
+
if (!value) return defaultValue;
|
|
1351
|
+
const n = parseInt(value, 10);
|
|
1352
|
+
return Number.isNaN(n) ? defaultValue : n;
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1277
1355
|
// vanilla/directives/admonition.ts
|
|
1278
1356
|
var admonitionDirective = ({ directiveType, props, renderSlot }) => {
|
|
1279
1357
|
const el = createAdmonition(directiveType, props.title, props.icon);
|
|
1280
|
-
|
|
1281
|
-
if (props.style) el.setAttribute("style", props.style);
|
|
1358
|
+
applyBaseProps(el, props);
|
|
1282
1359
|
const body = el.querySelector(".nr-admonition__body");
|
|
1283
1360
|
if (body) {
|
|
1284
1361
|
body.appendChild(renderSlot("default"));
|
|
@@ -1294,8 +1371,7 @@ var detailsDirective = ({ props, renderSlot }) => {
|
|
|
1294
1371
|
props.icon,
|
|
1295
1372
|
props.defaultOpen === "true"
|
|
1296
1373
|
);
|
|
1297
|
-
|
|
1298
|
-
if (props.style) el.setAttribute("style", props.style);
|
|
1374
|
+
applyBaseProps(el, props);
|
|
1299
1375
|
const body = el.querySelector(".nr-details__body");
|
|
1300
1376
|
if (body) {
|
|
1301
1377
|
body.appendChild(renderSlot("default"));
|
|
@@ -1308,12 +1384,12 @@ var details_default = detailsDirective;
|
|
|
1308
1384
|
var modalDirective = ({ props, renderSlot }) => {
|
|
1309
1385
|
const label = props.label || props.title || "Open";
|
|
1310
1386
|
const modalTitle = props.title || "Modal";
|
|
1311
|
-
const
|
|
1387
|
+
const align = props.align || "left";
|
|
1312
1388
|
const wrapper = document.createElement("div");
|
|
1313
|
-
wrapper.className = "nr-modal-trigger"
|
|
1389
|
+
wrapper.className = `nr-modal-trigger${align === "center" ? " nr-modal-trigger--center" : align === "right" ? " nr-modal-trigger--right" : ""}`;
|
|
1314
1390
|
const btn = document.createElement("button");
|
|
1315
1391
|
btn.className = `nr-button nr-button--default`;
|
|
1316
|
-
|
|
1392
|
+
applyBaseProps(btn, props);
|
|
1317
1393
|
const icon = props.icon || "open_in_new";
|
|
1318
1394
|
if (icon) btn.appendChild(createIcon(icon));
|
|
1319
1395
|
btn.appendChild(document.createTextNode(label));
|
|
@@ -1325,15 +1401,7 @@ var modalDirective = ({ props, renderSlot }) => {
|
|
|
1325
1401
|
prose.appendChild(renderSlot("default"));
|
|
1326
1402
|
body.appendChild(prose);
|
|
1327
1403
|
}
|
|
1328
|
-
btn.addEventListener("click", () =>
|
|
1329
|
-
if (!dialog.open) {
|
|
1330
|
-
document.body.appendChild(dialog);
|
|
1331
|
-
dialog.showModal();
|
|
1332
|
-
dialog.addEventListener("close", () => {
|
|
1333
|
-
dialog.remove();
|
|
1334
|
-
}, { once: true });
|
|
1335
|
-
}
|
|
1336
|
-
});
|
|
1404
|
+
btn.addEventListener("click", () => openModal(dialog));
|
|
1337
1405
|
wrapper.appendChild(btn);
|
|
1338
1406
|
wrapper.appendChild(dialog);
|
|
1339
1407
|
return wrapper;
|
|
@@ -1343,19 +1411,20 @@ var modal_default = modalDirective;
|
|
|
1343
1411
|
// vanilla/directives/button.ts
|
|
1344
1412
|
var buttonDirective = ({ props, renderSlot }) => {
|
|
1345
1413
|
const url = props.url || props.href || "#";
|
|
1346
|
-
const label = props.label;
|
|
1414
|
+
const label = props.label || props.title;
|
|
1347
1415
|
const icon = props.icon || "near_me";
|
|
1348
1416
|
const target = props.target || "_blank";
|
|
1349
1417
|
const customClass = props.class || "";
|
|
1418
|
+
const align = props.align || "left";
|
|
1350
1419
|
const wrapper = document.createElement("div");
|
|
1351
|
-
wrapper.className = "nr-button-wrap"
|
|
1420
|
+
wrapper.className = `nr-button-wrap${align === "center" ? " nr-button-wrap--center" : align === "right" ? " nr-button-wrap--right" : ""}`;
|
|
1352
1421
|
if (label) {
|
|
1353
1422
|
const a = document.createElement("a");
|
|
1354
1423
|
a.href = url;
|
|
1355
1424
|
a.target = target;
|
|
1356
1425
|
a.rel = "noopener noreferrer";
|
|
1357
1426
|
a.className = "nr-button nr-button--default";
|
|
1358
|
-
|
|
1427
|
+
applyBaseProps(a, props);
|
|
1359
1428
|
a.appendChild(createIcon(icon));
|
|
1360
1429
|
a.appendChild(document.createTextNode(label));
|
|
1361
1430
|
wrapper.appendChild(a);
|
|
@@ -1366,7 +1435,7 @@ var buttonDirective = ({ props, renderSlot }) => {
|
|
|
1366
1435
|
if (links.length > 0) {
|
|
1367
1436
|
links.forEach((link) => {
|
|
1368
1437
|
link.classList.add("nr-button", "nr-button--default");
|
|
1369
|
-
|
|
1438
|
+
applyBaseProps(link, props);
|
|
1370
1439
|
});
|
|
1371
1440
|
wrapper.appendChild(slotContent);
|
|
1372
1441
|
} else {
|
|
@@ -1375,7 +1444,7 @@ var buttonDirective = ({ props, renderSlot }) => {
|
|
|
1375
1444
|
a.target = target;
|
|
1376
1445
|
a.rel = "noopener noreferrer";
|
|
1377
1446
|
a.className = "nr-button nr-button--default";
|
|
1378
|
-
|
|
1447
|
+
applyBaseProps(a, props);
|
|
1379
1448
|
a.appendChild(createIcon(icon));
|
|
1380
1449
|
a.appendChild(slotContent);
|
|
1381
1450
|
wrapper.appendChild(a);
|
|
@@ -1398,12 +1467,9 @@ var cardDirective = ({
|
|
|
1398
1467
|
const { isSingleCard } = options || {};
|
|
1399
1468
|
const isModal = directiveType === "card-m";
|
|
1400
1469
|
const isLink = directiveType === "card-b";
|
|
1401
|
-
const inlineStyles = props.style ? parseCssString(props.style) : {};
|
|
1402
1470
|
const card = document.createElement("div");
|
|
1403
1471
|
card.className = `nr-card${isModal || isLink ? " nr-card--interactive" : ""} ${customClass}`.trim();
|
|
1404
|
-
|
|
1405
|
-
card.style.setProperty(key, String(value));
|
|
1406
|
-
}
|
|
1472
|
+
applyBaseProps(card, props);
|
|
1407
1473
|
if (image) {
|
|
1408
1474
|
const imgWrap = document.createElement("div");
|
|
1409
1475
|
imgWrap.className = `nr-card__image${isSingleCard ? " nr-card__image--tall" : ""}`;
|
|
@@ -1482,13 +1548,7 @@ var cardDirective = ({
|
|
|
1482
1548
|
prose.appendChild(renderSlot("content") || renderSlot("default"));
|
|
1483
1549
|
modalBody.appendChild(prose);
|
|
1484
1550
|
}
|
|
1485
|
-
card.addEventListener("click", () =>
|
|
1486
|
-
if (!dialog.open) {
|
|
1487
|
-
document.body.appendChild(dialog);
|
|
1488
|
-
dialog.showModal();
|
|
1489
|
-
dialog.addEventListener("close", () => dialog.remove(), { once: true });
|
|
1490
|
-
}
|
|
1491
|
-
});
|
|
1551
|
+
card.addEventListener("click", () => openModal(dialog));
|
|
1492
1552
|
const frag = document.createDocumentFragment();
|
|
1493
1553
|
frag.appendChild(card);
|
|
1494
1554
|
frag.appendChild(dialog);
|
|
@@ -1536,8 +1596,8 @@ var slideDirective = ({
|
|
|
1536
1596
|
if (lines.length === 0) {
|
|
1537
1597
|
return document.createDocumentFragment();
|
|
1538
1598
|
}
|
|
1539
|
-
const interval =
|
|
1540
|
-
const speed =
|
|
1599
|
+
const interval = parseIntProp(props.interval, 3e3);
|
|
1600
|
+
const speed = parseIntProp(props.speed, 500);
|
|
1541
1601
|
const rawClass = props.class || "";
|
|
1542
1602
|
const inlineStyle = props.style ? parseCssString(props.style) : {};
|
|
1543
1603
|
const scopeClass = `sld-${++slideCounter}`;
|
|
@@ -1588,10 +1648,11 @@ var slideDirective = ({
|
|
|
1588
1648
|
}
|
|
1589
1649
|
});
|
|
1590
1650
|
if (lines.length > 1) {
|
|
1591
|
-
setInterval(() => {
|
|
1651
|
+
const id = setInterval(() => {
|
|
1592
1652
|
current = (current + 1) % lines.length;
|
|
1593
1653
|
track.style.transform = `translateY(${-current * maxH}px)`;
|
|
1594
1654
|
}, interval);
|
|
1655
|
+
container.dataset.nrIntervalId = String(id);
|
|
1595
1656
|
}
|
|
1596
1657
|
return container;
|
|
1597
1658
|
};
|
|
@@ -1601,8 +1662,7 @@ var slide_default = slideDirective;
|
|
|
1601
1662
|
var keysDirective = ({ props, slots }) => {
|
|
1602
1663
|
const wrap = document.createElement("div");
|
|
1603
1664
|
wrap.className = "nr-keys";
|
|
1604
|
-
|
|
1605
|
-
if (props.style) wrap.setAttribute("style", props.style);
|
|
1665
|
+
applyBaseProps(wrap, props);
|
|
1606
1666
|
const sizeClass = props.size ? ` nr-kbd--${props.size}` : "";
|
|
1607
1667
|
const parts = (slots.default || "").split("+").map((p) => p.trim()).filter(Boolean);
|
|
1608
1668
|
parts.forEach((part, i) => {
|
|
@@ -1626,8 +1686,7 @@ var accordionCounter = 0;
|
|
|
1626
1686
|
var accordionItemDirective = ({ props, renderSlot }) => {
|
|
1627
1687
|
const item = document.createElement("div");
|
|
1628
1688
|
item.className = "nr-accordion__item";
|
|
1629
|
-
|
|
1630
|
-
if (props.style) item.setAttribute("style", props.style);
|
|
1689
|
+
applyBaseProps(item, props);
|
|
1631
1690
|
const input = document.createElement("input");
|
|
1632
1691
|
input.type = "radio";
|
|
1633
1692
|
input.className = "nr-accordion__input";
|
|
@@ -1646,8 +1705,7 @@ var accordionItemDirective = ({ props, renderSlot }) => {
|
|
|
1646
1705
|
var accordionDirective = ({ props, renderSlot }) => {
|
|
1647
1706
|
const wrap = document.createElement("div");
|
|
1648
1707
|
wrap.className = "nr-accordion";
|
|
1649
|
-
|
|
1650
|
-
if (props.style) wrap.setAttribute("style", props.style);
|
|
1708
|
+
applyBaseProps(wrap, props);
|
|
1651
1709
|
wrap.appendChild(renderSlot("default"));
|
|
1652
1710
|
const mode = props.mode === "checkbox" ? "checkbox" : "radio";
|
|
1653
1711
|
const group = `nr-acc-${++accordionCounter}`;
|
|
@@ -1660,7 +1718,6 @@ var accordionDirective = ({ props, renderSlot }) => {
|
|
|
1660
1718
|
var accordion_default = accordionDirective;
|
|
1661
1719
|
|
|
1662
1720
|
// vanilla/directives/carousel.ts
|
|
1663
|
-
var IMG_RE = /!\[([^\]]*)\]\(([^)]+)\)/g;
|
|
1664
1721
|
var carouselDirective = ({ props, slots }) => {
|
|
1665
1722
|
const images = [];
|
|
1666
1723
|
const raw = slots.default || "";
|
|
@@ -1676,19 +1733,9 @@ var carouselDirective = ({ props, slots }) => {
|
|
|
1676
1733
|
wrap.className = "nr-carousel";
|
|
1677
1734
|
wrap.tabIndex = 0;
|
|
1678
1735
|
wrap.setAttribute("aria-label", "Image carousel");
|
|
1679
|
-
|
|
1680
|
-
if (props.style) wrap.setAttribute("style", props.style);
|
|
1736
|
+
applyBaseProps(wrap, props);
|
|
1681
1737
|
if (props.width) wrap.style.width = props.width;
|
|
1682
|
-
|
|
1683
|
-
if (props.float === "left" || props.float === "right") {
|
|
1684
|
-
wrap.style.float = props.float;
|
|
1685
|
-
if (!props.width) wrap.style.maxWidth = "50%";
|
|
1686
|
-
wrap.style.marginInlineStart = props.float === "right" ? "1rem" : "";
|
|
1687
|
-
wrap.style.marginInlineEnd = props.float === "left" ? "1rem" : "";
|
|
1688
|
-
} else if (props.float === "center") {
|
|
1689
|
-
wrap.style.marginInline = "auto";
|
|
1690
|
-
}
|
|
1691
|
-
}
|
|
1738
|
+
applyFloatStyle(wrap, props.float, props.width);
|
|
1692
1739
|
const viewport = document.createElement("div");
|
|
1693
1740
|
viewport.className = "nr-carousel__viewport";
|
|
1694
1741
|
if (props.height) viewport.style.height = props.height;
|
|
@@ -1758,11 +1805,10 @@ var DEFAULT_LABELS = ["days", "hours", "min", "sec"];
|
|
|
1758
1805
|
var countdownDirective = ({ props }) => {
|
|
1759
1806
|
const wrap = document.createElement("div");
|
|
1760
1807
|
wrap.className = "nr-countdown";
|
|
1761
|
-
|
|
1762
|
-
if (props.style) wrap.setAttribute("style", props.style);
|
|
1808
|
+
applyBaseProps(wrap, props);
|
|
1763
1809
|
const labelParts = (props.labels || "").split("|").map((s) => s.trim());
|
|
1764
1810
|
const labels = DEFAULT_LABELS.map((label, i) => labelParts[i] || label);
|
|
1765
|
-
const digits =
|
|
1811
|
+
const digits = parseIntProp(props.digits, 2);
|
|
1766
1812
|
const targetTime = props.target ? new Date(props.target).getTime() : NaN;
|
|
1767
1813
|
const hasTarget = !Number.isNaN(targetTime);
|
|
1768
1814
|
const blocks = [];
|
|
@@ -1809,13 +1855,15 @@ var countdownDirective = ({ props }) => {
|
|
|
1809
1855
|
blocks.push({ value });
|
|
1810
1856
|
});
|
|
1811
1857
|
render();
|
|
1812
|
-
if (hasTarget)
|
|
1858
|
+
if (hasTarget) {
|
|
1859
|
+
const id = setInterval(render, 1e3);
|
|
1860
|
+
wrap.dataset.nrIntervalId = String(id);
|
|
1861
|
+
}
|
|
1813
1862
|
return wrap;
|
|
1814
1863
|
};
|
|
1815
1864
|
var countdown_default = countdownDirective;
|
|
1816
1865
|
|
|
1817
1866
|
// vanilla/directives/diff.ts
|
|
1818
|
-
var IMG_RE2 = /!\[([^\]]*)\]\(([^)]+)\)/g;
|
|
1819
1867
|
var diffDirective = ({ props, slots }) => {
|
|
1820
1868
|
let before = (props.before || "").split("#")[0].trim();
|
|
1821
1869
|
let after = (props.after || "").split("#")[0].trim();
|
|
@@ -1823,8 +1871,8 @@ var diffDirective = ({ props, slots }) => {
|
|
|
1823
1871
|
const urls = [];
|
|
1824
1872
|
const raw = slots.default || "";
|
|
1825
1873
|
let m;
|
|
1826
|
-
|
|
1827
|
-
while ((m =
|
|
1874
|
+
IMG_RE.lastIndex = 0;
|
|
1875
|
+
while ((m = IMG_RE.exec(raw)) !== null) {
|
|
1828
1876
|
urls.push(m[2].split("#")[0].trim());
|
|
1829
1877
|
}
|
|
1830
1878
|
if (!before && urls.length > 0) before = urls[0];
|
|
@@ -1837,21 +1885,11 @@ var diffDirective = ({ props, slots }) => {
|
|
|
1837
1885
|
figure.className = "nr-diff";
|
|
1838
1886
|
figure.tabIndex = 0;
|
|
1839
1887
|
figure.setAttribute("aria-label", "Image comparison slider");
|
|
1840
|
-
|
|
1841
|
-
if (props.style) figure.setAttribute("style", props.style);
|
|
1888
|
+
applyBaseProps(figure, props);
|
|
1842
1889
|
if (props.aspect) figure.style.aspectRatio = props.aspect;
|
|
1843
1890
|
if (props.height) figure.style.height = props.height;
|
|
1844
1891
|
if (props.width) figure.style.width = props.width;
|
|
1845
|
-
|
|
1846
|
-
if (props.float === "left" || props.float === "right") {
|
|
1847
|
-
figure.style.float = props.float;
|
|
1848
|
-
if (!props.width) figure.style.maxWidth = "50%";
|
|
1849
|
-
figure.style.marginInlineStart = props.float === "right" ? "1rem" : "";
|
|
1850
|
-
figure.style.marginInlineEnd = props.float === "left" ? "1rem" : "";
|
|
1851
|
-
} else if (props.float === "center") {
|
|
1852
|
-
figure.style.marginInline = "auto";
|
|
1853
|
-
}
|
|
1854
|
-
}
|
|
1892
|
+
applyFloatStyle(figure, props.float, props.width);
|
|
1855
1893
|
const beforeItem = document.createElement("div");
|
|
1856
1894
|
beforeItem.className = "nr-diff__item nr-diff__item--before";
|
|
1857
1895
|
beforeItem.setAttribute("role", "img");
|
|
@@ -1914,8 +1952,7 @@ var diff_default = diffDirective;
|
|
|
1914
1952
|
var hover3dDirective = ({ props, renderSlot }) => {
|
|
1915
1953
|
const container = document.createElement("div");
|
|
1916
1954
|
container.className = "nr-hover-3d";
|
|
1917
|
-
|
|
1918
|
-
if (props.style) container.setAttribute("style", props.style);
|
|
1955
|
+
applyBaseProps(container, props);
|
|
1919
1956
|
const stage = document.createElement("div");
|
|
1920
1957
|
stage.className = "nr-hover-3d__stage";
|
|
1921
1958
|
stage.appendChild(renderSlot("default"));
|
|
@@ -1928,14 +1965,13 @@ var hover3dDirective = ({ props, renderSlot }) => {
|
|
|
1928
1965
|
var hover3d_default = hover3dDirective;
|
|
1929
1966
|
|
|
1930
1967
|
// vanilla/directives/hovergallery.ts
|
|
1931
|
-
var IMG_RE3 = /!\[([^\]]*)\]\(([^)]+)\)/g;
|
|
1932
1968
|
var MAX_IMAGES = 10;
|
|
1933
1969
|
var hovergalleryDirective = ({ props, slots }) => {
|
|
1934
1970
|
const images = [];
|
|
1935
1971
|
const raw = slots.default || "";
|
|
1936
1972
|
let m;
|
|
1937
|
-
|
|
1938
|
-
while ((m =
|
|
1973
|
+
IMG_RE.lastIndex = 0;
|
|
1974
|
+
while ((m = IMG_RE.exec(raw)) !== null) {
|
|
1939
1975
|
images.push({ src: m[2].split("#")[0].trim(), alt: m[1].trim() || "gallery image" });
|
|
1940
1976
|
}
|
|
1941
1977
|
if (images.length === 0) {
|
|
@@ -1944,9 +1980,8 @@ var hovergalleryDirective = ({ props, slots }) => {
|
|
|
1944
1980
|
const count = Math.min(images.length, MAX_IMAGES);
|
|
1945
1981
|
const figure = document.createElement("figure");
|
|
1946
1982
|
figure.className = "nr-hover-gallery";
|
|
1983
|
+
applyBaseProps(figure, props);
|
|
1947
1984
|
if (props.aspect) figure.style.aspectRatio = props.aspect;
|
|
1948
|
-
if (props.class) figure.classList.add(...props.class.split(/\s+/).filter(Boolean));
|
|
1949
|
-
if (props.style) figure.setAttribute("style", (figure.getAttribute("style") || "") + ";" + props.style);
|
|
1950
1985
|
const imgEls = [];
|
|
1951
1986
|
for (let i = 0; i < count; i++) {
|
|
1952
1987
|
const el = document.createElement("img");
|
|
@@ -1996,28 +2031,11 @@ var hovergalleryDirective = ({ props, slots }) => {
|
|
|
1996
2031
|
var hovergallery_default = hovergalleryDirective;
|
|
1997
2032
|
|
|
1998
2033
|
// vanilla/directives/chat.ts
|
|
1999
|
-
var CHAT_THEME_TOKENS = /* @__PURE__ */ new Set([
|
|
2000
|
-
"primary",
|
|
2001
|
-
"secondary",
|
|
2002
|
-
"accent",
|
|
2003
|
-
"neutral",
|
|
2004
|
-
"info",
|
|
2005
|
-
"success",
|
|
2006
|
-
"warning",
|
|
2007
|
-
"error"
|
|
2008
|
-
]);
|
|
2009
|
-
function isArbitraryColor(value) {
|
|
2010
|
-
if (CHAT_THEME_TOKENS.has(value)) return false;
|
|
2011
|
-
if (/^(#|rgb|hsl|oklch|oklab|lab|lch|color\()/i.test(value)) return true;
|
|
2012
|
-
if (/^[a-zA-Z]+$/.test(value)) return true;
|
|
2013
|
-
return false;
|
|
2014
|
-
}
|
|
2015
2034
|
var chatItemDirective = ({ props, renderSlot }) => {
|
|
2016
2035
|
const side = props.side === "end" ? "end" : "start";
|
|
2017
2036
|
const wrap = document.createElement("div");
|
|
2018
2037
|
wrap.className = `nr-chat nr-chat--${side}`;
|
|
2019
|
-
|
|
2020
|
-
if (props.style) wrap.setAttribute("style", props.style);
|
|
2038
|
+
applyBaseProps(wrap, props);
|
|
2021
2039
|
const header = document.createElement("div");
|
|
2022
2040
|
header.className = "nr-chat__header";
|
|
2023
2041
|
if (props.name) {
|
|
@@ -2042,14 +2060,8 @@ var chatItemDirective = ({ props, renderSlot }) => {
|
|
|
2042
2060
|
avatar.appendChild(img);
|
|
2043
2061
|
wrap.appendChild(avatar);
|
|
2044
2062
|
}
|
|
2045
|
-
const isThemeToken = CHAT_THEME_TOKENS.has(props.color || "");
|
|
2046
|
-
const colorClass = isThemeToken ? ` nr-chat__bubble--${props.color}` : "";
|
|
2047
2063
|
const bubble = document.createElement("div");
|
|
2048
|
-
bubble.className = `nr-chat__bubble${
|
|
2049
|
-
if (props.color && isArbitraryColor(props.color) && !isThemeToken) {
|
|
2050
|
-
bubble.style.background = props.color;
|
|
2051
|
-
bubble.style.color = "white";
|
|
2052
|
-
}
|
|
2064
|
+
bubble.className = `nr-chat__bubble${applyColor(bubble, props.color, "nr-chat__bubble")}`;
|
|
2053
2065
|
bubble.appendChild(renderSlot("default"));
|
|
2054
2066
|
wrap.appendChild(bubble);
|
|
2055
2067
|
if (props.footer) {
|
|
@@ -2063,8 +2075,7 @@ var chatItemDirective = ({ props, renderSlot }) => {
|
|
|
2063
2075
|
var chatDirective = ({ props, renderSlot }) => {
|
|
2064
2076
|
const wrap = document.createElement("div");
|
|
2065
2077
|
wrap.className = "nr-chat";
|
|
2066
|
-
|
|
2067
|
-
if (props.style) wrap.setAttribute("style", props.style);
|
|
2078
|
+
applyBaseProps(wrap, props);
|
|
2068
2079
|
wrap.appendChild(renderSlot("default"));
|
|
2069
2080
|
return wrap;
|
|
2070
2081
|
};
|
|
@@ -2100,8 +2111,7 @@ function bindEventProp(el, eventProp) {
|
|
|
2100
2111
|
var richlistItemDirective = ({ props, renderSlot }) => {
|
|
2101
2112
|
const li = document.createElement("li");
|
|
2102
2113
|
li.className = "nr-richlist__item";
|
|
2103
|
-
|
|
2104
|
-
if (props.style) li.setAttribute("style", props.style);
|
|
2114
|
+
applyBaseProps(li, props);
|
|
2105
2115
|
if (props.image) {
|
|
2106
2116
|
const thumb = document.createElement("div");
|
|
2107
2117
|
thumb.className = "nr-richlist__thumb";
|
|
@@ -2163,36 +2173,20 @@ var richlistItemDirective = ({ props, renderSlot }) => {
|
|
|
2163
2173
|
var richlistDirective = ({ props, renderSlot }) => {
|
|
2164
2174
|
const ul = document.createElement("ul");
|
|
2165
2175
|
ul.className = "nr-richlist";
|
|
2166
|
-
|
|
2167
|
-
if (props.style) ul.setAttribute("style", props.style);
|
|
2176
|
+
applyBaseProps(ul, props);
|
|
2168
2177
|
ul.appendChild(renderSlot("default"));
|
|
2169
2178
|
return ul;
|
|
2170
2179
|
};
|
|
2171
2180
|
var richlist_default = richlistDirective;
|
|
2172
2181
|
|
|
2173
2182
|
// vanilla/directives/stat.ts
|
|
2174
|
-
var STAT_THEME_TOKENS = /* @__PURE__ */ new Set([
|
|
2175
|
-
"primary",
|
|
2176
|
-
"secondary",
|
|
2177
|
-
"info",
|
|
2178
|
-
"success",
|
|
2179
|
-
"warning",
|
|
2180
|
-
"error"
|
|
2181
|
-
]);
|
|
2182
|
-
function isArbitraryColor2(value) {
|
|
2183
|
-
if (STAT_THEME_TOKENS.has(value)) return false;
|
|
2184
|
-
if (/^(#|rgb|hsl|oklch|oklab|lab|lch|color\()/i.test(value)) return true;
|
|
2185
|
-
if (/^[a-zA-Z]+$/.test(value)) return true;
|
|
2186
|
-
return false;
|
|
2187
|
-
}
|
|
2188
2183
|
var statDirective = ({ props }) => {
|
|
2189
|
-
const
|
|
2190
|
-
const colorClass =
|
|
2184
|
+
const statIsThemeToken = isThemeToken(props.color);
|
|
2185
|
+
const colorClass = statIsThemeToken ? ` nr-stat--${props.color}` : "";
|
|
2191
2186
|
const stat = document.createElement("div");
|
|
2192
2187
|
stat.className = `nr-stat${colorClass}`;
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
const useInlineColor = props.color && isArbitraryColor2(props.color) && !isThemeToken;
|
|
2188
|
+
applyBaseProps(stat, props);
|
|
2189
|
+
const useInlineColor = props.color && isArbitraryColor(props.color) && !statIsThemeToken;
|
|
2196
2190
|
if (props.icon) {
|
|
2197
2191
|
const figure = document.createElement("div");
|
|
2198
2192
|
figure.className = "nr-stat__figure";
|
|
@@ -2285,9 +2279,12 @@ function renderHtmlString(html) {
|
|
|
2285
2279
|
processedContent = processedContent.replace(
|
|
2286
2280
|
/<style(?:\s+[^>]*)?>([\s\S]*?)<\/style>/gi,
|
|
2287
2281
|
(_match, cssContent) => {
|
|
2282
|
+
const trimmed = cssContent.trim();
|
|
2283
|
+
const existing = document.head.querySelector("style[data-nr-global]");
|
|
2284
|
+
if (existing && existing.textContent === trimmed) return "";
|
|
2288
2285
|
const styleEl = document.createElement("style");
|
|
2289
2286
|
styleEl.setAttribute("data-nr-global", "");
|
|
2290
|
-
styleEl.textContent =
|
|
2287
|
+
styleEl.textContent = trimmed;
|
|
2291
2288
|
document.head.appendChild(styleEl);
|
|
2292
2289
|
return "";
|
|
2293
2290
|
}
|
|
@@ -2357,19 +2354,14 @@ function renderElement(element, ctx, allElements) {
|
|
|
2357
2354
|
switch (element.type) {
|
|
2358
2355
|
case "header": {
|
|
2359
2356
|
const tag = `h${element.level}`;
|
|
2360
|
-
let text = element.text;
|
|
2361
|
-
const alignCenter = text.match(/^->\s*(.+?)\s*<-\s*$/);
|
|
2362
|
-
const alignRight = text.match(/^->\s*(.+?)\s*->\s*$/);
|
|
2363
|
-
if (alignCenter) text = alignCenter[1];
|
|
2364
|
-
else if (alignRight) text = alignRight[1];
|
|
2365
2357
|
const h = document.createElement(tag);
|
|
2366
2358
|
h.id = element.id;
|
|
2367
2359
|
let cls = `md-h${element.level}`;
|
|
2368
|
-
if (
|
|
2369
|
-
if (
|
|
2360
|
+
if (element.align === "center") cls += " text-center";
|
|
2361
|
+
else if (element.align === "right") cls += " text-right";
|
|
2370
2362
|
if (element.classes) cls += ` ${element.classes}`;
|
|
2371
2363
|
h.className = cls;
|
|
2372
|
-
h.appendChild(renderInline(text));
|
|
2364
|
+
h.appendChild(renderInline(element.text));
|
|
2373
2365
|
return h;
|
|
2374
2366
|
}
|
|
2375
2367
|
case "paragraph": {
|
|
@@ -2737,7 +2729,7 @@ var guideData = [
|
|
|
2737
2729
|
"title": "Modal",
|
|
2738
2730
|
"icon": "open_in_full",
|
|
2739
2731
|
"order": 2,
|
|
2740
|
-
"md": '# Modal\n\nLa directiva `:::modal` crea un **di\xE1logo modal** con su bot\xF3n de apertura.\n\n## Sintaxis\n\n```md\n:::modal {title="Confirmar borrado" label="Abrir modal" icon="delete"}\n\xBFSeguro que quieres borrar este documento? Esta acci\xF3n no se puede deshacer.\n\n| Acci\xF3n | Efecto |\n| --- | --- |\n| Aceptar | Borra el documento |\n| Cancelar | No hace nada |\n:::\n```\n\n:::modal {title="Confirmar borrado" label="Abrir modal" icon="delete"}\n\xBFSeguro que quieres borrar este documento? Esta acci\xF3n no se puede deshacer.\n\n| Acci\xF3n | Efecto |\n| --- | --- |\n| Aceptar | Borra el documento |\n| Cancelar | No hace nada |\n:::\n\n## Contenido enriquecido\n\n```md\n:::modal {title="Notas de la versi\xF3n" label="Ver novedades" icon="new_releases"}\n**v2.0** \u2014 cambios principales:\n\n- Nuevo componente `:::diff`\n- Gu\xEDa integrada en el editor\n- Especificidad CSS corregida en im\xE1genes\n:::\n```\n\n:::modal {title="Notas de la versi\xF3n" label="Ver novedades" icon="new_releases"}\n**v2.0** \u2014 cambios principales:\n\n- Nuevo componente `:::diff`\n- Gu\xEDa integrada en el editor\n- Especificidad CSS corregida en im\xE1genes\n:::\n\n## Props\n\n| Prop | Tipo | Descripci\xF3n |\n| --- | --- | --- |\n| `title` | texto | T\xEDtulo del modal |\n| `label` | texto | Texto del bot\xF3n de apertura (
|
|
2732
|
+
"md": '# Modal\n\nLa directiva `:::modal` crea un **di\xE1logo modal** con su bot\xF3n de apertura.\n\n## Sintaxis\n\n```md\n:::modal {title="Confirmar borrado" label="Abrir modal" icon="delete"}\n\xBFSeguro que quieres borrar este documento? Esta acci\xF3n no se puede deshacer.\n\n| Acci\xF3n | Efecto |\n| --- | --- |\n| Aceptar | Borra el documento |\n| Cancelar | No hace nada |\n:::\n```\n\n:::modal {title="Confirmar borrado" label="Abrir modal" icon="delete"}\n\xBFSeguro que quieres borrar este documento? Esta acci\xF3n no se puede deshacer.\n\n| Acci\xF3n | Efecto |\n| --- | --- |\n| Aceptar | Borra el documento |\n| Cancelar | No hace nada |\n:::\n\n## Contenido enriquecido\n\n```md\n:::modal {title="Notas de la versi\xF3n" label="Ver novedades" icon="new_releases"}\n**v2.0** \u2014 cambios principales:\n\n- Nuevo componente `:::diff`\n- Gu\xEDa integrada en el editor\n- Especificidad CSS corregida en im\xE1genes\n:::\n```\n\n:::modal {title="Notas de la versi\xF3n" label="Ver novedades" icon="new_releases"}\n**v2.0** \u2014 cambios principales:\n\n- Nuevo componente `:::diff`\n- Gu\xEDa integrada en el editor\n- Especificidad CSS corregida en im\xE1genes\n:::\n\n## Alineaci\xF3n del bot\xF3n\n\nEl bot\xF3n de apertura se alinea a la izquierda por defecto. Usa el prop `align` para cambiar la alineaci\xF3n:\n\n### Centrado\n\n```md\n:::modal {title="Centrado" label="Abrir" icon="open_in_full" align="center"}\nContenido del modal centrado.\n:::\n```\n\n:::modal {title="Centrado" label="Abrir" icon="open_in_full" align="center"}\nContenido del modal centrado.\n:::\n\n### Alineado a la derecha\n\n```md\n:::modal {title="Derecha" label="Abrir" icon="open_in_full" align="right"}\nContenido del modal alineado a la derecha.\n:::\n```\n\n:::modal {title="Derecha" label="Abrir" icon="open_in_full" align="right"}\nContenido del modal alineado a la derecha.\n:::\n\n## Props\n\n| Prop | Tipo | Descripci\xF3n |\n| --- | --- | --- |\n| `title` | texto | T\xEDtulo del modal |\n| `label` (o `title`) | texto | Texto del bot\xF3n de apertura (`title` funciona como alias, default: \xABOpen\xBB) |\n| `icon` | nombre Material | Icono del bot\xF3n (default `open_in_new`) |\n| `align` | `left` / `center` / `right` | Alineaci\xF3n del bot\xF3n de apertura (default `left`) |\n| `class` | texto | Clases CSS adicionales |\n| `style` | CSS | Estilos inline |\n\n## Interacci\xF3n\n\n- **Bot\xF3n**: abre el modal (focus se mueve dentro).\n- **Overlay** o bot\xF3n **\xD7**: cierra.\n- **Esc**: cierra (en desktop).\n- `dialog` nativo \u2192 accesible por defecto, focus trapped y `inert` al fondo.'
|
|
2741
2733
|
},
|
|
2742
2734
|
{
|
|
2743
2735
|
"id": "button",
|
|
@@ -2745,7 +2737,7 @@ var guideData = [
|
|
|
2745
2737
|
"title": "Button",
|
|
2746
2738
|
"icon": "touch_app",
|
|
2747
2739
|
"order": 3,
|
|
2748
|
-
"md": '# Button\n\nLa directiva `:::button` crea un **bot\xF3n con enlace** (se abre en pesta\xF1a nueva por defecto).\n\n## Sintaxis\n\n```md\n:::button {label="Documentaci\xF3n" url="https://example.com" icon="menu_book"}\n:::\n```\n\n:::button {label="Documentaci\xF3n" url="https://example.com" icon="menu_book"}\n:::\n\n## Variante con enlace interno\n\n```md\n:::button {label="Ir a la p\xE1gina de notas" url="#admonici\xF3n-nota" icon="sticky_note_2" target="_self"}\n:::\n```\n\n:::button {label="Ir a la p\xE1gina de notas" url="#admonici\xF3n-nota" icon="sticky_note_2" target="_self"}\n:::\n\n## Con contenido markdown\n\nSi el bloque contiene texto/enlaces, se renderizan dentro del bot\xF3n:\n\n```md\n:::button {label="Descargar" url="https://example.com/download" icon="download"}\nDescarga el **manual** en PDF\n:::\n```\n\n:::button {label="Descargar" url="https://example.com/download" icon="download"}\nDescarga el **manual** en PDF\n:::\n\n## Props\n\n| Prop | Tipo | Descripci\xF3n |\n| --- | --- | --- |\n| `label` | texto | Texto del bot\xF3n |\n| `url` (o `href`) | URL | Destino del enlace (default `#`) |\n| `icon` | nombre Material | Icono (default `near_me`) |\n| `target` | `_blank` / `_self` / ... | Destino del enlace (default `_blank`) |\n| `class` | texto | Clases CSS adicionales |'
|
|
2740
|
+
"md": '# Button\n\nLa directiva `:::button` crea un **bot\xF3n con enlace** (se abre en pesta\xF1a nueva por defecto).\n\n## Sintaxis\n\n```md\n:::button {label="Documentaci\xF3n" url="https://example.com" icon="menu_book"}\n:::\n```\n\n:::button {label="Documentaci\xF3n" url="https://example.com" icon="menu_book"}\n:::\n\n## Variante con enlace interno\n\n```md\n:::button {label="Ir a la p\xE1gina de notas" url="#admonici\xF3n-nota" icon="sticky_note_2" target="_self"}\n:::\n```\n\n:::button {label="Ir a la p\xE1gina de notas" url="#admonici\xF3n-nota" icon="sticky_note_2" target="_self"}\n:::\n\n## Con contenido markdown\n\nSi el bloque contiene texto/enlaces, se renderizan dentro del bot\xF3n:\n\n```md\n:::button {label="Descargar" url="https://example.com/download" icon="download"}\nDescarga el **manual** en PDF\n:::\n```\n\n:::button {label="Descargar" url="https://example.com/download" icon="download"}\nDescarga el **manual** en PDF\n:::\n\n## Alineaci\xF3n\n\nLos botones se alinean a la izquierda por defecto. Usa el prop `align` para cambiar la alineaci\xF3n:\n\n### Centrado\n\n```md\n:::button {label="Centrado" url="https://example.com" icon="center_focus_strong" align="center"}\n:::\n```\n\n:::button {label="Centrado" url="https://example.com" icon="center_focus_strong" align="center"}\n:::\n\n### Alineado a la derecha\n\n```md\n:::button {label="Derecha" url="https://example.com" icon="arrow_forward" align="right"}\n:::\n```\n\n:::button {label="Derecha" url="https://example.com" icon="arrow_forward" align="right"}\n:::\n\n## Props\n\n| Prop | Tipo | Descripci\xF3n |\n| --- | --- | --- |\n| `label` (o `title`) | texto | Texto del bot\xF3n (`title` funciona como alias por compatibilidad) |\n| `url` (o `href`) | URL | Destino del enlace (default `#`) |\n| `icon` | nombre Material | Icono (default `near_me`) |\n| `target` | `_blank` / `_self` / ... | Destino del enlace (default `_blank`) |\n| `align` | `left` / `center` / `right` | Alineaci\xF3n del bot\xF3n (default `left`) |\n| `class` | texto | Clases CSS adicionales |'
|
|
2749
2741
|
},
|
|
2750
2742
|
{
|
|
2751
2743
|
"id": "slide",
|