@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.
@@ -1388,6 +1388,158 @@ function createEmptyDocument2() {
1388
1388
  };
1389
1389
  }
1390
1390
 
1391
+ // src/editor/accentCommands.ts
1392
+ var ACCENT_COMMANDS = {
1393
+ vec: {
1394
+ id: "vec",
1395
+ englishTex: "\\vec",
1396
+ arabicTex: "\\arabvec",
1397
+ placement: "over",
1398
+ label: "\u20D7",
1399
+ title: "\u0633\u0647\u0645 \u0641\u0648\u0642"
1400
+ },
1401
+ hat: {
1402
+ id: "hat",
1403
+ englishTex: "\\hat",
1404
+ arabicTex: "\\hat",
1405
+ placement: "over",
1406
+ label: "\u02C6",
1407
+ title: "\u0642\u0628\u0639\u0629"
1408
+ },
1409
+ tilde: {
1410
+ id: "tilde",
1411
+ englishTex: "\\tilde",
1412
+ arabicTex: "\\tilde",
1413
+ placement: "over",
1414
+ label: "\u02DC",
1415
+ title: "\u0645\u062F\u0629"
1416
+ },
1417
+ dot: {
1418
+ id: "dot",
1419
+ englishTex: "\\dot",
1420
+ arabicTex: "\\dot",
1421
+ placement: "over",
1422
+ label: "\u02D9",
1423
+ title: "\u0646\u0642\u0637\u0629 \u0641\u0648\u0642"
1424
+ },
1425
+ ddot: {
1426
+ id: "ddot",
1427
+ englishTex: "\\ddot",
1428
+ arabicTex: "\\ddot",
1429
+ placement: "over",
1430
+ label: "\xA8",
1431
+ title: "\u0646\u0642\u0637\u062A\u0627\u0646 \u0641\u0648\u0642"
1432
+ },
1433
+ dddot: {
1434
+ id: "dddot",
1435
+ englishTex: "\\dddot",
1436
+ arabicTex: "\\dddot",
1437
+ placement: "over",
1438
+ label: "\u20DB",
1439
+ title: "\u062B\u0644\u0627\u062B \u0646\u0642\u0627\u0637 \u0641\u0648\u0642"
1440
+ },
1441
+ bar: {
1442
+ id: "bar",
1443
+ englishTex: "\\bar",
1444
+ arabicTex: "\\bar",
1445
+ placement: "over",
1446
+ label: "\xAF",
1447
+ title: "\u062E\u0637 \u0641\u0648\u0642"
1448
+ },
1449
+ check: {
1450
+ id: "check",
1451
+ englishTex: "\\check",
1452
+ arabicTex: "\\check",
1453
+ placement: "over",
1454
+ label: "\u02C7",
1455
+ title: "\u0639\u0644\u0627\u0645\u0629 \u062A\u062D\u0642\u0642"
1456
+ },
1457
+ breve: {
1458
+ id: "breve",
1459
+ englishTex: "\\breve",
1460
+ arabicTex: "\\breve",
1461
+ placement: "over",
1462
+ label: "\u02D8",
1463
+ title: "\u0642\u0648\u0633 \u0642\u0635\u064A\u0631"
1464
+ },
1465
+ acute: {
1466
+ id: "acute",
1467
+ englishTex: "\\acute",
1468
+ arabicTex: "\\grave",
1469
+ placement: "over",
1470
+ label: "\xB4",
1471
+ title: "\u0646\u0628\u0631\u0629 \u062D\u0627\u062F\u0629"
1472
+ },
1473
+ grave: {
1474
+ id: "grave",
1475
+ englishTex: "\\grave",
1476
+ arabicTex: "\\acute",
1477
+ placement: "over",
1478
+ label: "`",
1479
+ title: "\u0646\u0628\u0631\u0629 \u062B\u0642\u064A\u0644\u0629"
1480
+ },
1481
+ overline: {
1482
+ id: "overline",
1483
+ englishTex: "\\overline",
1484
+ arabicTex: "\\overline",
1485
+ placement: "over",
1486
+ label: "\u203E",
1487
+ title: "\u062E\u0637 \u0639\u0644\u0648\u064A \u0645\u0645\u062A\u062F"
1488
+ },
1489
+ underline: {
1490
+ id: "underline",
1491
+ englishTex: "\\underline",
1492
+ arabicTex: "\\underline",
1493
+ placement: "under",
1494
+ label: "_",
1495
+ title: "\u062E\u0637 \u0633\u0641\u0644\u064A"
1496
+ },
1497
+ overleftarrow: {
1498
+ id: "overleftarrow",
1499
+ englishTex: "\\overleftarrow",
1500
+ arabicTex: "\\overrightarrow",
1501
+ placement: "over",
1502
+ label: "\u2190",
1503
+ title: "\u0633\u0647\u0645 \u0639\u0644\u0648\u064A \u0625\u0644\u0649 \u0627\u0644\u064A\u0633\u0627\u0631"
1504
+ },
1505
+ overrightarrow: {
1506
+ id: "overrightarrow",
1507
+ englishTex: "\\overrightarrow",
1508
+ arabicTex: "\\overleftarrow",
1509
+ placement: "over",
1510
+ label: "\u2192",
1511
+ title: "\u0633\u0647\u0645 \u0639\u0644\u0648\u064A \u0625\u0644\u0649 \u0627\u0644\u064A\u0645\u064A\u0646"
1512
+ },
1513
+ overleftrightarrow: {
1514
+ id: "overleftrightarrow",
1515
+ englishTex: "\\overleftrightarrow",
1516
+ arabicTex: "\\overleftrightarrow",
1517
+ placement: "over",
1518
+ label: "\u2194",
1519
+ title: "\u0633\u0647\u0645 \u0639\u0644\u0648\u064A \u0645\u0632\u062F\u0648\u062C \u0627\u0644\u0627\u062A\u062C\u0627\u0647"
1520
+ }
1521
+ };
1522
+ function accentCommandSpec(id) {
1523
+ return Object.prototype.hasOwnProperty.call(ACCENT_COMMANDS, id) ? ACCENT_COMMANDS[id] : null;
1524
+ }
1525
+ function accentCommandsList() {
1526
+ return Object.values(ACCENT_COMMANDS);
1527
+ }
1528
+ function accentCommandIdFromTex(tex) {
1529
+ const normalized = tex.startsWith("\\") ? tex : `\\${tex}`;
1530
+ for (const spec of Object.values(ACCENT_COMMANDS)) {
1531
+ if (spec.englishTex === normalized) {
1532
+ return spec.id;
1533
+ }
1534
+ }
1535
+ for (const spec of Object.values(ACCENT_COMMANDS)) {
1536
+ if (spec.arabicTex === normalized) {
1537
+ return spec.id;
1538
+ }
1539
+ }
1540
+ return null;
1541
+ }
1542
+
1391
1543
  // src/editor/atomicCommands.ts
1392
1544
  var ATOMIC_COMMANDS = {
1393
1545
  ///////////////////////// Functions ////////////////////////////////
@@ -1808,7 +1960,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1808
1960
  id: "neq",
1809
1961
  category: "operators1",
1810
1962
  Tex: "\\neq",
1811
- mirror: false,
1963
+ mirror: true,
1812
1964
  Label: "\u2260",
1813
1965
  title: "\u0644\u0627 \u064A\u0633\u0627\u0648\u064A",
1814
1966
  svg_path: null
@@ -1818,6 +1970,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1818
1970
  category: "operators1",
1819
1971
  Tex: "\\approx",
1820
1972
  mirror: false,
1973
+ displayMirror: true,
1821
1974
  Label: "\u2248",
1822
1975
  title: "\u062A\u0642\u0631\u064A\u0628\u0627 \u064A\u0633\u0627\u0648\u064A",
1823
1976
  svg_path: null
@@ -1827,6 +1980,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1827
1980
  category: "operators1",
1828
1981
  Tex: "\\sim",
1829
1982
  mirror: false,
1983
+ displayMirror: true,
1830
1984
  Label: "\u223C",
1831
1985
  title: "\u0645\u0634\u0627\u0628\u0647",
1832
1986
  svg_path: null
@@ -1845,6 +1999,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1845
1999
  category: "operators1",
1846
2000
  Tex: "\\leq",
1847
2001
  mirror: true,
2002
+ displayMirror: false,
1848
2003
  Label: "\u2264",
1849
2004
  title: "\u0623\u0635\u063A\u0631 \u0645\u0646 \u0623\u0648 \u064A\u0633\u0627\u0648\u064A",
1850
2005
  svg_path: null
@@ -1854,6 +2009,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1854
2009
  category: "operators1",
1855
2010
  Tex: "\\geq",
1856
2011
  mirror: true,
2012
+ displayMirror: false,
1857
2013
  Label: "\u2265",
1858
2014
  title: "\u0623\u0643\u0628\u0631 \u0645\u0646 \u0623\u0648 \u064A\u0633\u0627\u0648\u064A",
1859
2015
  svg_path: null
@@ -1863,6 +2019,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1863
2019
  category: "operators1",
1864
2020
  Tex: "\\coloneqq",
1865
2021
  mirror: true,
2022
+ displayMirror: false,
1866
2023
  Label: "\u2254",
1867
2024
  title: "\u064A\u0639\u0631\u0641 \u0628\u0623\u0646\u0647 \u064A\u0633\u0627\u0648\u064A",
1868
2025
  svg_path: null
@@ -1872,6 +2029,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1872
2029
  category: "operators1",
1873
2030
  Tex: "\\eqqcolon",
1874
2031
  mirror: true,
2032
+ displayMirror: false,
1875
2033
  Label: "\u2255",
1876
2034
  title: "\u064A\u0633\u0627\u0648\u064A \u0628\u0627\u0644\u062A\u0639\u0631\u064A\u0641",
1877
2035
  svg_path: null
@@ -1882,6 +2040,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1882
2040
  category: "operators2",
1883
2041
  Tex: "\\propto",
1884
2042
  mirror: true,
2043
+ displayMirror: false,
1885
2044
  Label: "\u221D",
1886
2045
  title: "\u064A\u062A\u0646\u0627\u0633\u0628 \u0645\u0639",
1887
2046
  svg_path: null
@@ -1891,6 +2050,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1891
2050
  category: "operators2",
1892
2051
  Tex: "\\in",
1893
2052
  mirror: true,
2053
+ displayMirror: false,
1894
2054
  Label: "\u2208",
1895
2055
  title: "\u064A\u0646\u062A\u0645\u064A \u0625\u0644\u0649",
1896
2056
  svg_path: null
@@ -1900,6 +2060,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1900
2060
  category: "operators2",
1901
2061
  Tex: "\\notin",
1902
2062
  mirror: false,
2063
+ displayMirror: true,
1903
2064
  Label: "\u2209",
1904
2065
  title: "\u0644\u0627 \u064A\u0646\u062A\u0645\u064A \u0625\u0644\u0649",
1905
2066
  svg_path: null
@@ -1909,6 +2070,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1909
2070
  category: "operators2",
1910
2071
  Tex: "\\subset",
1911
2072
  mirror: true,
2073
+ displayMirror: false,
1912
2074
  Label: "\u2282",
1913
2075
  title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u062C\u0632\u0626\u064A\u0629 \u0645\u0646",
1914
2076
  svg_path: null
@@ -1918,6 +2080,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1918
2080
  category: "operators2",
1919
2081
  Tex: "\\supset",
1920
2082
  mirror: true,
2083
+ displayMirror: false,
1921
2084
  Label: "\u2283",
1922
2085
  title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u0634\u0627\u0645\u0644\u0629 \u0644\u0640",
1923
2086
  svg_path: null
@@ -1927,6 +2090,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1927
2090
  category: "operators2",
1928
2091
  Tex: "\\subseteq",
1929
2092
  mirror: true,
2093
+ displayMirror: false,
1930
2094
  Label: "\u2286",
1931
2095
  title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u062C\u0632\u0626\u064A\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
1932
2096
  svg_path: null
@@ -1936,6 +2100,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1936
2100
  category: "operators2",
1937
2101
  Tex: "\\supseteq",
1938
2102
  mirror: true,
2103
+ displayMirror: false,
1939
2104
  Label: "\u2287",
1940
2105
  title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u0634\u0627\u0645\u0644\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
1941
2106
  svg_path: null
@@ -1945,6 +2110,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1945
2110
  category: "operators2",
1946
2111
  Tex: "\\cap",
1947
2112
  mirror: false,
2113
+ displayMirror: true,
1948
2114
  Label: "\u2229",
1949
2115
  title: "\u062A\u0642\u0627\u0637\u0639",
1950
2116
  svg_path: null
@@ -1954,6 +2120,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1954
2120
  category: "operators2",
1955
2121
  Tex: "\\cup",
1956
2122
  mirror: false,
2123
+ displayMirror: true,
1957
2124
  Label: "\u222A",
1958
2125
  title: "\u0627\u062A\u062D\u0627\u062F",
1959
2126
  svg_path: null
@@ -1963,6 +2130,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1963
2130
  category: "operators2",
1964
2131
  Tex: "\\emptyset",
1965
2132
  mirror: false,
2133
+ displayMirror: true,
1966
2134
  Label: "\u2205",
1967
2135
  title: "\u0627\u0644\u0645\u062C\u0645\u0648\u0639\u0629 \u0627\u0644\u062E\u0627\u0644\u064A\u0629",
1968
2136
  svg_path: null
@@ -1972,6 +2140,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1972
2140
  category: "operators2",
1973
2141
  Tex: "\\nsubseteq",
1974
2142
  mirror: true,
2143
+ displayMirror: false,
1975
2144
  Label: "\u2288",
1976
2145
  title: "\u0644\u064A\u0633\u062A \u0645\u062C\u0645\u0648\u0639\u0629 \u062C\u0632\u0626\u064A\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
1977
2146
  svg_path: null
@@ -1981,6 +2150,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1981
2150
  category: "operators2",
1982
2151
  Tex: "\\nsupseteq",
1983
2152
  mirror: true,
2153
+ displayMirror: false,
1984
2154
  Label: "\u2289",
1985
2155
  title: "\u0644\u064A\u0633\u062A \u0645\u062C\u0645\u0648\u0639\u0629 \u0634\u0627\u0645\u0644\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
1986
2156
  svg_path: null
@@ -2192,6 +2362,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2192
2362
  category: "integrals",
2193
2363
  Tex: "\\iint",
2194
2364
  mirror: true,
2365
+ displayMirror: false,
2195
2366
  Label: "\u222C",
2196
2367
  title: "\u062A\u0643\u0627\u0645\u0644 \u0645\u0632\u062F\u0648\u062C",
2197
2368
  svg_path: null
@@ -2201,6 +2372,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2201
2372
  category: "integrals",
2202
2373
  Tex: "\\iiint",
2203
2374
  mirror: true,
2375
+ displayMirror: false,
2204
2376
  Label: "\u222D",
2205
2377
  title: "\u062A\u0643\u0627\u0645\u0644 \u062B\u0644\u0627\u062B\u064A",
2206
2378
  svg_path: null
@@ -2210,6 +2382,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2210
2382
  category: "integrals",
2211
2383
  Tex: "\\iiiint",
2212
2384
  mirror: true,
2385
+ displayMirror: false,
2213
2386
  Label: "\u2A0C",
2214
2387
  title: "\u062A\u0643\u0627\u0645\u0644 \u0631\u0628\u0627\u0639\u064A",
2215
2388
  svg_path: null
@@ -2219,6 +2392,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2219
2392
  category: "integrals",
2220
2393
  Tex: "\\oint",
2221
2394
  mirror: true,
2395
+ displayMirror: false,
2222
2396
  Label: "\u222E",
2223
2397
  title: "\u062A\u0643\u0627\u0645\u0644 \u0645\u063A\u0644\u0642",
2224
2398
  svg_path: null
@@ -2228,6 +2402,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2228
2402
  category: "integrals",
2229
2403
  Tex: "\\oiint",
2230
2404
  mirror: true,
2405
+ displayMirror: false,
2231
2406
  Label: "\u222F",
2232
2407
  title: "\u062A\u0643\u0627\u0645\u0644 \u0633\u0637\u062D\u064A \u0645\u063A\u0644\u0642",
2233
2408
  svg_path: null
@@ -2237,6 +2412,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2237
2412
  category: "integrals",
2238
2413
  Tex: "\\oiiint",
2239
2414
  mirror: true,
2415
+ displayMirror: false,
2240
2416
  Label: "\u2230",
2241
2417
  title: "\u062A\u0643\u0627\u0645\u0644 \u062D\u062C\u0645\u064A \u0645\u063A\u0644\u0642",
2242
2418
  svg_path: null
@@ -2338,6 +2514,9 @@ function createEditorNode(kind, expr) {
2338
2514
  denominator: null,
2339
2515
  radicand: null,
2340
2516
  rootIndex: null,
2517
+ overExpr: null,
2518
+ underExpr: null,
2519
+ baseExpr: null,
2341
2520
  envName: null,
2342
2521
  matrixStyle: null,
2343
2522
  matrixRows: null,
@@ -2366,6 +2545,26 @@ function createSqrtNode() {
2366
2545
  rootIndex: createEditorChain()
2367
2546
  };
2368
2547
  }
2548
+ function createOversetNode() {
2549
+ return {
2550
+ ...createEditorNode("overset", ""),
2551
+ overExpr: createEditorChain(),
2552
+ baseExpr: createEditorChain()
2553
+ };
2554
+ }
2555
+ function createUndersetNode() {
2556
+ return {
2557
+ ...createEditorNode("underset", ""),
2558
+ underExpr: createEditorChain(),
2559
+ baseExpr: createEditorChain()
2560
+ };
2561
+ }
2562
+ function createAccentNode(accentId) {
2563
+ return {
2564
+ ...createEditorNode("accent", accentId),
2565
+ baseExpr: createEditorChain()
2566
+ };
2567
+ }
2369
2568
  function createGridEnvNode(envName, rows, columns, columnAlignments) {
2370
2569
  const safeRows = Math.max(1, Math.min(12, Math.trunc(rows)));
2371
2570
  const safeColumns = Math.max(1, Math.min(12, Math.trunc(columns)));
@@ -2430,6 +2629,15 @@ function collectNodeIds(chain, ids) {
2430
2629
  if (node.radicand) {
2431
2630
  collectNodeIds(node.radicand, ids);
2432
2631
  }
2632
+ if (node.overExpr) {
2633
+ collectNodeIds(node.overExpr, ids);
2634
+ }
2635
+ if (node.underExpr) {
2636
+ collectNodeIds(node.underExpr, ids);
2637
+ }
2638
+ if (node.baseExpr) {
2639
+ collectNodeIds(node.baseExpr, ids);
2640
+ }
2433
2641
  if (node.matrixRows) {
2434
2642
  for (const row of node.matrixRows) {
2435
2643
  for (const cell of row) {
@@ -2566,6 +2774,22 @@ function renderMatrixRowsArabic(node, options) {
2566
2774
  }
2567
2775
  return `\\begin{${envName}}${rows.join(" \\\\\n")}\\end{${envName}}`;
2568
2776
  }
2777
+ function renderAccentEnglish(command, accent, base, options) {
2778
+ const baseTex = base ? renderChainEnglish(base, options) : "";
2779
+ const accentTex = accent ? renderChainEnglish(accent, options) : "";
2780
+ if (accentTex === "") {
2781
+ return baseTex;
2782
+ }
2783
+ return `\\${command}{${accentTex}}{${baseTex}}`;
2784
+ }
2785
+ function renderAccentArabic(command, accent, base, options) {
2786
+ const baseTex = base ? renderChainArabic(base, options) : "";
2787
+ const accentTex = accent ? renderChainArabic(accent, options) : "";
2788
+ if (accentTex === "") {
2789
+ return baseTex;
2790
+ }
2791
+ return `\\${command}{${accentTex}}{${baseTex}}`;
2792
+ }
2569
2793
  function escapeText(s) {
2570
2794
  return s.replace(/\\/g, "\\textbackslash{}").replace(/[{}]/g, "\\$&");
2571
2795
  }
@@ -2595,6 +2819,19 @@ function renderNodeEnglish(node, options) {
2595
2819
  const body = `\\sqrt${optionalRootIndexEnglish(node, options)}{${renderChainEnglish(node.radicand, options)}}`;
2596
2820
  return `${body}${latinScripts(node, options)}`;
2597
2821
  }
2822
+ if (node.kind === "overset" && node.baseExpr) {
2823
+ const body = renderAccentEnglish("overset", node.overExpr, node.baseExpr, options);
2824
+ return `${body}${latinScripts(node, options)}`;
2825
+ }
2826
+ if (node.kind === "underset" && node.baseExpr) {
2827
+ const body = renderAccentEnglish("underset", node.underExpr, node.baseExpr, options);
2828
+ return `${body}${latinScripts(node, options)}`;
2829
+ }
2830
+ if (node.kind === "accent" && node.baseExpr) {
2831
+ const cmd = accentCommandSpec(node.expr)?.englishTex ?? `\\${node.expr}`;
2832
+ const body = `${cmd}{${renderChainEnglish(node.baseExpr, options)}}`;
2833
+ return `${body}${latinScripts(node, options)}`;
2834
+ }
2598
2835
  if (node.kind === "env") {
2599
2836
  return `${renderMatrixRowsEnglish(node, options)}${latinScripts(node, options)}`;
2600
2837
  }
@@ -2627,6 +2864,19 @@ function renderNodeArabic(node, options) {
2627
2864
  const content = `\\arabsqrt${optionalRootIndexArabic(node, options)}{${renderChainArabic(node.radicand, options)}}`;
2628
2865
  return arabicScripts(node, content, options);
2629
2866
  }
2867
+ if (node.kind === "overset" && node.baseExpr) {
2868
+ const content = renderAccentArabic("overset", node.overExpr, node.baseExpr, options);
2869
+ return arabicScripts(node, content, options);
2870
+ }
2871
+ if (node.kind === "underset" && node.baseExpr) {
2872
+ const content = renderAccentArabic("underset", node.underExpr, node.baseExpr, options);
2873
+ return arabicScripts(node, content, options);
2874
+ }
2875
+ if (node.kind === "accent" && node.baseExpr) {
2876
+ const cmd = accentCommandSpec(node.expr)?.arabicTex ?? `\\${node.expr}`;
2877
+ const content = `${cmd}{${renderChainArabic(node.baseExpr, options)}}`;
2878
+ return arabicScripts(node, content, options);
2879
+ }
2630
2880
  if (node.kind === "env") {
2631
2881
  return arabicScripts(node, renderMatrixRowsArabic(node, options), options);
2632
2882
  }
@@ -2683,6 +2933,35 @@ function collectCaretPositions(chain) {
2683
2933
  if (node.radicand) {
2684
2934
  walkChain(node.radicand);
2685
2935
  }
2936
+ if (node.kind === "overset") {
2937
+ if (node.overExpr) {
2938
+ walkChain(node.overExpr);
2939
+ }
2940
+ if (node.baseExpr) {
2941
+ walkChain(node.baseExpr);
2942
+ }
2943
+ } else if (node.kind === "underset") {
2944
+ if (node.baseExpr) {
2945
+ walkChain(node.baseExpr);
2946
+ }
2947
+ if (node.underExpr) {
2948
+ walkChain(node.underExpr);
2949
+ }
2950
+ } else if (node.kind === "accent") {
2951
+ if (node.baseExpr) {
2952
+ walkChain(node.baseExpr);
2953
+ }
2954
+ } else {
2955
+ if (node.overExpr) {
2956
+ walkChain(node.overExpr);
2957
+ }
2958
+ if (node.underExpr) {
2959
+ walkChain(node.underExpr);
2960
+ }
2961
+ if (node.baseExpr) {
2962
+ walkChain(node.baseExpr);
2963
+ }
2964
+ }
2686
2965
  if (node.matrixRows) {
2687
2966
  for (const row of node.matrixRows) {
2688
2967
  for (const cell of row) {
@@ -2816,6 +3095,42 @@ function findChainById(root, chainId) {
2816
3095
  return nested;
2817
3096
  }
2818
3097
  }
3098
+ if (node.overExpr) {
3099
+ if (node.overExpr.id === chainId) {
3100
+ return {
3101
+ chain: node.overExpr,
3102
+ relation: { kind: "overExpr", ownerNodeId: node.id, ownerChainId: root.id }
3103
+ };
3104
+ }
3105
+ const nested = findChainById(node.overExpr, chainId);
3106
+ if (nested) {
3107
+ return nested;
3108
+ }
3109
+ }
3110
+ if (node.underExpr) {
3111
+ if (node.underExpr.id === chainId) {
3112
+ return {
3113
+ chain: node.underExpr,
3114
+ relation: { kind: "underExpr", ownerNodeId: node.id, ownerChainId: root.id }
3115
+ };
3116
+ }
3117
+ const nested = findChainById(node.underExpr, chainId);
3118
+ if (nested) {
3119
+ return nested;
3120
+ }
3121
+ }
3122
+ if (node.baseExpr) {
3123
+ if (node.baseExpr.id === chainId) {
3124
+ return {
3125
+ chain: node.baseExpr,
3126
+ relation: { kind: "baseExpr", ownerNodeId: node.id, ownerChainId: root.id }
3127
+ };
3128
+ }
3129
+ const nested = findChainById(node.baseExpr, chainId);
3130
+ if (nested) {
3131
+ return nested;
3132
+ }
3133
+ }
2819
3134
  if (node.matrixRows) {
2820
3135
  for (let rowIndex = 0; rowIndex < node.matrixRows.length; rowIndex += 1) {
2821
3136
  const row = node.matrixRows[rowIndex];
@@ -2889,6 +3204,24 @@ function findNodeById(root, nodeId) {
2889
3204
  return nested;
2890
3205
  }
2891
3206
  }
3207
+ if (node.overExpr) {
3208
+ const nested = findNodeById(node.overExpr, nodeId);
3209
+ if (nested) {
3210
+ return nested;
3211
+ }
3212
+ }
3213
+ if (node.underExpr) {
3214
+ const nested = findNodeById(node.underExpr, nodeId);
3215
+ if (nested) {
3216
+ return nested;
3217
+ }
3218
+ }
3219
+ if (node.baseExpr) {
3220
+ const nested = findNodeById(node.baseExpr, nodeId);
3221
+ if (nested) {
3222
+ return nested;
3223
+ }
3224
+ }
2892
3225
  if (node.matrixRows) {
2893
3226
  for (const row of node.matrixRows) {
2894
3227
  for (const cell of row) {
@@ -2924,6 +3257,15 @@ function nodeChildChains(node) {
2924
3257
  if (node.radicand) {
2925
3258
  chains.push(node.radicand);
2926
3259
  }
3260
+ if (node.overExpr) {
3261
+ chains.push(node.overExpr);
3262
+ }
3263
+ if (node.underExpr) {
3264
+ chains.push(node.underExpr);
3265
+ }
3266
+ if (node.baseExpr) {
3267
+ chains.push(node.baseExpr);
3268
+ }
2927
3269
  if (node.matrixRows) {
2928
3270
  for (const row of node.matrixRows) {
2929
3271
  chains.push(...row);
@@ -3294,6 +3636,91 @@ function derivativeTemplateInitialCaret(englishFrac) {
3294
3636
  };
3295
3637
  }
3296
3638
 
3639
+ // src/editor/limitsTemplates.ts
3640
+ var LIMITS_SERIES_TEMPLATE_IDS = /* @__PURE__ */ new Set([
3641
+ "sum",
3642
+ "prod",
3643
+ "lim",
3644
+ "max",
3645
+ "min",
3646
+ "sup",
3647
+ "inf"
3648
+ ]);
3649
+ function isLimitsSeriesTemplateId(commandId) {
3650
+ return LIMITS_SERIES_TEMPLATE_IDS.has(commandId);
3651
+ }
3652
+ function syncChainIds2(english, arabic) {
3653
+ arabic.id = english.id;
3654
+ const limit = Math.min(english.nodes.length, arabic.nodes.length);
3655
+ for (let index = 0; index < limit; index += 1) {
3656
+ arabic.nodes[index].id = english.nodes[index].id;
3657
+ }
3658
+ }
3659
+ function syncOversetIds(english, arabic) {
3660
+ arabic.id = english.id;
3661
+ if (english.overExpr && arabic.overExpr) {
3662
+ syncChainIds2(english.overExpr, arabic.overExpr);
3663
+ }
3664
+ if (english.baseExpr && arabic.baseExpr) {
3665
+ syncChainIds2(english.baseExpr, arabic.baseExpr);
3666
+ }
3667
+ }
3668
+ function syncUndersetIds(english, arabic) {
3669
+ arabic.id = english.id;
3670
+ if (english.underExpr && arabic.underExpr) {
3671
+ syncChainIds2(english.underExpr, arabic.underExpr);
3672
+ }
3673
+ if (english.baseExpr && arabic.baseExpr) {
3674
+ syncChainIds2(english.baseExpr, arabic.baseExpr);
3675
+ }
3676
+ }
3677
+ function buildLimitsSeriesTemplate(commandId) {
3678
+ if (!isLimitsSeriesTemplateId(commandId)) {
3679
+ throw new Error(`BuTeX: unsupported limits-series template id: ${commandId}`);
3680
+ }
3681
+ const englishOp = createAtomicCommandNode(commandId);
3682
+ const arabicOp = createAtomicCommandNode(commandId);
3683
+ arabicOp.id = englishOp.id;
3684
+ const englishOverset = createOversetNode();
3685
+ const arabicOverset = createOversetNode();
3686
+ syncOversetIds(englishOverset, arabicOverset);
3687
+ englishOverset.baseExpr = createEditorChain([englishOp]);
3688
+ arabicOverset.baseExpr = createEditorChain([arabicOp]);
3689
+ syncChainIds2(englishOverset.baseExpr, arabicOverset.baseExpr);
3690
+ const englishUnderset = createUndersetNode();
3691
+ const arabicUnderset = createUndersetNode();
3692
+ syncUndersetIds(englishUnderset, arabicUnderset);
3693
+ englishUnderset.baseExpr = createEditorChain([englishOverset]);
3694
+ arabicUnderset.baseExpr = createEditorChain([arabicOverset]);
3695
+ syncChainIds2(englishUnderset.baseExpr, arabicUnderset.baseExpr);
3696
+ return { english: englishUnderset, arabic: arabicUnderset };
3697
+ }
3698
+ function buildAccentPairTemplate() {
3699
+ const englishOverset = createOversetNode();
3700
+ const arabicOverset = createOversetNode();
3701
+ syncOversetIds(englishOverset, arabicOverset);
3702
+ const englishUnderset = createUndersetNode();
3703
+ const arabicUnderset = createUndersetNode();
3704
+ syncUndersetIds(englishUnderset, arabicUnderset);
3705
+ englishUnderset.baseExpr = createEditorChain([englishOverset]);
3706
+ arabicUnderset.baseExpr = createEditorChain([arabicOverset]);
3707
+ syncChainIds2(englishUnderset.baseExpr, arabicUnderset.baseExpr);
3708
+ return { english: englishUnderset, arabic: arabicUnderset };
3709
+ }
3710
+ function accentPairTemplateInitialCaret(englishUnderset) {
3711
+ const overset = englishUnderset.baseExpr?.nodes[0];
3712
+ return {
3713
+ chainId: overset?.baseExpr?.id ?? englishUnderset.underExpr?.id ?? "",
3714
+ index: 0
3715
+ };
3716
+ }
3717
+ function limitsSeriesTemplateInitialCaret(englishUnderset) {
3718
+ return {
3719
+ chainId: englishUnderset.underExpr?.id ?? englishUnderset.baseExpr?.id ?? "",
3720
+ index: 0
3721
+ };
3722
+ }
3723
+
3297
3724
  // src/editor/uiLocale.ts
3298
3725
  var ENGLISH_COMMAND_TITLES = {
3299
3726
  cos: "Cosine",
@@ -3337,6 +3764,24 @@ var ENGLISH_COMMAND_TITLES = {
3337
3764
  quadSpace: "Large space",
3338
3765
  qquadSpace: "Extra-large space"
3339
3766
  };
3767
+ var ENGLISH_ACCENT_TITLES = {
3768
+ vec: "Vector arrow",
3769
+ hat: "Hat",
3770
+ tilde: "Tilde",
3771
+ dot: "Dot",
3772
+ ddot: "Double dot",
3773
+ dddot: "Triple dot",
3774
+ bar: "Bar",
3775
+ check: "Check",
3776
+ breve: "Breve",
3777
+ acute: "Acute",
3778
+ grave: "Grave",
3779
+ overline: "Overline",
3780
+ underline: "Underline",
3781
+ overleftarrow: "Over left arrow",
3782
+ overrightarrow: "Over right arrow",
3783
+ overleftrightarrow: "Over left-right arrow"
3784
+ };
3340
3785
  var ENGLISH_OPERATOR_TITLES = {
3341
3786
  inf: "Infinity",
3342
3787
  times: "Multiplication",
@@ -3410,6 +3855,10 @@ var EQUATION_EDITOR_MESSAGES = {
3410
3855
  insertBraces: "\u0625\u062F\u0631\u0627\u062C \u062D\u0627\u0635\u0631\u062A\u064A\u0646",
3411
3856
  insertFraction: "\u0625\u062F\u0631\u0627\u062C \u0643\u0633\u0631",
3412
3857
  insertRoot: "\u0625\u062F\u0631\u0627\u062C \u062C\u0630\u0631",
3858
+ insertOverset: "\u0625\u062F\u0631\u0627\u062C \u0641\u0648\u0642",
3859
+ insertUnderset: "\u0625\u062F\u0631\u0627\u062C \u062A\u062D\u062A",
3860
+ insertAccentPair: "\u0625\u062F\u0631\u0627\u062C \u0641\u0648\u0642 \u0648\u062A\u062D\u062A",
3861
+ insertAccents: "\u0625\u062F\u0631\u0627\u062C \u0644\u0643\u0646\u0629",
3413
3862
  environments: "\u0627\u0644\u0628\u064A\u0626\u0627\u062A",
3414
3863
  insertEnvironment: "\u0625\u062F\u0631\u0627\u062C \u0628\u064A\u0626\u0629 \u0634\u0628\u0643\u064A\u0629",
3415
3864
  environmentType: "\u0646\u0648\u0639 \u0627\u0644\u0628\u064A\u0626\u0629",
@@ -3517,6 +3966,10 @@ var EQUATION_EDITOR_MESSAGES = {
3517
3966
  insertBraces: "Insert braces",
3518
3967
  insertFraction: "Insert fraction",
3519
3968
  insertRoot: "Insert root",
3969
+ insertOverset: "Insert overset",
3970
+ insertUnderset: "Insert underset",
3971
+ insertAccentPair: "Insert overset and underset",
3972
+ insertAccents: "Insert accent",
3520
3973
  environments: "Environments",
3521
3974
  insertEnvironment: "Insert grid environment",
3522
3975
  environmentType: "Environment type",
@@ -3617,6 +4070,9 @@ function atomicCommandTitle(spec, locale) {
3617
4070
  function atomicOperatorCommandTitle(spec, locale) {
3618
4071
  return locale === "en" ? ENGLISH_OPERATOR_TITLES[spec.id] ?? spec.title : spec.title;
3619
4072
  }
4073
+ function accentCommandTitle(spec, locale) {
4074
+ return locale === "en" ? ENGLISH_ACCENT_TITLES[spec.id] ?? spec.title : spec.title;
4075
+ }
3620
4076
 
3621
4077
  // src/editor/state.ts
3622
4078
  function ensureSyncEntry(session, nodeId) {
@@ -3651,7 +4107,7 @@ function syncSelectionToCaret(session) {
3651
4107
  session.selectedNodeId = located.relation.ownerNodeId;
3652
4108
  return;
3653
4109
  }
3654
- 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") {
4110
+ 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") {
3655
4111
  session.selectedNodeId = located.relation.ownerNodeId;
3656
4112
  return;
3657
4113
  }
@@ -4008,6 +4464,106 @@ function moveCaretVertical(session, direction) {
4008
4464
  appendDebug(next, "moveCaretVertical", "sqrt-radicand-down-exit");
4009
4465
  return next;
4010
4466
  }
4467
+ if (located.relation.kind === "overExpr" && ownerLocated && ownerNode && ownerNode.baseExpr) {
4468
+ if (direction === "down") {
4469
+ next.caret = {
4470
+ chainId: ownerNode.baseExpr.id,
4471
+ index: ownerNode.baseExpr.nodes.length
4472
+ };
4473
+ next.selectedStructureNodeId = null;
4474
+ syncSelectionToCaret(next);
4475
+ appendDebug(next, "moveCaretVertical", "overset-over->base");
4476
+ return next;
4477
+ }
4478
+ next.caret = {
4479
+ chainId: ownerLocated.chain.id,
4480
+ index: ownerLocated.index
4481
+ };
4482
+ next.selectedStructureNodeId = null;
4483
+ syncSelectionToCaret(next);
4484
+ appendDebug(next, "moveCaretVertical", "overset-over-up-exit");
4485
+ return next;
4486
+ }
4487
+ if (located.relation.kind === "baseExpr" && ownerLocated && ownerNode && ownerNode.kind === "overset" && ownerNode.overExpr) {
4488
+ if (direction === "up") {
4489
+ next.caret = {
4490
+ chainId: ownerNode.overExpr.id,
4491
+ index: ownerNode.overExpr.nodes.length
4492
+ };
4493
+ next.selectedStructureNodeId = null;
4494
+ syncSelectionToCaret(next);
4495
+ appendDebug(next, "moveCaretVertical", "overset-base->over");
4496
+ return next;
4497
+ }
4498
+ next.caret = {
4499
+ chainId: ownerLocated.chain.id,
4500
+ index: ownerLocated.index + 1
4501
+ };
4502
+ next.selectedStructureNodeId = null;
4503
+ syncSelectionToCaret(next);
4504
+ appendDebug(next, "moveCaretVertical", "overset-base-down-exit");
4505
+ return next;
4506
+ }
4507
+ if (located.relation.kind === "baseExpr" && ownerLocated && ownerNode && ownerNode.kind === "underset" && ownerNode.underExpr) {
4508
+ if (direction === "down") {
4509
+ next.caret = {
4510
+ chainId: ownerNode.underExpr.id,
4511
+ index: ownerNode.underExpr.nodes.length
4512
+ };
4513
+ next.selectedStructureNodeId = null;
4514
+ syncSelectionToCaret(next);
4515
+ appendDebug(next, "moveCaretVertical", "underset-base->under");
4516
+ return next;
4517
+ }
4518
+ next.caret = {
4519
+ chainId: ownerLocated.chain.id,
4520
+ index: ownerLocated.index
4521
+ };
4522
+ next.selectedStructureNodeId = null;
4523
+ syncSelectionToCaret(next);
4524
+ appendDebug(next, "moveCaretVertical", "underset-base-up-exit");
4525
+ return next;
4526
+ }
4527
+ if (located.relation.kind === "underExpr" && ownerLocated && ownerNode && ownerNode.baseExpr) {
4528
+ if (direction === "up") {
4529
+ next.caret = {
4530
+ chainId: ownerNode.baseExpr.id,
4531
+ index: ownerNode.baseExpr.nodes.length
4532
+ };
4533
+ next.selectedStructureNodeId = null;
4534
+ syncSelectionToCaret(next);
4535
+ appendDebug(next, "moveCaretVertical", "underset-under->base");
4536
+ return next;
4537
+ }
4538
+ next.caret = {
4539
+ chainId: ownerLocated.chain.id,
4540
+ index: ownerLocated.index + 1
4541
+ };
4542
+ next.selectedStructureNodeId = null;
4543
+ syncSelectionToCaret(next);
4544
+ appendDebug(next, "moveCaretVertical", "underset-under-down-exit");
4545
+ return next;
4546
+ }
4547
+ if (located.relation.kind === "baseExpr" && ownerLocated && ownerNode && ownerNode.kind === "accent") {
4548
+ if (direction === "up") {
4549
+ next.caret = {
4550
+ chainId: ownerLocated.chain.id,
4551
+ index: ownerLocated.index
4552
+ };
4553
+ next.selectedStructureNodeId = null;
4554
+ syncSelectionToCaret(next);
4555
+ appendDebug(next, "moveCaretVertical", "accent-base-up-exit");
4556
+ return next;
4557
+ }
4558
+ next.caret = {
4559
+ chainId: ownerLocated.chain.id,
4560
+ index: ownerLocated.index + 1
4561
+ };
4562
+ next.selectedStructureNodeId = null;
4563
+ syncSelectionToCaret(next);
4564
+ appendDebug(next, "moveCaretVertical", "accent-base-down-exit");
4565
+ return next;
4566
+ }
4011
4567
  if (located.relation.kind === "matrixCell" && ownerLocated && ownerNode?.matrixRows) {
4012
4568
  const rowIndex = located.relation.rowIndex ?? 0;
4013
4569
  const columnIndex = located.relation.columnIndex ?? 0;
@@ -4385,6 +4941,119 @@ function insertSqrt(session) {
4385
4941
  appendDebug(next, "insertSqrt", "");
4386
4942
  return next;
4387
4943
  }
4944
+ function insertOverset(session) {
4945
+ const base = replaceSelectionFirst(session);
4946
+ const next = cloneEditorSession(base);
4947
+ const englishNode = createOversetNode();
4948
+ const arabicNode = createOversetNode();
4949
+ arabicNode.id = englishNode.id;
4950
+ if (arabicNode.overExpr && englishNode.overExpr) {
4951
+ arabicNode.overExpr.id = englishNode.overExpr.id;
4952
+ }
4953
+ if (arabicNode.baseExpr && englishNode.baseExpr) {
4954
+ arabicNode.baseExpr.id = englishNode.baseExpr.id;
4955
+ }
4956
+ insertMirroredNode(next, next.caret.chainId, next.caret.index, englishNode, arabicNode);
4957
+ next.caret = {
4958
+ chainId: englishNode.overExpr ? englishNode.overExpr.id : next.caret.chainId,
4959
+ index: 0
4960
+ };
4961
+ next.selectedStructureNodeId = null;
4962
+ syncSelectionToCaret(next);
4963
+ appendDebug(next, "insertOverset", "");
4964
+ return next;
4965
+ }
4966
+ function insertUnderset(session) {
4967
+ const base = replaceSelectionFirst(session);
4968
+ const next = cloneEditorSession(base);
4969
+ const englishNode = createUndersetNode();
4970
+ const arabicNode = createUndersetNode();
4971
+ arabicNode.id = englishNode.id;
4972
+ if (arabicNode.underExpr && englishNode.underExpr) {
4973
+ arabicNode.underExpr.id = englishNode.underExpr.id;
4974
+ }
4975
+ if (arabicNode.baseExpr && englishNode.baseExpr) {
4976
+ arabicNode.baseExpr.id = englishNode.baseExpr.id;
4977
+ }
4978
+ insertMirroredNode(next, next.caret.chainId, next.caret.index, englishNode, arabicNode);
4979
+ next.caret = {
4980
+ chainId: englishNode.underExpr ? englishNode.underExpr.id : next.caret.chainId,
4981
+ index: 0
4982
+ };
4983
+ next.selectedStructureNodeId = null;
4984
+ syncSelectionToCaret(next);
4985
+ appendDebug(next, "insertUnderset", "");
4986
+ return next;
4987
+ }
4988
+ function insertLimitsSeriesTemplate(session, commandId) {
4989
+ const base = replaceSelectionFirst(session);
4990
+ const next = cloneEditorSession(base);
4991
+ const { english, arabic } = buildLimitsSeriesTemplate(commandId);
4992
+ insertMirroredNode(next, next.caret.chainId, next.caret.index, english, arabic);
4993
+ syncSubtreeRecursive(next, english, arabic);
4994
+ next.caret = limitsSeriesTemplateInitialCaret(english);
4995
+ next.selectedStructureNodeId = null;
4996
+ syncSelectionToCaret(next);
4997
+ appendDebug(next, "insertLimitsSeriesTemplate", commandId);
4998
+ return next;
4999
+ }
5000
+ function insertAccentPair(session) {
5001
+ const base = replaceSelectionFirst(session);
5002
+ const next = cloneEditorSession(base);
5003
+ const { english, arabic } = buildAccentPairTemplate();
5004
+ insertMirroredNode(next, next.caret.chainId, next.caret.index, english, arabic);
5005
+ syncSubtreeRecursive(next, english, arabic);
5006
+ next.caret = accentPairTemplateInitialCaret(english);
5007
+ next.selectedStructureNodeId = null;
5008
+ syncSelectionToCaret(next);
5009
+ appendDebug(next, "insertAccentPair", "");
5010
+ return next;
5011
+ }
5012
+ function insertAccent(session, accentId) {
5013
+ const next = cloneEditorSession(session);
5014
+ const englishNode = createAccentNode(accentId);
5015
+ const arabicNode = createAccentNode(accentId);
5016
+ arabicNode.id = englishNode.id;
5017
+ if (arabicNode.baseExpr && englishNode.baseExpr) {
5018
+ arabicNode.baseExpr.id = englishNode.baseExpr.id;
5019
+ }
5020
+ if (isSelectionActive(next.selection) && next.selection) {
5021
+ const sel = next.selection;
5022
+ const { start, end } = normalizeSelection(sel);
5023
+ const englishLocated = findChainById(next.englishTree, sel.chainId);
5024
+ const arabicLocated = findChainById(next.arabicTree, sel.chainId);
5025
+ if (englishLocated && arabicLocated && end > start) {
5026
+ const count = end - start;
5027
+ const englishWrapped = englishLocated.chain.nodes.splice(start, count);
5028
+ const arabicWrapped = arabicLocated.chain.nodes.splice(start, count);
5029
+ englishNode.baseExpr.nodes = englishWrapped;
5030
+ arabicNode.baseExpr.nodes = arabicWrapped;
5031
+ englishLocated.chain.nodes.splice(start, 0, englishNode);
5032
+ arabicLocated.chain.nodes.splice(start, 0, arabicNode);
5033
+ syncSubtreeRecursive(next, englishNode, arabicNode);
5034
+ next.caret = {
5035
+ chainId: englishNode.baseExpr.id,
5036
+ index: englishWrapped.length
5037
+ };
5038
+ next.selection = null;
5039
+ next.selectedStructureNodeId = null;
5040
+ syncSelectionToCaret(next);
5041
+ appendDebug(next, "insertAccent", `${accentId}:wrap`);
5042
+ return next;
5043
+ }
5044
+ }
5045
+ insertMirroredNode(next, next.caret.chainId, next.caret.index, englishNode, arabicNode);
5046
+ syncSubtreeRecursive(next, englishNode, arabicNode);
5047
+ next.caret = {
5048
+ chainId: englishNode.baseExpr ? englishNode.baseExpr.id : next.caret.chainId,
5049
+ index: 0
5050
+ };
5051
+ next.selection = null;
5052
+ next.selectedStructureNodeId = null;
5053
+ syncSelectionToCaret(next);
5054
+ appendDebug(next, "insertAccent", `${accentId}:empty`);
5055
+ return next;
5056
+ }
4388
5057
  function insertMatrixEnv(session, style, rows, columns) {
4389
5058
  return insertGridEnv(session, style, rows, columns);
4390
5059
  }
@@ -4632,7 +5301,7 @@ function deleteBackward(session) {
4632
5301
  if (!previousNode) {
4633
5302
  return session;
4634
5303
  }
4635
- if ((previousNode.kind === "delimiter" || previousNode.kind === "frac" || previousNode.kind === "sqrt" || previousNode.kind === "env") && next.selectedStructureNodeId !== previousNode.id) {
5304
+ 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) {
4636
5305
  next.selectedStructureNodeId = previousNode.id;
4637
5306
  next.selectedNodeId = previousNode.id;
4638
5307
  appendDebug(next, "deleteBackward", "selected structure");
@@ -5122,6 +5791,168 @@ function buildSqrtNodeBody(node, buildChain, side) {
5122
5791
  return wrap;
5123
5792
  }
5124
5793
 
5794
+ // src/editor/display/overset.ts
5795
+ var OVERSET_CSS = `
5796
+ .overset {
5797
+ display: inline-flex;
5798
+ flex-direction: column;
5799
+ align-items: center;
5800
+ justify-content: center;
5801
+ vertical-align: middle;
5802
+ margin: 0 2px;
5803
+ min-width: 1.2em;
5804
+ }
5805
+
5806
+ .overset-over {
5807
+ display: inline-flex;
5808
+ justify-content: center;
5809
+ align-items: center;
5810
+ min-height: 0.85em;
5811
+ padding: 0 2px;
5812
+ font-size: 0.72em;
5813
+ line-height: 1.1;
5814
+ }
5815
+
5816
+ .overset-base {
5817
+ display: inline-flex;
5818
+ justify-content: center;
5819
+ align-items: center;
5820
+ min-height: 1.05em;
5821
+ padding: 0 2px;
5822
+ }
5823
+ `.trim();
5824
+ function buildOversetNodeBody(node, buildChain) {
5825
+ const wrap = document.createElement("span");
5826
+ wrap.className = "overset";
5827
+ const over = document.createElement("span");
5828
+ over.className = "overset-over";
5829
+ if (node.overExpr) {
5830
+ over.appendChild(buildChain(node.overExpr));
5831
+ }
5832
+ const base = document.createElement("span");
5833
+ base.className = "overset-base";
5834
+ if (node.baseExpr) {
5835
+ base.appendChild(buildChain(node.baseExpr));
5836
+ }
5837
+ wrap.appendChild(over);
5838
+ wrap.appendChild(base);
5839
+ return wrap;
5840
+ }
5841
+
5842
+ // src/editor/display/underset.ts
5843
+ var UNDERSET_CSS = `
5844
+ .underset {
5845
+ display: inline-flex;
5846
+ flex-direction: column;
5847
+ align-items: center;
5848
+ justify-content: center;
5849
+ vertical-align: middle;
5850
+ margin: 0 2px;
5851
+ min-width: 1.2em;
5852
+ }
5853
+
5854
+ .underset-base {
5855
+ display: inline-flex;
5856
+ justify-content: center;
5857
+ align-items: center;
5858
+ min-height: 1.05em;
5859
+ padding: 0 2px;
5860
+ }
5861
+
5862
+ .underset-under {
5863
+ display: inline-flex;
5864
+ justify-content: center;
5865
+ align-items: center;
5866
+ min-height: 0.85em;
5867
+ padding: 0 2px;
5868
+ font-size: 0.72em;
5869
+ line-height: 1.1;
5870
+ }
5871
+ `.trim();
5872
+ function buildUndersetNodeBody(node, buildChain) {
5873
+ const wrap = document.createElement("span");
5874
+ wrap.className = "underset";
5875
+ const base = document.createElement("span");
5876
+ base.className = "underset-base";
5877
+ if (node.baseExpr) {
5878
+ base.appendChild(buildChain(node.baseExpr));
5879
+ }
5880
+ const under = document.createElement("span");
5881
+ under.className = "underset-under";
5882
+ if (node.underExpr) {
5883
+ under.appendChild(buildChain(node.underExpr));
5884
+ }
5885
+ wrap.appendChild(base);
5886
+ wrap.appendChild(under);
5887
+ return wrap;
5888
+ }
5889
+
5890
+ // src/editor/display/accent.ts
5891
+ var ACCENT_CSS = `
5892
+ .math-accent {
5893
+ display: inline-flex;
5894
+ flex-direction: column;
5895
+ align-items: center;
5896
+ justify-content: center;
5897
+ vertical-align: middle;
5898
+ margin: 0 2px;
5899
+ min-width: 1.1em;
5900
+ }
5901
+
5902
+ .math-accent-chrome {
5903
+ display: inline-flex;
5904
+ justify-content: center;
5905
+ align-items: center;
5906
+ min-height: 0.7em;
5907
+ padding: 0 2px;
5908
+ font-size: 0.85em;
5909
+ line-height: 1;
5910
+ color: var(--butex-script-color, #475569);
5911
+ user-select: none;
5912
+ }
5913
+
5914
+ .math-accent-base {
5915
+ display: inline-flex;
5916
+ justify-content: center;
5917
+ align-items: center;
5918
+ min-height: 1.05em;
5919
+ padding: 0 2px;
5920
+ }
5921
+
5922
+ .math-accent--under .math-accent-chrome {
5923
+ min-height: 0.45em;
5924
+ border-top: 1.5px solid currentColor;
5925
+ width: 100%;
5926
+ font-size: 0;
5927
+ color: var(--butex-surface-fg, #0f172a);
5928
+ }
5929
+ `.trim();
5930
+ function buildAccentNodeBody(node, buildChain) {
5931
+ const wrap = document.createElement("span");
5932
+ const spec = accentCommandSpec(node.expr);
5933
+ const placement = spec?.placement ?? "over";
5934
+ wrap.className = placement === "under" ? "math-accent math-accent--under" : "math-accent math-accent--over";
5935
+ const chrome = document.createElement("span");
5936
+ chrome.className = "math-accent-chrome";
5937
+ chrome.setAttribute("aria-hidden", "true");
5938
+ if (placement === "over") {
5939
+ chrome.textContent = spec?.label ?? "\u02C6";
5940
+ }
5941
+ const base = document.createElement("span");
5942
+ base.className = "math-accent-base";
5943
+ if (node.baseExpr) {
5944
+ base.appendChild(buildChain(node.baseExpr));
5945
+ }
5946
+ if (placement === "under") {
5947
+ wrap.appendChild(base);
5948
+ wrap.appendChild(chrome);
5949
+ } else {
5950
+ wrap.appendChild(chrome);
5951
+ wrap.appendChild(base);
5952
+ }
5953
+ return wrap;
5954
+ }
5955
+
5125
5956
  // src/editor/display/env.ts
5126
5957
  var WRAPPERS = {
5127
5958
  matrix: { left: "", right: "" },
@@ -5494,6 +6325,15 @@ function buildNodeBody(node, buildChain, side, digitForm = "western", uiLocale =
5494
6325
  if (node.kind === "sqrt") {
5495
6326
  return buildSqrtNodeBody(node, buildChain, side);
5496
6327
  }
6328
+ if (node.kind === "overset") {
6329
+ return buildOversetNodeBody(node, buildChain);
6330
+ }
6331
+ if (node.kind === "underset") {
6332
+ return buildUndersetNodeBody(node, buildChain);
6333
+ }
6334
+ if (node.kind === "accent") {
6335
+ return buildAccentNodeBody(node, buildChain);
6336
+ }
5497
6337
  if (node.kind === "env") {
5498
6338
  return buildMatrixEnvNodeBody(node, buildChain, side);
5499
6339
  }
@@ -5693,6 +6533,12 @@ ${FRAC_CSS}
5693
6533
 
5694
6534
  ${SQRT_CSS}
5695
6535
 
6536
+ ${OVERSET_CSS}
6537
+
6538
+ ${UNDERSET_CSS}
6539
+
6540
+ ${ACCENT_CSS}
6541
+
5696
6542
  ${MATRIX_ENV_CSS}
5697
6543
 
5698
6544
  ${ATOMIC_COMMAND_CSS}
@@ -6412,6 +7258,26 @@ function createEditorRuntime(options) {
6412
7258
  applyStructural((prev) => insertSqrt(prev));
6413
7259
  surfaceEl.focus();
6414
7260
  },
7261
+ insertOverset: () => {
7262
+ applyStructural((prev) => insertOverset(prev));
7263
+ surfaceEl.focus();
7264
+ },
7265
+ insertUnderset: () => {
7266
+ applyStructural((prev) => insertUnderset(prev));
7267
+ surfaceEl.focus();
7268
+ },
7269
+ insertLimitsSeriesTemplate: (commandId) => {
7270
+ applyStructural((prev) => insertLimitsSeriesTemplate(prev, commandId));
7271
+ surfaceEl.focus();
7272
+ },
7273
+ insertAccentPair: () => {
7274
+ applyStructural((prev) => insertAccentPair(prev));
7275
+ surfaceEl.focus();
7276
+ },
7277
+ insertAccent: (accentId) => {
7278
+ applyStructural((prev) => insertAccent(prev, accentId));
7279
+ surfaceEl.focus();
7280
+ },
6415
7281
  insertAtomicCommand: (commandId) => {
6416
7282
  applyStructural((prev) => insertAtomicCommand(prev, commandId));
6417
7283
  surfaceEl.focus();
@@ -6738,6 +7604,56 @@ function commandToEditorNode(node) {
6738
7604
  }
6739
7605
  return { editable: true, node: sqrt };
6740
7606
  }
7607
+ if (node.name === "\\overset" && node.mandatoryArgs.length >= 2) {
7608
+ const overset = createOversetNode();
7609
+ const overExpr = chainToEditorChain(node.mandatoryArgs[0]);
7610
+ const baseExpr = chainToEditorChain(node.mandatoryArgs[1]);
7611
+ if (!overExpr.editable) {
7612
+ return overExpr;
7613
+ }
7614
+ if (!baseExpr.editable) {
7615
+ return baseExpr;
7616
+ }
7617
+ overset.overExpr = overExpr.chain;
7618
+ overset.baseExpr = baseExpr.chain;
7619
+ const scripts = attachScripts(node, overset);
7620
+ if (scripts) {
7621
+ return scripts;
7622
+ }
7623
+ return { editable: true, node: overset };
7624
+ }
7625
+ if (node.name === "\\underset" && node.mandatoryArgs.length >= 2) {
7626
+ const underset = createUndersetNode();
7627
+ const underExpr = chainToEditorChain(node.mandatoryArgs[0]);
7628
+ const baseExpr = chainToEditorChain(node.mandatoryArgs[1]);
7629
+ if (!underExpr.editable) {
7630
+ return underExpr;
7631
+ }
7632
+ if (!baseExpr.editable) {
7633
+ return baseExpr;
7634
+ }
7635
+ underset.underExpr = underExpr.chain;
7636
+ underset.baseExpr = baseExpr.chain;
7637
+ const scripts = attachScripts(node, underset);
7638
+ if (scripts) {
7639
+ return scripts;
7640
+ }
7641
+ return { editable: true, node: underset };
7642
+ }
7643
+ const accentId = accentCommandIdFromTex(node.name);
7644
+ if (accentId && node.mandatoryArgs.length >= 1) {
7645
+ const accent = createAccentNode(accentId);
7646
+ const baseExpr = chainToEditorChain(node.mandatoryArgs[0]);
7647
+ if (!baseExpr.editable) {
7648
+ return baseExpr;
7649
+ }
7650
+ accent.baseExpr = baseExpr.chain;
7651
+ const scripts = attachScripts(node, accent);
7652
+ if (scripts) {
7653
+ return scripts;
7654
+ }
7655
+ return { editable: true, node: accent };
7656
+ }
6741
7657
  const atomicId = commandIdForTex(node.name);
6742
7658
  if (atomicId && node.optionalArgs.length === 0 && node.mandatoryArgs.length === 0) {
6743
7659
  const atomic = createEditorNode("atomicCommand", atomicId);
@@ -6874,6 +7790,21 @@ function editorEnvToAstNode(node) {
6874
7790
  const scripts = attachAstScripts(node, env);
6875
7791
  return scripts ?? { ok: true, node: env };
6876
7792
  }
7793
+ function accentChainForExport(accent) {
7794
+ if (!accent) {
7795
+ return { ok: true, chain: new ChainNode([]) };
7796
+ }
7797
+ return editorChainToAstChain(accent);
7798
+ }
7799
+ function nodeFromAccentBase(command, accent, base) {
7800
+ if (accent.chain.length > 0) {
7801
+ return new CommandNode(command, [], [accent, base]);
7802
+ }
7803
+ if (base.chain.length === 1) {
7804
+ return base.chain[0];
7805
+ }
7806
+ return new DelimiterNode("", base, "");
7807
+ }
6877
7808
  function editorNodeToAstNode(node) {
6878
7809
  let astNode;
6879
7810
  if (node.kind === "char") {
@@ -6912,6 +7843,36 @@ function editorNodeToAstNode(node) {
6912
7843
  optionalArgs.push(rootIndex.chain);
6913
7844
  }
6914
7845
  astNode = new CommandNode("\\sqrt", optionalArgs, [radicand.chain]);
7846
+ } else if (node.kind === "overset" && node.baseExpr) {
7847
+ const accent = accentChainForExport(node.overExpr);
7848
+ if (!accent.ok) {
7849
+ return accent;
7850
+ }
7851
+ const baseExpr = editorChainToAstChain(node.baseExpr);
7852
+ if (!baseExpr.ok) {
7853
+ return baseExpr;
7854
+ }
7855
+ astNode = nodeFromAccentBase("\\overset", accent.chain, baseExpr.chain);
7856
+ } else if (node.kind === "underset" && node.baseExpr) {
7857
+ const accent = accentChainForExport(node.underExpr);
7858
+ if (!accent.ok) {
7859
+ return accent;
7860
+ }
7861
+ const baseExpr = editorChainToAstChain(node.baseExpr);
7862
+ if (!baseExpr.ok) {
7863
+ return baseExpr;
7864
+ }
7865
+ astNode = nodeFromAccentBase("\\underset", accent.chain, baseExpr.chain);
7866
+ } else if (node.kind === "accent" && node.baseExpr) {
7867
+ const tex = accentCommandSpec(node.expr)?.englishTex;
7868
+ if (!tex) {
7869
+ 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}` };
7870
+ }
7871
+ const baseExpr = editorChainToAstChain(node.baseExpr);
7872
+ if (!baseExpr.ok) {
7873
+ return baseExpr;
7874
+ }
7875
+ astNode = new CommandNode(tex, [], [baseExpr.chain]);
6915
7876
  } else if (node.kind === "atomicCommand") {
6916
7877
  const tex = atomicCommandSpec(node.expr)?.englishTex;
6917
7878
  if (!tex) {
@@ -8902,7 +9863,10 @@ var import_react2 = require("react");
8902
9863
  // src/mathjax/svgPatcher.ts
8903
9864
  var SVG_ARABSQRT_SELECTOR = 'mjx-container[jax="SVG"] svg .mjx-rtl-mirror[data-mjx-rtl-root="true"]';
8904
9865
  var ARABSQRT_SELECTOR = '.mjx-rtl-mirror[data-mjx-rtl-root="true"]';
9866
+ var SVG_PREVIEW_MIRROR_SELECTOR = 'mjx-container[jax="SVG"] svg .butex-preview-mirror';
9867
+ var PREVIEW_MIRROR_SELECTOR = ".butex-preview-mirror";
8905
9868
  var PATCHED_ATTR = "data-butex-svg-arabsqrt";
9869
+ var MIRROR_PATCHED_ATTR = "data-butex-svg-mirror";
8906
9870
  var ROOT_INDEX_SCALE = 0.72;
8907
9871
  var ROOT_INDEX_GAP_FACTOR = 0.08;
8908
9872
  var ROOT_INDEX_MIN_GAP = 2;
@@ -8927,11 +9891,12 @@ function directSvgElementChildren(element) {
8927
9891
  return Array.from(element.children).filter((child) => child instanceof SVGElement);
8928
9892
  }
8929
9893
  function boxFor(element) {
8930
- if (!(element instanceof SVGGraphicsElement) || typeof element.getBBox !== "function") {
9894
+ const candidate = element;
9895
+ if (typeof candidate.getBBox !== "function") {
8931
9896
  return null;
8932
9897
  }
8933
9898
  try {
8934
- const box = element.getBBox();
9899
+ const box = candidate.getBBox();
8935
9900
  return {
8936
9901
  x: box.x,
8937
9902
  y: box.y,
@@ -9175,6 +10140,31 @@ function patchArabSqrtRoot(root) {
9175
10140
  root.setAttribute(PATCHED_ATTR, "patched");
9176
10141
  rootNode.setAttribute(PATCHED_ATTR, "patched");
9177
10142
  }
10143
+ function patchPreviewMirror(element) {
10144
+ if (element.getAttribute(MIRROR_PATCHED_ATTR) === "patched") {
10145
+ return;
10146
+ }
10147
+ const box = boxFor(element);
10148
+ if (!box || box.width <= 0) {
10149
+ return;
10150
+ }
10151
+ const [tx, ty] = readTranslate(element);
10152
+ const mirrorX = tx + 2 * box.x + box.width;
10153
+ element.setAttribute(
10154
+ "transform",
10155
+ `translate(${roundSvg(mirrorX)},${roundSvg(ty)}) scale(-1,1)`
10156
+ );
10157
+ element.setAttribute(MIRROR_PATCHED_ATTR, "patched");
10158
+ }
10159
+ function collectPreviewMirrors(root) {
10160
+ let mirrors = Array.from(root.querySelectorAll(SVG_PREVIEW_MIRROR_SELECTOR));
10161
+ if (!mirrors.length) {
10162
+ mirrors = Array.from(root.querySelectorAll(PREVIEW_MIRROR_SELECTOR)).filter((candidate) => {
10163
+ return candidate.closest('mjx-container[jax="SVG"]') != null;
10164
+ });
10165
+ }
10166
+ return mirrors;
10167
+ }
9178
10168
  function patchBuTeXSvgMath(root) {
9179
10169
  if (typeof root.querySelectorAll !== "function") {
9180
10170
  return;
@@ -9186,6 +10176,7 @@ function patchBuTeXSvgMath(root) {
9186
10176
  });
9187
10177
  }
9188
10178
  roots.sort((a, b) => rootDepth(b) - rootDepth(a)).forEach((arabSqrtRoot) => patchArabSqrtRoot(arabSqrtRoot));
10179
+ collectPreviewMirrors(root).forEach((mirror) => patchPreviewMirror(mirror));
9189
10180
  }
9190
10181
 
9191
10182
  // src/mathjax/renderIsland.ts
@@ -10945,6 +11936,29 @@ var WIDGET_CHROME_CSS = `
10945
11936
  padding-top: 1px;
10946
11937
  }
10947
11938
 
11939
+ .butex-widget .toolbar-accent-icon {
11940
+ display: inline-flex;
11941
+ flex-direction: column;
11942
+ align-items: center;
11943
+ justify-content: center;
11944
+ min-width: 14px;
11945
+ font-size: 10px;
11946
+ line-height: 1;
11947
+ gap: 1px;
11948
+ }
11949
+
11950
+ .butex-widget .toolbar-accent-icon--over span:first-child,
11951
+ .butex-widget .toolbar-accent-icon--under span:last-child {
11952
+ font-size: 8px;
11953
+ opacity: 0.85;
11954
+ }
11955
+
11956
+ .butex-widget .toolbar-accent-icon--pair span:first-child,
11957
+ .butex-widget .toolbar-accent-icon--pair span:last-child {
11958
+ font-size: 8px;
11959
+ opacity: 0.85;
11960
+ }
11961
+
10948
11962
  .butex-widget .matrix-command-menu {
10949
11963
  position: relative;
10950
11964
  display: inline-flex;
@@ -11681,6 +12695,7 @@ var CHARACTER_FONT_OPTIONS = [
11681
12695
  { id: "diwani", label: "\u062F\u064A\u0648" },
11682
12696
  { id: "diwaniOutline", label: "\u0638\u0644" }
11683
12697
  ];
12698
+ var ACCENT_COMMANDS_LIST = accentCommandsList();
11684
12699
  var FUNCTION_COMMANDS = atomicCommandsByCategory("function");
11685
12700
  var LIMITS_SERIES_COMMANDS = atomicCommandsByCategory("limits_series");
11686
12701
  var FUNCTION2_COMMANDS = atomicCommandsByCategory("function2");
@@ -11828,6 +12843,7 @@ var ButexEditor = (0, import_react8.forwardRef)(
11828
12843
  const [operator2MenuOpen, setOperator2MenuOpen] = (0, import_react8.useState)(false);
11829
12844
  const [operator3MenuOpen, setOperator3MenuOpen] = (0, import_react8.useState)(false);
11830
12845
  const [dotMenuOpen, setDotMenuOpen] = (0, import_react8.useState)(false);
12846
+ const [accentMenuOpen, setAccentMenuOpen] = (0, import_react8.useState)(false);
11831
12847
  const [integralMenuOpen, setIntegralMenuOpen] = (0, import_react8.useState)(false);
11832
12848
  const [selectedDigitForm2, setSelectedDigitForm] = (0, import_react8.useState)("western");
11833
12849
  const [selectedCharacterFont, setSelectedCharacterFont] = (0, import_react8.useState)("default");
@@ -12097,7 +13113,78 @@ ${arabic || currentMessages.empty}`;
12097
13113
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { id: "insert-sqrt", className: "icon-btn", type: "button", title: messages.insertRoot, "aria-label": messages.insertRoot, onClick: () => {
12098
13114
  runtimeRef.current?.insertSqrt();
12099
13115
  focusSurface();
12100
- }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "toolbar-sqrt-icon", "aria-hidden": "true", children: "\u221A" }) })
13116
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "toolbar-sqrt-icon", "aria-hidden": "true", children: "\u221A" }) }),
13117
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { id: "insert-overset", className: "icon-btn", type: "button", title: messages.insertOverset, "aria-label": messages.insertOverset, onClick: () => {
13118
+ runtimeRef.current?.insertOverset();
13119
+ focusSurface();
13120
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "toolbar-accent-icon toolbar-accent-icon--over", "aria-hidden": "true", children: [
13121
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: "\u2217" }),
13122
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: "\u25A1" })
13123
+ ] }) }),
13124
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { id: "insert-underset", className: "icon-btn", type: "button", title: messages.insertUnderset, "aria-label": messages.insertUnderset, onClick: () => {
13125
+ runtimeRef.current?.insertUnderset();
13126
+ focusSurface();
13127
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "toolbar-accent-icon toolbar-accent-icon--under", "aria-hidden": "true", children: [
13128
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: "\u25A1" }),
13129
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: "\u2217" })
13130
+ ] }) }),
13131
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { id: "insert-accent-pair", className: "icon-btn", type: "button", title: messages.insertAccentPair, "aria-label": messages.insertAccentPair, onClick: () => {
13132
+ runtimeRef.current?.insertAccentPair();
13133
+ focusSurface();
13134
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "toolbar-accent-icon toolbar-accent-icon--pair", "aria-hidden": "true", children: [
13135
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: "\u2217" }),
13136
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: "\u25A1" }),
13137
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: "\u2217" })
13138
+ ] }) }),
13139
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
13140
+ "div",
13141
+ {
13142
+ className: "function-command-menu operator-command-menu",
13143
+ onBlur: (event) => {
13144
+ const nextFocus = event.relatedTarget;
13145
+ if (!(nextFocus instanceof Node) || !event.currentTarget.contains(nextFocus)) {
13146
+ setAccentMenuOpen(false);
13147
+ }
13148
+ },
13149
+ children: [
13150
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
13151
+ "button",
13152
+ {
13153
+ id: "insert-accents",
13154
+ className: "icon-btn function-command-btn operator-command-btn",
13155
+ type: "button",
13156
+ title: messages.insertAccents,
13157
+ "aria-label": messages.insertAccents,
13158
+ "aria-haspopup": "listbox",
13159
+ "aria-expanded": accentMenuOpen,
13160
+ onClick: () => setAccentMenuOpen((open) => !open),
13161
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "toolbar-accent-icon toolbar-accent-icon--over", "aria-hidden": "true", children: [
13162
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: "\u02C6" }),
13163
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: "\u25A1" })
13164
+ ] })
13165
+ }
13166
+ ),
13167
+ /* @__PURE__ */ (0, import_jsx_runtime12.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_runtime12.jsx)(
13168
+ "button",
13169
+ {
13170
+ className: "function-command-option operator-command-option",
13171
+ type: "button",
13172
+ role: "option",
13173
+ title: accentCommandTitle(command, uiLocale),
13174
+ "aria-label": accentCommandTitle(command, uiLocale),
13175
+ onMouseDown: (event) => event.preventDefault(),
13176
+ onClick: () => {
13177
+ runtimeRef.current?.insertAccent(command.id);
13178
+ setAccentMenuOpen(false);
13179
+ focusSurface();
13180
+ },
13181
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "operator-command-label", children: command.label })
13182
+ },
13183
+ command.id
13184
+ )) })
13185
+ ]
13186
+ }
13187
+ )
12101
13188
  ] }),
12102
13189
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "toolbar-group toolbar-environments", role: "group", "aria-label": messages.environments, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
12103
13190
  "div",
@@ -12425,7 +13512,7 @@ ${arabic || currentMessages.empty}`;
12425
13512
  "aria-label": atomicCommandTitle(command, uiLocale),
12426
13513
  onMouseDown: (event) => event.preventDefault(),
12427
13514
  onClick: () => {
12428
- runtimeRef.current?.insertAtomicCommand(command.id);
13515
+ runtimeRef.current?.insertLimitsSeriesTemplate(command.id);
12429
13516
  setLimitsSeriesMenuOpen(false);
12430
13517
  focusSurface();
12431
13518
  },