@drghaliasri/butex 5.3.2 → 5.4.0

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.
@@ -694,6 +694,158 @@ function createEmptyDocument() {
694
694
  };
695
695
  }
696
696
 
697
+ // src/editor/accentCommands.ts
698
+ var ACCENT_COMMANDS = {
699
+ vec: {
700
+ id: "vec",
701
+ englishTex: "\\vec",
702
+ arabicTex: "\\arabvec",
703
+ placement: "over",
704
+ label: "\u20D7",
705
+ title: "\u0633\u0647\u0645 \u0641\u0648\u0642"
706
+ },
707
+ hat: {
708
+ id: "hat",
709
+ englishTex: "\\hat",
710
+ arabicTex: "\\hat",
711
+ placement: "over",
712
+ label: "\u02C6",
713
+ title: "\u0642\u0628\u0639\u0629"
714
+ },
715
+ tilde: {
716
+ id: "tilde",
717
+ englishTex: "\\tilde",
718
+ arabicTex: "\\tilde",
719
+ placement: "over",
720
+ label: "\u02DC",
721
+ title: "\u0645\u062F\u0629"
722
+ },
723
+ dot: {
724
+ id: "dot",
725
+ englishTex: "\\dot",
726
+ arabicTex: "\\dot",
727
+ placement: "over",
728
+ label: "\u02D9",
729
+ title: "\u0646\u0642\u0637\u0629 \u0641\u0648\u0642"
730
+ },
731
+ ddot: {
732
+ id: "ddot",
733
+ englishTex: "\\ddot",
734
+ arabicTex: "\\ddot",
735
+ placement: "over",
736
+ label: "\xA8",
737
+ title: "\u0646\u0642\u0637\u062A\u0627\u0646 \u0641\u0648\u0642"
738
+ },
739
+ dddot: {
740
+ id: "dddot",
741
+ englishTex: "\\dddot",
742
+ arabicTex: "\\dddot",
743
+ placement: "over",
744
+ label: "\u20DB",
745
+ title: "\u062B\u0644\u0627\u062B \u0646\u0642\u0627\u0637 \u0641\u0648\u0642"
746
+ },
747
+ bar: {
748
+ id: "bar",
749
+ englishTex: "\\bar",
750
+ arabicTex: "\\bar",
751
+ placement: "over",
752
+ label: "\xAF",
753
+ title: "\u062E\u0637 \u0641\u0648\u0642"
754
+ },
755
+ check: {
756
+ id: "check",
757
+ englishTex: "\\check",
758
+ arabicTex: "\\check",
759
+ placement: "over",
760
+ label: "\u02C7",
761
+ title: "\u0639\u0644\u0627\u0645\u0629 \u062A\u062D\u0642\u0642"
762
+ },
763
+ breve: {
764
+ id: "breve",
765
+ englishTex: "\\breve",
766
+ arabicTex: "\\breve",
767
+ placement: "over",
768
+ label: "\u02D8",
769
+ title: "\u0642\u0648\u0633 \u0642\u0635\u064A\u0631"
770
+ },
771
+ acute: {
772
+ id: "acute",
773
+ englishTex: "\\acute",
774
+ arabicTex: "\\grave",
775
+ placement: "over",
776
+ label: "\xB4",
777
+ title: "\u0646\u0628\u0631\u0629 \u062D\u0627\u062F\u0629"
778
+ },
779
+ grave: {
780
+ id: "grave",
781
+ englishTex: "\\grave",
782
+ arabicTex: "\\acute",
783
+ placement: "over",
784
+ label: "`",
785
+ title: "\u0646\u0628\u0631\u0629 \u062B\u0642\u064A\u0644\u0629"
786
+ },
787
+ overline: {
788
+ id: "overline",
789
+ englishTex: "\\overline",
790
+ arabicTex: "\\overline",
791
+ placement: "over",
792
+ label: "\u203E",
793
+ title: "\u062E\u0637 \u0639\u0644\u0648\u064A \u0645\u0645\u062A\u062F"
794
+ },
795
+ underline: {
796
+ id: "underline",
797
+ englishTex: "\\underline",
798
+ arabicTex: "\\underline",
799
+ placement: "under",
800
+ label: "_",
801
+ title: "\u062E\u0637 \u0633\u0641\u0644\u064A"
802
+ },
803
+ overleftarrow: {
804
+ id: "overleftarrow",
805
+ englishTex: "\\overleftarrow",
806
+ arabicTex: "\\overrightarrow",
807
+ placement: "over",
808
+ label: "\u2190",
809
+ title: "\u0633\u0647\u0645 \u0639\u0644\u0648\u064A \u0625\u0644\u0649 \u0627\u0644\u064A\u0633\u0627\u0631"
810
+ },
811
+ overrightarrow: {
812
+ id: "overrightarrow",
813
+ englishTex: "\\overrightarrow",
814
+ arabicTex: "\\overleftarrow",
815
+ placement: "over",
816
+ label: "\u2192",
817
+ title: "\u0633\u0647\u0645 \u0639\u0644\u0648\u064A \u0625\u0644\u0649 \u0627\u0644\u064A\u0645\u064A\u0646"
818
+ },
819
+ overleftrightarrow: {
820
+ id: "overleftrightarrow",
821
+ englishTex: "\\overleftrightarrow",
822
+ arabicTex: "\\overleftrightarrow",
823
+ placement: "over",
824
+ label: "\u2194",
825
+ title: "\u0633\u0647\u0645 \u0639\u0644\u0648\u064A \u0645\u0632\u062F\u0648\u062C \u0627\u0644\u0627\u062A\u062C\u0627\u0647"
826
+ }
827
+ };
828
+ function accentCommandSpec(id) {
829
+ return Object.prototype.hasOwnProperty.call(ACCENT_COMMANDS, id) ? ACCENT_COMMANDS[id] : null;
830
+ }
831
+ function accentCommandsList() {
832
+ return Object.values(ACCENT_COMMANDS);
833
+ }
834
+ function accentCommandIdFromTex(tex) {
835
+ const normalized = tex.startsWith("\\") ? tex : `\\${tex}`;
836
+ for (const spec of Object.values(ACCENT_COMMANDS)) {
837
+ if (spec.englishTex === normalized) {
838
+ return spec.id;
839
+ }
840
+ }
841
+ for (const spec of Object.values(ACCENT_COMMANDS)) {
842
+ if (spec.arabicTex === normalized) {
843
+ return spec.id;
844
+ }
845
+ }
846
+ return null;
847
+ }
848
+
697
849
  // src/editor/atomicCommands.ts
698
850
  var ATOMIC_COMMANDS = {
699
851
  ///////////////////////// Functions ////////////////////////////////
@@ -1114,7 +1266,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1114
1266
  id: "neq",
1115
1267
  category: "operators1",
1116
1268
  Tex: "\\neq",
1117
- mirror: false,
1269
+ mirror: true,
1118
1270
  Label: "\u2260",
1119
1271
  title: "\u0644\u0627 \u064A\u0633\u0627\u0648\u064A",
1120
1272
  svg_path: null
@@ -1124,6 +1276,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1124
1276
  category: "operators1",
1125
1277
  Tex: "\\approx",
1126
1278
  mirror: false,
1279
+ displayMirror: true,
1127
1280
  Label: "\u2248",
1128
1281
  title: "\u062A\u0642\u0631\u064A\u0628\u0627 \u064A\u0633\u0627\u0648\u064A",
1129
1282
  svg_path: null
@@ -1133,6 +1286,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1133
1286
  category: "operators1",
1134
1287
  Tex: "\\sim",
1135
1288
  mirror: false,
1289
+ displayMirror: true,
1136
1290
  Label: "\u223C",
1137
1291
  title: "\u0645\u0634\u0627\u0628\u0647",
1138
1292
  svg_path: null
@@ -1151,6 +1305,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1151
1305
  category: "operators1",
1152
1306
  Tex: "\\leq",
1153
1307
  mirror: true,
1308
+ displayMirror: false,
1154
1309
  Label: "\u2264",
1155
1310
  title: "\u0623\u0635\u063A\u0631 \u0645\u0646 \u0623\u0648 \u064A\u0633\u0627\u0648\u064A",
1156
1311
  svg_path: null
@@ -1160,6 +1315,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1160
1315
  category: "operators1",
1161
1316
  Tex: "\\geq",
1162
1317
  mirror: true,
1318
+ displayMirror: false,
1163
1319
  Label: "\u2265",
1164
1320
  title: "\u0623\u0643\u0628\u0631 \u0645\u0646 \u0623\u0648 \u064A\u0633\u0627\u0648\u064A",
1165
1321
  svg_path: null
@@ -1169,6 +1325,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1169
1325
  category: "operators1",
1170
1326
  Tex: "\\coloneqq",
1171
1327
  mirror: true,
1328
+ displayMirror: false,
1172
1329
  Label: "\u2254",
1173
1330
  title: "\u064A\u0639\u0631\u0641 \u0628\u0623\u0646\u0647 \u064A\u0633\u0627\u0648\u064A",
1174
1331
  svg_path: null
@@ -1178,6 +1335,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1178
1335
  category: "operators1",
1179
1336
  Tex: "\\eqqcolon",
1180
1337
  mirror: true,
1338
+ displayMirror: false,
1181
1339
  Label: "\u2255",
1182
1340
  title: "\u064A\u0633\u0627\u0648\u064A \u0628\u0627\u0644\u062A\u0639\u0631\u064A\u0641",
1183
1341
  svg_path: null
@@ -1188,6 +1346,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1188
1346
  category: "operators2",
1189
1347
  Tex: "\\propto",
1190
1348
  mirror: true,
1349
+ displayMirror: false,
1191
1350
  Label: "\u221D",
1192
1351
  title: "\u064A\u062A\u0646\u0627\u0633\u0628 \u0645\u0639",
1193
1352
  svg_path: null
@@ -1197,6 +1356,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1197
1356
  category: "operators2",
1198
1357
  Tex: "\\in",
1199
1358
  mirror: true,
1359
+ displayMirror: false,
1200
1360
  Label: "\u2208",
1201
1361
  title: "\u064A\u0646\u062A\u0645\u064A \u0625\u0644\u0649",
1202
1362
  svg_path: null
@@ -1206,6 +1366,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1206
1366
  category: "operators2",
1207
1367
  Tex: "\\notin",
1208
1368
  mirror: false,
1369
+ displayMirror: true,
1209
1370
  Label: "\u2209",
1210
1371
  title: "\u0644\u0627 \u064A\u0646\u062A\u0645\u064A \u0625\u0644\u0649",
1211
1372
  svg_path: null
@@ -1215,6 +1376,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1215
1376
  category: "operators2",
1216
1377
  Tex: "\\subset",
1217
1378
  mirror: true,
1379
+ displayMirror: false,
1218
1380
  Label: "\u2282",
1219
1381
  title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u062C\u0632\u0626\u064A\u0629 \u0645\u0646",
1220
1382
  svg_path: null
@@ -1224,6 +1386,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1224
1386
  category: "operators2",
1225
1387
  Tex: "\\supset",
1226
1388
  mirror: true,
1389
+ displayMirror: false,
1227
1390
  Label: "\u2283",
1228
1391
  title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u0634\u0627\u0645\u0644\u0629 \u0644\u0640",
1229
1392
  svg_path: null
@@ -1233,6 +1396,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1233
1396
  category: "operators2",
1234
1397
  Tex: "\\subseteq",
1235
1398
  mirror: true,
1399
+ displayMirror: false,
1236
1400
  Label: "\u2286",
1237
1401
  title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u062C\u0632\u0626\u064A\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
1238
1402
  svg_path: null
@@ -1242,6 +1406,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1242
1406
  category: "operators2",
1243
1407
  Tex: "\\supseteq",
1244
1408
  mirror: true,
1409
+ displayMirror: false,
1245
1410
  Label: "\u2287",
1246
1411
  title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u0634\u0627\u0645\u0644\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
1247
1412
  svg_path: null
@@ -1251,6 +1416,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1251
1416
  category: "operators2",
1252
1417
  Tex: "\\cap",
1253
1418
  mirror: false,
1419
+ displayMirror: true,
1254
1420
  Label: "\u2229",
1255
1421
  title: "\u062A\u0642\u0627\u0637\u0639",
1256
1422
  svg_path: null
@@ -1260,6 +1426,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1260
1426
  category: "operators2",
1261
1427
  Tex: "\\cup",
1262
1428
  mirror: false,
1429
+ displayMirror: true,
1263
1430
  Label: "\u222A",
1264
1431
  title: "\u0627\u062A\u062D\u0627\u062F",
1265
1432
  svg_path: null
@@ -1269,6 +1436,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1269
1436
  category: "operators2",
1270
1437
  Tex: "\\emptyset",
1271
1438
  mirror: false,
1439
+ displayMirror: true,
1272
1440
  Label: "\u2205",
1273
1441
  title: "\u0627\u0644\u0645\u062C\u0645\u0648\u0639\u0629 \u0627\u0644\u062E\u0627\u0644\u064A\u0629",
1274
1442
  svg_path: null
@@ -1278,6 +1446,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1278
1446
  category: "operators2",
1279
1447
  Tex: "\\nsubseteq",
1280
1448
  mirror: true,
1449
+ displayMirror: false,
1281
1450
  Label: "\u2288",
1282
1451
  title: "\u0644\u064A\u0633\u062A \u0645\u062C\u0645\u0648\u0639\u0629 \u062C\u0632\u0626\u064A\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
1283
1452
  svg_path: null
@@ -1287,6 +1456,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1287
1456
  category: "operators2",
1288
1457
  Tex: "\\nsupseteq",
1289
1458
  mirror: true,
1459
+ displayMirror: false,
1290
1460
  Label: "\u2289",
1291
1461
  title: "\u0644\u064A\u0633\u062A \u0645\u062C\u0645\u0648\u0639\u0629 \u0634\u0627\u0645\u0644\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
1292
1462
  svg_path: null
@@ -1498,6 +1668,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1498
1668
  category: "integrals",
1499
1669
  Tex: "\\iint",
1500
1670
  mirror: true,
1671
+ displayMirror: false,
1501
1672
  Label: "\u222C",
1502
1673
  title: "\u062A\u0643\u0627\u0645\u0644 \u0645\u0632\u062F\u0648\u062C",
1503
1674
  svg_path: null
@@ -1507,6 +1678,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1507
1678
  category: "integrals",
1508
1679
  Tex: "\\iiint",
1509
1680
  mirror: true,
1681
+ displayMirror: false,
1510
1682
  Label: "\u222D",
1511
1683
  title: "\u062A\u0643\u0627\u0645\u0644 \u062B\u0644\u0627\u062B\u064A",
1512
1684
  svg_path: null
@@ -1516,6 +1688,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1516
1688
  category: "integrals",
1517
1689
  Tex: "\\iiiint",
1518
1690
  mirror: true,
1691
+ displayMirror: false,
1519
1692
  Label: "\u2A0C",
1520
1693
  title: "\u062A\u0643\u0627\u0645\u0644 \u0631\u0628\u0627\u0639\u064A",
1521
1694
  svg_path: null
@@ -1525,6 +1698,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1525
1698
  category: "integrals",
1526
1699
  Tex: "\\oint",
1527
1700
  mirror: true,
1701
+ displayMirror: false,
1528
1702
  Label: "\u222E",
1529
1703
  title: "\u062A\u0643\u0627\u0645\u0644 \u0645\u063A\u0644\u0642",
1530
1704
  svg_path: null
@@ -1534,6 +1708,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1534
1708
  category: "integrals",
1535
1709
  Tex: "\\oiint",
1536
1710
  mirror: true,
1711
+ displayMirror: false,
1537
1712
  Label: "\u222F",
1538
1713
  title: "\u062A\u0643\u0627\u0645\u0644 \u0633\u0637\u062D\u064A \u0645\u063A\u0644\u0642",
1539
1714
  svg_path: null
@@ -1543,6 +1718,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1543
1718
  category: "integrals",
1544
1719
  Tex: "\\oiiint",
1545
1720
  mirror: true,
1721
+ displayMirror: false,
1546
1722
  Label: "\u2230",
1547
1723
  title: "\u062A\u0643\u0627\u0645\u0644 \u062D\u062C\u0645\u064A \u0645\u063A\u0644\u0642",
1548
1724
  svg_path: null
@@ -1644,6 +1820,9 @@ function createEditorNode(kind, expr) {
1644
1820
  denominator: null,
1645
1821
  radicand: null,
1646
1822
  rootIndex: null,
1823
+ overExpr: null,
1824
+ underExpr: null,
1825
+ baseExpr: null,
1647
1826
  envName: null,
1648
1827
  matrixStyle: null,
1649
1828
  matrixRows: null,
@@ -1672,6 +1851,26 @@ function createSqrtNode() {
1672
1851
  rootIndex: createEditorChain()
1673
1852
  };
1674
1853
  }
1854
+ function createOversetNode() {
1855
+ return {
1856
+ ...createEditorNode("overset", ""),
1857
+ overExpr: createEditorChain(),
1858
+ baseExpr: createEditorChain()
1859
+ };
1860
+ }
1861
+ function createUndersetNode() {
1862
+ return {
1863
+ ...createEditorNode("underset", ""),
1864
+ underExpr: createEditorChain(),
1865
+ baseExpr: createEditorChain()
1866
+ };
1867
+ }
1868
+ function createAccentNode(accentId) {
1869
+ return {
1870
+ ...createEditorNode("accent", accentId),
1871
+ baseExpr: createEditorChain()
1872
+ };
1873
+ }
1675
1874
  function createGridEnvNode(envName, rows, columns, columnAlignments) {
1676
1875
  const safeRows = Math.max(1, Math.min(12, Math.trunc(rows)));
1677
1876
  const safeColumns = Math.max(1, Math.min(12, Math.trunc(columns)));
@@ -1736,6 +1935,15 @@ function collectNodeIds(chain, ids) {
1736
1935
  if (node.radicand) {
1737
1936
  collectNodeIds(node.radicand, ids);
1738
1937
  }
1938
+ if (node.overExpr) {
1939
+ collectNodeIds(node.overExpr, ids);
1940
+ }
1941
+ if (node.underExpr) {
1942
+ collectNodeIds(node.underExpr, ids);
1943
+ }
1944
+ if (node.baseExpr) {
1945
+ collectNodeIds(node.baseExpr, ids);
1946
+ }
1739
1947
  if (node.matrixRows) {
1740
1948
  for (const row of node.matrixRows) {
1741
1949
  for (const cell of row) {
@@ -1900,6 +2108,22 @@ function renderMatrixRowsArabic(node, options) {
1900
2108
  }
1901
2109
  return `\\begin{${envName}}${rows.join(" \\\\\n")}\\end{${envName}}`;
1902
2110
  }
2111
+ function renderAccentEnglish(command, accent, base, options) {
2112
+ const baseTex = base ? renderChainEnglish(base, options) : "";
2113
+ const accentTex = accent ? renderChainEnglish(accent, options) : "";
2114
+ if (accentTex === "") {
2115
+ return baseTex;
2116
+ }
2117
+ return `\\${command}{${accentTex}}{${baseTex}}`;
2118
+ }
2119
+ function renderAccentArabic(command, accent, base, options) {
2120
+ const baseTex = base ? renderChainArabic(base, options) : "";
2121
+ const accentTex = accent ? renderChainArabic(accent, options) : "";
2122
+ if (accentTex === "") {
2123
+ return baseTex;
2124
+ }
2125
+ return `\\${command}{${accentTex}}{${baseTex}}`;
2126
+ }
1903
2127
  function escapeText(s) {
1904
2128
  return s.replace(/\\/g, "\\textbackslash{}").replace(/[{}]/g, "\\$&");
1905
2129
  }
@@ -1929,6 +2153,19 @@ function renderNodeEnglish(node, options) {
1929
2153
  const body = `\\sqrt${optionalRootIndexEnglish(node, options)}{${renderChainEnglish(node.radicand, options)}}`;
1930
2154
  return `${body}${latinScripts(node, options)}`;
1931
2155
  }
2156
+ if (node.kind === "overset" && node.baseExpr) {
2157
+ const body = renderAccentEnglish("overset", node.overExpr, node.baseExpr, options);
2158
+ return `${body}${latinScripts(node, options)}`;
2159
+ }
2160
+ if (node.kind === "underset" && node.baseExpr) {
2161
+ const body = renderAccentEnglish("underset", node.underExpr, node.baseExpr, options);
2162
+ return `${body}${latinScripts(node, options)}`;
2163
+ }
2164
+ if (node.kind === "accent" && node.baseExpr) {
2165
+ const cmd = accentCommandSpec(node.expr)?.englishTex ?? `\\${node.expr}`;
2166
+ const body = `${cmd}{${renderChainEnglish(node.baseExpr, options)}}`;
2167
+ return `${body}${latinScripts(node, options)}`;
2168
+ }
1932
2169
  if (node.kind === "env") {
1933
2170
  return `${renderMatrixRowsEnglish(node, options)}${latinScripts(node, options)}`;
1934
2171
  }
@@ -1961,6 +2198,19 @@ function renderNodeArabic(node, options) {
1961
2198
  const content = `\\arabsqrt${optionalRootIndexArabic(node, options)}{${renderChainArabic(node.radicand, options)}}`;
1962
2199
  return arabicScripts(node, content, options);
1963
2200
  }
2201
+ if (node.kind === "overset" && node.baseExpr) {
2202
+ const content = renderAccentArabic("overset", node.overExpr, node.baseExpr, options);
2203
+ return arabicScripts(node, content, options);
2204
+ }
2205
+ if (node.kind === "underset" && node.baseExpr) {
2206
+ const content = renderAccentArabic("underset", node.underExpr, node.baseExpr, options);
2207
+ return arabicScripts(node, content, options);
2208
+ }
2209
+ if (node.kind === "accent" && node.baseExpr) {
2210
+ const cmd = accentCommandSpec(node.expr)?.arabicTex ?? `\\${node.expr}`;
2211
+ const content = `${cmd}{${renderChainArabic(node.baseExpr, options)}}`;
2212
+ return arabicScripts(node, content, options);
2213
+ }
1964
2214
  if (node.kind === "env") {
1965
2215
  return arabicScripts(node, renderMatrixRowsArabic(node, options), options);
1966
2216
  }
@@ -2017,6 +2267,35 @@ function collectCaretPositions(chain) {
2017
2267
  if (node.radicand) {
2018
2268
  walkChain(node.radicand);
2019
2269
  }
2270
+ if (node.kind === "overset") {
2271
+ if (node.overExpr) {
2272
+ walkChain(node.overExpr);
2273
+ }
2274
+ if (node.baseExpr) {
2275
+ walkChain(node.baseExpr);
2276
+ }
2277
+ } else if (node.kind === "underset") {
2278
+ if (node.baseExpr) {
2279
+ walkChain(node.baseExpr);
2280
+ }
2281
+ if (node.underExpr) {
2282
+ walkChain(node.underExpr);
2283
+ }
2284
+ } else if (node.kind === "accent") {
2285
+ if (node.baseExpr) {
2286
+ walkChain(node.baseExpr);
2287
+ }
2288
+ } else {
2289
+ if (node.overExpr) {
2290
+ walkChain(node.overExpr);
2291
+ }
2292
+ if (node.underExpr) {
2293
+ walkChain(node.underExpr);
2294
+ }
2295
+ if (node.baseExpr) {
2296
+ walkChain(node.baseExpr);
2297
+ }
2298
+ }
2020
2299
  if (node.matrixRows) {
2021
2300
  for (const row of node.matrixRows) {
2022
2301
  for (const cell of row) {
@@ -2150,6 +2429,42 @@ function findChainById(root, chainId) {
2150
2429
  return nested;
2151
2430
  }
2152
2431
  }
2432
+ if (node.overExpr) {
2433
+ if (node.overExpr.id === chainId) {
2434
+ return {
2435
+ chain: node.overExpr,
2436
+ relation: { kind: "overExpr", ownerNodeId: node.id, ownerChainId: root.id }
2437
+ };
2438
+ }
2439
+ const nested = findChainById(node.overExpr, chainId);
2440
+ if (nested) {
2441
+ return nested;
2442
+ }
2443
+ }
2444
+ if (node.underExpr) {
2445
+ if (node.underExpr.id === chainId) {
2446
+ return {
2447
+ chain: node.underExpr,
2448
+ relation: { kind: "underExpr", ownerNodeId: node.id, ownerChainId: root.id }
2449
+ };
2450
+ }
2451
+ const nested = findChainById(node.underExpr, chainId);
2452
+ if (nested) {
2453
+ return nested;
2454
+ }
2455
+ }
2456
+ if (node.baseExpr) {
2457
+ if (node.baseExpr.id === chainId) {
2458
+ return {
2459
+ chain: node.baseExpr,
2460
+ relation: { kind: "baseExpr", ownerNodeId: node.id, ownerChainId: root.id }
2461
+ };
2462
+ }
2463
+ const nested = findChainById(node.baseExpr, chainId);
2464
+ if (nested) {
2465
+ return nested;
2466
+ }
2467
+ }
2153
2468
  if (node.matrixRows) {
2154
2469
  for (let rowIndex = 0; rowIndex < node.matrixRows.length; rowIndex += 1) {
2155
2470
  const row = node.matrixRows[rowIndex];
@@ -2223,6 +2538,24 @@ function findNodeById(root, nodeId) {
2223
2538
  return nested;
2224
2539
  }
2225
2540
  }
2541
+ if (node.overExpr) {
2542
+ const nested = findNodeById(node.overExpr, nodeId);
2543
+ if (nested) {
2544
+ return nested;
2545
+ }
2546
+ }
2547
+ if (node.underExpr) {
2548
+ const nested = findNodeById(node.underExpr, nodeId);
2549
+ if (nested) {
2550
+ return nested;
2551
+ }
2552
+ }
2553
+ if (node.baseExpr) {
2554
+ const nested = findNodeById(node.baseExpr, nodeId);
2555
+ if (nested) {
2556
+ return nested;
2557
+ }
2558
+ }
2226
2559
  if (node.matrixRows) {
2227
2560
  for (const row of node.matrixRows) {
2228
2561
  for (const cell of row) {
@@ -2258,6 +2591,15 @@ function nodeChildChains(node) {
2258
2591
  if (node.radicand) {
2259
2592
  chains.push(node.radicand);
2260
2593
  }
2594
+ if (node.overExpr) {
2595
+ chains.push(node.overExpr);
2596
+ }
2597
+ if (node.underExpr) {
2598
+ chains.push(node.underExpr);
2599
+ }
2600
+ if (node.baseExpr) {
2601
+ chains.push(node.baseExpr);
2602
+ }
2261
2603
  if (node.matrixRows) {
2262
2604
  for (const row of node.matrixRows) {
2263
2605
  chains.push(...row);
@@ -2628,6 +2970,91 @@ function derivativeTemplateInitialCaret(englishFrac) {
2628
2970
  };
2629
2971
  }
2630
2972
 
2973
+ // src/editor/limitsTemplates.ts
2974
+ var LIMITS_SERIES_TEMPLATE_IDS = /* @__PURE__ */ new Set([
2975
+ "sum",
2976
+ "prod",
2977
+ "lim",
2978
+ "max",
2979
+ "min",
2980
+ "sup",
2981
+ "inf"
2982
+ ]);
2983
+ function isLimitsSeriesTemplateId(commandId) {
2984
+ return LIMITS_SERIES_TEMPLATE_IDS.has(commandId);
2985
+ }
2986
+ function syncChainIds2(english, arabic) {
2987
+ arabic.id = english.id;
2988
+ const limit = Math.min(english.nodes.length, arabic.nodes.length);
2989
+ for (let index = 0; index < limit; index += 1) {
2990
+ arabic.nodes[index].id = english.nodes[index].id;
2991
+ }
2992
+ }
2993
+ function syncOversetIds(english, arabic) {
2994
+ arabic.id = english.id;
2995
+ if (english.overExpr && arabic.overExpr) {
2996
+ syncChainIds2(english.overExpr, arabic.overExpr);
2997
+ }
2998
+ if (english.baseExpr && arabic.baseExpr) {
2999
+ syncChainIds2(english.baseExpr, arabic.baseExpr);
3000
+ }
3001
+ }
3002
+ function syncUndersetIds(english, arabic) {
3003
+ arabic.id = english.id;
3004
+ if (english.underExpr && arabic.underExpr) {
3005
+ syncChainIds2(english.underExpr, arabic.underExpr);
3006
+ }
3007
+ if (english.baseExpr && arabic.baseExpr) {
3008
+ syncChainIds2(english.baseExpr, arabic.baseExpr);
3009
+ }
3010
+ }
3011
+ function buildLimitsSeriesTemplate(commandId) {
3012
+ if (!isLimitsSeriesTemplateId(commandId)) {
3013
+ throw new Error(`BuTeX: unsupported limits-series template id: ${commandId}`);
3014
+ }
3015
+ const englishOp = createAtomicCommandNode(commandId);
3016
+ const arabicOp = createAtomicCommandNode(commandId);
3017
+ arabicOp.id = englishOp.id;
3018
+ const englishOverset = createOversetNode();
3019
+ const arabicOverset = createOversetNode();
3020
+ syncOversetIds(englishOverset, arabicOverset);
3021
+ englishOverset.baseExpr = createEditorChain([englishOp]);
3022
+ arabicOverset.baseExpr = createEditorChain([arabicOp]);
3023
+ syncChainIds2(englishOverset.baseExpr, arabicOverset.baseExpr);
3024
+ const englishUnderset = createUndersetNode();
3025
+ const arabicUnderset = createUndersetNode();
3026
+ syncUndersetIds(englishUnderset, arabicUnderset);
3027
+ englishUnderset.baseExpr = createEditorChain([englishOverset]);
3028
+ arabicUnderset.baseExpr = createEditorChain([arabicOverset]);
3029
+ syncChainIds2(englishUnderset.baseExpr, arabicUnderset.baseExpr);
3030
+ return { english: englishUnderset, arabic: arabicUnderset };
3031
+ }
3032
+ function buildAccentPairTemplate() {
3033
+ const englishOverset = createOversetNode();
3034
+ const arabicOverset = createOversetNode();
3035
+ syncOversetIds(englishOverset, arabicOverset);
3036
+ const englishUnderset = createUndersetNode();
3037
+ const arabicUnderset = createUndersetNode();
3038
+ syncUndersetIds(englishUnderset, arabicUnderset);
3039
+ englishUnderset.baseExpr = createEditorChain([englishOverset]);
3040
+ arabicUnderset.baseExpr = createEditorChain([arabicOverset]);
3041
+ syncChainIds2(englishUnderset.baseExpr, arabicUnderset.baseExpr);
3042
+ return { english: englishUnderset, arabic: arabicUnderset };
3043
+ }
3044
+ function accentPairTemplateInitialCaret(englishUnderset) {
3045
+ const overset = englishUnderset.baseExpr?.nodes[0];
3046
+ return {
3047
+ chainId: overset?.baseExpr?.id ?? englishUnderset.underExpr?.id ?? "",
3048
+ index: 0
3049
+ };
3050
+ }
3051
+ function limitsSeriesTemplateInitialCaret(englishUnderset) {
3052
+ return {
3053
+ chainId: englishUnderset.underExpr?.id ?? englishUnderset.baseExpr?.id ?? "",
3054
+ index: 0
3055
+ };
3056
+ }
3057
+
2631
3058
  // src/editor/uiLocale.ts
2632
3059
  var ENGLISH_COMMAND_TITLES = {
2633
3060
  cos: "Cosine",
@@ -2671,6 +3098,24 @@ var ENGLISH_COMMAND_TITLES = {
2671
3098
  quadSpace: "Large space",
2672
3099
  qquadSpace: "Extra-large space"
2673
3100
  };
3101
+ var ENGLISH_ACCENT_TITLES = {
3102
+ vec: "Vector arrow",
3103
+ hat: "Hat",
3104
+ tilde: "Tilde",
3105
+ dot: "Dot",
3106
+ ddot: "Double dot",
3107
+ dddot: "Triple dot",
3108
+ bar: "Bar",
3109
+ check: "Check",
3110
+ breve: "Breve",
3111
+ acute: "Acute",
3112
+ grave: "Grave",
3113
+ overline: "Overline",
3114
+ underline: "Underline",
3115
+ overleftarrow: "Over left arrow",
3116
+ overrightarrow: "Over right arrow",
3117
+ overleftrightarrow: "Over left-right arrow"
3118
+ };
2674
3119
  var ENGLISH_OPERATOR_TITLES = {
2675
3120
  inf: "Infinity",
2676
3121
  times: "Multiplication",
@@ -2744,6 +3189,10 @@ var EQUATION_EDITOR_MESSAGES = {
2744
3189
  insertBraces: "\u0625\u062F\u0631\u0627\u062C \u062D\u0627\u0635\u0631\u062A\u064A\u0646",
2745
3190
  insertFraction: "\u0625\u062F\u0631\u0627\u062C \u0643\u0633\u0631",
2746
3191
  insertRoot: "\u0625\u062F\u0631\u0627\u062C \u062C\u0630\u0631",
3192
+ insertOverset: "\u0625\u062F\u0631\u0627\u062C \u0641\u0648\u0642",
3193
+ insertUnderset: "\u0625\u062F\u0631\u0627\u062C \u062A\u062D\u062A",
3194
+ insertAccentPair: "\u0625\u062F\u0631\u0627\u062C \u0641\u0648\u0642 \u0648\u062A\u062D\u062A",
3195
+ insertAccents: "\u0625\u062F\u0631\u0627\u062C \u0644\u0643\u0646\u0629",
2747
3196
  environments: "\u0627\u0644\u0628\u064A\u0626\u0627\u062A",
2748
3197
  insertEnvironment: "\u0625\u062F\u0631\u0627\u062C \u0628\u064A\u0626\u0629 \u0634\u0628\u0643\u064A\u0629",
2749
3198
  environmentType: "\u0646\u0648\u0639 \u0627\u0644\u0628\u064A\u0626\u0629",
@@ -2851,6 +3300,10 @@ var EQUATION_EDITOR_MESSAGES = {
2851
3300
  insertBraces: "Insert braces",
2852
3301
  insertFraction: "Insert fraction",
2853
3302
  insertRoot: "Insert root",
3303
+ insertOverset: "Insert overset",
3304
+ insertUnderset: "Insert underset",
3305
+ insertAccentPair: "Insert overset and underset",
3306
+ insertAccents: "Insert accent",
2854
3307
  environments: "Environments",
2855
3308
  insertEnvironment: "Insert grid environment",
2856
3309
  environmentType: "Environment type",
@@ -2951,6 +3404,9 @@ function atomicCommandTitle(spec, locale) {
2951
3404
  function atomicOperatorCommandTitle(spec, locale) {
2952
3405
  return locale === "en" ? ENGLISH_OPERATOR_TITLES[spec.id] ?? spec.title : spec.title;
2953
3406
  }
3407
+ function accentCommandTitle(spec, locale) {
3408
+ return locale === "en" ? ENGLISH_ACCENT_TITLES[spec.id] ?? spec.title : spec.title;
3409
+ }
2954
3410
 
2955
3411
  // src/editor/state.ts
2956
3412
  function ensureSyncEntry(session, nodeId) {
@@ -2985,7 +3441,7 @@ function syncSelectionToCaret(session) {
2985
3441
  session.selectedNodeId = located.relation.ownerNodeId;
2986
3442
  return;
2987
3443
  }
2988
- if (located.relation.kind === "inner" || located.relation.kind === "numerator" || located.relation.kind === "denominator" || located.relation.kind === "radicand" || located.relation.kind === "rootIndex" || located.relation.kind === "matrixCell") {
3444
+ if (located.relation.kind === "inner" || located.relation.kind === "numerator" || located.relation.kind === "denominator" || located.relation.kind === "radicand" || located.relation.kind === "rootIndex" || located.relation.kind === "overExpr" || located.relation.kind === "underExpr" || located.relation.kind === "baseExpr" || located.relation.kind === "matrixCell") {
2989
3445
  session.selectedNodeId = located.relation.ownerNodeId;
2990
3446
  return;
2991
3447
  }
@@ -3342,6 +3798,106 @@ function moveCaretVertical(session, direction) {
3342
3798
  appendDebug(next, "moveCaretVertical", "sqrt-radicand-down-exit");
3343
3799
  return next;
3344
3800
  }
3801
+ if (located.relation.kind === "overExpr" && ownerLocated && ownerNode && ownerNode.baseExpr) {
3802
+ if (direction === "down") {
3803
+ next.caret = {
3804
+ chainId: ownerNode.baseExpr.id,
3805
+ index: ownerNode.baseExpr.nodes.length
3806
+ };
3807
+ next.selectedStructureNodeId = null;
3808
+ syncSelectionToCaret(next);
3809
+ appendDebug(next, "moveCaretVertical", "overset-over->base");
3810
+ return next;
3811
+ }
3812
+ next.caret = {
3813
+ chainId: ownerLocated.chain.id,
3814
+ index: ownerLocated.index
3815
+ };
3816
+ next.selectedStructureNodeId = null;
3817
+ syncSelectionToCaret(next);
3818
+ appendDebug(next, "moveCaretVertical", "overset-over-up-exit");
3819
+ return next;
3820
+ }
3821
+ if (located.relation.kind === "baseExpr" && ownerLocated && ownerNode && ownerNode.kind === "overset" && ownerNode.overExpr) {
3822
+ if (direction === "up") {
3823
+ next.caret = {
3824
+ chainId: ownerNode.overExpr.id,
3825
+ index: ownerNode.overExpr.nodes.length
3826
+ };
3827
+ next.selectedStructureNodeId = null;
3828
+ syncSelectionToCaret(next);
3829
+ appendDebug(next, "moveCaretVertical", "overset-base->over");
3830
+ return next;
3831
+ }
3832
+ next.caret = {
3833
+ chainId: ownerLocated.chain.id,
3834
+ index: ownerLocated.index + 1
3835
+ };
3836
+ next.selectedStructureNodeId = null;
3837
+ syncSelectionToCaret(next);
3838
+ appendDebug(next, "moveCaretVertical", "overset-base-down-exit");
3839
+ return next;
3840
+ }
3841
+ if (located.relation.kind === "baseExpr" && ownerLocated && ownerNode && ownerNode.kind === "underset" && ownerNode.underExpr) {
3842
+ if (direction === "down") {
3843
+ next.caret = {
3844
+ chainId: ownerNode.underExpr.id,
3845
+ index: ownerNode.underExpr.nodes.length
3846
+ };
3847
+ next.selectedStructureNodeId = null;
3848
+ syncSelectionToCaret(next);
3849
+ appendDebug(next, "moveCaretVertical", "underset-base->under");
3850
+ return next;
3851
+ }
3852
+ next.caret = {
3853
+ chainId: ownerLocated.chain.id,
3854
+ index: ownerLocated.index
3855
+ };
3856
+ next.selectedStructureNodeId = null;
3857
+ syncSelectionToCaret(next);
3858
+ appendDebug(next, "moveCaretVertical", "underset-base-up-exit");
3859
+ return next;
3860
+ }
3861
+ if (located.relation.kind === "underExpr" && ownerLocated && ownerNode && ownerNode.baseExpr) {
3862
+ if (direction === "up") {
3863
+ next.caret = {
3864
+ chainId: ownerNode.baseExpr.id,
3865
+ index: ownerNode.baseExpr.nodes.length
3866
+ };
3867
+ next.selectedStructureNodeId = null;
3868
+ syncSelectionToCaret(next);
3869
+ appendDebug(next, "moveCaretVertical", "underset-under->base");
3870
+ return next;
3871
+ }
3872
+ next.caret = {
3873
+ chainId: ownerLocated.chain.id,
3874
+ index: ownerLocated.index + 1
3875
+ };
3876
+ next.selectedStructureNodeId = null;
3877
+ syncSelectionToCaret(next);
3878
+ appendDebug(next, "moveCaretVertical", "underset-under-down-exit");
3879
+ return next;
3880
+ }
3881
+ if (located.relation.kind === "baseExpr" && ownerLocated && ownerNode && ownerNode.kind === "accent") {
3882
+ if (direction === "up") {
3883
+ next.caret = {
3884
+ chainId: ownerLocated.chain.id,
3885
+ index: ownerLocated.index
3886
+ };
3887
+ next.selectedStructureNodeId = null;
3888
+ syncSelectionToCaret(next);
3889
+ appendDebug(next, "moveCaretVertical", "accent-base-up-exit");
3890
+ return next;
3891
+ }
3892
+ next.caret = {
3893
+ chainId: ownerLocated.chain.id,
3894
+ index: ownerLocated.index + 1
3895
+ };
3896
+ next.selectedStructureNodeId = null;
3897
+ syncSelectionToCaret(next);
3898
+ appendDebug(next, "moveCaretVertical", "accent-base-down-exit");
3899
+ return next;
3900
+ }
3345
3901
  if (located.relation.kind === "matrixCell" && ownerLocated && ownerNode?.matrixRows) {
3346
3902
  const rowIndex = located.relation.rowIndex ?? 0;
3347
3903
  const columnIndex = located.relation.columnIndex ?? 0;
@@ -3719,6 +4275,119 @@ function insertSqrt(session) {
3719
4275
  appendDebug(next, "insertSqrt", "");
3720
4276
  return next;
3721
4277
  }
4278
+ function insertOverset(session) {
4279
+ const base = replaceSelectionFirst(session);
4280
+ const next = cloneEditorSession(base);
4281
+ const englishNode = createOversetNode();
4282
+ const arabicNode = createOversetNode();
4283
+ arabicNode.id = englishNode.id;
4284
+ if (arabicNode.overExpr && englishNode.overExpr) {
4285
+ arabicNode.overExpr.id = englishNode.overExpr.id;
4286
+ }
4287
+ if (arabicNode.baseExpr && englishNode.baseExpr) {
4288
+ arabicNode.baseExpr.id = englishNode.baseExpr.id;
4289
+ }
4290
+ insertMirroredNode(next, next.caret.chainId, next.caret.index, englishNode, arabicNode);
4291
+ next.caret = {
4292
+ chainId: englishNode.overExpr ? englishNode.overExpr.id : next.caret.chainId,
4293
+ index: 0
4294
+ };
4295
+ next.selectedStructureNodeId = null;
4296
+ syncSelectionToCaret(next);
4297
+ appendDebug(next, "insertOverset", "");
4298
+ return next;
4299
+ }
4300
+ function insertUnderset(session) {
4301
+ const base = replaceSelectionFirst(session);
4302
+ const next = cloneEditorSession(base);
4303
+ const englishNode = createUndersetNode();
4304
+ const arabicNode = createUndersetNode();
4305
+ arabicNode.id = englishNode.id;
4306
+ if (arabicNode.underExpr && englishNode.underExpr) {
4307
+ arabicNode.underExpr.id = englishNode.underExpr.id;
4308
+ }
4309
+ if (arabicNode.baseExpr && englishNode.baseExpr) {
4310
+ arabicNode.baseExpr.id = englishNode.baseExpr.id;
4311
+ }
4312
+ insertMirroredNode(next, next.caret.chainId, next.caret.index, englishNode, arabicNode);
4313
+ next.caret = {
4314
+ chainId: englishNode.underExpr ? englishNode.underExpr.id : next.caret.chainId,
4315
+ index: 0
4316
+ };
4317
+ next.selectedStructureNodeId = null;
4318
+ syncSelectionToCaret(next);
4319
+ appendDebug(next, "insertUnderset", "");
4320
+ return next;
4321
+ }
4322
+ function insertLimitsSeriesTemplate(session, commandId) {
4323
+ const base = replaceSelectionFirst(session);
4324
+ const next = cloneEditorSession(base);
4325
+ const { english, arabic } = buildLimitsSeriesTemplate(commandId);
4326
+ insertMirroredNode(next, next.caret.chainId, next.caret.index, english, arabic);
4327
+ syncSubtreeRecursive(next, english, arabic);
4328
+ next.caret = limitsSeriesTemplateInitialCaret(english);
4329
+ next.selectedStructureNodeId = null;
4330
+ syncSelectionToCaret(next);
4331
+ appendDebug(next, "insertLimitsSeriesTemplate", commandId);
4332
+ return next;
4333
+ }
4334
+ function insertAccentPair(session) {
4335
+ const base = replaceSelectionFirst(session);
4336
+ const next = cloneEditorSession(base);
4337
+ const { english, arabic } = buildAccentPairTemplate();
4338
+ insertMirroredNode(next, next.caret.chainId, next.caret.index, english, arabic);
4339
+ syncSubtreeRecursive(next, english, arabic);
4340
+ next.caret = accentPairTemplateInitialCaret(english);
4341
+ next.selectedStructureNodeId = null;
4342
+ syncSelectionToCaret(next);
4343
+ appendDebug(next, "insertAccentPair", "");
4344
+ return next;
4345
+ }
4346
+ function insertAccent(session, accentId) {
4347
+ const next = cloneEditorSession(session);
4348
+ const englishNode = createAccentNode(accentId);
4349
+ const arabicNode = createAccentNode(accentId);
4350
+ arabicNode.id = englishNode.id;
4351
+ if (arabicNode.baseExpr && englishNode.baseExpr) {
4352
+ arabicNode.baseExpr.id = englishNode.baseExpr.id;
4353
+ }
4354
+ if (isSelectionActive(next.selection) && next.selection) {
4355
+ const sel = next.selection;
4356
+ const { start, end } = normalizeSelection(sel);
4357
+ const englishLocated = findChainById(next.englishTree, sel.chainId);
4358
+ const arabicLocated = findChainById(next.arabicTree, sel.chainId);
4359
+ if (englishLocated && arabicLocated && end > start) {
4360
+ const count = end - start;
4361
+ const englishWrapped = englishLocated.chain.nodes.splice(start, count);
4362
+ const arabicWrapped = arabicLocated.chain.nodes.splice(start, count);
4363
+ englishNode.baseExpr.nodes = englishWrapped;
4364
+ arabicNode.baseExpr.nodes = arabicWrapped;
4365
+ englishLocated.chain.nodes.splice(start, 0, englishNode);
4366
+ arabicLocated.chain.nodes.splice(start, 0, arabicNode);
4367
+ syncSubtreeRecursive(next, englishNode, arabicNode);
4368
+ next.caret = {
4369
+ chainId: englishNode.baseExpr.id,
4370
+ index: englishWrapped.length
4371
+ };
4372
+ next.selection = null;
4373
+ next.selectedStructureNodeId = null;
4374
+ syncSelectionToCaret(next);
4375
+ appendDebug(next, "insertAccent", `${accentId}:wrap`);
4376
+ return next;
4377
+ }
4378
+ }
4379
+ insertMirroredNode(next, next.caret.chainId, next.caret.index, englishNode, arabicNode);
4380
+ syncSubtreeRecursive(next, englishNode, arabicNode);
4381
+ next.caret = {
4382
+ chainId: englishNode.baseExpr ? englishNode.baseExpr.id : next.caret.chainId,
4383
+ index: 0
4384
+ };
4385
+ next.selection = null;
4386
+ next.selectedStructureNodeId = null;
4387
+ syncSelectionToCaret(next);
4388
+ appendDebug(next, "insertAccent", `${accentId}:empty`);
4389
+ return next;
4390
+ }
3722
4391
  function insertMatrixEnv(session, style, rows, columns) {
3723
4392
  return insertGridEnv(session, style, rows, columns);
3724
4393
  }
@@ -3966,7 +4635,7 @@ function deleteBackward(session) {
3966
4635
  if (!previousNode) {
3967
4636
  return session;
3968
4637
  }
3969
- if ((previousNode.kind === "delimiter" || previousNode.kind === "frac" || previousNode.kind === "sqrt" || previousNode.kind === "env") && next.selectedStructureNodeId !== previousNode.id) {
4638
+ if ((previousNode.kind === "delimiter" || previousNode.kind === "frac" || previousNode.kind === "sqrt" || previousNode.kind === "overset" || previousNode.kind === "underset" || previousNode.kind === "accent" || previousNode.kind === "env") && next.selectedStructureNodeId !== previousNode.id) {
3970
4639
  next.selectedStructureNodeId = previousNode.id;
3971
4640
  next.selectedNodeId = previousNode.id;
3972
4641
  appendDebug(next, "deleteBackward", "selected structure");
@@ -4456,6 +5125,168 @@ function buildSqrtNodeBody(node, buildChain, side) {
4456
5125
  return wrap;
4457
5126
  }
4458
5127
 
5128
+ // src/editor/display/overset.ts
5129
+ var OVERSET_CSS = `
5130
+ .overset {
5131
+ display: inline-flex;
5132
+ flex-direction: column;
5133
+ align-items: center;
5134
+ justify-content: center;
5135
+ vertical-align: middle;
5136
+ margin: 0 2px;
5137
+ min-width: 1.2em;
5138
+ }
5139
+
5140
+ .overset-over {
5141
+ display: inline-flex;
5142
+ justify-content: center;
5143
+ align-items: center;
5144
+ min-height: 0.85em;
5145
+ padding: 0 2px;
5146
+ font-size: 0.72em;
5147
+ line-height: 1.1;
5148
+ }
5149
+
5150
+ .overset-base {
5151
+ display: inline-flex;
5152
+ justify-content: center;
5153
+ align-items: center;
5154
+ min-height: 1.05em;
5155
+ padding: 0 2px;
5156
+ }
5157
+ `.trim();
5158
+ function buildOversetNodeBody(node, buildChain) {
5159
+ const wrap = document.createElement("span");
5160
+ wrap.className = "overset";
5161
+ const over = document.createElement("span");
5162
+ over.className = "overset-over";
5163
+ if (node.overExpr) {
5164
+ over.appendChild(buildChain(node.overExpr));
5165
+ }
5166
+ const base = document.createElement("span");
5167
+ base.className = "overset-base";
5168
+ if (node.baseExpr) {
5169
+ base.appendChild(buildChain(node.baseExpr));
5170
+ }
5171
+ wrap.appendChild(over);
5172
+ wrap.appendChild(base);
5173
+ return wrap;
5174
+ }
5175
+
5176
+ // src/editor/display/underset.ts
5177
+ var UNDERSET_CSS = `
5178
+ .underset {
5179
+ display: inline-flex;
5180
+ flex-direction: column;
5181
+ align-items: center;
5182
+ justify-content: center;
5183
+ vertical-align: middle;
5184
+ margin: 0 2px;
5185
+ min-width: 1.2em;
5186
+ }
5187
+
5188
+ .underset-base {
5189
+ display: inline-flex;
5190
+ justify-content: center;
5191
+ align-items: center;
5192
+ min-height: 1.05em;
5193
+ padding: 0 2px;
5194
+ }
5195
+
5196
+ .underset-under {
5197
+ display: inline-flex;
5198
+ justify-content: center;
5199
+ align-items: center;
5200
+ min-height: 0.85em;
5201
+ padding: 0 2px;
5202
+ font-size: 0.72em;
5203
+ line-height: 1.1;
5204
+ }
5205
+ `.trim();
5206
+ function buildUndersetNodeBody(node, buildChain) {
5207
+ const wrap = document.createElement("span");
5208
+ wrap.className = "underset";
5209
+ const base = document.createElement("span");
5210
+ base.className = "underset-base";
5211
+ if (node.baseExpr) {
5212
+ base.appendChild(buildChain(node.baseExpr));
5213
+ }
5214
+ const under = document.createElement("span");
5215
+ under.className = "underset-under";
5216
+ if (node.underExpr) {
5217
+ under.appendChild(buildChain(node.underExpr));
5218
+ }
5219
+ wrap.appendChild(base);
5220
+ wrap.appendChild(under);
5221
+ return wrap;
5222
+ }
5223
+
5224
+ // src/editor/display/accent.ts
5225
+ var ACCENT_CSS = `
5226
+ .math-accent {
5227
+ display: inline-flex;
5228
+ flex-direction: column;
5229
+ align-items: center;
5230
+ justify-content: center;
5231
+ vertical-align: middle;
5232
+ margin: 0 2px;
5233
+ min-width: 1.1em;
5234
+ }
5235
+
5236
+ .math-accent-chrome {
5237
+ display: inline-flex;
5238
+ justify-content: center;
5239
+ align-items: center;
5240
+ min-height: 0.7em;
5241
+ padding: 0 2px;
5242
+ font-size: 0.85em;
5243
+ line-height: 1;
5244
+ color: var(--butex-script-color, #475569);
5245
+ user-select: none;
5246
+ }
5247
+
5248
+ .math-accent-base {
5249
+ display: inline-flex;
5250
+ justify-content: center;
5251
+ align-items: center;
5252
+ min-height: 1.05em;
5253
+ padding: 0 2px;
5254
+ }
5255
+
5256
+ .math-accent--under .math-accent-chrome {
5257
+ min-height: 0.45em;
5258
+ border-top: 1.5px solid currentColor;
5259
+ width: 100%;
5260
+ font-size: 0;
5261
+ color: var(--butex-surface-fg, #0f172a);
5262
+ }
5263
+ `.trim();
5264
+ function buildAccentNodeBody(node, buildChain) {
5265
+ const wrap = document.createElement("span");
5266
+ const spec = accentCommandSpec(node.expr);
5267
+ const placement = spec?.placement ?? "over";
5268
+ wrap.className = placement === "under" ? "math-accent math-accent--under" : "math-accent math-accent--over";
5269
+ const chrome = document.createElement("span");
5270
+ chrome.className = "math-accent-chrome";
5271
+ chrome.setAttribute("aria-hidden", "true");
5272
+ if (placement === "over") {
5273
+ chrome.textContent = spec?.label ?? "\u02C6";
5274
+ }
5275
+ const base = document.createElement("span");
5276
+ base.className = "math-accent-base";
5277
+ if (node.baseExpr) {
5278
+ base.appendChild(buildChain(node.baseExpr));
5279
+ }
5280
+ if (placement === "under") {
5281
+ wrap.appendChild(base);
5282
+ wrap.appendChild(chrome);
5283
+ } else {
5284
+ wrap.appendChild(chrome);
5285
+ wrap.appendChild(base);
5286
+ }
5287
+ return wrap;
5288
+ }
5289
+
4459
5290
  // src/editor/display/env.ts
4460
5291
  var WRAPPERS = {
4461
5292
  matrix: { left: "", right: "" },
@@ -4828,6 +5659,15 @@ function buildNodeBody(node, buildChain, side, digitForm = "western", uiLocale =
4828
5659
  if (node.kind === "sqrt") {
4829
5660
  return buildSqrtNodeBody(node, buildChain, side);
4830
5661
  }
5662
+ if (node.kind === "overset") {
5663
+ return buildOversetNodeBody(node, buildChain);
5664
+ }
5665
+ if (node.kind === "underset") {
5666
+ return buildUndersetNodeBody(node, buildChain);
5667
+ }
5668
+ if (node.kind === "accent") {
5669
+ return buildAccentNodeBody(node, buildChain);
5670
+ }
4831
5671
  if (node.kind === "env") {
4832
5672
  return buildMatrixEnvNodeBody(node, buildChain, side);
4833
5673
  }
@@ -5027,6 +5867,12 @@ ${FRAC_CSS}
5027
5867
 
5028
5868
  ${SQRT_CSS}
5029
5869
 
5870
+ ${OVERSET_CSS}
5871
+
5872
+ ${UNDERSET_CSS}
5873
+
5874
+ ${ACCENT_CSS}
5875
+
5030
5876
  ${MATRIX_ENV_CSS}
5031
5877
 
5032
5878
  ${ATOMIC_COMMAND_CSS}
@@ -5746,6 +6592,26 @@ function createEditorRuntime(options) {
5746
6592
  applyStructural((prev) => insertSqrt(prev));
5747
6593
  surfaceEl.focus();
5748
6594
  },
6595
+ insertOverset: () => {
6596
+ applyStructural((prev) => insertOverset(prev));
6597
+ surfaceEl.focus();
6598
+ },
6599
+ insertUnderset: () => {
6600
+ applyStructural((prev) => insertUnderset(prev));
6601
+ surfaceEl.focus();
6602
+ },
6603
+ insertLimitsSeriesTemplate: (commandId) => {
6604
+ applyStructural((prev) => insertLimitsSeriesTemplate(prev, commandId));
6605
+ surfaceEl.focus();
6606
+ },
6607
+ insertAccentPair: () => {
6608
+ applyStructural((prev) => insertAccentPair(prev));
6609
+ surfaceEl.focus();
6610
+ },
6611
+ insertAccent: (accentId) => {
6612
+ applyStructural((prev) => insertAccent(prev, accentId));
6613
+ surfaceEl.focus();
6614
+ },
5749
6615
  insertAtomicCommand: (commandId) => {
5750
6616
  applyStructural((prev) => insertAtomicCommand(prev, commandId));
5751
6617
  surfaceEl.focus();
@@ -6072,6 +6938,56 @@ function commandToEditorNode(node) {
6072
6938
  }
6073
6939
  return { editable: true, node: sqrt };
6074
6940
  }
6941
+ if (node.name === "\\overset" && node.mandatoryArgs.length >= 2) {
6942
+ const overset = createOversetNode();
6943
+ const overExpr = chainToEditorChain(node.mandatoryArgs[0]);
6944
+ const baseExpr = chainToEditorChain(node.mandatoryArgs[1]);
6945
+ if (!overExpr.editable) {
6946
+ return overExpr;
6947
+ }
6948
+ if (!baseExpr.editable) {
6949
+ return baseExpr;
6950
+ }
6951
+ overset.overExpr = overExpr.chain;
6952
+ overset.baseExpr = baseExpr.chain;
6953
+ const scripts = attachScripts(node, overset);
6954
+ if (scripts) {
6955
+ return scripts;
6956
+ }
6957
+ return { editable: true, node: overset };
6958
+ }
6959
+ if (node.name === "\\underset" && node.mandatoryArgs.length >= 2) {
6960
+ const underset = createUndersetNode();
6961
+ const underExpr = chainToEditorChain(node.mandatoryArgs[0]);
6962
+ const baseExpr = chainToEditorChain(node.mandatoryArgs[1]);
6963
+ if (!underExpr.editable) {
6964
+ return underExpr;
6965
+ }
6966
+ if (!baseExpr.editable) {
6967
+ return baseExpr;
6968
+ }
6969
+ underset.underExpr = underExpr.chain;
6970
+ underset.baseExpr = baseExpr.chain;
6971
+ const scripts = attachScripts(node, underset);
6972
+ if (scripts) {
6973
+ return scripts;
6974
+ }
6975
+ return { editable: true, node: underset };
6976
+ }
6977
+ const accentId = accentCommandIdFromTex(node.name);
6978
+ if (accentId && node.mandatoryArgs.length >= 1) {
6979
+ const accent = createAccentNode(accentId);
6980
+ const baseExpr = chainToEditorChain(node.mandatoryArgs[0]);
6981
+ if (!baseExpr.editable) {
6982
+ return baseExpr;
6983
+ }
6984
+ accent.baseExpr = baseExpr.chain;
6985
+ const scripts = attachScripts(node, accent);
6986
+ if (scripts) {
6987
+ return scripts;
6988
+ }
6989
+ return { editable: true, node: accent };
6990
+ }
6075
6991
  const atomicId = commandIdForTex(node.name);
6076
6992
  if (atomicId && node.optionalArgs.length === 0 && node.mandatoryArgs.length === 0) {
6077
6993
  const atomic = createEditorNode("atomicCommand", atomicId);
@@ -6208,6 +7124,21 @@ function editorEnvToAstNode(node) {
6208
7124
  const scripts = attachAstScripts(node, env);
6209
7125
  return scripts ?? { ok: true, node: env };
6210
7126
  }
7127
+ function accentChainForExport(accent) {
7128
+ if (!accent) {
7129
+ return { ok: true, chain: new ChainNode([]) };
7130
+ }
7131
+ return editorChainToAstChain(accent);
7132
+ }
7133
+ function nodeFromAccentBase(command, accent, base) {
7134
+ if (accent.chain.length > 0) {
7135
+ return new CommandNode(command, [], [accent, base]);
7136
+ }
7137
+ if (base.chain.length === 1) {
7138
+ return base.chain[0];
7139
+ }
7140
+ return new DelimiterNode("", base, "");
7141
+ }
6211
7142
  function editorNodeToAstNode(node) {
6212
7143
  let astNode;
6213
7144
  if (node.kind === "char") {
@@ -6246,6 +7177,36 @@ function editorNodeToAstNode(node) {
6246
7177
  optionalArgs.push(rootIndex.chain);
6247
7178
  }
6248
7179
  astNode = new CommandNode("\\sqrt", optionalArgs, [radicand.chain]);
7180
+ } else if (node.kind === "overset" && node.baseExpr) {
7181
+ const accent = accentChainForExport(node.overExpr);
7182
+ if (!accent.ok) {
7183
+ return accent;
7184
+ }
7185
+ const baseExpr = editorChainToAstChain(node.baseExpr);
7186
+ if (!baseExpr.ok) {
7187
+ return baseExpr;
7188
+ }
7189
+ astNode = nodeFromAccentBase("\\overset", accent.chain, baseExpr.chain);
7190
+ } else if (node.kind === "underset" && node.baseExpr) {
7191
+ const accent = accentChainForExport(node.underExpr);
7192
+ if (!accent.ok) {
7193
+ return accent;
7194
+ }
7195
+ const baseExpr = editorChainToAstChain(node.baseExpr);
7196
+ if (!baseExpr.ok) {
7197
+ return baseExpr;
7198
+ }
7199
+ astNode = nodeFromAccentBase("\\underset", accent.chain, baseExpr.chain);
7200
+ } else if (node.kind === "accent" && node.baseExpr) {
7201
+ const tex = accentCommandSpec(node.expr)?.englishTex;
7202
+ if (!tex) {
7203
+ return { ok: false, reason: `\u0644\u0643\u0646\u0629 \u0631\u064A\u0627\u0636\u064A\u0629 \u063A\u064A\u0631 \u0645\u062F\u0639\u0648\u0645\u0629 \u062D\u0627\u0644\u064A\u0627: ${node.expr}` };
7204
+ }
7205
+ const baseExpr = editorChainToAstChain(node.baseExpr);
7206
+ if (!baseExpr.ok) {
7207
+ return baseExpr;
7208
+ }
7209
+ astNode = new CommandNode(tex, [], [baseExpr.chain]);
6249
7210
  } else if (node.kind === "atomicCommand") {
6250
7211
  const tex = atomicCommandSpec(node.expr)?.englishTex;
6251
7212
  if (!tex) {
@@ -6767,7 +7728,10 @@ function documentInlineText(inlines) {
6767
7728
  // src/mathjax/svgPatcher.ts
6768
7729
  var SVG_ARABSQRT_SELECTOR = 'mjx-container[jax="SVG"] svg .mjx-rtl-mirror[data-mjx-rtl-root="true"]';
6769
7730
  var ARABSQRT_SELECTOR = '.mjx-rtl-mirror[data-mjx-rtl-root="true"]';
7731
+ var SVG_PREVIEW_MIRROR_SELECTOR = 'mjx-container[jax="SVG"] svg .butex-preview-mirror';
7732
+ var PREVIEW_MIRROR_SELECTOR = ".butex-preview-mirror";
6770
7733
  var PATCHED_ATTR = "data-butex-svg-arabsqrt";
7734
+ var MIRROR_PATCHED_ATTR = "data-butex-svg-mirror";
6771
7735
  var ROOT_INDEX_SCALE = 0.72;
6772
7736
  var ROOT_INDEX_GAP_FACTOR = 0.08;
6773
7737
  var ROOT_INDEX_MIN_GAP = 2;
@@ -6792,11 +7756,12 @@ function directSvgElementChildren(element) {
6792
7756
  return Array.from(element.children).filter((child) => child instanceof SVGElement);
6793
7757
  }
6794
7758
  function boxFor(element) {
6795
- if (!(element instanceof SVGGraphicsElement) || typeof element.getBBox !== "function") {
7759
+ const candidate = element;
7760
+ if (typeof candidate.getBBox !== "function") {
6796
7761
  return null;
6797
7762
  }
6798
7763
  try {
6799
- const box = element.getBBox();
7764
+ const box = candidate.getBBox();
6800
7765
  return {
6801
7766
  x: box.x,
6802
7767
  y: box.y,
@@ -7040,6 +8005,31 @@ function patchArabSqrtRoot(root) {
7040
8005
  root.setAttribute(PATCHED_ATTR, "patched");
7041
8006
  rootNode.setAttribute(PATCHED_ATTR, "patched");
7042
8007
  }
8008
+ function patchPreviewMirror(element) {
8009
+ if (element.getAttribute(MIRROR_PATCHED_ATTR) === "patched") {
8010
+ return;
8011
+ }
8012
+ const box = boxFor(element);
8013
+ if (!box || box.width <= 0) {
8014
+ return;
8015
+ }
8016
+ const [tx, ty] = readTranslate(element);
8017
+ const mirrorX = tx + 2 * box.x + box.width;
8018
+ element.setAttribute(
8019
+ "transform",
8020
+ `translate(${roundSvg(mirrorX)},${roundSvg(ty)}) scale(-1,1)`
8021
+ );
8022
+ element.setAttribute(MIRROR_PATCHED_ATTR, "patched");
8023
+ }
8024
+ function collectPreviewMirrors(root) {
8025
+ let mirrors = Array.from(root.querySelectorAll(SVG_PREVIEW_MIRROR_SELECTOR));
8026
+ if (!mirrors.length) {
8027
+ mirrors = Array.from(root.querySelectorAll(PREVIEW_MIRROR_SELECTOR)).filter((candidate) => {
8028
+ return candidate.closest('mjx-container[jax="SVG"]') != null;
8029
+ });
8030
+ }
8031
+ return mirrors;
8032
+ }
7043
8033
  function patchBuTeXSvgMath(root) {
7044
8034
  if (typeof root.querySelectorAll !== "function") {
7045
8035
  return;
@@ -7051,6 +8041,7 @@ function patchBuTeXSvgMath(root) {
7051
8041
  });
7052
8042
  }
7053
8043
  roots.sort((a, b) => rootDepth(b) - rootDepth(a)).forEach((arabSqrtRoot) => patchArabSqrtRoot(arabSqrtRoot));
8044
+ collectPreviewMirrors(root).forEach((mirror) => patchPreviewMirror(mirror));
7054
8045
  }
7055
8046
 
7056
8047
  // src/mathjax/renderIsland.ts
@@ -7338,6 +8329,29 @@ var WIDGET_CHROME_CSS = `
7338
8329
  padding-top: 1px;
7339
8330
  }
7340
8331
 
8332
+ .butex-widget .toolbar-accent-icon {
8333
+ display: inline-flex;
8334
+ flex-direction: column;
8335
+ align-items: center;
8336
+ justify-content: center;
8337
+ min-width: 14px;
8338
+ font-size: 10px;
8339
+ line-height: 1;
8340
+ gap: 1px;
8341
+ }
8342
+
8343
+ .butex-widget .toolbar-accent-icon--over span:first-child,
8344
+ .butex-widget .toolbar-accent-icon--under span:last-child {
8345
+ font-size: 8px;
8346
+ opacity: 0.85;
8347
+ }
8348
+
8349
+ .butex-widget .toolbar-accent-icon--pair span:first-child,
8350
+ .butex-widget .toolbar-accent-icon--pair span:last-child {
8351
+ font-size: 8px;
8352
+ opacity: 0.85;
8353
+ }
8354
+
7341
8355
  .butex-widget .matrix-command-menu {
7342
8356
  position: relative;
7343
8357
  display: inline-flex;
@@ -8079,6 +9093,7 @@ var CHARACTER_FONT_OPTIONS = [
8079
9093
  { id: "diwani", label: "\u062F\u064A\u0648" },
8080
9094
  { id: "diwaniOutline", label: "\u0638\u0644" }
8081
9095
  ];
9096
+ var ACCENT_COMMANDS_LIST = accentCommandsList();
8082
9097
  var FUNCTION_COMMANDS = atomicCommandsByCategory("function");
8083
9098
  var LIMITS_SERIES_COMMANDS = atomicCommandsByCategory("limits_series");
8084
9099
  var FUNCTION2_COMMANDS = atomicCommandsByCategory("function2");
@@ -8226,6 +9241,7 @@ var ButexEditor = (0, import_react.forwardRef)(
8226
9241
  const [operator2MenuOpen, setOperator2MenuOpen] = (0, import_react.useState)(false);
8227
9242
  const [operator3MenuOpen, setOperator3MenuOpen] = (0, import_react.useState)(false);
8228
9243
  const [dotMenuOpen, setDotMenuOpen] = (0, import_react.useState)(false);
9244
+ const [accentMenuOpen, setAccentMenuOpen] = (0, import_react.useState)(false);
8229
9245
  const [integralMenuOpen, setIntegralMenuOpen] = (0, import_react.useState)(false);
8230
9246
  const [selectedDigitForm2, setSelectedDigitForm] = (0, import_react.useState)("western");
8231
9247
  const [selectedCharacterFont, setSelectedCharacterFont] = (0, import_react.useState)("default");
@@ -8495,7 +9511,78 @@ ${arabic || currentMessages.empty}`;
8495
9511
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { id: "insert-sqrt", className: "icon-btn", type: "button", title: messages.insertRoot, "aria-label": messages.insertRoot, onClick: () => {
8496
9512
  runtimeRef.current?.insertSqrt();
8497
9513
  focusSurface();
8498
- }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "toolbar-sqrt-icon", "aria-hidden": "true", children: "\u221A" }) })
9514
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "toolbar-sqrt-icon", "aria-hidden": "true", children: "\u221A" }) }),
9515
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { id: "insert-overset", className: "icon-btn", type: "button", title: messages.insertOverset, "aria-label": messages.insertOverset, onClick: () => {
9516
+ runtimeRef.current?.insertOverset();
9517
+ focusSurface();
9518
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "toolbar-accent-icon toolbar-accent-icon--over", "aria-hidden": "true", children: [
9519
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "\u2217" }),
9520
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "\u25A1" })
9521
+ ] }) }),
9522
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { id: "insert-underset", className: "icon-btn", type: "button", title: messages.insertUnderset, "aria-label": messages.insertUnderset, onClick: () => {
9523
+ runtimeRef.current?.insertUnderset();
9524
+ focusSurface();
9525
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "toolbar-accent-icon toolbar-accent-icon--under", "aria-hidden": "true", children: [
9526
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "\u25A1" }),
9527
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "\u2217" })
9528
+ ] }) }),
9529
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { id: "insert-accent-pair", className: "icon-btn", type: "button", title: messages.insertAccentPair, "aria-label": messages.insertAccentPair, onClick: () => {
9530
+ runtimeRef.current?.insertAccentPair();
9531
+ focusSurface();
9532
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "toolbar-accent-icon toolbar-accent-icon--pair", "aria-hidden": "true", children: [
9533
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "\u2217" }),
9534
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "\u25A1" }),
9535
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "\u2217" })
9536
+ ] }) }),
9537
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
9538
+ "div",
9539
+ {
9540
+ className: "function-command-menu operator-command-menu",
9541
+ onBlur: (event) => {
9542
+ const nextFocus = event.relatedTarget;
9543
+ if (!(nextFocus instanceof Node) || !event.currentTarget.contains(nextFocus)) {
9544
+ setAccentMenuOpen(false);
9545
+ }
9546
+ },
9547
+ children: [
9548
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
9549
+ "button",
9550
+ {
9551
+ id: "insert-accents",
9552
+ className: "icon-btn function-command-btn operator-command-btn",
9553
+ type: "button",
9554
+ title: messages.insertAccents,
9555
+ "aria-label": messages.insertAccents,
9556
+ "aria-haspopup": "listbox",
9557
+ "aria-expanded": accentMenuOpen,
9558
+ onClick: () => setAccentMenuOpen((open) => !open),
9559
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "toolbar-accent-icon toolbar-accent-icon--over", "aria-hidden": "true", children: [
9560
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "\u02C6" }),
9561
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "\u25A1" })
9562
+ ] })
9563
+ }
9564
+ ),
9565
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "function-command-options operator-command-options", role: "listbox", "aria-label": messages.insertAccents, hidden: !accentMenuOpen, children: ACCENT_COMMANDS_LIST.map((command) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
9566
+ "button",
9567
+ {
9568
+ className: "function-command-option operator-command-option",
9569
+ type: "button",
9570
+ role: "option",
9571
+ title: accentCommandTitle(command, uiLocale),
9572
+ "aria-label": accentCommandTitle(command, uiLocale),
9573
+ onMouseDown: (event) => event.preventDefault(),
9574
+ onClick: () => {
9575
+ runtimeRef.current?.insertAccent(command.id);
9576
+ setAccentMenuOpen(false);
9577
+ focusSurface();
9578
+ },
9579
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "operator-command-label", children: command.label })
9580
+ },
9581
+ command.id
9582
+ )) })
9583
+ ]
9584
+ }
9585
+ )
8499
9586
  ] }),
8500
9587
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "toolbar-group toolbar-environments", role: "group", "aria-label": messages.environments, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
8501
9588
  "div",
@@ -8823,7 +9910,7 @@ ${arabic || currentMessages.empty}`;
8823
9910
  "aria-label": atomicCommandTitle(command, uiLocale),
8824
9911
  onMouseDown: (event) => event.preventDefault(),
8825
9912
  onClick: () => {
8826
- runtimeRef.current?.insertAtomicCommand(command.id);
9913
+ runtimeRef.current?.insertLimitsSeriesTemplate(command.id);
8827
9914
  setLimitsSeriesMenuOpen(false);
8828
9915
  focusSurface();
8829
9916
  },