@drghaliasri/butex 5.3.1 → 5.3.3

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.
@@ -303,6 +303,10 @@ function cloneDocument2Meta(meta) {
303
303
  }
304
304
 
305
305
  // src/document2/citations.ts
306
+ var DEFAULT_REFERENCE_FIELD_SEPARATOR = "\u060C";
307
+ function normalizeReferenceFieldSeparator(value) {
308
+ return value === "," ? "," : DEFAULT_REFERENCE_FIELD_SEPARATOR;
309
+ }
306
310
  function referenceNumberMap(references) {
307
311
  const map = /* @__PURE__ */ new Map();
308
312
  references.forEach((reference, index) => {
@@ -348,7 +352,8 @@ function referenceFromJson(json) {
348
352
  title: typeof json.title === "string" ? json.title : "",
349
353
  year: typeof json.year === "string" ? json.year : "",
350
354
  url: typeof json.url === "string" ? json.url : "",
351
- venue: typeof json.venue === "string" ? json.venue : ""
355
+ venue: typeof json.venue === "string" ? json.venue : "",
356
+ fieldSeparator: normalizeReferenceFieldSeparator(json.field_separator)
352
357
  };
353
358
  }
354
359
  function createEmptyReference2(partial = {}) {
@@ -358,15 +363,33 @@ function createEmptyReference2(partial = {}) {
358
363
  title: partial.title,
359
364
  year: partial.year,
360
365
  url: partial.url,
361
- venue: partial.venue
366
+ venue: partial.venue,
367
+ field_separator: partial.field_separator
362
368
  });
363
369
  }
370
+ function bibliographyEntryBody(reference, separator = reference.fieldSeparator, options = {}) {
371
+ const year = options.digitForm !== void 0 ? formatDigits(reference.year, options.digitForm) : reference.year;
372
+ const parts = [reference.authors, reference.title, reference.venue, year].filter((part) => part.trim().length > 0);
373
+ return parts.join(`${separator} `);
374
+ }
364
375
  function bibliographyEntryLatex(reference) {
365
- const parts = [reference.authors, reference.title, reference.venue, reference.year].filter((part) => part.trim().length > 0);
366
- const body = parts.join(", ");
376
+ const body = bibliographyEntryBody(reference);
367
377
  const url = reference.url.trim().length > 0 ? ` \\url{${reference.url}}` : "";
368
378
  return `\\bibitem{${reference.key}} ${body}${url}`.trim();
369
379
  }
380
+ function absoluteHttpHref(url) {
381
+ const trimmed = url.trim();
382
+ if (trimmed.length === 0) {
383
+ return "";
384
+ }
385
+ if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(trimmed)) {
386
+ return trimmed;
387
+ }
388
+ if (trimmed.startsWith("//")) {
389
+ return `https:${trimmed}`;
390
+ }
391
+ return `https://${trimmed}`;
392
+ }
370
393
 
371
394
  // src/ast/commands/index.ts
372
395
  function renderCommandCore(context) {
@@ -851,6 +874,23 @@ function labelNumberMap(document2) {
851
874
  }
852
875
  return map;
853
876
  }
877
+ function formatFloatCaptionTitle(kind, number, options = {}) {
878
+ const locale = options.uiLocale ?? "ar";
879
+ const kindWord = kind === "fig" ? locale === "ar" ? "\u0627\u0644\u0634\u0643\u0644" : "Figure" : kind === "tab" ? locale === "ar" ? "\u0627\u0644\u062C\u062F\u0648\u0644" : "Table" : locale === "ar" ? "\u0627\u0644\u0645\u0639\u0627\u062F\u0644\u0629" : "Equation";
880
+ const digits = formatBibliographyNumber(number, {
881
+ documentDirection: options.documentDirection ?? (locale === "ar" ? "rtl" : "ltr"),
882
+ digitForm: options.digitForm ?? (locale === "ar" ? "arabicIndic" : "western")
883
+ });
884
+ return `${kindWord} ${digits}`;
885
+ }
886
+ function formatFloatCaptionPreview(title, caption, uiLocale = "ar") {
887
+ const trimmed = caption?.trim() ?? "";
888
+ if (trimmed.length === 0) {
889
+ return title;
890
+ }
891
+ const separator = uiLocale === "ar" ? ": " : ". ";
892
+ return `${title}${separator}${trimmed}`;
893
+ }
854
894
  function formatRefLabel(keys, document2, refCommand, options = {}) {
855
895
  const documentDirection = options.documentDirection ?? "rtl";
856
896
  const digitForm = options.digitForm ?? (documentDirection === "rtl" ? "arabicIndic" : "western");
@@ -1121,7 +1161,8 @@ function parseReferences(json) {
1121
1161
  title: typeof entry.title === "string" ? entry.title : void 0,
1122
1162
  year: typeof entry.year === "string" ? entry.year : void 0,
1123
1163
  url: typeof entry.url === "string" ? entry.url : void 0,
1124
- venue: typeof entry.venue === "string" ? entry.venue : void 0
1164
+ venue: typeof entry.venue === "string" ? entry.venue : void 0,
1165
+ field_separator: entry.field_separator === "," || entry.field_separator === "\u060C" ? entry.field_separator : void 0
1125
1166
  })
1126
1167
  );
1127
1168
  }
@@ -1767,7 +1808,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1767
1808
  id: "neq",
1768
1809
  category: "operators1",
1769
1810
  Tex: "\\neq",
1770
- mirror: false,
1811
+ mirror: true,
1771
1812
  Label: "\u2260",
1772
1813
  title: "\u0644\u0627 \u064A\u0633\u0627\u0648\u064A",
1773
1814
  svg_path: null
@@ -1777,6 +1818,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1777
1818
  category: "operators1",
1778
1819
  Tex: "\\approx",
1779
1820
  mirror: false,
1821
+ displayMirror: true,
1780
1822
  Label: "\u2248",
1781
1823
  title: "\u062A\u0642\u0631\u064A\u0628\u0627 \u064A\u0633\u0627\u0648\u064A",
1782
1824
  svg_path: null
@@ -1786,6 +1828,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1786
1828
  category: "operators1",
1787
1829
  Tex: "\\sim",
1788
1830
  mirror: false,
1831
+ displayMirror: true,
1789
1832
  Label: "\u223C",
1790
1833
  title: "\u0645\u0634\u0627\u0628\u0647",
1791
1834
  svg_path: null
@@ -1804,6 +1847,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1804
1847
  category: "operators1",
1805
1848
  Tex: "\\leq",
1806
1849
  mirror: true,
1850
+ displayMirror: false,
1807
1851
  Label: "\u2264",
1808
1852
  title: "\u0623\u0635\u063A\u0631 \u0645\u0646 \u0623\u0648 \u064A\u0633\u0627\u0648\u064A",
1809
1853
  svg_path: null
@@ -1813,6 +1857,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1813
1857
  category: "operators1",
1814
1858
  Tex: "\\geq",
1815
1859
  mirror: true,
1860
+ displayMirror: false,
1816
1861
  Label: "\u2265",
1817
1862
  title: "\u0623\u0643\u0628\u0631 \u0645\u0646 \u0623\u0648 \u064A\u0633\u0627\u0648\u064A",
1818
1863
  svg_path: null
@@ -1822,6 +1867,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1822
1867
  category: "operators1",
1823
1868
  Tex: "\\coloneqq",
1824
1869
  mirror: true,
1870
+ displayMirror: false,
1825
1871
  Label: "\u2254",
1826
1872
  title: "\u064A\u0639\u0631\u0641 \u0628\u0623\u0646\u0647 \u064A\u0633\u0627\u0648\u064A",
1827
1873
  svg_path: null
@@ -1831,6 +1877,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1831
1877
  category: "operators1",
1832
1878
  Tex: "\\eqqcolon",
1833
1879
  mirror: true,
1880
+ displayMirror: false,
1834
1881
  Label: "\u2255",
1835
1882
  title: "\u064A\u0633\u0627\u0648\u064A \u0628\u0627\u0644\u062A\u0639\u0631\u064A\u0641",
1836
1883
  svg_path: null
@@ -1841,6 +1888,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1841
1888
  category: "operators2",
1842
1889
  Tex: "\\propto",
1843
1890
  mirror: true,
1891
+ displayMirror: false,
1844
1892
  Label: "\u221D",
1845
1893
  title: "\u064A\u062A\u0646\u0627\u0633\u0628 \u0645\u0639",
1846
1894
  svg_path: null
@@ -1850,6 +1898,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1850
1898
  category: "operators2",
1851
1899
  Tex: "\\in",
1852
1900
  mirror: true,
1901
+ displayMirror: false,
1853
1902
  Label: "\u2208",
1854
1903
  title: "\u064A\u0646\u062A\u0645\u064A \u0625\u0644\u0649",
1855
1904
  svg_path: null
@@ -1859,6 +1908,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1859
1908
  category: "operators2",
1860
1909
  Tex: "\\notin",
1861
1910
  mirror: false,
1911
+ displayMirror: true,
1862
1912
  Label: "\u2209",
1863
1913
  title: "\u0644\u0627 \u064A\u0646\u062A\u0645\u064A \u0625\u0644\u0649",
1864
1914
  svg_path: null
@@ -1868,6 +1918,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1868
1918
  category: "operators2",
1869
1919
  Tex: "\\subset",
1870
1920
  mirror: true,
1921
+ displayMirror: false,
1871
1922
  Label: "\u2282",
1872
1923
  title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u062C\u0632\u0626\u064A\u0629 \u0645\u0646",
1873
1924
  svg_path: null
@@ -1877,6 +1928,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1877
1928
  category: "operators2",
1878
1929
  Tex: "\\supset",
1879
1930
  mirror: true,
1931
+ displayMirror: false,
1880
1932
  Label: "\u2283",
1881
1933
  title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u0634\u0627\u0645\u0644\u0629 \u0644\u0640",
1882
1934
  svg_path: null
@@ -1886,6 +1938,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1886
1938
  category: "operators2",
1887
1939
  Tex: "\\subseteq",
1888
1940
  mirror: true,
1941
+ displayMirror: false,
1889
1942
  Label: "\u2286",
1890
1943
  title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u062C\u0632\u0626\u064A\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
1891
1944
  svg_path: null
@@ -1895,6 +1948,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1895
1948
  category: "operators2",
1896
1949
  Tex: "\\supseteq",
1897
1950
  mirror: true,
1951
+ displayMirror: false,
1898
1952
  Label: "\u2287",
1899
1953
  title: "\u0645\u062C\u0645\u0648\u0639\u0629 \u0634\u0627\u0645\u0644\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
1900
1954
  svg_path: null
@@ -1904,6 +1958,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1904
1958
  category: "operators2",
1905
1959
  Tex: "\\cap",
1906
1960
  mirror: false,
1961
+ displayMirror: true,
1907
1962
  Label: "\u2229",
1908
1963
  title: "\u062A\u0642\u0627\u0637\u0639",
1909
1964
  svg_path: null
@@ -1913,6 +1968,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1913
1968
  category: "operators2",
1914
1969
  Tex: "\\cup",
1915
1970
  mirror: false,
1971
+ displayMirror: true,
1916
1972
  Label: "\u222A",
1917
1973
  title: "\u0627\u062A\u062D\u0627\u062F",
1918
1974
  svg_path: null
@@ -1922,6 +1978,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1922
1978
  category: "operators2",
1923
1979
  Tex: "\\emptyset",
1924
1980
  mirror: false,
1981
+ displayMirror: true,
1925
1982
  Label: "\u2205",
1926
1983
  title: "\u0627\u0644\u0645\u062C\u0645\u0648\u0639\u0629 \u0627\u0644\u062E\u0627\u0644\u064A\u0629",
1927
1984
  svg_path: null
@@ -1931,6 +1988,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1931
1988
  category: "operators2",
1932
1989
  Tex: "\\nsubseteq",
1933
1990
  mirror: true,
1991
+ displayMirror: false,
1934
1992
  Label: "\u2288",
1935
1993
  title: "\u0644\u064A\u0633\u062A \u0645\u062C\u0645\u0648\u0639\u0629 \u062C\u0632\u0626\u064A\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
1936
1994
  svg_path: null
@@ -1940,6 +1998,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
1940
1998
  category: "operators2",
1941
1999
  Tex: "\\nsupseteq",
1942
2000
  mirror: true,
2001
+ displayMirror: false,
1943
2002
  Label: "\u2289",
1944
2003
  title: "\u0644\u064A\u0633\u062A \u0645\u062C\u0645\u0648\u0639\u0629 \u0634\u0627\u0645\u0644\u0629 \u0623\u0648 \u062A\u0633\u0627\u0648\u064A",
1945
2004
  svg_path: null
@@ -2151,6 +2210,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2151
2210
  category: "integrals",
2152
2211
  Tex: "\\iint",
2153
2212
  mirror: true,
2213
+ displayMirror: false,
2154
2214
  Label: "\u222C",
2155
2215
  title: "\u062A\u0643\u0627\u0645\u0644 \u0645\u0632\u062F\u0648\u062C",
2156
2216
  svg_path: null
@@ -2160,6 +2220,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2160
2220
  category: "integrals",
2161
2221
  Tex: "\\iiint",
2162
2222
  mirror: true,
2223
+ displayMirror: false,
2163
2224
  Label: "\u222D",
2164
2225
  title: "\u062A\u0643\u0627\u0645\u0644 \u062B\u0644\u0627\u062B\u064A",
2165
2226
  svg_path: null
@@ -2169,6 +2230,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2169
2230
  category: "integrals",
2170
2231
  Tex: "\\iiiint",
2171
2232
  mirror: true,
2233
+ displayMirror: false,
2172
2234
  Label: "\u2A0C",
2173
2235
  title: "\u062A\u0643\u0627\u0645\u0644 \u0631\u0628\u0627\u0639\u064A",
2174
2236
  svg_path: null
@@ -2178,6 +2240,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2178
2240
  category: "integrals",
2179
2241
  Tex: "\\oint",
2180
2242
  mirror: true,
2243
+ displayMirror: false,
2181
2244
  Label: "\u222E",
2182
2245
  title: "\u062A\u0643\u0627\u0645\u0644 \u0645\u063A\u0644\u0642",
2183
2246
  svg_path: null
@@ -2187,6 +2250,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2187
2250
  category: "integrals",
2188
2251
  Tex: "\\oiint",
2189
2252
  mirror: true,
2253
+ displayMirror: false,
2190
2254
  Label: "\u222F",
2191
2255
  title: "\u062A\u0643\u0627\u0645\u0644 \u0633\u0637\u062D\u064A \u0645\u063A\u0644\u0642",
2192
2256
  svg_path: null
@@ -2196,6 +2260,7 @@ var ATOMIC_OPERATOR_COMMANDS = {
2196
2260
  category: "integrals",
2197
2261
  Tex: "\\oiiint",
2198
2262
  mirror: true,
2263
+ displayMirror: false,
2199
2264
  Label: "\u2230",
2200
2265
  title: "\u062A\u0643\u0627\u0645\u0644 \u062D\u062C\u0645\u064A \u0645\u063A\u0644\u0642",
2201
2266
  svg_path: null
@@ -7553,6 +7618,9 @@ function updateDocument2Reference(document2, referenceId, patch) {
7553
7618
  if (typeof patch.venue === "string") {
7554
7619
  reference.venue = patch.venue;
7555
7620
  }
7621
+ if (patch.field_separator === "," || patch.field_separator === "\u060C") {
7622
+ reference.fieldSeparator = patch.field_separator;
7623
+ }
7556
7624
  return next;
7557
7625
  }
7558
7626
  function removeDocument2Reference(document2, referenceId) {
@@ -7586,6 +7654,48 @@ function updateDocument2Meta(document2, patch) {
7586
7654
  return next;
7587
7655
  }
7588
7656
 
7657
+ // src/document2/keys.ts
7658
+ var DOCUMENT2_KEY_PATTERN = /^[\p{L}\p{M}0-9:._-]+$/u;
7659
+ function normalizeDocument2Key(key) {
7660
+ return key.normalize("NFC").trim();
7661
+ }
7662
+ function isDuplicateDocument2Key(key, namespace) {
7663
+ const normalized = normalizeDocument2Key(key);
7664
+ if (normalized.length === 0) {
7665
+ return false;
7666
+ }
7667
+ for (const reference of namespace.references ?? []) {
7668
+ if (namespace.excludeReferenceId && reference.id === namespace.excludeReferenceId) {
7669
+ continue;
7670
+ }
7671
+ if (normalizeDocument2Key(reference.key) === normalized) {
7672
+ return true;
7673
+ }
7674
+ }
7675
+ for (const label of namespace.labels ?? []) {
7676
+ if (namespace.excludeOwnerId && label.ownerId === namespace.excludeOwnerId) {
7677
+ continue;
7678
+ }
7679
+ if (normalizeDocument2Key(label.key) === normalized) {
7680
+ return true;
7681
+ }
7682
+ }
7683
+ return false;
7684
+ }
7685
+ function document2KeyError(key, namespace = {}) {
7686
+ const normalized = normalizeDocument2Key(key);
7687
+ if (normalized.length === 0) {
7688
+ return "empty";
7689
+ }
7690
+ if (!DOCUMENT2_KEY_PATTERN.test(normalized)) {
7691
+ return "invalid";
7692
+ }
7693
+ if (isDuplicateDocument2Key(normalized, namespace)) {
7694
+ return "duplicate";
7695
+ }
7696
+ return null;
7697
+ }
7698
+
7589
7699
  // src/document2/arabicPreamble.ts
7590
7700
  function arabicXeLatexPreamblePkg(twocolumn = false) {
7591
7701
  const classOptions = twocolumn ? "12pt,a4paper,notitlepage,twocolumn" : "12pt,a4paper,notitlepage";
@@ -8136,13 +8246,11 @@ function floatNumberLabel(document2, key, previewOptions) {
8136
8246
  if (!hit || hit.kind !== "fig" && hit.kind !== "tab") {
8137
8247
  return void 0;
8138
8248
  }
8139
- const locale = previewOptions.uiLocale ?? "ar";
8140
- const kindWord = hit.kind === "fig" ? locale === "ar" ? "\u0627\u0644\u0634\u0643\u0644" : "Figure" : locale === "ar" ? "\u0627\u0644\u062C\u062F\u0648\u0644" : "Table";
8141
- const digits = formatBibliographyNumber(hit.number, {
8249
+ return formatFloatCaptionTitle(hit.kind, hit.number, {
8250
+ uiLocale: previewOptions.uiLocale ?? "ar",
8142
8251
  documentDirection: previewOptions.documentDirection,
8143
8252
  digitForm: previewOptions.digitForm
8144
8253
  });
8145
- return `${kindWord} ${digits}`;
8146
8254
  }
8147
8255
  function blockPreview(block, islands, output, equationSide, document2, previewOptions) {
8148
8256
  if (block.kind === "textBlock") {
@@ -8197,7 +8305,8 @@ function blockPreview(block, islands, output, equationSide, document2, previewOp
8197
8305
  title: reference.title,
8198
8306
  year: reference.year,
8199
8307
  url: reference.url,
8200
- venue: reference.venue
8308
+ venue: reference.venue,
8309
+ fieldSeparator: reference.fieldSeparator
8201
8310
  }))
8202
8311
  };
8203
8312
  }
@@ -8348,6 +8457,15 @@ var DOCUMENT2_MESSAGES = {
8348
8457
  labelKindFig: "\u0634\u0643\u0644",
8349
8458
  labelKindTab: "\u062C\u062F\u0648\u0644",
8350
8459
  labelKindEq: "\u0645\u0639\u0627\u062F\u0644\u0629",
8460
+ captionPreview: "\u0645\u0639\u0627\u064A\u0646\u0629 \u0627\u0644\u062A\u0639\u0644\u064A\u0642",
8461
+ referencePreview: "\u0645\u0639\u0627\u064A\u0646\u0629 \u0627\u0644\u0645\u0631\u062C\u0639",
8462
+ referenceFieldSeparator: "\u0641\u0627\u0635\u0644 \u0627\u0644\u062D\u0642\u0648\u0644",
8463
+ referenceCommaLtr: "\u0641\u0627\u0635\u0644\u0629 \u0625\u0646\u062C\u0644\u064A\u0632\u064A\u0629 ,",
8464
+ referenceCommaRtl: "\u0641\u0627\u0635\u0644\u0629 \u0639\u0631\u0628\u064A\u0629 \u060C",
8465
+ keyEmpty: "\u0627\u0644\u0645\u0641\u062A\u0627\u062D \u0645\u0637\u0644\u0648\u0628",
8466
+ keyInvalid: "\u0627\u0644\u0645\u0641\u062A\u0627\u062D \u063A\u064A\u0631 \u0635\u0627\u0644\u062D: \u0628\u062F\u0648\u0646 \u0645\u0633\u0627\u0641\u0627\u062A\u060C \u0648\u064A\u064F\u0633\u0645\u062D \u0628\u0627\u0644\u062D\u0631\u0648\u0641 \u0648\u0627\u0644\u0623\u0631\u0642\u0627\u0645 \u0648`:._-` \u0641\u0642\u0637",
8467
+ keyDuplicate: "\u0647\u0630\u0627 \u0627\u0644\u0645\u0641\u062A\u0627\u062D \u0645\u0633\u062A\u062E\u062F\u0645 \u0645\u0633\u0628\u0642\u0627\u064B",
8468
+ keyRulesHint: "\u062D\u0631\u0648\u0641 (\u0639\u0631\u0628\u064A\u0629 \u0623\u0648 \u0644\u0627\u062A\u064A\u0646\u064A\u0629) \u0648\u0623\u0631\u0642\u0627\u0645 \u0648`:._-` \u0628\u062F\u0648\u0646 \u0645\u0633\u0627\u0641\u0627\u062A",
8351
8469
  citePickerTitle: "\u0627\u062E\u062A\u064A\u0627\u0631 \u0627\u0644\u0645\u0631\u0627\u062C\u0639",
8352
8470
  noReferencesYet: "\u0644\u0627 \u062A\u0648\u062C\u062F \u0645\u0631\u0627\u062C\u0639 \u0628\u0639\u062F. \u0623\u0636\u0641 \u0645\u0631\u062C\u0639\u0627\u064B \u0623\u0648\u0644\u0627\u064B.",
8353
8471
  editCitation: "\u062A\u062D\u0631\u064A\u0631 \u0627\u0644\u0627\u0642\u062A\u0628\u0627\u0633",
@@ -8478,6 +8596,15 @@ var DOCUMENT2_MESSAGES = {
8478
8596
  labelKindFig: "Figure",
8479
8597
  labelKindTab: "Table",
8480
8598
  labelKindEq: "Equation",
8599
+ captionPreview: "Caption preview",
8600
+ referencePreview: "Reference preview",
8601
+ referenceFieldSeparator: "Field separator",
8602
+ referenceCommaLtr: "Latin comma ,",
8603
+ referenceCommaRtl: "Arabic comma \u060C",
8604
+ keyEmpty: "Key is required",
8605
+ keyInvalid: "Invalid key: letters, digits, and `:._-` only; no spaces",
8606
+ keyDuplicate: "This key is already in use",
8607
+ keyRulesHint: "Letters (Arabic or Latin), digits, and `:._-`; no spaces",
8481
8608
  citePickerTitle: "Select references",
8482
8609
  noReferencesYet: "No references yet. Add a reference first.",
8483
8610
  editCitation: "Edit citation",
@@ -8715,7 +8842,10 @@ function focusArticleMetaPanel(panel) {
8715
8842
  }
8716
8843
 
8717
8844
  // src/react-document2/ButexDocumentEditor2.tsx
8718
- var import_react11 = require("react");
8845
+ var import_react13 = require("react");
8846
+
8847
+ // src/react-document2/BlockEditor.tsx
8848
+ var import_react4 = require("react");
8719
8849
 
8720
8850
  // src/react-document2/InlineField.tsx
8721
8851
  var import_react3 = require("react");
@@ -8796,7 +8926,10 @@ var import_react2 = require("react");
8796
8926
  // src/mathjax/svgPatcher.ts
8797
8927
  var SVG_ARABSQRT_SELECTOR = 'mjx-container[jax="SVG"] svg .mjx-rtl-mirror[data-mjx-rtl-root="true"]';
8798
8928
  var ARABSQRT_SELECTOR = '.mjx-rtl-mirror[data-mjx-rtl-root="true"]';
8929
+ var SVG_PREVIEW_MIRROR_SELECTOR = 'mjx-container[jax="SVG"] svg .butex-preview-mirror';
8930
+ var PREVIEW_MIRROR_SELECTOR = ".butex-preview-mirror";
8799
8931
  var PATCHED_ATTR = "data-butex-svg-arabsqrt";
8932
+ var MIRROR_PATCHED_ATTR = "data-butex-svg-mirror";
8800
8933
  var ROOT_INDEX_SCALE = 0.72;
8801
8934
  var ROOT_INDEX_GAP_FACTOR = 0.08;
8802
8935
  var ROOT_INDEX_MIN_GAP = 2;
@@ -8821,11 +8954,12 @@ function directSvgElementChildren(element) {
8821
8954
  return Array.from(element.children).filter((child) => child instanceof SVGElement);
8822
8955
  }
8823
8956
  function boxFor(element) {
8824
- if (!(element instanceof SVGGraphicsElement) || typeof element.getBBox !== "function") {
8957
+ const candidate = element;
8958
+ if (typeof candidate.getBBox !== "function") {
8825
8959
  return null;
8826
8960
  }
8827
8961
  try {
8828
- const box = element.getBBox();
8962
+ const box = candidate.getBBox();
8829
8963
  return {
8830
8964
  x: box.x,
8831
8965
  y: box.y,
@@ -9069,6 +9203,31 @@ function patchArabSqrtRoot(root) {
9069
9203
  root.setAttribute(PATCHED_ATTR, "patched");
9070
9204
  rootNode.setAttribute(PATCHED_ATTR, "patched");
9071
9205
  }
9206
+ function patchPreviewMirror(element) {
9207
+ if (element.getAttribute(MIRROR_PATCHED_ATTR) === "patched") {
9208
+ return;
9209
+ }
9210
+ const box = boxFor(element);
9211
+ if (!box || box.width <= 0) {
9212
+ return;
9213
+ }
9214
+ const [tx, ty] = readTranslate(element);
9215
+ const mirrorX = tx + 2 * box.x + box.width;
9216
+ element.setAttribute(
9217
+ "transform",
9218
+ `translate(${roundSvg(mirrorX)},${roundSvg(ty)}) scale(-1,1)`
9219
+ );
9220
+ element.setAttribute(MIRROR_PATCHED_ATTR, "patched");
9221
+ }
9222
+ function collectPreviewMirrors(root) {
9223
+ let mirrors = Array.from(root.querySelectorAll(SVG_PREVIEW_MIRROR_SELECTOR));
9224
+ if (!mirrors.length) {
9225
+ mirrors = Array.from(root.querySelectorAll(PREVIEW_MIRROR_SELECTOR)).filter((candidate) => {
9226
+ return candidate.closest('mjx-container[jax="SVG"]') != null;
9227
+ });
9228
+ }
9229
+ return mirrors;
9230
+ }
9072
9231
  function patchBuTeXSvgMath(root) {
9073
9232
  if (typeof root.querySelectorAll !== "function") {
9074
9233
  return;
@@ -9080,6 +9239,7 @@ function patchBuTeXSvgMath(root) {
9080
9239
  });
9081
9240
  }
9082
9241
  roots.sort((a, b) => rootDepth(b) - rootDepth(a)).forEach((arabSqrtRoot) => patchArabSqrtRoot(arabSqrtRoot));
9242
+ collectPreviewMirrors(root).forEach((mirror) => patchPreviewMirror(mirror));
9083
9243
  }
9084
9244
 
9085
9245
  // src/mathjax/renderIsland.ts
@@ -9752,6 +9912,18 @@ function inlineFieldSummary(field) {
9752
9912
  }).join("")
9753
9913
  );
9754
9914
  }
9915
+ function keyErrorMessage(error, messages) {
9916
+ if (error === "empty") {
9917
+ return messages.keyEmpty;
9918
+ }
9919
+ if (error === "invalid") {
9920
+ return messages.keyInvalid;
9921
+ }
9922
+ if (error === "duplicate") {
9923
+ return messages.keyDuplicate;
9924
+ }
9925
+ return null;
9926
+ }
9755
9927
  function FloatMetaEditor({
9756
9928
  captionEnabled,
9757
9929
  caption,
@@ -9760,8 +9932,18 @@ function FloatMetaEditor({
9760
9932
  labelPlaceholder,
9761
9933
  labelDir,
9762
9934
  messages,
9935
+ ownerId,
9936
+ references,
9937
+ labels,
9763
9938
  onChange
9764
9939
  }) {
9940
+ const [labelOverride, setLabelOverride] = (0, import_react4.useState)(null);
9941
+ const displayedLabel = labelOverride ?? label;
9942
+ const labelError = labelEnabled ? document2KeyError(displayedLabel, {
9943
+ references,
9944
+ labels,
9945
+ excludeOwnerId: ownerId
9946
+ }) : null;
9765
9947
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "butex-document2-widget__float-meta", children: [
9766
9948
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "butex-document2-widget__float-meta-toggle", children: [
9767
9949
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
@@ -9811,15 +9993,27 @@ function FloatMetaEditor({
9811
9993
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
9812
9994
  "input",
9813
9995
  {
9814
- value: label,
9996
+ value: displayedLabel,
9815
9997
  dir: labelDir,
9816
9998
  placeholder: labelPlaceholder,
9999
+ "aria-invalid": labelError !== null ? true : void 0,
9817
10000
  onChange: (event) => {
9818
10001
  const value = event.currentTarget.value;
10002
+ setLabelOverride(value);
10003
+ const error = document2KeyError(value, {
10004
+ references,
10005
+ labels,
10006
+ excludeOwnerId: ownerId
10007
+ });
10008
+ if (error !== null) {
10009
+ return;
10010
+ }
9819
10011
  onChange({ label: value });
10012
+ setLabelOverride(null);
9820
10013
  }
9821
10014
  }
9822
- )
10015
+ ),
10016
+ labelError !== null ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "butex-document2-widget__field-error", children: labelError === "invalid" ? messages.keyRulesHint : keyErrorMessage(labelError, messages) }) : null
9823
10017
  ] }) : null
9824
10018
  ] });
9825
10019
  }
@@ -9878,6 +10072,8 @@ function BlockEditor({
9878
10072
  onManageReferences
9879
10073
  }) {
9880
10074
  const messages = document2Messages(uiLocale);
10075
+ const labels = documentNode ? collectDocument2Labels(documentNode) : [];
10076
+ const referenceList = references ?? [];
9881
10077
  const showChrome = depth === 0;
9882
10078
  const chromeClass = [
9883
10079
  blockChromeClass(block),
@@ -10040,6 +10236,9 @@ function BlockEditor({
10040
10236
  labelPlaceholder: messages.tableLabelPlaceholder,
10041
10237
  labelDir: uiLocaleDirection(uiLocale),
10042
10238
  messages,
10239
+ ownerId: block.id,
10240
+ references: referenceList,
10241
+ labels,
10043
10242
  onChange: (patch) => onFloatMetaChange?.(block.id, "table", patch)
10044
10243
  }
10045
10244
  )
@@ -10083,6 +10282,9 @@ function BlockEditor({
10083
10282
  labelPlaceholder: messages.figureLabelPlaceholder,
10084
10283
  labelDir: uiLocaleDirection(uiLocale),
10085
10284
  messages,
10285
+ ownerId: block.id,
10286
+ references: referenceList,
10287
+ labels,
10086
10288
  onChange: (patch) => onFloatMetaChange?.(block.id, "image", patch)
10087
10289
  }
10088
10290
  )
@@ -10091,14 +10293,16 @@ function BlockEditor({
10091
10293
  if (block.kind === "bibliography") {
10092
10294
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("section", { className: chromeClass, children: [
10093
10295
  header,
10094
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("ol", { className: "butex-document2-widget__bibliography-editor", dir: documentDirection, children: references.map((reference, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("li", { children: [
10296
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("ol", { className: "butex-document2-widget__bibliography-editor", dir: documentDirection, children: referenceList.map((reference, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("li", { children: [
10095
10297
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("strong", { children: [
10096
10298
  "[",
10097
- index + 1,
10299
+ formatBibliographyNumber(index + 1, { documentDirection, digitForm }),
10098
10300
  "] ",
10099
10301
  reference.key
10100
10302
  ] }),
10101
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: [reference.authors, reference.title, reference.venue, reference.year].filter(Boolean).join(" \u2014 ") })
10303
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: bibliographyEntryBody(reference, reference.fieldSeparator, {
10304
+ digitForm: digitForm ?? (documentDirection === "rtl" ? "arabicIndic" : "western")
10305
+ }) })
10102
10306
  ] }, reference.id)) }),
10103
10307
  onManageReferences ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", onClick: onManageReferences, children: messages.manageReferences }) : null
10104
10308
  ] });
@@ -10110,20 +10314,22 @@ function BlockEditor({
10110
10314
  }
10111
10315
 
10112
10316
  // src/react-document2/CitePickerPopover.tsx
10113
- var import_react4 = require("react");
10317
+ var import_react5 = require("react");
10114
10318
  var import_jsx_runtime8 = require("react/jsx-runtime");
10115
10319
  function CitePickerPopover({
10116
10320
  open,
10117
10321
  references,
10118
10322
  initialKeys = [],
10119
10323
  uiLocale = "ar",
10324
+ digitForm = "arabicIndic",
10120
10325
  onClose,
10121
10326
  onConfirm,
10122
10327
  onManageReferences
10123
10328
  }) {
10124
10329
  const messages = document2Messages(uiLocale);
10125
- const [selected, setSelected] = (0, import_react4.useState)(initialKeys);
10126
- (0, import_react4.useEffect)(() => {
10330
+ const documentDirection = uiLocale === "ar" ? "rtl" : "ltr";
10331
+ const [selected, setSelected] = (0, import_react5.useState)(initialKeys);
10332
+ (0, import_react5.useEffect)(() => {
10127
10333
  if (open) {
10128
10334
  setSelected(initialKeys);
10129
10335
  }
@@ -10149,12 +10355,13 @@ function CitePickerPopover({
10149
10355
  references.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "butex-document2-widget__cite-picker-empty", children: messages.noReferencesYet }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("ul", { className: "butex-document2-widget__cite-picker-list", children: references.map((reference, index) => {
10150
10356
  const checked = selected.includes(reference.key);
10151
10357
  const subtitle = [reference.authors, reference.title].filter(Boolean).join(" \u2014 ");
10358
+ const numberLabel = formatBibliographyNumber(index + 1, { documentDirection, digitForm });
10152
10359
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "butex-document2-widget__cite-picker-item", children: [
10153
10360
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("input", { type: "checkbox", checked, onChange: () => toggleKey(reference.key) }),
10154
10361
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { children: [
10155
10362
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("strong", { children: [
10156
10363
  "[",
10157
- index + 1,
10364
+ numberLabel,
10158
10365
  "] ",
10159
10366
  reference.key
10160
10367
  ] }),
@@ -10182,18 +10389,18 @@ function CitePickerPopover({
10182
10389
  }
10183
10390
 
10184
10391
  // src/react-document2/DocumentInsertToolbar.tsx
10185
- var import_react6 = require("react");
10392
+ var import_react7 = require("react");
10186
10393
 
10187
10394
  // src/react-document2/TableInsertPopover.tsx
10188
- var import_react5 = require("react");
10395
+ var import_react6 = require("react");
10189
10396
  var import_jsx_runtime9 = require("react/jsx-runtime");
10190
10397
  function TableInsertPopover({ uiLocale = "ar", onConfirm }) {
10191
10398
  const messages = document2Messages(uiLocale);
10192
- const [open, setOpen] = (0, import_react5.useState)(false);
10193
- const [rows, setRows] = (0, import_react5.useState)("3");
10194
- const [cols, setCols] = (0, import_react5.useState)("3");
10195
- const rootRef = (0, import_react5.useRef)(null);
10196
- (0, import_react5.useEffect)(() => {
10399
+ const [open, setOpen] = (0, import_react6.useState)(false);
10400
+ const [rows, setRows] = (0, import_react6.useState)("3");
10401
+ const [cols, setCols] = (0, import_react6.useState)("3");
10402
+ const rootRef = (0, import_react6.useRef)(null);
10403
+ (0, import_react6.useEffect)(() => {
10197
10404
  if (!open) {
10198
10405
  return;
10199
10406
  }
@@ -10284,7 +10491,7 @@ function DocumentInsertToolbar({
10284
10491
  onDigitFormChange
10285
10492
  }) {
10286
10493
  const messages = document2Messages(uiLocale);
10287
- const [digitMenuOpen, setDigitMenuOpen] = (0, import_react6.useState)(false);
10494
+ const [digitMenuOpen, setDigitMenuOpen] = (0, import_react7.useState)(false);
10288
10495
  function digitTitle(id) {
10289
10496
  if (id === "arabicIndic") {
10290
10497
  return messages.arabicIndicDigits;
@@ -10455,7 +10662,8 @@ function PreviewBlock({
10455
10662
  output,
10456
10663
  resolveImageUrl,
10457
10664
  uiLocale,
10458
- documentDirection
10665
+ documentDirection,
10666
+ digitForm
10459
10667
  }) {
10460
10668
  const messages = document2Messages(uiLocale);
10461
10669
  const floatCaptionSeparator = uiLocale === "ar" ? ": " : ". ";
@@ -10514,7 +10722,8 @@ function PreviewBlock({
10514
10722
  output,
10515
10723
  resolveImageUrl,
10516
10724
  uiLocale,
10517
- documentDirection
10725
+ documentDirection,
10726
+ digitForm
10518
10727
  },
10519
10728
  child.id
10520
10729
  ))
@@ -10544,10 +10753,10 @@ function PreviewBlock({
10544
10753
  ] }),
10545
10754
  " ",
10546
10755
  /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { children: [
10547
- [item.authors, item.title, item.venue, item.year].filter(Boolean).join(", "),
10756
+ bibliographyEntryBody(item, item.fieldSeparator, { digitForm }),
10548
10757
  item.url ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
10549
10758
  " ",
10550
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("a", { href: item.url, target: "_blank", rel: "noreferrer", children: item.url })
10759
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("a", { href: absoluteHttpHref(item.url), target: "_blank", rel: "noreferrer", children: item.url })
10551
10760
  ] }) : null
10552
10761
  ] })
10553
10762
  ] }, item.id)) });
@@ -10559,9 +10768,11 @@ function DocumentPreview({
10559
10768
  output,
10560
10769
  documentDirection = "rtl",
10561
10770
  uiLocale = "ar",
10771
+ digitForm,
10562
10772
  resolveImageUrl
10563
10773
  }) {
10564
10774
  const messages = document2Messages(uiLocale);
10775
+ const resolvedDigitForm = digitForm ?? (documentDirection === "rtl" ? "arabicIndic" : "western");
10565
10776
  const hasBody = blocks.some(isBodyPreviewBlock);
10566
10777
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "butex-document2-widget__preview", dir: documentDirection, children: [
10567
10778
  blocks.map((block) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
@@ -10571,7 +10782,8 @@ function DocumentPreview({
10571
10782
  output,
10572
10783
  resolveImageUrl,
10573
10784
  uiLocale,
10574
- documentDirection
10785
+ documentDirection,
10786
+ digitForm: resolvedDigitForm
10575
10787
  },
10576
10788
  block.id
10577
10789
  )),
@@ -10580,10 +10792,10 @@ function DocumentPreview({
10580
10792
  }
10581
10793
 
10582
10794
  // src/react-document2/EquationDrawer.tsx
10583
- var import_react8 = require("react");
10795
+ var import_react9 = require("react");
10584
10796
 
10585
10797
  // src/react/ButexEditor.tsx
10586
- var import_react7 = require("react");
10798
+ var import_react8 = require("react");
10587
10799
 
10588
10800
  // src/react/widgetChromeCss.ts
10589
10801
  var WIDGET_CHROME_CSS = `
@@ -11629,61 +11841,61 @@ function passiveTreeText(session, messages) {
11629
11841
 
11630
11842
  ${latex || messages.empty}`;
11631
11843
  }
11632
- var ButexEditor = (0, import_react7.forwardRef)(
11844
+ var ButexEditor = (0, import_react8.forwardRef)(
11633
11845
  function ButexEditor2({ className, debug = false, defaultSide, uiLocale = "ar", initialSession, onSessionChange }, ref) {
11634
11846
  const messages = equationEditorMessages(uiLocale);
11635
- const wrapperRef = (0, import_react7.useRef)(null);
11636
- const surfaceRef = (0, import_react7.useRef)(null);
11637
- const mathOutputRef = (0, import_react7.useRef)(null);
11638
- const renderErrorRef = (0, import_react7.useRef)(null);
11639
- const latexLinesRef = (0, import_react7.useRef)(null);
11640
- const passivePreviewRef = (0, import_react7.useRef)(null);
11641
- const debugLogRef = (0, import_react7.useRef)(null);
11642
- const undoBtnRef = (0, import_react7.useRef)(null);
11643
- const redoBtnRef = (0, import_react7.useRef)(null);
11644
- const copyBtnRef = (0, import_react7.useRef)(null);
11645
- const cutBtnRef = (0, import_react7.useRef)(null);
11646
- const splitTypingBtnRef = (0, import_react7.useRef)(null);
11647
- const characterFontBtnRef = (0, import_react7.useRef)(null);
11648
- const digitFormBtnRef = (0, import_react7.useRef)(null);
11649
- const runtimeRef = (0, import_react7.useRef)(null);
11650
- const debugRef = (0, import_react7.useRef)(debug);
11847
+ const wrapperRef = (0, import_react8.useRef)(null);
11848
+ const surfaceRef = (0, import_react8.useRef)(null);
11849
+ const mathOutputRef = (0, import_react8.useRef)(null);
11850
+ const renderErrorRef = (0, import_react8.useRef)(null);
11851
+ const latexLinesRef = (0, import_react8.useRef)(null);
11852
+ const passivePreviewRef = (0, import_react8.useRef)(null);
11853
+ const debugLogRef = (0, import_react8.useRef)(null);
11854
+ const undoBtnRef = (0, import_react8.useRef)(null);
11855
+ const redoBtnRef = (0, import_react8.useRef)(null);
11856
+ const copyBtnRef = (0, import_react8.useRef)(null);
11857
+ const cutBtnRef = (0, import_react8.useRef)(null);
11858
+ const splitTypingBtnRef = (0, import_react8.useRef)(null);
11859
+ const characterFontBtnRef = (0, import_react8.useRef)(null);
11860
+ const digitFormBtnRef = (0, import_react8.useRef)(null);
11861
+ const runtimeRef = (0, import_react8.useRef)(null);
11862
+ const debugRef = (0, import_react8.useRef)(debug);
11651
11863
  debugRef.current = debug;
11652
- const uiLocaleRef = (0, import_react7.useRef)(uiLocale);
11864
+ const uiLocaleRef = (0, import_react8.useRef)(uiLocale);
11653
11865
  uiLocaleRef.current = uiLocale;
11654
- const onSessionChangeRef = (0, import_react7.useRef)(onSessionChange);
11866
+ const onSessionChangeRef = (0, import_react8.useRef)(onSessionChange);
11655
11867
  onSessionChangeRef.current = onSessionChange;
11656
- const debugBodyHiddenRef = (0, import_react7.useRef)(false);
11657
- const [debugBodyHidden, setDebugBodyHidden] = (0, import_react7.useState)(false);
11868
+ const debugBodyHiddenRef = (0, import_react8.useRef)(false);
11869
+ const [debugBodyHidden, setDebugBodyHidden] = (0, import_react8.useState)(false);
11658
11870
  debugBodyHiddenRef.current = debugBodyHidden;
11659
- const [digitMenuOpen, setDigitMenuOpen] = (0, import_react7.useState)(false);
11660
- const [characterFontMenuOpen, setCharacterFontMenuOpen] = (0, import_react7.useState)(false);
11661
- const [delimiterMenuOpen, setDelimiterMenuOpen] = (0, import_react7.useState)(false);
11662
- const [matrixMenuOpen, setMatrixMenuOpen] = (0, import_react7.useState)(false);
11663
- const [spacingMenuOpen, setSpacingMenuOpen] = (0, import_react7.useState)(false);
11664
- const [functionMenuOpen, setFunctionMenuOpen] = (0, import_react7.useState)(false);
11665
- const [limitsSeriesMenuOpen, setLimitsSeriesMenuOpen] = (0, import_react7.useState)(false);
11666
- const [function2MenuOpen, setFunction2MenuOpen] = (0, import_react7.useState)(false);
11667
- const [derivativeMenuOpen, setDerivativeMenuOpen] = (0, import_react7.useState)(false);
11668
- const [groupMenuOpen, setGroupMenuOpen] = (0, import_react7.useState)(false);
11669
- const [operatorMenuOpen, setOperatorMenuOpen] = (0, import_react7.useState)(false);
11670
- const [operator2MenuOpen, setOperator2MenuOpen] = (0, import_react7.useState)(false);
11671
- const [operator3MenuOpen, setOperator3MenuOpen] = (0, import_react7.useState)(false);
11672
- const [dotMenuOpen, setDotMenuOpen] = (0, import_react7.useState)(false);
11673
- const [integralMenuOpen, setIntegralMenuOpen] = (0, import_react7.useState)(false);
11674
- const [selectedDigitForm2, setSelectedDigitForm] = (0, import_react7.useState)("western");
11675
- const [selectedCharacterFont, setSelectedCharacterFont] = (0, import_react7.useState)("default");
11676
- const [activeEditorSide, setActiveEditorSide] = (0, import_react7.useState)("arabic");
11677
- const [envPaletteMode, setEnvPaletteMode] = (0, import_react7.useState)("matrix");
11678
- const [matrixStyle, setMatrixStyle] = (0, import_react7.useState)("pmatrix");
11679
- const [matrixRows, setMatrixRows] = (0, import_react7.useState)(2);
11680
- const [matrixColumns, setMatrixColumns] = (0, import_react7.useState)(2);
11681
- const [matrixHover, setMatrixHover] = (0, import_react7.useState)(null);
11682
- const [arrayAlignmentColumn, setArrayAlignmentColumn] = (0, import_react7.useState)(1);
11683
- (0, import_react7.useImperativeHandle)(ref, () => ({
11871
+ const [digitMenuOpen, setDigitMenuOpen] = (0, import_react8.useState)(false);
11872
+ const [characterFontMenuOpen, setCharacterFontMenuOpen] = (0, import_react8.useState)(false);
11873
+ const [delimiterMenuOpen, setDelimiterMenuOpen] = (0, import_react8.useState)(false);
11874
+ const [matrixMenuOpen, setMatrixMenuOpen] = (0, import_react8.useState)(false);
11875
+ const [spacingMenuOpen, setSpacingMenuOpen] = (0, import_react8.useState)(false);
11876
+ const [functionMenuOpen, setFunctionMenuOpen] = (0, import_react8.useState)(false);
11877
+ const [limitsSeriesMenuOpen, setLimitsSeriesMenuOpen] = (0, import_react8.useState)(false);
11878
+ const [function2MenuOpen, setFunction2MenuOpen] = (0, import_react8.useState)(false);
11879
+ const [derivativeMenuOpen, setDerivativeMenuOpen] = (0, import_react8.useState)(false);
11880
+ const [groupMenuOpen, setGroupMenuOpen] = (0, import_react8.useState)(false);
11881
+ const [operatorMenuOpen, setOperatorMenuOpen] = (0, import_react8.useState)(false);
11882
+ const [operator2MenuOpen, setOperator2MenuOpen] = (0, import_react8.useState)(false);
11883
+ const [operator3MenuOpen, setOperator3MenuOpen] = (0, import_react8.useState)(false);
11884
+ const [dotMenuOpen, setDotMenuOpen] = (0, import_react8.useState)(false);
11885
+ const [integralMenuOpen, setIntegralMenuOpen] = (0, import_react8.useState)(false);
11886
+ const [selectedDigitForm2, setSelectedDigitForm] = (0, import_react8.useState)("western");
11887
+ const [selectedCharacterFont, setSelectedCharacterFont] = (0, import_react8.useState)("default");
11888
+ const [activeEditorSide, setActiveEditorSide] = (0, import_react8.useState)("arabic");
11889
+ const [envPaletteMode, setEnvPaletteMode] = (0, import_react8.useState)("matrix");
11890
+ const [matrixStyle, setMatrixStyle] = (0, import_react8.useState)("pmatrix");
11891
+ const [matrixRows, setMatrixRows] = (0, import_react8.useState)(2);
11892
+ const [matrixColumns, setMatrixColumns] = (0, import_react8.useState)(2);
11893
+ const [matrixHover, setMatrixHover] = (0, import_react8.useState)(null);
11894
+ const [arrayAlignmentColumn, setArrayAlignmentColumn] = (0, import_react8.useState)(1);
11895
+ (0, import_react8.useImperativeHandle)(ref, () => ({
11684
11896
  getRuntime: () => runtimeRef.current
11685
11897
  }));
11686
- const updatePreview = (0, import_react7.useCallback)(async (session) => {
11898
+ const updatePreview = (0, import_react8.useCallback)(async (session) => {
11687
11899
  const mathOutputEl = mathOutputRef.current;
11688
11900
  const renderErrorEl = renderErrorRef.current;
11689
11901
  const latexLinesEl = latexLinesRef.current;
@@ -11733,9 +11945,9 @@ ${arabic || currentMessages.empty}`;
11733
11945
  }
11734
11946
  }
11735
11947
  }, []);
11736
- const updatePreviewRef = (0, import_react7.useRef)(updatePreview);
11948
+ const updatePreviewRef = (0, import_react8.useRef)(updatePreview);
11737
11949
  updatePreviewRef.current = updatePreview;
11738
- (0, import_react7.useEffect)(() => {
11950
+ (0, import_react8.useEffect)(() => {
11739
11951
  injectWidgetChromeCss();
11740
11952
  injectBuTeXEditorStyles(typeof document !== "undefined" ? document : void 0);
11741
11953
  const surfaceEl = surfaceRef.current;
@@ -11791,7 +12003,7 @@ ${arabic || currentMessages.empty}`;
11791
12003
  runtimeRef.current = null;
11792
12004
  };
11793
12005
  }, []);
11794
- (0, import_react7.useEffect)(() => {
12006
+ (0, import_react8.useEffect)(() => {
11795
12007
  runtimeRef.current?.setUiLocale(uiLocale);
11796
12008
  const session = runtimeRef.current?.getSession();
11797
12009
  if (session) {
@@ -12864,6 +13076,18 @@ ButexEditor.displayName = "ButexEditor";
12864
13076
 
12865
13077
  // src/react-document2/EquationDrawer.tsx
12866
13078
  var import_jsx_runtime13 = require("react/jsx-runtime");
13079
+ function keyErrorMessage2(error, messages) {
13080
+ if (error === "empty") {
13081
+ return messages.keyEmpty;
13082
+ }
13083
+ if (error === "invalid") {
13084
+ return messages.keyInvalid;
13085
+ }
13086
+ if (error === "duplicate") {
13087
+ return messages.keyDuplicate;
13088
+ }
13089
+ return null;
13090
+ }
12867
13091
  function EquationDrawer({
12868
13092
  session,
12869
13093
  reason,
@@ -12873,6 +13097,9 @@ function EquationDrawer({
12873
13097
  uiLocale = "ar",
12874
13098
  labelEnabled = false,
12875
13099
  label = "",
13100
+ labels = [],
13101
+ references = [],
13102
+ ownerId = "",
12876
13103
  onLabelEnabledChange,
12877
13104
  onLabelChange,
12878
13105
  onMathModeChange,
@@ -12881,8 +13108,18 @@ function EquationDrawer({
12881
13108
  onDelete
12882
13109
  }) {
12883
13110
  const messages = document2Messages(uiLocale);
12884
- const latestSession = (0, import_react8.useRef)(session);
12885
- (0, import_react8.useEffect)(() => {
13111
+ const latestSession = (0, import_react9.useRef)(session);
13112
+ const [labelOverride, setLabelOverride] = (0, import_react9.useState)(null);
13113
+ const displayedLabel = labelOverride ?? label;
13114
+ const labelError = labelEnabled && mathMode === "display" ? document2KeyError(displayedLabel, {
13115
+ references,
13116
+ labels,
13117
+ excludeOwnerId: ownerId || void 0
13118
+ }) : null;
13119
+ (0, import_react9.useEffect)(() => {
13120
+ setLabelOverride(null);
13121
+ }, [ownerId, label]);
13122
+ (0, import_react9.useEffect)(() => {
12886
13123
  const onKeyDown = (event) => {
12887
13124
  if (event.key === "Escape") {
12888
13125
  onClose();
@@ -12942,12 +13179,27 @@ function EquationDrawer({
12942
13179
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
12943
13180
  "input",
12944
13181
  {
12945
- value: label,
13182
+ value: displayedLabel,
12946
13183
  dir: uiLocaleDirection(uiLocale),
12947
13184
  placeholder: messages.equationLabelPlaceholder,
12948
- onChange: (event) => onLabelChange?.(event.currentTarget.value)
13185
+ "aria-invalid": labelError !== null ? true : void 0,
13186
+ onChange: (event) => {
13187
+ const value = event.currentTarget.value;
13188
+ setLabelOverride(value);
13189
+ const error = document2KeyError(value, {
13190
+ references,
13191
+ labels,
13192
+ excludeOwnerId: ownerId || void 0
13193
+ });
13194
+ if (error !== null) {
13195
+ return;
13196
+ }
13197
+ onLabelChange?.(value);
13198
+ setLabelOverride(null);
13199
+ }
12949
13200
  }
12950
- )
13201
+ ),
13202
+ labelError !== null ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "butex-document2-widget__field-error", children: labelError === "invalid" ? messages.keyRulesHint : keyErrorMessage2(labelError, messages) }) : null
12951
13203
  ] }) : null
12952
13204
  ] }) : null,
12953
13205
  reason ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "butex-document2-widget__error", children: uiLocale === "en" ? messages.equationUnavailable : reason }) : null,
@@ -12965,7 +13217,15 @@ function EquationDrawer({
12965
13217
  ),
12966
13218
  /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "butex-document2-widget__row", children: [
12967
13219
  canDelete && onDelete ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", className: "butex-document2-widget__button--danger", onClick: onDelete, children: messages.deleteEquation }) : null,
12968
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => onSave({ ...latestSession.current, activeSide: equationSide }), children: messages.saveEquation })
13220
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
13221
+ "button",
13222
+ {
13223
+ type: "button",
13224
+ disabled: labelEnabled && mathMode === "display" && labelError !== null,
13225
+ onClick: () => onSave({ ...latestSession.current, activeSide: equationSide }),
13226
+ children: messages.saveEquation
13227
+ }
13228
+ )
12969
13229
  ] })
12970
13230
  ]
12971
13231
  }
@@ -12974,92 +13234,243 @@ function EquationDrawer({
12974
13234
  }
12975
13235
 
12976
13236
  // src/react-document2/LabelsPanel.tsx
13237
+ var import_react10 = require("react");
12977
13238
  var import_jsx_runtime14 = require("react/jsx-runtime");
12978
- function kindLabel(kind, uiLocale) {
12979
- const messages = document2Messages(uiLocale);
12980
- if (kind === "fig") {
12981
- return messages.labelKindFig;
13239
+ function keyErrorMessage3(error, messages) {
13240
+ if (error === "empty") {
13241
+ return messages.keyEmpty;
12982
13242
  }
12983
- if (kind === "tab") {
12984
- return messages.labelKindTab;
13243
+ if (error === "invalid") {
13244
+ return messages.keyInvalid;
12985
13245
  }
12986
- return messages.labelKindEq;
13246
+ if (error === "duplicate") {
13247
+ return messages.keyDuplicate;
13248
+ }
13249
+ return null;
12987
13250
  }
12988
13251
  function LabelsPanel({
12989
13252
  open,
12990
13253
  labels,
13254
+ references = [],
12991
13255
  uiLocale = "ar",
13256
+ digitForm = "arabicIndic",
12992
13257
  onClose,
12993
13258
  onUpdateFloat,
12994
13259
  onUpdateEquationLabel
12995
13260
  }) {
12996
13261
  const messages = document2Messages(uiLocale);
13262
+ const documentDirection = uiLocale === "ar" ? "rtl" : "ltr";
13263
+ const [keyOverrides, setKeyOverrides] = (0, import_react10.useState)({});
12997
13264
  if (!open) {
12998
13265
  return null;
12999
13266
  }
13000
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "butex-document2-widget__refs-backdrop", role: "presentation", onClick: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "butex-document2-widget__refs-panel", role: "dialog", "aria-label": messages.labelsTitle, onClick: (event) => event.stopPropagation(), children: [
13001
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("header", { className: "butex-document2-widget__refs-header", children: [
13002
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("strong", { children: messages.labelsTitle }),
13003
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", className: "butex-document2-widget__icon-btn", title: messages.close, "aria-label": messages.close, onClick: onClose, children: "\xD7" })
13004
- ] }),
13005
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "butex-document2-widget__labels-help", children: messages.labelsHelp }),
13006
- labels.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "butex-document2-widget__cite-picker-empty", children: messages.noLabelsYet }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("ul", { className: "butex-document2-widget__refs-list", children: labels.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("li", { className: "butex-document2-widget__refs-item", children: [
13007
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "butex-document2-widget__refs-item-head", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("strong", { children: [
13008
- "[",
13009
- kindLabel(entry.kind, uiLocale),
13010
- " ",
13011
- entry.number,
13012
- "] ",
13013
- entry.key
13014
- ] }) }),
13015
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "butex-document2-widget__refs-grid", children: [
13016
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "butex-document2-widget__refs-field", children: [
13017
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: messages.floatLabel }),
13018
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
13019
- "input",
13020
- {
13021
- value: entry.key,
13022
- dir: uiLocaleDirection(uiLocale),
13023
- onChange: (event) => {
13024
- const value = event.currentTarget.value;
13025
- if (entry.kind === "eq") {
13026
- onUpdateEquationLabel?.(entry.ownerId, { label: value, labelEnabled: true });
13027
- } else if (entry.kind === "fig" || entry.kind === "tab") {
13028
- onUpdateFloat?.(entry.ownerId, entry.kind, { label: value, labelEnabled: true });
13029
- }
13030
- }
13031
- }
13032
- )
13267
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "butex-document2-widget__refs-backdrop", role: "presentation", onClick: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
13268
+ "div",
13269
+ {
13270
+ className: "butex-document2-widget__refs-panel",
13271
+ role: "dialog",
13272
+ "aria-label": messages.labelsTitle,
13273
+ onClick: (event) => event.stopPropagation(),
13274
+ children: [
13275
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("header", { className: "butex-document2-widget__refs-header", children: [
13276
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("strong", { children: messages.labelsTitle }),
13277
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", className: "butex-document2-widget__icon-btn", title: messages.close, "aria-label": messages.close, onClick: onClose, children: "\xD7" })
13033
13278
  ] }),
13034
- entry.kind === "fig" || entry.kind === "tab" ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "butex-document2-widget__refs-field", children: [
13035
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: messages.floatCaption }),
13036
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
13037
- "input",
13038
- {
13039
- value: entry.caption,
13040
- onChange: (event) => {
13041
- const value = event.currentTarget.value;
13042
- const kind = entry.kind;
13043
- if (kind === "fig" || kind === "tab") {
13044
- onUpdateFloat?.(entry.ownerId, kind, { caption: value, captionEnabled: true });
13045
- }
13279
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "butex-document2-widget__labels-help", children: messages.labelsHelp }),
13280
+ labels.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "butex-document2-widget__cite-picker-empty", children: messages.noLabelsYet }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("ul", { className: "butex-document2-widget__refs-list", children: labels.map((entry) => {
13281
+ const title = formatFloatCaptionTitle(entry.kind, entry.number, {
13282
+ uiLocale,
13283
+ digitForm,
13284
+ documentDirection
13285
+ });
13286
+ const captionPreview = entry.kind === "eq" ? title : formatFloatCaptionPreview(title, entry.caption, uiLocale);
13287
+ const overrideKey = `${entry.kind}:${entry.ownerId}`;
13288
+ const displayedKey = keyOverrides[overrideKey] ?? entry.key;
13289
+ const entryKeyError = document2KeyError(displayedKey, {
13290
+ references,
13291
+ labels,
13292
+ excludeOwnerId: entry.ownerId
13293
+ });
13294
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("li", { className: "butex-document2-widget__refs-item", children: [
13295
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "butex-document2-widget__refs-item-head", children: [
13296
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("strong", { children: title }),
13297
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "butex-document2-widget__refs-item-key", children: entry.key })
13298
+ ] }),
13299
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
13300
+ "div",
13301
+ {
13302
+ className: "butex-document2-widget__modal-preview",
13303
+ dir: uiLocaleDirection(uiLocale),
13304
+ "aria-label": messages.captionPreview,
13305
+ children: captionPreview
13046
13306
  }
13047
- }
13048
- )
13049
- ] }) : null
13050
- ] })
13051
- ] }, `${entry.kind}:${entry.ownerId}`)) })
13052
- ] }) });
13307
+ ),
13308
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "butex-document2-widget__refs-grid", children: [
13309
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "butex-document2-widget__refs-field", children: [
13310
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: messages.floatLabel }),
13311
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
13312
+ "input",
13313
+ {
13314
+ value: displayedKey,
13315
+ dir: uiLocaleDirection(uiLocale),
13316
+ "aria-invalid": entryKeyError !== null ? true : void 0,
13317
+ onChange: (event) => {
13318
+ const value = event.currentTarget.value;
13319
+ setKeyOverrides((current) => ({ ...current, [overrideKey]: value }));
13320
+ const error = document2KeyError(value, {
13321
+ references,
13322
+ labels,
13323
+ excludeOwnerId: entry.ownerId
13324
+ });
13325
+ if (error !== null) {
13326
+ return;
13327
+ }
13328
+ if (entry.kind === "eq") {
13329
+ onUpdateEquationLabel?.(entry.ownerId, { label: value, labelEnabled: true });
13330
+ } else if (entry.kind === "fig" || entry.kind === "tab") {
13331
+ onUpdateFloat?.(entry.ownerId, entry.kind, { label: value, labelEnabled: true });
13332
+ }
13333
+ setKeyOverrides((current) => {
13334
+ const next = { ...current };
13335
+ delete next[overrideKey];
13336
+ return next;
13337
+ });
13338
+ }
13339
+ }
13340
+ ),
13341
+ entryKeyError !== null ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "butex-document2-widget__field-error", children: entryKeyError === "invalid" ? messages.keyRulesHint : keyErrorMessage3(entryKeyError, messages) }) : null
13342
+ ] }),
13343
+ entry.kind === "fig" || entry.kind === "tab" ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "butex-document2-widget__refs-field", children: [
13344
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: messages.floatCaption }),
13345
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
13346
+ "input",
13347
+ {
13348
+ value: entry.caption,
13349
+ onChange: (event) => {
13350
+ const value = event.currentTarget.value;
13351
+ const kind = entry.kind;
13352
+ if (kind === "fig" || kind === "tab") {
13353
+ onUpdateFloat?.(entry.ownerId, kind, { caption: value, captionEnabled: true });
13354
+ }
13355
+ }
13356
+ }
13357
+ )
13358
+ ] }) : null
13359
+ ] })
13360
+ ] }, overrideKey);
13361
+ }) })
13362
+ ]
13363
+ }
13364
+ ) });
13053
13365
  }
13054
13366
 
13055
13367
  // src/react-document2/ReferencesPanel.tsx
13056
- var import_react9 = require("react");
13368
+ var import_react11 = require("react");
13057
13369
  var import_jsx_runtime15 = require("react/jsx-runtime");
13058
- var EMPTY_DRAFT = { key: "", authors: "", title: "", year: "", url: "", venue: "" };
13370
+ var EMPTY_DRAFT = {
13371
+ key: "",
13372
+ authors: "",
13373
+ title: "",
13374
+ year: "",
13375
+ url: "",
13376
+ venue: "",
13377
+ field_separator: DEFAULT_REFERENCE_FIELD_SEPARATOR
13378
+ };
13379
+ var REFERENCE_FIELDS = [
13380
+ ["key", "referenceKey"],
13381
+ ["authors", "referenceAuthors"],
13382
+ ["title", "referenceTitle"],
13383
+ ["year", "referenceYear"],
13384
+ ["venue", "referenceVenue"],
13385
+ ["url", "referenceUrl"]
13386
+ ];
13387
+ function keyErrorMessage4(error, messages) {
13388
+ if (error === "empty") {
13389
+ return messages.keyEmpty;
13390
+ }
13391
+ if (error === "invalid") {
13392
+ return messages.keyInvalid;
13393
+ }
13394
+ if (error === "duplicate") {
13395
+ return messages.keyDuplicate;
13396
+ }
13397
+ return null;
13398
+ }
13399
+ function FieldSeparatorToggle({
13400
+ value,
13401
+ messages,
13402
+ onChange
13403
+ }) {
13404
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "butex-document2-widget__refs-field butex-document2-widget__refs-separator", children: [
13405
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: messages.referenceFieldSeparator }),
13406
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "butex-document2-widget__refs-separator-toggle", role: "group", "aria-label": messages.referenceFieldSeparator, children: [
13407
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13408
+ "button",
13409
+ {
13410
+ type: "button",
13411
+ className: value === "\u060C" ? "is-active" : void 0,
13412
+ title: messages.referenceCommaRtl,
13413
+ "aria-label": messages.referenceCommaRtl,
13414
+ "aria-pressed": value === "\u060C",
13415
+ onClick: () => onChange("\u060C"),
13416
+ children: "\u060C"
13417
+ }
13418
+ ),
13419
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13420
+ "button",
13421
+ {
13422
+ type: "button",
13423
+ className: value === "," ? "is-active" : void 0,
13424
+ title: messages.referenceCommaLtr,
13425
+ "aria-label": messages.referenceCommaLtr,
13426
+ "aria-pressed": value === ",",
13427
+ onClick: () => onChange(","),
13428
+ children: ","
13429
+ }
13430
+ )
13431
+ ] })
13432
+ ] });
13433
+ }
13434
+ function ReferencePreview({
13435
+ authors,
13436
+ title,
13437
+ venue,
13438
+ year,
13439
+ url,
13440
+ fieldSeparator,
13441
+ numberLabel,
13442
+ messages,
13443
+ uiLocale,
13444
+ digitForm
13445
+ }) {
13446
+ const body = bibliographyEntryBody({ authors, title, venue, year, fieldSeparator }, fieldSeparator, { digitForm });
13447
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
13448
+ "div",
13449
+ {
13450
+ className: "butex-document2-widget__modal-preview",
13451
+ dir: uiLocaleDirection(uiLocale),
13452
+ "aria-label": messages.referencePreview,
13453
+ children: [
13454
+ numberLabel ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { className: "butex-document2-widget__modal-preview-number", children: [
13455
+ "[",
13456
+ numberLabel,
13457
+ "] "
13458
+ ] }) : null,
13459
+ body.length > 0 ? body : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "butex-document2-widget__cite-picker-empty", children: "\u2026" }),
13460
+ url.trim().length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
13461
+ " ",
13462
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "butex-document2-widget__modal-preview-url", children: url.trim() })
13463
+ ] }) : null
13464
+ ]
13465
+ }
13466
+ );
13467
+ }
13059
13468
  function ReferencesPanel({
13060
13469
  open,
13061
13470
  references,
13471
+ labels = [],
13062
13472
  uiLocale = "ar",
13473
+ digitForm = "arabicIndic",
13063
13474
  onClose,
13064
13475
  onAdd,
13065
13476
  onUpdate,
@@ -13067,101 +13478,190 @@ function ReferencesPanel({
13067
13478
  onMove
13068
13479
  }) {
13069
13480
  const messages = document2Messages(uiLocale);
13070
- const [draft, setDraft] = (0, import_react9.useState)(EMPTY_DRAFT);
13481
+ const [draft, setDraft] = (0, import_react11.useState)(EMPTY_DRAFT);
13482
+ const [draftKeyTouched, setDraftKeyTouched] = (0, import_react11.useState)(false);
13483
+ const [keyOverrides, setKeyOverrides] = (0, import_react11.useState)({});
13484
+ const draftSeparator = draft.field_separator === "," ? "," : DEFAULT_REFERENCE_FIELD_SEPARATOR;
13485
+ const documentDirection = uiLocale === "ar" ? "rtl" : "ltr";
13486
+ const draftKeyError = (0, import_react11.useMemo)(
13487
+ () => document2KeyError(draft.key ?? "", {
13488
+ references,
13489
+ labels
13490
+ }),
13491
+ [draft.key, references, labels]
13492
+ );
13071
13493
  if (!open) {
13072
13494
  return null;
13073
13495
  }
13074
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "butex-document2-widget__refs-backdrop", role: "presentation", onClick: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "butex-document2-widget__refs-panel", role: "dialog", "aria-label": messages.referencesTitle, onClick: (event) => event.stopPropagation(), children: [
13075
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("header", { className: "butex-document2-widget__refs-header", children: [
13076
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("strong", { children: messages.referencesTitle }),
13077
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", className: "butex-document2-widget__icon-btn", title: messages.close, "aria-label": messages.close, onClick: onClose, children: "\xD7" })
13078
- ] }),
13079
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "butex-document2-widget__refs-add", children: [
13080
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h3", { children: messages.addReference }),
13081
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "butex-document2-widget__refs-grid", children: [
13082
- ["key", messages.referenceKey],
13083
- ["authors", messages.referenceAuthors],
13084
- ["title", messages.referenceTitle],
13085
- ["year", messages.referenceYear],
13086
- ["venue", messages.referenceVenue],
13087
- ["url", messages.referenceUrl]
13088
- ].map(([field, label]) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { className: "butex-document2-widget__refs-field", children: [
13089
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: label }),
13090
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13091
- "input",
13092
- {
13093
- value: draft[field] ?? "",
13094
- onChange: (event) => {
13095
- const value = event.currentTarget.value;
13096
- setDraft((current) => ({ ...current, [field]: value }));
13097
- }
13098
- }
13099
- )
13100
- ] }, field)) }),
13101
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13102
- "button",
13103
- {
13104
- type: "button",
13105
- className: "butex-document2-widget__primary-btn",
13106
- disabled: !draft.key?.trim(),
13107
- onClick: () => {
13108
- onAdd(draft);
13109
- setDraft(EMPTY_DRAFT);
13110
- },
13111
- children: messages.addReference
13112
- }
13113
- )
13114
- ] }),
13115
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("ul", { className: "butex-document2-widget__refs-list", children: references.map((reference, index) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("li", { className: "butex-document2-widget__refs-item", children: [
13116
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "butex-document2-widget__refs-item-head", children: [
13117
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("strong", { children: [
13118
- "[",
13119
- index + 1,
13120
- "] ",
13121
- reference.key
13496
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "butex-document2-widget__refs-backdrop", role: "presentation", onClick: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
13497
+ "div",
13498
+ {
13499
+ className: "butex-document2-widget__refs-panel",
13500
+ role: "dialog",
13501
+ "aria-label": messages.referencesTitle,
13502
+ onClick: (event) => event.stopPropagation(),
13503
+ children: [
13504
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("header", { className: "butex-document2-widget__refs-header", children: [
13505
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("strong", { children: messages.referencesTitle }),
13506
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", className: "butex-document2-widget__icon-btn", title: messages.close, "aria-label": messages.close, onClick: onClose, children: "\xD7" })
13122
13507
  ] }),
13123
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "butex-document2-widget__refs-item-actions", children: [
13124
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", title: messages.moveUp, "aria-label": messages.moveUp, disabled: index === 0, onClick: () => onMove(reference.id, -1), children: "\u2191" }),
13508
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "butex-document2-widget__refs-add", children: [
13509
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h3", { children: messages.addReference }),
13510
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "butex-document2-widget__refs-grid", children: [
13511
+ REFERENCE_FIELDS.map(([field, messageKey]) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { className: "butex-document2-widget__refs-field", children: [
13512
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: messages[messageKey] }),
13513
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13514
+ "input",
13515
+ {
13516
+ value: draft[field] ?? "",
13517
+ "aria-invalid": field === "key" && draftKeyTouched && draftKeyError !== null ? true : void 0,
13518
+ onChange: (event) => {
13519
+ const value = event.currentTarget.value;
13520
+ if (field === "key") {
13521
+ setDraftKeyTouched(true);
13522
+ }
13523
+ setDraft((current) => ({ ...current, [field]: value }));
13524
+ }
13525
+ }
13526
+ ),
13527
+ field === "key" && draftKeyTouched && draftKeyError !== null ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "butex-document2-widget__field-error", children: draftKeyError === "invalid" ? messages.keyRulesHint : keyErrorMessage4(draftKeyError, messages) }) : null
13528
+ ] }, field)),
13529
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13530
+ FieldSeparatorToggle,
13531
+ {
13532
+ value: draftSeparator,
13533
+ messages,
13534
+ onChange: (next) => setDraft((current) => ({ ...current, field_separator: next }))
13535
+ }
13536
+ )
13537
+ ] }),
13125
13538
  /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13126
- "button",
13539
+ ReferencePreview,
13127
13540
  {
13128
- type: "button",
13129
- title: messages.moveDown,
13130
- "aria-label": messages.moveDown,
13131
- disabled: index === references.length - 1,
13132
- onClick: () => onMove(reference.id, 1),
13133
- children: "\u2193"
13541
+ authors: draft.authors ?? "",
13542
+ title: draft.title ?? "",
13543
+ venue: draft.venue ?? "",
13544
+ year: draft.year ?? "",
13545
+ url: draft.url ?? "",
13546
+ fieldSeparator: draftSeparator,
13547
+ messages,
13548
+ uiLocale,
13549
+ digitForm
13134
13550
  }
13135
13551
  ),
13136
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", title: messages.deleteReference, "aria-label": messages.deleteReference, onClick: () => onRemove(reference.id), children: "\xD7" })
13137
- ] })
13138
- ] }),
13139
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "butex-document2-widget__refs-grid", children: [
13140
- ["key", messages.referenceKey],
13141
- ["authors", messages.referenceAuthors],
13142
- ["title", messages.referenceTitle],
13143
- ["year", messages.referenceYear],
13144
- ["venue", messages.referenceVenue],
13145
- ["url", messages.referenceUrl]
13146
- ].map(([field, label]) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { className: "butex-document2-widget__refs-field", children: [
13147
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: label }),
13148
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13149
- "input",
13150
- {
13151
- value: reference[field],
13152
- onChange: (event) => {
13153
- const value = event.currentTarget.value;
13154
- onUpdate(reference.id, { [field]: value });
13552
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13553
+ "button",
13554
+ {
13555
+ type: "button",
13556
+ className: "butex-document2-widget__primary-btn",
13557
+ disabled: draftKeyError !== null,
13558
+ onClick: () => {
13559
+ onAdd({ ...draft, field_separator: draftSeparator });
13560
+ setDraft(EMPTY_DRAFT);
13561
+ setDraftKeyTouched(false);
13562
+ },
13563
+ children: messages.addReference
13155
13564
  }
13156
- }
13157
- )
13158
- ] }, field)) })
13159
- ] }, reference.id)) })
13160
- ] }) });
13565
+ )
13566
+ ] }),
13567
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("ul", { className: "butex-document2-widget__refs-list", children: references.map((reference, index) => {
13568
+ const displayedKey = keyOverrides[reference.id] ?? reference.key;
13569
+ const entryKeyError = document2KeyError(displayedKey, {
13570
+ references,
13571
+ labels,
13572
+ excludeReferenceId: reference.id
13573
+ });
13574
+ const numberLabel = formatBibliographyNumber(index + 1, { documentDirection, digitForm });
13575
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("li", { className: "butex-document2-widget__refs-item", children: [
13576
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "butex-document2-widget__refs-item-head", children: [
13577
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("strong", { children: [
13578
+ "[",
13579
+ numberLabel,
13580
+ "] ",
13581
+ reference.key
13582
+ ] }),
13583
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "butex-document2-widget__refs-item-actions", children: [
13584
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", title: messages.moveUp, "aria-label": messages.moveUp, disabled: index === 0, onClick: () => onMove(reference.id, -1), children: "\u2191" }),
13585
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13586
+ "button",
13587
+ {
13588
+ type: "button",
13589
+ title: messages.moveDown,
13590
+ "aria-label": messages.moveDown,
13591
+ disabled: index === references.length - 1,
13592
+ onClick: () => onMove(reference.id, 1),
13593
+ children: "\u2193"
13594
+ }
13595
+ ),
13596
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", title: messages.deleteReference, "aria-label": messages.deleteReference, onClick: () => onRemove(reference.id), children: "\xD7" })
13597
+ ] })
13598
+ ] }),
13599
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13600
+ ReferencePreview,
13601
+ {
13602
+ authors: reference.authors,
13603
+ title: reference.title,
13604
+ venue: reference.venue,
13605
+ year: reference.year,
13606
+ url: reference.url,
13607
+ fieldSeparator: reference.fieldSeparator,
13608
+ numberLabel,
13609
+ messages,
13610
+ uiLocale,
13611
+ digitForm
13612
+ }
13613
+ ),
13614
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "butex-document2-widget__refs-grid", children: [
13615
+ REFERENCE_FIELDS.map(([field, messageKey]) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { className: "butex-document2-widget__refs-field", children: [
13616
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: messages[messageKey] }),
13617
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13618
+ "input",
13619
+ {
13620
+ value: field === "key" ? displayedKey : reference[field],
13621
+ "aria-invalid": field === "key" && entryKeyError !== null ? true : void 0,
13622
+ onChange: (event) => {
13623
+ const value = event.currentTarget.value;
13624
+ if (field !== "key") {
13625
+ onUpdate(reference.id, { [field]: value });
13626
+ return;
13627
+ }
13628
+ setKeyOverrides((current) => ({ ...current, [reference.id]: value }));
13629
+ const error = document2KeyError(value, {
13630
+ references,
13631
+ labels,
13632
+ excludeReferenceId: reference.id
13633
+ });
13634
+ if (error === null) {
13635
+ onUpdate(reference.id, { key: value });
13636
+ setKeyOverrides((current) => {
13637
+ const next = { ...current };
13638
+ delete next[reference.id];
13639
+ return next;
13640
+ });
13641
+ }
13642
+ }
13643
+ }
13644
+ ),
13645
+ field === "key" && entryKeyError !== null ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "butex-document2-widget__field-error", children: entryKeyError === "invalid" ? messages.keyRulesHint : keyErrorMessage4(entryKeyError, messages) }) : null
13646
+ ] }, field)),
13647
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13648
+ FieldSeparatorToggle,
13649
+ {
13650
+ value: reference.fieldSeparator,
13651
+ messages,
13652
+ onChange: (next) => onUpdate(reference.id, { field_separator: next })
13653
+ }
13654
+ )
13655
+ ] })
13656
+ ] }, reference.id);
13657
+ }) })
13658
+ ]
13659
+ }
13660
+ ) });
13161
13661
  }
13162
13662
 
13163
13663
  // src/react-document2/RefPickerPopover.tsx
13164
- var import_react10 = require("react");
13664
+ var import_react12 = require("react");
13165
13665
  var import_jsx_runtime16 = require("react/jsx-runtime");
13166
13666
  function RefPickerPopover({
13167
13667
  open,
@@ -13169,14 +13669,16 @@ function RefPickerPopover({
13169
13669
  initialKeys = [],
13170
13670
  initialRefCommand = "ref",
13171
13671
  uiLocale = "ar",
13672
+ digitForm = "arabicIndic",
13172
13673
  onClose,
13173
13674
  onConfirm,
13174
13675
  onManageLabels
13175
13676
  }) {
13176
13677
  const messages = document2Messages(uiLocale);
13177
- const [selected, setSelected] = (0, import_react10.useState)(initialKeys);
13178
- const [refCommand, setRefCommand] = (0, import_react10.useState)(initialRefCommand);
13179
- (0, import_react10.useEffect)(() => {
13678
+ const documentDirection = uiLocale === "ar" ? "rtl" : "ltr";
13679
+ const [selected, setSelected] = (0, import_react12.useState)(initialKeys);
13680
+ const [refCommand, setRefCommand] = (0, import_react12.useState)(initialRefCommand);
13681
+ (0, import_react12.useEffect)(() => {
13180
13682
  if (open) {
13181
13683
  setSelected(initialKeys);
13182
13684
  setRefCommand(initialRefCommand);
@@ -13203,16 +13705,18 @@ function RefPickerPopover({
13203
13705
  ] }),
13204
13706
  labels.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "butex-document2-widget__cite-picker-empty", children: messages.noLabelsYet }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("ul", { className: "butex-document2-widget__cite-picker-list", children: labels.map((entry) => {
13205
13707
  const checked = selected.includes(entry.key);
13708
+ const title = formatFloatCaptionTitle(entry.kind, entry.number, {
13709
+ uiLocale,
13710
+ digitForm,
13711
+ documentDirection
13712
+ });
13206
13713
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("label", { className: "butex-document2-widget__cite-picker-item", children: [
13207
13714
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("input", { type: "radio", name: "butex-ref-key", checked, onChange: () => selectKey(entry.key, entry.kind) }),
13208
13715
  /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("span", { children: [
13209
13716
  /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("strong", { children: [
13210
- "[",
13211
- entry.kind,
13717
+ title,
13212
13718
  " ",
13213
- entry.number,
13214
- "] ",
13215
- entry.key
13719
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "butex-document2-widget__refs-item-key", children: entry.key })
13216
13720
  ] }),
13217
13721
  entry.caption ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "butex-document2-widget__cite-picker-meta", children: entry.caption }) : null
13218
13722
  ] })
@@ -14404,6 +14908,24 @@ var DOCUMENT2_WIDGET_CSS = `
14404
14908
  width: 100%;
14405
14909
  }
14406
14910
 
14911
+ .butex-document2-widget__field-error {
14912
+ color: #b42318;
14913
+ font-size: 0.85em;
14914
+ line-height: 1.35;
14915
+ margin: 0;
14916
+ }
14917
+
14918
+ .butex-document2-widget__field-hint {
14919
+ color: var(--butex-document2-muted);
14920
+ font-size: 0.82em;
14921
+ line-height: 1.35;
14922
+ margin: 0;
14923
+ }
14924
+
14925
+ .butex-document2-widget__refs-field input[aria-invalid='true'] {
14926
+ border-color: color-mix(in srgb, #b42318 55%, var(--butex-document2-border));
14927
+ }
14928
+
14407
14929
  .butex-document2-widget__refs-item {
14408
14930
  border: 1px solid var(--butex-document2-border);
14409
14931
  border-radius: 10px;
@@ -14412,6 +14934,58 @@ var DOCUMENT2_WIDGET_CSS = `
14412
14934
  padding: 0.75rem;
14413
14935
  }
14414
14936
 
14937
+ .butex-document2-widget__refs-item-key {
14938
+ color: var(--butex-document2-muted);
14939
+ font-size: 0.9em;
14940
+ font-weight: 500;
14941
+ }
14942
+
14943
+ .butex-document2-widget__modal-preview {
14944
+ background: color-mix(in srgb, var(--butex-document2-panel) 88%, var(--butex-document2-accent-bg));
14945
+ border: 1px dashed color-mix(in srgb, var(--butex-document2-accent) 30%, var(--butex-document2-border));
14946
+ border-radius: 8px;
14947
+ color: inherit;
14948
+ font-size: 0.95em;
14949
+ line-height: 1.55;
14950
+ padding: 0.55rem 0.7rem;
14951
+ text-align: center;
14952
+ }
14953
+
14954
+ .butex-document2-widget__modal-preview-number {
14955
+ color: var(--butex-document2-muted);
14956
+ font-weight: 600;
14957
+ }
14958
+
14959
+ .butex-document2-widget__modal-preview-url {
14960
+ color: var(--butex-document2-accent);
14961
+ word-break: break-all;
14962
+ }
14963
+
14964
+ .butex-document2-widget__refs-separator-toggle {
14965
+ display: inline-flex;
14966
+ gap: 0.35rem;
14967
+ }
14968
+
14969
+ .butex-document2-widget__refs-separator-toggle button {
14970
+ background: var(--butex-document2-input-bg, var(--butex-document2-panel));
14971
+ border: 1px solid var(--butex-document2-border);
14972
+ border-radius: 6px;
14973
+ color: inherit;
14974
+ cursor: pointer;
14975
+ font: inherit;
14976
+ font-size: 1.15em;
14977
+ line-height: 1;
14978
+ min-width: 2.25rem;
14979
+ padding: 0.35rem 0.55rem;
14980
+ }
14981
+
14982
+ .butex-document2-widget__refs-separator-toggle button.is-active {
14983
+ background: var(--butex-document2-accent-bg);
14984
+ border-color: color-mix(in srgb, var(--butex-document2-accent) 45%, var(--butex-document2-border));
14985
+ color: var(--butex-document2-accent);
14986
+ font-weight: 700;
14987
+ }
14988
+
14415
14989
  .butex-document2-widget__refs-item-actions {
14416
14990
  display: inline-flex;
14417
14991
  gap: 0.25rem;
@@ -14903,36 +15477,36 @@ function ButexDocumentEditor2({
14903
15477
  onLatexChange
14904
15478
  }) {
14905
15479
  const messages = document2Messages(uiLocale);
14906
- const initialState = (0, import_react11.useMemo)(
15480
+ const initialState = (0, import_react13.useMemo)(
14907
15481
  () => resolveInitialDocument2(initialDocument, uiLocale, documentMeta),
14908
15482
  [initialDocument, documentMeta, uiLocale]
14909
15483
  );
14910
- const [documentNode, setDocumentNode] = (0, import_react11.useState)(initialState.document);
14911
- const [error, setError] = (0, import_react11.useState)(initialState.error);
14912
- const [editorOpen, setEditorOpen] = (0, import_react11.useState)(true);
14913
- const [previewOpen, setPreviewOpen] = (0, import_react11.useState)(true);
14914
- const [selectedMath, setSelectedMath] = (0, import_react11.useState)(null);
14915
- const [citePicker, setCitePicker] = (0, import_react11.useState)(null);
14916
- const [referencesOpen, setReferencesOpen] = (0, import_react11.useState)(false);
14917
- const [labelsOpen, setLabelsOpen] = (0, import_react11.useState)(false);
14918
- const [refPicker, setRefPicker] = (0, import_react11.useState)(null);
14919
- const [digitFormState, setDigitFormState] = (0, import_react11.useState)(null);
14920
- const [editorFocus, setEditorFocus] = (0, import_react11.useState)(createEmptyDocument2EditorFocus());
14921
- const [collapsedBlockIds, setCollapsedBlockIds] = (0, import_react11.useState)(() => /* @__PURE__ */ new Set());
14922
- const [blockSelectionState, setBlockSelectionState] = (0, import_react11.useState)(emptyBlockSelection);
14923
- const [historyTick, setHistoryTick] = (0, import_react11.useState)(0);
15484
+ const [documentNode, setDocumentNode] = (0, import_react13.useState)(initialState.document);
15485
+ const [error, setError] = (0, import_react13.useState)(initialState.error);
15486
+ const [editorOpen, setEditorOpen] = (0, import_react13.useState)(true);
15487
+ const [previewOpen, setPreviewOpen] = (0, import_react13.useState)(true);
15488
+ const [selectedMath, setSelectedMath] = (0, import_react13.useState)(null);
15489
+ const [citePicker, setCitePicker] = (0, import_react13.useState)(null);
15490
+ const [referencesOpen, setReferencesOpen] = (0, import_react13.useState)(false);
15491
+ const [labelsOpen, setLabelsOpen] = (0, import_react13.useState)(false);
15492
+ const [refPicker, setRefPicker] = (0, import_react13.useState)(null);
15493
+ const [digitFormState, setDigitFormState] = (0, import_react13.useState)(null);
15494
+ const [editorFocus, setEditorFocus] = (0, import_react13.useState)(createEmptyDocument2EditorFocus());
15495
+ const [collapsedBlockIds, setCollapsedBlockIds] = (0, import_react13.useState)(() => /* @__PURE__ */ new Set());
15496
+ const [blockSelectionState, setBlockSelectionState] = (0, import_react13.useState)(emptyBlockSelection);
15497
+ const [historyTick, setHistoryTick] = (0, import_react13.useState)(0);
14924
15498
  const digitForm = digitFormProp ?? digitFormState ?? (documentDirection === "rtl" ? "arabicIndic" : "western");
14925
- const historyRef = (0, import_react11.useRef)(createDocument2History());
14926
- const documentRef = (0, import_react11.useRef)(documentNode);
14927
- const textSnapshotArmedRef = (0, import_react11.useRef)(false);
14928
- const textDebounceRef = (0, import_react11.useRef)(null);
14929
- const widgetRef = (0, import_react11.useRef)(null);
14930
- const articleMetaPanelRef = (0, import_react11.useRef)(null);
14931
- const pendingFocusRef = (0, import_react11.useRef)(null);
15499
+ const historyRef = (0, import_react13.useRef)(createDocument2History());
15500
+ const documentRef = (0, import_react13.useRef)(documentNode);
15501
+ const textSnapshotArmedRef = (0, import_react13.useRef)(false);
15502
+ const textDebounceRef = (0, import_react13.useRef)(null);
15503
+ const widgetRef = (0, import_react13.useRef)(null);
15504
+ const articleMetaPanelRef = (0, import_react13.useRef)(null);
15505
+ const pendingFocusRef = (0, import_react13.useRef)(null);
14932
15506
  documentRef.current = documentNode;
14933
15507
  const latex = document2Latex(documentNode);
14934
- const documentLabels = (0, import_react11.useMemo)(() => collectDocument2Labels(documentNode), [documentNode]);
14935
- const preview = (0, import_react11.useMemo)(
15508
+ const documentLabels = (0, import_react13.useMemo)(() => collectDocument2Labels(documentNode), [documentNode]);
15509
+ const preview = (0, import_react13.useMemo)(
14936
15510
  () => document2Preview(documentNode, mathOutput, equationSide, {
14937
15511
  documentDirection,
14938
15512
  digitForm,
@@ -14940,7 +15514,7 @@ function ButexDocumentEditor2({
14940
15514
  }),
14941
15515
  [documentNode, documentDirection, digitForm, equationSide, mathOutput, uiLocale]
14942
15516
  );
14943
- const debugEnabled = (0, import_react11.useMemo)(() => {
15517
+ const debugEnabled = (0, import_react13.useMemo)(() => {
14944
15518
  if (debug) {
14945
15519
  return true;
14946
15520
  }
@@ -14949,8 +15523,8 @@ function ButexDocumentEditor2({
14949
15523
  }
14950
15524
  return new URLSearchParams(window.location.search).get("debug") === "1";
14951
15525
  }, [debug]);
14952
- const canUndo = (0, import_react11.useMemo)(() => document2HistoryCanUndo(historyRef.current), [historyTick, documentNode]);
14953
- const canRedo = (0, import_react11.useMemo)(() => document2HistoryCanRedo(historyRef.current), [historyTick, documentNode]);
15526
+ const canUndo = (0, import_react13.useMemo)(() => document2HistoryCanUndo(historyRef.current), [historyTick, documentNode]);
15527
+ const canRedo = (0, import_react13.useMemo)(() => document2HistoryCanRedo(historyRef.current), [historyTick, documentNode]);
14954
15528
  const blockSelection = normalizeBlockSelection(blockSelectionState.selection, documentNode.blocks.length);
14955
15529
  const selectionCount = blockSelection ? blockSelection.to - blockSelection.from + 1 : 0;
14956
15530
  const canMoveSelectionUp = Boolean(blockSelection && blockSelection.from > 0);
@@ -14992,15 +15566,15 @@ function ButexDocumentEditor2({
14992
15566
  applyDocument(removeDocument2BlockRange(documentRef.current, selection.from, selection.to), "immediate");
14993
15567
  clearBlockSelection();
14994
15568
  }
14995
- (0, import_react11.useEffect)(() => {
15569
+ (0, import_react13.useEffect)(() => {
14996
15570
  injectBuTeXDocument2Styles();
14997
15571
  }, []);
14998
- (0, import_react11.useEffect)(() => {
15572
+ (0, import_react13.useEffect)(() => {
14999
15573
  if (!editableEquations || previewOnly) {
15000
15574
  setSelectedMath(null);
15001
15575
  }
15002
15576
  }, [editableEquations, previewOnly]);
15003
- (0, import_react11.useEffect)(() => {
15577
+ (0, import_react13.useEffect)(() => {
15004
15578
  const next = resolveInitialDocument2(initialDocument, uiLocale, documentMeta);
15005
15579
  setDocumentNode(next.document);
15006
15580
  setError(next.error);
@@ -15009,13 +15583,13 @@ function ButexDocumentEditor2({
15009
15583
  historyRef.current = createDocument2History();
15010
15584
  setHistoryTick((tick) => tick + 1);
15011
15585
  }, [initialDocument, documentMeta, uiLocale]);
15012
- (0, import_react11.useEffect)(() => {
15586
+ (0, import_react13.useEffect)(() => {
15013
15587
  onDocumentChange?.(documentNode);
15014
15588
  }, [documentNode, onDocumentChange]);
15015
- (0, import_react11.useEffect)(() => {
15589
+ (0, import_react13.useEffect)(() => {
15016
15590
  onLatexChange?.(latex);
15017
15591
  }, [latex, onLatexChange]);
15018
- (0, import_react11.useEffect)(() => {
15592
+ (0, import_react13.useEffect)(() => {
15019
15593
  const pending = pendingFocusRef.current;
15020
15594
  const root = widgetRef.current;
15021
15595
  if (!pending || !root) {
@@ -15055,10 +15629,10 @@ function ButexDocumentEditor2({
15055
15629
  textarea.setSelectionRange(safeOffset, safeOffset);
15056
15630
  });
15057
15631
  }, [documentNode]);
15058
- const bumpHistoryUi = (0, import_react11.useCallback)(() => {
15632
+ const bumpHistoryUi = (0, import_react13.useCallback)(() => {
15059
15633
  setHistoryTick((tick) => tick + 1);
15060
15634
  }, []);
15061
- const applyDocument = (0, import_react11.useCallback)(
15635
+ const applyDocument = (0, import_react13.useCallback)(
15062
15636
  (next, mode = "immediate") => {
15063
15637
  if (mode === "immediate") {
15064
15638
  pushDocument2Snapshot(historyRef.current, documentRef.current);
@@ -15080,7 +15654,7 @@ function ButexDocumentEditor2({
15080
15654
  },
15081
15655
  [bumpHistoryUi]
15082
15656
  );
15083
- const afterBlockId = (0, import_react11.useCallback)(() => resolveInsertAfterBlockId(documentRef.current, editorFocus), [editorFocus]);
15657
+ const afterBlockId = (0, import_react13.useCallback)(() => resolveInsertAfterBlockId(documentRef.current, editorFocus), [editorFocus]);
15084
15658
  function undoDocument() {
15085
15659
  const restored = restoreDocument2Undo(historyRef.current, documentRef.current);
15086
15660
  if (!restored) {
@@ -15131,7 +15705,7 @@ function ButexDocumentEditor2({
15131
15705
  function openAllBlocks() {
15132
15706
  setCollapsedBlockIds(/* @__PURE__ */ new Set());
15133
15707
  }
15134
- (0, import_react11.useEffect)(() => {
15708
+ (0, import_react13.useEffect)(() => {
15135
15709
  const root = widgetRef.current;
15136
15710
  if (!root) {
15137
15711
  return;
@@ -15611,6 +16185,7 @@ function ButexDocumentEditor2({
15611
16185
  output: mathOutput,
15612
16186
  documentDirection,
15613
16187
  uiLocale,
16188
+ digitForm,
15614
16189
  resolveImageUrl
15615
16190
  }
15616
16191
  )
@@ -15640,6 +16215,9 @@ function ButexDocumentEditor2({
15640
16215
  uiLocale,
15641
16216
  labelEnabled: selectedMath.labelEnabled,
15642
16217
  label: selectedMath.label,
16218
+ labels: documentLabels,
16219
+ references: documentNode.references,
16220
+ ownerId: selectedMath.tokenId ?? void 0,
15643
16221
  onLabelEnabledChange: (enabled) => setSelectedMath((current) => current ? { ...current, labelEnabled: enabled } : current),
15644
16222
  onLabelChange: (nextLabel) => setSelectedMath((current) => current ? { ...current, label: nextLabel } : current),
15645
16223
  onMathModeChange: (mode) => setSelectedMath((current) => current ? { ...current, mathMode: mode } : current),
@@ -15655,6 +16233,7 @@ function ButexDocumentEditor2({
15655
16233
  references: documentNode.references,
15656
16234
  initialKeys: citePicker?.keys ?? [],
15657
16235
  uiLocale,
16236
+ digitForm,
15658
16237
  onClose: () => setCitePicker(null),
15659
16238
  onConfirm: confirmCiteKeys,
15660
16239
  onManageReferences: () => {
@@ -15671,6 +16250,7 @@ function ButexDocumentEditor2({
15671
16250
  initialKeys: refPicker?.keys ?? [],
15672
16251
  initialRefCommand: refPicker?.refCommand ?? "ref",
15673
16252
  uiLocale,
16253
+ digitForm,
15674
16254
  onClose: () => setRefPicker(null),
15675
16255
  onConfirm: confirmRefKeys,
15676
16256
  onManageLabels: () => {
@@ -15684,7 +16264,9 @@ function ButexDocumentEditor2({
15684
16264
  {
15685
16265
  open: referencesOpen,
15686
16266
  references: documentNode.references,
16267
+ labels: documentLabels,
15687
16268
  uiLocale,
16269
+ digitForm,
15688
16270
  onClose: () => setReferencesOpen(false),
15689
16271
  onAdd: (partial) => applyDocument(addDocument2Reference(documentRef.current, partial), "immediate"),
15690
16272
  onUpdate: (referenceId, patch) => applyDocument(updateDocument2Reference(documentRef.current, referenceId, patch), "immediate"),
@@ -15697,7 +16279,9 @@ function ButexDocumentEditor2({
15697
16279
  {
15698
16280
  open: labelsOpen,
15699
16281
  labels: documentLabels,
16282
+ references: documentNode.references,
15700
16283
  uiLocale,
16284
+ digitForm,
15701
16285
  onClose: () => setLabelsOpen(false),
15702
16286
  onUpdateFloat: (ownerId, kind, patch) => applyDocument(
15703
16287
  kind === "fig" ? updateDocument2ImageMeta(documentRef.current, ownerId, patch) : updateDocument2TableMeta(documentRef.current, ownerId, patch),