@drghaliasri/butex 5.3.1 → 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.
@@ -268,6 +268,10 @@ function cloneDocument2Meta(meta) {
268
268
  }
269
269
 
270
270
  // src/document2/citations.ts
271
+ var DEFAULT_REFERENCE_FIELD_SEPARATOR = "\u060C";
272
+ function normalizeReferenceFieldSeparator(value) {
273
+ return value === "," ? "," : DEFAULT_REFERENCE_FIELD_SEPARATOR;
274
+ }
271
275
  function referenceNumberMap(references) {
272
276
  const map = /* @__PURE__ */ new Map();
273
277
  references.forEach((reference, index) => {
@@ -313,7 +317,8 @@ function referenceFromJson(json) {
313
317
  title: typeof json.title === "string" ? json.title : "",
314
318
  year: typeof json.year === "string" ? json.year : "",
315
319
  url: typeof json.url === "string" ? json.url : "",
316
- venue: typeof json.venue === "string" ? json.venue : ""
320
+ venue: typeof json.venue === "string" ? json.venue : "",
321
+ fieldSeparator: normalizeReferenceFieldSeparator(json.field_separator)
317
322
  };
318
323
  }
319
324
  function createEmptyReference2(partial = {}) {
@@ -323,15 +328,33 @@ function createEmptyReference2(partial = {}) {
323
328
  title: partial.title,
324
329
  year: partial.year,
325
330
  url: partial.url,
326
- venue: partial.venue
331
+ venue: partial.venue,
332
+ field_separator: partial.field_separator
327
333
  });
328
334
  }
335
+ function bibliographyEntryBody(reference, separator = reference.fieldSeparator, options = {}) {
336
+ const year = options.digitForm !== void 0 ? formatDigits(reference.year, options.digitForm) : reference.year;
337
+ const parts = [reference.authors, reference.title, reference.venue, year].filter((part) => part.trim().length > 0);
338
+ return parts.join(`${separator} `);
339
+ }
329
340
  function bibliographyEntryLatex(reference) {
330
- const parts = [reference.authors, reference.title, reference.venue, reference.year].filter((part) => part.trim().length > 0);
331
- const body = parts.join(", ");
341
+ const body = bibliographyEntryBody(reference);
332
342
  const url = reference.url.trim().length > 0 ? ` \\url{${reference.url}}` : "";
333
343
  return `\\bibitem{${reference.key}} ${body}${url}`.trim();
334
344
  }
345
+ function absoluteHttpHref(url) {
346
+ const trimmed = url.trim();
347
+ if (trimmed.length === 0) {
348
+ return "";
349
+ }
350
+ if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(trimmed)) {
351
+ return trimmed;
352
+ }
353
+ if (trimmed.startsWith("//")) {
354
+ return `https:${trimmed}`;
355
+ }
356
+ return `https://${trimmed}`;
357
+ }
335
358
 
336
359
  // src/ast/commands/index.ts
337
360
  function renderCommandCore(context) {
@@ -816,6 +839,23 @@ function labelNumberMap(document2) {
816
839
  }
817
840
  return map;
818
841
  }
842
+ function formatFloatCaptionTitle(kind, number, options = {}) {
843
+ const locale = options.uiLocale ?? "ar";
844
+ 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";
845
+ const digits = formatBibliographyNumber(number, {
846
+ documentDirection: options.documentDirection ?? (locale === "ar" ? "rtl" : "ltr"),
847
+ digitForm: options.digitForm ?? (locale === "ar" ? "arabicIndic" : "western")
848
+ });
849
+ return `${kindWord} ${digits}`;
850
+ }
851
+ function formatFloatCaptionPreview(title, caption, uiLocale = "ar") {
852
+ const trimmed = caption?.trim() ?? "";
853
+ if (trimmed.length === 0) {
854
+ return title;
855
+ }
856
+ const separator = uiLocale === "ar" ? ": " : ". ";
857
+ return `${title}${separator}${trimmed}`;
858
+ }
819
859
  function formatRefLabel(keys, document2, refCommand, options = {}) {
820
860
  const documentDirection = options.documentDirection ?? "rtl";
821
861
  const digitForm = options.digitForm ?? (documentDirection === "rtl" ? "arabicIndic" : "western");
@@ -1086,7 +1126,8 @@ function parseReferences(json) {
1086
1126
  title: typeof entry.title === "string" ? entry.title : void 0,
1087
1127
  year: typeof entry.year === "string" ? entry.year : void 0,
1088
1128
  url: typeof entry.url === "string" ? entry.url : void 0,
1089
- venue: typeof entry.venue === "string" ? entry.venue : void 0
1129
+ venue: typeof entry.venue === "string" ? entry.venue : void 0,
1130
+ field_separator: entry.field_separator === "," || entry.field_separator === "\u060C" ? entry.field_separator : void 0
1090
1131
  })
1091
1132
  );
1092
1133
  }
@@ -7518,6 +7559,9 @@ function updateDocument2Reference(document2, referenceId, patch) {
7518
7559
  if (typeof patch.venue === "string") {
7519
7560
  reference.venue = patch.venue;
7520
7561
  }
7562
+ if (patch.field_separator === "," || patch.field_separator === "\u060C") {
7563
+ reference.fieldSeparator = patch.field_separator;
7564
+ }
7521
7565
  return next;
7522
7566
  }
7523
7567
  function removeDocument2Reference(document2, referenceId) {
@@ -7551,6 +7595,48 @@ function updateDocument2Meta(document2, patch) {
7551
7595
  return next;
7552
7596
  }
7553
7597
 
7598
+ // src/document2/keys.ts
7599
+ var DOCUMENT2_KEY_PATTERN = /^[\p{L}\p{M}0-9:._-]+$/u;
7600
+ function normalizeDocument2Key(key) {
7601
+ return key.normalize("NFC").trim();
7602
+ }
7603
+ function isDuplicateDocument2Key(key, namespace) {
7604
+ const normalized = normalizeDocument2Key(key);
7605
+ if (normalized.length === 0) {
7606
+ return false;
7607
+ }
7608
+ for (const reference of namespace.references ?? []) {
7609
+ if (namespace.excludeReferenceId && reference.id === namespace.excludeReferenceId) {
7610
+ continue;
7611
+ }
7612
+ if (normalizeDocument2Key(reference.key) === normalized) {
7613
+ return true;
7614
+ }
7615
+ }
7616
+ for (const label of namespace.labels ?? []) {
7617
+ if (namespace.excludeOwnerId && label.ownerId === namespace.excludeOwnerId) {
7618
+ continue;
7619
+ }
7620
+ if (normalizeDocument2Key(label.key) === normalized) {
7621
+ return true;
7622
+ }
7623
+ }
7624
+ return false;
7625
+ }
7626
+ function document2KeyError(key, namespace = {}) {
7627
+ const normalized = normalizeDocument2Key(key);
7628
+ if (normalized.length === 0) {
7629
+ return "empty";
7630
+ }
7631
+ if (!DOCUMENT2_KEY_PATTERN.test(normalized)) {
7632
+ return "invalid";
7633
+ }
7634
+ if (isDuplicateDocument2Key(normalized, namespace)) {
7635
+ return "duplicate";
7636
+ }
7637
+ return null;
7638
+ }
7639
+
7554
7640
  // src/document2/arabicPreamble.ts
7555
7641
  function arabicXeLatexPreamblePkg(twocolumn = false) {
7556
7642
  const classOptions = twocolumn ? "12pt,a4paper,notitlepage,twocolumn" : "12pt,a4paper,notitlepage";
@@ -8101,13 +8187,11 @@ function floatNumberLabel(document2, key, previewOptions) {
8101
8187
  if (!hit || hit.kind !== "fig" && hit.kind !== "tab") {
8102
8188
  return void 0;
8103
8189
  }
8104
- const locale = previewOptions.uiLocale ?? "ar";
8105
- const kindWord = hit.kind === "fig" ? locale === "ar" ? "\u0627\u0644\u0634\u0643\u0644" : "Figure" : locale === "ar" ? "\u0627\u0644\u062C\u062F\u0648\u0644" : "Table";
8106
- const digits = formatBibliographyNumber(hit.number, {
8190
+ return formatFloatCaptionTitle(hit.kind, hit.number, {
8191
+ uiLocale: previewOptions.uiLocale ?? "ar",
8107
8192
  documentDirection: previewOptions.documentDirection,
8108
8193
  digitForm: previewOptions.digitForm
8109
8194
  });
8110
- return `${kindWord} ${digits}`;
8111
8195
  }
8112
8196
  function blockPreview(block, islands, output, equationSide, document2, previewOptions) {
8113
8197
  if (block.kind === "textBlock") {
@@ -8162,7 +8246,8 @@ function blockPreview(block, islands, output, equationSide, document2, previewOp
8162
8246
  title: reference.title,
8163
8247
  year: reference.year,
8164
8248
  url: reference.url,
8165
- venue: reference.venue
8249
+ venue: reference.venue,
8250
+ fieldSeparator: reference.fieldSeparator
8166
8251
  }))
8167
8252
  };
8168
8253
  }
@@ -8313,6 +8398,15 @@ var DOCUMENT2_MESSAGES = {
8313
8398
  labelKindFig: "\u0634\u0643\u0644",
8314
8399
  labelKindTab: "\u062C\u062F\u0648\u0644",
8315
8400
  labelKindEq: "\u0645\u0639\u0627\u062F\u0644\u0629",
8401
+ captionPreview: "\u0645\u0639\u0627\u064A\u0646\u0629 \u0627\u0644\u062A\u0639\u0644\u064A\u0642",
8402
+ referencePreview: "\u0645\u0639\u0627\u064A\u0646\u0629 \u0627\u0644\u0645\u0631\u062C\u0639",
8403
+ referenceFieldSeparator: "\u0641\u0627\u0635\u0644 \u0627\u0644\u062D\u0642\u0648\u0644",
8404
+ referenceCommaLtr: "\u0641\u0627\u0635\u0644\u0629 \u0625\u0646\u062C\u0644\u064A\u0632\u064A\u0629 ,",
8405
+ referenceCommaRtl: "\u0641\u0627\u0635\u0644\u0629 \u0639\u0631\u0628\u064A\u0629 \u060C",
8406
+ keyEmpty: "\u0627\u0644\u0645\u0641\u062A\u0627\u062D \u0645\u0637\u0644\u0648\u0628",
8407
+ 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",
8408
+ keyDuplicate: "\u0647\u0630\u0627 \u0627\u0644\u0645\u0641\u062A\u0627\u062D \u0645\u0633\u062A\u062E\u062F\u0645 \u0645\u0633\u0628\u0642\u0627\u064B",
8409
+ 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",
8316
8410
  citePickerTitle: "\u0627\u062E\u062A\u064A\u0627\u0631 \u0627\u0644\u0645\u0631\u0627\u062C\u0639",
8317
8411
  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.",
8318
8412
  editCitation: "\u062A\u062D\u0631\u064A\u0631 \u0627\u0644\u0627\u0642\u062A\u0628\u0627\u0633",
@@ -8443,6 +8537,15 @@ var DOCUMENT2_MESSAGES = {
8443
8537
  labelKindFig: "Figure",
8444
8538
  labelKindTab: "Table",
8445
8539
  labelKindEq: "Equation",
8540
+ captionPreview: "Caption preview",
8541
+ referencePreview: "Reference preview",
8542
+ referenceFieldSeparator: "Field separator",
8543
+ referenceCommaLtr: "Latin comma ,",
8544
+ referenceCommaRtl: "Arabic comma \u060C",
8545
+ keyEmpty: "Key is required",
8546
+ keyInvalid: "Invalid key: letters, digits, and `:._-` only; no spaces",
8547
+ keyDuplicate: "This key is already in use",
8548
+ keyRulesHint: "Letters (Arabic or Latin), digits, and `:._-`; no spaces",
8446
8549
  citePickerTitle: "Select references",
8447
8550
  noReferencesYet: "No references yet. Add a reference first.",
8448
8551
  editCitation: "Edit citation",
@@ -8680,7 +8783,10 @@ function focusArticleMetaPanel(panel) {
8680
8783
  }
8681
8784
 
8682
8785
  // src/react-document2/ButexDocumentEditor2.tsx
8683
- import { useCallback as useCallback2, useEffect as useEffect8, useMemo, useRef as useRef7, useState as useState9 } from "react";
8786
+ import { useCallback as useCallback2, useEffect as useEffect8, useMemo as useMemo2, useRef as useRef7, useState as useState12 } from "react";
8787
+
8788
+ // src/react-document2/BlockEditor.tsx
8789
+ import { useState as useState3 } from "react";
8684
8790
 
8685
8791
  // src/react-document2/InlineField.tsx
8686
8792
  import { useRef as useRef3 } from "react";
@@ -9717,6 +9823,18 @@ function inlineFieldSummary(field) {
9717
9823
  }).join("")
9718
9824
  );
9719
9825
  }
9826
+ function keyErrorMessage(error, messages) {
9827
+ if (error === "empty") {
9828
+ return messages.keyEmpty;
9829
+ }
9830
+ if (error === "invalid") {
9831
+ return messages.keyInvalid;
9832
+ }
9833
+ if (error === "duplicate") {
9834
+ return messages.keyDuplicate;
9835
+ }
9836
+ return null;
9837
+ }
9720
9838
  function FloatMetaEditor({
9721
9839
  captionEnabled,
9722
9840
  caption,
@@ -9725,8 +9843,18 @@ function FloatMetaEditor({
9725
9843
  labelPlaceholder,
9726
9844
  labelDir,
9727
9845
  messages,
9846
+ ownerId,
9847
+ references,
9848
+ labels,
9728
9849
  onChange
9729
9850
  }) {
9851
+ const [labelOverride, setLabelOverride] = useState3(null);
9852
+ const displayedLabel = labelOverride ?? label;
9853
+ const labelError = labelEnabled ? document2KeyError(displayedLabel, {
9854
+ references,
9855
+ labels,
9856
+ excludeOwnerId: ownerId
9857
+ }) : null;
9730
9858
  return /* @__PURE__ */ jsxs5("div", { className: "butex-document2-widget__float-meta", children: [
9731
9859
  /* @__PURE__ */ jsxs5("label", { className: "butex-document2-widget__float-meta-toggle", children: [
9732
9860
  /* @__PURE__ */ jsx7(
@@ -9776,15 +9904,27 @@ function FloatMetaEditor({
9776
9904
  /* @__PURE__ */ jsx7(
9777
9905
  "input",
9778
9906
  {
9779
- value: label,
9907
+ value: displayedLabel,
9780
9908
  dir: labelDir,
9781
9909
  placeholder: labelPlaceholder,
9910
+ "aria-invalid": labelError !== null ? true : void 0,
9782
9911
  onChange: (event) => {
9783
9912
  const value = event.currentTarget.value;
9913
+ setLabelOverride(value);
9914
+ const error = document2KeyError(value, {
9915
+ references,
9916
+ labels,
9917
+ excludeOwnerId: ownerId
9918
+ });
9919
+ if (error !== null) {
9920
+ return;
9921
+ }
9784
9922
  onChange({ label: value });
9923
+ setLabelOverride(null);
9785
9924
  }
9786
9925
  }
9787
- )
9926
+ ),
9927
+ labelError !== null ? /* @__PURE__ */ jsx7("p", { className: "butex-document2-widget__field-error", children: labelError === "invalid" ? messages.keyRulesHint : keyErrorMessage(labelError, messages) }) : null
9788
9928
  ] }) : null
9789
9929
  ] });
9790
9930
  }
@@ -9843,6 +9983,8 @@ function BlockEditor({
9843
9983
  onManageReferences
9844
9984
  }) {
9845
9985
  const messages = document2Messages(uiLocale);
9986
+ const labels = documentNode ? collectDocument2Labels(documentNode) : [];
9987
+ const referenceList = references ?? [];
9846
9988
  const showChrome = depth === 0;
9847
9989
  const chromeClass = [
9848
9990
  blockChromeClass(block),
@@ -10005,6 +10147,9 @@ function BlockEditor({
10005
10147
  labelPlaceholder: messages.tableLabelPlaceholder,
10006
10148
  labelDir: uiLocaleDirection(uiLocale),
10007
10149
  messages,
10150
+ ownerId: block.id,
10151
+ references: referenceList,
10152
+ labels,
10008
10153
  onChange: (patch) => onFloatMetaChange?.(block.id, "table", patch)
10009
10154
  }
10010
10155
  )
@@ -10048,6 +10193,9 @@ function BlockEditor({
10048
10193
  labelPlaceholder: messages.figureLabelPlaceholder,
10049
10194
  labelDir: uiLocaleDirection(uiLocale),
10050
10195
  messages,
10196
+ ownerId: block.id,
10197
+ references: referenceList,
10198
+ labels,
10051
10199
  onChange: (patch) => onFloatMetaChange?.(block.id, "image", patch)
10052
10200
  }
10053
10201
  )
@@ -10056,14 +10204,16 @@ function BlockEditor({
10056
10204
  if (block.kind === "bibliography") {
10057
10205
  return /* @__PURE__ */ jsxs5("section", { className: chromeClass, children: [
10058
10206
  header,
10059
- /* @__PURE__ */ jsx7("ol", { className: "butex-document2-widget__bibliography-editor", dir: documentDirection, children: references.map((reference, index) => /* @__PURE__ */ jsxs5("li", { children: [
10207
+ /* @__PURE__ */ jsx7("ol", { className: "butex-document2-widget__bibliography-editor", dir: documentDirection, children: referenceList.map((reference, index) => /* @__PURE__ */ jsxs5("li", { children: [
10060
10208
  /* @__PURE__ */ jsxs5("strong", { children: [
10061
10209
  "[",
10062
- index + 1,
10210
+ formatBibliographyNumber(index + 1, { documentDirection, digitForm }),
10063
10211
  "] ",
10064
10212
  reference.key
10065
10213
  ] }),
10066
- /* @__PURE__ */ jsx7("span", { children: [reference.authors, reference.title, reference.venue, reference.year].filter(Boolean).join(" \u2014 ") })
10214
+ /* @__PURE__ */ jsx7("span", { children: bibliographyEntryBody(reference, reference.fieldSeparator, {
10215
+ digitForm: digitForm ?? (documentDirection === "rtl" ? "arabicIndic" : "western")
10216
+ }) })
10067
10217
  ] }, reference.id)) }),
10068
10218
  onManageReferences ? /* @__PURE__ */ jsx7("button", { type: "button", onClick: onManageReferences, children: messages.manageReferences }) : null
10069
10219
  ] });
@@ -10075,19 +10225,21 @@ function BlockEditor({
10075
10225
  }
10076
10226
 
10077
10227
  // src/react-document2/CitePickerPopover.tsx
10078
- import { useEffect as useEffect3, useState as useState3 } from "react";
10228
+ import { useEffect as useEffect3, useState as useState4 } from "react";
10079
10229
  import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
10080
10230
  function CitePickerPopover({
10081
10231
  open,
10082
10232
  references,
10083
10233
  initialKeys = [],
10084
10234
  uiLocale = "ar",
10235
+ digitForm = "arabicIndic",
10085
10236
  onClose,
10086
10237
  onConfirm,
10087
10238
  onManageReferences
10088
10239
  }) {
10089
10240
  const messages = document2Messages(uiLocale);
10090
- const [selected, setSelected] = useState3(initialKeys);
10241
+ const documentDirection = uiLocale === "ar" ? "rtl" : "ltr";
10242
+ const [selected, setSelected] = useState4(initialKeys);
10091
10243
  useEffect3(() => {
10092
10244
  if (open) {
10093
10245
  setSelected(initialKeys);
@@ -10114,12 +10266,13 @@ function CitePickerPopover({
10114
10266
  references.length === 0 ? /* @__PURE__ */ jsx8("p", { className: "butex-document2-widget__cite-picker-empty", children: messages.noReferencesYet }) : /* @__PURE__ */ jsx8("ul", { className: "butex-document2-widget__cite-picker-list", children: references.map((reference, index) => {
10115
10267
  const checked = selected.includes(reference.key);
10116
10268
  const subtitle = [reference.authors, reference.title].filter(Boolean).join(" \u2014 ");
10269
+ const numberLabel = formatBibliographyNumber(index + 1, { documentDirection, digitForm });
10117
10270
  return /* @__PURE__ */ jsx8("li", { children: /* @__PURE__ */ jsxs6("label", { className: "butex-document2-widget__cite-picker-item", children: [
10118
10271
  /* @__PURE__ */ jsx8("input", { type: "checkbox", checked, onChange: () => toggleKey(reference.key) }),
10119
10272
  /* @__PURE__ */ jsxs6("span", { children: [
10120
10273
  /* @__PURE__ */ jsxs6("strong", { children: [
10121
10274
  "[",
10122
- index + 1,
10275
+ numberLabel,
10123
10276
  "] ",
10124
10277
  reference.key
10125
10278
  ] }),
@@ -10147,16 +10300,16 @@ function CitePickerPopover({
10147
10300
  }
10148
10301
 
10149
10302
  // src/react-document2/DocumentInsertToolbar.tsx
10150
- import { useState as useState5 } from "react";
10303
+ import { useState as useState6 } from "react";
10151
10304
 
10152
10305
  // src/react-document2/TableInsertPopover.tsx
10153
- import { useEffect as useEffect4, useRef as useRef4, useState as useState4 } from "react";
10306
+ import { useEffect as useEffect4, useRef as useRef4, useState as useState5 } from "react";
10154
10307
  import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
10155
10308
  function TableInsertPopover({ uiLocale = "ar", onConfirm }) {
10156
10309
  const messages = document2Messages(uiLocale);
10157
- const [open, setOpen] = useState4(false);
10158
- const [rows, setRows] = useState4("3");
10159
- const [cols, setCols] = useState4("3");
10310
+ const [open, setOpen] = useState5(false);
10311
+ const [rows, setRows] = useState5("3");
10312
+ const [cols, setCols] = useState5("3");
10160
10313
  const rootRef = useRef4(null);
10161
10314
  useEffect4(() => {
10162
10315
  if (!open) {
@@ -10249,7 +10402,7 @@ function DocumentInsertToolbar({
10249
10402
  onDigitFormChange
10250
10403
  }) {
10251
10404
  const messages = document2Messages(uiLocale);
10252
- const [digitMenuOpen, setDigitMenuOpen] = useState5(false);
10405
+ const [digitMenuOpen, setDigitMenuOpen] = useState6(false);
10253
10406
  function digitTitle(id) {
10254
10407
  if (id === "arabicIndic") {
10255
10408
  return messages.arabicIndicDigits;
@@ -10420,7 +10573,8 @@ function PreviewBlock({
10420
10573
  output,
10421
10574
  resolveImageUrl,
10422
10575
  uiLocale,
10423
- documentDirection
10576
+ documentDirection,
10577
+ digitForm
10424
10578
  }) {
10425
10579
  const messages = document2Messages(uiLocale);
10426
10580
  const floatCaptionSeparator = uiLocale === "ar" ? ": " : ". ";
@@ -10479,7 +10633,8 @@ function PreviewBlock({
10479
10633
  output,
10480
10634
  resolveImageUrl,
10481
10635
  uiLocale,
10482
- documentDirection
10636
+ documentDirection,
10637
+ digitForm
10483
10638
  },
10484
10639
  child.id
10485
10640
  ))
@@ -10509,10 +10664,10 @@ function PreviewBlock({
10509
10664
  ] }),
10510
10665
  " ",
10511
10666
  /* @__PURE__ */ jsxs9("span", { children: [
10512
- [item.authors, item.title, item.venue, item.year].filter(Boolean).join(", "),
10667
+ bibliographyEntryBody(item, item.fieldSeparator, { digitForm }),
10513
10668
  item.url ? /* @__PURE__ */ jsxs9(Fragment, { children: [
10514
10669
  " ",
10515
- /* @__PURE__ */ jsx11("a", { href: item.url, target: "_blank", rel: "noreferrer", children: item.url })
10670
+ /* @__PURE__ */ jsx11("a", { href: absoluteHttpHref(item.url), target: "_blank", rel: "noreferrer", children: item.url })
10516
10671
  ] }) : null
10517
10672
  ] })
10518
10673
  ] }, item.id)) });
@@ -10524,9 +10679,11 @@ function DocumentPreview({
10524
10679
  output,
10525
10680
  documentDirection = "rtl",
10526
10681
  uiLocale = "ar",
10682
+ digitForm,
10527
10683
  resolveImageUrl
10528
10684
  }) {
10529
10685
  const messages = document2Messages(uiLocale);
10686
+ const resolvedDigitForm = digitForm ?? (documentDirection === "rtl" ? "arabicIndic" : "western");
10530
10687
  const hasBody = blocks.some(isBodyPreviewBlock);
10531
10688
  return /* @__PURE__ */ jsxs9("div", { className: "butex-document2-widget__preview", dir: documentDirection, children: [
10532
10689
  blocks.map((block) => /* @__PURE__ */ jsx11(
@@ -10536,7 +10693,8 @@ function DocumentPreview({
10536
10693
  output,
10537
10694
  resolveImageUrl,
10538
10695
  uiLocale,
10539
- documentDirection
10696
+ documentDirection,
10697
+ digitForm: resolvedDigitForm
10540
10698
  },
10541
10699
  block.id
10542
10700
  )),
@@ -10545,7 +10703,7 @@ function DocumentPreview({
10545
10703
  }
10546
10704
 
10547
10705
  // src/react-document2/EquationDrawer.tsx
10548
- import { useEffect as useEffect6, useRef as useRef6 } from "react";
10706
+ import { useEffect as useEffect6, useRef as useRef6, useState as useState8 } from "react";
10549
10707
 
10550
10708
  // src/react/ButexEditor.tsx
10551
10709
  import {
@@ -10554,7 +10712,7 @@ import {
10554
10712
  useEffect as useEffect5,
10555
10713
  useImperativeHandle,
10556
10714
  useRef as useRef5,
10557
- useState as useState6
10715
+ useState as useState7
10558
10716
  } from "react";
10559
10717
 
10560
10718
  // src/react/widgetChromeCss.ts
@@ -11626,32 +11784,32 @@ var ButexEditor = forwardRef(
11626
11784
  const onSessionChangeRef = useRef5(onSessionChange);
11627
11785
  onSessionChangeRef.current = onSessionChange;
11628
11786
  const debugBodyHiddenRef = useRef5(false);
11629
- const [debugBodyHidden, setDebugBodyHidden] = useState6(false);
11787
+ const [debugBodyHidden, setDebugBodyHidden] = useState7(false);
11630
11788
  debugBodyHiddenRef.current = debugBodyHidden;
11631
- const [digitMenuOpen, setDigitMenuOpen] = useState6(false);
11632
- const [characterFontMenuOpen, setCharacterFontMenuOpen] = useState6(false);
11633
- const [delimiterMenuOpen, setDelimiterMenuOpen] = useState6(false);
11634
- const [matrixMenuOpen, setMatrixMenuOpen] = useState6(false);
11635
- const [spacingMenuOpen, setSpacingMenuOpen] = useState6(false);
11636
- const [functionMenuOpen, setFunctionMenuOpen] = useState6(false);
11637
- const [limitsSeriesMenuOpen, setLimitsSeriesMenuOpen] = useState6(false);
11638
- const [function2MenuOpen, setFunction2MenuOpen] = useState6(false);
11639
- const [derivativeMenuOpen, setDerivativeMenuOpen] = useState6(false);
11640
- const [groupMenuOpen, setGroupMenuOpen] = useState6(false);
11641
- const [operatorMenuOpen, setOperatorMenuOpen] = useState6(false);
11642
- const [operator2MenuOpen, setOperator2MenuOpen] = useState6(false);
11643
- const [operator3MenuOpen, setOperator3MenuOpen] = useState6(false);
11644
- const [dotMenuOpen, setDotMenuOpen] = useState6(false);
11645
- const [integralMenuOpen, setIntegralMenuOpen] = useState6(false);
11646
- const [selectedDigitForm2, setSelectedDigitForm] = useState6("western");
11647
- const [selectedCharacterFont, setSelectedCharacterFont] = useState6("default");
11648
- const [activeEditorSide, setActiveEditorSide] = useState6("arabic");
11649
- const [envPaletteMode, setEnvPaletteMode] = useState6("matrix");
11650
- const [matrixStyle, setMatrixStyle] = useState6("pmatrix");
11651
- const [matrixRows, setMatrixRows] = useState6(2);
11652
- const [matrixColumns, setMatrixColumns] = useState6(2);
11653
- const [matrixHover, setMatrixHover] = useState6(null);
11654
- const [arrayAlignmentColumn, setArrayAlignmentColumn] = useState6(1);
11789
+ const [digitMenuOpen, setDigitMenuOpen] = useState7(false);
11790
+ const [characterFontMenuOpen, setCharacterFontMenuOpen] = useState7(false);
11791
+ const [delimiterMenuOpen, setDelimiterMenuOpen] = useState7(false);
11792
+ const [matrixMenuOpen, setMatrixMenuOpen] = useState7(false);
11793
+ const [spacingMenuOpen, setSpacingMenuOpen] = useState7(false);
11794
+ const [functionMenuOpen, setFunctionMenuOpen] = useState7(false);
11795
+ const [limitsSeriesMenuOpen, setLimitsSeriesMenuOpen] = useState7(false);
11796
+ const [function2MenuOpen, setFunction2MenuOpen] = useState7(false);
11797
+ const [derivativeMenuOpen, setDerivativeMenuOpen] = useState7(false);
11798
+ const [groupMenuOpen, setGroupMenuOpen] = useState7(false);
11799
+ const [operatorMenuOpen, setOperatorMenuOpen] = useState7(false);
11800
+ const [operator2MenuOpen, setOperator2MenuOpen] = useState7(false);
11801
+ const [operator3MenuOpen, setOperator3MenuOpen] = useState7(false);
11802
+ const [dotMenuOpen, setDotMenuOpen] = useState7(false);
11803
+ const [integralMenuOpen, setIntegralMenuOpen] = useState7(false);
11804
+ const [selectedDigitForm2, setSelectedDigitForm] = useState7("western");
11805
+ const [selectedCharacterFont, setSelectedCharacterFont] = useState7("default");
11806
+ const [activeEditorSide, setActiveEditorSide] = useState7("arabic");
11807
+ const [envPaletteMode, setEnvPaletteMode] = useState7("matrix");
11808
+ const [matrixStyle, setMatrixStyle] = useState7("pmatrix");
11809
+ const [matrixRows, setMatrixRows] = useState7(2);
11810
+ const [matrixColumns, setMatrixColumns] = useState7(2);
11811
+ const [matrixHover, setMatrixHover] = useState7(null);
11812
+ const [arrayAlignmentColumn, setArrayAlignmentColumn] = useState7(1);
11655
11813
  useImperativeHandle(ref, () => ({
11656
11814
  getRuntime: () => runtimeRef.current
11657
11815
  }));
@@ -12836,6 +12994,18 @@ ButexEditor.displayName = "ButexEditor";
12836
12994
 
12837
12995
  // src/react-document2/EquationDrawer.tsx
12838
12996
  import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
12997
+ function keyErrorMessage2(error, messages) {
12998
+ if (error === "empty") {
12999
+ return messages.keyEmpty;
13000
+ }
13001
+ if (error === "invalid") {
13002
+ return messages.keyInvalid;
13003
+ }
13004
+ if (error === "duplicate") {
13005
+ return messages.keyDuplicate;
13006
+ }
13007
+ return null;
13008
+ }
12839
13009
  function EquationDrawer({
12840
13010
  session,
12841
13011
  reason,
@@ -12845,6 +13015,9 @@ function EquationDrawer({
12845
13015
  uiLocale = "ar",
12846
13016
  labelEnabled = false,
12847
13017
  label = "",
13018
+ labels = [],
13019
+ references = [],
13020
+ ownerId = "",
12848
13021
  onLabelEnabledChange,
12849
13022
  onLabelChange,
12850
13023
  onMathModeChange,
@@ -12854,6 +13027,16 @@ function EquationDrawer({
12854
13027
  }) {
12855
13028
  const messages = document2Messages(uiLocale);
12856
13029
  const latestSession = useRef6(session);
13030
+ const [labelOverride, setLabelOverride] = useState8(null);
13031
+ const displayedLabel = labelOverride ?? label;
13032
+ const labelError = labelEnabled && mathMode === "display" ? document2KeyError(displayedLabel, {
13033
+ references,
13034
+ labels,
13035
+ excludeOwnerId: ownerId || void 0
13036
+ }) : null;
13037
+ useEffect6(() => {
13038
+ setLabelOverride(null);
13039
+ }, [ownerId, label]);
12857
13040
  useEffect6(() => {
12858
13041
  const onKeyDown = (event) => {
12859
13042
  if (event.key === "Escape") {
@@ -12914,12 +13097,27 @@ function EquationDrawer({
12914
13097
  /* @__PURE__ */ jsx13(
12915
13098
  "input",
12916
13099
  {
12917
- value: label,
13100
+ value: displayedLabel,
12918
13101
  dir: uiLocaleDirection(uiLocale),
12919
13102
  placeholder: messages.equationLabelPlaceholder,
12920
- onChange: (event) => onLabelChange?.(event.currentTarget.value)
13103
+ "aria-invalid": labelError !== null ? true : void 0,
13104
+ onChange: (event) => {
13105
+ const value = event.currentTarget.value;
13106
+ setLabelOverride(value);
13107
+ const error = document2KeyError(value, {
13108
+ references,
13109
+ labels,
13110
+ excludeOwnerId: ownerId || void 0
13111
+ });
13112
+ if (error !== null) {
13113
+ return;
13114
+ }
13115
+ onLabelChange?.(value);
13116
+ setLabelOverride(null);
13117
+ }
12921
13118
  }
12922
- )
13119
+ ),
13120
+ labelError !== null ? /* @__PURE__ */ jsx13("p", { className: "butex-document2-widget__field-error", children: labelError === "invalid" ? messages.keyRulesHint : keyErrorMessage2(labelError, messages) }) : null
12923
13121
  ] }) : null
12924
13122
  ] }) : null,
12925
13123
  reason ? /* @__PURE__ */ jsx13("p", { className: "butex-document2-widget__error", children: uiLocale === "en" ? messages.equationUnavailable : reason }) : null,
@@ -12937,7 +13135,15 @@ function EquationDrawer({
12937
13135
  ),
12938
13136
  /* @__PURE__ */ jsxs11("div", { className: "butex-document2-widget__row", children: [
12939
13137
  canDelete && onDelete ? /* @__PURE__ */ jsx13("button", { type: "button", className: "butex-document2-widget__button--danger", onClick: onDelete, children: messages.deleteEquation }) : null,
12940
- /* @__PURE__ */ jsx13("button", { type: "button", onClick: () => onSave({ ...latestSession.current, activeSide: equationSide }), children: messages.saveEquation })
13138
+ /* @__PURE__ */ jsx13(
13139
+ "button",
13140
+ {
13141
+ type: "button",
13142
+ disabled: labelEnabled && mathMode === "display" && labelError !== null,
13143
+ onClick: () => onSave({ ...latestSession.current, activeSide: equationSide }),
13144
+ children: messages.saveEquation
13145
+ }
13146
+ )
12941
13147
  ] })
12942
13148
  ]
12943
13149
  }
@@ -12946,92 +13152,243 @@ function EquationDrawer({
12946
13152
  }
12947
13153
 
12948
13154
  // src/react-document2/LabelsPanel.tsx
13155
+ import { useState as useState9 } from "react";
12949
13156
  import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
12950
- function kindLabel(kind, uiLocale) {
12951
- const messages = document2Messages(uiLocale);
12952
- if (kind === "fig") {
12953
- return messages.labelKindFig;
13157
+ function keyErrorMessage3(error, messages) {
13158
+ if (error === "empty") {
13159
+ return messages.keyEmpty;
12954
13160
  }
12955
- if (kind === "tab") {
12956
- return messages.labelKindTab;
13161
+ if (error === "invalid") {
13162
+ return messages.keyInvalid;
12957
13163
  }
12958
- return messages.labelKindEq;
13164
+ if (error === "duplicate") {
13165
+ return messages.keyDuplicate;
13166
+ }
13167
+ return null;
12959
13168
  }
12960
13169
  function LabelsPanel({
12961
13170
  open,
12962
13171
  labels,
13172
+ references = [],
12963
13173
  uiLocale = "ar",
13174
+ digitForm = "arabicIndic",
12964
13175
  onClose,
12965
13176
  onUpdateFloat,
12966
13177
  onUpdateEquationLabel
12967
13178
  }) {
12968
13179
  const messages = document2Messages(uiLocale);
13180
+ const documentDirection = uiLocale === "ar" ? "rtl" : "ltr";
13181
+ const [keyOverrides, setKeyOverrides] = useState9({});
12969
13182
  if (!open) {
12970
13183
  return null;
12971
13184
  }
12972
- return /* @__PURE__ */ jsx14("div", { className: "butex-document2-widget__refs-backdrop", role: "presentation", onClick: onClose, children: /* @__PURE__ */ jsxs12("div", { className: "butex-document2-widget__refs-panel", role: "dialog", "aria-label": messages.labelsTitle, onClick: (event) => event.stopPropagation(), children: [
12973
- /* @__PURE__ */ jsxs12("header", { className: "butex-document2-widget__refs-header", children: [
12974
- /* @__PURE__ */ jsx14("strong", { children: messages.labelsTitle }),
12975
- /* @__PURE__ */ jsx14("button", { type: "button", className: "butex-document2-widget__icon-btn", title: messages.close, "aria-label": messages.close, onClick: onClose, children: "\xD7" })
12976
- ] }),
12977
- /* @__PURE__ */ jsx14("p", { className: "butex-document2-widget__labels-help", children: messages.labelsHelp }),
12978
- labels.length === 0 ? /* @__PURE__ */ jsx14("p", { className: "butex-document2-widget__cite-picker-empty", children: messages.noLabelsYet }) : /* @__PURE__ */ jsx14("ul", { className: "butex-document2-widget__refs-list", children: labels.map((entry) => /* @__PURE__ */ jsxs12("li", { className: "butex-document2-widget__refs-item", children: [
12979
- /* @__PURE__ */ jsx14("div", { className: "butex-document2-widget__refs-item-head", children: /* @__PURE__ */ jsxs12("strong", { children: [
12980
- "[",
12981
- kindLabel(entry.kind, uiLocale),
12982
- " ",
12983
- entry.number,
12984
- "] ",
12985
- entry.key
12986
- ] }) }),
12987
- /* @__PURE__ */ jsxs12("div", { className: "butex-document2-widget__refs-grid", children: [
12988
- /* @__PURE__ */ jsxs12("label", { className: "butex-document2-widget__refs-field", children: [
12989
- /* @__PURE__ */ jsx14("span", { children: messages.floatLabel }),
12990
- /* @__PURE__ */ jsx14(
12991
- "input",
12992
- {
12993
- value: entry.key,
12994
- dir: uiLocaleDirection(uiLocale),
12995
- onChange: (event) => {
12996
- const value = event.currentTarget.value;
12997
- if (entry.kind === "eq") {
12998
- onUpdateEquationLabel?.(entry.ownerId, { label: value, labelEnabled: true });
12999
- } else if (entry.kind === "fig" || entry.kind === "tab") {
13000
- onUpdateFloat?.(entry.ownerId, entry.kind, { label: value, labelEnabled: true });
13001
- }
13002
- }
13003
- }
13004
- )
13185
+ return /* @__PURE__ */ jsx14("div", { className: "butex-document2-widget__refs-backdrop", role: "presentation", onClick: onClose, children: /* @__PURE__ */ jsxs12(
13186
+ "div",
13187
+ {
13188
+ className: "butex-document2-widget__refs-panel",
13189
+ role: "dialog",
13190
+ "aria-label": messages.labelsTitle,
13191
+ onClick: (event) => event.stopPropagation(),
13192
+ children: [
13193
+ /* @__PURE__ */ jsxs12("header", { className: "butex-document2-widget__refs-header", children: [
13194
+ /* @__PURE__ */ jsx14("strong", { children: messages.labelsTitle }),
13195
+ /* @__PURE__ */ jsx14("button", { type: "button", className: "butex-document2-widget__icon-btn", title: messages.close, "aria-label": messages.close, onClick: onClose, children: "\xD7" })
13005
13196
  ] }),
13006
- entry.kind === "fig" || entry.kind === "tab" ? /* @__PURE__ */ jsxs12("label", { className: "butex-document2-widget__refs-field", children: [
13007
- /* @__PURE__ */ jsx14("span", { children: messages.floatCaption }),
13008
- /* @__PURE__ */ jsx14(
13009
- "input",
13010
- {
13011
- value: entry.caption,
13012
- onChange: (event) => {
13013
- const value = event.currentTarget.value;
13014
- const kind = entry.kind;
13015
- if (kind === "fig" || kind === "tab") {
13016
- onUpdateFloat?.(entry.ownerId, kind, { caption: value, captionEnabled: true });
13017
- }
13197
+ /* @__PURE__ */ jsx14("p", { className: "butex-document2-widget__labels-help", children: messages.labelsHelp }),
13198
+ labels.length === 0 ? /* @__PURE__ */ jsx14("p", { className: "butex-document2-widget__cite-picker-empty", children: messages.noLabelsYet }) : /* @__PURE__ */ jsx14("ul", { className: "butex-document2-widget__refs-list", children: labels.map((entry) => {
13199
+ const title = formatFloatCaptionTitle(entry.kind, entry.number, {
13200
+ uiLocale,
13201
+ digitForm,
13202
+ documentDirection
13203
+ });
13204
+ const captionPreview = entry.kind === "eq" ? title : formatFloatCaptionPreview(title, entry.caption, uiLocale);
13205
+ const overrideKey = `${entry.kind}:${entry.ownerId}`;
13206
+ const displayedKey = keyOverrides[overrideKey] ?? entry.key;
13207
+ const entryKeyError = document2KeyError(displayedKey, {
13208
+ references,
13209
+ labels,
13210
+ excludeOwnerId: entry.ownerId
13211
+ });
13212
+ return /* @__PURE__ */ jsxs12("li", { className: "butex-document2-widget__refs-item", children: [
13213
+ /* @__PURE__ */ jsxs12("div", { className: "butex-document2-widget__refs-item-head", children: [
13214
+ /* @__PURE__ */ jsx14("strong", { children: title }),
13215
+ /* @__PURE__ */ jsx14("span", { className: "butex-document2-widget__refs-item-key", children: entry.key })
13216
+ ] }),
13217
+ /* @__PURE__ */ jsx14(
13218
+ "div",
13219
+ {
13220
+ className: "butex-document2-widget__modal-preview",
13221
+ dir: uiLocaleDirection(uiLocale),
13222
+ "aria-label": messages.captionPreview,
13223
+ children: captionPreview
13018
13224
  }
13019
- }
13020
- )
13021
- ] }) : null
13022
- ] })
13023
- ] }, `${entry.kind}:${entry.ownerId}`)) })
13024
- ] }) });
13225
+ ),
13226
+ /* @__PURE__ */ jsxs12("div", { className: "butex-document2-widget__refs-grid", children: [
13227
+ /* @__PURE__ */ jsxs12("label", { className: "butex-document2-widget__refs-field", children: [
13228
+ /* @__PURE__ */ jsx14("span", { children: messages.floatLabel }),
13229
+ /* @__PURE__ */ jsx14(
13230
+ "input",
13231
+ {
13232
+ value: displayedKey,
13233
+ dir: uiLocaleDirection(uiLocale),
13234
+ "aria-invalid": entryKeyError !== null ? true : void 0,
13235
+ onChange: (event) => {
13236
+ const value = event.currentTarget.value;
13237
+ setKeyOverrides((current) => ({ ...current, [overrideKey]: value }));
13238
+ const error = document2KeyError(value, {
13239
+ references,
13240
+ labels,
13241
+ excludeOwnerId: entry.ownerId
13242
+ });
13243
+ if (error !== null) {
13244
+ return;
13245
+ }
13246
+ if (entry.kind === "eq") {
13247
+ onUpdateEquationLabel?.(entry.ownerId, { label: value, labelEnabled: true });
13248
+ } else if (entry.kind === "fig" || entry.kind === "tab") {
13249
+ onUpdateFloat?.(entry.ownerId, entry.kind, { label: value, labelEnabled: true });
13250
+ }
13251
+ setKeyOverrides((current) => {
13252
+ const next = { ...current };
13253
+ delete next[overrideKey];
13254
+ return next;
13255
+ });
13256
+ }
13257
+ }
13258
+ ),
13259
+ entryKeyError !== null ? /* @__PURE__ */ jsx14("p", { className: "butex-document2-widget__field-error", children: entryKeyError === "invalid" ? messages.keyRulesHint : keyErrorMessage3(entryKeyError, messages) }) : null
13260
+ ] }),
13261
+ entry.kind === "fig" || entry.kind === "tab" ? /* @__PURE__ */ jsxs12("label", { className: "butex-document2-widget__refs-field", children: [
13262
+ /* @__PURE__ */ jsx14("span", { children: messages.floatCaption }),
13263
+ /* @__PURE__ */ jsx14(
13264
+ "input",
13265
+ {
13266
+ value: entry.caption,
13267
+ onChange: (event) => {
13268
+ const value = event.currentTarget.value;
13269
+ const kind = entry.kind;
13270
+ if (kind === "fig" || kind === "tab") {
13271
+ onUpdateFloat?.(entry.ownerId, kind, { caption: value, captionEnabled: true });
13272
+ }
13273
+ }
13274
+ }
13275
+ )
13276
+ ] }) : null
13277
+ ] })
13278
+ ] }, overrideKey);
13279
+ }) })
13280
+ ]
13281
+ }
13282
+ ) });
13025
13283
  }
13026
13284
 
13027
13285
  // src/react-document2/ReferencesPanel.tsx
13028
- import { useState as useState7 } from "react";
13029
- import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
13030
- var EMPTY_DRAFT = { key: "", authors: "", title: "", year: "", url: "", venue: "" };
13286
+ import { useMemo, useState as useState10 } from "react";
13287
+ import { Fragment as Fragment3, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
13288
+ var EMPTY_DRAFT = {
13289
+ key: "",
13290
+ authors: "",
13291
+ title: "",
13292
+ year: "",
13293
+ url: "",
13294
+ venue: "",
13295
+ field_separator: DEFAULT_REFERENCE_FIELD_SEPARATOR
13296
+ };
13297
+ var REFERENCE_FIELDS = [
13298
+ ["key", "referenceKey"],
13299
+ ["authors", "referenceAuthors"],
13300
+ ["title", "referenceTitle"],
13301
+ ["year", "referenceYear"],
13302
+ ["venue", "referenceVenue"],
13303
+ ["url", "referenceUrl"]
13304
+ ];
13305
+ function keyErrorMessage4(error, messages) {
13306
+ if (error === "empty") {
13307
+ return messages.keyEmpty;
13308
+ }
13309
+ if (error === "invalid") {
13310
+ return messages.keyInvalid;
13311
+ }
13312
+ if (error === "duplicate") {
13313
+ return messages.keyDuplicate;
13314
+ }
13315
+ return null;
13316
+ }
13317
+ function FieldSeparatorToggle({
13318
+ value,
13319
+ messages,
13320
+ onChange
13321
+ }) {
13322
+ return /* @__PURE__ */ jsxs13("div", { className: "butex-document2-widget__refs-field butex-document2-widget__refs-separator", children: [
13323
+ /* @__PURE__ */ jsx15("span", { children: messages.referenceFieldSeparator }),
13324
+ /* @__PURE__ */ jsxs13("div", { className: "butex-document2-widget__refs-separator-toggle", role: "group", "aria-label": messages.referenceFieldSeparator, children: [
13325
+ /* @__PURE__ */ jsx15(
13326
+ "button",
13327
+ {
13328
+ type: "button",
13329
+ className: value === "\u060C" ? "is-active" : void 0,
13330
+ title: messages.referenceCommaRtl,
13331
+ "aria-label": messages.referenceCommaRtl,
13332
+ "aria-pressed": value === "\u060C",
13333
+ onClick: () => onChange("\u060C"),
13334
+ children: "\u060C"
13335
+ }
13336
+ ),
13337
+ /* @__PURE__ */ jsx15(
13338
+ "button",
13339
+ {
13340
+ type: "button",
13341
+ className: value === "," ? "is-active" : void 0,
13342
+ title: messages.referenceCommaLtr,
13343
+ "aria-label": messages.referenceCommaLtr,
13344
+ "aria-pressed": value === ",",
13345
+ onClick: () => onChange(","),
13346
+ children: ","
13347
+ }
13348
+ )
13349
+ ] })
13350
+ ] });
13351
+ }
13352
+ function ReferencePreview({
13353
+ authors,
13354
+ title,
13355
+ venue,
13356
+ year,
13357
+ url,
13358
+ fieldSeparator,
13359
+ numberLabel,
13360
+ messages,
13361
+ uiLocale,
13362
+ digitForm
13363
+ }) {
13364
+ const body = bibliographyEntryBody({ authors, title, venue, year, fieldSeparator }, fieldSeparator, { digitForm });
13365
+ return /* @__PURE__ */ jsxs13(
13366
+ "div",
13367
+ {
13368
+ className: "butex-document2-widget__modal-preview",
13369
+ dir: uiLocaleDirection(uiLocale),
13370
+ "aria-label": messages.referencePreview,
13371
+ children: [
13372
+ numberLabel ? /* @__PURE__ */ jsxs13("span", { className: "butex-document2-widget__modal-preview-number", children: [
13373
+ "[",
13374
+ numberLabel,
13375
+ "] "
13376
+ ] }) : null,
13377
+ body.length > 0 ? body : /* @__PURE__ */ jsx15("span", { className: "butex-document2-widget__cite-picker-empty", children: "\u2026" }),
13378
+ url.trim().length > 0 ? /* @__PURE__ */ jsxs13(Fragment3, { children: [
13379
+ " ",
13380
+ /* @__PURE__ */ jsx15("span", { className: "butex-document2-widget__modal-preview-url", children: url.trim() })
13381
+ ] }) : null
13382
+ ]
13383
+ }
13384
+ );
13385
+ }
13031
13386
  function ReferencesPanel({
13032
13387
  open,
13033
13388
  references,
13389
+ labels = [],
13034
13390
  uiLocale = "ar",
13391
+ digitForm = "arabicIndic",
13035
13392
  onClose,
13036
13393
  onAdd,
13037
13394
  onUpdate,
@@ -13039,101 +13396,190 @@ function ReferencesPanel({
13039
13396
  onMove
13040
13397
  }) {
13041
13398
  const messages = document2Messages(uiLocale);
13042
- const [draft, setDraft] = useState7(EMPTY_DRAFT);
13399
+ const [draft, setDraft] = useState10(EMPTY_DRAFT);
13400
+ const [draftKeyTouched, setDraftKeyTouched] = useState10(false);
13401
+ const [keyOverrides, setKeyOverrides] = useState10({});
13402
+ const draftSeparator = draft.field_separator === "," ? "," : DEFAULT_REFERENCE_FIELD_SEPARATOR;
13403
+ const documentDirection = uiLocale === "ar" ? "rtl" : "ltr";
13404
+ const draftKeyError = useMemo(
13405
+ () => document2KeyError(draft.key ?? "", {
13406
+ references,
13407
+ labels
13408
+ }),
13409
+ [draft.key, references, labels]
13410
+ );
13043
13411
  if (!open) {
13044
13412
  return null;
13045
13413
  }
13046
- return /* @__PURE__ */ jsx15("div", { className: "butex-document2-widget__refs-backdrop", role: "presentation", onClick: onClose, children: /* @__PURE__ */ jsxs13("div", { className: "butex-document2-widget__refs-panel", role: "dialog", "aria-label": messages.referencesTitle, onClick: (event) => event.stopPropagation(), children: [
13047
- /* @__PURE__ */ jsxs13("header", { className: "butex-document2-widget__refs-header", children: [
13048
- /* @__PURE__ */ jsx15("strong", { children: messages.referencesTitle }),
13049
- /* @__PURE__ */ jsx15("button", { type: "button", className: "butex-document2-widget__icon-btn", title: messages.close, "aria-label": messages.close, onClick: onClose, children: "\xD7" })
13050
- ] }),
13051
- /* @__PURE__ */ jsxs13("div", { className: "butex-document2-widget__refs-add", children: [
13052
- /* @__PURE__ */ jsx15("h3", { children: messages.addReference }),
13053
- /* @__PURE__ */ jsx15("div", { className: "butex-document2-widget__refs-grid", children: [
13054
- ["key", messages.referenceKey],
13055
- ["authors", messages.referenceAuthors],
13056
- ["title", messages.referenceTitle],
13057
- ["year", messages.referenceYear],
13058
- ["venue", messages.referenceVenue],
13059
- ["url", messages.referenceUrl]
13060
- ].map(([field, label]) => /* @__PURE__ */ jsxs13("label", { className: "butex-document2-widget__refs-field", children: [
13061
- /* @__PURE__ */ jsx15("span", { children: label }),
13062
- /* @__PURE__ */ jsx15(
13063
- "input",
13064
- {
13065
- value: draft[field] ?? "",
13066
- onChange: (event) => {
13067
- const value = event.currentTarget.value;
13068
- setDraft((current) => ({ ...current, [field]: value }));
13069
- }
13070
- }
13071
- )
13072
- ] }, field)) }),
13073
- /* @__PURE__ */ jsx15(
13074
- "button",
13075
- {
13076
- type: "button",
13077
- className: "butex-document2-widget__primary-btn",
13078
- disabled: !draft.key?.trim(),
13079
- onClick: () => {
13080
- onAdd(draft);
13081
- setDraft(EMPTY_DRAFT);
13082
- },
13083
- children: messages.addReference
13084
- }
13085
- )
13086
- ] }),
13087
- /* @__PURE__ */ jsx15("ul", { className: "butex-document2-widget__refs-list", children: references.map((reference, index) => /* @__PURE__ */ jsxs13("li", { className: "butex-document2-widget__refs-item", children: [
13088
- /* @__PURE__ */ jsxs13("div", { className: "butex-document2-widget__refs-item-head", children: [
13089
- /* @__PURE__ */ jsxs13("strong", { children: [
13090
- "[",
13091
- index + 1,
13092
- "] ",
13093
- reference.key
13414
+ return /* @__PURE__ */ jsx15("div", { className: "butex-document2-widget__refs-backdrop", role: "presentation", onClick: onClose, children: /* @__PURE__ */ jsxs13(
13415
+ "div",
13416
+ {
13417
+ className: "butex-document2-widget__refs-panel",
13418
+ role: "dialog",
13419
+ "aria-label": messages.referencesTitle,
13420
+ onClick: (event) => event.stopPropagation(),
13421
+ children: [
13422
+ /* @__PURE__ */ jsxs13("header", { className: "butex-document2-widget__refs-header", children: [
13423
+ /* @__PURE__ */ jsx15("strong", { children: messages.referencesTitle }),
13424
+ /* @__PURE__ */ jsx15("button", { type: "button", className: "butex-document2-widget__icon-btn", title: messages.close, "aria-label": messages.close, onClick: onClose, children: "\xD7" })
13094
13425
  ] }),
13095
- /* @__PURE__ */ jsxs13("div", { className: "butex-document2-widget__refs-item-actions", children: [
13096
- /* @__PURE__ */ jsx15("button", { type: "button", title: messages.moveUp, "aria-label": messages.moveUp, disabled: index === 0, onClick: () => onMove(reference.id, -1), children: "\u2191" }),
13426
+ /* @__PURE__ */ jsxs13("div", { className: "butex-document2-widget__refs-add", children: [
13427
+ /* @__PURE__ */ jsx15("h3", { children: messages.addReference }),
13428
+ /* @__PURE__ */ jsxs13("div", { className: "butex-document2-widget__refs-grid", children: [
13429
+ REFERENCE_FIELDS.map(([field, messageKey]) => /* @__PURE__ */ jsxs13("label", { className: "butex-document2-widget__refs-field", children: [
13430
+ /* @__PURE__ */ jsx15("span", { children: messages[messageKey] }),
13431
+ /* @__PURE__ */ jsx15(
13432
+ "input",
13433
+ {
13434
+ value: draft[field] ?? "",
13435
+ "aria-invalid": field === "key" && draftKeyTouched && draftKeyError !== null ? true : void 0,
13436
+ onChange: (event) => {
13437
+ const value = event.currentTarget.value;
13438
+ if (field === "key") {
13439
+ setDraftKeyTouched(true);
13440
+ }
13441
+ setDraft((current) => ({ ...current, [field]: value }));
13442
+ }
13443
+ }
13444
+ ),
13445
+ field === "key" && draftKeyTouched && draftKeyError !== null ? /* @__PURE__ */ jsx15("p", { className: "butex-document2-widget__field-error", children: draftKeyError === "invalid" ? messages.keyRulesHint : keyErrorMessage4(draftKeyError, messages) }) : null
13446
+ ] }, field)),
13447
+ /* @__PURE__ */ jsx15(
13448
+ FieldSeparatorToggle,
13449
+ {
13450
+ value: draftSeparator,
13451
+ messages,
13452
+ onChange: (next) => setDraft((current) => ({ ...current, field_separator: next }))
13453
+ }
13454
+ )
13455
+ ] }),
13097
13456
  /* @__PURE__ */ jsx15(
13098
- "button",
13457
+ ReferencePreview,
13099
13458
  {
13100
- type: "button",
13101
- title: messages.moveDown,
13102
- "aria-label": messages.moveDown,
13103
- disabled: index === references.length - 1,
13104
- onClick: () => onMove(reference.id, 1),
13105
- children: "\u2193"
13459
+ authors: draft.authors ?? "",
13460
+ title: draft.title ?? "",
13461
+ venue: draft.venue ?? "",
13462
+ year: draft.year ?? "",
13463
+ url: draft.url ?? "",
13464
+ fieldSeparator: draftSeparator,
13465
+ messages,
13466
+ uiLocale,
13467
+ digitForm
13106
13468
  }
13107
13469
  ),
13108
- /* @__PURE__ */ jsx15("button", { type: "button", title: messages.deleteReference, "aria-label": messages.deleteReference, onClick: () => onRemove(reference.id), children: "\xD7" })
13109
- ] })
13110
- ] }),
13111
- /* @__PURE__ */ jsx15("div", { className: "butex-document2-widget__refs-grid", children: [
13112
- ["key", messages.referenceKey],
13113
- ["authors", messages.referenceAuthors],
13114
- ["title", messages.referenceTitle],
13115
- ["year", messages.referenceYear],
13116
- ["venue", messages.referenceVenue],
13117
- ["url", messages.referenceUrl]
13118
- ].map(([field, label]) => /* @__PURE__ */ jsxs13("label", { className: "butex-document2-widget__refs-field", children: [
13119
- /* @__PURE__ */ jsx15("span", { children: label }),
13120
- /* @__PURE__ */ jsx15(
13121
- "input",
13122
- {
13123
- value: reference[field],
13124
- onChange: (event) => {
13125
- const value = event.currentTarget.value;
13126
- onUpdate(reference.id, { [field]: value });
13470
+ /* @__PURE__ */ jsx15(
13471
+ "button",
13472
+ {
13473
+ type: "button",
13474
+ className: "butex-document2-widget__primary-btn",
13475
+ disabled: draftKeyError !== null,
13476
+ onClick: () => {
13477
+ onAdd({ ...draft, field_separator: draftSeparator });
13478
+ setDraft(EMPTY_DRAFT);
13479
+ setDraftKeyTouched(false);
13480
+ },
13481
+ children: messages.addReference
13127
13482
  }
13128
- }
13129
- )
13130
- ] }, field)) })
13131
- ] }, reference.id)) })
13132
- ] }) });
13483
+ )
13484
+ ] }),
13485
+ /* @__PURE__ */ jsx15("ul", { className: "butex-document2-widget__refs-list", children: references.map((reference, index) => {
13486
+ const displayedKey = keyOverrides[reference.id] ?? reference.key;
13487
+ const entryKeyError = document2KeyError(displayedKey, {
13488
+ references,
13489
+ labels,
13490
+ excludeReferenceId: reference.id
13491
+ });
13492
+ const numberLabel = formatBibliographyNumber(index + 1, { documentDirection, digitForm });
13493
+ return /* @__PURE__ */ jsxs13("li", { className: "butex-document2-widget__refs-item", children: [
13494
+ /* @__PURE__ */ jsxs13("div", { className: "butex-document2-widget__refs-item-head", children: [
13495
+ /* @__PURE__ */ jsxs13("strong", { children: [
13496
+ "[",
13497
+ numberLabel,
13498
+ "] ",
13499
+ reference.key
13500
+ ] }),
13501
+ /* @__PURE__ */ jsxs13("div", { className: "butex-document2-widget__refs-item-actions", children: [
13502
+ /* @__PURE__ */ jsx15("button", { type: "button", title: messages.moveUp, "aria-label": messages.moveUp, disabled: index === 0, onClick: () => onMove(reference.id, -1), children: "\u2191" }),
13503
+ /* @__PURE__ */ jsx15(
13504
+ "button",
13505
+ {
13506
+ type: "button",
13507
+ title: messages.moveDown,
13508
+ "aria-label": messages.moveDown,
13509
+ disabled: index === references.length - 1,
13510
+ onClick: () => onMove(reference.id, 1),
13511
+ children: "\u2193"
13512
+ }
13513
+ ),
13514
+ /* @__PURE__ */ jsx15("button", { type: "button", title: messages.deleteReference, "aria-label": messages.deleteReference, onClick: () => onRemove(reference.id), children: "\xD7" })
13515
+ ] })
13516
+ ] }),
13517
+ /* @__PURE__ */ jsx15(
13518
+ ReferencePreview,
13519
+ {
13520
+ authors: reference.authors,
13521
+ title: reference.title,
13522
+ venue: reference.venue,
13523
+ year: reference.year,
13524
+ url: reference.url,
13525
+ fieldSeparator: reference.fieldSeparator,
13526
+ numberLabel,
13527
+ messages,
13528
+ uiLocale,
13529
+ digitForm
13530
+ }
13531
+ ),
13532
+ /* @__PURE__ */ jsxs13("div", { className: "butex-document2-widget__refs-grid", children: [
13533
+ REFERENCE_FIELDS.map(([field, messageKey]) => /* @__PURE__ */ jsxs13("label", { className: "butex-document2-widget__refs-field", children: [
13534
+ /* @__PURE__ */ jsx15("span", { children: messages[messageKey] }),
13535
+ /* @__PURE__ */ jsx15(
13536
+ "input",
13537
+ {
13538
+ value: field === "key" ? displayedKey : reference[field],
13539
+ "aria-invalid": field === "key" && entryKeyError !== null ? true : void 0,
13540
+ onChange: (event) => {
13541
+ const value = event.currentTarget.value;
13542
+ if (field !== "key") {
13543
+ onUpdate(reference.id, { [field]: value });
13544
+ return;
13545
+ }
13546
+ setKeyOverrides((current) => ({ ...current, [reference.id]: value }));
13547
+ const error = document2KeyError(value, {
13548
+ references,
13549
+ labels,
13550
+ excludeReferenceId: reference.id
13551
+ });
13552
+ if (error === null) {
13553
+ onUpdate(reference.id, { key: value });
13554
+ setKeyOverrides((current) => {
13555
+ const next = { ...current };
13556
+ delete next[reference.id];
13557
+ return next;
13558
+ });
13559
+ }
13560
+ }
13561
+ }
13562
+ ),
13563
+ field === "key" && entryKeyError !== null ? /* @__PURE__ */ jsx15("p", { className: "butex-document2-widget__field-error", children: entryKeyError === "invalid" ? messages.keyRulesHint : keyErrorMessage4(entryKeyError, messages) }) : null
13564
+ ] }, field)),
13565
+ /* @__PURE__ */ jsx15(
13566
+ FieldSeparatorToggle,
13567
+ {
13568
+ value: reference.fieldSeparator,
13569
+ messages,
13570
+ onChange: (next) => onUpdate(reference.id, { field_separator: next })
13571
+ }
13572
+ )
13573
+ ] })
13574
+ ] }, reference.id);
13575
+ }) })
13576
+ ]
13577
+ }
13578
+ ) });
13133
13579
  }
13134
13580
 
13135
13581
  // src/react-document2/RefPickerPopover.tsx
13136
- import { useEffect as useEffect7, useState as useState8 } from "react";
13582
+ import { useEffect as useEffect7, useState as useState11 } from "react";
13137
13583
  import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
13138
13584
  function RefPickerPopover({
13139
13585
  open,
@@ -13141,13 +13587,15 @@ function RefPickerPopover({
13141
13587
  initialKeys = [],
13142
13588
  initialRefCommand = "ref",
13143
13589
  uiLocale = "ar",
13590
+ digitForm = "arabicIndic",
13144
13591
  onClose,
13145
13592
  onConfirm,
13146
13593
  onManageLabels
13147
13594
  }) {
13148
13595
  const messages = document2Messages(uiLocale);
13149
- const [selected, setSelected] = useState8(initialKeys);
13150
- const [refCommand, setRefCommand] = useState8(initialRefCommand);
13596
+ const documentDirection = uiLocale === "ar" ? "rtl" : "ltr";
13597
+ const [selected, setSelected] = useState11(initialKeys);
13598
+ const [refCommand, setRefCommand] = useState11(initialRefCommand);
13151
13599
  useEffect7(() => {
13152
13600
  if (open) {
13153
13601
  setSelected(initialKeys);
@@ -13175,16 +13623,18 @@ function RefPickerPopover({
13175
13623
  ] }),
13176
13624
  labels.length === 0 ? /* @__PURE__ */ jsx16("p", { className: "butex-document2-widget__cite-picker-empty", children: messages.noLabelsYet }) : /* @__PURE__ */ jsx16("ul", { className: "butex-document2-widget__cite-picker-list", children: labels.map((entry) => {
13177
13625
  const checked = selected.includes(entry.key);
13626
+ const title = formatFloatCaptionTitle(entry.kind, entry.number, {
13627
+ uiLocale,
13628
+ digitForm,
13629
+ documentDirection
13630
+ });
13178
13631
  return /* @__PURE__ */ jsx16("li", { children: /* @__PURE__ */ jsxs14("label", { className: "butex-document2-widget__cite-picker-item", children: [
13179
13632
  /* @__PURE__ */ jsx16("input", { type: "radio", name: "butex-ref-key", checked, onChange: () => selectKey(entry.key, entry.kind) }),
13180
13633
  /* @__PURE__ */ jsxs14("span", { children: [
13181
13634
  /* @__PURE__ */ jsxs14("strong", { children: [
13182
- "[",
13183
- entry.kind,
13635
+ title,
13184
13636
  " ",
13185
- entry.number,
13186
- "] ",
13187
- entry.key
13637
+ /* @__PURE__ */ jsx16("span", { className: "butex-document2-widget__refs-item-key", children: entry.key })
13188
13638
  ] }),
13189
13639
  entry.caption ? /* @__PURE__ */ jsx16("span", { className: "butex-document2-widget__cite-picker-meta", children: entry.caption }) : null
13190
13640
  ] })
@@ -14376,6 +14826,24 @@ var DOCUMENT2_WIDGET_CSS = `
14376
14826
  width: 100%;
14377
14827
  }
14378
14828
 
14829
+ .butex-document2-widget__field-error {
14830
+ color: #b42318;
14831
+ font-size: 0.85em;
14832
+ line-height: 1.35;
14833
+ margin: 0;
14834
+ }
14835
+
14836
+ .butex-document2-widget__field-hint {
14837
+ color: var(--butex-document2-muted);
14838
+ font-size: 0.82em;
14839
+ line-height: 1.35;
14840
+ margin: 0;
14841
+ }
14842
+
14843
+ .butex-document2-widget__refs-field input[aria-invalid='true'] {
14844
+ border-color: color-mix(in srgb, #b42318 55%, var(--butex-document2-border));
14845
+ }
14846
+
14379
14847
  .butex-document2-widget__refs-item {
14380
14848
  border: 1px solid var(--butex-document2-border);
14381
14849
  border-radius: 10px;
@@ -14384,6 +14852,58 @@ var DOCUMENT2_WIDGET_CSS = `
14384
14852
  padding: 0.75rem;
14385
14853
  }
14386
14854
 
14855
+ .butex-document2-widget__refs-item-key {
14856
+ color: var(--butex-document2-muted);
14857
+ font-size: 0.9em;
14858
+ font-weight: 500;
14859
+ }
14860
+
14861
+ .butex-document2-widget__modal-preview {
14862
+ background: color-mix(in srgb, var(--butex-document2-panel) 88%, var(--butex-document2-accent-bg));
14863
+ border: 1px dashed color-mix(in srgb, var(--butex-document2-accent) 30%, var(--butex-document2-border));
14864
+ border-radius: 8px;
14865
+ color: inherit;
14866
+ font-size: 0.95em;
14867
+ line-height: 1.55;
14868
+ padding: 0.55rem 0.7rem;
14869
+ text-align: center;
14870
+ }
14871
+
14872
+ .butex-document2-widget__modal-preview-number {
14873
+ color: var(--butex-document2-muted);
14874
+ font-weight: 600;
14875
+ }
14876
+
14877
+ .butex-document2-widget__modal-preview-url {
14878
+ color: var(--butex-document2-accent);
14879
+ word-break: break-all;
14880
+ }
14881
+
14882
+ .butex-document2-widget__refs-separator-toggle {
14883
+ display: inline-flex;
14884
+ gap: 0.35rem;
14885
+ }
14886
+
14887
+ .butex-document2-widget__refs-separator-toggle button {
14888
+ background: var(--butex-document2-input-bg, var(--butex-document2-panel));
14889
+ border: 1px solid var(--butex-document2-border);
14890
+ border-radius: 6px;
14891
+ color: inherit;
14892
+ cursor: pointer;
14893
+ font: inherit;
14894
+ font-size: 1.15em;
14895
+ line-height: 1;
14896
+ min-width: 2.25rem;
14897
+ padding: 0.35rem 0.55rem;
14898
+ }
14899
+
14900
+ .butex-document2-widget__refs-separator-toggle button.is-active {
14901
+ background: var(--butex-document2-accent-bg);
14902
+ border-color: color-mix(in srgb, var(--butex-document2-accent) 45%, var(--butex-document2-border));
14903
+ color: var(--butex-document2-accent);
14904
+ font-weight: 700;
14905
+ }
14906
+
14387
14907
  .butex-document2-widget__refs-item-actions {
14388
14908
  display: inline-flex;
14389
14909
  gap: 0.25rem;
@@ -14666,7 +15186,7 @@ function injectBuTeXDocument2Styles(doc) {
14666
15186
  }
14667
15187
 
14668
15188
  // src/react-document2/ButexDocumentEditor2.tsx
14669
- import { Fragment as Fragment3, jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
15189
+ import { Fragment as Fragment4, jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
14670
15190
  function mathDelimiters(mode) {
14671
15191
  return mode === "inline" ? { opening: "$", closing: "$" } : { opening: "\\[", closing: "\\]" };
14672
15192
  }
@@ -14875,24 +15395,24 @@ function ButexDocumentEditor2({
14875
15395
  onLatexChange
14876
15396
  }) {
14877
15397
  const messages = document2Messages(uiLocale);
14878
- const initialState = useMemo(
15398
+ const initialState = useMemo2(
14879
15399
  () => resolveInitialDocument2(initialDocument, uiLocale, documentMeta),
14880
15400
  [initialDocument, documentMeta, uiLocale]
14881
15401
  );
14882
- const [documentNode, setDocumentNode] = useState9(initialState.document);
14883
- const [error, setError] = useState9(initialState.error);
14884
- const [editorOpen, setEditorOpen] = useState9(true);
14885
- const [previewOpen, setPreviewOpen] = useState9(true);
14886
- const [selectedMath, setSelectedMath] = useState9(null);
14887
- const [citePicker, setCitePicker] = useState9(null);
14888
- const [referencesOpen, setReferencesOpen] = useState9(false);
14889
- const [labelsOpen, setLabelsOpen] = useState9(false);
14890
- const [refPicker, setRefPicker] = useState9(null);
14891
- const [digitFormState, setDigitFormState] = useState9(null);
14892
- const [editorFocus, setEditorFocus] = useState9(createEmptyDocument2EditorFocus());
14893
- const [collapsedBlockIds, setCollapsedBlockIds] = useState9(() => /* @__PURE__ */ new Set());
14894
- const [blockSelectionState, setBlockSelectionState] = useState9(emptyBlockSelection);
14895
- const [historyTick, setHistoryTick] = useState9(0);
15402
+ const [documentNode, setDocumentNode] = useState12(initialState.document);
15403
+ const [error, setError] = useState12(initialState.error);
15404
+ const [editorOpen, setEditorOpen] = useState12(true);
15405
+ const [previewOpen, setPreviewOpen] = useState12(true);
15406
+ const [selectedMath, setSelectedMath] = useState12(null);
15407
+ const [citePicker, setCitePicker] = useState12(null);
15408
+ const [referencesOpen, setReferencesOpen] = useState12(false);
15409
+ const [labelsOpen, setLabelsOpen] = useState12(false);
15410
+ const [refPicker, setRefPicker] = useState12(null);
15411
+ const [digitFormState, setDigitFormState] = useState12(null);
15412
+ const [editorFocus, setEditorFocus] = useState12(createEmptyDocument2EditorFocus());
15413
+ const [collapsedBlockIds, setCollapsedBlockIds] = useState12(() => /* @__PURE__ */ new Set());
15414
+ const [blockSelectionState, setBlockSelectionState] = useState12(emptyBlockSelection);
15415
+ const [historyTick, setHistoryTick] = useState12(0);
14896
15416
  const digitForm = digitFormProp ?? digitFormState ?? (documentDirection === "rtl" ? "arabicIndic" : "western");
14897
15417
  const historyRef = useRef7(createDocument2History());
14898
15418
  const documentRef = useRef7(documentNode);
@@ -14903,8 +15423,8 @@ function ButexDocumentEditor2({
14903
15423
  const pendingFocusRef = useRef7(null);
14904
15424
  documentRef.current = documentNode;
14905
15425
  const latex = document2Latex(documentNode);
14906
- const documentLabels = useMemo(() => collectDocument2Labels(documentNode), [documentNode]);
14907
- const preview = useMemo(
15426
+ const documentLabels = useMemo2(() => collectDocument2Labels(documentNode), [documentNode]);
15427
+ const preview = useMemo2(
14908
15428
  () => document2Preview(documentNode, mathOutput, equationSide, {
14909
15429
  documentDirection,
14910
15430
  digitForm,
@@ -14912,7 +15432,7 @@ function ButexDocumentEditor2({
14912
15432
  }),
14913
15433
  [documentNode, documentDirection, digitForm, equationSide, mathOutput, uiLocale]
14914
15434
  );
14915
- const debugEnabled = useMemo(() => {
15435
+ const debugEnabled = useMemo2(() => {
14916
15436
  if (debug) {
14917
15437
  return true;
14918
15438
  }
@@ -14921,8 +15441,8 @@ function ButexDocumentEditor2({
14921
15441
  }
14922
15442
  return new URLSearchParams(window.location.search).get("debug") === "1";
14923
15443
  }, [debug]);
14924
- const canUndo = useMemo(() => document2HistoryCanUndo(historyRef.current), [historyTick, documentNode]);
14925
- const canRedo = useMemo(() => document2HistoryCanRedo(historyRef.current), [historyTick, documentNode]);
15444
+ const canUndo = useMemo2(() => document2HistoryCanUndo(historyRef.current), [historyTick, documentNode]);
15445
+ const canRedo = useMemo2(() => document2HistoryCanRedo(historyRef.current), [historyTick, documentNode]);
14926
15446
  const blockSelection = normalizeBlockSelection(blockSelectionState.selection, documentNode.blocks.length);
14927
15447
  const selectionCount = blockSelection ? blockSelection.to - blockSelection.from + 1 : 0;
14928
15448
  const canMoveSelectionUp = Boolean(blockSelection && blockSelection.from > 0);
@@ -15583,6 +16103,7 @@ function ButexDocumentEditor2({
15583
16103
  output: mathOutput,
15584
16104
  documentDirection,
15585
16105
  uiLocale,
16106
+ digitForm,
15586
16107
  resolveImageUrl
15587
16108
  }
15588
16109
  )
@@ -15592,7 +16113,7 @@ function ButexDocumentEditor2({
15592
16113
  }
15593
16114
  ),
15594
16115
  debugEnabled ? /* @__PURE__ */ jsxs15("div", { className: "butex-document2-widget__dev", children: [
15595
- debugEnabled && documentNode.diagnostics.length > 0 ? /* @__PURE__ */ jsxs15(Fragment3, { children: [
16116
+ debugEnabled && documentNode.diagnostics.length > 0 ? /* @__PURE__ */ jsxs15(Fragment4, { children: [
15596
16117
  /* @__PURE__ */ jsx17("strong", { children: messages.importWarnings }),
15597
16118
  documentNode.diagnostics.map((diagnostic) => /* @__PURE__ */ jsx17("p", { className: "butex-document2-widget__dev-diagnostic", children: formatDocument2Diagnostic(diagnostic, messages) }, `${diagnostic.path}-${diagnostic.message}`))
15598
16119
  ] }) : null,
@@ -15612,6 +16133,9 @@ function ButexDocumentEditor2({
15612
16133
  uiLocale,
15613
16134
  labelEnabled: selectedMath.labelEnabled,
15614
16135
  label: selectedMath.label,
16136
+ labels: documentLabels,
16137
+ references: documentNode.references,
16138
+ ownerId: selectedMath.tokenId ?? void 0,
15615
16139
  onLabelEnabledChange: (enabled) => setSelectedMath((current) => current ? { ...current, labelEnabled: enabled } : current),
15616
16140
  onLabelChange: (nextLabel) => setSelectedMath((current) => current ? { ...current, label: nextLabel } : current),
15617
16141
  onMathModeChange: (mode) => setSelectedMath((current) => current ? { ...current, mathMode: mode } : current),
@@ -15627,6 +16151,7 @@ function ButexDocumentEditor2({
15627
16151
  references: documentNode.references,
15628
16152
  initialKeys: citePicker?.keys ?? [],
15629
16153
  uiLocale,
16154
+ digitForm,
15630
16155
  onClose: () => setCitePicker(null),
15631
16156
  onConfirm: confirmCiteKeys,
15632
16157
  onManageReferences: () => {
@@ -15643,6 +16168,7 @@ function ButexDocumentEditor2({
15643
16168
  initialKeys: refPicker?.keys ?? [],
15644
16169
  initialRefCommand: refPicker?.refCommand ?? "ref",
15645
16170
  uiLocale,
16171
+ digitForm,
15646
16172
  onClose: () => setRefPicker(null),
15647
16173
  onConfirm: confirmRefKeys,
15648
16174
  onManageLabels: () => {
@@ -15656,7 +16182,9 @@ function ButexDocumentEditor2({
15656
16182
  {
15657
16183
  open: referencesOpen,
15658
16184
  references: documentNode.references,
16185
+ labels: documentLabels,
15659
16186
  uiLocale,
16187
+ digitForm,
15660
16188
  onClose: () => setReferencesOpen(false),
15661
16189
  onAdd: (partial) => applyDocument(addDocument2Reference(documentRef.current, partial), "immediate"),
15662
16190
  onUpdate: (referenceId, patch) => applyDocument(updateDocument2Reference(documentRef.current, referenceId, patch), "immediate"),
@@ -15669,7 +16197,9 @@ function ButexDocumentEditor2({
15669
16197
  {
15670
16198
  open: labelsOpen,
15671
16199
  labels: documentLabels,
16200
+ references: documentNode.references,
15672
16201
  uiLocale,
16202
+ digitForm,
15673
16203
  onClose: () => setLabelsOpen(false),
15674
16204
  onUpdateFloat: (ownerId, kind, patch) => applyDocument(
15675
16205
  kind === "fig" ? updateDocument2ImageMeta(documentRef.current, ownerId, patch) : updateDocument2TableMeta(documentRef.current, ownerId, patch),