@drghaliasri/butex 5.3.0 → 5.3.2

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.
@@ -73,9 +73,11 @@ function formatDigits(value, digitForm = "western") {
73
73
  }
74
74
 
75
75
  // src/document2/articleMeta.ts
76
- var BUTEX_BASMALA_LINE1 = "\u0628\u0650\u0633\u0652\u0645\u0650 \u0627\u0644\u0644\u064E\u0651\u0647\u0650 \u0627\u0644\u0631\u064E\u0651\u062D\u0652\u0645\u064E\u0670\u0646\u0650 \u0627\u0644\u0631\u064E\u0651\u062D\u0650\u064A\u0645\u0650";
77
- var BUTEX_BASMALA_SALAWAT = "\u0635\u064E\u0644\u064E\u0651\u0649 \u0627\u0644\u0644\u064E\u0651\u0647\u064F \u0639\u064E\u0644\u064E\u064A\u0652\u0647\u0650 \u0648\u064E\u0633\u064E\u0644\u064E\u0651\u0645\u064E";
76
+ var BUTEX_BASMALA_LINE1 = "\u0628\u0650\u0633\u0652\u0645\u0650 \u0671\u0644\u0644\u064E\u0651\u0670\u0647\u0650 \u0671\u0644\u0631\u064E\u0651\u062D\u0652\u0645\u064E\u0670\u0646\u0650 \u0671\u0644\u0631\u064E\u0651\u062D\u0650\u064A\u0645\u0650";
77
+ var BUTEX_BASMALA_LINE2 = "\u0648\u064E\u0671\u0644\u0635\u064E\u0651\u0644\u064E\u0627\u0629\u064F \u0648\u064E\u0671\u0644\u0633\u064E\u0651\u0644\u064E\u0627\u0645\u064F \u0639\u064E\u0644\u064E\u0649\u0670 \u0631\u064E\u0633\u064F\u0648\u0644\u0650 \u0671\u0644\u0644\u064E\u0651\u0670\u0647\u0650";
78
+ var BUTEX_BASMALA_SALAWAT = "\u0635\u064E\u0644\u064E\u0651\u0649 \u0671\u0644\u0644\u064E\u0651\u0647\u064F \u0639\u064E\u0644\u064E\u064A\u0652\u0647\u0650 \u0648\u064E\u0633\u064E\u0644\u064E\u0651\u0645\u064E";
78
79
  var BUTEX_BASMALA = `${BUTEX_BASMALA_LINE1}
80
+ ${BUTEX_BASMALA_LINE2}
79
81
  ${BUTEX_BASMALA_SALAWAT}`;
80
82
  var BUTEX_CLOSING_HAMDALA = "\u0627\u0644\u0652\u062D\u064E\u0645\u0652\u062F\u064F \u0644\u0650\u0644\u064E\u0651\u0647\u0650 \u0646\u064E\u0641\u064E\u0639\u064E\u0646\u064E\u0627 \u0628\u0650\u0639\u0650\u0644\u0652\u0645\u0650\u0647\u0650";
81
83
  function escapeButexTextArg(text) {
@@ -89,26 +91,60 @@ function butexDiwaniDisplayLatex(text) {
89
91
  ${butexDiwaniDisplayTex(text)}
90
92
  \\]`;
91
93
  }
94
+ var BASMALA_LINES = [BUTEX_BASMALA_LINE1, BUTEX_BASMALA_LINE2, BUTEX_BASMALA_SALAWAT];
92
95
  function butexBasmalaDisplayTex() {
93
- return `${butexDiwaniDisplayTex(BUTEX_BASMALA_LINE1)} \\\\ ${butexDiwaniDisplayTex(BUTEX_BASMALA_SALAWAT)}`;
96
+ return BASMALA_LINES.map((line) => butexDiwaniDisplayTex(line)).join(" \\\\ ");
94
97
  }
95
98
  function butexBasmalaDisplayLatex() {
96
99
  return `\\[
97
100
  ${butexBasmalaDisplayTex()}
98
101
  \\]`;
99
102
  }
100
- function butexBasmalaTitlingPreamble() {
101
- return [
103
+ function butexInColumnMaketitleHook() {
104
+ return String.raw`\makeatletter
105
+ \renewcommand{\maketitle}{%
106
+ \par
107
+ \begingroup
108
+ \renewcommand\thefootnote{\@fnsymbol\c@footnote}%
109
+ \def\@makefnmark{\rlap{\@textsuperscript{\normalfont\@thefnmark}}}%
110
+ \long\def\@makefntext##1{\parindent 1em\noindent
111
+ \hb@xt@1.8em{\hss\@textsuperscript{\normalfont\@thefnmark}}##1}%
112
+ \@maketitle
113
+ \thispagestyle{plain}\@thanks
114
+ \endgroup
115
+ \setcounter{footnote}{0}%
116
+ \global\let\thanks\relax
117
+ \global\let\maketitle\relax
118
+ \global\let\@maketitle\relax
119
+ \global\let\@thanks\@empty
120
+ \global\let\@author\@empty
121
+ \global\let\@date\@empty
122
+ \global\let\@title\@empty
123
+ \global\let\title\relax
124
+ \global\let\author\relax
125
+ \global\let\date\relax
126
+ \global\let\and\relax
127
+ }
128
+ \makeatother`;
129
+ }
130
+ function butexBasmalaTitlingPreamble(options = {}) {
131
+ const lines = [
102
132
  "\\usepackage{titling}",
103
133
  "\\pretitle{%",
104
134
  " \\begin{center}",
105
- ` ${butexDiwaniDisplayTex(BUTEX_BASMALA_LINE1)}\\\\`,
106
- ` ${butexDiwaniDisplayTex(BUTEX_BASMALA_SALAWAT)}`,
135
+ ...BASMALA_LINES.map((line, index) => {
136
+ const suffix = index < BASMALA_LINES.length - 1 ? "\\\\" : "";
137
+ return ` ${butexDiwaniDisplayTex(line)}${suffix}`;
138
+ }),
107
139
  " \\par\\vspace{1.5em}",
108
140
  " \\LARGE",
109
141
  "}",
110
142
  "\\posttitle{\\par\\end{center}}"
111
- ].join("\n");
143
+ ];
144
+ if (options.twocolumn) {
145
+ lines.push(butexInColumnMaketitleHook());
146
+ }
147
+ return lines.join("\n");
112
148
  }
113
149
  var HIJRI_YEAR_MIN = 1400;
114
150
  var HIJRI_YEAR_MAX = 1500;
@@ -267,6 +303,10 @@ function cloneDocument2Meta(meta) {
267
303
  }
268
304
 
269
305
  // src/document2/citations.ts
306
+ var DEFAULT_REFERENCE_FIELD_SEPARATOR = "\u060C";
307
+ function normalizeReferenceFieldSeparator(value) {
308
+ return value === "," ? "," : DEFAULT_REFERENCE_FIELD_SEPARATOR;
309
+ }
270
310
  function referenceNumberMap(references) {
271
311
  const map = /* @__PURE__ */ new Map();
272
312
  references.forEach((reference, index) => {
@@ -312,7 +352,8 @@ function referenceFromJson(json) {
312
352
  title: typeof json.title === "string" ? json.title : "",
313
353
  year: typeof json.year === "string" ? json.year : "",
314
354
  url: typeof json.url === "string" ? json.url : "",
315
- venue: typeof json.venue === "string" ? json.venue : ""
355
+ venue: typeof json.venue === "string" ? json.venue : "",
356
+ fieldSeparator: normalizeReferenceFieldSeparator(json.field_separator)
316
357
  };
317
358
  }
318
359
  function createEmptyReference2(partial = {}) {
@@ -322,15 +363,33 @@ function createEmptyReference2(partial = {}) {
322
363
  title: partial.title,
323
364
  year: partial.year,
324
365
  url: partial.url,
325
- venue: partial.venue
366
+ venue: partial.venue,
367
+ field_separator: partial.field_separator
326
368
  });
327
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
+ }
328
375
  function bibliographyEntryLatex(reference) {
329
- const parts = [reference.authors, reference.title, reference.venue, reference.year].filter((part) => part.trim().length > 0);
330
- const body = parts.join(", ");
376
+ const body = bibliographyEntryBody(reference);
331
377
  const url = reference.url.trim().length > 0 ? ` \\url{${reference.url}}` : "";
332
378
  return `\\bibitem{${reference.key}} ${body}${url}`.trim();
333
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
+ }
334
393
 
335
394
  // src/ast/commands/index.ts
336
395
  function renderCommandCore(context) {
@@ -815,6 +874,23 @@ function labelNumberMap(document2) {
815
874
  }
816
875
  return map;
817
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
+ }
818
894
  function formatRefLabel(keys, document2, refCommand, options = {}) {
819
895
  const documentDirection = options.documentDirection ?? "rtl";
820
896
  const digitForm = options.digitForm ?? (documentDirection === "rtl" ? "arabicIndic" : "western");
@@ -1085,7 +1161,8 @@ function parseReferences(json) {
1085
1161
  title: typeof entry.title === "string" ? entry.title : void 0,
1086
1162
  year: typeof entry.year === "string" ? entry.year : void 0,
1087
1163
  url: typeof entry.url === "string" ? entry.url : void 0,
1088
- 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
1089
1166
  })
1090
1167
  );
1091
1168
  }
@@ -7232,7 +7309,7 @@ function addDocument2ImageBlock(document2, src = "", afterBlockId) {
7232
7309
  kind: "image",
7233
7310
  command: "\\includegraphics",
7234
7311
  value: src,
7235
- options: { width: "0.8\\textwidth" },
7312
+ options: { width: "0.8\\columnwidth" },
7236
7313
  ...defaultFloatMeta()
7237
7314
  };
7238
7315
  return insertDocument2BlockAfter(document2, afterBlockId, block);
@@ -7517,6 +7594,9 @@ function updateDocument2Reference(document2, referenceId, patch) {
7517
7594
  if (typeof patch.venue === "string") {
7518
7595
  reference.venue = patch.venue;
7519
7596
  }
7597
+ if (patch.field_separator === "," || patch.field_separator === "\u060C") {
7598
+ reference.fieldSeparator = patch.field_separator;
7599
+ }
7520
7600
  return next;
7521
7601
  }
7522
7602
  function removeDocument2Reference(document2, referenceId) {
@@ -7550,6 +7630,48 @@ function updateDocument2Meta(document2, patch) {
7550
7630
  return next;
7551
7631
  }
7552
7632
 
7633
+ // src/document2/keys.ts
7634
+ var DOCUMENT2_KEY_PATTERN = /^[\p{L}\p{M}0-9:._-]+$/u;
7635
+ function normalizeDocument2Key(key) {
7636
+ return key.normalize("NFC").trim();
7637
+ }
7638
+ function isDuplicateDocument2Key(key, namespace) {
7639
+ const normalized = normalizeDocument2Key(key);
7640
+ if (normalized.length === 0) {
7641
+ return false;
7642
+ }
7643
+ for (const reference of namespace.references ?? []) {
7644
+ if (namespace.excludeReferenceId && reference.id === namespace.excludeReferenceId) {
7645
+ continue;
7646
+ }
7647
+ if (normalizeDocument2Key(reference.key) === normalized) {
7648
+ return true;
7649
+ }
7650
+ }
7651
+ for (const label of namespace.labels ?? []) {
7652
+ if (namespace.excludeOwnerId && label.ownerId === namespace.excludeOwnerId) {
7653
+ continue;
7654
+ }
7655
+ if (normalizeDocument2Key(label.key) === normalized) {
7656
+ return true;
7657
+ }
7658
+ }
7659
+ return false;
7660
+ }
7661
+ function document2KeyError(key, namespace = {}) {
7662
+ const normalized = normalizeDocument2Key(key);
7663
+ if (normalized.length === 0) {
7664
+ return "empty";
7665
+ }
7666
+ if (!DOCUMENT2_KEY_PATTERN.test(normalized)) {
7667
+ return "invalid";
7668
+ }
7669
+ if (isDuplicateDocument2Key(normalized, namespace)) {
7670
+ return "duplicate";
7671
+ }
7672
+ return null;
7673
+ }
7674
+
7553
7675
  // src/document2/arabicPreamble.ts
7554
7676
  function arabicXeLatexPreamblePkg(twocolumn = false) {
7555
7677
  const classOptions = twocolumn ? "12pt,a4paper,notitlepage,twocolumn" : "12pt,a4paper,notitlepage";
@@ -7832,8 +7954,16 @@ function tableBlockLatex(block) {
7832
7954
  lines.push("\\end{table}");
7833
7955
  return lines.join("\n");
7834
7956
  }
7835
- function imageOptionsLatex(block) {
7836
- const entries = Object.entries(block.options);
7957
+ function remapImageWidthForColumns(value) {
7958
+ return value.replace(/\\textwidth\b/g, "\\columnwidth");
7959
+ }
7960
+ function imageOptionsLatex(block, constrainToColumn) {
7961
+ const entries = Object.entries(block.options).map(([key, value]) => {
7962
+ if (constrainToColumn && key === "width") {
7963
+ return [key, remapImageWidthForColumns(value)];
7964
+ }
7965
+ return [key, value];
7966
+ });
7837
7967
  if (entries.length === 0) {
7838
7968
  return "";
7839
7969
  }
@@ -7844,7 +7974,7 @@ function imageBlockLatex(block) {
7844
7974
  if (block.centered) {
7845
7975
  lines.push(" \\centering");
7846
7976
  }
7847
- lines.push(` ${block.command}${imageOptionsLatex(block)}{${block.value}}`);
7977
+ lines.push(` ${block.command}${imageOptionsLatex(block, true)}{${block.value}}`);
7848
7978
  lines.push(...floatCaptionLabelLines(block));
7849
7979
  lines.push("\\end{figure}");
7850
7980
  return lines.join("\n");
@@ -7874,11 +8004,11 @@ ${block.closing}`;
7874
8004
  function authorLatex(authors) {
7875
8005
  return authors.split(/\n+/).map((line) => line.trim()).filter((line) => line.length > 0).join(" \\\\ ");
7876
8006
  }
7877
- function articleMaketitlePreamble(meta) {
8007
+ function articleMaketitlePreamble(meta, twocolumn = false) {
7878
8008
  if (!document2HasMaketitle(meta)) {
7879
8009
  return "";
7880
8010
  }
7881
- const parts = [butexBasmalaTitlingPreamble()];
8011
+ const parts = [butexBasmalaTitlingPreamble({ twocolumn })];
7882
8012
  if (meta.title.trim().length > 0) {
7883
8013
  parts.push(`\\title{${meta.title.trim()}}`);
7884
8014
  }
@@ -7904,21 +8034,22 @@ ${meta.abstract.trim()}
7904
8034
  }
7905
8035
  function document2Latex(document2, options = {}) {
7906
8036
  const meta = document2.meta ?? emptyDocument2Meta();
8037
+ const twocolumn = options.twocolumn === true;
7907
8038
  const front = articleFrontMatterLatex(meta);
7908
8039
  const bodyBlocks = document2.blocks.map((block) => blockLatex(block, document2.references));
7909
8040
  const closing = butexDiwaniDisplayLatex(BUTEX_CLOSING_HAMDALA);
7910
8041
  const body = [...front, ...bodyBlocks, closing].filter((part) => part.length > 0).join("\n\n");
7911
8042
  const wrapDocument = options.wrapDocument !== false;
7912
8043
  if (!wrapDocument) {
7913
- const metaPreamble = articleMaketitlePreamble(meta);
8044
+ const metaPreamble = articleMaketitlePreamble(meta, twocolumn);
7914
8045
  return metaPreamble.length > 0 ? `${metaPreamble}
7915
8046
 
7916
8047
  ${body}` : body;
7917
8048
  }
7918
8049
  const preamble = getArabicXeLatexPreamble({
7919
8050
  digitsMapping: options.digitsMapping ?? "arabicdigits",
7920
- twocolumn: options.twocolumn === true
7921
- }) + "\n" + articleMaketitlePreamble(meta);
8051
+ twocolumn
8052
+ }) + "\n" + articleMaketitlePreamble(meta, twocolumn);
7922
8053
  return `${preamble}
7923
8054
  \\begin{document}
7924
8055
 
@@ -8091,13 +8222,11 @@ function floatNumberLabel(document2, key, previewOptions) {
8091
8222
  if (!hit || hit.kind !== "fig" && hit.kind !== "tab") {
8092
8223
  return void 0;
8093
8224
  }
8094
- const locale = previewOptions.uiLocale ?? "ar";
8095
- const kindWord = hit.kind === "fig" ? locale === "ar" ? "\u0627\u0644\u0634\u0643\u0644" : "Figure" : locale === "ar" ? "\u0627\u0644\u062C\u062F\u0648\u0644" : "Table";
8096
- const digits = formatBibliographyNumber(hit.number, {
8225
+ return formatFloatCaptionTitle(hit.kind, hit.number, {
8226
+ uiLocale: previewOptions.uiLocale ?? "ar",
8097
8227
  documentDirection: previewOptions.documentDirection,
8098
8228
  digitForm: previewOptions.digitForm
8099
8229
  });
8100
- return `${kindWord} ${digits}`;
8101
8230
  }
8102
8231
  function blockPreview(block, islands, output, equationSide, document2, previewOptions) {
8103
8232
  if (block.kind === "textBlock") {
@@ -8152,7 +8281,8 @@ function blockPreview(block, islands, output, equationSide, document2, previewOp
8152
8281
  title: reference.title,
8153
8282
  year: reference.year,
8154
8283
  url: reference.url,
8155
- venue: reference.venue
8284
+ venue: reference.venue,
8285
+ fieldSeparator: reference.fieldSeparator
8156
8286
  }))
8157
8287
  };
8158
8288
  }
@@ -8303,6 +8433,15 @@ var DOCUMENT2_MESSAGES = {
8303
8433
  labelKindFig: "\u0634\u0643\u0644",
8304
8434
  labelKindTab: "\u062C\u062F\u0648\u0644",
8305
8435
  labelKindEq: "\u0645\u0639\u0627\u062F\u0644\u0629",
8436
+ captionPreview: "\u0645\u0639\u0627\u064A\u0646\u0629 \u0627\u0644\u062A\u0639\u0644\u064A\u0642",
8437
+ referencePreview: "\u0645\u0639\u0627\u064A\u0646\u0629 \u0627\u0644\u0645\u0631\u062C\u0639",
8438
+ referenceFieldSeparator: "\u0641\u0627\u0635\u0644 \u0627\u0644\u062D\u0642\u0648\u0644",
8439
+ referenceCommaLtr: "\u0641\u0627\u0635\u0644\u0629 \u0625\u0646\u062C\u0644\u064A\u0632\u064A\u0629 ,",
8440
+ referenceCommaRtl: "\u0641\u0627\u0635\u0644\u0629 \u0639\u0631\u0628\u064A\u0629 \u060C",
8441
+ keyEmpty: "\u0627\u0644\u0645\u0641\u062A\u0627\u062D \u0645\u0637\u0644\u0648\u0628",
8442
+ 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",
8443
+ keyDuplicate: "\u0647\u0630\u0627 \u0627\u0644\u0645\u0641\u062A\u0627\u062D \u0645\u0633\u062A\u062E\u062F\u0645 \u0645\u0633\u0628\u0642\u0627\u064B",
8444
+ 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",
8306
8445
  citePickerTitle: "\u0627\u062E\u062A\u064A\u0627\u0631 \u0627\u0644\u0645\u0631\u0627\u062C\u0639",
8307
8446
  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.",
8308
8447
  editCitation: "\u062A\u062D\u0631\u064A\u0631 \u0627\u0644\u0627\u0642\u062A\u0628\u0627\u0633",
@@ -8433,6 +8572,15 @@ var DOCUMENT2_MESSAGES = {
8433
8572
  labelKindFig: "Figure",
8434
8573
  labelKindTab: "Table",
8435
8574
  labelKindEq: "Equation",
8575
+ captionPreview: "Caption preview",
8576
+ referencePreview: "Reference preview",
8577
+ referenceFieldSeparator: "Field separator",
8578
+ referenceCommaLtr: "Latin comma ,",
8579
+ referenceCommaRtl: "Arabic comma \u060C",
8580
+ keyEmpty: "Key is required",
8581
+ keyInvalid: "Invalid key: letters, digits, and `:._-` only; no spaces",
8582
+ keyDuplicate: "This key is already in use",
8583
+ keyRulesHint: "Letters (Arabic or Latin), digits, and `:._-`; no spaces",
8436
8584
  citePickerTitle: "Select references",
8437
8585
  noReferencesYet: "No references yet. Add a reference first.",
8438
8586
  editCitation: "Edit citation",
@@ -8563,6 +8711,8 @@ function ArticleMetaPanel({
8563
8711
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "butex-document2-widget__article-meta-fixed", dir: "rtl", children: [
8564
8712
  BUTEX_BASMALA_LINE1,
8565
8713
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}),
8714
+ BUTEX_BASMALA_LINE2,
8715
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}),
8566
8716
  BUTEX_BASMALA_SALAWAT
8567
8717
  ] }),
8568
8718
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "butex-document2-widget__article-meta-grid", children: [
@@ -8668,7 +8818,10 @@ function focusArticleMetaPanel(panel) {
8668
8818
  }
8669
8819
 
8670
8820
  // src/react-document2/ButexDocumentEditor2.tsx
8671
- var import_react11 = require("react");
8821
+ var import_react13 = require("react");
8822
+
8823
+ // src/react-document2/BlockEditor.tsx
8824
+ var import_react4 = require("react");
8672
8825
 
8673
8826
  // src/react-document2/InlineField.tsx
8674
8827
  var import_react3 = require("react");
@@ -9705,6 +9858,18 @@ function inlineFieldSummary(field) {
9705
9858
  }).join("")
9706
9859
  );
9707
9860
  }
9861
+ function keyErrorMessage(error, messages) {
9862
+ if (error === "empty") {
9863
+ return messages.keyEmpty;
9864
+ }
9865
+ if (error === "invalid") {
9866
+ return messages.keyInvalid;
9867
+ }
9868
+ if (error === "duplicate") {
9869
+ return messages.keyDuplicate;
9870
+ }
9871
+ return null;
9872
+ }
9708
9873
  function FloatMetaEditor({
9709
9874
  captionEnabled,
9710
9875
  caption,
@@ -9713,8 +9878,18 @@ function FloatMetaEditor({
9713
9878
  labelPlaceholder,
9714
9879
  labelDir,
9715
9880
  messages,
9881
+ ownerId,
9882
+ references,
9883
+ labels,
9716
9884
  onChange
9717
9885
  }) {
9886
+ const [labelOverride, setLabelOverride] = (0, import_react4.useState)(null);
9887
+ const displayedLabel = labelOverride ?? label;
9888
+ const labelError = labelEnabled ? document2KeyError(displayedLabel, {
9889
+ references,
9890
+ labels,
9891
+ excludeOwnerId: ownerId
9892
+ }) : null;
9718
9893
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "butex-document2-widget__float-meta", children: [
9719
9894
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "butex-document2-widget__float-meta-toggle", children: [
9720
9895
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
@@ -9764,15 +9939,27 @@ function FloatMetaEditor({
9764
9939
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
9765
9940
  "input",
9766
9941
  {
9767
- value: label,
9942
+ value: displayedLabel,
9768
9943
  dir: labelDir,
9769
9944
  placeholder: labelPlaceholder,
9945
+ "aria-invalid": labelError !== null ? true : void 0,
9770
9946
  onChange: (event) => {
9771
9947
  const value = event.currentTarget.value;
9948
+ setLabelOverride(value);
9949
+ const error = document2KeyError(value, {
9950
+ references,
9951
+ labels,
9952
+ excludeOwnerId: ownerId
9953
+ });
9954
+ if (error !== null) {
9955
+ return;
9956
+ }
9772
9957
  onChange({ label: value });
9958
+ setLabelOverride(null);
9773
9959
  }
9774
9960
  }
9775
- )
9961
+ ),
9962
+ labelError !== null ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "butex-document2-widget__field-error", children: labelError === "invalid" ? messages.keyRulesHint : keyErrorMessage(labelError, messages) }) : null
9776
9963
  ] }) : null
9777
9964
  ] });
9778
9965
  }
@@ -9831,6 +10018,8 @@ function BlockEditor({
9831
10018
  onManageReferences
9832
10019
  }) {
9833
10020
  const messages = document2Messages(uiLocale);
10021
+ const labels = documentNode ? collectDocument2Labels(documentNode) : [];
10022
+ const referenceList = references ?? [];
9834
10023
  const showChrome = depth === 0;
9835
10024
  const chromeClass = [
9836
10025
  blockChromeClass(block),
@@ -9993,6 +10182,9 @@ function BlockEditor({
9993
10182
  labelPlaceholder: messages.tableLabelPlaceholder,
9994
10183
  labelDir: uiLocaleDirection(uiLocale),
9995
10184
  messages,
10185
+ ownerId: block.id,
10186
+ references: referenceList,
10187
+ labels,
9996
10188
  onChange: (patch) => onFloatMetaChange?.(block.id, "table", patch)
9997
10189
  }
9998
10190
  )
@@ -10036,6 +10228,9 @@ function BlockEditor({
10036
10228
  labelPlaceholder: messages.figureLabelPlaceholder,
10037
10229
  labelDir: uiLocaleDirection(uiLocale),
10038
10230
  messages,
10231
+ ownerId: block.id,
10232
+ references: referenceList,
10233
+ labels,
10039
10234
  onChange: (patch) => onFloatMetaChange?.(block.id, "image", patch)
10040
10235
  }
10041
10236
  )
@@ -10044,14 +10239,16 @@ function BlockEditor({
10044
10239
  if (block.kind === "bibliography") {
10045
10240
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("section", { className: chromeClass, children: [
10046
10241
  header,
10047
- /* @__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: [
10242
+ /* @__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: [
10048
10243
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("strong", { children: [
10049
10244
  "[",
10050
- index + 1,
10245
+ formatBibliographyNumber(index + 1, { documentDirection, digitForm }),
10051
10246
  "] ",
10052
10247
  reference.key
10053
10248
  ] }),
10054
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: [reference.authors, reference.title, reference.venue, reference.year].filter(Boolean).join(" \u2014 ") })
10249
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: bibliographyEntryBody(reference, reference.fieldSeparator, {
10250
+ digitForm: digitForm ?? (documentDirection === "rtl" ? "arabicIndic" : "western")
10251
+ }) })
10055
10252
  ] }, reference.id)) }),
10056
10253
  onManageReferences ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", onClick: onManageReferences, children: messages.manageReferences }) : null
10057
10254
  ] });
@@ -10063,20 +10260,22 @@ function BlockEditor({
10063
10260
  }
10064
10261
 
10065
10262
  // src/react-document2/CitePickerPopover.tsx
10066
- var import_react4 = require("react");
10263
+ var import_react5 = require("react");
10067
10264
  var import_jsx_runtime8 = require("react/jsx-runtime");
10068
10265
  function CitePickerPopover({
10069
10266
  open,
10070
10267
  references,
10071
10268
  initialKeys = [],
10072
10269
  uiLocale = "ar",
10270
+ digitForm = "arabicIndic",
10073
10271
  onClose,
10074
10272
  onConfirm,
10075
10273
  onManageReferences
10076
10274
  }) {
10077
10275
  const messages = document2Messages(uiLocale);
10078
- const [selected, setSelected] = (0, import_react4.useState)(initialKeys);
10079
- (0, import_react4.useEffect)(() => {
10276
+ const documentDirection = uiLocale === "ar" ? "rtl" : "ltr";
10277
+ const [selected, setSelected] = (0, import_react5.useState)(initialKeys);
10278
+ (0, import_react5.useEffect)(() => {
10080
10279
  if (open) {
10081
10280
  setSelected(initialKeys);
10082
10281
  }
@@ -10102,12 +10301,13 @@ function CitePickerPopover({
10102
10301
  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) => {
10103
10302
  const checked = selected.includes(reference.key);
10104
10303
  const subtitle = [reference.authors, reference.title].filter(Boolean).join(" \u2014 ");
10304
+ const numberLabel = formatBibliographyNumber(index + 1, { documentDirection, digitForm });
10105
10305
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "butex-document2-widget__cite-picker-item", children: [
10106
10306
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("input", { type: "checkbox", checked, onChange: () => toggleKey(reference.key) }),
10107
10307
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { children: [
10108
10308
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("strong", { children: [
10109
10309
  "[",
10110
- index + 1,
10310
+ numberLabel,
10111
10311
  "] ",
10112
10312
  reference.key
10113
10313
  ] }),
@@ -10135,18 +10335,18 @@ function CitePickerPopover({
10135
10335
  }
10136
10336
 
10137
10337
  // src/react-document2/DocumentInsertToolbar.tsx
10138
- var import_react6 = require("react");
10338
+ var import_react7 = require("react");
10139
10339
 
10140
10340
  // src/react-document2/TableInsertPopover.tsx
10141
- var import_react5 = require("react");
10341
+ var import_react6 = require("react");
10142
10342
  var import_jsx_runtime9 = require("react/jsx-runtime");
10143
10343
  function TableInsertPopover({ uiLocale = "ar", onConfirm }) {
10144
10344
  const messages = document2Messages(uiLocale);
10145
- const [open, setOpen] = (0, import_react5.useState)(false);
10146
- const [rows, setRows] = (0, import_react5.useState)("3");
10147
- const [cols, setCols] = (0, import_react5.useState)("3");
10148
- const rootRef = (0, import_react5.useRef)(null);
10149
- (0, import_react5.useEffect)(() => {
10345
+ const [open, setOpen] = (0, import_react6.useState)(false);
10346
+ const [rows, setRows] = (0, import_react6.useState)("3");
10347
+ const [cols, setCols] = (0, import_react6.useState)("3");
10348
+ const rootRef = (0, import_react6.useRef)(null);
10349
+ (0, import_react6.useEffect)(() => {
10150
10350
  if (!open) {
10151
10351
  return;
10152
10352
  }
@@ -10237,7 +10437,7 @@ function DocumentInsertToolbar({
10237
10437
  onDigitFormChange
10238
10438
  }) {
10239
10439
  const messages = document2Messages(uiLocale);
10240
- const [digitMenuOpen, setDigitMenuOpen] = (0, import_react6.useState)(false);
10440
+ const [digitMenuOpen, setDigitMenuOpen] = (0, import_react7.useState)(false);
10241
10441
  function digitTitle(id) {
10242
10442
  if (id === "arabicIndic") {
10243
10443
  return messages.arabicIndicDigits;
@@ -10408,7 +10608,8 @@ function PreviewBlock({
10408
10608
  output,
10409
10609
  resolveImageUrl,
10410
10610
  uiLocale,
10411
- documentDirection
10611
+ documentDirection,
10612
+ digitForm
10412
10613
  }) {
10413
10614
  const messages = document2Messages(uiLocale);
10414
10615
  const floatCaptionSeparator = uiLocale === "ar" ? ": " : ". ";
@@ -10467,7 +10668,8 @@ function PreviewBlock({
10467
10668
  output,
10468
10669
  resolveImageUrl,
10469
10670
  uiLocale,
10470
- documentDirection
10671
+ documentDirection,
10672
+ digitForm
10471
10673
  },
10472
10674
  child.id
10473
10675
  ))
@@ -10497,10 +10699,10 @@ function PreviewBlock({
10497
10699
  ] }),
10498
10700
  " ",
10499
10701
  /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { children: [
10500
- [item.authors, item.title, item.venue, item.year].filter(Boolean).join(", "),
10702
+ bibliographyEntryBody(item, item.fieldSeparator, { digitForm }),
10501
10703
  item.url ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
10502
10704
  " ",
10503
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("a", { href: item.url, target: "_blank", rel: "noreferrer", children: item.url })
10705
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("a", { href: absoluteHttpHref(item.url), target: "_blank", rel: "noreferrer", children: item.url })
10504
10706
  ] }) : null
10505
10707
  ] })
10506
10708
  ] }, item.id)) });
@@ -10512,9 +10714,11 @@ function DocumentPreview({
10512
10714
  output,
10513
10715
  documentDirection = "rtl",
10514
10716
  uiLocale = "ar",
10717
+ digitForm,
10515
10718
  resolveImageUrl
10516
10719
  }) {
10517
10720
  const messages = document2Messages(uiLocale);
10721
+ const resolvedDigitForm = digitForm ?? (documentDirection === "rtl" ? "arabicIndic" : "western");
10518
10722
  const hasBody = blocks.some(isBodyPreviewBlock);
10519
10723
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "butex-document2-widget__preview", dir: documentDirection, children: [
10520
10724
  blocks.map((block) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
@@ -10524,7 +10728,8 @@ function DocumentPreview({
10524
10728
  output,
10525
10729
  resolveImageUrl,
10526
10730
  uiLocale,
10527
- documentDirection
10731
+ documentDirection,
10732
+ digitForm: resolvedDigitForm
10528
10733
  },
10529
10734
  block.id
10530
10735
  )),
@@ -10533,10 +10738,10 @@ function DocumentPreview({
10533
10738
  }
10534
10739
 
10535
10740
  // src/react-document2/EquationDrawer.tsx
10536
- var import_react8 = require("react");
10741
+ var import_react9 = require("react");
10537
10742
 
10538
10743
  // src/react/ButexEditor.tsx
10539
- var import_react7 = require("react");
10744
+ var import_react8 = require("react");
10540
10745
 
10541
10746
  // src/react/widgetChromeCss.ts
10542
10747
  var WIDGET_CHROME_CSS = `
@@ -11582,61 +11787,61 @@ function passiveTreeText(session, messages) {
11582
11787
 
11583
11788
  ${latex || messages.empty}`;
11584
11789
  }
11585
- var ButexEditor = (0, import_react7.forwardRef)(
11790
+ var ButexEditor = (0, import_react8.forwardRef)(
11586
11791
  function ButexEditor2({ className, debug = false, defaultSide, uiLocale = "ar", initialSession, onSessionChange }, ref) {
11587
11792
  const messages = equationEditorMessages(uiLocale);
11588
- const wrapperRef = (0, import_react7.useRef)(null);
11589
- const surfaceRef = (0, import_react7.useRef)(null);
11590
- const mathOutputRef = (0, import_react7.useRef)(null);
11591
- const renderErrorRef = (0, import_react7.useRef)(null);
11592
- const latexLinesRef = (0, import_react7.useRef)(null);
11593
- const passivePreviewRef = (0, import_react7.useRef)(null);
11594
- const debugLogRef = (0, import_react7.useRef)(null);
11595
- const undoBtnRef = (0, import_react7.useRef)(null);
11596
- const redoBtnRef = (0, import_react7.useRef)(null);
11597
- const copyBtnRef = (0, import_react7.useRef)(null);
11598
- const cutBtnRef = (0, import_react7.useRef)(null);
11599
- const splitTypingBtnRef = (0, import_react7.useRef)(null);
11600
- const characterFontBtnRef = (0, import_react7.useRef)(null);
11601
- const digitFormBtnRef = (0, import_react7.useRef)(null);
11602
- const runtimeRef = (0, import_react7.useRef)(null);
11603
- const debugRef = (0, import_react7.useRef)(debug);
11793
+ const wrapperRef = (0, import_react8.useRef)(null);
11794
+ const surfaceRef = (0, import_react8.useRef)(null);
11795
+ const mathOutputRef = (0, import_react8.useRef)(null);
11796
+ const renderErrorRef = (0, import_react8.useRef)(null);
11797
+ const latexLinesRef = (0, import_react8.useRef)(null);
11798
+ const passivePreviewRef = (0, import_react8.useRef)(null);
11799
+ const debugLogRef = (0, import_react8.useRef)(null);
11800
+ const undoBtnRef = (0, import_react8.useRef)(null);
11801
+ const redoBtnRef = (0, import_react8.useRef)(null);
11802
+ const copyBtnRef = (0, import_react8.useRef)(null);
11803
+ const cutBtnRef = (0, import_react8.useRef)(null);
11804
+ const splitTypingBtnRef = (0, import_react8.useRef)(null);
11805
+ const characterFontBtnRef = (0, import_react8.useRef)(null);
11806
+ const digitFormBtnRef = (0, import_react8.useRef)(null);
11807
+ const runtimeRef = (0, import_react8.useRef)(null);
11808
+ const debugRef = (0, import_react8.useRef)(debug);
11604
11809
  debugRef.current = debug;
11605
- const uiLocaleRef = (0, import_react7.useRef)(uiLocale);
11810
+ const uiLocaleRef = (0, import_react8.useRef)(uiLocale);
11606
11811
  uiLocaleRef.current = uiLocale;
11607
- const onSessionChangeRef = (0, import_react7.useRef)(onSessionChange);
11812
+ const onSessionChangeRef = (0, import_react8.useRef)(onSessionChange);
11608
11813
  onSessionChangeRef.current = onSessionChange;
11609
- const debugBodyHiddenRef = (0, import_react7.useRef)(false);
11610
- const [debugBodyHidden, setDebugBodyHidden] = (0, import_react7.useState)(false);
11814
+ const debugBodyHiddenRef = (0, import_react8.useRef)(false);
11815
+ const [debugBodyHidden, setDebugBodyHidden] = (0, import_react8.useState)(false);
11611
11816
  debugBodyHiddenRef.current = debugBodyHidden;
11612
- const [digitMenuOpen, setDigitMenuOpen] = (0, import_react7.useState)(false);
11613
- const [characterFontMenuOpen, setCharacterFontMenuOpen] = (0, import_react7.useState)(false);
11614
- const [delimiterMenuOpen, setDelimiterMenuOpen] = (0, import_react7.useState)(false);
11615
- const [matrixMenuOpen, setMatrixMenuOpen] = (0, import_react7.useState)(false);
11616
- const [spacingMenuOpen, setSpacingMenuOpen] = (0, import_react7.useState)(false);
11617
- const [functionMenuOpen, setFunctionMenuOpen] = (0, import_react7.useState)(false);
11618
- const [limitsSeriesMenuOpen, setLimitsSeriesMenuOpen] = (0, import_react7.useState)(false);
11619
- const [function2MenuOpen, setFunction2MenuOpen] = (0, import_react7.useState)(false);
11620
- const [derivativeMenuOpen, setDerivativeMenuOpen] = (0, import_react7.useState)(false);
11621
- const [groupMenuOpen, setGroupMenuOpen] = (0, import_react7.useState)(false);
11622
- const [operatorMenuOpen, setOperatorMenuOpen] = (0, import_react7.useState)(false);
11623
- const [operator2MenuOpen, setOperator2MenuOpen] = (0, import_react7.useState)(false);
11624
- const [operator3MenuOpen, setOperator3MenuOpen] = (0, import_react7.useState)(false);
11625
- const [dotMenuOpen, setDotMenuOpen] = (0, import_react7.useState)(false);
11626
- const [integralMenuOpen, setIntegralMenuOpen] = (0, import_react7.useState)(false);
11627
- const [selectedDigitForm2, setSelectedDigitForm] = (0, import_react7.useState)("western");
11628
- const [selectedCharacterFont, setSelectedCharacterFont] = (0, import_react7.useState)("default");
11629
- const [activeEditorSide, setActiveEditorSide] = (0, import_react7.useState)("arabic");
11630
- const [envPaletteMode, setEnvPaletteMode] = (0, import_react7.useState)("matrix");
11631
- const [matrixStyle, setMatrixStyle] = (0, import_react7.useState)("pmatrix");
11632
- const [matrixRows, setMatrixRows] = (0, import_react7.useState)(2);
11633
- const [matrixColumns, setMatrixColumns] = (0, import_react7.useState)(2);
11634
- const [matrixHover, setMatrixHover] = (0, import_react7.useState)(null);
11635
- const [arrayAlignmentColumn, setArrayAlignmentColumn] = (0, import_react7.useState)(1);
11636
- (0, import_react7.useImperativeHandle)(ref, () => ({
11817
+ const [digitMenuOpen, setDigitMenuOpen] = (0, import_react8.useState)(false);
11818
+ const [characterFontMenuOpen, setCharacterFontMenuOpen] = (0, import_react8.useState)(false);
11819
+ const [delimiterMenuOpen, setDelimiterMenuOpen] = (0, import_react8.useState)(false);
11820
+ const [matrixMenuOpen, setMatrixMenuOpen] = (0, import_react8.useState)(false);
11821
+ const [spacingMenuOpen, setSpacingMenuOpen] = (0, import_react8.useState)(false);
11822
+ const [functionMenuOpen, setFunctionMenuOpen] = (0, import_react8.useState)(false);
11823
+ const [limitsSeriesMenuOpen, setLimitsSeriesMenuOpen] = (0, import_react8.useState)(false);
11824
+ const [function2MenuOpen, setFunction2MenuOpen] = (0, import_react8.useState)(false);
11825
+ const [derivativeMenuOpen, setDerivativeMenuOpen] = (0, import_react8.useState)(false);
11826
+ const [groupMenuOpen, setGroupMenuOpen] = (0, import_react8.useState)(false);
11827
+ const [operatorMenuOpen, setOperatorMenuOpen] = (0, import_react8.useState)(false);
11828
+ const [operator2MenuOpen, setOperator2MenuOpen] = (0, import_react8.useState)(false);
11829
+ const [operator3MenuOpen, setOperator3MenuOpen] = (0, import_react8.useState)(false);
11830
+ const [dotMenuOpen, setDotMenuOpen] = (0, import_react8.useState)(false);
11831
+ const [integralMenuOpen, setIntegralMenuOpen] = (0, import_react8.useState)(false);
11832
+ const [selectedDigitForm2, setSelectedDigitForm] = (0, import_react8.useState)("western");
11833
+ const [selectedCharacterFont, setSelectedCharacterFont] = (0, import_react8.useState)("default");
11834
+ const [activeEditorSide, setActiveEditorSide] = (0, import_react8.useState)("arabic");
11835
+ const [envPaletteMode, setEnvPaletteMode] = (0, import_react8.useState)("matrix");
11836
+ const [matrixStyle, setMatrixStyle] = (0, import_react8.useState)("pmatrix");
11837
+ const [matrixRows, setMatrixRows] = (0, import_react8.useState)(2);
11838
+ const [matrixColumns, setMatrixColumns] = (0, import_react8.useState)(2);
11839
+ const [matrixHover, setMatrixHover] = (0, import_react8.useState)(null);
11840
+ const [arrayAlignmentColumn, setArrayAlignmentColumn] = (0, import_react8.useState)(1);
11841
+ (0, import_react8.useImperativeHandle)(ref, () => ({
11637
11842
  getRuntime: () => runtimeRef.current
11638
11843
  }));
11639
- const updatePreview = (0, import_react7.useCallback)(async (session) => {
11844
+ const updatePreview = (0, import_react8.useCallback)(async (session) => {
11640
11845
  const mathOutputEl = mathOutputRef.current;
11641
11846
  const renderErrorEl = renderErrorRef.current;
11642
11847
  const latexLinesEl = latexLinesRef.current;
@@ -11686,9 +11891,9 @@ ${arabic || currentMessages.empty}`;
11686
11891
  }
11687
11892
  }
11688
11893
  }, []);
11689
- const updatePreviewRef = (0, import_react7.useRef)(updatePreview);
11894
+ const updatePreviewRef = (0, import_react8.useRef)(updatePreview);
11690
11895
  updatePreviewRef.current = updatePreview;
11691
- (0, import_react7.useEffect)(() => {
11896
+ (0, import_react8.useEffect)(() => {
11692
11897
  injectWidgetChromeCss();
11693
11898
  injectBuTeXEditorStyles(typeof document !== "undefined" ? document : void 0);
11694
11899
  const surfaceEl = surfaceRef.current;
@@ -11744,7 +11949,7 @@ ${arabic || currentMessages.empty}`;
11744
11949
  runtimeRef.current = null;
11745
11950
  };
11746
11951
  }, []);
11747
- (0, import_react7.useEffect)(() => {
11952
+ (0, import_react8.useEffect)(() => {
11748
11953
  runtimeRef.current?.setUiLocale(uiLocale);
11749
11954
  const session = runtimeRef.current?.getSession();
11750
11955
  if (session) {
@@ -12817,6 +13022,18 @@ ButexEditor.displayName = "ButexEditor";
12817
13022
 
12818
13023
  // src/react-document2/EquationDrawer.tsx
12819
13024
  var import_jsx_runtime13 = require("react/jsx-runtime");
13025
+ function keyErrorMessage2(error, messages) {
13026
+ if (error === "empty") {
13027
+ return messages.keyEmpty;
13028
+ }
13029
+ if (error === "invalid") {
13030
+ return messages.keyInvalid;
13031
+ }
13032
+ if (error === "duplicate") {
13033
+ return messages.keyDuplicate;
13034
+ }
13035
+ return null;
13036
+ }
12820
13037
  function EquationDrawer({
12821
13038
  session,
12822
13039
  reason,
@@ -12826,6 +13043,9 @@ function EquationDrawer({
12826
13043
  uiLocale = "ar",
12827
13044
  labelEnabled = false,
12828
13045
  label = "",
13046
+ labels = [],
13047
+ references = [],
13048
+ ownerId = "",
12829
13049
  onLabelEnabledChange,
12830
13050
  onLabelChange,
12831
13051
  onMathModeChange,
@@ -12834,8 +13054,18 @@ function EquationDrawer({
12834
13054
  onDelete
12835
13055
  }) {
12836
13056
  const messages = document2Messages(uiLocale);
12837
- const latestSession = (0, import_react8.useRef)(session);
12838
- (0, import_react8.useEffect)(() => {
13057
+ const latestSession = (0, import_react9.useRef)(session);
13058
+ const [labelOverride, setLabelOverride] = (0, import_react9.useState)(null);
13059
+ const displayedLabel = labelOverride ?? label;
13060
+ const labelError = labelEnabled && mathMode === "display" ? document2KeyError(displayedLabel, {
13061
+ references,
13062
+ labels,
13063
+ excludeOwnerId: ownerId || void 0
13064
+ }) : null;
13065
+ (0, import_react9.useEffect)(() => {
13066
+ setLabelOverride(null);
13067
+ }, [ownerId, label]);
13068
+ (0, import_react9.useEffect)(() => {
12839
13069
  const onKeyDown = (event) => {
12840
13070
  if (event.key === "Escape") {
12841
13071
  onClose();
@@ -12895,12 +13125,27 @@ function EquationDrawer({
12895
13125
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
12896
13126
  "input",
12897
13127
  {
12898
- value: label,
13128
+ value: displayedLabel,
12899
13129
  dir: uiLocaleDirection(uiLocale),
12900
13130
  placeholder: messages.equationLabelPlaceholder,
12901
- onChange: (event) => onLabelChange?.(event.currentTarget.value)
13131
+ "aria-invalid": labelError !== null ? true : void 0,
13132
+ onChange: (event) => {
13133
+ const value = event.currentTarget.value;
13134
+ setLabelOverride(value);
13135
+ const error = document2KeyError(value, {
13136
+ references,
13137
+ labels,
13138
+ excludeOwnerId: ownerId || void 0
13139
+ });
13140
+ if (error !== null) {
13141
+ return;
13142
+ }
13143
+ onLabelChange?.(value);
13144
+ setLabelOverride(null);
13145
+ }
12902
13146
  }
12903
- )
13147
+ ),
13148
+ labelError !== null ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "butex-document2-widget__field-error", children: labelError === "invalid" ? messages.keyRulesHint : keyErrorMessage2(labelError, messages) }) : null
12904
13149
  ] }) : null
12905
13150
  ] }) : null,
12906
13151
  reason ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "butex-document2-widget__error", children: uiLocale === "en" ? messages.equationUnavailable : reason }) : null,
@@ -12918,7 +13163,15 @@ function EquationDrawer({
12918
13163
  ),
12919
13164
  /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "butex-document2-widget__row", children: [
12920
13165
  canDelete && onDelete ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", className: "butex-document2-widget__button--danger", onClick: onDelete, children: messages.deleteEquation }) : null,
12921
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => onSave({ ...latestSession.current, activeSide: equationSide }), children: messages.saveEquation })
13166
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
13167
+ "button",
13168
+ {
13169
+ type: "button",
13170
+ disabled: labelEnabled && mathMode === "display" && labelError !== null,
13171
+ onClick: () => onSave({ ...latestSession.current, activeSide: equationSide }),
13172
+ children: messages.saveEquation
13173
+ }
13174
+ )
12922
13175
  ] })
12923
13176
  ]
12924
13177
  }
@@ -12927,92 +13180,243 @@ function EquationDrawer({
12927
13180
  }
12928
13181
 
12929
13182
  // src/react-document2/LabelsPanel.tsx
13183
+ var import_react10 = require("react");
12930
13184
  var import_jsx_runtime14 = require("react/jsx-runtime");
12931
- function kindLabel(kind, uiLocale) {
12932
- const messages = document2Messages(uiLocale);
12933
- if (kind === "fig") {
12934
- return messages.labelKindFig;
13185
+ function keyErrorMessage3(error, messages) {
13186
+ if (error === "empty") {
13187
+ return messages.keyEmpty;
13188
+ }
13189
+ if (error === "invalid") {
13190
+ return messages.keyInvalid;
12935
13191
  }
12936
- if (kind === "tab") {
12937
- return messages.labelKindTab;
13192
+ if (error === "duplicate") {
13193
+ return messages.keyDuplicate;
12938
13194
  }
12939
- return messages.labelKindEq;
13195
+ return null;
12940
13196
  }
12941
13197
  function LabelsPanel({
12942
13198
  open,
12943
13199
  labels,
13200
+ references = [],
12944
13201
  uiLocale = "ar",
13202
+ digitForm = "arabicIndic",
12945
13203
  onClose,
12946
13204
  onUpdateFloat,
12947
13205
  onUpdateEquationLabel
12948
13206
  }) {
12949
13207
  const messages = document2Messages(uiLocale);
13208
+ const documentDirection = uiLocale === "ar" ? "rtl" : "ltr";
13209
+ const [keyOverrides, setKeyOverrides] = (0, import_react10.useState)({});
12950
13210
  if (!open) {
12951
13211
  return null;
12952
13212
  }
12953
- 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: [
12954
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("header", { className: "butex-document2-widget__refs-header", children: [
12955
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("strong", { children: messages.labelsTitle }),
12956
- /* @__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" })
12957
- ] }),
12958
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "butex-document2-widget__labels-help", children: messages.labelsHelp }),
12959
- 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: [
12960
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "butex-document2-widget__refs-item-head", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("strong", { children: [
12961
- "[",
12962
- kindLabel(entry.kind, uiLocale),
12963
- " ",
12964
- entry.number,
12965
- "] ",
12966
- entry.key
12967
- ] }) }),
12968
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "butex-document2-widget__refs-grid", children: [
12969
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "butex-document2-widget__refs-field", children: [
12970
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: messages.floatLabel }),
12971
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
12972
- "input",
12973
- {
12974
- value: entry.key,
12975
- dir: uiLocaleDirection(uiLocale),
12976
- onChange: (event) => {
12977
- const value = event.currentTarget.value;
12978
- if (entry.kind === "eq") {
12979
- onUpdateEquationLabel?.(entry.ownerId, { label: value, labelEnabled: true });
12980
- } else if (entry.kind === "fig" || entry.kind === "tab") {
12981
- onUpdateFloat?.(entry.ownerId, entry.kind, { label: value, labelEnabled: true });
12982
- }
12983
- }
12984
- }
12985
- )
13213
+ 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)(
13214
+ "div",
13215
+ {
13216
+ className: "butex-document2-widget__refs-panel",
13217
+ role: "dialog",
13218
+ "aria-label": messages.labelsTitle,
13219
+ onClick: (event) => event.stopPropagation(),
13220
+ children: [
13221
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("header", { className: "butex-document2-widget__refs-header", children: [
13222
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("strong", { children: messages.labelsTitle }),
13223
+ /* @__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" })
12986
13224
  ] }),
12987
- entry.kind === "fig" || entry.kind === "tab" ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "butex-document2-widget__refs-field", children: [
12988
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: messages.floatCaption }),
12989
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
12990
- "input",
12991
- {
12992
- value: entry.caption,
12993
- onChange: (event) => {
12994
- const value = event.currentTarget.value;
12995
- const kind = entry.kind;
12996
- if (kind === "fig" || kind === "tab") {
12997
- onUpdateFloat?.(entry.ownerId, kind, { caption: value, captionEnabled: true });
12998
- }
13225
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "butex-document2-widget__labels-help", children: messages.labelsHelp }),
13226
+ 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) => {
13227
+ const title = formatFloatCaptionTitle(entry.kind, entry.number, {
13228
+ uiLocale,
13229
+ digitForm,
13230
+ documentDirection
13231
+ });
13232
+ const captionPreview = entry.kind === "eq" ? title : formatFloatCaptionPreview(title, entry.caption, uiLocale);
13233
+ const overrideKey = `${entry.kind}:${entry.ownerId}`;
13234
+ const displayedKey = keyOverrides[overrideKey] ?? entry.key;
13235
+ const entryKeyError = document2KeyError(displayedKey, {
13236
+ references,
13237
+ labels,
13238
+ excludeOwnerId: entry.ownerId
13239
+ });
13240
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("li", { className: "butex-document2-widget__refs-item", children: [
13241
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "butex-document2-widget__refs-item-head", children: [
13242
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("strong", { children: title }),
13243
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "butex-document2-widget__refs-item-key", children: entry.key })
13244
+ ] }),
13245
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
13246
+ "div",
13247
+ {
13248
+ className: "butex-document2-widget__modal-preview",
13249
+ dir: uiLocaleDirection(uiLocale),
13250
+ "aria-label": messages.captionPreview,
13251
+ children: captionPreview
12999
13252
  }
13000
- }
13001
- )
13002
- ] }) : null
13003
- ] })
13004
- ] }, `${entry.kind}:${entry.ownerId}`)) })
13005
- ] }) });
13253
+ ),
13254
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "butex-document2-widget__refs-grid", children: [
13255
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "butex-document2-widget__refs-field", children: [
13256
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: messages.floatLabel }),
13257
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
13258
+ "input",
13259
+ {
13260
+ value: displayedKey,
13261
+ dir: uiLocaleDirection(uiLocale),
13262
+ "aria-invalid": entryKeyError !== null ? true : void 0,
13263
+ onChange: (event) => {
13264
+ const value = event.currentTarget.value;
13265
+ setKeyOverrides((current) => ({ ...current, [overrideKey]: value }));
13266
+ const error = document2KeyError(value, {
13267
+ references,
13268
+ labels,
13269
+ excludeOwnerId: entry.ownerId
13270
+ });
13271
+ if (error !== null) {
13272
+ return;
13273
+ }
13274
+ if (entry.kind === "eq") {
13275
+ onUpdateEquationLabel?.(entry.ownerId, { label: value, labelEnabled: true });
13276
+ } else if (entry.kind === "fig" || entry.kind === "tab") {
13277
+ onUpdateFloat?.(entry.ownerId, entry.kind, { label: value, labelEnabled: true });
13278
+ }
13279
+ setKeyOverrides((current) => {
13280
+ const next = { ...current };
13281
+ delete next[overrideKey];
13282
+ return next;
13283
+ });
13284
+ }
13285
+ }
13286
+ ),
13287
+ entryKeyError !== null ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "butex-document2-widget__field-error", children: entryKeyError === "invalid" ? messages.keyRulesHint : keyErrorMessage3(entryKeyError, messages) }) : null
13288
+ ] }),
13289
+ entry.kind === "fig" || entry.kind === "tab" ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "butex-document2-widget__refs-field", children: [
13290
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: messages.floatCaption }),
13291
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
13292
+ "input",
13293
+ {
13294
+ value: entry.caption,
13295
+ onChange: (event) => {
13296
+ const value = event.currentTarget.value;
13297
+ const kind = entry.kind;
13298
+ if (kind === "fig" || kind === "tab") {
13299
+ onUpdateFloat?.(entry.ownerId, kind, { caption: value, captionEnabled: true });
13300
+ }
13301
+ }
13302
+ }
13303
+ )
13304
+ ] }) : null
13305
+ ] })
13306
+ ] }, overrideKey);
13307
+ }) })
13308
+ ]
13309
+ }
13310
+ ) });
13006
13311
  }
13007
13312
 
13008
13313
  // src/react-document2/ReferencesPanel.tsx
13009
- var import_react9 = require("react");
13314
+ var import_react11 = require("react");
13010
13315
  var import_jsx_runtime15 = require("react/jsx-runtime");
13011
- var EMPTY_DRAFT = { key: "", authors: "", title: "", year: "", url: "", venue: "" };
13316
+ var EMPTY_DRAFT = {
13317
+ key: "",
13318
+ authors: "",
13319
+ title: "",
13320
+ year: "",
13321
+ url: "",
13322
+ venue: "",
13323
+ field_separator: DEFAULT_REFERENCE_FIELD_SEPARATOR
13324
+ };
13325
+ var REFERENCE_FIELDS = [
13326
+ ["key", "referenceKey"],
13327
+ ["authors", "referenceAuthors"],
13328
+ ["title", "referenceTitle"],
13329
+ ["year", "referenceYear"],
13330
+ ["venue", "referenceVenue"],
13331
+ ["url", "referenceUrl"]
13332
+ ];
13333
+ function keyErrorMessage4(error, messages) {
13334
+ if (error === "empty") {
13335
+ return messages.keyEmpty;
13336
+ }
13337
+ if (error === "invalid") {
13338
+ return messages.keyInvalid;
13339
+ }
13340
+ if (error === "duplicate") {
13341
+ return messages.keyDuplicate;
13342
+ }
13343
+ return null;
13344
+ }
13345
+ function FieldSeparatorToggle({
13346
+ value,
13347
+ messages,
13348
+ onChange
13349
+ }) {
13350
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "butex-document2-widget__refs-field butex-document2-widget__refs-separator", children: [
13351
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: messages.referenceFieldSeparator }),
13352
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "butex-document2-widget__refs-separator-toggle", role: "group", "aria-label": messages.referenceFieldSeparator, children: [
13353
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13354
+ "button",
13355
+ {
13356
+ type: "button",
13357
+ className: value === "\u060C" ? "is-active" : void 0,
13358
+ title: messages.referenceCommaRtl,
13359
+ "aria-label": messages.referenceCommaRtl,
13360
+ "aria-pressed": value === "\u060C",
13361
+ onClick: () => onChange("\u060C"),
13362
+ children: "\u060C"
13363
+ }
13364
+ ),
13365
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13366
+ "button",
13367
+ {
13368
+ type: "button",
13369
+ className: value === "," ? "is-active" : void 0,
13370
+ title: messages.referenceCommaLtr,
13371
+ "aria-label": messages.referenceCommaLtr,
13372
+ "aria-pressed": value === ",",
13373
+ onClick: () => onChange(","),
13374
+ children: ","
13375
+ }
13376
+ )
13377
+ ] })
13378
+ ] });
13379
+ }
13380
+ function ReferencePreview({
13381
+ authors,
13382
+ title,
13383
+ venue,
13384
+ year,
13385
+ url,
13386
+ fieldSeparator,
13387
+ numberLabel,
13388
+ messages,
13389
+ uiLocale,
13390
+ digitForm
13391
+ }) {
13392
+ const body = bibliographyEntryBody({ authors, title, venue, year, fieldSeparator }, fieldSeparator, { digitForm });
13393
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
13394
+ "div",
13395
+ {
13396
+ className: "butex-document2-widget__modal-preview",
13397
+ dir: uiLocaleDirection(uiLocale),
13398
+ "aria-label": messages.referencePreview,
13399
+ children: [
13400
+ numberLabel ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { className: "butex-document2-widget__modal-preview-number", children: [
13401
+ "[",
13402
+ numberLabel,
13403
+ "] "
13404
+ ] }) : null,
13405
+ body.length > 0 ? body : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "butex-document2-widget__cite-picker-empty", children: "\u2026" }),
13406
+ url.trim().length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
13407
+ " ",
13408
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "butex-document2-widget__modal-preview-url", children: url.trim() })
13409
+ ] }) : null
13410
+ ]
13411
+ }
13412
+ );
13413
+ }
13012
13414
  function ReferencesPanel({
13013
13415
  open,
13014
13416
  references,
13417
+ labels = [],
13015
13418
  uiLocale = "ar",
13419
+ digitForm = "arabicIndic",
13016
13420
  onClose,
13017
13421
  onAdd,
13018
13422
  onUpdate,
@@ -13020,101 +13424,190 @@ function ReferencesPanel({
13020
13424
  onMove
13021
13425
  }) {
13022
13426
  const messages = document2Messages(uiLocale);
13023
- const [draft, setDraft] = (0, import_react9.useState)(EMPTY_DRAFT);
13427
+ const [draft, setDraft] = (0, import_react11.useState)(EMPTY_DRAFT);
13428
+ const [draftKeyTouched, setDraftKeyTouched] = (0, import_react11.useState)(false);
13429
+ const [keyOverrides, setKeyOverrides] = (0, import_react11.useState)({});
13430
+ const draftSeparator = draft.field_separator === "," ? "," : DEFAULT_REFERENCE_FIELD_SEPARATOR;
13431
+ const documentDirection = uiLocale === "ar" ? "rtl" : "ltr";
13432
+ const draftKeyError = (0, import_react11.useMemo)(
13433
+ () => document2KeyError(draft.key ?? "", {
13434
+ references,
13435
+ labels
13436
+ }),
13437
+ [draft.key, references, labels]
13438
+ );
13024
13439
  if (!open) {
13025
13440
  return null;
13026
13441
  }
13027
- 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: [
13028
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("header", { className: "butex-document2-widget__refs-header", children: [
13029
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("strong", { children: messages.referencesTitle }),
13030
- /* @__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" })
13031
- ] }),
13032
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "butex-document2-widget__refs-add", children: [
13033
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h3", { children: messages.addReference }),
13034
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "butex-document2-widget__refs-grid", children: [
13035
- ["key", messages.referenceKey],
13036
- ["authors", messages.referenceAuthors],
13037
- ["title", messages.referenceTitle],
13038
- ["year", messages.referenceYear],
13039
- ["venue", messages.referenceVenue],
13040
- ["url", messages.referenceUrl]
13041
- ].map(([field, label]) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { className: "butex-document2-widget__refs-field", children: [
13042
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: label }),
13043
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13044
- "input",
13045
- {
13046
- value: draft[field] ?? "",
13047
- onChange: (event) => {
13048
- const value = event.currentTarget.value;
13049
- setDraft((current) => ({ ...current, [field]: value }));
13050
- }
13051
- }
13052
- )
13053
- ] }, field)) }),
13054
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13055
- "button",
13056
- {
13057
- type: "button",
13058
- className: "butex-document2-widget__primary-btn",
13059
- disabled: !draft.key?.trim(),
13060
- onClick: () => {
13061
- onAdd(draft);
13062
- setDraft(EMPTY_DRAFT);
13063
- },
13064
- children: messages.addReference
13065
- }
13066
- )
13067
- ] }),
13068
- /* @__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: [
13069
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "butex-document2-widget__refs-item-head", children: [
13070
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("strong", { children: [
13071
- "[",
13072
- index + 1,
13073
- "] ",
13074
- reference.key
13442
+ 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)(
13443
+ "div",
13444
+ {
13445
+ className: "butex-document2-widget__refs-panel",
13446
+ role: "dialog",
13447
+ "aria-label": messages.referencesTitle,
13448
+ onClick: (event) => event.stopPropagation(),
13449
+ children: [
13450
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("header", { className: "butex-document2-widget__refs-header", children: [
13451
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("strong", { children: messages.referencesTitle }),
13452
+ /* @__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" })
13075
13453
  ] }),
13076
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "butex-document2-widget__refs-item-actions", children: [
13077
- /* @__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" }),
13454
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "butex-document2-widget__refs-add", children: [
13455
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h3", { children: messages.addReference }),
13456
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "butex-document2-widget__refs-grid", children: [
13457
+ REFERENCE_FIELDS.map(([field, messageKey]) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { className: "butex-document2-widget__refs-field", children: [
13458
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: messages[messageKey] }),
13459
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13460
+ "input",
13461
+ {
13462
+ value: draft[field] ?? "",
13463
+ "aria-invalid": field === "key" && draftKeyTouched && draftKeyError !== null ? true : void 0,
13464
+ onChange: (event) => {
13465
+ const value = event.currentTarget.value;
13466
+ if (field === "key") {
13467
+ setDraftKeyTouched(true);
13468
+ }
13469
+ setDraft((current) => ({ ...current, [field]: value }));
13470
+ }
13471
+ }
13472
+ ),
13473
+ 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
13474
+ ] }, field)),
13475
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13476
+ FieldSeparatorToggle,
13477
+ {
13478
+ value: draftSeparator,
13479
+ messages,
13480
+ onChange: (next) => setDraft((current) => ({ ...current, field_separator: next }))
13481
+ }
13482
+ )
13483
+ ] }),
13078
13484
  /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13079
- "button",
13485
+ ReferencePreview,
13080
13486
  {
13081
- type: "button",
13082
- title: messages.moveDown,
13083
- "aria-label": messages.moveDown,
13084
- disabled: index === references.length - 1,
13085
- onClick: () => onMove(reference.id, 1),
13086
- children: "\u2193"
13487
+ authors: draft.authors ?? "",
13488
+ title: draft.title ?? "",
13489
+ venue: draft.venue ?? "",
13490
+ year: draft.year ?? "",
13491
+ url: draft.url ?? "",
13492
+ fieldSeparator: draftSeparator,
13493
+ messages,
13494
+ uiLocale,
13495
+ digitForm
13087
13496
  }
13088
13497
  ),
13089
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", title: messages.deleteReference, "aria-label": messages.deleteReference, onClick: () => onRemove(reference.id), children: "\xD7" })
13090
- ] })
13091
- ] }),
13092
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "butex-document2-widget__refs-grid", children: [
13093
- ["key", messages.referenceKey],
13094
- ["authors", messages.referenceAuthors],
13095
- ["title", messages.referenceTitle],
13096
- ["year", messages.referenceYear],
13097
- ["venue", messages.referenceVenue],
13098
- ["url", messages.referenceUrl]
13099
- ].map(([field, label]) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { className: "butex-document2-widget__refs-field", children: [
13100
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: label }),
13101
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13102
- "input",
13103
- {
13104
- value: reference[field],
13105
- onChange: (event) => {
13106
- const value = event.currentTarget.value;
13107
- onUpdate(reference.id, { [field]: value });
13498
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13499
+ "button",
13500
+ {
13501
+ type: "button",
13502
+ className: "butex-document2-widget__primary-btn",
13503
+ disabled: draftKeyError !== null,
13504
+ onClick: () => {
13505
+ onAdd({ ...draft, field_separator: draftSeparator });
13506
+ setDraft(EMPTY_DRAFT);
13507
+ setDraftKeyTouched(false);
13508
+ },
13509
+ children: messages.addReference
13108
13510
  }
13109
- }
13110
- )
13111
- ] }, field)) })
13112
- ] }, reference.id)) })
13113
- ] }) });
13511
+ )
13512
+ ] }),
13513
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("ul", { className: "butex-document2-widget__refs-list", children: references.map((reference, index) => {
13514
+ const displayedKey = keyOverrides[reference.id] ?? reference.key;
13515
+ const entryKeyError = document2KeyError(displayedKey, {
13516
+ references,
13517
+ labels,
13518
+ excludeReferenceId: reference.id
13519
+ });
13520
+ const numberLabel = formatBibliographyNumber(index + 1, { documentDirection, digitForm });
13521
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("li", { className: "butex-document2-widget__refs-item", children: [
13522
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "butex-document2-widget__refs-item-head", children: [
13523
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("strong", { children: [
13524
+ "[",
13525
+ numberLabel,
13526
+ "] ",
13527
+ reference.key
13528
+ ] }),
13529
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "butex-document2-widget__refs-item-actions", children: [
13530
+ /* @__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" }),
13531
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13532
+ "button",
13533
+ {
13534
+ type: "button",
13535
+ title: messages.moveDown,
13536
+ "aria-label": messages.moveDown,
13537
+ disabled: index === references.length - 1,
13538
+ onClick: () => onMove(reference.id, 1),
13539
+ children: "\u2193"
13540
+ }
13541
+ ),
13542
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", title: messages.deleteReference, "aria-label": messages.deleteReference, onClick: () => onRemove(reference.id), children: "\xD7" })
13543
+ ] })
13544
+ ] }),
13545
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13546
+ ReferencePreview,
13547
+ {
13548
+ authors: reference.authors,
13549
+ title: reference.title,
13550
+ venue: reference.venue,
13551
+ year: reference.year,
13552
+ url: reference.url,
13553
+ fieldSeparator: reference.fieldSeparator,
13554
+ numberLabel,
13555
+ messages,
13556
+ uiLocale,
13557
+ digitForm
13558
+ }
13559
+ ),
13560
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "butex-document2-widget__refs-grid", children: [
13561
+ REFERENCE_FIELDS.map(([field, messageKey]) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { className: "butex-document2-widget__refs-field", children: [
13562
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: messages[messageKey] }),
13563
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13564
+ "input",
13565
+ {
13566
+ value: field === "key" ? displayedKey : reference[field],
13567
+ "aria-invalid": field === "key" && entryKeyError !== null ? true : void 0,
13568
+ onChange: (event) => {
13569
+ const value = event.currentTarget.value;
13570
+ if (field !== "key") {
13571
+ onUpdate(reference.id, { [field]: value });
13572
+ return;
13573
+ }
13574
+ setKeyOverrides((current) => ({ ...current, [reference.id]: value }));
13575
+ const error = document2KeyError(value, {
13576
+ references,
13577
+ labels,
13578
+ excludeReferenceId: reference.id
13579
+ });
13580
+ if (error === null) {
13581
+ onUpdate(reference.id, { key: value });
13582
+ setKeyOverrides((current) => {
13583
+ const next = { ...current };
13584
+ delete next[reference.id];
13585
+ return next;
13586
+ });
13587
+ }
13588
+ }
13589
+ }
13590
+ ),
13591
+ 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
13592
+ ] }, field)),
13593
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
13594
+ FieldSeparatorToggle,
13595
+ {
13596
+ value: reference.fieldSeparator,
13597
+ messages,
13598
+ onChange: (next) => onUpdate(reference.id, { field_separator: next })
13599
+ }
13600
+ )
13601
+ ] })
13602
+ ] }, reference.id);
13603
+ }) })
13604
+ ]
13605
+ }
13606
+ ) });
13114
13607
  }
13115
13608
 
13116
13609
  // src/react-document2/RefPickerPopover.tsx
13117
- var import_react10 = require("react");
13610
+ var import_react12 = require("react");
13118
13611
  var import_jsx_runtime16 = require("react/jsx-runtime");
13119
13612
  function RefPickerPopover({
13120
13613
  open,
@@ -13122,14 +13615,16 @@ function RefPickerPopover({
13122
13615
  initialKeys = [],
13123
13616
  initialRefCommand = "ref",
13124
13617
  uiLocale = "ar",
13618
+ digitForm = "arabicIndic",
13125
13619
  onClose,
13126
13620
  onConfirm,
13127
13621
  onManageLabels
13128
13622
  }) {
13129
13623
  const messages = document2Messages(uiLocale);
13130
- const [selected, setSelected] = (0, import_react10.useState)(initialKeys);
13131
- const [refCommand, setRefCommand] = (0, import_react10.useState)(initialRefCommand);
13132
- (0, import_react10.useEffect)(() => {
13624
+ const documentDirection = uiLocale === "ar" ? "rtl" : "ltr";
13625
+ const [selected, setSelected] = (0, import_react12.useState)(initialKeys);
13626
+ const [refCommand, setRefCommand] = (0, import_react12.useState)(initialRefCommand);
13627
+ (0, import_react12.useEffect)(() => {
13133
13628
  if (open) {
13134
13629
  setSelected(initialKeys);
13135
13630
  setRefCommand(initialRefCommand);
@@ -13156,16 +13651,18 @@ function RefPickerPopover({
13156
13651
  ] }),
13157
13652
  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) => {
13158
13653
  const checked = selected.includes(entry.key);
13654
+ const title = formatFloatCaptionTitle(entry.kind, entry.number, {
13655
+ uiLocale,
13656
+ digitForm,
13657
+ documentDirection
13658
+ });
13159
13659
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("label", { className: "butex-document2-widget__cite-picker-item", children: [
13160
13660
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("input", { type: "radio", name: "butex-ref-key", checked, onChange: () => selectKey(entry.key, entry.kind) }),
13161
13661
  /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("span", { children: [
13162
13662
  /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("strong", { children: [
13163
- "[",
13164
- entry.kind,
13663
+ title,
13165
13664
  " ",
13166
- entry.number,
13167
- "] ",
13168
- entry.key
13665
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "butex-document2-widget__refs-item-key", children: entry.key })
13169
13666
  ] }),
13170
13667
  entry.caption ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "butex-document2-widget__cite-picker-meta", children: entry.caption }) : null
13171
13668
  ] })
@@ -14357,6 +14854,24 @@ var DOCUMENT2_WIDGET_CSS = `
14357
14854
  width: 100%;
14358
14855
  }
14359
14856
 
14857
+ .butex-document2-widget__field-error {
14858
+ color: #b42318;
14859
+ font-size: 0.85em;
14860
+ line-height: 1.35;
14861
+ margin: 0;
14862
+ }
14863
+
14864
+ .butex-document2-widget__field-hint {
14865
+ color: var(--butex-document2-muted);
14866
+ font-size: 0.82em;
14867
+ line-height: 1.35;
14868
+ margin: 0;
14869
+ }
14870
+
14871
+ .butex-document2-widget__refs-field input[aria-invalid='true'] {
14872
+ border-color: color-mix(in srgb, #b42318 55%, var(--butex-document2-border));
14873
+ }
14874
+
14360
14875
  .butex-document2-widget__refs-item {
14361
14876
  border: 1px solid var(--butex-document2-border);
14362
14877
  border-radius: 10px;
@@ -14365,6 +14880,58 @@ var DOCUMENT2_WIDGET_CSS = `
14365
14880
  padding: 0.75rem;
14366
14881
  }
14367
14882
 
14883
+ .butex-document2-widget__refs-item-key {
14884
+ color: var(--butex-document2-muted);
14885
+ font-size: 0.9em;
14886
+ font-weight: 500;
14887
+ }
14888
+
14889
+ .butex-document2-widget__modal-preview {
14890
+ background: color-mix(in srgb, var(--butex-document2-panel) 88%, var(--butex-document2-accent-bg));
14891
+ border: 1px dashed color-mix(in srgb, var(--butex-document2-accent) 30%, var(--butex-document2-border));
14892
+ border-radius: 8px;
14893
+ color: inherit;
14894
+ font-size: 0.95em;
14895
+ line-height: 1.55;
14896
+ padding: 0.55rem 0.7rem;
14897
+ text-align: center;
14898
+ }
14899
+
14900
+ .butex-document2-widget__modal-preview-number {
14901
+ color: var(--butex-document2-muted);
14902
+ font-weight: 600;
14903
+ }
14904
+
14905
+ .butex-document2-widget__modal-preview-url {
14906
+ color: var(--butex-document2-accent);
14907
+ word-break: break-all;
14908
+ }
14909
+
14910
+ .butex-document2-widget__refs-separator-toggle {
14911
+ display: inline-flex;
14912
+ gap: 0.35rem;
14913
+ }
14914
+
14915
+ .butex-document2-widget__refs-separator-toggle button {
14916
+ background: var(--butex-document2-input-bg, var(--butex-document2-panel));
14917
+ border: 1px solid var(--butex-document2-border);
14918
+ border-radius: 6px;
14919
+ color: inherit;
14920
+ cursor: pointer;
14921
+ font: inherit;
14922
+ font-size: 1.15em;
14923
+ line-height: 1;
14924
+ min-width: 2.25rem;
14925
+ padding: 0.35rem 0.55rem;
14926
+ }
14927
+
14928
+ .butex-document2-widget__refs-separator-toggle button.is-active {
14929
+ background: var(--butex-document2-accent-bg);
14930
+ border-color: color-mix(in srgb, var(--butex-document2-accent) 45%, var(--butex-document2-border));
14931
+ color: var(--butex-document2-accent);
14932
+ font-weight: 700;
14933
+ }
14934
+
14368
14935
  .butex-document2-widget__refs-item-actions {
14369
14936
  display: inline-flex;
14370
14937
  gap: 0.25rem;
@@ -14856,36 +15423,36 @@ function ButexDocumentEditor2({
14856
15423
  onLatexChange
14857
15424
  }) {
14858
15425
  const messages = document2Messages(uiLocale);
14859
- const initialState = (0, import_react11.useMemo)(
15426
+ const initialState = (0, import_react13.useMemo)(
14860
15427
  () => resolveInitialDocument2(initialDocument, uiLocale, documentMeta),
14861
15428
  [initialDocument, documentMeta, uiLocale]
14862
15429
  );
14863
- const [documentNode, setDocumentNode] = (0, import_react11.useState)(initialState.document);
14864
- const [error, setError] = (0, import_react11.useState)(initialState.error);
14865
- const [editorOpen, setEditorOpen] = (0, import_react11.useState)(true);
14866
- const [previewOpen, setPreviewOpen] = (0, import_react11.useState)(true);
14867
- const [selectedMath, setSelectedMath] = (0, import_react11.useState)(null);
14868
- const [citePicker, setCitePicker] = (0, import_react11.useState)(null);
14869
- const [referencesOpen, setReferencesOpen] = (0, import_react11.useState)(false);
14870
- const [labelsOpen, setLabelsOpen] = (0, import_react11.useState)(false);
14871
- const [refPicker, setRefPicker] = (0, import_react11.useState)(null);
14872
- const [digitFormState, setDigitFormState] = (0, import_react11.useState)(null);
14873
- const [editorFocus, setEditorFocus] = (0, import_react11.useState)(createEmptyDocument2EditorFocus());
14874
- const [collapsedBlockIds, setCollapsedBlockIds] = (0, import_react11.useState)(() => /* @__PURE__ */ new Set());
14875
- const [blockSelectionState, setBlockSelectionState] = (0, import_react11.useState)(emptyBlockSelection);
14876
- const [historyTick, setHistoryTick] = (0, import_react11.useState)(0);
15430
+ const [documentNode, setDocumentNode] = (0, import_react13.useState)(initialState.document);
15431
+ const [error, setError] = (0, import_react13.useState)(initialState.error);
15432
+ const [editorOpen, setEditorOpen] = (0, import_react13.useState)(true);
15433
+ const [previewOpen, setPreviewOpen] = (0, import_react13.useState)(true);
15434
+ const [selectedMath, setSelectedMath] = (0, import_react13.useState)(null);
15435
+ const [citePicker, setCitePicker] = (0, import_react13.useState)(null);
15436
+ const [referencesOpen, setReferencesOpen] = (0, import_react13.useState)(false);
15437
+ const [labelsOpen, setLabelsOpen] = (0, import_react13.useState)(false);
15438
+ const [refPicker, setRefPicker] = (0, import_react13.useState)(null);
15439
+ const [digitFormState, setDigitFormState] = (0, import_react13.useState)(null);
15440
+ const [editorFocus, setEditorFocus] = (0, import_react13.useState)(createEmptyDocument2EditorFocus());
15441
+ const [collapsedBlockIds, setCollapsedBlockIds] = (0, import_react13.useState)(() => /* @__PURE__ */ new Set());
15442
+ const [blockSelectionState, setBlockSelectionState] = (0, import_react13.useState)(emptyBlockSelection);
15443
+ const [historyTick, setHistoryTick] = (0, import_react13.useState)(0);
14877
15444
  const digitForm = digitFormProp ?? digitFormState ?? (documentDirection === "rtl" ? "arabicIndic" : "western");
14878
- const historyRef = (0, import_react11.useRef)(createDocument2History());
14879
- const documentRef = (0, import_react11.useRef)(documentNode);
14880
- const textSnapshotArmedRef = (0, import_react11.useRef)(false);
14881
- const textDebounceRef = (0, import_react11.useRef)(null);
14882
- const widgetRef = (0, import_react11.useRef)(null);
14883
- const articleMetaPanelRef = (0, import_react11.useRef)(null);
14884
- const pendingFocusRef = (0, import_react11.useRef)(null);
15445
+ const historyRef = (0, import_react13.useRef)(createDocument2History());
15446
+ const documentRef = (0, import_react13.useRef)(documentNode);
15447
+ const textSnapshotArmedRef = (0, import_react13.useRef)(false);
15448
+ const textDebounceRef = (0, import_react13.useRef)(null);
15449
+ const widgetRef = (0, import_react13.useRef)(null);
15450
+ const articleMetaPanelRef = (0, import_react13.useRef)(null);
15451
+ const pendingFocusRef = (0, import_react13.useRef)(null);
14885
15452
  documentRef.current = documentNode;
14886
15453
  const latex = document2Latex(documentNode);
14887
- const documentLabels = (0, import_react11.useMemo)(() => collectDocument2Labels(documentNode), [documentNode]);
14888
- const preview = (0, import_react11.useMemo)(
15454
+ const documentLabels = (0, import_react13.useMemo)(() => collectDocument2Labels(documentNode), [documentNode]);
15455
+ const preview = (0, import_react13.useMemo)(
14889
15456
  () => document2Preview(documentNode, mathOutput, equationSide, {
14890
15457
  documentDirection,
14891
15458
  digitForm,
@@ -14893,7 +15460,7 @@ function ButexDocumentEditor2({
14893
15460
  }),
14894
15461
  [documentNode, documentDirection, digitForm, equationSide, mathOutput, uiLocale]
14895
15462
  );
14896
- const debugEnabled = (0, import_react11.useMemo)(() => {
15463
+ const debugEnabled = (0, import_react13.useMemo)(() => {
14897
15464
  if (debug) {
14898
15465
  return true;
14899
15466
  }
@@ -14902,8 +15469,8 @@ function ButexDocumentEditor2({
14902
15469
  }
14903
15470
  return new URLSearchParams(window.location.search).get("debug") === "1";
14904
15471
  }, [debug]);
14905
- const canUndo = (0, import_react11.useMemo)(() => document2HistoryCanUndo(historyRef.current), [historyTick, documentNode]);
14906
- const canRedo = (0, import_react11.useMemo)(() => document2HistoryCanRedo(historyRef.current), [historyTick, documentNode]);
15472
+ const canUndo = (0, import_react13.useMemo)(() => document2HistoryCanUndo(historyRef.current), [historyTick, documentNode]);
15473
+ const canRedo = (0, import_react13.useMemo)(() => document2HistoryCanRedo(historyRef.current), [historyTick, documentNode]);
14907
15474
  const blockSelection = normalizeBlockSelection(blockSelectionState.selection, documentNode.blocks.length);
14908
15475
  const selectionCount = blockSelection ? blockSelection.to - blockSelection.from + 1 : 0;
14909
15476
  const canMoveSelectionUp = Boolean(blockSelection && blockSelection.from > 0);
@@ -14945,15 +15512,15 @@ function ButexDocumentEditor2({
14945
15512
  applyDocument(removeDocument2BlockRange(documentRef.current, selection.from, selection.to), "immediate");
14946
15513
  clearBlockSelection();
14947
15514
  }
14948
- (0, import_react11.useEffect)(() => {
15515
+ (0, import_react13.useEffect)(() => {
14949
15516
  injectBuTeXDocument2Styles();
14950
15517
  }, []);
14951
- (0, import_react11.useEffect)(() => {
15518
+ (0, import_react13.useEffect)(() => {
14952
15519
  if (!editableEquations || previewOnly) {
14953
15520
  setSelectedMath(null);
14954
15521
  }
14955
15522
  }, [editableEquations, previewOnly]);
14956
- (0, import_react11.useEffect)(() => {
15523
+ (0, import_react13.useEffect)(() => {
14957
15524
  const next = resolveInitialDocument2(initialDocument, uiLocale, documentMeta);
14958
15525
  setDocumentNode(next.document);
14959
15526
  setError(next.error);
@@ -14962,13 +15529,13 @@ function ButexDocumentEditor2({
14962
15529
  historyRef.current = createDocument2History();
14963
15530
  setHistoryTick((tick) => tick + 1);
14964
15531
  }, [initialDocument, documentMeta, uiLocale]);
14965
- (0, import_react11.useEffect)(() => {
15532
+ (0, import_react13.useEffect)(() => {
14966
15533
  onDocumentChange?.(documentNode);
14967
15534
  }, [documentNode, onDocumentChange]);
14968
- (0, import_react11.useEffect)(() => {
15535
+ (0, import_react13.useEffect)(() => {
14969
15536
  onLatexChange?.(latex);
14970
15537
  }, [latex, onLatexChange]);
14971
- (0, import_react11.useEffect)(() => {
15538
+ (0, import_react13.useEffect)(() => {
14972
15539
  const pending = pendingFocusRef.current;
14973
15540
  const root = widgetRef.current;
14974
15541
  if (!pending || !root) {
@@ -15008,10 +15575,10 @@ function ButexDocumentEditor2({
15008
15575
  textarea.setSelectionRange(safeOffset, safeOffset);
15009
15576
  });
15010
15577
  }, [documentNode]);
15011
- const bumpHistoryUi = (0, import_react11.useCallback)(() => {
15578
+ const bumpHistoryUi = (0, import_react13.useCallback)(() => {
15012
15579
  setHistoryTick((tick) => tick + 1);
15013
15580
  }, []);
15014
- const applyDocument = (0, import_react11.useCallback)(
15581
+ const applyDocument = (0, import_react13.useCallback)(
15015
15582
  (next, mode = "immediate") => {
15016
15583
  if (mode === "immediate") {
15017
15584
  pushDocument2Snapshot(historyRef.current, documentRef.current);
@@ -15033,7 +15600,7 @@ function ButexDocumentEditor2({
15033
15600
  },
15034
15601
  [bumpHistoryUi]
15035
15602
  );
15036
- const afterBlockId = (0, import_react11.useCallback)(() => resolveInsertAfterBlockId(documentRef.current, editorFocus), [editorFocus]);
15603
+ const afterBlockId = (0, import_react13.useCallback)(() => resolveInsertAfterBlockId(documentRef.current, editorFocus), [editorFocus]);
15037
15604
  function undoDocument() {
15038
15605
  const restored = restoreDocument2Undo(historyRef.current, documentRef.current);
15039
15606
  if (!restored) {
@@ -15084,7 +15651,7 @@ function ButexDocumentEditor2({
15084
15651
  function openAllBlocks() {
15085
15652
  setCollapsedBlockIds(/* @__PURE__ */ new Set());
15086
15653
  }
15087
- (0, import_react11.useEffect)(() => {
15654
+ (0, import_react13.useEffect)(() => {
15088
15655
  const root = widgetRef.current;
15089
15656
  if (!root) {
15090
15657
  return;
@@ -15564,6 +16131,7 @@ function ButexDocumentEditor2({
15564
16131
  output: mathOutput,
15565
16132
  documentDirection,
15566
16133
  uiLocale,
16134
+ digitForm,
15567
16135
  resolveImageUrl
15568
16136
  }
15569
16137
  )
@@ -15593,6 +16161,9 @@ function ButexDocumentEditor2({
15593
16161
  uiLocale,
15594
16162
  labelEnabled: selectedMath.labelEnabled,
15595
16163
  label: selectedMath.label,
16164
+ labels: documentLabels,
16165
+ references: documentNode.references,
16166
+ ownerId: selectedMath.tokenId ?? void 0,
15596
16167
  onLabelEnabledChange: (enabled) => setSelectedMath((current) => current ? { ...current, labelEnabled: enabled } : current),
15597
16168
  onLabelChange: (nextLabel) => setSelectedMath((current) => current ? { ...current, label: nextLabel } : current),
15598
16169
  onMathModeChange: (mode) => setSelectedMath((current) => current ? { ...current, mathMode: mode } : current),
@@ -15608,6 +16179,7 @@ function ButexDocumentEditor2({
15608
16179
  references: documentNode.references,
15609
16180
  initialKeys: citePicker?.keys ?? [],
15610
16181
  uiLocale,
16182
+ digitForm,
15611
16183
  onClose: () => setCitePicker(null),
15612
16184
  onConfirm: confirmCiteKeys,
15613
16185
  onManageReferences: () => {
@@ -15624,6 +16196,7 @@ function ButexDocumentEditor2({
15624
16196
  initialKeys: refPicker?.keys ?? [],
15625
16197
  initialRefCommand: refPicker?.refCommand ?? "ref",
15626
16198
  uiLocale,
16199
+ digitForm,
15627
16200
  onClose: () => setRefPicker(null),
15628
16201
  onConfirm: confirmRefKeys,
15629
16202
  onManageLabels: () => {
@@ -15637,7 +16210,9 @@ function ButexDocumentEditor2({
15637
16210
  {
15638
16211
  open: referencesOpen,
15639
16212
  references: documentNode.references,
16213
+ labels: documentLabels,
15640
16214
  uiLocale,
16215
+ digitForm,
15641
16216
  onClose: () => setReferencesOpen(false),
15642
16217
  onAdd: (partial) => applyDocument(addDocument2Reference(documentRef.current, partial), "immediate"),
15643
16218
  onUpdate: (referenceId, patch) => applyDocument(updateDocument2Reference(documentRef.current, referenceId, patch), "immediate"),
@@ -15650,7 +16225,9 @@ function ButexDocumentEditor2({
15650
16225
  {
15651
16226
  open: labelsOpen,
15652
16227
  labels: documentLabels,
16228
+ references: documentNode.references,
15653
16229
  uiLocale,
16230
+ digitForm,
15654
16231
  onClose: () => setLabelsOpen(false),
15655
16232
  onUpdateFloat: (ownerId, kind, patch) => applyDocument(
15656
16233
  kind === "fig" ? updateDocument2ImageMeta(documentRef.current, ownerId, patch) : updateDocument2TableMeta(documentRef.current, ownerId, patch),