@talqui-oss/template-builder 0.1.3 → 0.1.4
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/index.cjs +124 -67
- package/dist/index.d.cts +58 -3
- package/dist/index.d.ts +58 -3
- package/dist/index.js +123 -67
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
EDITOR_LABELS: () => EDITOR_LABELS,
|
|
23
24
|
TemplateValidationError: () => TemplateValidationError,
|
|
24
25
|
UnsupportedByProviderError: () => UnsupportedByProviderError,
|
|
25
26
|
applyEdit: () => applyEdit,
|
|
@@ -1341,43 +1342,93 @@ var ICONS = {
|
|
|
1341
1342
|
};
|
|
1342
1343
|
|
|
1343
1344
|
// src/editor/model.ts
|
|
1345
|
+
var EDITOR_LABELS = {
|
|
1346
|
+
basics: "Basics",
|
|
1347
|
+
name: "Name",
|
|
1348
|
+
nameHint: "lowercase, numbers and _",
|
|
1349
|
+
language: "Language",
|
|
1350
|
+
category: "Category",
|
|
1351
|
+
utility: "Utility",
|
|
1352
|
+
marketing: "Marketing",
|
|
1353
|
+
authentication: "Authentication",
|
|
1354
|
+
content: "Content",
|
|
1355
|
+
header: "Header",
|
|
1356
|
+
headerNone: "None",
|
|
1357
|
+
headerText: "Text",
|
|
1358
|
+
headerImage: "Image",
|
|
1359
|
+
headerVideo: "Video",
|
|
1360
|
+
headerDocument: "Document",
|
|
1361
|
+
headerTextField: "Header text",
|
|
1362
|
+
sampleFileUrl: "Sample file URL",
|
|
1363
|
+
body: "Body",
|
|
1364
|
+
footer: "Footer",
|
|
1365
|
+
formattingNote: "Use {{name}} for variables and *bold*, _italic_, ~strike~ for formatting.",
|
|
1366
|
+
buttons: "Buttons",
|
|
1367
|
+
buttonType: "Type",
|
|
1368
|
+
quickReply: "Quick reply",
|
|
1369
|
+
link: "Link",
|
|
1370
|
+
phone: "Phone",
|
|
1371
|
+
copyCode: "Copy code",
|
|
1372
|
+
buttonText: "Button text",
|
|
1373
|
+
url: "URL",
|
|
1374
|
+
phoneNumber: "Phone number",
|
|
1375
|
+
sampleCode: "Sample code",
|
|
1376
|
+
removeButton: "Remove button",
|
|
1377
|
+
addButton: "Add button",
|
|
1378
|
+
variables: "Variables",
|
|
1379
|
+
/** Followed by the variable's number, e.g. "position 1". */
|
|
1380
|
+
variablePosition: "position",
|
|
1381
|
+
exampleValue: "Example value",
|
|
1382
|
+
noVariables: "Type a placeholder such as {{first_name}} in the text to add one.",
|
|
1383
|
+
codeMessage: "Code message",
|
|
1384
|
+
securityRecommendation: "Add \u201Cdo not share this code\u201D",
|
|
1385
|
+
expiresAfter: "Expires after",
|
|
1386
|
+
expiresHint: "minutes, 1 to 90",
|
|
1387
|
+
optional: "optional",
|
|
1388
|
+
/** Default text of new buttons. */
|
|
1389
|
+
newQuickReply: "Reply",
|
|
1390
|
+
newLinkButton: "Open link",
|
|
1391
|
+
newPhoneButton: "Call us"
|
|
1392
|
+
};
|
|
1344
1393
|
var LANGUAGES = [
|
|
1345
1394
|
{ value: "en_US", label: "English (US)" },
|
|
1346
1395
|
{ value: "pt_BR", label: "Portuguese (BR)" },
|
|
1347
1396
|
{ value: "es", label: "Spanish" }
|
|
1348
1397
|
];
|
|
1349
|
-
var
|
|
1350
|
-
{ value: "UTILITY", label:
|
|
1351
|
-
{ value: "MARKETING", label:
|
|
1352
|
-
{ value: "AUTHENTICATION", label:
|
|
1398
|
+
var categories = (l) => [
|
|
1399
|
+
{ value: "UTILITY", label: l.utility },
|
|
1400
|
+
{ value: "MARKETING", label: l.marketing },
|
|
1401
|
+
{ value: "AUTHENTICATION", label: l.authentication }
|
|
1353
1402
|
];
|
|
1354
|
-
var
|
|
1355
|
-
{ value: "NONE", label:
|
|
1356
|
-
{ value: "TEXT", label:
|
|
1357
|
-
{ value: "IMAGE", label:
|
|
1358
|
-
{ value: "VIDEO", label:
|
|
1359
|
-
{ value: "DOCUMENT", label:
|
|
1403
|
+
var headerKinds = (l) => [
|
|
1404
|
+
{ value: "NONE", label: l.headerNone },
|
|
1405
|
+
{ value: "TEXT", label: l.headerText },
|
|
1406
|
+
{ value: "IMAGE", label: l.headerImage },
|
|
1407
|
+
{ value: "VIDEO", label: l.headerVideo },
|
|
1408
|
+
{ value: "DOCUMENT", label: l.headerDocument }
|
|
1360
1409
|
];
|
|
1361
|
-
var BUTTON_TYPES = [
|
|
1362
|
-
|
|
1363
|
-
{ value: "
|
|
1364
|
-
{ value: "
|
|
1365
|
-
{ value: "
|
|
1410
|
+
var BUTTON_TYPES = ["QUICK_REPLY", "URL", "PHONE_NUMBER", "COPY_CODE"];
|
|
1411
|
+
var buttonTypes = (l) => [
|
|
1412
|
+
{ value: "QUICK_REPLY", label: l.quickReply },
|
|
1413
|
+
{ value: "URL", label: l.link },
|
|
1414
|
+
{ value: "PHONE_NUMBER", label: l.phone },
|
|
1415
|
+
{ value: "COPY_CODE", label: l.copyCode }
|
|
1366
1416
|
];
|
|
1367
1417
|
var MAX_BUTTONS = 10;
|
|
1368
1418
|
var count = (text, max) => `${[...text].length}/${max}`;
|
|
1369
1419
|
function editorSections(template, options = {}) {
|
|
1420
|
+
const l = { ...EDITOR_LABELS, ...options.labels };
|
|
1370
1421
|
const basics = {
|
|
1371
1422
|
id: "basics",
|
|
1372
|
-
title:
|
|
1423
|
+
title: l.basics,
|
|
1373
1424
|
rows: [
|
|
1374
1425
|
{
|
|
1375
1426
|
fields: [
|
|
1376
1427
|
{
|
|
1377
1428
|
kind: "text",
|
|
1378
1429
|
id: "name",
|
|
1379
|
-
label:
|
|
1380
|
-
hint:
|
|
1430
|
+
label: l.name,
|
|
1431
|
+
hint: l.nameHint,
|
|
1381
1432
|
value: template.name,
|
|
1382
1433
|
mono: true
|
|
1383
1434
|
}
|
|
@@ -1388,47 +1439,48 @@ function editorSections(template, options = {}) {
|
|
|
1388
1439
|
{
|
|
1389
1440
|
kind: "select",
|
|
1390
1441
|
id: "language",
|
|
1391
|
-
label:
|
|
1442
|
+
label: l.language,
|
|
1392
1443
|
value: template.language,
|
|
1393
1444
|
options: options.languages ?? LANGUAGES
|
|
1394
1445
|
},
|
|
1395
1446
|
{
|
|
1396
1447
|
kind: "segment",
|
|
1397
1448
|
id: "category",
|
|
1398
|
-
label:
|
|
1449
|
+
label: l.category,
|
|
1399
1450
|
value: template.category,
|
|
1400
|
-
options:
|
|
1451
|
+
options: categories(l)
|
|
1401
1452
|
}
|
|
1402
1453
|
]
|
|
1403
1454
|
}
|
|
1404
1455
|
]
|
|
1405
1456
|
};
|
|
1406
1457
|
if (template.category === "AUTHENTICATION")
|
|
1407
|
-
return [basics, codeSection(template)];
|
|
1458
|
+
return [basics, codeSection(template, l)];
|
|
1408
1459
|
return [
|
|
1409
1460
|
basics,
|
|
1410
|
-
contentSection(template),
|
|
1411
|
-
buttonsSection(template),
|
|
1412
|
-
variablesSection(template)
|
|
1461
|
+
contentSection(template, l),
|
|
1462
|
+
buttonsSection(template, l),
|
|
1463
|
+
variablesSection(template, l)
|
|
1413
1464
|
];
|
|
1414
1465
|
}
|
|
1415
|
-
function contentSection(template) {
|
|
1466
|
+
function contentSection(template, l) {
|
|
1416
1467
|
const header2 = template.header;
|
|
1417
|
-
const
|
|
1468
|
+
const kinds = headerKinds(l);
|
|
1469
|
+
const kind = kinds.some((option) => option.value === header2?.type) ? header2.type : "NONE";
|
|
1418
1470
|
const headerRow = [
|
|
1419
1471
|
{
|
|
1420
1472
|
kind: "select",
|
|
1421
1473
|
id: "header.kind",
|
|
1422
|
-
label:
|
|
1474
|
+
label: l.header,
|
|
1423
1475
|
value: kind,
|
|
1424
|
-
options:
|
|
1476
|
+
options: kinds
|
|
1425
1477
|
}
|
|
1426
1478
|
];
|
|
1427
1479
|
if (header2?.type === "TEXT")
|
|
1428
1480
|
headerRow.push({
|
|
1429
1481
|
kind: "text",
|
|
1430
1482
|
id: "header.text",
|
|
1431
|
-
label:
|
|
1483
|
+
label: l.headerTextField,
|
|
1432
1484
|
hint: count(header2.text, 60),
|
|
1433
1485
|
value: header2.text
|
|
1434
1486
|
});
|
|
@@ -1436,13 +1488,13 @@ function contentSection(template) {
|
|
|
1436
1488
|
headerRow.push({
|
|
1437
1489
|
kind: "text",
|
|
1438
1490
|
id: "header.url",
|
|
1439
|
-
label:
|
|
1491
|
+
label: l.sampleFileUrl,
|
|
1440
1492
|
value: header2.url,
|
|
1441
1493
|
mono: true
|
|
1442
1494
|
});
|
|
1443
1495
|
return {
|
|
1444
1496
|
id: "content",
|
|
1445
|
-
title:
|
|
1497
|
+
title: l.content,
|
|
1446
1498
|
rows: [
|
|
1447
1499
|
{ fields: headerRow },
|
|
1448
1500
|
{
|
|
@@ -1450,7 +1502,7 @@ function contentSection(template) {
|
|
|
1450
1502
|
{
|
|
1451
1503
|
kind: "textarea",
|
|
1452
1504
|
id: "body",
|
|
1453
|
-
label:
|
|
1505
|
+
label: l.body,
|
|
1454
1506
|
hint: count(template.body.text, 1024),
|
|
1455
1507
|
value: template.body.text
|
|
1456
1508
|
}
|
|
@@ -1461,35 +1513,35 @@ function contentSection(template) {
|
|
|
1461
1513
|
{
|
|
1462
1514
|
kind: "text",
|
|
1463
1515
|
id: "footer",
|
|
1464
|
-
label:
|
|
1516
|
+
label: l.footer,
|
|
1465
1517
|
hint: count(template.footer?.text ?? "", 60),
|
|
1466
1518
|
value: template.footer?.text ?? ""
|
|
1467
1519
|
}
|
|
1468
1520
|
]
|
|
1469
1521
|
}
|
|
1470
1522
|
],
|
|
1471
|
-
note:
|
|
1523
|
+
note: l.formattingNote
|
|
1472
1524
|
};
|
|
1473
1525
|
}
|
|
1474
|
-
function buttonsSection(template) {
|
|
1526
|
+
function buttonsSection(template, l) {
|
|
1475
1527
|
const buttons = template.buttons ?? [];
|
|
1476
1528
|
const rows = buttons.map((button2, index) => {
|
|
1477
1529
|
const at = `buttons.${index}`;
|
|
1478
|
-
const type = BUTTON_TYPES.
|
|
1530
|
+
const type = BUTTON_TYPES.includes(button2.type) ? button2.type : "QUICK_REPLY";
|
|
1479
1531
|
const fields = [
|
|
1480
1532
|
{
|
|
1481
1533
|
kind: "select",
|
|
1482
1534
|
id: `${at}.type`,
|
|
1483
|
-
label:
|
|
1535
|
+
label: l.buttonType,
|
|
1484
1536
|
value: type,
|
|
1485
|
-
options:
|
|
1537
|
+
options: buttonTypes(l)
|
|
1486
1538
|
}
|
|
1487
1539
|
];
|
|
1488
1540
|
if ("text" in button2 && button2.text !== void 0)
|
|
1489
1541
|
fields.push({
|
|
1490
1542
|
kind: "text",
|
|
1491
1543
|
id: `${at}.text`,
|
|
1492
|
-
label:
|
|
1544
|
+
label: l.buttonText,
|
|
1493
1545
|
hint: count(button2.text, 25),
|
|
1494
1546
|
value: button2.text
|
|
1495
1547
|
});
|
|
@@ -1497,7 +1549,7 @@ function buttonsSection(template) {
|
|
|
1497
1549
|
fields.push({
|
|
1498
1550
|
kind: "text",
|
|
1499
1551
|
id: `${at}.url`,
|
|
1500
|
-
label:
|
|
1552
|
+
label: l.url,
|
|
1501
1553
|
value: button2.url,
|
|
1502
1554
|
mono: true
|
|
1503
1555
|
});
|
|
@@ -1505,7 +1557,7 @@ function buttonsSection(template) {
|
|
|
1505
1557
|
fields.push({
|
|
1506
1558
|
kind: "text",
|
|
1507
1559
|
id: `${at}.phoneNumber`,
|
|
1508
|
-
label:
|
|
1560
|
+
label: l.phoneNumber,
|
|
1509
1561
|
value: button2.phoneNumber,
|
|
1510
1562
|
mono: true
|
|
1511
1563
|
});
|
|
@@ -1513,14 +1565,14 @@ function buttonsSection(template) {
|
|
|
1513
1565
|
fields.push({
|
|
1514
1566
|
kind: "text",
|
|
1515
1567
|
id: `${at}.example`,
|
|
1516
|
-
label:
|
|
1568
|
+
label: l.sampleCode,
|
|
1517
1569
|
value: button2.example,
|
|
1518
1570
|
mono: true
|
|
1519
1571
|
});
|
|
1520
1572
|
fields.push({
|
|
1521
1573
|
kind: "action",
|
|
1522
1574
|
id: `${at}.remove`,
|
|
1523
|
-
label:
|
|
1575
|
+
label: l.removeButton,
|
|
1524
1576
|
icon: "remove"
|
|
1525
1577
|
});
|
|
1526
1578
|
return { fields, list: true };
|
|
@@ -1530,7 +1582,7 @@ function buttonsSection(template) {
|
|
|
1530
1582
|
{
|
|
1531
1583
|
kind: "action",
|
|
1532
1584
|
id: "buttons.add",
|
|
1533
|
-
label:
|
|
1585
|
+
label: l.addButton,
|
|
1534
1586
|
icon: "add",
|
|
1535
1587
|
disabled: buttons.length >= MAX_BUTTONS
|
|
1536
1588
|
}
|
|
@@ -1538,42 +1590,42 @@ function buttonsSection(template) {
|
|
|
1538
1590
|
});
|
|
1539
1591
|
return {
|
|
1540
1592
|
id: "buttons",
|
|
1541
|
-
title:
|
|
1593
|
+
title: `${l.buttons} ${buttons.length}/${MAX_BUTTONS}`,
|
|
1542
1594
|
rows
|
|
1543
1595
|
};
|
|
1544
1596
|
}
|
|
1545
|
-
function variablesSection(template) {
|
|
1597
|
+
function variablesSection(template, l) {
|
|
1546
1598
|
const variables = Object.entries(template.variables ?? {});
|
|
1547
1599
|
return {
|
|
1548
1600
|
id: "variables",
|
|
1549
|
-
title:
|
|
1601
|
+
title: l.variables,
|
|
1550
1602
|
rows: variables.map(([name, variable], index) => ({
|
|
1551
1603
|
fields: [
|
|
1552
1604
|
{
|
|
1553
1605
|
kind: "text",
|
|
1554
1606
|
id: `variables.${name}`,
|
|
1555
1607
|
label: `{{${name}}}`,
|
|
1556
|
-
hint:
|
|
1608
|
+
hint: `${l.variablePosition} ${index + 1}`,
|
|
1557
1609
|
value: variable.example,
|
|
1558
|
-
placeholder:
|
|
1610
|
+
placeholder: l.exampleValue
|
|
1559
1611
|
}
|
|
1560
1612
|
]
|
|
1561
1613
|
})),
|
|
1562
|
-
note: variables.length ? void 0 :
|
|
1614
|
+
note: variables.length ? void 0 : l.noVariables
|
|
1563
1615
|
};
|
|
1564
1616
|
}
|
|
1565
|
-
function codeSection(template) {
|
|
1617
|
+
function codeSection(template, l) {
|
|
1566
1618
|
const minutes = template.footer?.codeExpirationMinutes;
|
|
1567
1619
|
return {
|
|
1568
1620
|
id: "code",
|
|
1569
|
-
title:
|
|
1621
|
+
title: l.codeMessage,
|
|
1570
1622
|
rows: [
|
|
1571
1623
|
{
|
|
1572
1624
|
fields: [
|
|
1573
1625
|
{
|
|
1574
1626
|
kind: "checkbox",
|
|
1575
1627
|
id: "body.addSecurityRecommendation",
|
|
1576
|
-
label:
|
|
1628
|
+
label: l.securityRecommendation,
|
|
1577
1629
|
checked: template.body?.addSecurityRecommendation ?? false
|
|
1578
1630
|
}
|
|
1579
1631
|
]
|
|
@@ -1583,25 +1635,25 @@ function codeSection(template) {
|
|
|
1583
1635
|
{
|
|
1584
1636
|
kind: "text",
|
|
1585
1637
|
id: "footer.codeExpirationMinutes",
|
|
1586
|
-
label:
|
|
1587
|
-
hint:
|
|
1638
|
+
label: l.expiresAfter,
|
|
1639
|
+
hint: l.expiresHint,
|
|
1588
1640
|
value: minutes === void 0 ? "" : String(minutes),
|
|
1589
1641
|
mono: true
|
|
1590
1642
|
},
|
|
1591
1643
|
{
|
|
1592
1644
|
kind: "text",
|
|
1593
1645
|
id: "button.text",
|
|
1594
|
-
label:
|
|
1595
|
-
hint:
|
|
1646
|
+
label: l.buttonText,
|
|
1647
|
+
hint: l.optional,
|
|
1596
1648
|
value: template.button.text ?? "",
|
|
1597
|
-
placeholder:
|
|
1649
|
+
placeholder: l.copyCode
|
|
1598
1650
|
}
|
|
1599
1651
|
]
|
|
1600
1652
|
}
|
|
1601
1653
|
]
|
|
1602
1654
|
};
|
|
1603
1655
|
}
|
|
1604
|
-
function applyEdit(template, id, value, remembered = {}) {
|
|
1656
|
+
function applyEdit(template, id, value, remembered = {}, labels = {}) {
|
|
1605
1657
|
const text = typeof value === "string" ? value : "";
|
|
1606
1658
|
if (id === "name") return { ...template, name: text };
|
|
1607
1659
|
if (id === "language") return { ...template, language: text };
|
|
@@ -1634,9 +1686,12 @@ function applyEdit(template, id, value, remembered = {}) {
|
|
|
1634
1686
|
[id.slice("variables.".length)]: { example: text }
|
|
1635
1687
|
}
|
|
1636
1688
|
};
|
|
1637
|
-
return syncVariables(
|
|
1689
|
+
return syncVariables(
|
|
1690
|
+
editStandard(template, id, text, { ...EDITOR_LABELS, ...labels }),
|
|
1691
|
+
remembered
|
|
1692
|
+
);
|
|
1638
1693
|
}
|
|
1639
|
-
function editStandard(template, id, text) {
|
|
1694
|
+
function editStandard(template, id, text, l) {
|
|
1640
1695
|
if (id === "header.kind") return { ...template, header: newHeader(text) };
|
|
1641
1696
|
if (id === "header.text")
|
|
1642
1697
|
return { ...template, header: { type: "TEXT", text } };
|
|
@@ -1651,7 +1706,7 @@ function editStandard(template, id, text) {
|
|
|
1651
1706
|
buttons: next2.length ? next2 : void 0
|
|
1652
1707
|
});
|
|
1653
1708
|
if (id === "buttons.add")
|
|
1654
|
-
return buttons.length >= MAX_BUTTONS ? template : withButtons([...buttons, newButton("QUICK_REPLY")]);
|
|
1709
|
+
return buttons.length >= MAX_BUTTONS ? template : withButtons([...buttons, newButton(l, "QUICK_REPLY")]);
|
|
1655
1710
|
const match = /^buttons\.(\d+)\.(\w+)$/.exec(id);
|
|
1656
1711
|
if (!match) return template;
|
|
1657
1712
|
const index = Number(match[1]);
|
|
@@ -1661,6 +1716,7 @@ function editStandard(template, id, text) {
|
|
|
1661
1716
|
if (field === "remove")
|
|
1662
1717
|
return withButtons(buttons.filter((_, i) => i !== index));
|
|
1663
1718
|
const next = field === "type" ? newButton(
|
|
1719
|
+
l,
|
|
1664
1720
|
text,
|
|
1665
1721
|
"text" in button2 ? button2.text ?? "" : ""
|
|
1666
1722
|
) : { ...button2, [field]: text };
|
|
@@ -1702,13 +1758,13 @@ function newHeader(kind) {
|
|
|
1702
1758
|
return { type: kind, url: "https://" };
|
|
1703
1759
|
return void 0;
|
|
1704
1760
|
}
|
|
1705
|
-
function newButton(type, label = "") {
|
|
1761
|
+
function newButton(l, type, label = "") {
|
|
1706
1762
|
if (type === "URL")
|
|
1707
|
-
return { type, text: label ||
|
|
1763
|
+
return { type, text: label || l.newLinkButton, url: "https://" };
|
|
1708
1764
|
if (type === "PHONE_NUMBER")
|
|
1709
|
-
return { type, text: label ||
|
|
1765
|
+
return { type, text: label || l.newPhoneButton, phoneNumber: "+" };
|
|
1710
1766
|
if (type === "COPY_CODE") return { type, example: "CODE10" };
|
|
1711
|
-
return { type: "QUICK_REPLY", text: label ||
|
|
1767
|
+
return { type: "QUICK_REPLY", text: label || l.newQuickReply };
|
|
1712
1768
|
}
|
|
1713
1769
|
|
|
1714
1770
|
// src/editor/tree.ts
|
|
@@ -1837,6 +1893,7 @@ function node2(tag, className, attrs, children = []) {
|
|
|
1837
1893
|
}
|
|
1838
1894
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1839
1895
|
0 && (module.exports = {
|
|
1896
|
+
EDITOR_LABELS,
|
|
1840
1897
|
TemplateValidationError,
|
|
1841
1898
|
UnsupportedByProviderError,
|
|
1842
1899
|
applyEdit,
|
package/dist/index.d.cts
CHANGED
|
@@ -277,9 +277,62 @@ type EditorSection = {
|
|
|
277
277
|
/** Help text under the section, e.g. the formatting syntax. */
|
|
278
278
|
note?: string;
|
|
279
279
|
};
|
|
280
|
+
/** Every text the editor shows, so it can be translated. */
|
|
281
|
+
type EditorLabels = typeof EDITOR_LABELS;
|
|
282
|
+
/** The editor texts in English, the default. */
|
|
283
|
+
declare const EDITOR_LABELS: {
|
|
284
|
+
basics: string;
|
|
285
|
+
name: string;
|
|
286
|
+
nameHint: string;
|
|
287
|
+
language: string;
|
|
288
|
+
category: string;
|
|
289
|
+
utility: string;
|
|
290
|
+
marketing: string;
|
|
291
|
+
authentication: string;
|
|
292
|
+
content: string;
|
|
293
|
+
header: string;
|
|
294
|
+
headerNone: string;
|
|
295
|
+
headerText: string;
|
|
296
|
+
headerImage: string;
|
|
297
|
+
headerVideo: string;
|
|
298
|
+
headerDocument: string;
|
|
299
|
+
headerTextField: string;
|
|
300
|
+
sampleFileUrl: string;
|
|
301
|
+
body: string;
|
|
302
|
+
footer: string;
|
|
303
|
+
formattingNote: string;
|
|
304
|
+
buttons: string;
|
|
305
|
+
buttonType: string;
|
|
306
|
+
quickReply: string;
|
|
307
|
+
link: string;
|
|
308
|
+
phone: string;
|
|
309
|
+
copyCode: string;
|
|
310
|
+
buttonText: string;
|
|
311
|
+
url: string;
|
|
312
|
+
phoneNumber: string;
|
|
313
|
+
sampleCode: string;
|
|
314
|
+
removeButton: string;
|
|
315
|
+
addButton: string;
|
|
316
|
+
variables: string;
|
|
317
|
+
/** Followed by the variable's number, e.g. "position 1". */
|
|
318
|
+
variablePosition: string;
|
|
319
|
+
exampleValue: string;
|
|
320
|
+
noVariables: string;
|
|
321
|
+
codeMessage: string;
|
|
322
|
+
securityRecommendation: string;
|
|
323
|
+
expiresAfter: string;
|
|
324
|
+
expiresHint: string;
|
|
325
|
+
optional: string;
|
|
326
|
+
/** Default text of new buttons. */
|
|
327
|
+
newQuickReply: string;
|
|
328
|
+
newLinkButton: string;
|
|
329
|
+
newPhoneButton: string;
|
|
330
|
+
};
|
|
280
331
|
type EditorOptions = {
|
|
281
332
|
/** Languages offered in the language select. Default: English (US), Portuguese (BR), Spanish. */
|
|
282
333
|
languages?: EditorOption[];
|
|
334
|
+
/** Texts to replace, e.g. to show the editor in another language. Default: English. */
|
|
335
|
+
labels?: Partial<EditorLabels>;
|
|
283
336
|
};
|
|
284
337
|
/** The sections of the editor for a template. */
|
|
285
338
|
declare function editorSections(template: Template, options?: EditorOptions): EditorSection[];
|
|
@@ -290,8 +343,10 @@ declare function editorSections(template: Template, options?: EditorOptions): Ed
|
|
|
290
343
|
*
|
|
291
344
|
* `remembered` holds examples of variables seen earlier: while someone types `{{name}}` the
|
|
292
345
|
* placeholder is briefly incomplete, and its example comes back from here once it is whole.
|
|
346
|
+
*
|
|
347
|
+
* `labels` gives new buttons their default text in the editor's language.
|
|
293
348
|
*/
|
|
294
|
-
declare function applyEdit(template: Template, id: string, value?: string | boolean, remembered?: Variables): Template;
|
|
349
|
+
declare function applyEdit(template: Template, id: string, value?: string | boolean, remembered?: Variables, labels?: Partial<EditorLabels>): Template;
|
|
295
350
|
/**
|
|
296
351
|
* Switches category. Authentication has its own shape, so moving in or out of it keeps only
|
|
297
352
|
* the name and language.
|
|
@@ -311,5 +366,5 @@ declare function editorTree(template: Template, options?: EditorOptions & {
|
|
|
311
366
|
idPrefix?: string;
|
|
312
367
|
}): PreviewNode;
|
|
313
368
|
|
|
314
|
-
export { Adapter, Category, HttpRequest, StandardTemplate, Template, TemplateValidationError, Variables, applyEdit, changeCategory, codes, editorSections, editorTree, extractVariables, previewTree, syncVariables, toCurl, toPreviewModel, toRequests, validate };
|
|
315
|
-
export type { ButtonIcon, Code, EditorField, EditorOption, EditorOptions, EditorRow, EditorSection, Issue, Line, Platform, PreviewButton, PreviewCard, PreviewHeader, PreviewModel, PreviewNode, PreviewOptions, Severity, Span, TreeOptions, ValidateOptions, ValidationResult };
|
|
369
|
+
export { Adapter, Category, EDITOR_LABELS, HttpRequest, StandardTemplate, Template, TemplateValidationError, Variables, applyEdit, changeCategory, codes, editorSections, editorTree, extractVariables, previewTree, syncVariables, toCurl, toPreviewModel, toRequests, validate };
|
|
370
|
+
export type { ButtonIcon, Code, EditorField, EditorLabels, EditorOption, EditorOptions, EditorRow, EditorSection, Issue, Line, Platform, PreviewButton, PreviewCard, PreviewHeader, PreviewModel, PreviewNode, PreviewOptions, Severity, Span, TreeOptions, ValidateOptions, ValidationResult };
|
package/dist/index.d.ts
CHANGED
|
@@ -277,9 +277,62 @@ type EditorSection = {
|
|
|
277
277
|
/** Help text under the section, e.g. the formatting syntax. */
|
|
278
278
|
note?: string;
|
|
279
279
|
};
|
|
280
|
+
/** Every text the editor shows, so it can be translated. */
|
|
281
|
+
type EditorLabels = typeof EDITOR_LABELS;
|
|
282
|
+
/** The editor texts in English, the default. */
|
|
283
|
+
declare const EDITOR_LABELS: {
|
|
284
|
+
basics: string;
|
|
285
|
+
name: string;
|
|
286
|
+
nameHint: string;
|
|
287
|
+
language: string;
|
|
288
|
+
category: string;
|
|
289
|
+
utility: string;
|
|
290
|
+
marketing: string;
|
|
291
|
+
authentication: string;
|
|
292
|
+
content: string;
|
|
293
|
+
header: string;
|
|
294
|
+
headerNone: string;
|
|
295
|
+
headerText: string;
|
|
296
|
+
headerImage: string;
|
|
297
|
+
headerVideo: string;
|
|
298
|
+
headerDocument: string;
|
|
299
|
+
headerTextField: string;
|
|
300
|
+
sampleFileUrl: string;
|
|
301
|
+
body: string;
|
|
302
|
+
footer: string;
|
|
303
|
+
formattingNote: string;
|
|
304
|
+
buttons: string;
|
|
305
|
+
buttonType: string;
|
|
306
|
+
quickReply: string;
|
|
307
|
+
link: string;
|
|
308
|
+
phone: string;
|
|
309
|
+
copyCode: string;
|
|
310
|
+
buttonText: string;
|
|
311
|
+
url: string;
|
|
312
|
+
phoneNumber: string;
|
|
313
|
+
sampleCode: string;
|
|
314
|
+
removeButton: string;
|
|
315
|
+
addButton: string;
|
|
316
|
+
variables: string;
|
|
317
|
+
/** Followed by the variable's number, e.g. "position 1". */
|
|
318
|
+
variablePosition: string;
|
|
319
|
+
exampleValue: string;
|
|
320
|
+
noVariables: string;
|
|
321
|
+
codeMessage: string;
|
|
322
|
+
securityRecommendation: string;
|
|
323
|
+
expiresAfter: string;
|
|
324
|
+
expiresHint: string;
|
|
325
|
+
optional: string;
|
|
326
|
+
/** Default text of new buttons. */
|
|
327
|
+
newQuickReply: string;
|
|
328
|
+
newLinkButton: string;
|
|
329
|
+
newPhoneButton: string;
|
|
330
|
+
};
|
|
280
331
|
type EditorOptions = {
|
|
281
332
|
/** Languages offered in the language select. Default: English (US), Portuguese (BR), Spanish. */
|
|
282
333
|
languages?: EditorOption[];
|
|
334
|
+
/** Texts to replace, e.g. to show the editor in another language. Default: English. */
|
|
335
|
+
labels?: Partial<EditorLabels>;
|
|
283
336
|
};
|
|
284
337
|
/** The sections of the editor for a template. */
|
|
285
338
|
declare function editorSections(template: Template, options?: EditorOptions): EditorSection[];
|
|
@@ -290,8 +343,10 @@ declare function editorSections(template: Template, options?: EditorOptions): Ed
|
|
|
290
343
|
*
|
|
291
344
|
* `remembered` holds examples of variables seen earlier: while someone types `{{name}}` the
|
|
292
345
|
* placeholder is briefly incomplete, and its example comes back from here once it is whole.
|
|
346
|
+
*
|
|
347
|
+
* `labels` gives new buttons their default text in the editor's language.
|
|
293
348
|
*/
|
|
294
|
-
declare function applyEdit(template: Template, id: string, value?: string | boolean, remembered?: Variables): Template;
|
|
349
|
+
declare function applyEdit(template: Template, id: string, value?: string | boolean, remembered?: Variables, labels?: Partial<EditorLabels>): Template;
|
|
295
350
|
/**
|
|
296
351
|
* Switches category. Authentication has its own shape, so moving in or out of it keeps only
|
|
297
352
|
* the name and language.
|
|
@@ -311,5 +366,5 @@ declare function editorTree(template: Template, options?: EditorOptions & {
|
|
|
311
366
|
idPrefix?: string;
|
|
312
367
|
}): PreviewNode;
|
|
313
368
|
|
|
314
|
-
export { Adapter, Category, HttpRequest, StandardTemplate, Template, TemplateValidationError, Variables, applyEdit, changeCategory, codes, editorSections, editorTree, extractVariables, previewTree, syncVariables, toCurl, toPreviewModel, toRequests, validate };
|
|
315
|
-
export type { ButtonIcon, Code, EditorField, EditorOption, EditorOptions, EditorRow, EditorSection, Issue, Line, Platform, PreviewButton, PreviewCard, PreviewHeader, PreviewModel, PreviewNode, PreviewOptions, Severity, Span, TreeOptions, ValidateOptions, ValidationResult };
|
|
369
|
+
export { Adapter, Category, EDITOR_LABELS, HttpRequest, StandardTemplate, Template, TemplateValidationError, Variables, applyEdit, changeCategory, codes, editorSections, editorTree, extractVariables, previewTree, syncVariables, toCurl, toPreviewModel, toRequests, validate };
|
|
370
|
+
export type { ButtonIcon, Code, EditorField, EditorLabels, EditorOption, EditorOptions, EditorRow, EditorSection, Issue, Line, Platform, PreviewButton, PreviewCard, PreviewHeader, PreviewModel, PreviewNode, PreviewOptions, Severity, Span, TreeOptions, ValidateOptions, ValidationResult };
|
package/dist/index.js
CHANGED
|
@@ -1230,43 +1230,93 @@ var ICONS = {
|
|
|
1230
1230
|
};
|
|
1231
1231
|
|
|
1232
1232
|
// src/editor/model.ts
|
|
1233
|
+
var EDITOR_LABELS = {
|
|
1234
|
+
basics: "Basics",
|
|
1235
|
+
name: "Name",
|
|
1236
|
+
nameHint: "lowercase, numbers and _",
|
|
1237
|
+
language: "Language",
|
|
1238
|
+
category: "Category",
|
|
1239
|
+
utility: "Utility",
|
|
1240
|
+
marketing: "Marketing",
|
|
1241
|
+
authentication: "Authentication",
|
|
1242
|
+
content: "Content",
|
|
1243
|
+
header: "Header",
|
|
1244
|
+
headerNone: "None",
|
|
1245
|
+
headerText: "Text",
|
|
1246
|
+
headerImage: "Image",
|
|
1247
|
+
headerVideo: "Video",
|
|
1248
|
+
headerDocument: "Document",
|
|
1249
|
+
headerTextField: "Header text",
|
|
1250
|
+
sampleFileUrl: "Sample file URL",
|
|
1251
|
+
body: "Body",
|
|
1252
|
+
footer: "Footer",
|
|
1253
|
+
formattingNote: "Use {{name}} for variables and *bold*, _italic_, ~strike~ for formatting.",
|
|
1254
|
+
buttons: "Buttons",
|
|
1255
|
+
buttonType: "Type",
|
|
1256
|
+
quickReply: "Quick reply",
|
|
1257
|
+
link: "Link",
|
|
1258
|
+
phone: "Phone",
|
|
1259
|
+
copyCode: "Copy code",
|
|
1260
|
+
buttonText: "Button text",
|
|
1261
|
+
url: "URL",
|
|
1262
|
+
phoneNumber: "Phone number",
|
|
1263
|
+
sampleCode: "Sample code",
|
|
1264
|
+
removeButton: "Remove button",
|
|
1265
|
+
addButton: "Add button",
|
|
1266
|
+
variables: "Variables",
|
|
1267
|
+
/** Followed by the variable's number, e.g. "position 1". */
|
|
1268
|
+
variablePosition: "position",
|
|
1269
|
+
exampleValue: "Example value",
|
|
1270
|
+
noVariables: "Type a placeholder such as {{first_name}} in the text to add one.",
|
|
1271
|
+
codeMessage: "Code message",
|
|
1272
|
+
securityRecommendation: "Add \u201Cdo not share this code\u201D",
|
|
1273
|
+
expiresAfter: "Expires after",
|
|
1274
|
+
expiresHint: "minutes, 1 to 90",
|
|
1275
|
+
optional: "optional",
|
|
1276
|
+
/** Default text of new buttons. */
|
|
1277
|
+
newQuickReply: "Reply",
|
|
1278
|
+
newLinkButton: "Open link",
|
|
1279
|
+
newPhoneButton: "Call us"
|
|
1280
|
+
};
|
|
1233
1281
|
var LANGUAGES = [
|
|
1234
1282
|
{ value: "en_US", label: "English (US)" },
|
|
1235
1283
|
{ value: "pt_BR", label: "Portuguese (BR)" },
|
|
1236
1284
|
{ value: "es", label: "Spanish" }
|
|
1237
1285
|
];
|
|
1238
|
-
var
|
|
1239
|
-
{ value: "UTILITY", label:
|
|
1240
|
-
{ value: "MARKETING", label:
|
|
1241
|
-
{ value: "AUTHENTICATION", label:
|
|
1286
|
+
var categories = (l) => [
|
|
1287
|
+
{ value: "UTILITY", label: l.utility },
|
|
1288
|
+
{ value: "MARKETING", label: l.marketing },
|
|
1289
|
+
{ value: "AUTHENTICATION", label: l.authentication }
|
|
1242
1290
|
];
|
|
1243
|
-
var
|
|
1244
|
-
{ value: "NONE", label:
|
|
1245
|
-
{ value: "TEXT", label:
|
|
1246
|
-
{ value: "IMAGE", label:
|
|
1247
|
-
{ value: "VIDEO", label:
|
|
1248
|
-
{ value: "DOCUMENT", label:
|
|
1291
|
+
var headerKinds = (l) => [
|
|
1292
|
+
{ value: "NONE", label: l.headerNone },
|
|
1293
|
+
{ value: "TEXT", label: l.headerText },
|
|
1294
|
+
{ value: "IMAGE", label: l.headerImage },
|
|
1295
|
+
{ value: "VIDEO", label: l.headerVideo },
|
|
1296
|
+
{ value: "DOCUMENT", label: l.headerDocument }
|
|
1249
1297
|
];
|
|
1250
|
-
var BUTTON_TYPES = [
|
|
1251
|
-
|
|
1252
|
-
{ value: "
|
|
1253
|
-
{ value: "
|
|
1254
|
-
{ value: "
|
|
1298
|
+
var BUTTON_TYPES = ["QUICK_REPLY", "URL", "PHONE_NUMBER", "COPY_CODE"];
|
|
1299
|
+
var buttonTypes = (l) => [
|
|
1300
|
+
{ value: "QUICK_REPLY", label: l.quickReply },
|
|
1301
|
+
{ value: "URL", label: l.link },
|
|
1302
|
+
{ value: "PHONE_NUMBER", label: l.phone },
|
|
1303
|
+
{ value: "COPY_CODE", label: l.copyCode }
|
|
1255
1304
|
];
|
|
1256
1305
|
var MAX_BUTTONS = 10;
|
|
1257
1306
|
var count = (text, max) => `${[...text].length}/${max}`;
|
|
1258
1307
|
function editorSections(template, options = {}) {
|
|
1308
|
+
const l = { ...EDITOR_LABELS, ...options.labels };
|
|
1259
1309
|
const basics = {
|
|
1260
1310
|
id: "basics",
|
|
1261
|
-
title:
|
|
1311
|
+
title: l.basics,
|
|
1262
1312
|
rows: [
|
|
1263
1313
|
{
|
|
1264
1314
|
fields: [
|
|
1265
1315
|
{
|
|
1266
1316
|
kind: "text",
|
|
1267
1317
|
id: "name",
|
|
1268
|
-
label:
|
|
1269
|
-
hint:
|
|
1318
|
+
label: l.name,
|
|
1319
|
+
hint: l.nameHint,
|
|
1270
1320
|
value: template.name,
|
|
1271
1321
|
mono: true
|
|
1272
1322
|
}
|
|
@@ -1277,47 +1327,48 @@ function editorSections(template, options = {}) {
|
|
|
1277
1327
|
{
|
|
1278
1328
|
kind: "select",
|
|
1279
1329
|
id: "language",
|
|
1280
|
-
label:
|
|
1330
|
+
label: l.language,
|
|
1281
1331
|
value: template.language,
|
|
1282
1332
|
options: options.languages ?? LANGUAGES
|
|
1283
1333
|
},
|
|
1284
1334
|
{
|
|
1285
1335
|
kind: "segment",
|
|
1286
1336
|
id: "category",
|
|
1287
|
-
label:
|
|
1337
|
+
label: l.category,
|
|
1288
1338
|
value: template.category,
|
|
1289
|
-
options:
|
|
1339
|
+
options: categories(l)
|
|
1290
1340
|
}
|
|
1291
1341
|
]
|
|
1292
1342
|
}
|
|
1293
1343
|
]
|
|
1294
1344
|
};
|
|
1295
1345
|
if (template.category === "AUTHENTICATION")
|
|
1296
|
-
return [basics, codeSection(template)];
|
|
1346
|
+
return [basics, codeSection(template, l)];
|
|
1297
1347
|
return [
|
|
1298
1348
|
basics,
|
|
1299
|
-
contentSection(template),
|
|
1300
|
-
buttonsSection(template),
|
|
1301
|
-
variablesSection(template)
|
|
1349
|
+
contentSection(template, l),
|
|
1350
|
+
buttonsSection(template, l),
|
|
1351
|
+
variablesSection(template, l)
|
|
1302
1352
|
];
|
|
1303
1353
|
}
|
|
1304
|
-
function contentSection(template) {
|
|
1354
|
+
function contentSection(template, l) {
|
|
1305
1355
|
const header2 = template.header;
|
|
1306
|
-
const
|
|
1356
|
+
const kinds = headerKinds(l);
|
|
1357
|
+
const kind = kinds.some((option) => option.value === header2?.type) ? header2.type : "NONE";
|
|
1307
1358
|
const headerRow = [
|
|
1308
1359
|
{
|
|
1309
1360
|
kind: "select",
|
|
1310
1361
|
id: "header.kind",
|
|
1311
|
-
label:
|
|
1362
|
+
label: l.header,
|
|
1312
1363
|
value: kind,
|
|
1313
|
-
options:
|
|
1364
|
+
options: kinds
|
|
1314
1365
|
}
|
|
1315
1366
|
];
|
|
1316
1367
|
if (header2?.type === "TEXT")
|
|
1317
1368
|
headerRow.push({
|
|
1318
1369
|
kind: "text",
|
|
1319
1370
|
id: "header.text",
|
|
1320
|
-
label:
|
|
1371
|
+
label: l.headerTextField,
|
|
1321
1372
|
hint: count(header2.text, 60),
|
|
1322
1373
|
value: header2.text
|
|
1323
1374
|
});
|
|
@@ -1325,13 +1376,13 @@ function contentSection(template) {
|
|
|
1325
1376
|
headerRow.push({
|
|
1326
1377
|
kind: "text",
|
|
1327
1378
|
id: "header.url",
|
|
1328
|
-
label:
|
|
1379
|
+
label: l.sampleFileUrl,
|
|
1329
1380
|
value: header2.url,
|
|
1330
1381
|
mono: true
|
|
1331
1382
|
});
|
|
1332
1383
|
return {
|
|
1333
1384
|
id: "content",
|
|
1334
|
-
title:
|
|
1385
|
+
title: l.content,
|
|
1335
1386
|
rows: [
|
|
1336
1387
|
{ fields: headerRow },
|
|
1337
1388
|
{
|
|
@@ -1339,7 +1390,7 @@ function contentSection(template) {
|
|
|
1339
1390
|
{
|
|
1340
1391
|
kind: "textarea",
|
|
1341
1392
|
id: "body",
|
|
1342
|
-
label:
|
|
1393
|
+
label: l.body,
|
|
1343
1394
|
hint: count(template.body.text, 1024),
|
|
1344
1395
|
value: template.body.text
|
|
1345
1396
|
}
|
|
@@ -1350,35 +1401,35 @@ function contentSection(template) {
|
|
|
1350
1401
|
{
|
|
1351
1402
|
kind: "text",
|
|
1352
1403
|
id: "footer",
|
|
1353
|
-
label:
|
|
1404
|
+
label: l.footer,
|
|
1354
1405
|
hint: count(template.footer?.text ?? "", 60),
|
|
1355
1406
|
value: template.footer?.text ?? ""
|
|
1356
1407
|
}
|
|
1357
1408
|
]
|
|
1358
1409
|
}
|
|
1359
1410
|
],
|
|
1360
|
-
note:
|
|
1411
|
+
note: l.formattingNote
|
|
1361
1412
|
};
|
|
1362
1413
|
}
|
|
1363
|
-
function buttonsSection(template) {
|
|
1414
|
+
function buttonsSection(template, l) {
|
|
1364
1415
|
const buttons = template.buttons ?? [];
|
|
1365
1416
|
const rows = buttons.map((button2, index) => {
|
|
1366
1417
|
const at = `buttons.${index}`;
|
|
1367
|
-
const type = BUTTON_TYPES.
|
|
1418
|
+
const type = BUTTON_TYPES.includes(button2.type) ? button2.type : "QUICK_REPLY";
|
|
1368
1419
|
const fields = [
|
|
1369
1420
|
{
|
|
1370
1421
|
kind: "select",
|
|
1371
1422
|
id: `${at}.type`,
|
|
1372
|
-
label:
|
|
1423
|
+
label: l.buttonType,
|
|
1373
1424
|
value: type,
|
|
1374
|
-
options:
|
|
1425
|
+
options: buttonTypes(l)
|
|
1375
1426
|
}
|
|
1376
1427
|
];
|
|
1377
1428
|
if ("text" in button2 && button2.text !== void 0)
|
|
1378
1429
|
fields.push({
|
|
1379
1430
|
kind: "text",
|
|
1380
1431
|
id: `${at}.text`,
|
|
1381
|
-
label:
|
|
1432
|
+
label: l.buttonText,
|
|
1382
1433
|
hint: count(button2.text, 25),
|
|
1383
1434
|
value: button2.text
|
|
1384
1435
|
});
|
|
@@ -1386,7 +1437,7 @@ function buttonsSection(template) {
|
|
|
1386
1437
|
fields.push({
|
|
1387
1438
|
kind: "text",
|
|
1388
1439
|
id: `${at}.url`,
|
|
1389
|
-
label:
|
|
1440
|
+
label: l.url,
|
|
1390
1441
|
value: button2.url,
|
|
1391
1442
|
mono: true
|
|
1392
1443
|
});
|
|
@@ -1394,7 +1445,7 @@ function buttonsSection(template) {
|
|
|
1394
1445
|
fields.push({
|
|
1395
1446
|
kind: "text",
|
|
1396
1447
|
id: `${at}.phoneNumber`,
|
|
1397
|
-
label:
|
|
1448
|
+
label: l.phoneNumber,
|
|
1398
1449
|
value: button2.phoneNumber,
|
|
1399
1450
|
mono: true
|
|
1400
1451
|
});
|
|
@@ -1402,14 +1453,14 @@ function buttonsSection(template) {
|
|
|
1402
1453
|
fields.push({
|
|
1403
1454
|
kind: "text",
|
|
1404
1455
|
id: `${at}.example`,
|
|
1405
|
-
label:
|
|
1456
|
+
label: l.sampleCode,
|
|
1406
1457
|
value: button2.example,
|
|
1407
1458
|
mono: true
|
|
1408
1459
|
});
|
|
1409
1460
|
fields.push({
|
|
1410
1461
|
kind: "action",
|
|
1411
1462
|
id: `${at}.remove`,
|
|
1412
|
-
label:
|
|
1463
|
+
label: l.removeButton,
|
|
1413
1464
|
icon: "remove"
|
|
1414
1465
|
});
|
|
1415
1466
|
return { fields, list: true };
|
|
@@ -1419,7 +1470,7 @@ function buttonsSection(template) {
|
|
|
1419
1470
|
{
|
|
1420
1471
|
kind: "action",
|
|
1421
1472
|
id: "buttons.add",
|
|
1422
|
-
label:
|
|
1473
|
+
label: l.addButton,
|
|
1423
1474
|
icon: "add",
|
|
1424
1475
|
disabled: buttons.length >= MAX_BUTTONS
|
|
1425
1476
|
}
|
|
@@ -1427,42 +1478,42 @@ function buttonsSection(template) {
|
|
|
1427
1478
|
});
|
|
1428
1479
|
return {
|
|
1429
1480
|
id: "buttons",
|
|
1430
|
-
title:
|
|
1481
|
+
title: `${l.buttons} ${buttons.length}/${MAX_BUTTONS}`,
|
|
1431
1482
|
rows
|
|
1432
1483
|
};
|
|
1433
1484
|
}
|
|
1434
|
-
function variablesSection(template) {
|
|
1485
|
+
function variablesSection(template, l) {
|
|
1435
1486
|
const variables = Object.entries(template.variables ?? {});
|
|
1436
1487
|
return {
|
|
1437
1488
|
id: "variables",
|
|
1438
|
-
title:
|
|
1489
|
+
title: l.variables,
|
|
1439
1490
|
rows: variables.map(([name, variable], index) => ({
|
|
1440
1491
|
fields: [
|
|
1441
1492
|
{
|
|
1442
1493
|
kind: "text",
|
|
1443
1494
|
id: `variables.${name}`,
|
|
1444
1495
|
label: `{{${name}}}`,
|
|
1445
|
-
hint:
|
|
1496
|
+
hint: `${l.variablePosition} ${index + 1}`,
|
|
1446
1497
|
value: variable.example,
|
|
1447
|
-
placeholder:
|
|
1498
|
+
placeholder: l.exampleValue
|
|
1448
1499
|
}
|
|
1449
1500
|
]
|
|
1450
1501
|
})),
|
|
1451
|
-
note: variables.length ? void 0 :
|
|
1502
|
+
note: variables.length ? void 0 : l.noVariables
|
|
1452
1503
|
};
|
|
1453
1504
|
}
|
|
1454
|
-
function codeSection(template) {
|
|
1505
|
+
function codeSection(template, l) {
|
|
1455
1506
|
const minutes = template.footer?.codeExpirationMinutes;
|
|
1456
1507
|
return {
|
|
1457
1508
|
id: "code",
|
|
1458
|
-
title:
|
|
1509
|
+
title: l.codeMessage,
|
|
1459
1510
|
rows: [
|
|
1460
1511
|
{
|
|
1461
1512
|
fields: [
|
|
1462
1513
|
{
|
|
1463
1514
|
kind: "checkbox",
|
|
1464
1515
|
id: "body.addSecurityRecommendation",
|
|
1465
|
-
label:
|
|
1516
|
+
label: l.securityRecommendation,
|
|
1466
1517
|
checked: template.body?.addSecurityRecommendation ?? false
|
|
1467
1518
|
}
|
|
1468
1519
|
]
|
|
@@ -1472,25 +1523,25 @@ function codeSection(template) {
|
|
|
1472
1523
|
{
|
|
1473
1524
|
kind: "text",
|
|
1474
1525
|
id: "footer.codeExpirationMinutes",
|
|
1475
|
-
label:
|
|
1476
|
-
hint:
|
|
1526
|
+
label: l.expiresAfter,
|
|
1527
|
+
hint: l.expiresHint,
|
|
1477
1528
|
value: minutes === void 0 ? "" : String(minutes),
|
|
1478
1529
|
mono: true
|
|
1479
1530
|
},
|
|
1480
1531
|
{
|
|
1481
1532
|
kind: "text",
|
|
1482
1533
|
id: "button.text",
|
|
1483
|
-
label:
|
|
1484
|
-
hint:
|
|
1534
|
+
label: l.buttonText,
|
|
1535
|
+
hint: l.optional,
|
|
1485
1536
|
value: template.button.text ?? "",
|
|
1486
|
-
placeholder:
|
|
1537
|
+
placeholder: l.copyCode
|
|
1487
1538
|
}
|
|
1488
1539
|
]
|
|
1489
1540
|
}
|
|
1490
1541
|
]
|
|
1491
1542
|
};
|
|
1492
1543
|
}
|
|
1493
|
-
function applyEdit(template, id, value, remembered = {}) {
|
|
1544
|
+
function applyEdit(template, id, value, remembered = {}, labels = {}) {
|
|
1494
1545
|
const text = typeof value === "string" ? value : "";
|
|
1495
1546
|
if (id === "name") return { ...template, name: text };
|
|
1496
1547
|
if (id === "language") return { ...template, language: text };
|
|
@@ -1523,9 +1574,12 @@ function applyEdit(template, id, value, remembered = {}) {
|
|
|
1523
1574
|
[id.slice("variables.".length)]: { example: text }
|
|
1524
1575
|
}
|
|
1525
1576
|
};
|
|
1526
|
-
return syncVariables(
|
|
1577
|
+
return syncVariables(
|
|
1578
|
+
editStandard(template, id, text, { ...EDITOR_LABELS, ...labels }),
|
|
1579
|
+
remembered
|
|
1580
|
+
);
|
|
1527
1581
|
}
|
|
1528
|
-
function editStandard(template, id, text) {
|
|
1582
|
+
function editStandard(template, id, text, l) {
|
|
1529
1583
|
if (id === "header.kind") return { ...template, header: newHeader(text) };
|
|
1530
1584
|
if (id === "header.text")
|
|
1531
1585
|
return { ...template, header: { type: "TEXT", text } };
|
|
@@ -1540,7 +1594,7 @@ function editStandard(template, id, text) {
|
|
|
1540
1594
|
buttons: next2.length ? next2 : void 0
|
|
1541
1595
|
});
|
|
1542
1596
|
if (id === "buttons.add")
|
|
1543
|
-
return buttons.length >= MAX_BUTTONS ? template : withButtons([...buttons, newButton("QUICK_REPLY")]);
|
|
1597
|
+
return buttons.length >= MAX_BUTTONS ? template : withButtons([...buttons, newButton(l, "QUICK_REPLY")]);
|
|
1544
1598
|
const match = /^buttons\.(\d+)\.(\w+)$/.exec(id);
|
|
1545
1599
|
if (!match) return template;
|
|
1546
1600
|
const index = Number(match[1]);
|
|
@@ -1550,6 +1604,7 @@ function editStandard(template, id, text) {
|
|
|
1550
1604
|
if (field === "remove")
|
|
1551
1605
|
return withButtons(buttons.filter((_, i) => i !== index));
|
|
1552
1606
|
const next = field === "type" ? newButton(
|
|
1607
|
+
l,
|
|
1553
1608
|
text,
|
|
1554
1609
|
"text" in button2 ? button2.text ?? "" : ""
|
|
1555
1610
|
) : { ...button2, [field]: text };
|
|
@@ -1591,13 +1646,13 @@ function newHeader(kind) {
|
|
|
1591
1646
|
return { type: kind, url: "https://" };
|
|
1592
1647
|
return void 0;
|
|
1593
1648
|
}
|
|
1594
|
-
function newButton(type, label = "") {
|
|
1649
|
+
function newButton(l, type, label = "") {
|
|
1595
1650
|
if (type === "URL")
|
|
1596
|
-
return { type, text: label ||
|
|
1651
|
+
return { type, text: label || l.newLinkButton, url: "https://" };
|
|
1597
1652
|
if (type === "PHONE_NUMBER")
|
|
1598
|
-
return { type, text: label ||
|
|
1653
|
+
return { type, text: label || l.newPhoneButton, phoneNumber: "+" };
|
|
1599
1654
|
if (type === "COPY_CODE") return { type, example: "CODE10" };
|
|
1600
|
-
return { type: "QUICK_REPLY", text: label ||
|
|
1655
|
+
return { type: "QUICK_REPLY", text: label || l.newQuickReply };
|
|
1601
1656
|
}
|
|
1602
1657
|
|
|
1603
1658
|
// src/editor/tree.ts
|
|
@@ -1725,6 +1780,7 @@ function node2(tag, className, attrs, children = []) {
|
|
|
1725
1780
|
return { tag, ...className && { class: className }, attrs, children };
|
|
1726
1781
|
}
|
|
1727
1782
|
export {
|
|
1783
|
+
EDITOR_LABELS,
|
|
1728
1784
|
TemplateValidationError,
|
|
1729
1785
|
UnsupportedByProviderError,
|
|
1730
1786
|
applyEdit,
|