@drghaliasri/butex 5.4.6 → 5.5.1
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.
- package/README.md +3 -2
- package/dist/document.js +2 -1
- package/dist/document.js.map +1 -1
- package/dist/document.mjs +2 -1
- package/dist/document.mjs.map +1 -1
- package/dist/document2.d.mts +20 -2
- package/dist/document2.d.ts +20 -2
- package/dist/document2.js +184 -22
- package/dist/document2.js.map +1 -1
- package/dist/document2.mjs +183 -22
- package/dist/document2.mjs.map +1 -1
- package/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.global.js +137 -37
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +137 -37
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +137 -37
- package/dist/index.mjs.map +1 -1
- package/dist/react-document.js +171 -39
- package/dist/react-document.js.map +1 -1
- package/dist/react-document.mjs +171 -39
- package/dist/react-document.mjs.map +1 -1
- package/dist/react-document2.d.mts +23 -3
- package/dist/react-document2.d.ts +23 -3
- package/dist/react-document2.js +690 -95
- package/dist/react-document2.js.map +1 -1
- package/dist/react-document2.mjs +736 -141
- package/dist/react-document2.mjs.map +1 -1
- package/dist/react.d.mts +1 -0
- package/dist/react.d.ts +1 -0
- package/dist/react.js +171 -39
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +171 -39
- package/dist/react.mjs.map +1 -1
- package/package.json +1 -1
package/dist/react-document2.js
CHANGED
|
@@ -1168,7 +1168,7 @@ function parseReferences(json) {
|
|
|
1168
1168
|
}
|
|
1169
1169
|
return references;
|
|
1170
1170
|
}
|
|
1171
|
-
function createInlineField2(value = "", mathObjects = [], options = {}, path = "$", diagnostics = []) {
|
|
1171
|
+
function createInlineField2(value = "", mathObjects = [], options = {}, path = "$", diagnostics = [], formats = []) {
|
|
1172
1172
|
const mode = options.mode ?? "english";
|
|
1173
1173
|
const spans = detectInlineSpans2(value);
|
|
1174
1174
|
const mathSpans = spans.filter((span) => span.kind === "math");
|
|
@@ -1180,7 +1180,7 @@ function createInlineField2(value = "", mathObjects = [], options = {}, path = "
|
|
|
1180
1180
|
}
|
|
1181
1181
|
for (const span of spans) {
|
|
1182
1182
|
if (span.start > index) {
|
|
1183
|
-
tokens
|
|
1183
|
+
pushFormattedTextTokens(tokens, value.slice(index, span.start), index, formats);
|
|
1184
1184
|
}
|
|
1185
1185
|
if (span.kind === "cite") {
|
|
1186
1186
|
tokens.push({
|
|
@@ -1236,9 +1236,81 @@ function createInlineField2(value = "", mathObjects = [], options = {}, path = "
|
|
|
1236
1236
|
index = span.end;
|
|
1237
1237
|
}
|
|
1238
1238
|
if (index < value.length || tokens.length === 0) {
|
|
1239
|
-
tokens
|
|
1239
|
+
pushFormattedTextTokens(tokens, value.slice(index), index, formats);
|
|
1240
|
+
}
|
|
1241
|
+
return { id: document2Id("field"), tokens: compactTextTokens(tokens) };
|
|
1242
|
+
}
|
|
1243
|
+
function styleFromFormat(format) {
|
|
1244
|
+
const style = {};
|
|
1245
|
+
if (format.bold === true) {
|
|
1246
|
+
style.bold = true;
|
|
1247
|
+
}
|
|
1248
|
+
if (format.italic === true) {
|
|
1249
|
+
style.italic = true;
|
|
1250
|
+
}
|
|
1251
|
+
if (format.underline === true) {
|
|
1252
|
+
style.underline = true;
|
|
1253
|
+
}
|
|
1254
|
+
return style.bold || style.italic || style.underline ? style : null;
|
|
1255
|
+
}
|
|
1256
|
+
function mergeTextStyle(base, added) {
|
|
1257
|
+
return {
|
|
1258
|
+
...base?.bold ? { bold: true } : {},
|
|
1259
|
+
...base?.italic ? { italic: true } : {},
|
|
1260
|
+
...base?.underline ? { underline: true } : {},
|
|
1261
|
+
...added.bold ? { bold: true } : {},
|
|
1262
|
+
...added.italic ? { italic: true } : {},
|
|
1263
|
+
...added.underline ? { underline: true } : {}
|
|
1264
|
+
};
|
|
1265
|
+
}
|
|
1266
|
+
function textStylesEqual(a, b) {
|
|
1267
|
+
return Boolean(a?.bold) === Boolean(b?.bold) && Boolean(a?.italic) === Boolean(b?.italic) && Boolean(a?.underline) === Boolean(b?.underline);
|
|
1268
|
+
}
|
|
1269
|
+
function compactTextTokens(tokens) {
|
|
1270
|
+
const compacted = [];
|
|
1271
|
+
for (const token of tokens) {
|
|
1272
|
+
const previous = compacted[compacted.length - 1];
|
|
1273
|
+
if (previous?.kind === "text" && token.kind === "text" && textStylesEqual(previous.style, token.style)) {
|
|
1274
|
+
previous.text += token.text;
|
|
1275
|
+
} else {
|
|
1276
|
+
compacted.push(token);
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
return compacted;
|
|
1280
|
+
}
|
|
1281
|
+
function styleKey(style) {
|
|
1282
|
+
return `${style?.bold ? "b" : ""}${style?.italic ? "i" : ""}${style?.underline ? "u" : ""}`;
|
|
1283
|
+
}
|
|
1284
|
+
function pushFormattedTextTokens(tokens, text, sourceStart, formats) {
|
|
1285
|
+
if (text.length === 0) {
|
|
1286
|
+
tokens.push({ id: document2Id("text"), kind: "text", text });
|
|
1287
|
+
return;
|
|
1288
|
+
}
|
|
1289
|
+
const styles = Array.from({ length: text.length });
|
|
1290
|
+
for (const format of formats) {
|
|
1291
|
+
const style = styleFromFormat(format);
|
|
1292
|
+
if (!style || !Number.isFinite(format.start) || !Number.isFinite(format.end)) {
|
|
1293
|
+
continue;
|
|
1294
|
+
}
|
|
1295
|
+
const start = Math.max(0, Math.min(text.length, Math.trunc(format.start) - sourceStart));
|
|
1296
|
+
const end = Math.max(0, Math.min(text.length, Math.trunc(format.end) - sourceStart));
|
|
1297
|
+
if (end <= start) {
|
|
1298
|
+
continue;
|
|
1299
|
+
}
|
|
1300
|
+
for (let index = start; index < end; index += 1) {
|
|
1301
|
+
styles[index] = mergeTextStyle(styles[index], style);
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
let chunkStart = 0;
|
|
1305
|
+
for (let index = 1; index <= text.length; index += 1) {
|
|
1306
|
+
if (index < text.length && styleKey(styles[index]) === styleKey(styles[chunkStart])) {
|
|
1307
|
+
continue;
|
|
1308
|
+
}
|
|
1309
|
+
const chunk = text.slice(chunkStart, index);
|
|
1310
|
+
const style = styles[chunkStart];
|
|
1311
|
+
tokens.push({ id: document2Id("text"), kind: "text", text: chunk, ...style ? { style } : {} });
|
|
1312
|
+
chunkStart = index;
|
|
1240
1313
|
}
|
|
1241
|
-
return { id: document2Id("field"), tokens };
|
|
1242
1314
|
}
|
|
1243
1315
|
function closingForList(command) {
|
|
1244
1316
|
return command === "\\begin{itemize}" ? "\\end{itemize}" : "\\end{enumerate}";
|
|
@@ -1249,7 +1321,7 @@ function parseTextBlock(json, options, path, diagnostics) {
|
|
|
1249
1321
|
id: document2Id("block"),
|
|
1250
1322
|
kind: "textBlock",
|
|
1251
1323
|
command: json.command,
|
|
1252
|
-
field: createInlineField2(value, json.math_objects ?? [], options, `${path}.value`, diagnostics),
|
|
1324
|
+
field: createInlineField2(value, json.math_objects ?? [], options, `${path}.value`, diagnostics, json.command === "\\paragraph" ? json.formats ?? [] : []),
|
|
1253
1325
|
...json.centered === true ? { centered: true } : {}
|
|
1254
1326
|
};
|
|
1255
1327
|
}
|
|
@@ -1258,7 +1330,7 @@ function parseListItem(json, options, path, diagnostics) {
|
|
|
1258
1330
|
const blocksJson = Array.isArray(json.blocks) ? json.blocks : [];
|
|
1259
1331
|
return {
|
|
1260
1332
|
id: document2Id("item"),
|
|
1261
|
-
field: createInlineField2(value, json.math_objects ?? [], options, `${path}.value`, diagnostics),
|
|
1333
|
+
field: createInlineField2(value, json.math_objects ?? [], options, `${path}.value`, diagnostics, json.formats ?? []),
|
|
1262
1334
|
blocks: blocksJson.map((block, index) => parseBlock(asBlockJson(block), options, `${path}.blocks[${String(index)}]`, diagnostics))
|
|
1263
1335
|
};
|
|
1264
1336
|
}
|
|
@@ -1291,7 +1363,8 @@ function parseTableBlock(json, options, path, diagnostics) {
|
|
|
1291
1363
|
const spanCount = detectMathSpans2(value).length;
|
|
1292
1364
|
const cellMathObjects = mathObjects.slice(mathObjectIndex, mathObjectIndex + spanCount);
|
|
1293
1365
|
mathObjectIndex += spanCount;
|
|
1294
|
-
|
|
1366
|
+
const cellFormats = json.cell_formats?.[rowIndex]?.[columnIndex] ?? [];
|
|
1367
|
+
return createInlineField2(value, cellMathObjects, options, `${path}.rows[${String(rowIndex)}][${String(columnIndex)}]`, diagnostics, cellFormats);
|
|
1295
1368
|
});
|
|
1296
1369
|
});
|
|
1297
1370
|
if (mathObjects.length > 0 && mathObjects.length !== mathObjectIndex) {
|
|
@@ -6362,7 +6435,8 @@ ${BUTEX_FONT_FACE_CSS}
|
|
|
6362
6435
|
transition: box-shadow 0.15s ease, border-color 0.15s ease;
|
|
6363
6436
|
}
|
|
6364
6437
|
|
|
6365
|
-
.surface:focus
|
|
6438
|
+
.surface:focus,
|
|
6439
|
+
.surface.surface--typing-focus {
|
|
6366
6440
|
border-color: var(--butex-focus-border, rgba(13, 148, 136, 0.45));
|
|
6367
6441
|
box-shadow: 0 0 0 3px var(--butex-focus-shadow, rgba(13, 148, 136, 0.12));
|
|
6368
6442
|
}
|
|
@@ -6564,7 +6638,7 @@ function injectBuTeXEditorStyles(doc) {
|
|
|
6564
6638
|
|
|
6565
6639
|
// src/editor/runtime.ts
|
|
6566
6640
|
function createEditorRuntime(options) {
|
|
6567
|
-
const { surfaceEl } = options;
|
|
6641
|
+
const { surfaceEl, inputEl } = options;
|
|
6568
6642
|
const buttonElements = options.buttonElements ?? {};
|
|
6569
6643
|
const outsidePointerIgnoreSelectors = options.outsidePointerIgnoreSelectors ?? [];
|
|
6570
6644
|
let session = options.initialSession ?? createStarterSession();
|
|
@@ -6578,6 +6652,23 @@ function createEditorRuntime(options) {
|
|
|
6578
6652
|
let dragSelecting = false;
|
|
6579
6653
|
let dragChainId = null;
|
|
6580
6654
|
let dragChanged = false;
|
|
6655
|
+
let composingInput = false;
|
|
6656
|
+
let pendingCompositionText = null;
|
|
6657
|
+
function resetInputElement() {
|
|
6658
|
+
if (!inputEl) {
|
|
6659
|
+
return;
|
|
6660
|
+
}
|
|
6661
|
+
inputEl.value = "";
|
|
6662
|
+
}
|
|
6663
|
+
function focusInput() {
|
|
6664
|
+
if (!inputEl) {
|
|
6665
|
+
surfaceEl.focus();
|
|
6666
|
+
return;
|
|
6667
|
+
}
|
|
6668
|
+
inputEl.focus({ preventScroll: true });
|
|
6669
|
+
const end = inputEl.value.length;
|
|
6670
|
+
inputEl.setSelectionRange(end, end);
|
|
6671
|
+
}
|
|
6581
6672
|
function notifySessionChange() {
|
|
6582
6673
|
options.onSessionChange?.(session);
|
|
6583
6674
|
}
|
|
@@ -6842,7 +6933,7 @@ function createEditorRuntime(options) {
|
|
|
6842
6933
|
event.preventDefault();
|
|
6843
6934
|
event.stopPropagation();
|
|
6844
6935
|
startDragSelection(chainId, index);
|
|
6845
|
-
|
|
6936
|
+
focusInput();
|
|
6846
6937
|
});
|
|
6847
6938
|
slot.addEventListener("click", (event) => {
|
|
6848
6939
|
if (dragChanged) {
|
|
@@ -6852,7 +6943,7 @@ function createEditorRuntime(options) {
|
|
|
6852
6943
|
return;
|
|
6853
6944
|
}
|
|
6854
6945
|
applyTransient((prev) => setCaret(prev, chainId, index));
|
|
6855
|
-
|
|
6946
|
+
focusInput();
|
|
6856
6947
|
});
|
|
6857
6948
|
if (session.caret.chainId === chainId && session.caret.index === index) {
|
|
6858
6949
|
const caret = document.createElement("span");
|
|
@@ -6884,7 +6975,7 @@ function createEditorRuntime(options) {
|
|
|
6884
6975
|
event.preventDefault();
|
|
6885
6976
|
event.stopPropagation();
|
|
6886
6977
|
startDragSelection(chainId, indexInChain);
|
|
6887
|
-
|
|
6978
|
+
focusInput();
|
|
6888
6979
|
});
|
|
6889
6980
|
nodeEl.addEventListener("click", (event) => {
|
|
6890
6981
|
if (dragChanged) {
|
|
@@ -6895,7 +6986,7 @@ function createEditorRuntime(options) {
|
|
|
6895
6986
|
}
|
|
6896
6987
|
event.stopPropagation();
|
|
6897
6988
|
applyTransient((prev) => selectNode(prev, node.id));
|
|
6898
|
-
|
|
6989
|
+
focusInput();
|
|
6899
6990
|
});
|
|
6900
6991
|
const body = document.createElement("span");
|
|
6901
6992
|
body.className = "node-body";
|
|
@@ -6930,7 +7021,7 @@ function createEditorRuntime(options) {
|
|
|
6930
7021
|
const activeTree = session[activeTreeKey(session.activeSide)];
|
|
6931
7022
|
surfaceEl.appendChild(buildChain(activeTree));
|
|
6932
7023
|
if (initialKeyboardFocusPending) {
|
|
6933
|
-
requestAnimationFrame(
|
|
7024
|
+
requestAnimationFrame(focusInput);
|
|
6934
7025
|
initialKeyboardFocusPending = false;
|
|
6935
7026
|
}
|
|
6936
7027
|
notifySessionChange();
|
|
@@ -6968,7 +7059,7 @@ function createEditorRuntime(options) {
|
|
|
6968
7059
|
}
|
|
6969
7060
|
session = restored;
|
|
6970
7061
|
render();
|
|
6971
|
-
|
|
7062
|
+
focusInput();
|
|
6972
7063
|
}
|
|
6973
7064
|
function performRedo() {
|
|
6974
7065
|
const restored = restoreRedo(undoRedo, session);
|
|
@@ -6977,9 +7068,12 @@ function createEditorRuntime(options) {
|
|
|
6977
7068
|
}
|
|
6978
7069
|
session = restored;
|
|
6979
7070
|
render();
|
|
6980
|
-
|
|
7071
|
+
focusInput();
|
|
6981
7072
|
}
|
|
6982
7073
|
function onKeyDown(event) {
|
|
7074
|
+
if (event.isComposing || event.key === "Process" || event.keyCode === 229) {
|
|
7075
|
+
return;
|
|
7076
|
+
}
|
|
6983
7077
|
const shortcutMod = event.ctrlKey || event.metaKey;
|
|
6984
7078
|
const keyLower = typeof event.key === "string" ? event.key.toLowerCase() : "";
|
|
6985
7079
|
if (shortcutMod && !event.altKey && keyLower === "z") {
|
|
@@ -7078,6 +7172,70 @@ function createEditorRuntime(options) {
|
|
|
7078
7172
|
applyStructural((prev) => insertChar(prev, char));
|
|
7079
7173
|
}
|
|
7080
7174
|
}
|
|
7175
|
+
function onBeforeInput(event) {
|
|
7176
|
+
if (composingInput || event.isComposing) {
|
|
7177
|
+
return;
|
|
7178
|
+
}
|
|
7179
|
+
if (event.inputType === "deleteContentBackward") {
|
|
7180
|
+
event.preventDefault();
|
|
7181
|
+
applyStructural((prev) => deleteBackward(prev));
|
|
7182
|
+
resetInputElement();
|
|
7183
|
+
return;
|
|
7184
|
+
}
|
|
7185
|
+
if (event.inputType === "deleteContentForward") {
|
|
7186
|
+
event.preventDefault();
|
|
7187
|
+
applyStructural((prev) => deleteForward(prev));
|
|
7188
|
+
resetInputElement();
|
|
7189
|
+
}
|
|
7190
|
+
}
|
|
7191
|
+
function onInput(event) {
|
|
7192
|
+
if (!inputEl || composingInput) {
|
|
7193
|
+
return;
|
|
7194
|
+
}
|
|
7195
|
+
const inputEvent = event;
|
|
7196
|
+
const text = inputEvent.data ?? inputEl.value;
|
|
7197
|
+
resetInputElement();
|
|
7198
|
+
if (pendingCompositionText !== null && (inputEvent.inputType === "insertFromComposition" || text === pendingCompositionText)) {
|
|
7199
|
+
pendingCompositionText = null;
|
|
7200
|
+
return;
|
|
7201
|
+
}
|
|
7202
|
+
pendingCompositionText = null;
|
|
7203
|
+
if (inputEvent.inputType === "deleteContentBackward") {
|
|
7204
|
+
applyStructural((prev) => deleteBackward(prev));
|
|
7205
|
+
return;
|
|
7206
|
+
}
|
|
7207
|
+
if (inputEvent.inputType === "deleteContentForward") {
|
|
7208
|
+
applyStructural((prev) => deleteForward(prev));
|
|
7209
|
+
return;
|
|
7210
|
+
}
|
|
7211
|
+
if (text) {
|
|
7212
|
+
applyStructural((prev) => pasteText(prev, text));
|
|
7213
|
+
}
|
|
7214
|
+
}
|
|
7215
|
+
function onCompositionStart() {
|
|
7216
|
+
composingInput = true;
|
|
7217
|
+
}
|
|
7218
|
+
function onCompositionEnd(event) {
|
|
7219
|
+
if (!inputEl) {
|
|
7220
|
+
return;
|
|
7221
|
+
}
|
|
7222
|
+
composingInput = false;
|
|
7223
|
+
const text = event.data || inputEl.value;
|
|
7224
|
+
resetInputElement();
|
|
7225
|
+
if (text) {
|
|
7226
|
+
applyStructural((prev) => pasteText(prev, text));
|
|
7227
|
+
}
|
|
7228
|
+
pendingCompositionText = text || null;
|
|
7229
|
+
window.setTimeout(() => {
|
|
7230
|
+
pendingCompositionText = null;
|
|
7231
|
+
}, 0);
|
|
7232
|
+
}
|
|
7233
|
+
function onInputFocus() {
|
|
7234
|
+
surfaceEl.classList.add("surface--typing-focus");
|
|
7235
|
+
}
|
|
7236
|
+
function onInputBlur() {
|
|
7237
|
+
surfaceEl.classList.remove("surface--typing-focus");
|
|
7238
|
+
}
|
|
7081
7239
|
function isShortcutOnlyEvent(event) {
|
|
7082
7240
|
if (!(event.ctrlKey || event.metaKey) || event.altKey) {
|
|
7083
7241
|
return false;
|
|
@@ -7127,7 +7285,7 @@ function createEditorRuntime(options) {
|
|
|
7127
7285
|
}
|
|
7128
7286
|
event.preventDefault();
|
|
7129
7287
|
startDragSelection(resolved.chainId, resolved.slotIndex);
|
|
7130
|
-
|
|
7288
|
+
focusInput();
|
|
7131
7289
|
}
|
|
7132
7290
|
function onSurfaceClick(event) {
|
|
7133
7291
|
if (dragChanged) {
|
|
@@ -7144,7 +7302,7 @@ function createEditorRuntime(options) {
|
|
|
7144
7302
|
} else {
|
|
7145
7303
|
clearSelectionAndNodeHighlights();
|
|
7146
7304
|
}
|
|
7147
|
-
|
|
7305
|
+
focusInput();
|
|
7148
7306
|
}
|
|
7149
7307
|
function onDocumentPointerDown(event) {
|
|
7150
7308
|
const target = event.target;
|
|
@@ -7160,6 +7318,13 @@ function createEditorRuntime(options) {
|
|
|
7160
7318
|
clearSelectionAndNodeHighlights();
|
|
7161
7319
|
}
|
|
7162
7320
|
surfaceEl.addEventListener("keydown", onKeyDown);
|
|
7321
|
+
inputEl?.addEventListener("keydown", onKeyDown);
|
|
7322
|
+
inputEl?.addEventListener("beforeinput", onBeforeInput);
|
|
7323
|
+
inputEl?.addEventListener("input", onInput);
|
|
7324
|
+
inputEl?.addEventListener("compositionstart", onCompositionStart);
|
|
7325
|
+
inputEl?.addEventListener("compositionend", onCompositionEnd);
|
|
7326
|
+
inputEl?.addEventListener("focus", onInputFocus);
|
|
7327
|
+
inputEl?.addEventListener("blur", onInputBlur);
|
|
7163
7328
|
document.addEventListener("keydown", onDocumentKeyDown);
|
|
7164
7329
|
document.addEventListener("mouseup", endDragSelection);
|
|
7165
7330
|
document.addEventListener("mouseleave", endDragSelection);
|
|
@@ -7171,6 +7336,13 @@ function createEditorRuntime(options) {
|
|
|
7171
7336
|
render,
|
|
7172
7337
|
destroy: () => {
|
|
7173
7338
|
surfaceEl.removeEventListener("keydown", onKeyDown);
|
|
7339
|
+
inputEl?.removeEventListener("keydown", onKeyDown);
|
|
7340
|
+
inputEl?.removeEventListener("beforeinput", onBeforeInput);
|
|
7341
|
+
inputEl?.removeEventListener("input", onInput);
|
|
7342
|
+
inputEl?.removeEventListener("compositionstart", onCompositionStart);
|
|
7343
|
+
inputEl?.removeEventListener("compositionend", onCompositionEnd);
|
|
7344
|
+
inputEl?.removeEventListener("focus", onInputFocus);
|
|
7345
|
+
inputEl?.removeEventListener("blur", onInputBlur);
|
|
7174
7346
|
document.removeEventListener("keydown", onDocumentKeyDown);
|
|
7175
7347
|
document.removeEventListener("mouseup", endDragSelection);
|
|
7176
7348
|
document.removeEventListener("mouseleave", endDragSelection);
|
|
@@ -7191,6 +7363,7 @@ function createEditorRuntime(options) {
|
|
|
7191
7363
|
uiLocale = locale;
|
|
7192
7364
|
render();
|
|
7193
7365
|
},
|
|
7366
|
+
focusInput,
|
|
7194
7367
|
performUndo,
|
|
7195
7368
|
performRedo,
|
|
7196
7369
|
performCopy,
|
|
@@ -7198,27 +7371,27 @@ function createEditorRuntime(options) {
|
|
|
7198
7371
|
performPaste,
|
|
7199
7372
|
toggleSide: () => {
|
|
7200
7373
|
applyTransient((prev) => switchSide(prev));
|
|
7201
|
-
|
|
7374
|
+
focusInput();
|
|
7202
7375
|
},
|
|
7203
7376
|
toggleSplitLeafTyping: () => {
|
|
7204
7377
|
applyStructural((prev) => setSplitLeafTyping(prev, !prev.splitLeafTyping));
|
|
7205
|
-
|
|
7378
|
+
focusInput();
|
|
7206
7379
|
},
|
|
7207
7380
|
toggleArabicReverseNumberTyping: () => {
|
|
7208
7381
|
applyStructural((prev) => setArabicReverseNumberTyping(prev, !prev.arabicReverseNumberTyping));
|
|
7209
|
-
|
|
7382
|
+
focusInput();
|
|
7210
7383
|
},
|
|
7211
7384
|
toggleTakweenCharacterFont: () => {
|
|
7212
7385
|
applyTransient((prev) => toggleTakweenCharacterFont(prev));
|
|
7213
|
-
|
|
7386
|
+
focusInput();
|
|
7214
7387
|
},
|
|
7215
7388
|
setCurrentCharacterFont: (fontId) => {
|
|
7216
7389
|
applyTransient((prev) => setCurrentCharacterFont(prev, fontId));
|
|
7217
|
-
|
|
7390
|
+
focusInput();
|
|
7218
7391
|
},
|
|
7219
7392
|
setCurrentDigitForm: (digitForm) => {
|
|
7220
7393
|
applyStructural((prev) => setCurrentDigitForm(prev, digitForm));
|
|
7221
|
-
|
|
7394
|
+
focusInput();
|
|
7222
7395
|
},
|
|
7223
7396
|
insertDelimiterByKind: (kind) => {
|
|
7224
7397
|
if (kind === "paren") {
|
|
@@ -7228,79 +7401,79 @@ function createEditorRuntime(options) {
|
|
|
7228
7401
|
} else {
|
|
7229
7402
|
applyStructural((prev) => insertDelimiterPair(prev, "\\left\\{", "\\right\\}"));
|
|
7230
7403
|
}
|
|
7231
|
-
|
|
7404
|
+
focusInput();
|
|
7232
7405
|
},
|
|
7233
7406
|
insertFraction: () => {
|
|
7234
7407
|
applyStructural((prev) => insertFraction(prev));
|
|
7235
|
-
|
|
7408
|
+
focusInput();
|
|
7236
7409
|
},
|
|
7237
7410
|
insertFirstDerivative: () => {
|
|
7238
7411
|
applyStructural((prev) => insertFirstDerivative(prev));
|
|
7239
|
-
|
|
7412
|
+
focusInput();
|
|
7240
7413
|
},
|
|
7241
7414
|
insertSecondDerivative: () => {
|
|
7242
7415
|
applyStructural((prev) => insertSecondDerivative(prev));
|
|
7243
|
-
|
|
7416
|
+
focusInput();
|
|
7244
7417
|
},
|
|
7245
7418
|
insertMatrixEnv: (style, rows, columns) => {
|
|
7246
7419
|
applyStructural((prev) => insertMatrixEnv(prev, style, rows, columns));
|
|
7247
|
-
|
|
7420
|
+
focusInput();
|
|
7248
7421
|
},
|
|
7249
7422
|
insertArrayEnv: (rows, columns) => {
|
|
7250
7423
|
applyStructural((prev) => insertArrayEnv(prev, rows, columns));
|
|
7251
|
-
|
|
7424
|
+
focusInput();
|
|
7252
7425
|
},
|
|
7253
7426
|
insertAlignedEnv: (rows, columns) => {
|
|
7254
7427
|
applyStructural((prev) => insertAlignedEnv(prev, rows, columns));
|
|
7255
|
-
|
|
7428
|
+
focusInput();
|
|
7256
7429
|
},
|
|
7257
7430
|
insertSqrt: () => {
|
|
7258
7431
|
applyStructural((prev) => insertSqrt(prev));
|
|
7259
|
-
|
|
7432
|
+
focusInput();
|
|
7260
7433
|
},
|
|
7261
7434
|
insertOverset: () => {
|
|
7262
7435
|
applyStructural((prev) => insertOverset(prev));
|
|
7263
|
-
|
|
7436
|
+
focusInput();
|
|
7264
7437
|
},
|
|
7265
7438
|
insertUnderset: () => {
|
|
7266
7439
|
applyStructural((prev) => insertUnderset(prev));
|
|
7267
|
-
|
|
7440
|
+
focusInput();
|
|
7268
7441
|
},
|
|
7269
7442
|
insertLimitsSeriesTemplate: (commandId) => {
|
|
7270
7443
|
applyStructural((prev) => insertLimitsSeriesTemplate(prev, commandId));
|
|
7271
|
-
|
|
7444
|
+
focusInput();
|
|
7272
7445
|
},
|
|
7273
7446
|
insertAccentPair: () => {
|
|
7274
7447
|
applyStructural((prev) => insertAccentPair(prev));
|
|
7275
|
-
|
|
7448
|
+
focusInput();
|
|
7276
7449
|
},
|
|
7277
7450
|
insertAccent: (accentId) => {
|
|
7278
7451
|
applyStructural((prev) => insertAccent(prev, accentId));
|
|
7279
|
-
|
|
7452
|
+
focusInput();
|
|
7280
7453
|
},
|
|
7281
7454
|
insertAtomicCommand: (commandId) => {
|
|
7282
7455
|
applyStructural((prev) => insertAtomicCommand(prev, commandId));
|
|
7283
|
-
|
|
7456
|
+
focusInput();
|
|
7284
7457
|
},
|
|
7285
7458
|
insertAtomicOperatorCommand: (commandId) => {
|
|
7286
7459
|
applyStructural((prev) => insertAtomicOperatorCommand(prev, commandId));
|
|
7287
|
-
|
|
7460
|
+
focusInput();
|
|
7288
7461
|
},
|
|
7289
7462
|
addSup: () => {
|
|
7290
7463
|
applyStructural((prev) => addSup(prev));
|
|
7291
|
-
|
|
7464
|
+
focusInput();
|
|
7292
7465
|
},
|
|
7293
7466
|
addSub: () => {
|
|
7294
7467
|
applyStructural((prev) => addSub(prev));
|
|
7295
|
-
|
|
7468
|
+
focusInput();
|
|
7296
7469
|
},
|
|
7297
7470
|
removeSup: () => {
|
|
7298
7471
|
applyStructural((prev) => removeSup(prev));
|
|
7299
|
-
|
|
7472
|
+
focusInput();
|
|
7300
7473
|
},
|
|
7301
7474
|
removeSub: () => {
|
|
7302
7475
|
applyStructural((prev) => removeSub(prev));
|
|
7303
|
-
|
|
7476
|
+
focusInput();
|
|
7304
7477
|
},
|
|
7305
7478
|
setMatrixEnvStyle: (style) => {
|
|
7306
7479
|
applyStructural((prev) => setMatrixEnvStyle(prev, style));
|
|
@@ -7322,7 +7495,7 @@ function createEditorRuntime(options) {
|
|
|
7322
7495
|
},
|
|
7323
7496
|
deleteStructure: () => {
|
|
7324
7497
|
applyStructural((prev) => deleteStructure(prev));
|
|
7325
|
-
|
|
7498
|
+
focusInput();
|
|
7326
7499
|
}
|
|
7327
7500
|
};
|
|
7328
7501
|
render();
|
|
@@ -8116,6 +8289,79 @@ function normalizeFieldTokens(tokens) {
|
|
|
8116
8289
|
}
|
|
8117
8290
|
return tokens;
|
|
8118
8291
|
}
|
|
8292
|
+
function textStylesEqual2(a, b) {
|
|
8293
|
+
return Boolean(a?.bold) === Boolean(b?.bold) && Boolean(a?.italic) === Boolean(b?.italic) && Boolean(a?.underline) === Boolean(b?.underline);
|
|
8294
|
+
}
|
|
8295
|
+
function compactAdjacentTextTokens(tokens) {
|
|
8296
|
+
const compacted = [];
|
|
8297
|
+
for (const token of tokens) {
|
|
8298
|
+
const previous = compacted[compacted.length - 1];
|
|
8299
|
+
if (previous?.kind === "text" && token.kind === "text" && textStylesEqual2(previous.style, token.style)) {
|
|
8300
|
+
previous.text += token.text;
|
|
8301
|
+
} else {
|
|
8302
|
+
compacted.push(token);
|
|
8303
|
+
}
|
|
8304
|
+
}
|
|
8305
|
+
return normalizeFieldTokens(compacted);
|
|
8306
|
+
}
|
|
8307
|
+
function withoutEmptyStyle(style) {
|
|
8308
|
+
const next = {};
|
|
8309
|
+
if (style.bold) {
|
|
8310
|
+
next.bold = true;
|
|
8311
|
+
}
|
|
8312
|
+
if (style.italic) {
|
|
8313
|
+
next.italic = true;
|
|
8314
|
+
}
|
|
8315
|
+
if (style.underline) {
|
|
8316
|
+
next.underline = true;
|
|
8317
|
+
}
|
|
8318
|
+
return next.bold || next.italic || next.underline ? next : void 0;
|
|
8319
|
+
}
|
|
8320
|
+
function textTokenPart(text, style, id = document2Id("text")) {
|
|
8321
|
+
return { id, kind: "text", text, ...style ? { style } : {} };
|
|
8322
|
+
}
|
|
8323
|
+
function toggleTextTokenStyle(document2, fieldId, tokenId, selectionStart, selectionEnd, styleName) {
|
|
8324
|
+
if (selectionEnd <= selectionStart) {
|
|
8325
|
+
return document2;
|
|
8326
|
+
}
|
|
8327
|
+
const next = cloneDocument(document2);
|
|
8328
|
+
visitFields(next.blocks, (field) => {
|
|
8329
|
+
if (field.id !== fieldId) {
|
|
8330
|
+
return false;
|
|
8331
|
+
}
|
|
8332
|
+
const tokenIndex = field.tokens.findIndex((entry) => entry.id === tokenId && entry.kind === "text");
|
|
8333
|
+
if (tokenIndex < 0) {
|
|
8334
|
+
return true;
|
|
8335
|
+
}
|
|
8336
|
+
const token = field.tokens[tokenIndex];
|
|
8337
|
+
const start = Math.max(0, Math.min(token.text.length, selectionStart));
|
|
8338
|
+
const end = Math.max(0, Math.min(token.text.length, selectionEnd));
|
|
8339
|
+
if (end <= start) {
|
|
8340
|
+
return true;
|
|
8341
|
+
}
|
|
8342
|
+
const selectedStyle = token.style ?? {};
|
|
8343
|
+
const enabled = selectedStyle[styleName] === true;
|
|
8344
|
+
const nextStyle = withoutEmptyStyle({ ...selectedStyle, [styleName]: enabled ? void 0 : true });
|
|
8345
|
+
const parts = [];
|
|
8346
|
+
const before = token.text.slice(0, start);
|
|
8347
|
+
const selected = token.text.slice(start, end);
|
|
8348
|
+
const after = token.text.slice(end);
|
|
8349
|
+
if (before.length > 0) {
|
|
8350
|
+
parts.push(textTokenPart(before, token.style, token.id));
|
|
8351
|
+
}
|
|
8352
|
+
parts.push(textTokenPart(selected, nextStyle, before.length > 0 ? document2Id("text") : token.id));
|
|
8353
|
+
if (after.length > 0) {
|
|
8354
|
+
parts.push(textTokenPart(after, token.style));
|
|
8355
|
+
}
|
|
8356
|
+
field.tokens = compactAdjacentTextTokens([
|
|
8357
|
+
...field.tokens.slice(0, tokenIndex),
|
|
8358
|
+
...parts,
|
|
8359
|
+
...field.tokens.slice(tokenIndex + 1)
|
|
8360
|
+
]);
|
|
8361
|
+
return true;
|
|
8362
|
+
});
|
|
8363
|
+
return next;
|
|
8364
|
+
}
|
|
8119
8365
|
function stitchTextAroundRemovedToken(tokens, index) {
|
|
8120
8366
|
const before = tokens[index - 1];
|
|
8121
8367
|
const after = tokens[index + 1];
|
|
@@ -8143,8 +8389,8 @@ function removeMathTokenById(document2, tokenId) {
|
|
|
8143
8389
|
function splitTextTokenAt(token, offset) {
|
|
8144
8390
|
const safeOffset = Math.max(0, Math.min(offset, token.text.length));
|
|
8145
8391
|
return [
|
|
8146
|
-
{ id: token.id, kind: "text", text: token.text.slice(0, safeOffset) },
|
|
8147
|
-
{ id: document2Id("text"), kind: "text", text: token.text.slice(safeOffset) }
|
|
8392
|
+
{ id: token.id, kind: "text", text: token.text.slice(0, safeOffset), ...token.style ? { style: token.style } : {} },
|
|
8393
|
+
{ id: document2Id("text"), kind: "text", text: token.text.slice(safeOffset), ...token.style ? { style: token.style } : {} }
|
|
8148
8394
|
];
|
|
8149
8395
|
}
|
|
8150
8396
|
function insertMathTokenAtCaret(document2, fieldId, textTokenId, caretOffset, session, opening = "$", closing = "$", side = "arabic") {
|
|
@@ -8647,7 +8893,7 @@ function arabicXeLatexPreamblePkg(twocolumn = false) {
|
|
|
8647
8893
|
\usepackage{bidi}
|
|
8648
8894
|
\usepackage{multirow}
|
|
8649
8895
|
\usepackage{booktabs}
|
|
8650
|
-
\usepackage{graphicx} % For \
|
|
8896
|
+
\usepackage{graphicx} % For \reflectbox
|
|
8651
8897
|
\usepackage{xcolor}
|
|
8652
8898
|
\usepackage{tikz}
|
|
8653
8899
|
\usepackage{tcolorbox} % For tcolorbox environment
|
|
@@ -8716,10 +8962,8 @@ function arabicXeLatexPreambleCmd() {
|
|
|
8716
8962
|
\newcommand{\horzbar}{\rule[.5ex]{2.5ex}{0.5pt}}
|
|
8717
8963
|
|
|
8718
8964
|
|
|
8719
|
-
\newcommand{\
|
|
8720
|
-
|
|
8721
|
-
\newcommand{\arabsqrt}[2]{\butexreflect{\(\sqrt[\butexreflect{\(#1\)}]{\butexreflect{\(#2\)}}\)}}
|
|
8722
|
-
\newcommand{\arabvec}[1]{\butexreflect{$\vec{\butexreflect{$#1$}}$}}
|
|
8965
|
+
\newcommand{\arabsqrt}[2]{\reflectbox{\(\sqrt[\reflectbox{\(#1\)}]{\reflectbox{\(#2\)}}\)}}
|
|
8966
|
+
\newcommand{\arabvec}[1]{\reflectbox{$\vec{\reflectbox{$#1$}}$}}
|
|
8723
8967
|
|
|
8724
8968
|
\newcommand{\arabexp}[1]{{}^{#1}\!\raisebox{-4.5pt}{\text{\diwani{ه}}}}
|
|
8725
8969
|
\newcommand{\arablog}[2]{\left(\text{#2}\right)\!\prescript{}{\text{#1}}{\text{\diwani{لو}}}}
|
|
@@ -8767,9 +9011,9 @@ function arabicXeLatexPreambleCmd() {
|
|
|
8767
9011
|
\newcommand{\araboddde}[2][-5pt]{\stackrel{\raisebox{#1}{$\vcenter{\hbox{$\cdot\!\cdot\!\cdot$}}$}}{\text{#2}}}
|
|
8768
9012
|
\newcommand{\arabpde}[1]{\prescript{}{#1\!\!}{\nabla}} % arabic partial differential equation (PDE)
|
|
8769
9013
|
|
|
8770
|
-
\newcommand{\arabprime}[0]{\
|
|
8771
|
-
\newcommand{\arabpprime}[0]{\
|
|
8772
|
-
\newcommand{\arabppprime}[0]{\
|
|
9014
|
+
\newcommand{\arabprime}[0]{\reflectbox{$\prime$}\!} % arabic prime notation
|
|
9015
|
+
\newcommand{\arabpprime}[0]{\reflectbox{$\prime$}\reflectbox{$\prime$}\!} % arabic prime notation
|
|
9016
|
+
\newcommand{\arabppprime}[0]{\reflectbox{$\prime$}\reflectbox{$\prime$}\reflectbox{$\prime$}\!} % arabic prime notation
|
|
8773
9017
|
|
|
8774
9018
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
8775
9019
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
@@ -8789,7 +9033,7 @@ function arabicXeLatexPreambleCmd() {
|
|
|
8789
9033
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
8790
9034
|
|
|
8791
9035
|
|
|
8792
|
-
\newcommand{\arsqrt}[2][]{\
|
|
9036
|
+
\newcommand{\arsqrt}[2][]{\reflectbox{\(\sqrt[\reflectbox{\(#1\)}]{\reflectbox{\(#2\)}}\)}}
|
|
8793
9037
|
\newcommand{\arexp}[0]{\!\raisebox{-4.5pt}{\text{\diwani{ه}}}}
|
|
8794
9038
|
\newcommand{\arlog}[0]{\!\!\text{\diwani{لو}}}
|
|
8795
9039
|
\newcommand{\arln}[0]{\!\!\prescript{}{\text{\diwani{ه}}}{\text{\diwani{لو}}}}
|
|
@@ -8852,9 +9096,22 @@ function mathBodyLatex(token) {
|
|
|
8852
9096
|
const rendered = renderMathNodeLatex(token.math);
|
|
8853
9097
|
return stripDisplayMathDelimiters(rendered);
|
|
8854
9098
|
}
|
|
9099
|
+
function styledTextLatex(text, style) {
|
|
9100
|
+
let output = text;
|
|
9101
|
+
if (style?.bold) {
|
|
9102
|
+
output = `\\textbf{${output}}`;
|
|
9103
|
+
}
|
|
9104
|
+
if (style?.italic) {
|
|
9105
|
+
output = `\\textit{${output}}`;
|
|
9106
|
+
}
|
|
9107
|
+
if (style?.underline) {
|
|
9108
|
+
output = `\\underline{${output}}`;
|
|
9109
|
+
}
|
|
9110
|
+
return output;
|
|
9111
|
+
}
|
|
8855
9112
|
function tokenLatex(token) {
|
|
8856
9113
|
if (token.kind === "text") {
|
|
8857
|
-
return token.text;
|
|
9114
|
+
return styledTextLatex(token.text, token.style);
|
|
8858
9115
|
}
|
|
8859
9116
|
if (token.kind === "cite") {
|
|
8860
9117
|
return citeTokenLatex(token.keys);
|
|
@@ -8878,7 +9135,9 @@ function inlineFieldLatex(field) {
|
|
|
8878
9135
|
return field.tokens.map((token) => tokenLatex(token)).join("");
|
|
8879
9136
|
}
|
|
8880
9137
|
function textBlockLatex(block) {
|
|
8881
|
-
const
|
|
9138
|
+
const content = inlineFieldLatex(block.field);
|
|
9139
|
+
const body = block.command === "\\paragraph" ? `\\par
|
|
9140
|
+
${content}` : `${block.command}{${content}}`;
|
|
8882
9141
|
if (block.command === "\\paragraph" && block.centered) {
|
|
8883
9142
|
return `\\begin{center}
|
|
8884
9143
|
${body}
|
|
@@ -9130,7 +9389,7 @@ function mathTex(token, equationSide) {
|
|
|
9130
9389
|
function previewInlines(field, islands, output, equationSide, document2, previewOptions) {
|
|
9131
9390
|
return field.tokens.map((token) => {
|
|
9132
9391
|
if (token.kind === "text") {
|
|
9133
|
-
return { kind: "text", text: token.text };
|
|
9392
|
+
return { kind: "text", text: token.text, ...token.style ? { style: token.style } : {} };
|
|
9134
9393
|
}
|
|
9135
9394
|
if (token.kind === "cite") {
|
|
9136
9395
|
return {
|
|
@@ -9306,6 +9565,10 @@ var DOCUMENT2_MESSAGES = {
|
|
|
9306
9565
|
redo: "\u0625\u0639\u0627\u062F\u0629",
|
|
9307
9566
|
structure: "\u0647\u064A\u0643\u0644",
|
|
9308
9567
|
content: "\u0645\u062D\u062A\u0648\u0649",
|
|
9568
|
+
textFormatting: "\u062A\u0646\u0633\u064A\u0642 \u0627\u0644\u0646\u0635",
|
|
9569
|
+
bold: "\u063A\u0627\u0645\u0642",
|
|
9570
|
+
italic: "\u0645\u0627\u0626\u0644",
|
|
9571
|
+
underline: "\u062A\u062D\u062A\u0647 \u062E\u0637",
|
|
9309
9572
|
equations: "\u0645\u0639\u0627\u062F\u0644\u0627\u062A",
|
|
9310
9573
|
citations: "\u0627\u0642\u062A\u0628\u0627\u0633\u0627\u062A \u0648\u0645\u0631\u0627\u062C\u0639",
|
|
9311
9574
|
lists: "\u0642\u0648\u0627\u0626\u0645",
|
|
@@ -9445,6 +9708,10 @@ var DOCUMENT2_MESSAGES = {
|
|
|
9445
9708
|
redo: "Redo",
|
|
9446
9709
|
structure: "Structure",
|
|
9447
9710
|
content: "Content",
|
|
9711
|
+
textFormatting: "Text formatting",
|
|
9712
|
+
bold: "Bold",
|
|
9713
|
+
italic: "Italic",
|
|
9714
|
+
underline: "Underline",
|
|
9448
9715
|
equations: "Equations",
|
|
9449
9716
|
citations: "Citations and references",
|
|
9450
9717
|
lists: "Lists",
|
|
@@ -10483,7 +10750,9 @@ function rememberCaret(element, blockId, fieldId, tokenId, onFieldFocus) {
|
|
|
10483
10750
|
if (!blockId || !onFieldFocus) {
|
|
10484
10751
|
return;
|
|
10485
10752
|
}
|
|
10486
|
-
|
|
10753
|
+
const selectionStart = element.selectionStart ?? element.value.length;
|
|
10754
|
+
const selectionEnd = element.selectionEnd ?? selectionStart;
|
|
10755
|
+
onFieldFocus(blockId, fieldId, tokenId, selectionEnd, selectionStart, selectionEnd);
|
|
10487
10756
|
}
|
|
10488
10757
|
function fitTextareaHeight(element) {
|
|
10489
10758
|
if (!element) {
|
|
@@ -10617,6 +10886,9 @@ function InlineField({
|
|
|
10617
10886
|
{
|
|
10618
10887
|
className: "butex-document2-widget__inline-text",
|
|
10619
10888
|
value: token.text,
|
|
10889
|
+
"data-bold": token.style?.bold === true ? "true" : void 0,
|
|
10890
|
+
"data-italic": token.style?.italic === true ? "true" : void 0,
|
|
10891
|
+
"data-underline": token.style?.underline === true ? "true" : void 0,
|
|
10620
10892
|
dir: documentDirection,
|
|
10621
10893
|
"aria-label": messages.text,
|
|
10622
10894
|
rows: 1,
|
|
@@ -11413,8 +11685,11 @@ function DocumentInsertToolbar({
|
|
|
11413
11685
|
selectionCount = 0,
|
|
11414
11686
|
canMoveSelectionUp = false,
|
|
11415
11687
|
canMoveSelectionDown = false,
|
|
11688
|
+
canFormatText = false,
|
|
11689
|
+
activeTextStyles = {},
|
|
11416
11690
|
onUndo,
|
|
11417
11691
|
onRedo,
|
|
11692
|
+
onToggleTextStyle,
|
|
11418
11693
|
onMoveSelectionUp,
|
|
11419
11694
|
onMoveSelectionDown,
|
|
11420
11695
|
onDeleteSelection,
|
|
@@ -11438,6 +11713,56 @@ function DocumentInsertToolbar({
|
|
|
11438
11713
|
}) {
|
|
11439
11714
|
const messages = document2Messages(uiLocale);
|
|
11440
11715
|
const [digitMenuOpen, setDigitMenuOpen] = (0, import_react7.useState)(false);
|
|
11716
|
+
const [referencesMenuOpen, setReferencesMenuOpen] = (0, import_react7.useState)(false);
|
|
11717
|
+
const referencesMenuRef = (0, import_react7.useRef)(null);
|
|
11718
|
+
const referencesTriggerRef = (0, import_react7.useRef)(null);
|
|
11719
|
+
(0, import_react7.useEffect)(() => {
|
|
11720
|
+
if (!referencesMenuOpen) {
|
|
11721
|
+
return;
|
|
11722
|
+
}
|
|
11723
|
+
referencesMenuRef.current?.querySelector('[role="menuitem"]')?.focus();
|
|
11724
|
+
const closeOnOutsideClick = (event) => {
|
|
11725
|
+
if (!referencesMenuRef.current?.contains(event.target)) {
|
|
11726
|
+
setReferencesMenuOpen(false);
|
|
11727
|
+
}
|
|
11728
|
+
};
|
|
11729
|
+
const closeOnEscape = (event) => {
|
|
11730
|
+
if (event.key === "Escape") {
|
|
11731
|
+
setReferencesMenuOpen(false);
|
|
11732
|
+
referencesTriggerRef.current?.focus();
|
|
11733
|
+
}
|
|
11734
|
+
};
|
|
11735
|
+
document.addEventListener("mousedown", closeOnOutsideClick);
|
|
11736
|
+
document.addEventListener("keydown", closeOnEscape);
|
|
11737
|
+
return () => {
|
|
11738
|
+
document.removeEventListener("mousedown", closeOnOutsideClick);
|
|
11739
|
+
document.removeEventListener("keydown", closeOnEscape);
|
|
11740
|
+
};
|
|
11741
|
+
}, [referencesMenuOpen]);
|
|
11742
|
+
function runReferenceAction(action) {
|
|
11743
|
+
setReferencesMenuOpen(false);
|
|
11744
|
+
action();
|
|
11745
|
+
}
|
|
11746
|
+
function moveReferenceMenuFocus(event) {
|
|
11747
|
+
if (!["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) {
|
|
11748
|
+
return;
|
|
11749
|
+
}
|
|
11750
|
+
const items = Array.from(event.currentTarget.querySelectorAll('[role="menuitem"]'));
|
|
11751
|
+
if (items.length === 0) {
|
|
11752
|
+
return;
|
|
11753
|
+
}
|
|
11754
|
+
event.preventDefault();
|
|
11755
|
+
const currentIndex = items.indexOf(document.activeElement);
|
|
11756
|
+
if (event.key === "Home") {
|
|
11757
|
+
items[0]?.focus();
|
|
11758
|
+
} else if (event.key === "End") {
|
|
11759
|
+
items[items.length - 1]?.focus();
|
|
11760
|
+
} else {
|
|
11761
|
+
const change = event.key === "ArrowDown" ? 1 : -1;
|
|
11762
|
+
const nextIndex = (currentIndex + change + items.length) % items.length;
|
|
11763
|
+
items[nextIndex]?.focus();
|
|
11764
|
+
}
|
|
11765
|
+
}
|
|
11441
11766
|
function digitTitle(id) {
|
|
11442
11767
|
if (id === "arabicIndic") {
|
|
11443
11768
|
return messages.arabicIndicDigits;
|
|
@@ -11495,6 +11820,50 @@ function DocumentInsertToolbar({
|
|
|
11495
11820
|
messages.selectedBlockCount
|
|
11496
11821
|
] }) : null
|
|
11497
11822
|
] }),
|
|
11823
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "butex-document2-widget__toolbar-group", role: "group", "aria-label": messages.textFormatting, children: [
|
|
11824
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
11825
|
+
"button",
|
|
11826
|
+
{
|
|
11827
|
+
type: "button",
|
|
11828
|
+
className: "butex-document2-widget__icon-btn butex-document2-widget__format-btn",
|
|
11829
|
+
title: messages.bold,
|
|
11830
|
+
"aria-label": messages.bold,
|
|
11831
|
+
"aria-pressed": activeTextStyles.bold === true,
|
|
11832
|
+
disabled: !canFormatText,
|
|
11833
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
11834
|
+
onClick: () => onToggleTextStyle?.("bold"),
|
|
11835
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "butex-document2-widget__format-icon butex-document2-widget__format-icon--bold", "aria-hidden": "true", children: "\u0646\u0635" })
|
|
11836
|
+
}
|
|
11837
|
+
),
|
|
11838
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
11839
|
+
"button",
|
|
11840
|
+
{
|
|
11841
|
+
type: "button",
|
|
11842
|
+
className: "butex-document2-widget__icon-btn butex-document2-widget__format-btn",
|
|
11843
|
+
title: messages.italic,
|
|
11844
|
+
"aria-label": messages.italic,
|
|
11845
|
+
"aria-pressed": activeTextStyles.italic === true,
|
|
11846
|
+
disabled: !canFormatText,
|
|
11847
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
11848
|
+
onClick: () => onToggleTextStyle?.("italic"),
|
|
11849
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "butex-document2-widget__format-icon butex-document2-widget__format-icon--italic", "aria-hidden": "true", children: "\u0646\u0635" })
|
|
11850
|
+
}
|
|
11851
|
+
),
|
|
11852
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
11853
|
+
"button",
|
|
11854
|
+
{
|
|
11855
|
+
type: "button",
|
|
11856
|
+
className: "butex-document2-widget__icon-btn butex-document2-widget__format-btn",
|
|
11857
|
+
title: messages.underline,
|
|
11858
|
+
"aria-label": messages.underline,
|
|
11859
|
+
"aria-pressed": activeTextStyles.underline === true,
|
|
11860
|
+
disabled: !canFormatText,
|
|
11861
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
11862
|
+
onClick: () => onToggleTextStyle?.("underline"),
|
|
11863
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "butex-document2-widget__format-icon butex-document2-widget__format-icon--underline", "aria-hidden": "true", children: "\u0646\u0635" })
|
|
11864
|
+
}
|
|
11865
|
+
)
|
|
11866
|
+
] }),
|
|
11498
11867
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "butex-document2-widget__toolbar-group", role: "group", "aria-label": messages.structure, children: [
|
|
11499
11868
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
11500
11869
|
"button",
|
|
@@ -11546,35 +11915,57 @@ function DocumentInsertToolbar({
|
|
|
11546
11915
|
)) }) : null
|
|
11547
11916
|
] })
|
|
11548
11917
|
] }),
|
|
11549
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.
|
|
11550
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.
|
|
11551
|
-
|
|
11552
|
-
|
|
11553
|
-
|
|
11554
|
-
"
|
|
11555
|
-
|
|
11556
|
-
|
|
11557
|
-
|
|
11558
|
-
|
|
11559
|
-
|
|
11560
|
-
|
|
11561
|
-
|
|
11562
|
-
|
|
11563
|
-
|
|
11564
|
-
|
|
11565
|
-
|
|
11566
|
-
|
|
11567
|
-
|
|
11568
|
-
|
|
11569
|
-
|
|
11570
|
-
|
|
11571
|
-
|
|
11572
|
-
|
|
11573
|
-
|
|
11574
|
-
|
|
11575
|
-
|
|
11576
|
-
|
|
11577
|
-
|
|
11918
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "butex-document2-widget__toolbar-group", role: "group", "aria-label": messages.citations, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "butex-document2-widget__references-menu", ref: referencesMenuRef, children: [
|
|
11919
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
11920
|
+
"button",
|
|
11921
|
+
{
|
|
11922
|
+
ref: referencesTriggerRef,
|
|
11923
|
+
type: "button",
|
|
11924
|
+
className: "butex-document2-widget__icon-btn butex-document2-widget__references-trigger",
|
|
11925
|
+
title: messages.citations,
|
|
11926
|
+
"aria-label": messages.citations,
|
|
11927
|
+
"aria-haspopup": "menu",
|
|
11928
|
+
"aria-expanded": referencesMenuOpen,
|
|
11929
|
+
onClick: () => setReferencesMenuOpen((open) => !open),
|
|
11930
|
+
children: [
|
|
11931
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "butex-document2-widget__icon-bibliography", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { viewBox: "0 0 16 16", width: "14", height: "14", focusable: "false", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { fill: "currentColor", d: "M2 2.2h4.2c.7 0 1.3.3 1.8.8.5-.5 1.1-.8 1.8-.8H14v10.6H9.8c-.6 0-1.1.3-1.4.8h-.8c-.3-.5-.8-.8-1.4-.8H2V2.2zm1.2 1.2v8.2h3c.4 0 .8.1 1.2.3V4.6c-.2-.7-.6-1.2-1.2-1.2h-3zm9.6 0h-3c-.6 0-1 .5-1.2 1.2v7.3c.4-.2.8-.3 1.2-.3h3V3.4z" }) }) }),
|
|
11932
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: messages.citations }),
|
|
11933
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "butex-document2-widget__menu-chevron", "aria-hidden": "true", children: "\u2304" })
|
|
11934
|
+
]
|
|
11935
|
+
}
|
|
11936
|
+
),
|
|
11937
|
+
referencesMenuOpen ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
11938
|
+
"div",
|
|
11939
|
+
{
|
|
11940
|
+
className: "butex-document2-widget__references-menu-options",
|
|
11941
|
+
role: "menu",
|
|
11942
|
+
"aria-label": messages.citations,
|
|
11943
|
+
onKeyDown: moveReferenceMenuFocus,
|
|
11944
|
+
children: [
|
|
11945
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("button", { type: "button", role: "menuitem", title: messages.insertCitation, onClick: () => runReferenceAction(onInsertCitation), children: [
|
|
11946
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { "aria-hidden": "true", children: "[]" }),
|
|
11947
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: messages.insertCitation })
|
|
11948
|
+
] }),
|
|
11949
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("button", { type: "button", role: "menuitem", title: messages.insertInternalRef, onClick: () => runReferenceAction(onInsertInternalRef), children: [
|
|
11950
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { "aria-hidden": "true", children: "\xA7" }),
|
|
11951
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: messages.insertInternalRef })
|
|
11952
|
+
] }),
|
|
11953
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("button", { type: "button", role: "menuitem", title: messages.insertBibliography, onClick: () => runReferenceAction(onInsertBibliography), children: [
|
|
11954
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "butex-document2-widget__icon-bibliography", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { viewBox: "0 0 16 16", width: "14", height: "14", focusable: "false", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { fill: "currentColor", d: "M2.2 2.4h7.2c.9 0 1.6.7 1.6 1.6v9.2c0 .5-.6.8-1 .5l-2.2-1.6H2.2c-.9 0-1.6-.7-1.6-1.6V4c0-.9.7-1.6 1.6-1.6zm0 1.2c-.2 0-.4.2-.4.4v6.5c0 .2.2.4.4.4h6.1l1.5 1.1V4c0-.2-.2-.4-.4-.4H2.2zM3.4 5.2h5.2v1H3.4zm0 2.1h4.2v1H3.4zm0 2.1h3.4v1H3.4zM11.4 4.1h2.2c.8 0 1.4.6 1.4 1.4v7.1c0 .4-.5.7-.8.4l-1.7-1.3h-1.1V4.1zm1.2 1.2v5.4l.7.5V5.5c0-.1-.1-.2-.2-.2h-.5z" }) }) }),
|
|
11955
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: messages.insertBibliography })
|
|
11956
|
+
] }),
|
|
11957
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("button", { type: "button", role: "menuitem", title: messages.manageReferences, onClick: () => runReferenceAction(onManageReferences), children: [
|
|
11958
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { "aria-hidden": "true", children: "\u2630" }),
|
|
11959
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: messages.manageReferences })
|
|
11960
|
+
] }),
|
|
11961
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("button", { type: "button", role: "menuitem", title: messages.manageLabels, onClick: () => runReferenceAction(onManageLabels), children: [
|
|
11962
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { "aria-hidden": "true", children: "\u2317" }),
|
|
11963
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: messages.manageLabels })
|
|
11964
|
+
] })
|
|
11965
|
+
]
|
|
11966
|
+
}
|
|
11967
|
+
) : null
|
|
11968
|
+
] }) }),
|
|
11578
11969
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "butex-document2-widget__toolbar-group", role: "group", "aria-label": messages.lists, children: [
|
|
11579
11970
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", className: "butex-document2-widget__icon-btn", title: messages.bulletedList, "aria-label": messages.bulletedList, onClick: onAddList, children: "\u2022\u2261" }),
|
|
11580
11971
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", className: "butex-document2-widget__icon-btn", title: messages.numberedList, "aria-label": messages.numberedList, onClick: onAddEnumerate, children: "1." })
|
|
@@ -11589,7 +11980,17 @@ var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
|
11589
11980
|
function PreviewInlines({ inlines, output }) {
|
|
11590
11981
|
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_jsx_runtime11.Fragment, { children: inlines.map((inline, index) => {
|
|
11591
11982
|
if (inline.kind === "text") {
|
|
11592
|
-
|
|
11983
|
+
let content = /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: inline.text });
|
|
11984
|
+
if (inline.style?.bold) {
|
|
11985
|
+
content = /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("strong", { children: content });
|
|
11986
|
+
}
|
|
11987
|
+
if (inline.style?.italic) {
|
|
11988
|
+
content = /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("em", { children: content });
|
|
11989
|
+
}
|
|
11990
|
+
if (inline.style?.underline) {
|
|
11991
|
+
content = /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "butex-document2-widget__preview-underline", children: content });
|
|
11992
|
+
}
|
|
11993
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: content }, index);
|
|
11593
11994
|
}
|
|
11594
11995
|
if (inline.kind === "cite") {
|
|
11595
11996
|
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "butex-document2-widget__preview-cite", children: inline.label }, inline.id);
|
|
@@ -11815,6 +12216,22 @@ var WIDGET_CHROME_CSS = `
|
|
|
11815
12216
|
padding: 10px 12px;
|
|
11816
12217
|
}
|
|
11817
12218
|
|
|
12219
|
+
.butex-widget .butex-editor-input-bridge {
|
|
12220
|
+
border: 0;
|
|
12221
|
+
font-size: 16px;
|
|
12222
|
+
height: 1px;
|
|
12223
|
+
margin: 0;
|
|
12224
|
+
max-height: 1px;
|
|
12225
|
+
min-height: 1px;
|
|
12226
|
+
opacity: 0;
|
|
12227
|
+
overflow: hidden;
|
|
12228
|
+
padding: 0;
|
|
12229
|
+
pointer-events: none;
|
|
12230
|
+
position: absolute;
|
|
12231
|
+
resize: none;
|
|
12232
|
+
width: 1px;
|
|
12233
|
+
}
|
|
12234
|
+
|
|
11818
12235
|
.butex-widget .toolbar {
|
|
11819
12236
|
display: flex;
|
|
11820
12237
|
flex-wrap: wrap;
|
|
@@ -12816,6 +13233,7 @@ var ButexEditor = (0, import_react8.forwardRef)(
|
|
|
12816
13233
|
const messages = equationEditorMessages(uiLocale);
|
|
12817
13234
|
const wrapperRef = (0, import_react8.useRef)(null);
|
|
12818
13235
|
const surfaceRef = (0, import_react8.useRef)(null);
|
|
13236
|
+
const inputRef = (0, import_react8.useRef)(null);
|
|
12819
13237
|
const mathOutputRef = (0, import_react8.useRef)(null);
|
|
12820
13238
|
const renderErrorRef = (0, import_react8.useRef)(null);
|
|
12821
13239
|
const latexLinesRef = (0, import_react8.useRef)(null);
|
|
@@ -12927,6 +13345,7 @@ ${arabic || currentMessages.empty}`;
|
|
|
12927
13345
|
}
|
|
12928
13346
|
const runtime = createEditorRuntime({
|
|
12929
13347
|
surfaceEl,
|
|
13348
|
+
inputEl: inputRef.current,
|
|
12930
13349
|
initialSession,
|
|
12931
13350
|
defaultSide,
|
|
12932
13351
|
uiLocale,
|
|
@@ -12968,7 +13387,7 @@ ${arabic || currentMessages.empty}`;
|
|
|
12968
13387
|
} else {
|
|
12969
13388
|
runtime.render();
|
|
12970
13389
|
}
|
|
12971
|
-
|
|
13390
|
+
runtime.focusInput();
|
|
12972
13391
|
return () => {
|
|
12973
13392
|
runtime.destroy();
|
|
12974
13393
|
runtimeRef.current = null;
|
|
@@ -12982,7 +13401,7 @@ ${arabic || currentMessages.empty}`;
|
|
|
12982
13401
|
}
|
|
12983
13402
|
}, [uiLocale]);
|
|
12984
13403
|
function focusSurface() {
|
|
12985
|
-
|
|
13404
|
+
runtimeRef.current?.focusInput();
|
|
12986
13405
|
}
|
|
12987
13406
|
function insertSelectedEnvironment(rows, columns) {
|
|
12988
13407
|
if (envPaletteMode === "array") {
|
|
@@ -14060,6 +14479,20 @@ ${arabic || currentMessages.empty}`;
|
|
|
14060
14479
|
"aria-label": messages.equationEditor
|
|
14061
14480
|
}
|
|
14062
14481
|
),
|
|
14482
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
14483
|
+
"textarea",
|
|
14484
|
+
{
|
|
14485
|
+
ref: inputRef,
|
|
14486
|
+
className: "butex-editor-input-bridge",
|
|
14487
|
+
"aria-label": messages.equationEditor,
|
|
14488
|
+
autoCapitalize: "none",
|
|
14489
|
+
autoComplete: "off",
|
|
14490
|
+
autoCorrect: "off",
|
|
14491
|
+
inputMode: "text",
|
|
14492
|
+
spellCheck: false,
|
|
14493
|
+
tabIndex: -1
|
|
14494
|
+
}
|
|
14495
|
+
),
|
|
14063
14496
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { ref: renderErrorRef, className: "error", hidden: true })
|
|
14064
14497
|
] }),
|
|
14065
14498
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("section", { className: "panel panel-preview", "aria-label": messages.renderPreview, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { ref: mathOutputRef, className: "preview-box" }) }),
|
|
@@ -14785,7 +15218,7 @@ function RefPickerPopover({
|
|
|
14785
15218
|
|
|
14786
15219
|
// src/react-document2/editorFocus.ts
|
|
14787
15220
|
function createEmptyDocument2EditorFocus() {
|
|
14788
|
-
return { blockId: null, fieldId: null, textTokenId: null, caretOffset: 0 };
|
|
15221
|
+
return { blockId: null, fieldId: null, textTokenId: null, caretOffset: 0, selectionStart: 0, selectionEnd: 0 };
|
|
14789
15222
|
}
|
|
14790
15223
|
function findBlockIdForField(blocks, fieldId) {
|
|
14791
15224
|
for (const block of blocks) {
|
|
@@ -14993,6 +15426,89 @@ var DOCUMENT2_WIDGET_CSS = `
|
|
|
14993
15426
|
display: block;
|
|
14994
15427
|
}
|
|
14995
15428
|
|
|
15429
|
+
.butex-document2-widget__format-btn {
|
|
15430
|
+
font-family: "Amiri", "Noto Serif Arabic", Georgia, serif;
|
|
15431
|
+
min-width: 36px;
|
|
15432
|
+
}
|
|
15433
|
+
|
|
15434
|
+
.butex-document2-widget__format-icon {
|
|
15435
|
+
direction: rtl;
|
|
15436
|
+
display: inline-block;
|
|
15437
|
+
font-size: 0.84rem;
|
|
15438
|
+
font-weight: 500;
|
|
15439
|
+
}
|
|
15440
|
+
|
|
15441
|
+
.butex-document2-widget__format-icon--bold {
|
|
15442
|
+
font-weight: 900;
|
|
15443
|
+
}
|
|
15444
|
+
|
|
15445
|
+
.butex-document2-widget__format-icon--italic {
|
|
15446
|
+
font-style: italic;
|
|
15447
|
+
transform: skewX(-7deg);
|
|
15448
|
+
}
|
|
15449
|
+
|
|
15450
|
+
.butex-document2-widget__format-icon--underline {
|
|
15451
|
+
text-decoration: underline;
|
|
15452
|
+
text-underline-offset: 0.12em;
|
|
15453
|
+
}
|
|
15454
|
+
|
|
15455
|
+
.butex-document2-widget__format-underline,
|
|
15456
|
+
.butex-document2-widget__preview-underline {
|
|
15457
|
+
text-decoration: underline;
|
|
15458
|
+
text-underline-offset: 0.12em;
|
|
15459
|
+
}
|
|
15460
|
+
|
|
15461
|
+
.butex-document2-widget__references-menu {
|
|
15462
|
+
position: relative;
|
|
15463
|
+
}
|
|
15464
|
+
|
|
15465
|
+
.butex-document2-widget__references-trigger {
|
|
15466
|
+
gap: 5px;
|
|
15467
|
+
white-space: nowrap;
|
|
15468
|
+
}
|
|
15469
|
+
|
|
15470
|
+
.butex-document2-widget__menu-chevron {
|
|
15471
|
+
color: var(--butex-document2-muted);
|
|
15472
|
+
font-size: 0.8rem;
|
|
15473
|
+
}
|
|
15474
|
+
|
|
15475
|
+
.butex-document2-widget__references-menu-options {
|
|
15476
|
+
background: var(--butex-document2-panel);
|
|
15477
|
+
border: 1px solid var(--butex-document2-border);
|
|
15478
|
+
border-radius: 8px;
|
|
15479
|
+
box-shadow: 0 8px 24px color-mix(in srgb, var(--butex-document2-fg) 16%, transparent);
|
|
15480
|
+
display: grid;
|
|
15481
|
+
gap: 2px;
|
|
15482
|
+
inset-inline-start: 0;
|
|
15483
|
+
margin-top: 4px;
|
|
15484
|
+
min-width: max-content;
|
|
15485
|
+
padding: 4px;
|
|
15486
|
+
position: absolute;
|
|
15487
|
+
top: 100%;
|
|
15488
|
+
z-index: 30;
|
|
15489
|
+
}
|
|
15490
|
+
|
|
15491
|
+
.butex-document2-widget__references-menu-options button {
|
|
15492
|
+
align-items: center;
|
|
15493
|
+
background: transparent;
|
|
15494
|
+
border: 0;
|
|
15495
|
+
border-radius: 6px;
|
|
15496
|
+
color: var(--butex-document2-fg);
|
|
15497
|
+
cursor: pointer;
|
|
15498
|
+
display: grid;
|
|
15499
|
+
font: inherit;
|
|
15500
|
+
gap: 8px;
|
|
15501
|
+
grid-template-columns: 18px 1fr;
|
|
15502
|
+
padding: 7px 9px;
|
|
15503
|
+
text-align: start;
|
|
15504
|
+
}
|
|
15505
|
+
|
|
15506
|
+
.butex-document2-widget__references-menu-options button:hover,
|
|
15507
|
+
.butex-document2-widget__references-menu-options button:focus-visible {
|
|
15508
|
+
background: var(--butex-document2-accent-bg);
|
|
15509
|
+
outline: none;
|
|
15510
|
+
}
|
|
15511
|
+
|
|
14996
15512
|
.butex-document2-widget__float-meta {
|
|
14997
15513
|
display: grid;
|
|
14998
15514
|
gap: 8px;
|
|
@@ -15436,6 +15952,19 @@ var DOCUMENT2_WIDGET_CSS = `
|
|
|
15436
15952
|
border-color: color-mix(in srgb, var(--butex-document2-text-token-border) 55%, var(--butex-document2-accent));
|
|
15437
15953
|
}
|
|
15438
15954
|
|
|
15955
|
+
.butex-document2-widget__inline-text[data-bold="true"] {
|
|
15956
|
+
font-weight: 700;
|
|
15957
|
+
}
|
|
15958
|
+
|
|
15959
|
+
.butex-document2-widget__inline-text[data-italic="true"] {
|
|
15960
|
+
font-style: italic;
|
|
15961
|
+
}
|
|
15962
|
+
|
|
15963
|
+
.butex-document2-widget__inline-text[data-underline="true"] {
|
|
15964
|
+
text-decoration: underline;
|
|
15965
|
+
text-underline-offset: 0.12em;
|
|
15966
|
+
}
|
|
15967
|
+
|
|
15439
15968
|
.butex-document2-widget__inline-field input {
|
|
15440
15969
|
min-width: 12ch;
|
|
15441
15970
|
}
|
|
@@ -16453,6 +16982,50 @@ function topLevelBlockIdForField(document2, fieldId) {
|
|
|
16453
16982
|
function topLevelBlockIdForToken(document2, tokenId) {
|
|
16454
16983
|
return document2.blocks.find((block) => blockHasToken(block, tokenId))?.id ?? null;
|
|
16455
16984
|
}
|
|
16985
|
+
function findFormatTextToken(document2, focus) {
|
|
16986
|
+
if (!focus.fieldId || !focus.textTokenId || focus.selectionEnd <= focus.selectionStart) {
|
|
16987
|
+
return null;
|
|
16988
|
+
}
|
|
16989
|
+
function textTokenFromField(field) {
|
|
16990
|
+
if (field.id !== focus.fieldId) {
|
|
16991
|
+
return null;
|
|
16992
|
+
}
|
|
16993
|
+
const token = field.tokens.find((entry) => entry.id === focus.textTokenId && entry.kind === "text");
|
|
16994
|
+
return token ?? null;
|
|
16995
|
+
}
|
|
16996
|
+
function visit(blocks) {
|
|
16997
|
+
for (const block of blocks) {
|
|
16998
|
+
if (block.kind === "textBlock") {
|
|
16999
|
+
const token = block.command === "\\paragraph" ? textTokenFromField(block.field) : null;
|
|
17000
|
+
if (token) {
|
|
17001
|
+
return token;
|
|
17002
|
+
}
|
|
17003
|
+
} else if (block.kind === "list") {
|
|
17004
|
+
for (const item of block.items) {
|
|
17005
|
+
const itemToken = textTokenFromField(item.field);
|
|
17006
|
+
if (itemToken) {
|
|
17007
|
+
return itemToken;
|
|
17008
|
+
}
|
|
17009
|
+
const nestedToken = visit(item.blocks);
|
|
17010
|
+
if (nestedToken) {
|
|
17011
|
+
return nestedToken;
|
|
17012
|
+
}
|
|
17013
|
+
}
|
|
17014
|
+
} else if (block.kind === "table") {
|
|
17015
|
+
for (const row of block.rows) {
|
|
17016
|
+
for (const cell of row) {
|
|
17017
|
+
const token = textTokenFromField(cell);
|
|
17018
|
+
if (token) {
|
|
17019
|
+
return token;
|
|
17020
|
+
}
|
|
17021
|
+
}
|
|
17022
|
+
}
|
|
17023
|
+
}
|
|
17024
|
+
}
|
|
17025
|
+
return null;
|
|
17026
|
+
}
|
|
17027
|
+
return visit(document2.blocks);
|
|
17028
|
+
}
|
|
16456
17029
|
function formatDocument2Diagnostic(d, messages) {
|
|
16457
17030
|
if (d.message === "math_objects order mismatch") {
|
|
16458
17031
|
return `${messages.importOrderMismatch} ${messages.path}: ${d.path}`;
|
|
@@ -16571,6 +17144,9 @@ function ButexDocumentEditor2({
|
|
|
16571
17144
|
const selectionCount = blockSelection ? blockSelection.to - blockSelection.from + 1 : 0;
|
|
16572
17145
|
const canMoveSelectionUp = Boolean(blockSelection && blockSelection.from > 0);
|
|
16573
17146
|
const canMoveSelectionDown = Boolean(blockSelection && blockSelection.to < documentNode.blocks.length - 1);
|
|
17147
|
+
const formatTextToken = (0, import_react13.useMemo)(() => findFormatTextToken(documentNode, editorFocus), [documentNode, editorFocus]);
|
|
17148
|
+
const canFormatText = formatTextToken !== null;
|
|
17149
|
+
const activeTextStyles = formatTextToken?.style ?? {};
|
|
16574
17150
|
function clearBlockSelection() {
|
|
16575
17151
|
setBlockSelectionState(emptyBlockSelection());
|
|
16576
17152
|
}
|
|
@@ -16771,15 +17347,15 @@ function ButexDocumentEditor2({
|
|
|
16771
17347
|
root.addEventListener("keydown", onKeyDown);
|
|
16772
17348
|
return () => root.removeEventListener("keydown", onKeyDown);
|
|
16773
17349
|
}, [editorOpen]);
|
|
16774
|
-
function rememberFieldFocus(blockId, fieldId, textTokenId, caretOffset) {
|
|
17350
|
+
function rememberFieldFocus(blockId, fieldId, textTokenId, caretOffset, selectionStart, selectionEnd) {
|
|
16775
17351
|
openBlock(blockId);
|
|
16776
17352
|
clearBlockSelection();
|
|
16777
|
-
setEditorFocus({ blockId, fieldId, textTokenId, caretOffset });
|
|
17353
|
+
setEditorFocus({ blockId, fieldId, textTokenId, caretOffset, selectionStart, selectionEnd });
|
|
16778
17354
|
}
|
|
16779
17355
|
function rememberMathFocus(blockId, fieldId) {
|
|
16780
17356
|
openBlock(blockId);
|
|
16781
17357
|
clearBlockSelection();
|
|
16782
|
-
setEditorFocus({ blockId, fieldId, textTokenId: null, caretOffset: 0 });
|
|
17358
|
+
setEditorFocus({ blockId, fieldId, textTokenId: null, caretOffset: 0, selectionStart: 0, selectionEnd: 0 });
|
|
16783
17359
|
}
|
|
16784
17360
|
function rememberBlockFocus(blockId) {
|
|
16785
17361
|
openBlock(blockId);
|
|
@@ -17042,6 +17618,22 @@ function ButexDocumentEditor2({
|
|
|
17042
17618
|
function deleteRefToken(tokenId) {
|
|
17043
17619
|
applyDocument(removeRefTokenById(documentRef.current, tokenId), "immediate");
|
|
17044
17620
|
}
|
|
17621
|
+
function toggleInlineTextStyle(styleName) {
|
|
17622
|
+
if (!canFormatText || !editorFocus.fieldId || !editorFocus.textTokenId) {
|
|
17623
|
+
return;
|
|
17624
|
+
}
|
|
17625
|
+
applyDocument(
|
|
17626
|
+
toggleTextTokenStyle(
|
|
17627
|
+
documentRef.current,
|
|
17628
|
+
editorFocus.fieldId,
|
|
17629
|
+
editorFocus.textTokenId,
|
|
17630
|
+
editorFocus.selectionStart,
|
|
17631
|
+
editorFocus.selectionEnd,
|
|
17632
|
+
styleName
|
|
17633
|
+
),
|
|
17634
|
+
"immediate"
|
|
17635
|
+
);
|
|
17636
|
+
}
|
|
17045
17637
|
const showEditorPanel = !previewOnly && editorOpen;
|
|
17046
17638
|
const showPreviewPanel = previewOnly || previewOpen;
|
|
17047
17639
|
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
@@ -17064,8 +17656,11 @@ function ButexDocumentEditor2({
|
|
|
17064
17656
|
selectionCount,
|
|
17065
17657
|
canMoveSelectionUp,
|
|
17066
17658
|
canMoveSelectionDown,
|
|
17659
|
+
canFormatText,
|
|
17660
|
+
activeTextStyles,
|
|
17067
17661
|
onUndo: undoDocument,
|
|
17068
17662
|
onRedo: redoDocument,
|
|
17663
|
+
onToggleTextStyle: toggleInlineTextStyle,
|
|
17069
17664
|
onMoveSelectionUp: () => moveSelectedBlocks(-1),
|
|
17070
17665
|
onMoveSelectionDown: () => moveSelectedBlocks(1),
|
|
17071
17666
|
onDeleteSelection: deleteSelectedBlocks,
|