@baasix/lexical 0.0.10 → 0.0.12
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/dist/index.js +974 -576
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -57,11 +57,11 @@ import "./chunk-PZ5AY32C.js";
|
|
|
57
57
|
|
|
58
58
|
// src/LexicalEditor.tsx
|
|
59
59
|
import {
|
|
60
|
-
useCallback as
|
|
60
|
+
useCallback as useCallback31,
|
|
61
61
|
useEffect as useEffect48,
|
|
62
62
|
useMemo as useMemo24,
|
|
63
|
-
useRef as
|
|
64
|
-
useState as
|
|
63
|
+
useRef as useRef20,
|
|
64
|
+
useState as useState44
|
|
65
65
|
} from "react";
|
|
66
66
|
import { LexicalComposer as LexicalComposer2 } from "@lexical/react/LexicalComposer";
|
|
67
67
|
import { OnChangePlugin as OnChangePlugin2 } from "@lexical/react/LexicalOnChangePlugin";
|
|
@@ -87,7 +87,7 @@ import { TabIndentationPlugin } from "@lexical/react/LexicalTabIndentationPlugin
|
|
|
87
87
|
import { TablePlugin } from "@lexical/react/LexicalTablePlugin";
|
|
88
88
|
import { useLexicalEditable as useLexicalEditable10 } from "@lexical/react/useLexicalEditable";
|
|
89
89
|
import { CAN_USE_DOM } from "@lexical/utils";
|
|
90
|
-
import { useEffect as useEffect47, useState as
|
|
90
|
+
import { useEffect as useEffect47, useState as useState43 } from "react";
|
|
91
91
|
|
|
92
92
|
// src/plugins/ActionsPlugin/index.tsx
|
|
93
93
|
import { $createCodeNode, $isCodeNode } from "@lexical/code";
|
|
@@ -6234,7 +6234,7 @@ import {
|
|
|
6234
6234
|
$isRangeSelection as $isRangeSelection7,
|
|
6235
6235
|
FORMAT_ELEMENT_COMMAND
|
|
6236
6236
|
} from "lexical";
|
|
6237
|
-
import { useCallback as
|
|
6237
|
+
import { useCallback as useCallback23, useMemo as useMemo18, useState as useState31 } from "react";
|
|
6238
6238
|
import * as ReactDOM2 from "react-dom";
|
|
6239
6239
|
|
|
6240
6240
|
// src/plugins/DateTimePlugin/index.tsx
|
|
@@ -7646,7 +7646,7 @@ function PageBreakPlugin() {
|
|
|
7646
7646
|
import { useLexicalComposerContext as useLexicalComposerContext21 } from "@lexical/react/LexicalComposerContext";
|
|
7647
7647
|
import { $insertNodeToNearestRoot as $insertNodeToNearestRoot7 } from "@lexical/utils";
|
|
7648
7648
|
import { COMMAND_PRIORITY_EDITOR as COMMAND_PRIORITY_EDITOR13, createCommand as createCommand13 } from "lexical";
|
|
7649
|
-
import { useCallback as useCallback12, useEffect as useEffect23, useMemo as useMemo8, useState as useState18 } from "react";
|
|
7649
|
+
import { useCallback as useCallback12, useEffect as useEffect23, useMemo as useMemo8, useRef as useRef9, useState as useState18 } from "react";
|
|
7650
7650
|
|
|
7651
7651
|
// src/nodes/NotesNode.tsx
|
|
7652
7652
|
import { $getNodeByKey as $getNodeByKey4 } from "lexical";
|
|
@@ -7942,34 +7942,68 @@ function convertNotes(input) {
|
|
|
7942
7942
|
const doc = parser.parseFromString(input, "text/html");
|
|
7943
7943
|
html += Array.from(doc.body.childNodes).map(processNode).join("");
|
|
7944
7944
|
} else {
|
|
7945
|
-
const paragraphs = input.split(/\n\s*\n/);
|
|
7946
7945
|
const style = CARD_STYLES.notes;
|
|
7947
|
-
|
|
7948
|
-
|
|
7949
|
-
|
|
7950
|
-
if (
|
|
7951
|
-
|
|
7952
|
-
const isOrdered = p.match(/^\d+\./);
|
|
7953
|
-
const tag = isOrdered ? "ol" : "ul";
|
|
7954
|
-
html += ` <${tag} style="margin-left: 20px; padding-left: 20px; margin-bottom: 15px;">
|
|
7946
|
+
const lines = input.split("\n");
|
|
7947
|
+
let inList = null;
|
|
7948
|
+
const closeList = () => {
|
|
7949
|
+
if (inList) {
|
|
7950
|
+
html += ` </${inList}>
|
|
7955
7951
|
`;
|
|
7956
|
-
|
|
7957
|
-
|
|
7958
|
-
|
|
7959
|
-
|
|
7952
|
+
inList = null;
|
|
7953
|
+
}
|
|
7954
|
+
};
|
|
7955
|
+
const isBullet = (line) => /^[\s]*[-•*]\s/.test(line);
|
|
7956
|
+
const isOrdered = (line) => /^[\s]*\d+[.)]\s/.test(line);
|
|
7957
|
+
const isHeading = (line) => {
|
|
7958
|
+
const t = line.trim();
|
|
7959
|
+
if (t.length > 120 || t.length < 2) return false;
|
|
7960
|
+
if (t.endsWith(".") || t.endsWith(",")) return false;
|
|
7961
|
+
if (isBullet(t) || isOrdered(t)) return false;
|
|
7962
|
+
if (t.endsWith(":")) return true;
|
|
7963
|
+
if (t.length < 80 && !/[.!?,;]$/.test(t)) return true;
|
|
7964
|
+
return false;
|
|
7965
|
+
};
|
|
7966
|
+
for (let i = 0; i < lines.length; i++) {
|
|
7967
|
+
const line = lines[i];
|
|
7968
|
+
const trimmed = line.trim();
|
|
7969
|
+
if (!trimmed) {
|
|
7970
|
+
closeList();
|
|
7971
|
+
continue;
|
|
7972
|
+
}
|
|
7973
|
+
if (isBullet(trimmed)) {
|
|
7974
|
+
if (inList !== "ul") {
|
|
7975
|
+
closeList();
|
|
7976
|
+
inList = "ul";
|
|
7977
|
+
html += ` <ul style="margin-left: 20px; padding-left: 20px; margin-bottom: 15px;">
|
|
7960
7978
|
`;
|
|
7961
|
-
|
|
7962
|
-
|
|
7963
|
-
html += `
|
|
7979
|
+
}
|
|
7980
|
+
const cleanItem = trimmed.replace(/^[-•*]\s*/, "");
|
|
7981
|
+
html += ` <li style="margin-bottom: 5px;">${cleanItem}</li>
|
|
7964
7982
|
`;
|
|
7965
|
-
|
|
7966
|
-
|
|
7983
|
+
continue;
|
|
7984
|
+
}
|
|
7985
|
+
if (isOrdered(trimmed)) {
|
|
7986
|
+
if (inList !== "ol") {
|
|
7987
|
+
closeList();
|
|
7988
|
+
inList = "ol";
|
|
7989
|
+
html += ` <ol style="margin-left: 20px; padding-left: 20px; margin-bottom: 15px;">
|
|
7967
7990
|
`;
|
|
7968
|
-
|
|
7969
|
-
|
|
7991
|
+
}
|
|
7992
|
+
const cleanItem = trimmed.replace(/^\d+[.)]\s*/, "");
|
|
7993
|
+
html += ` <li style="margin-bottom: 5px;">${cleanItem}</li>
|
|
7970
7994
|
`;
|
|
7995
|
+
continue;
|
|
7971
7996
|
}
|
|
7972
|
-
|
|
7997
|
+
closeList();
|
|
7998
|
+
if (isHeading(trimmed)) {
|
|
7999
|
+
html += ` <h3 style="color: ${style.headingColor}; border-bottom: 2px solid ${style.headingBorder}; padding-bottom: 5px; margin-top: 25px; margin-bottom: 15px;">${trimmed}</h3>
|
|
8000
|
+
`;
|
|
8001
|
+
continue;
|
|
8002
|
+
}
|
|
8003
|
+
html += ` <p style="margin-bottom: 15px;">${trimmed}</p>
|
|
8004
|
+
`;
|
|
8005
|
+
}
|
|
8006
|
+
closeList();
|
|
7973
8007
|
}
|
|
7974
8008
|
html += "</div>";
|
|
7975
8009
|
return compactHtml(html);
|
|
@@ -8133,7 +8167,7 @@ function convertTextCards(input) {
|
|
|
8133
8167
|
const c = styles[key];
|
|
8134
8168
|
html += ` <div style="background: ${c.light}; border: 2px solid ${c.border}; border-left: 4px solid ${c.border}; padding: 16px; border-radius: 12px; min-height: 120px;">
|
|
8135
8169
|
<h3 style="margin-top: 0; color: inherit; font-size: 14px;">${c.emoji} ${c.number}. ${c.title}</h3>
|
|
8136
|
-
<p style="margin: 0; font-size: 13px;">${content}</p>
|
|
8170
|
+
<p style="margin: 0; font-size: 13px;">${nl2br(content)}</p>
|
|
8137
8171
|
</div>
|
|
8138
8172
|
`;
|
|
8139
8173
|
});
|
|
@@ -8239,8 +8273,8 @@ var QUESTIONS_CARD_GRID_SECTIONS = [
|
|
|
8239
8273
|
"tips"
|
|
8240
8274
|
];
|
|
8241
8275
|
var QUESTIONS_SECTION_PATTERNS = {
|
|
8242
|
-
question: /^Q\
|
|
8243
|
-
answer: /^Answer:\s
|
|
8276
|
+
question: /^(\d+\.\s*)?Q(uestion|\d+)\s*[\s.:]/i,
|
|
8277
|
+
answer: /^(Model\s+)?Answer:\s*/i,
|
|
8244
8278
|
rubric: /^(\d+\.\s*)?MARKING\s+RUBRIC/i,
|
|
8245
8279
|
mnemonics: /^(\d+\.\s*)?MNEMONIC/i,
|
|
8246
8280
|
examiner: /^(\d+\.\s*)?EXAMINER/i,
|
|
@@ -8251,103 +8285,244 @@ var QUESTIONS_SECTION_PATTERNS = {
|
|
|
8251
8285
|
variations: /^(\d+\.\s*)?EXAM\s+VARIATION/i,
|
|
8252
8286
|
tips: /^(\d+\.\s*)?(HIGH-YIELD|EXAM\s+TIP)/i
|
|
8253
8287
|
};
|
|
8288
|
+
function formatMcqQuestion(text) {
|
|
8289
|
+
const optionMatch = text.match(/\s+[a-eA-E][)]\s/);
|
|
8290
|
+
if (!optionMatch || optionMatch.index === void 0) return text;
|
|
8291
|
+
const questionPart = text.substring(0, optionMatch.index).trim();
|
|
8292
|
+
const optionsPart = text.substring(optionMatch.index).trim();
|
|
8293
|
+
const options = optionsPart.split(/(?=\s*[a-eA-E][)]\s)/).map((o) => o.trim()).filter(Boolean);
|
|
8294
|
+
if (options.length < 2) return text;
|
|
8295
|
+
let optionsHtml = '<div style="margin-top: 10px; display: flex; flex-direction: column; gap: 6px;">';
|
|
8296
|
+
options.forEach((opt) => {
|
|
8297
|
+
const letter = opt.charAt(0).toUpperCase();
|
|
8298
|
+
const optText = opt.replace(/^[a-eA-E][)]\s*/, "").trim();
|
|
8299
|
+
optionsHtml += `<div style="display: flex; align-items: baseline; gap: 8px;">
|
|
8300
|
+
<span style="background: rgba(0,0,0,0.08); border-radius: 4px; padding: 2px 8px; font-weight: 600; font-size: 13px; min-width: 24px; text-align: center;">${letter}</span>
|
|
8301
|
+
<span style="font-size: 14px;">${optText}</span>
|
|
8302
|
+
</div>`;
|
|
8303
|
+
});
|
|
8304
|
+
optionsHtml += "</div>";
|
|
8305
|
+
return `${questionPart}${optionsHtml}`;
|
|
8306
|
+
}
|
|
8307
|
+
function formatMcqAnswer(text) {
|
|
8308
|
+
const match = text.match(/^([a-eA-E])[)]\s*/);
|
|
8309
|
+
if (!match) return text;
|
|
8310
|
+
const letter = match[1].toUpperCase();
|
|
8311
|
+
const explanation = text.substring(match[0].length).trim();
|
|
8312
|
+
return `<span style="background: rgba(76, 175, 80, 0.15); border: 1px solid rgba(76, 175, 80, 0.4); border-radius: 4px; padding: 2px 8px; font-weight: 700; font-size: 14px; margin-right: 8px;">${letter}</span> ${explanation}`;
|
|
8313
|
+
}
|
|
8314
|
+
function nl2br(text) {
|
|
8315
|
+
return text.replace(/\n/g, "<br>");
|
|
8316
|
+
}
|
|
8254
8317
|
function convertQuestionsCards(input) {
|
|
8255
8318
|
if (!input.trim()) return "";
|
|
8256
|
-
const
|
|
8319
|
+
const parsed = parseQuestionsInput(input);
|
|
8257
8320
|
const styles = CARD_STYLES.questionsCards;
|
|
8258
8321
|
let html = "";
|
|
8259
|
-
|
|
8260
|
-
|
|
8261
|
-
|
|
8262
|
-
|
|
8263
|
-
|
|
8322
|
+
parsed.qaPairs.forEach((qa, idx) => {
|
|
8323
|
+
if (qa.question) {
|
|
8324
|
+
const c = styles.question;
|
|
8325
|
+
const qLabel = parsed.qaPairs.length > 1 ? `Question ${idx + 1}` : "Question";
|
|
8326
|
+
const formattedQ = formatMcqQuestion(nl2br(qa.question));
|
|
8327
|
+
html += `<div style="background: ${c.light}; border: 2px solid ${c.border}; border-left: 4px solid ${c.border}; padding: 16px 20px; border-radius: 12px; margin-bottom: 20px;">
|
|
8328
|
+
<h3 style="margin: 0; color: inherit;">${c.emoji} ${qLabel}</h3>
|
|
8329
|
+
<div style="margin-top: 8px; color: inherit;">${formattedQ}</div>
|
|
8264
8330
|
</div>
|
|
8265
8331
|
`;
|
|
8266
|
-
|
|
8267
|
-
|
|
8268
|
-
|
|
8269
|
-
|
|
8332
|
+
}
|
|
8333
|
+
if (qa.answer) {
|
|
8334
|
+
const c = styles.answer;
|
|
8335
|
+
const formattedA = formatMcqAnswer(nl2br(qa.answer));
|
|
8336
|
+
html += `<div style="background: ${c.light}; border: 2px solid ${c.border}; border-left: 4px solid ${c.border}; padding: 16px 20px; border-radius: 12px; margin-bottom: 20px;">
|
|
8270
8337
|
<h3 style="margin-top: 0; color: inherit;">${c.emoji} ${c.title}</h3>
|
|
8271
|
-
<p>${
|
|
8338
|
+
<p>${formattedA}</p>
|
|
8272
8339
|
</div>
|
|
8273
8340
|
`;
|
|
8274
|
-
|
|
8275
|
-
|
|
8276
|
-
|
|
8277
|
-
|
|
8341
|
+
}
|
|
8342
|
+
const qaSections = qa.sections || {};
|
|
8343
|
+
const hasGridCards = QUESTIONS_CARD_GRID_SECTIONS.some((k) => qaSections[k]);
|
|
8344
|
+
if (hasGridCards) {
|
|
8345
|
+
html += `<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 16px; margin-top: 8px; margin-bottom: 24px;">
|
|
8278
8346
|
`;
|
|
8279
|
-
|
|
8280
|
-
|
|
8281
|
-
|
|
8282
|
-
|
|
8283
|
-
|
|
8347
|
+
QUESTIONS_CARD_GRID_SECTIONS.forEach((key) => {
|
|
8348
|
+
const content = qaSections[key];
|
|
8349
|
+
if (!content) return;
|
|
8350
|
+
const c = styles[key];
|
|
8351
|
+
html += ` <div style="background: ${c.light}; border: 2px solid ${c.border}; border-left: 4px solid ${c.border}; padding: 16px; border-radius: 12px; min-height: 120px;">
|
|
8284
8352
|
<h3 style="margin-top: 0; color: inherit; font-size: 14px;">${c.emoji} ${c.number}. ${c.title}</h3>
|
|
8285
|
-
<p style="margin: 0; font-size: 13px;">${content}</p>
|
|
8353
|
+
<p style="margin: 0; font-size: 13px;">${nl2br(content)}</p>
|
|
8286
8354
|
</div>
|
|
8287
8355
|
`;
|
|
8288
|
-
|
|
8289
|
-
|
|
8290
|
-
|
|
8356
|
+
});
|
|
8357
|
+
html += "</div>\n";
|
|
8358
|
+
}
|
|
8359
|
+
});
|
|
8291
8360
|
return compactHtml(html);
|
|
8292
8361
|
}
|
|
8362
|
+
var INLINE_ANSWER_PATTERNS = [
|
|
8363
|
+
/\s+Correct\s+Answer:\s*/i,
|
|
8364
|
+
/\s+Model\s+Answer:\s*/i
|
|
8365
|
+
];
|
|
8366
|
+
var MCQ_LINE_PATTERN = /^\d+[.)]\s+/;
|
|
8293
8367
|
function parseQuestionsInput(input) {
|
|
8294
8368
|
const lines = input.split("\n").filter((l) => l.trim());
|
|
8295
|
-
const
|
|
8369
|
+
const result = { qaPairs: [] };
|
|
8296
8370
|
let currentSection = null;
|
|
8297
8371
|
let contentBuffer = [];
|
|
8298
|
-
|
|
8372
|
+
let currentQA = { question: "", answer: "", sections: {} };
|
|
8373
|
+
let inQASection = null;
|
|
8374
|
+
const flushQA = () => {
|
|
8375
|
+
if (inQASection === "question") {
|
|
8376
|
+
currentQA.question = contentBuffer.join("\n").trim();
|
|
8377
|
+
} else if (inQASection === "answer") {
|
|
8378
|
+
currentQA.answer = contentBuffer.join("\n").trim();
|
|
8379
|
+
}
|
|
8380
|
+
contentBuffer = [];
|
|
8381
|
+
};
|
|
8382
|
+
const flushSection = () => {
|
|
8299
8383
|
if (currentSection && contentBuffer.length > 0) {
|
|
8300
|
-
sections[currentSection] = contentBuffer.join("
|
|
8384
|
+
currentQA.sections[currentSection] = contentBuffer.join("\n").trim();
|
|
8301
8385
|
}
|
|
8302
8386
|
contentBuffer = [];
|
|
8303
8387
|
};
|
|
8388
|
+
const pushCurrentQA = () => {
|
|
8389
|
+
if (currentQA.question || currentQA.answer || Object.keys(currentQA.sections).length > 0) {
|
|
8390
|
+
result.qaPairs.push({ ...currentQA, sections: { ...currentQA.sections } });
|
|
8391
|
+
currentQA = { question: "", answer: "", sections: {} };
|
|
8392
|
+
}
|
|
8393
|
+
};
|
|
8394
|
+
const trySplitInline = (line) => {
|
|
8395
|
+
for (const pattern of INLINE_ANSWER_PATTERNS) {
|
|
8396
|
+
const match = line.match(pattern);
|
|
8397
|
+
if (match && match.index !== void 0) {
|
|
8398
|
+
return {
|
|
8399
|
+
question: line.substring(0, match.index).trim(),
|
|
8400
|
+
answer: line.substring(match.index + match[0].length).trim()
|
|
8401
|
+
};
|
|
8402
|
+
}
|
|
8403
|
+
}
|
|
8404
|
+
return null;
|
|
8405
|
+
};
|
|
8304
8406
|
for (const line of lines) {
|
|
8305
8407
|
const trimmed = line.trim();
|
|
8408
|
+
if (QUESTIONS_SECTION_PATTERNS.question.test(trimmed)) {
|
|
8409
|
+
if (inQASection) flushQA();
|
|
8410
|
+
if (currentSection) {
|
|
8411
|
+
flushSection();
|
|
8412
|
+
currentSection = null;
|
|
8413
|
+
}
|
|
8414
|
+
pushCurrentQA();
|
|
8415
|
+
const qText = trimmed.replace(/^(\d+\.\s*)?Q(uestion|\d+)\s*[\s.:]+/i, "").trim();
|
|
8416
|
+
const inlineSplit = trySplitInline(qText);
|
|
8417
|
+
if (inlineSplit) {
|
|
8418
|
+
currentQA = { question: inlineSplit.question, answer: inlineSplit.answer, sections: {} };
|
|
8419
|
+
inQASection = null;
|
|
8420
|
+
} else {
|
|
8421
|
+
inQASection = "question";
|
|
8422
|
+
if (qText) contentBuffer.push(qText);
|
|
8423
|
+
}
|
|
8424
|
+
continue;
|
|
8425
|
+
}
|
|
8426
|
+
if (QUESTIONS_SECTION_PATTERNS.answer.test(trimmed)) {
|
|
8427
|
+
if (inQASection) flushQA();
|
|
8428
|
+
if (currentSection) {
|
|
8429
|
+
flushSection();
|
|
8430
|
+
currentSection = null;
|
|
8431
|
+
}
|
|
8432
|
+
inQASection = "answer";
|
|
8433
|
+
const aText = trimmed.replace(/^(Model\s+)?Answer:\s*/i, "").trim();
|
|
8434
|
+
if (aText) contentBuffer.push(aText);
|
|
8435
|
+
continue;
|
|
8436
|
+
}
|
|
8437
|
+
if (MCQ_LINE_PATTERN.test(trimmed) && !QUESTIONS_SECTION_PATTERNS.question.test(trimmed)) {
|
|
8438
|
+
const inlineSplit = trySplitInline(trimmed);
|
|
8439
|
+
if (inlineSplit) {
|
|
8440
|
+
if (inQASection) flushQA();
|
|
8441
|
+
if (currentSection) {
|
|
8442
|
+
flushSection();
|
|
8443
|
+
currentSection = null;
|
|
8444
|
+
}
|
|
8445
|
+
pushCurrentQA();
|
|
8446
|
+
const qText = inlineSplit.question.replace(/^\d+[.)]\s*/, "").trim();
|
|
8447
|
+
currentQA = { question: qText, answer: inlineSplit.answer, sections: {} };
|
|
8448
|
+
inQASection = null;
|
|
8449
|
+
continue;
|
|
8450
|
+
}
|
|
8451
|
+
}
|
|
8306
8452
|
let foundSection = false;
|
|
8307
8453
|
for (const [key, pattern] of Object.entries(QUESTIONS_SECTION_PATTERNS)) {
|
|
8454
|
+
if (key === "question" || key === "answer") continue;
|
|
8308
8455
|
if (pattern.test(trimmed)) {
|
|
8309
|
-
|
|
8456
|
+
if (inQASection) {
|
|
8457
|
+
flushQA();
|
|
8458
|
+
inQASection = null;
|
|
8459
|
+
}
|
|
8460
|
+
if (currentSection) flushSection();
|
|
8310
8461
|
currentSection = key;
|
|
8311
8462
|
foundSection = true;
|
|
8312
|
-
if (key === "question") {
|
|
8313
|
-
const qText = trimmed.replace(/^Q\d+\.\s*/, "").trim();
|
|
8314
|
-
if (qText) contentBuffer.push(qText);
|
|
8315
|
-
}
|
|
8316
8463
|
break;
|
|
8317
8464
|
}
|
|
8318
8465
|
}
|
|
8319
8466
|
if (foundSection) continue;
|
|
8320
|
-
|
|
8321
|
-
contentBuffer.push(trimmed);
|
|
8322
|
-
}
|
|
8467
|
+
contentBuffer.push(trimmed);
|
|
8323
8468
|
}
|
|
8324
|
-
|
|
8325
|
-
|
|
8469
|
+
if (inQASection) flushQA();
|
|
8470
|
+
if (currentSection) flushSection();
|
|
8471
|
+
pushCurrentQA();
|
|
8472
|
+
return result;
|
|
8326
8473
|
}
|
|
8327
8474
|
function parseQuestionsCardsHtml(html) {
|
|
8328
8475
|
const parser = new DOMParser();
|
|
8329
8476
|
const doc = parser.parseFromString(html, "text/html");
|
|
8330
8477
|
const result = {
|
|
8331
|
-
|
|
8332
|
-
answer: "",
|
|
8333
|
-
sections: []
|
|
8478
|
+
qaPairs: []
|
|
8334
8479
|
};
|
|
8335
8480
|
const styles = CARD_STYLES.questionsCards;
|
|
8336
8481
|
const gridEntries = QUESTIONS_CARD_GRID_SECTIONS.map((k) => ({ key: k, title: styles[k].title }));
|
|
8482
|
+
let currentQA = null;
|
|
8337
8483
|
const children = Array.from(doc.body.children);
|
|
8338
8484
|
for (const el of children) {
|
|
8339
8485
|
const h3 = el.querySelector("h3");
|
|
8340
8486
|
if (!h3) continue;
|
|
8341
8487
|
const h3Text = (h3.textContent || "").trim();
|
|
8342
8488
|
if (h3Text.includes("Question")) {
|
|
8489
|
+
if (currentQA) result.qaPairs.push(currentQA);
|
|
8490
|
+
currentQA = { question: "", answer: "", sections: [] };
|
|
8343
8491
|
const clone = el.cloneNode(true);
|
|
8344
8492
|
clone.querySelector("h3")?.remove();
|
|
8345
|
-
|
|
8493
|
+
const optionsContainer = clone.querySelector('div[style*="flex-direction"]');
|
|
8494
|
+
if (optionsContainer) {
|
|
8495
|
+
const optionDivs = optionsContainer.querySelectorAll("div");
|
|
8496
|
+
const options = [];
|
|
8497
|
+
optionDivs.forEach((optDiv) => {
|
|
8498
|
+
const spans = optDiv.querySelectorAll("span");
|
|
8499
|
+
if (spans.length >= 2) {
|
|
8500
|
+
const letter = (spans[0].textContent || "").trim().toLowerCase();
|
|
8501
|
+
const text = (spans[1].textContent || "").trim();
|
|
8502
|
+
options.push(`${letter}) ${text}`);
|
|
8503
|
+
}
|
|
8504
|
+
});
|
|
8505
|
+
optionsContainer.remove();
|
|
8506
|
+
const qText = (clone.textContent || "").trim();
|
|
8507
|
+
currentQA.question = qText + (options.length > 0 ? " " + options.join(" ") : "");
|
|
8508
|
+
} else {
|
|
8509
|
+
currentQA.question = (clone.textContent || "").trim();
|
|
8510
|
+
}
|
|
8346
8511
|
} else if (h3Text.includes("Answer")) {
|
|
8512
|
+
if (!currentQA) currentQA = { question: "", answer: "", sections: [] };
|
|
8347
8513
|
const clone = el.cloneNode(true);
|
|
8348
8514
|
clone.querySelector("h3")?.remove();
|
|
8349
|
-
|
|
8515
|
+
const badge = clone.querySelector('span[style*="rgba(76"]');
|
|
8516
|
+
if (badge) {
|
|
8517
|
+
const letter = (badge.textContent || "").trim().toLowerCase();
|
|
8518
|
+
badge.remove();
|
|
8519
|
+
const explanation = (clone.textContent || "").trim();
|
|
8520
|
+
currentQA.answer = `${letter}) ${explanation}`;
|
|
8521
|
+
} else {
|
|
8522
|
+
currentQA.answer = (clone.textContent || "").trim();
|
|
8523
|
+
}
|
|
8350
8524
|
} else if (el.children.length > 1) {
|
|
8525
|
+
if (!currentQA) currentQA = { question: "", answer: "", sections: [] };
|
|
8351
8526
|
for (const card of Array.from(el.children)) {
|
|
8352
8527
|
const cardH3 = card.querySelector("h3");
|
|
8353
8528
|
if (!cardH3) continue;
|
|
@@ -8356,10 +8531,14 @@ function parseQuestionsCardsHtml(html) {
|
|
|
8356
8531
|
const key = match ? match.key : "rubric";
|
|
8357
8532
|
const clone = card.cloneNode(true);
|
|
8358
8533
|
clone.querySelector("h3")?.remove();
|
|
8359
|
-
|
|
8534
|
+
currentQA.sections.push({ key, content: (clone.textContent || "").trim() });
|
|
8360
8535
|
}
|
|
8361
8536
|
}
|
|
8362
8537
|
}
|
|
8538
|
+
if (currentQA) result.qaPairs.push(currentQA);
|
|
8539
|
+
if (result.qaPairs.length === 0) {
|
|
8540
|
+
result.qaPairs.push({ question: "", answer: "", sections: [] });
|
|
8541
|
+
}
|
|
8363
8542
|
return result;
|
|
8364
8543
|
}
|
|
8365
8544
|
|
|
@@ -8397,7 +8576,7 @@ function NotesComponent({
|
|
|
8397
8576
|
setIsEditing(false);
|
|
8398
8577
|
}, []);
|
|
8399
8578
|
return /* @__PURE__ */ jsx23(BlockWithAlignableContents4, { className, format, nodeKey, children: /* @__PURE__ */ jsxs13("div", { style: { position: "relative" }, children: [
|
|
8400
|
-
isEditable &&
|
|
8579
|
+
isEditable && /* @__PURE__ */ jsx23(
|
|
8401
8580
|
"button",
|
|
8402
8581
|
{
|
|
8403
8582
|
type: "button",
|
|
@@ -8422,37 +8601,13 @@ function NotesComponent({
|
|
|
8422
8601
|
children: "Edit Notes"
|
|
8423
8602
|
}
|
|
8424
8603
|
),
|
|
8425
|
-
|
|
8426
|
-
|
|
8427
|
-
/* @__PURE__ */ jsx23("span", { style: { fontSize: 13, fontWeight: 600, color: CARD_STYLES.notes.headingColor }, children: "Edit Notes" }),
|
|
8428
|
-
/* @__PURE__ */ jsxs13("div", { style: { display: "flex", gap: 4 }, children: [
|
|
8429
|
-
/* @__PURE__ */ jsx23(
|
|
8430
|
-
"button",
|
|
8431
|
-
{
|
|
8432
|
-
type: "button",
|
|
8433
|
-
onClick: cancelEdit,
|
|
8434
|
-
style: { padding: "2px 10px", fontSize: 12, border: "1px solid #ccc", borderRadius: 4, background: "#fff", cursor: "pointer" },
|
|
8435
|
-
children: "Cancel"
|
|
8436
|
-
}
|
|
8437
|
-
),
|
|
8438
|
-
/* @__PURE__ */ jsx23(
|
|
8439
|
-
"button",
|
|
8440
|
-
{
|
|
8441
|
-
type: "button",
|
|
8442
|
-
onClick: saveChanges,
|
|
8443
|
-
disabled: !preview,
|
|
8444
|
-
style: { padding: "2px 10px", fontSize: 12, border: "none", borderRadius: 4, background: "#2563eb", color: "#fff", cursor: "pointer", opacity: preview ? 1 : 0.5 },
|
|
8445
|
-
children: "Save"
|
|
8446
|
-
}
|
|
8447
|
-
)
|
|
8448
|
-
] })
|
|
8449
|
-
] }),
|
|
8604
|
+
/* @__PURE__ */ jsx23("div", { dangerouslySetInnerHTML: { __html: html } }),
|
|
8605
|
+
isEditing && /* @__PURE__ */ jsx23(Modal, { onClose: cancelEdit, title: "Edit Notes", children: /* @__PURE__ */ jsxs13("div", { style: { minWidth: 500 }, children: [
|
|
8450
8606
|
/* @__PURE__ */ jsx23(
|
|
8451
8607
|
"textarea",
|
|
8452
8608
|
{
|
|
8453
8609
|
value: editText,
|
|
8454
8610
|
onChange: (e) => setEditText(e.target.value),
|
|
8455
|
-
onMouseDown: (e) => e.stopPropagation(),
|
|
8456
8611
|
style: {
|
|
8457
8612
|
width: "100%",
|
|
8458
8613
|
minHeight: 150,
|
|
@@ -8465,11 +8620,15 @@ function NotesComponent({
|
|
|
8465
8620
|
}
|
|
8466
8621
|
}
|
|
8467
8622
|
),
|
|
8468
|
-
preview && /* @__PURE__ */ jsxs13("div", { style: { marginTop: 8, padding: 8, border: "1px solid #e5e7eb", borderRadius: 4, background: "#fff" }, children: [
|
|
8623
|
+
preview && /* @__PURE__ */ jsxs13("div", { style: { marginTop: 8, padding: 8, border: "1px solid #e5e7eb", borderRadius: 4, background: "#fff", maxHeight: 200, overflow: "auto" }, children: [
|
|
8469
8624
|
/* @__PURE__ */ jsx23("span", { style: { fontSize: 11, color: "#888", display: "block", marginBottom: 4 }, children: "Preview:" }),
|
|
8470
8625
|
/* @__PURE__ */ jsx23("div", { dangerouslySetInnerHTML: { __html: preview } })
|
|
8626
|
+
] }),
|
|
8627
|
+
/* @__PURE__ */ jsxs13("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 12 }, children: [
|
|
8628
|
+
/* @__PURE__ */ jsx23("button", { type: "button", onClick: cancelEdit, style: { padding: "6px 16px", fontSize: 13, border: "1px solid #ccc", borderRadius: 4, background: "#fff", cursor: "pointer" }, children: "Cancel" }),
|
|
8629
|
+
/* @__PURE__ */ jsx23("button", { type: "button", onClick: saveChanges, disabled: !preview, style: { padding: "6px 16px", fontSize: 13, border: "none", borderRadius: 4, background: "#2563eb", color: "#fff", cursor: "pointer", opacity: preview ? 1 : 0.5 }, children: "Save" })
|
|
8471
8630
|
] })
|
|
8472
|
-
] })
|
|
8631
|
+
] }) })
|
|
8473
8632
|
] }) });
|
|
8474
8633
|
}
|
|
8475
8634
|
var DATA_ATTR = "data-lexical-notes";
|
|
@@ -8569,27 +8728,95 @@ function NotesPlugin() {
|
|
|
8569
8728
|
}, [editor]);
|
|
8570
8729
|
return null;
|
|
8571
8730
|
}
|
|
8731
|
+
function convertRichHtmlToNotes(htmlStr, baasixClient, folder) {
|
|
8732
|
+
return new Promise(async (resolve) => {
|
|
8733
|
+
const parser = new DOMParser();
|
|
8734
|
+
const doc = parser.parseFromString(htmlStr, "text/html");
|
|
8735
|
+
if (baasixClient) {
|
|
8736
|
+
const imgs = doc.querySelectorAll("img");
|
|
8737
|
+
for (let i = 0; i < imgs.length; i++) {
|
|
8738
|
+
const img2 = imgs[i];
|
|
8739
|
+
const src = img2.getAttribute("src") || "";
|
|
8740
|
+
if (src.startsWith("data:")) {
|
|
8741
|
+
try {
|
|
8742
|
+
const resp = await fetch(src);
|
|
8743
|
+
const blob = await resp.blob();
|
|
8744
|
+
const ext = blob.type.split("/")[1] || "png";
|
|
8745
|
+
const file = new File([blob], `note-image-${i}.${ext}`, { type: blob.type });
|
|
8746
|
+
const uploadedUrl = await uploadImageToBaasix(baasixClient, file, folder);
|
|
8747
|
+
img2.setAttribute("src", uploadedUrl);
|
|
8748
|
+
} catch {
|
|
8749
|
+
}
|
|
8750
|
+
}
|
|
8751
|
+
}
|
|
8752
|
+
}
|
|
8753
|
+
let html = `<div style="font-family: sans-serif; line-height: 1.6; color: inherit;">`;
|
|
8754
|
+
const children = Array.from(doc.body.childNodes);
|
|
8755
|
+
for (const child of children) {
|
|
8756
|
+
html += processNode(child);
|
|
8757
|
+
}
|
|
8758
|
+
html += "</div>";
|
|
8759
|
+
resolve(html.replace(/>\s+</g, "><"));
|
|
8760
|
+
});
|
|
8761
|
+
}
|
|
8572
8762
|
function InsertNotesDialog({
|
|
8573
8763
|
activeEditor,
|
|
8574
8764
|
onClose
|
|
8575
8765
|
}) {
|
|
8576
8766
|
const [input, setInput] = useState18("");
|
|
8577
|
-
const
|
|
8767
|
+
const [richHtml, setRichHtml] = useState18("");
|
|
8768
|
+
const [isUploading, setIsUploading] = useState18(false);
|
|
8769
|
+
const pasteAreaRef = useRef9(null);
|
|
8770
|
+
let editorConfig = null;
|
|
8771
|
+
try {
|
|
8772
|
+
editorConfig = useEditorConfig();
|
|
8773
|
+
} catch {
|
|
8774
|
+
}
|
|
8775
|
+
const handleRichPaste = useCallback12(async (e) => {
|
|
8776
|
+
e.preventDefault();
|
|
8777
|
+
const clipboardData = e.clipboardData;
|
|
8778
|
+
const htmlData = clipboardData.getData("text/html");
|
|
8779
|
+
const textData = clipboardData.getData("text/plain");
|
|
8780
|
+
if (htmlData) {
|
|
8781
|
+
setIsUploading(true);
|
|
8782
|
+
try {
|
|
8783
|
+
const processed = await convertRichHtmlToNotes(
|
|
8784
|
+
htmlData,
|
|
8785
|
+
editorConfig?.baasixClient,
|
|
8786
|
+
editorConfig?.folder
|
|
8787
|
+
);
|
|
8788
|
+
setRichHtml(processed);
|
|
8789
|
+
setInput("");
|
|
8790
|
+
} finally {
|
|
8791
|
+
setIsUploading(false);
|
|
8792
|
+
}
|
|
8793
|
+
} else if (textData) {
|
|
8794
|
+
setInput((prev) => prev ? prev + "\n" + textData : textData);
|
|
8795
|
+
}
|
|
8796
|
+
if (pasteAreaRef.current) {
|
|
8797
|
+
pasteAreaRef.current.innerHTML = '<span style="color: #9ca3af; pointer-events: none; user-select: none;">Paste from Word/Docs here (preserves formatting)</span>';
|
|
8798
|
+
}
|
|
8799
|
+
}, [editorConfig]);
|
|
8800
|
+
const finalHtml = useMemo8(() => {
|
|
8801
|
+
if (richHtml) return richHtml;
|
|
8578
8802
|
if (!input.trim()) return "";
|
|
8579
8803
|
return convertNotes(input);
|
|
8580
|
-
}, [input]);
|
|
8804
|
+
}, [input, richHtml]);
|
|
8581
8805
|
const handleInsert = useCallback12(() => {
|
|
8582
|
-
if (!
|
|
8583
|
-
activeEditor.dispatchCommand(INSERT_NOTES_COMMAND,
|
|
8806
|
+
if (!finalHtml) return;
|
|
8807
|
+
activeEditor.dispatchCommand(INSERT_NOTES_COMMAND, finalHtml);
|
|
8584
8808
|
onClose();
|
|
8585
|
-
}, [activeEditor,
|
|
8809
|
+
}, [activeEditor, finalHtml, onClose]);
|
|
8586
8810
|
return /* @__PURE__ */ jsxs14("div", { style: { minWidth: 500 }, children: [
|
|
8587
8811
|
/* @__PURE__ */ jsx24(
|
|
8588
8812
|
"textarea",
|
|
8589
8813
|
{
|
|
8590
8814
|
value: input,
|
|
8591
|
-
onChange: (e) =>
|
|
8592
|
-
|
|
8815
|
+
onChange: (e) => {
|
|
8816
|
+
setInput(e.target.value);
|
|
8817
|
+
setRichHtml("");
|
|
8818
|
+
},
|
|
8819
|
+
placeholder: "Paste or type notes here (plain text)...\nExample:\nSuperficial Fascia\nThe superficial fascia is a layer of loose...\n\nFunctions\n- Passageway for vessels\n- Insulation",
|
|
8593
8820
|
style: {
|
|
8594
8821
|
width: "100%",
|
|
8595
8822
|
minHeight: 120,
|
|
@@ -8603,9 +8830,33 @@ function InsertNotesDialog({
|
|
|
8603
8830
|
}
|
|
8604
8831
|
}
|
|
8605
8832
|
),
|
|
8606
|
-
|
|
8833
|
+
/* @__PURE__ */ jsx24(
|
|
8834
|
+
"div",
|
|
8835
|
+
{
|
|
8836
|
+
ref: pasteAreaRef,
|
|
8837
|
+
contentEditable: true,
|
|
8838
|
+
onPaste: handleRichPaste,
|
|
8839
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
8840
|
+
style: {
|
|
8841
|
+
width: "100%",
|
|
8842
|
+
minHeight: 40,
|
|
8843
|
+
padding: 8,
|
|
8844
|
+
border: "2px dashed #93c5fd",
|
|
8845
|
+
borderRadius: 4,
|
|
8846
|
+
fontSize: 12,
|
|
8847
|
+
color: "#6b7280",
|
|
8848
|
+
marginBottom: 8,
|
|
8849
|
+
outline: "none",
|
|
8850
|
+
background: "#f0f7ff"
|
|
8851
|
+
},
|
|
8852
|
+
suppressContentEditableWarning: true,
|
|
8853
|
+
children: /* @__PURE__ */ jsx24("span", { style: { color: "#9ca3af", pointerEvents: "none", userSelect: "none" }, children: isUploading ? "Processing content..." : "Paste from Word/Docs here (preserves formatting)" })
|
|
8854
|
+
}
|
|
8855
|
+
),
|
|
8856
|
+
richHtml && /* @__PURE__ */ jsx24("div", { style: { marginBottom: 8, fontSize: 11, color: "#16a34a" }, children: "Rich content captured (formatting preserved)" }),
|
|
8857
|
+
finalHtml && /* @__PURE__ */ jsxs14("div", { style: { marginBottom: 8, padding: 8, border: "1px solid #e5e7eb", borderRadius: 4, background: "#fafafa", maxHeight: 200, overflow: "auto" }, children: [
|
|
8607
8858
|
/* @__PURE__ */ jsx24("span", { style: { fontSize: 11, color: "#888", display: "block", marginBottom: 4 }, children: "Preview:" }),
|
|
8608
|
-
/* @__PURE__ */ jsx24("div", { dangerouslySetInnerHTML: { __html:
|
|
8859
|
+
/* @__PURE__ */ jsx24("div", { dangerouslySetInnerHTML: { __html: finalHtml } })
|
|
8609
8860
|
] }),
|
|
8610
8861
|
/* @__PURE__ */ jsxs14("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8 }, children: [
|
|
8611
8862
|
/* @__PURE__ */ jsx24(
|
|
@@ -8622,9 +8873,9 @@ function InsertNotesDialog({
|
|
|
8622
8873
|
{
|
|
8623
8874
|
type: "button",
|
|
8624
8875
|
onClick: handleInsert,
|
|
8625
|
-
disabled: !
|
|
8626
|
-
style: { padding: "6px 16px", fontSize: 13, border: "none", borderRadius: 4, background: "#2563eb", color: "#fff", cursor: "pointer", opacity:
|
|
8627
|
-
children: "Insert"
|
|
8876
|
+
disabled: !finalHtml || isUploading,
|
|
8877
|
+
style: { padding: "6px 16px", fontSize: 13, border: "none", borderRadius: 4, background: "#2563eb", color: "#fff", cursor: "pointer", opacity: finalHtml && !isUploading ? 1 : 0.5 },
|
|
8878
|
+
children: isUploading ? "Processing..." : "Insert"
|
|
8628
8879
|
}
|
|
8629
8880
|
)
|
|
8630
8881
|
] })
|
|
@@ -8743,7 +8994,7 @@ function RevisionComponent({
|
|
|
8743
8994
|
setItems((prev) => prev.filter((_, i) => i !== index));
|
|
8744
8995
|
}, []);
|
|
8745
8996
|
return /* @__PURE__ */ jsx26(BlockWithAlignableContents5, { className, format, nodeKey, children: /* @__PURE__ */ jsxs16("div", { style: { position: "relative" }, children: [
|
|
8746
|
-
isEditable &&
|
|
8997
|
+
isEditable && /* @__PURE__ */ jsx26(
|
|
8747
8998
|
"button",
|
|
8748
8999
|
{
|
|
8749
9000
|
type: "button",
|
|
@@ -8768,31 +9019,8 @@ function RevisionComponent({
|
|
|
8768
9019
|
children: "Edit Revision"
|
|
8769
9020
|
}
|
|
8770
9021
|
),
|
|
8771
|
-
|
|
8772
|
-
|
|
8773
|
-
/* @__PURE__ */ jsx26("span", { style: { fontSize: 13, fontWeight: 600, color: "#c2703a" }, children: "Edit Revision Points" }),
|
|
8774
|
-
/* @__PURE__ */ jsxs16("div", { style: { display: "flex", gap: 4 }, children: [
|
|
8775
|
-
/* @__PURE__ */ jsx26(
|
|
8776
|
-
"button",
|
|
8777
|
-
{
|
|
8778
|
-
type: "button",
|
|
8779
|
-
onClick: cancelEdit,
|
|
8780
|
-
style: { padding: "2px 10px", fontSize: 12, border: "1px solid #ccc", borderRadius: 4, background: "#fff", cursor: "pointer" },
|
|
8781
|
-
children: "Cancel"
|
|
8782
|
-
}
|
|
8783
|
-
),
|
|
8784
|
-
/* @__PURE__ */ jsx26(
|
|
8785
|
-
"button",
|
|
8786
|
-
{
|
|
8787
|
-
type: "button",
|
|
8788
|
-
onClick: saveChanges,
|
|
8789
|
-
disabled: !preview,
|
|
8790
|
-
style: { padding: "2px 10px", fontSize: 12, border: "none", borderRadius: 4, background: "#2563eb", color: "#fff", cursor: "pointer", opacity: preview ? 1 : 0.5 },
|
|
8791
|
-
children: "Save"
|
|
8792
|
-
}
|
|
8793
|
-
)
|
|
8794
|
-
] })
|
|
8795
|
-
] }),
|
|
9022
|
+
/* @__PURE__ */ jsx26("div", { dangerouslySetInnerHTML: { __html: html } }),
|
|
9023
|
+
isEditing && /* @__PURE__ */ jsx26(Modal, { onClose: cancelEdit, title: "Edit Revision Points", children: /* @__PURE__ */ jsxs16("div", { style: { minWidth: 500 }, children: [
|
|
8796
9024
|
items.map((item, index) => /* @__PURE__ */ jsxs16("div", { style: { display: "flex", gap: 4, marginBottom: 4, alignItems: "center" }, children: [
|
|
8797
9025
|
/* @__PURE__ */ jsx26(
|
|
8798
9026
|
"input",
|
|
@@ -8801,7 +9029,6 @@ function RevisionComponent({
|
|
|
8801
9029
|
placeholder: "Revision point",
|
|
8802
9030
|
value: item,
|
|
8803
9031
|
onChange: (e) => updateItem(index, e.target.value),
|
|
8804
|
-
onMouseDown: (e) => e.stopPropagation(),
|
|
8805
9032
|
style: { flex: 1, padding: "4px 6px", fontSize: 12, border: "1px solid #ddd", borderRadius: 4 }
|
|
8806
9033
|
}
|
|
8807
9034
|
),
|
|
@@ -8824,11 +9051,15 @@ function RevisionComponent({
|
|
|
8824
9051
|
children: "+ Add Point"
|
|
8825
9052
|
}
|
|
8826
9053
|
),
|
|
8827
|
-
preview && /* @__PURE__ */ jsxs16("div", { style: { marginTop: 8, padding: 8, border: "1px solid #e5e7eb", borderRadius: 4, background: "#fff" }, children: [
|
|
9054
|
+
preview && /* @__PURE__ */ jsxs16("div", { style: { marginTop: 8, padding: 8, border: "1px solid #e5e7eb", borderRadius: 4, background: "#fff", maxHeight: 200, overflow: "auto" }, children: [
|
|
8828
9055
|
/* @__PURE__ */ jsx26("span", { style: { fontSize: 11, color: "#888", display: "block", marginBottom: 4 }, children: "Preview:" }),
|
|
8829
9056
|
/* @__PURE__ */ jsx26("div", { dangerouslySetInnerHTML: { __html: preview } })
|
|
9057
|
+
] }),
|
|
9058
|
+
/* @__PURE__ */ jsxs16("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 12 }, children: [
|
|
9059
|
+
/* @__PURE__ */ jsx26("button", { type: "button", onClick: cancelEdit, style: { padding: "6px 16px", fontSize: 13, border: "1px solid #ccc", borderRadius: 4, background: "#fff", cursor: "pointer" }, children: "Cancel" }),
|
|
9060
|
+
/* @__PURE__ */ jsx26("button", { type: "button", onClick: saveChanges, disabled: !preview, style: { padding: "6px 16px", fontSize: 13, border: "none", borderRadius: 4, background: "#2563eb", color: "#fff", cursor: "pointer", opacity: preview ? 1 : 0.5 }, children: "Save" })
|
|
8830
9061
|
] })
|
|
8831
|
-
] })
|
|
9062
|
+
] }) })
|
|
8832
9063
|
] }) });
|
|
8833
9064
|
}
|
|
8834
9065
|
var DATA_ATTR2 = "data-lexical-revision";
|
|
@@ -9047,57 +9278,36 @@ function TerminologyComponent({
|
|
|
9047
9278
|
const removeItem = useCallback15((index) => {
|
|
9048
9279
|
setItems((prev) => prev.filter((_, i) => i !== index));
|
|
9049
9280
|
}, []);
|
|
9050
|
-
return /* @__PURE__ */
|
|
9051
|
-
|
|
9052
|
-
|
|
9053
|
-
|
|
9054
|
-
|
|
9055
|
-
|
|
9056
|
-
|
|
9057
|
-
|
|
9058
|
-
|
|
9059
|
-
|
|
9060
|
-
|
|
9061
|
-
|
|
9062
|
-
|
|
9063
|
-
|
|
9064
|
-
|
|
9065
|
-
|
|
9066
|
-
|
|
9067
|
-
|
|
9068
|
-
|
|
9069
|
-
|
|
9070
|
-
|
|
9071
|
-
|
|
9072
|
-
|
|
9073
|
-
|
|
9074
|
-
|
|
9075
|
-
|
|
9076
|
-
|
|
9077
|
-
/* @__PURE__ */
|
|
9078
|
-
|
|
9079
|
-
|
|
9080
|
-
/* @__PURE__ */ jsx28(
|
|
9081
|
-
"button",
|
|
9082
|
-
{
|
|
9083
|
-
type: "button",
|
|
9084
|
-
onClick: cancelEdit,
|
|
9085
|
-
style: { padding: "2px 10px", fontSize: 12, border: "1px solid #ccc", borderRadius: 4, background: "#fff", cursor: "pointer" },
|
|
9086
|
-
children: "Cancel"
|
|
9087
|
-
}
|
|
9088
|
-
),
|
|
9089
|
-
/* @__PURE__ */ jsx28(
|
|
9090
|
-
"button",
|
|
9091
|
-
{
|
|
9092
|
-
type: "button",
|
|
9093
|
-
onClick: saveChanges,
|
|
9094
|
-
disabled: !preview,
|
|
9095
|
-
style: { padding: "2px 10px", fontSize: 12, border: "none", borderRadius: 4, background: "#2563eb", color: "#fff", cursor: "pointer", opacity: preview ? 1 : 0.5 },
|
|
9096
|
-
children: "Save"
|
|
9097
|
-
}
|
|
9098
|
-
)
|
|
9099
|
-
] })
|
|
9100
|
-
] }),
|
|
9281
|
+
return /* @__PURE__ */ jsxs18(BlockWithAlignableContents6, { className, format, nodeKey, children: [
|
|
9282
|
+
/* @__PURE__ */ jsxs18("div", { style: { position: "relative" }, children: [
|
|
9283
|
+
isEditable && /* @__PURE__ */ jsx28(
|
|
9284
|
+
"button",
|
|
9285
|
+
{
|
|
9286
|
+
type: "button",
|
|
9287
|
+
onClick: openEditor,
|
|
9288
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
9289
|
+
style: {
|
|
9290
|
+
position: "absolute",
|
|
9291
|
+
top: 4,
|
|
9292
|
+
right: 4,
|
|
9293
|
+
zIndex: 10,
|
|
9294
|
+
background: CARD_STYLES.terminology.keyColor,
|
|
9295
|
+
color: "#fff",
|
|
9296
|
+
border: "none",
|
|
9297
|
+
borderRadius: 4,
|
|
9298
|
+
padding: "2px 8px",
|
|
9299
|
+
fontSize: 12,
|
|
9300
|
+
cursor: "pointer",
|
|
9301
|
+
opacity: 0,
|
|
9302
|
+
transition: "opacity 0.15s"
|
|
9303
|
+
},
|
|
9304
|
+
className: "html-block-edit-btn",
|
|
9305
|
+
children: "Edit Terminology"
|
|
9306
|
+
}
|
|
9307
|
+
),
|
|
9308
|
+
/* @__PURE__ */ jsx28("div", { dangerouslySetInnerHTML: { __html: html } })
|
|
9309
|
+
] }),
|
|
9310
|
+
isEditing && /* @__PURE__ */ jsx28(Modal, { onClose: cancelEdit, title: "Edit Terminology", children: /* @__PURE__ */ jsxs18("div", { style: { minWidth: 500 }, children: [
|
|
9101
9311
|
items.map((item, index) => /* @__PURE__ */ jsxs18("div", { style: { display: "flex", gap: 4, marginBottom: 4, alignItems: "center" }, children: [
|
|
9102
9312
|
/* @__PURE__ */ jsx28(
|
|
9103
9313
|
"input",
|
|
@@ -9106,7 +9316,6 @@ function TerminologyComponent({
|
|
|
9106
9316
|
placeholder: "Term",
|
|
9107
9317
|
value: item.term,
|
|
9108
9318
|
onChange: (e) => updateItem(index, "term", e.target.value),
|
|
9109
|
-
onMouseDown: (e) => e.stopPropagation(),
|
|
9110
9319
|
style: { width: "30%", padding: "4px 6px", fontSize: 12, border: "1px solid #ddd", borderRadius: 4 }
|
|
9111
9320
|
}
|
|
9112
9321
|
),
|
|
@@ -9117,7 +9326,6 @@ function TerminologyComponent({
|
|
|
9117
9326
|
placeholder: "Definition",
|
|
9118
9327
|
value: item.definition,
|
|
9119
9328
|
onChange: (e) => updateItem(index, "definition", e.target.value),
|
|
9120
|
-
onMouseDown: (e) => e.stopPropagation(),
|
|
9121
9329
|
style: { flex: 1, padding: "4px 6px", fontSize: 12, border: "1px solid #ddd", borderRadius: 4 }
|
|
9122
9330
|
}
|
|
9123
9331
|
),
|
|
@@ -9136,16 +9344,37 @@ function TerminologyComponent({
|
|
|
9136
9344
|
{
|
|
9137
9345
|
type: "button",
|
|
9138
9346
|
onClick: addItem,
|
|
9139
|
-
style: { padding: "2px 10px", fontSize: 12, border: "1px solid #ddd", borderRadius: 4, background: "#fff", cursor: "pointer", marginTop: 4 },
|
|
9347
|
+
style: { padding: "2px 10px", fontSize: 12, border: "1px solid #ddd", borderRadius: 4, background: "#fff", cursor: "pointer", marginTop: 4, marginBottom: 8 },
|
|
9140
9348
|
children: "+ Add Term"
|
|
9141
9349
|
}
|
|
9142
9350
|
),
|
|
9143
|
-
preview && /* @__PURE__ */ jsxs18("div", { style: {
|
|
9351
|
+
preview && /* @__PURE__ */ jsxs18("div", { style: { marginBottom: 8, padding: 8, border: "1px solid #e5e7eb", borderRadius: 4, background: "#fff", maxHeight: 200, overflow: "auto" }, children: [
|
|
9144
9352
|
/* @__PURE__ */ jsx28("span", { style: { fontSize: 11, color: "#888", display: "block", marginBottom: 4 }, children: "Preview:" }),
|
|
9145
9353
|
/* @__PURE__ */ jsx28("div", { dangerouslySetInnerHTML: { __html: preview } })
|
|
9354
|
+
] }),
|
|
9355
|
+
/* @__PURE__ */ jsxs18("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8 }, children: [
|
|
9356
|
+
/* @__PURE__ */ jsx28(
|
|
9357
|
+
"button",
|
|
9358
|
+
{
|
|
9359
|
+
type: "button",
|
|
9360
|
+
onClick: cancelEdit,
|
|
9361
|
+
style: { padding: "6px 16px", fontSize: 13, border: "1px solid #ccc", borderRadius: 4, background: "#fff", cursor: "pointer" },
|
|
9362
|
+
children: "Cancel"
|
|
9363
|
+
}
|
|
9364
|
+
),
|
|
9365
|
+
/* @__PURE__ */ jsx28(
|
|
9366
|
+
"button",
|
|
9367
|
+
{
|
|
9368
|
+
type: "button",
|
|
9369
|
+
onClick: saveChanges,
|
|
9370
|
+
disabled: !preview,
|
|
9371
|
+
style: { padding: "6px 16px", fontSize: 13, border: "none", borderRadius: 4, background: "#2563eb", color: "#fff", cursor: "pointer", opacity: preview ? 1 : 0.5 },
|
|
9372
|
+
children: "Save"
|
|
9373
|
+
}
|
|
9374
|
+
)
|
|
9146
9375
|
] })
|
|
9147
|
-
] })
|
|
9148
|
-
] })
|
|
9376
|
+
] }) })
|
|
9377
|
+
] });
|
|
9149
9378
|
}
|
|
9150
9379
|
var DATA_ATTR3 = "data-lexical-terminology";
|
|
9151
9380
|
var TerminologyNode = class _TerminologyNode extends DecoratorBlockNode6 {
|
|
@@ -9310,7 +9539,7 @@ function InsertTerminologyDialog({
|
|
|
9310
9539
|
import { useLexicalComposerContext as useLexicalComposerContext28 } from "@lexical/react/LexicalComposerContext";
|
|
9311
9540
|
import { $insertNodeToNearestRoot as $insertNodeToNearestRoot10 } from "@lexical/utils";
|
|
9312
9541
|
import { COMMAND_PRIORITY_EDITOR as COMMAND_PRIORITY_EDITOR17, createCommand as createCommand17 } from "lexical";
|
|
9313
|
-
import { useCallback as
|
|
9542
|
+
import { useCallback as useCallback19, useEffect as useEffect27, useMemo as useMemo14, useState as useState26 } from "react";
|
|
9314
9543
|
|
|
9315
9544
|
// src/nodes/TextCardsNode.tsx
|
|
9316
9545
|
import { $getNodeByKey as $getNodeByKey7 } from "lexical";
|
|
@@ -9419,7 +9648,7 @@ function TextCardsComponent({
|
|
|
9419
9648
|
}, []);
|
|
9420
9649
|
const styles = CARD_STYLES.textCards;
|
|
9421
9650
|
return /* @__PURE__ */ jsx30(BlockWithAlignableContents7, { className, format, nodeKey, children: /* @__PURE__ */ jsxs20("div", { style: { position: "relative" }, children: [
|
|
9422
|
-
isEditable &&
|
|
9651
|
+
isEditable && /* @__PURE__ */ jsx30(
|
|
9423
9652
|
"button",
|
|
9424
9653
|
{
|
|
9425
9654
|
type: "button",
|
|
@@ -9444,31 +9673,8 @@ function TextCardsComponent({
|
|
|
9444
9673
|
children: "Edit Text Cards"
|
|
9445
9674
|
}
|
|
9446
9675
|
),
|
|
9447
|
-
|
|
9448
|
-
|
|
9449
|
-
/* @__PURE__ */ jsx30("span", { style: { fontSize: 13, fontWeight: 600, color: "rgba(76, 175, 80, 0.8)" }, children: "Edit Text Cards" }),
|
|
9450
|
-
/* @__PURE__ */ jsxs20("div", { style: { display: "flex", gap: 4 }, children: [
|
|
9451
|
-
/* @__PURE__ */ jsx30(
|
|
9452
|
-
"button",
|
|
9453
|
-
{
|
|
9454
|
-
type: "button",
|
|
9455
|
-
onClick: cancelEdit,
|
|
9456
|
-
style: { padding: "2px 10px", fontSize: 12, border: "1px solid #ccc", borderRadius: 4, background: "#fff", cursor: "pointer" },
|
|
9457
|
-
children: "Cancel"
|
|
9458
|
-
}
|
|
9459
|
-
),
|
|
9460
|
-
/* @__PURE__ */ jsx30(
|
|
9461
|
-
"button",
|
|
9462
|
-
{
|
|
9463
|
-
type: "button",
|
|
9464
|
-
onClick: saveChanges,
|
|
9465
|
-
disabled: !preview,
|
|
9466
|
-
style: { padding: "2px 10px", fontSize: 12, border: "none", borderRadius: 4, background: "#2563eb", color: "#fff", cursor: "pointer", opacity: preview ? 1 : 0.5 },
|
|
9467
|
-
children: "Save"
|
|
9468
|
-
}
|
|
9469
|
-
)
|
|
9470
|
-
] })
|
|
9471
|
-
] }),
|
|
9676
|
+
/* @__PURE__ */ jsx30("div", { dangerouslySetInnerHTML: { __html: html } }),
|
|
9677
|
+
isEditing && /* @__PURE__ */ jsx30(Modal, { onClose: cancelEdit, title: "Edit Text Cards", children: /* @__PURE__ */ jsxs20("div", { style: { minWidth: 500 }, children: [
|
|
9472
9678
|
concepts.map((concept, cIdx) => /* @__PURE__ */ jsxs20("div", { style: { border: "1px solid #e5e7eb", borderRadius: 6, padding: 8, marginBottom: 8, background: "#fff" }, children: [
|
|
9473
9679
|
/* @__PURE__ */ jsxs20("div", { style: { display: "flex", gap: 4, marginBottom: 6, alignItems: "center" }, children: [
|
|
9474
9680
|
/* @__PURE__ */ jsxs20("span", { style: { fontSize: 12, fontWeight: 600, color: "#4caf50", minWidth: 80 }, children: [
|
|
@@ -9483,7 +9689,6 @@ function TextCardsComponent({
|
|
|
9483
9689
|
placeholder: "Concept title",
|
|
9484
9690
|
value: concept.conceptTitle,
|
|
9485
9691
|
onChange: (e) => updateConceptTitle(cIdx, e.target.value),
|
|
9486
|
-
onMouseDown: (e) => e.stopPropagation(),
|
|
9487
9692
|
style: { flex: 1, padding: "4px 6px", fontSize: 12, border: "1px solid #ddd", borderRadius: 4 }
|
|
9488
9693
|
}
|
|
9489
9694
|
),
|
|
@@ -9508,7 +9713,6 @@ function TextCardsComponent({
|
|
|
9508
9713
|
placeholder: `${label} content...`,
|
|
9509
9714
|
value: section.content,
|
|
9510
9715
|
onChange: (e) => updateSection(cIdx, sIdx, e.target.value),
|
|
9511
|
-
onMouseDown: (e) => e.stopPropagation(),
|
|
9512
9716
|
style: { width: "100%", padding: "4px 6px", fontSize: 12, border: "1px solid #ddd", borderRadius: 4, minHeight: 40, resize: "vertical" }
|
|
9513
9717
|
}
|
|
9514
9718
|
)
|
|
@@ -9524,11 +9728,15 @@ function TextCardsComponent({
|
|
|
9524
9728
|
children: "+ Add Concept"
|
|
9525
9729
|
}
|
|
9526
9730
|
),
|
|
9527
|
-
preview && /* @__PURE__ */ jsxs20("div", { style: { marginTop: 8, padding: 8, border: "1px solid #e5e7eb", borderRadius: 4, background: "#fff" }, children: [
|
|
9731
|
+
preview && /* @__PURE__ */ jsxs20("div", { style: { marginTop: 8, padding: 8, border: "1px solid #e5e7eb", borderRadius: 4, background: "#fff", maxHeight: 200, overflow: "auto" }, children: [
|
|
9528
9732
|
/* @__PURE__ */ jsx30("span", { style: { fontSize: 11, color: "#888", display: "block", marginBottom: 4 }, children: "Preview:" }),
|
|
9529
9733
|
/* @__PURE__ */ jsx30("div", { dangerouslySetInnerHTML: { __html: preview } })
|
|
9734
|
+
] }),
|
|
9735
|
+
/* @__PURE__ */ jsxs20("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 12 }, children: [
|
|
9736
|
+
/* @__PURE__ */ jsx30("button", { type: "button", onClick: cancelEdit, style: { padding: "6px 16px", fontSize: 13, border: "1px solid #ccc", borderRadius: 4, background: "#fff", cursor: "pointer" }, children: "Cancel" }),
|
|
9737
|
+
/* @__PURE__ */ jsx30("button", { type: "button", onClick: saveChanges, disabled: !preview, style: { padding: "6px 16px", fontSize: 13, border: "none", borderRadius: 4, background: "#2563eb", color: "#fff", cursor: "pointer", opacity: preview ? 1 : 0.5 }, children: "Save" })
|
|
9530
9738
|
] })
|
|
9531
|
-
] })
|
|
9739
|
+
] }) })
|
|
9532
9740
|
] }) });
|
|
9533
9741
|
}
|
|
9534
9742
|
var DATA_ATTR4 = "data-lexical-text-cards";
|
|
@@ -9605,6 +9813,134 @@ function $isTextCardsNode(node) {
|
|
|
9605
9813
|
return node instanceof TextCardsNode;
|
|
9606
9814
|
}
|
|
9607
9815
|
|
|
9816
|
+
// src/utils/useRichPaste.ts
|
|
9817
|
+
import { useCallback as useCallback18, useRef as useRef10, useState as useState25 } from "react";
|
|
9818
|
+
function useRichPaste(onText, baasixClient, folder) {
|
|
9819
|
+
const [images, setImages] = useState25([]);
|
|
9820
|
+
const [isUploading, setIsUploading] = useState25(false);
|
|
9821
|
+
const pasteAreaRef = useRef10(null);
|
|
9822
|
+
const extractImages = useCallback18(
|
|
9823
|
+
async (htmlStr) => {
|
|
9824
|
+
const parser = new DOMParser();
|
|
9825
|
+
const doc = parser.parseFromString(htmlStr, "text/html");
|
|
9826
|
+
const imgs = doc.querySelectorAll("img");
|
|
9827
|
+
const newImages = [];
|
|
9828
|
+
for (let i = 0; i < imgs.length; i++) {
|
|
9829
|
+
const img2 = imgs[i];
|
|
9830
|
+
const src = img2.getAttribute("src") || "";
|
|
9831
|
+
const placeholder = `__IMG_${Date.now()}_${i}__`;
|
|
9832
|
+
if (src.startsWith("data:") && baasixClient) {
|
|
9833
|
+
try {
|
|
9834
|
+
const resp = await fetch(src);
|
|
9835
|
+
const blob = await resp.blob();
|
|
9836
|
+
const ext = blob.type.split("/")[1] || "png";
|
|
9837
|
+
const file = new File([blob], `pasted-image-${i}.${ext}`, { type: blob.type });
|
|
9838
|
+
const uploadedUrl = await uploadImageToBaasix(baasixClient, file, folder);
|
|
9839
|
+
newImages.push({ placeholder, src: uploadedUrl });
|
|
9840
|
+
} catch {
|
|
9841
|
+
newImages.push({ placeholder, src });
|
|
9842
|
+
}
|
|
9843
|
+
} else if (src) {
|
|
9844
|
+
newImages.push({ placeholder, src });
|
|
9845
|
+
}
|
|
9846
|
+
}
|
|
9847
|
+
return newImages;
|
|
9848
|
+
},
|
|
9849
|
+
[baasixClient, folder]
|
|
9850
|
+
);
|
|
9851
|
+
const insertPlaceholders = useCallback18(
|
|
9852
|
+
(plainText, htmlStr, imgPlaceholders) => {
|
|
9853
|
+
if (imgPlaceholders.length === 0) return plainText;
|
|
9854
|
+
const parser = new DOMParser();
|
|
9855
|
+
const doc = parser.parseFromString(htmlStr, "text/html");
|
|
9856
|
+
const segments = [];
|
|
9857
|
+
let imgIdx = 0;
|
|
9858
|
+
const blockTags = /* @__PURE__ */ new Set(["P", "DIV", "LI", "TR", "H1", "H2", "H3", "H4", "H5", "H6", "BLOCKQUOTE", "PRE", "TABLE"]);
|
|
9859
|
+
const walkNode = (node) => {
|
|
9860
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
9861
|
+
const t = (node.textContent || "").trim();
|
|
9862
|
+
if (t) segments.push({ type: "text", text: t });
|
|
9863
|
+
return;
|
|
9864
|
+
}
|
|
9865
|
+
if (node.nodeType !== Node.ELEMENT_NODE) return;
|
|
9866
|
+
const el = node;
|
|
9867
|
+
if (el.tagName === "IMG") {
|
|
9868
|
+
segments.push({ type: "img", idx: imgIdx++ });
|
|
9869
|
+
return;
|
|
9870
|
+
}
|
|
9871
|
+
for (const child of Array.from(el.childNodes)) walkNode(child);
|
|
9872
|
+
};
|
|
9873
|
+
walkNode(doc.body);
|
|
9874
|
+
const textCountBeforeImg = [];
|
|
9875
|
+
let textCount = 0;
|
|
9876
|
+
for (const seg of segments) {
|
|
9877
|
+
if (seg.type === "text") {
|
|
9878
|
+
textCount++;
|
|
9879
|
+
} else {
|
|
9880
|
+
textCountBeforeImg.push(textCount);
|
|
9881
|
+
}
|
|
9882
|
+
}
|
|
9883
|
+
const lines = plainText.split("\n");
|
|
9884
|
+
const nonEmptyLineIndices = [];
|
|
9885
|
+
for (let i = 0; i < lines.length; i++) {
|
|
9886
|
+
if (lines[i].trim()) nonEmptyLineIndices.push(i);
|
|
9887
|
+
}
|
|
9888
|
+
for (let i = textCountBeforeImg.length - 1; i >= 0; i--) {
|
|
9889
|
+
const placeholder = imgPlaceholders[i]?.placeholder;
|
|
9890
|
+
if (!placeholder) continue;
|
|
9891
|
+
const tc = textCountBeforeImg[i];
|
|
9892
|
+
const lineIdx = tc > 0 && tc <= nonEmptyLineIndices.length ? nonEmptyLineIndices[tc - 1] : nonEmptyLineIndices.length > 0 ? nonEmptyLineIndices[nonEmptyLineIndices.length - 1] : lines.length - 1;
|
|
9893
|
+
lines.splice(lineIdx + 1, 0, placeholder);
|
|
9894
|
+
for (let j = 0; j < nonEmptyLineIndices.length; j++) {
|
|
9895
|
+
if (nonEmptyLineIndices[j] > lineIdx) nonEmptyLineIndices[j]++;
|
|
9896
|
+
}
|
|
9897
|
+
}
|
|
9898
|
+
return lines.join("\n");
|
|
9899
|
+
},
|
|
9900
|
+
[]
|
|
9901
|
+
);
|
|
9902
|
+
const handlePaste = useCallback18(
|
|
9903
|
+
async (e) => {
|
|
9904
|
+
e.preventDefault();
|
|
9905
|
+
const clipboardData = e.clipboardData;
|
|
9906
|
+
const htmlData = clipboardData.getData("text/html");
|
|
9907
|
+
const textData = clipboardData.getData("text/plain");
|
|
9908
|
+
if (htmlData && htmlData.includes("<img")) {
|
|
9909
|
+
setIsUploading(true);
|
|
9910
|
+
try {
|
|
9911
|
+
const processedImages = await extractImages(htmlData);
|
|
9912
|
+
let text = textData || "";
|
|
9913
|
+
text = insertPlaceholders(text, htmlData, processedImages);
|
|
9914
|
+
onText(text);
|
|
9915
|
+
setImages((prev) => [...prev, ...processedImages]);
|
|
9916
|
+
} finally {
|
|
9917
|
+
setIsUploading(false);
|
|
9918
|
+
}
|
|
9919
|
+
} else {
|
|
9920
|
+
onText(textData || "");
|
|
9921
|
+
}
|
|
9922
|
+
if (pasteAreaRef.current) {
|
|
9923
|
+
pasteAreaRef.current.textContent = "";
|
|
9924
|
+
}
|
|
9925
|
+
},
|
|
9926
|
+
[extractImages, insertPlaceholders, onText]
|
|
9927
|
+
);
|
|
9928
|
+
const replaceImagePlaceholders = useCallback18(
|
|
9929
|
+
(html) => {
|
|
9930
|
+
let result = html;
|
|
9931
|
+
images.forEach(({ placeholder, src }) => {
|
|
9932
|
+
result = result.replace(
|
|
9933
|
+
new RegExp(placeholder.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"),
|
|
9934
|
+
`<img src="${src}" style="max-width: 100%; border-radius: 8px; margin: 8px 0;" />`
|
|
9935
|
+
);
|
|
9936
|
+
});
|
|
9937
|
+
return result;
|
|
9938
|
+
},
|
|
9939
|
+
[images]
|
|
9940
|
+
);
|
|
9941
|
+
return { images, isUploading, pasteAreaRef, handlePaste, replaceImagePlaceholders };
|
|
9942
|
+
}
|
|
9943
|
+
|
|
9608
9944
|
// src/plugins/TextCardsPlugin/index.tsx
|
|
9609
9945
|
import { jsx as jsx31, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
9610
9946
|
var INSERT_TEXT_CARDS_COMMAND = createCommand17(
|
|
@@ -9632,16 +9968,27 @@ function InsertTextCardsDialog({
|
|
|
9632
9968
|
activeEditor,
|
|
9633
9969
|
onClose
|
|
9634
9970
|
}) {
|
|
9635
|
-
const [input, setInput] =
|
|
9636
|
-
|
|
9971
|
+
const [input, setInput] = useState26("");
|
|
9972
|
+
let editorConfig = null;
|
|
9973
|
+
try {
|
|
9974
|
+
editorConfig = useEditorConfig();
|
|
9975
|
+
} catch {
|
|
9976
|
+
}
|
|
9977
|
+
const richPaste = useRichPaste(
|
|
9978
|
+
(text) => setInput((prev) => prev ? prev + "\n" + text : text),
|
|
9979
|
+
editorConfig?.baasixClient,
|
|
9980
|
+
editorConfig?.folder
|
|
9981
|
+
);
|
|
9982
|
+
const finalHtml = useMemo14(() => {
|
|
9637
9983
|
if (!input.trim()) return "";
|
|
9638
|
-
|
|
9639
|
-
|
|
9640
|
-
|
|
9641
|
-
|
|
9642
|
-
|
|
9984
|
+
const html = convertTextCards(input);
|
|
9985
|
+
return richPaste.replaceImagePlaceholders(html);
|
|
9986
|
+
}, [input, richPaste]);
|
|
9987
|
+
const handleInsert = useCallback19(() => {
|
|
9988
|
+
if (!finalHtml) return;
|
|
9989
|
+
activeEditor.dispatchCommand(INSERT_TEXT_CARDS_COMMAND, finalHtml);
|
|
9643
9990
|
onClose();
|
|
9644
|
-
}, [activeEditor,
|
|
9991
|
+
}, [activeEditor, finalHtml, onClose]);
|
|
9645
9992
|
return /* @__PURE__ */ jsxs21("div", { style: { minWidth: 500 }, children: [
|
|
9646
9993
|
/* @__PURE__ */ jsx31(
|
|
9647
9994
|
"textarea",
|
|
@@ -9668,7 +10015,7 @@ Critical Insight
|
|
|
9668
10015
|
Pathology bridges clinical suspicion with molecular certainty...`,
|
|
9669
10016
|
style: {
|
|
9670
10017
|
width: "100%",
|
|
9671
|
-
minHeight:
|
|
10018
|
+
minHeight: 150,
|
|
9672
10019
|
fontFamily: "monospace",
|
|
9673
10020
|
fontSize: 13,
|
|
9674
10021
|
padding: 8,
|
|
@@ -9679,9 +10026,38 @@ Pathology bridges clinical suspicion with molecular certainty...`,
|
|
|
9679
10026
|
}
|
|
9680
10027
|
}
|
|
9681
10028
|
),
|
|
9682
|
-
|
|
10029
|
+
/* @__PURE__ */ jsx31(
|
|
10030
|
+
"div",
|
|
10031
|
+
{
|
|
10032
|
+
ref: richPaste.pasteAreaRef,
|
|
10033
|
+
contentEditable: true,
|
|
10034
|
+
onPaste: richPaste.handlePaste,
|
|
10035
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
10036
|
+
style: {
|
|
10037
|
+
width: "100%",
|
|
10038
|
+
minHeight: 40,
|
|
10039
|
+
padding: 8,
|
|
10040
|
+
border: "2px dashed #93c5fd",
|
|
10041
|
+
borderRadius: 4,
|
|
10042
|
+
fontSize: 12,
|
|
10043
|
+
color: "#6b7280",
|
|
10044
|
+
marginBottom: 8,
|
|
10045
|
+
outline: "none",
|
|
10046
|
+
background: "#f0f7ff"
|
|
10047
|
+
},
|
|
10048
|
+
suppressContentEditableWarning: true,
|
|
10049
|
+
children: /* @__PURE__ */ jsx31("span", { style: { color: "#9ca3af", pointerEvents: "none", userSelect: "none" }, children: richPaste.isUploading ? "Uploading images..." : "Paste from Word/Docs here for image support" })
|
|
10050
|
+
}
|
|
10051
|
+
),
|
|
10052
|
+
richPaste.images.length > 0 && /* @__PURE__ */ jsxs21("div", { style: { marginBottom: 8, fontSize: 11, color: "#16a34a" }, children: [
|
|
10053
|
+
richPaste.images.length,
|
|
10054
|
+
" image",
|
|
10055
|
+
richPaste.images.length > 1 ? "s" : "",
|
|
10056
|
+
" captured"
|
|
10057
|
+
] }),
|
|
10058
|
+
finalHtml && /* @__PURE__ */ jsxs21("div", { style: { marginBottom: 8, padding: 8, border: "1px solid #e5e7eb", borderRadius: 4, background: "#fafafa", maxHeight: 250, overflow: "auto" }, children: [
|
|
9683
10059
|
/* @__PURE__ */ jsx31("span", { style: { fontSize: 11, color: "#888", display: "block", marginBottom: 4 }, children: "Preview:" }),
|
|
9684
|
-
/* @__PURE__ */ jsx31("div", { dangerouslySetInnerHTML: { __html:
|
|
10060
|
+
/* @__PURE__ */ jsx31("div", { dangerouslySetInnerHTML: { __html: finalHtml } })
|
|
9685
10061
|
] }),
|
|
9686
10062
|
/* @__PURE__ */ jsxs21("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8 }, children: [
|
|
9687
10063
|
/* @__PURE__ */ jsx31(
|
|
@@ -9698,9 +10074,9 @@ Pathology bridges clinical suspicion with molecular certainty...`,
|
|
|
9698
10074
|
{
|
|
9699
10075
|
type: "button",
|
|
9700
10076
|
onClick: handleInsert,
|
|
9701
|
-
disabled: !
|
|
9702
|
-
style: { padding: "6px 16px", fontSize: 13, border: "none", borderRadius: 4, background: "#2563eb", color: "#fff", cursor: "pointer", opacity:
|
|
9703
|
-
children: "Insert"
|
|
10077
|
+
disabled: !finalHtml || richPaste.isUploading,
|
|
10078
|
+
style: { padding: "6px 16px", fontSize: 13, border: "none", borderRadius: 4, background: "#2563eb", color: "#fff", cursor: "pointer", opacity: finalHtml && !richPaste.isUploading ? 1 : 0.5 },
|
|
10079
|
+
children: richPaste.isUploading ? "Uploading..." : "Insert"
|
|
9704
10080
|
}
|
|
9705
10081
|
)
|
|
9706
10082
|
] })
|
|
@@ -9711,7 +10087,7 @@ Pathology bridges clinical suspicion with molecular certainty...`,
|
|
|
9711
10087
|
import { useLexicalComposerContext as useLexicalComposerContext30 } from "@lexical/react/LexicalComposerContext";
|
|
9712
10088
|
import { $insertNodeToNearestRoot as $insertNodeToNearestRoot11 } from "@lexical/utils";
|
|
9713
10089
|
import { COMMAND_PRIORITY_EDITOR as COMMAND_PRIORITY_EDITOR18, createCommand as createCommand18 } from "lexical";
|
|
9714
|
-
import { useCallback as
|
|
10090
|
+
import { useCallback as useCallback21, useEffect as useEffect28, useMemo as useMemo16, useState as useState28 } from "react";
|
|
9715
10091
|
|
|
9716
10092
|
// src/nodes/QuestionsCardsNode.tsx
|
|
9717
10093
|
import { $getNodeByKey as $getNodeByKey8 } from "lexical";
|
|
@@ -9721,7 +10097,7 @@ import {
|
|
|
9721
10097
|
} from "@lexical/react/LexicalDecoratorBlockNode";
|
|
9722
10098
|
import { useLexicalComposerContext as useLexicalComposerContext29 } from "@lexical/react/LexicalComposerContext";
|
|
9723
10099
|
import { useLexicalEditable as useLexicalEditable5 } from "@lexical/react/useLexicalEditable";
|
|
9724
|
-
import { useCallback as
|
|
10100
|
+
import { useCallback as useCallback20, useMemo as useMemo15, useState as useState27 } from "react";
|
|
9725
10101
|
import { jsx as jsx32, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
9726
10102
|
var GRID_SECTION_KEYS = [
|
|
9727
10103
|
"rubric",
|
|
@@ -9742,44 +10118,45 @@ function QuestionsCardsComponent({
|
|
|
9742
10118
|
}) {
|
|
9743
10119
|
const [editor] = useLexicalComposerContext29();
|
|
9744
10120
|
const isEditable = useLexicalEditable5();
|
|
9745
|
-
const [isEditing, setIsEditing] =
|
|
9746
|
-
const [
|
|
9747
|
-
const
|
|
9748
|
-
|
|
9749
|
-
|
|
10121
|
+
const [isEditing, setIsEditing] = useState27(false);
|
|
10122
|
+
const [qaPairs, setQaPairs] = useState27([]);
|
|
10123
|
+
const makeEmptyQA = () => ({
|
|
10124
|
+
question: "",
|
|
10125
|
+
answer: "",
|
|
10126
|
+
sections: GRID_SECTION_KEYS.map((k) => ({ key: k, content: "" }))
|
|
10127
|
+
});
|
|
10128
|
+
const openEditor = useCallback20(() => {
|
|
9750
10129
|
const parsed = parseQuestionsCardsHtml(html);
|
|
9751
|
-
|
|
9752
|
-
|
|
9753
|
-
|
|
9754
|
-
|
|
9755
|
-
|
|
9756
|
-
|
|
10130
|
+
const pairs = parsed.qaPairs.map((qa) => {
|
|
10131
|
+
const existing = qa.sections || [];
|
|
10132
|
+
const all = GRID_SECTION_KEYS.map((k) => {
|
|
10133
|
+
const found = existing.find((s) => s.key === k);
|
|
10134
|
+
return found || { key: k, content: "" };
|
|
10135
|
+
});
|
|
10136
|
+
return { question: qa.question, answer: qa.answer, sections: all };
|
|
9757
10137
|
});
|
|
9758
|
-
|
|
10138
|
+
setQaPairs(pairs.length > 0 ? pairs : [makeEmptyQA()]);
|
|
9759
10139
|
setIsEditing(true);
|
|
9760
10140
|
}, [html]);
|
|
9761
10141
|
const preview = useMemo15(() => {
|
|
9762
10142
|
if (!isEditing) return "";
|
|
9763
|
-
const
|
|
10143
|
+
const cStyles = CARD_STYLES.questionsCards;
|
|
9764
10144
|
const lines = [];
|
|
9765
|
-
|
|
9766
|
-
lines.push(
|
|
9767
|
-
|
|
9768
|
-
|
|
9769
|
-
|
|
9770
|
-
|
|
9771
|
-
|
|
9772
|
-
|
|
9773
|
-
|
|
9774
|
-
|
|
9775
|
-
lines.push(sStyle.title);
|
|
9776
|
-
lines.push(s.content);
|
|
9777
|
-
}
|
|
10145
|
+
qaPairs.forEach((qa, idx) => {
|
|
10146
|
+
if (qa.question) lines.push(`${idx + 1}. Question: ${qa.question}`);
|
|
10147
|
+
if (qa.answer) lines.push(`Answer: ${qa.answer}`);
|
|
10148
|
+
qa.sections.forEach((s) => {
|
|
10149
|
+
const sStyle = cStyles[s.key];
|
|
10150
|
+
if (sStyle && "title" in sStyle && s.content) {
|
|
10151
|
+
lines.push(sStyle.title);
|
|
10152
|
+
lines.push(s.content);
|
|
10153
|
+
}
|
|
10154
|
+
});
|
|
9778
10155
|
});
|
|
9779
10156
|
const text = lines.join("\n");
|
|
9780
10157
|
return text.trim() ? convertQuestionsCards(text) : "";
|
|
9781
|
-
}, [isEditing,
|
|
9782
|
-
const saveChanges =
|
|
10158
|
+
}, [isEditing, qaPairs]);
|
|
10159
|
+
const saveChanges = useCallback20(() => {
|
|
9783
10160
|
if (!preview) return;
|
|
9784
10161
|
editor.update(() => {
|
|
9785
10162
|
const node = $getNodeByKey8(nodeKey);
|
|
@@ -9789,17 +10166,27 @@ function QuestionsCardsComponent({
|
|
|
9789
10166
|
});
|
|
9790
10167
|
setIsEditing(false);
|
|
9791
10168
|
}, [editor, nodeKey, preview]);
|
|
9792
|
-
const cancelEdit =
|
|
10169
|
+
const cancelEdit = useCallback20(() => {
|
|
9793
10170
|
setIsEditing(false);
|
|
9794
10171
|
}, []);
|
|
9795
|
-
const
|
|
9796
|
-
|
|
9797
|
-
|
|
9798
|
-
|
|
10172
|
+
const updateQA = useCallback20((idx, field, value) => {
|
|
10173
|
+
setQaPairs((prev) => prev.map((qa, i) => i === idx ? { ...qa, [field]: value } : qa));
|
|
10174
|
+
}, []);
|
|
10175
|
+
const addQAPair = useCallback20(() => {
|
|
10176
|
+
setQaPairs((prev) => [...prev, makeEmptyQA()]);
|
|
10177
|
+
}, []);
|
|
10178
|
+
const removeQAPair = useCallback20((idx) => {
|
|
10179
|
+
setQaPairs((prev) => prev.filter((_, i) => i !== idx));
|
|
10180
|
+
}, []);
|
|
10181
|
+
const updateSection = useCallback20((qIdx, sIdx, value) => {
|
|
10182
|
+
setQaPairs((prev) => prev.map((qa, i) => {
|
|
10183
|
+
if (i !== qIdx) return qa;
|
|
10184
|
+
return { ...qa, sections: qa.sections.map((s, j) => j === sIdx ? { ...s, content: value } : s) };
|
|
10185
|
+
}));
|
|
9799
10186
|
}, []);
|
|
9800
10187
|
const styles = CARD_STYLES.questionsCards;
|
|
9801
10188
|
return /* @__PURE__ */ jsx32(BlockWithAlignableContents8, { className, format, nodeKey, children: /* @__PURE__ */ jsxs22("div", { style: { position: "relative" }, children: [
|
|
9802
|
-
isEditable &&
|
|
10189
|
+
isEditable && /* @__PURE__ */ jsx32(
|
|
9803
10190
|
"button",
|
|
9804
10191
|
{
|
|
9805
10192
|
type: "button",
|
|
@@ -9824,82 +10211,86 @@ function QuestionsCardsComponent({
|
|
|
9824
10211
|
children: "Edit Questions Card"
|
|
9825
10212
|
}
|
|
9826
10213
|
),
|
|
9827
|
-
|
|
9828
|
-
|
|
9829
|
-
|
|
9830
|
-
/* @__PURE__ */ jsxs22("div", { style: { display: "flex",
|
|
9831
|
-
/* @__PURE__ */
|
|
10214
|
+
/* @__PURE__ */ jsx32("div", { dangerouslySetInnerHTML: { __html: html } }),
|
|
10215
|
+
isEditing && /* @__PURE__ */ jsx32(Modal, { onClose: cancelEdit, title: "Edit Questions Card", children: /* @__PURE__ */ jsxs22("div", { style: { minWidth: 500 }, children: [
|
|
10216
|
+
qaPairs.map((qa, qIdx) => /* @__PURE__ */ jsxs22("div", { style: { border: "1px solid #e5e7eb", borderRadius: 6, padding: 8, marginBottom: 8, background: "#fff" }, children: [
|
|
10217
|
+
/* @__PURE__ */ jsxs22("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 4 }, children: [
|
|
10218
|
+
/* @__PURE__ */ jsxs22("span", { style: { fontSize: 12, fontWeight: 600, color: "#1976d2" }, children: [
|
|
10219
|
+
"Q",
|
|
10220
|
+
qIdx + 1
|
|
10221
|
+
] }),
|
|
10222
|
+
qaPairs.length > 1 && /* @__PURE__ */ jsx32(
|
|
9832
10223
|
"button",
|
|
9833
10224
|
{
|
|
9834
10225
|
type: "button",
|
|
9835
|
-
onClick:
|
|
9836
|
-
style: { padding: "2px
|
|
9837
|
-
children: "
|
|
10226
|
+
onClick: () => removeQAPair(qIdx),
|
|
10227
|
+
style: { padding: "2px 6px", fontSize: 14, border: "1px solid #ddd", borderRadius: 4, background: "#fff", cursor: "pointer", color: "#e11d48" },
|
|
10228
|
+
children: "\xD7"
|
|
9838
10229
|
}
|
|
9839
|
-
)
|
|
10230
|
+
)
|
|
10231
|
+
] }),
|
|
10232
|
+
/* @__PURE__ */ jsxs22("div", { style: { marginBottom: 4 }, children: [
|
|
10233
|
+
/* @__PURE__ */ jsx32("label", { style: { fontSize: 11, color: "#1976d2", fontWeight: 600, display: "block", marginBottom: 2 }, children: "Question" }),
|
|
9840
10234
|
/* @__PURE__ */ jsx32(
|
|
9841
|
-
"
|
|
10235
|
+
"textarea",
|
|
9842
10236
|
{
|
|
9843
|
-
|
|
9844
|
-
|
|
9845
|
-
|
|
9846
|
-
style: { padding: "
|
|
9847
|
-
|
|
10237
|
+
placeholder: "Enter question text...",
|
|
10238
|
+
value: qa.question,
|
|
10239
|
+
onChange: (e) => updateQA(qIdx, "question", e.target.value),
|
|
10240
|
+
style: { width: "100%", padding: "4px 6px", fontSize: 12, border: "1px solid #ddd", borderRadius: 4, minHeight: 40, resize: "vertical" }
|
|
10241
|
+
}
|
|
10242
|
+
)
|
|
10243
|
+
] }),
|
|
10244
|
+
/* @__PURE__ */ jsxs22("div", { style: { marginBottom: 4 }, children: [
|
|
10245
|
+
/* @__PURE__ */ jsx32("label", { style: { fontSize: 11, color: "#666", fontWeight: 600, display: "block", marginBottom: 2 }, children: "Answer" }),
|
|
10246
|
+
/* @__PURE__ */ jsx32(
|
|
10247
|
+
"textarea",
|
|
10248
|
+
{
|
|
10249
|
+
placeholder: "Enter answer text...",
|
|
10250
|
+
value: qa.answer,
|
|
10251
|
+
onChange: (e) => updateQA(qIdx, "answer", e.target.value),
|
|
10252
|
+
style: { width: "100%", padding: "4px 6px", fontSize: 12, border: "1px solid #ddd", borderRadius: 4, minHeight: 60, resize: "vertical" }
|
|
9848
10253
|
}
|
|
9849
10254
|
)
|
|
10255
|
+
] }),
|
|
10256
|
+
/* @__PURE__ */ jsxs22("details", { style: { marginTop: 4 }, children: [
|
|
10257
|
+
/* @__PURE__ */ jsx32("summary", { style: { fontSize: 11, color: "#666", fontWeight: 600, cursor: "pointer" }, children: "Card Sections" }),
|
|
10258
|
+
/* @__PURE__ */ jsx32("div", { style: { marginTop: 4 }, children: qa.sections.map((section, sIdx) => {
|
|
10259
|
+
const sStyle = styles[section.key];
|
|
10260
|
+
const label = sStyle && "title" in sStyle ? sStyle.title : section.key;
|
|
10261
|
+
return /* @__PURE__ */ jsxs22("div", { style: { marginBottom: 4 }, children: [
|
|
10262
|
+
/* @__PURE__ */ jsx32("label", { style: { fontSize: 11, color: "#666", display: "block", marginBottom: 2 }, children: label }),
|
|
10263
|
+
/* @__PURE__ */ jsx32(
|
|
10264
|
+
"textarea",
|
|
10265
|
+
{
|
|
10266
|
+
placeholder: `${label} content...`,
|
|
10267
|
+
value: section.content,
|
|
10268
|
+
onChange: (e) => updateSection(qIdx, sIdx, e.target.value),
|
|
10269
|
+
style: { width: "100%", padding: "4px 6px", fontSize: 12, border: "1px solid #ddd", borderRadius: 4, minHeight: 40, resize: "vertical" }
|
|
10270
|
+
}
|
|
10271
|
+
)
|
|
10272
|
+
] }, sIdx);
|
|
10273
|
+
}) })
|
|
9850
10274
|
] })
|
|
9851
|
-
] }),
|
|
9852
|
-
/* @__PURE__ */
|
|
9853
|
-
|
|
9854
|
-
|
|
9855
|
-
"
|
|
9856
|
-
|
|
9857
|
-
|
|
9858
|
-
|
|
9859
|
-
|
|
9860
|
-
|
|
9861
|
-
|
|
9862
|
-
}
|
|
9863
|
-
)
|
|
9864
|
-
] }),
|
|
9865
|
-
/* @__PURE__ */ jsxs22("div", { style: { marginBottom: 6 }, children: [
|
|
9866
|
-
/* @__PURE__ */ jsx32("label", { style: { fontSize: 11, color: "#666", fontWeight: 600, display: "block", marginBottom: 2 }, children: "Answer" }),
|
|
9867
|
-
/* @__PURE__ */ jsx32(
|
|
9868
|
-
"textarea",
|
|
9869
|
-
{
|
|
9870
|
-
placeholder: "Enter answer text...",
|
|
9871
|
-
value: answer,
|
|
9872
|
-
onChange: (e) => setAnswer(e.target.value),
|
|
9873
|
-
onMouseDown: (e) => e.stopPropagation(),
|
|
9874
|
-
style: { width: "100%", padding: "4px 6px", fontSize: 12, border: "1px solid #ddd", borderRadius: 4, minHeight: 60, resize: "vertical" }
|
|
9875
|
-
}
|
|
9876
|
-
)
|
|
9877
|
-
] }),
|
|
9878
|
-
/* @__PURE__ */ jsxs22("div", { style: { border: "1px solid #e5e7eb", borderRadius: 6, padding: 8, background: "#fff" }, children: [
|
|
9879
|
-
/* @__PURE__ */ jsx32("span", { style: { fontSize: 11, color: "#666", fontWeight: 600, display: "block", marginBottom: 4 }, children: "Card Sections" }),
|
|
9880
|
-
sections.map((section, idx) => {
|
|
9881
|
-
const sStyle = styles[section.key];
|
|
9882
|
-
const label = sStyle && "title" in sStyle ? sStyle.title : section.key;
|
|
9883
|
-
return /* @__PURE__ */ jsxs22("div", { style: { marginBottom: 4 }, children: [
|
|
9884
|
-
/* @__PURE__ */ jsx32("label", { style: { fontSize: 11, color: "#666", display: "block", marginBottom: 2 }, children: label }),
|
|
9885
|
-
/* @__PURE__ */ jsx32(
|
|
9886
|
-
"textarea",
|
|
9887
|
-
{
|
|
9888
|
-
placeholder: `${label} content...`,
|
|
9889
|
-
value: section.content,
|
|
9890
|
-
onChange: (e) => updateSection(idx, e.target.value),
|
|
9891
|
-
onMouseDown: (e) => e.stopPropagation(),
|
|
9892
|
-
style: { width: "100%", padding: "4px 6px", fontSize: 12, border: "1px solid #ddd", borderRadius: 4, minHeight: 40, resize: "vertical" }
|
|
9893
|
-
}
|
|
9894
|
-
)
|
|
9895
|
-
] }, idx);
|
|
9896
|
-
})
|
|
9897
|
-
] }),
|
|
9898
|
-
preview && /* @__PURE__ */ jsxs22("div", { style: { marginTop: 8, padding: 8, border: "1px solid #e5e7eb", borderRadius: 4, background: "#fff" }, children: [
|
|
10275
|
+
] }, qIdx)),
|
|
10276
|
+
/* @__PURE__ */ jsx32(
|
|
10277
|
+
"button",
|
|
10278
|
+
{
|
|
10279
|
+
type: "button",
|
|
10280
|
+
onClick: addQAPair,
|
|
10281
|
+
style: { padding: "2px 10px", fontSize: 12, border: "1px solid #ddd", borderRadius: 4, background: "#fff", cursor: "pointer", marginBottom: 8 },
|
|
10282
|
+
children: "+ Add Question"
|
|
10283
|
+
}
|
|
10284
|
+
),
|
|
10285
|
+
preview && /* @__PURE__ */ jsxs22("div", { style: { marginTop: 8, padding: 8, border: "1px solid #e5e7eb", borderRadius: 4, background: "#fff", maxHeight: 200, overflow: "auto" }, children: [
|
|
9899
10286
|
/* @__PURE__ */ jsx32("span", { style: { fontSize: 11, color: "#888", display: "block", marginBottom: 4 }, children: "Preview:" }),
|
|
9900
10287
|
/* @__PURE__ */ jsx32("div", { dangerouslySetInnerHTML: { __html: preview } })
|
|
10288
|
+
] }),
|
|
10289
|
+
/* @__PURE__ */ jsxs22("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 12 }, children: [
|
|
10290
|
+
/* @__PURE__ */ jsx32("button", { type: "button", onClick: cancelEdit, style: { padding: "6px 16px", fontSize: 13, border: "1px solid #ccc", borderRadius: 4, background: "#fff", cursor: "pointer" }, children: "Cancel" }),
|
|
10291
|
+
/* @__PURE__ */ jsx32("button", { type: "button", onClick: saveChanges, disabled: !preview, style: { padding: "6px 16px", fontSize: 13, border: "none", borderRadius: 4, background: "#2563eb", color: "#fff", cursor: "pointer", opacity: preview ? 1 : 0.5 }, children: "Save" })
|
|
9901
10292
|
] })
|
|
9902
|
-
] })
|
|
10293
|
+
] }) })
|
|
9903
10294
|
] }) });
|
|
9904
10295
|
}
|
|
9905
10296
|
var DATA_ATTR5 = "data-lexical-questions-cards";
|
|
@@ -10003,16 +10394,27 @@ function InsertQuestionsCardsDialog({
|
|
|
10003
10394
|
activeEditor,
|
|
10004
10395
|
onClose
|
|
10005
10396
|
}) {
|
|
10006
|
-
const [input, setInput] =
|
|
10007
|
-
|
|
10397
|
+
const [input, setInput] = useState28("");
|
|
10398
|
+
let editorConfig = null;
|
|
10399
|
+
try {
|
|
10400
|
+
editorConfig = useEditorConfig();
|
|
10401
|
+
} catch {
|
|
10402
|
+
}
|
|
10403
|
+
const richPaste = useRichPaste(
|
|
10404
|
+
(text) => setInput((prev) => prev ? prev + "\n" + text : text),
|
|
10405
|
+
editorConfig?.baasixClient,
|
|
10406
|
+
editorConfig?.folder
|
|
10407
|
+
);
|
|
10408
|
+
const finalHtml = useMemo16(() => {
|
|
10008
10409
|
if (!input.trim()) return "";
|
|
10009
|
-
|
|
10010
|
-
|
|
10011
|
-
|
|
10012
|
-
|
|
10013
|
-
|
|
10410
|
+
const html = convertQuestionsCards(input);
|
|
10411
|
+
return richPaste.replaceImagePlaceholders(html);
|
|
10412
|
+
}, [input, richPaste]);
|
|
10413
|
+
const handleInsert = useCallback21(() => {
|
|
10414
|
+
if (!finalHtml) return;
|
|
10415
|
+
activeEditor.dispatchCommand(INSERT_QUESTIONS_CARDS_COMMAND, finalHtml);
|
|
10014
10416
|
onClose();
|
|
10015
|
-
}, [activeEditor,
|
|
10417
|
+
}, [activeEditor, finalHtml, onClose]);
|
|
10016
10418
|
return /* @__PURE__ */ jsxs23("div", { style: { minWidth: 500 }, children: [
|
|
10017
10419
|
/* @__PURE__ */ jsx33(
|
|
10018
10420
|
"textarea",
|
|
@@ -10021,28 +10423,18 @@ function InsertQuestionsCardsDialog({
|
|
|
10021
10423
|
onChange: (e) => setInput(e.target.value),
|
|
10022
10424
|
placeholder: `Paste question content here...
|
|
10023
10425
|
Example:
|
|
10024
|
-
Q1
|
|
10426
|
+
Q1 : Describe the pathogenesis of tuberculosis.
|
|
10025
10427
|
|
|
10026
|
-
Answer:
|
|
10027
|
-
Tuberculosis is caused by Mycobacterium tuberculosis...
|
|
10428
|
+
Answer: Tuberculosis is caused by Mycobacterium tuberculosis...
|
|
10028
10429
|
|
|
10029
|
-
MARKING RUBRIC
|
|
10430
|
+
1. MARKING RUBRIC
|
|
10030
10431
|
Definition: 2 marks, Pathogenesis: 5 marks...
|
|
10031
10432
|
|
|
10032
|
-
MNEMONICS
|
|
10033
|
-
Remember TB pathogenesis with "IGRA"
|
|
10034
|
-
|
|
10035
|
-
EXAMINER'S PERSPECTIVE
|
|
10036
|
-
Examiners look for systematic approach...
|
|
10037
|
-
|
|
10038
|
-
CLINICAL CORRELATION
|
|
10039
|
-
TB commonly presents with...
|
|
10040
|
-
|
|
10041
|
-
HIGH-YIELD EXAM TIP
|
|
10042
|
-
Always mention Ghon complex...`,
|
|
10433
|
+
2. MNEMONICS
|
|
10434
|
+
Remember TB pathogenesis with "IGRA"...`,
|
|
10043
10435
|
style: {
|
|
10044
10436
|
width: "100%",
|
|
10045
|
-
minHeight:
|
|
10437
|
+
minHeight: 150,
|
|
10046
10438
|
fontFamily: "monospace",
|
|
10047
10439
|
fontSize: 13,
|
|
10048
10440
|
padding: 8,
|
|
@@ -10053,9 +10445,38 @@ Always mention Ghon complex...`,
|
|
|
10053
10445
|
}
|
|
10054
10446
|
}
|
|
10055
10447
|
),
|
|
10056
|
-
|
|
10448
|
+
/* @__PURE__ */ jsx33(
|
|
10449
|
+
"div",
|
|
10450
|
+
{
|
|
10451
|
+
ref: richPaste.pasteAreaRef,
|
|
10452
|
+
contentEditable: true,
|
|
10453
|
+
onPaste: richPaste.handlePaste,
|
|
10454
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
10455
|
+
style: {
|
|
10456
|
+
width: "100%",
|
|
10457
|
+
minHeight: 40,
|
|
10458
|
+
padding: 8,
|
|
10459
|
+
border: "2px dashed #93c5fd",
|
|
10460
|
+
borderRadius: 4,
|
|
10461
|
+
fontSize: 12,
|
|
10462
|
+
color: "#6b7280",
|
|
10463
|
+
marginBottom: 8,
|
|
10464
|
+
outline: "none",
|
|
10465
|
+
background: "#f0f7ff"
|
|
10466
|
+
},
|
|
10467
|
+
suppressContentEditableWarning: true,
|
|
10468
|
+
children: /* @__PURE__ */ jsx33("span", { style: { color: "#9ca3af", pointerEvents: "none", userSelect: "none" }, children: richPaste.isUploading ? "Uploading images..." : "Paste from Word/Docs here for image support" })
|
|
10469
|
+
}
|
|
10470
|
+
),
|
|
10471
|
+
richPaste.images.length > 0 && /* @__PURE__ */ jsxs23("div", { style: { marginBottom: 8, fontSize: 11, color: "#16a34a" }, children: [
|
|
10472
|
+
richPaste.images.length,
|
|
10473
|
+
" image",
|
|
10474
|
+
richPaste.images.length > 1 ? "s" : "",
|
|
10475
|
+
" captured"
|
|
10476
|
+
] }),
|
|
10477
|
+
finalHtml && /* @__PURE__ */ jsxs23("div", { style: { marginBottom: 8, padding: 8, border: "1px solid #e5e7eb", borderRadius: 4, background: "#fafafa", maxHeight: 250, overflow: "auto" }, children: [
|
|
10057
10478
|
/* @__PURE__ */ jsx33("span", { style: { fontSize: 11, color: "#888", display: "block", marginBottom: 4 }, children: "Preview:" }),
|
|
10058
|
-
/* @__PURE__ */ jsx33("div", { dangerouslySetInnerHTML: { __html:
|
|
10479
|
+
/* @__PURE__ */ jsx33("div", { dangerouslySetInnerHTML: { __html: finalHtml } })
|
|
10059
10480
|
] }),
|
|
10060
10481
|
/* @__PURE__ */ jsxs23("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8 }, children: [
|
|
10061
10482
|
/* @__PURE__ */ jsx33(
|
|
@@ -10072,9 +10493,9 @@ Always mention Ghon complex...`,
|
|
|
10072
10493
|
{
|
|
10073
10494
|
type: "button",
|
|
10074
10495
|
onClick: handleInsert,
|
|
10075
|
-
disabled: !
|
|
10076
|
-
style: { padding: "6px 16px", fontSize: 13, border: "none", borderRadius: 4, background: "#2563eb", color: "#fff", cursor: "pointer", opacity:
|
|
10077
|
-
children: "Insert"
|
|
10496
|
+
disabled: !finalHtml || richPaste.isUploading,
|
|
10497
|
+
style: { padding: "6px 16px", fontSize: 13, border: "none", borderRadius: 4, background: "#2563eb", color: "#fff", cursor: "pointer", opacity: finalHtml && !richPaste.isUploading ? 1 : 0.5 },
|
|
10498
|
+
children: richPaste.isUploading ? "Uploading..." : "Insert"
|
|
10078
10499
|
}
|
|
10079
10500
|
)
|
|
10080
10501
|
] })
|
|
@@ -10089,7 +10510,7 @@ import {
|
|
|
10089
10510
|
TableNode as TableNode2,
|
|
10090
10511
|
TableRowNode as TableRowNode2
|
|
10091
10512
|
} from "@lexical/table";
|
|
10092
|
-
import { createContext as createContext4, useContext as useContext4, useEffect as useEffect29, useMemo as useMemo17, useState as
|
|
10513
|
+
import { createContext as createContext4, useContext as useContext4, useEffect as useEffect29, useMemo as useMemo17, useState as useState29 } from "react";
|
|
10093
10514
|
import { Fragment as Fragment10, jsx as jsx34, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
10094
10515
|
var CellContext = createContext4({
|
|
10095
10516
|
cellEditorConfig: null,
|
|
@@ -10101,9 +10522,9 @@ function InsertTableDialog({
|
|
|
10101
10522
|
activeEditor,
|
|
10102
10523
|
onClose
|
|
10103
10524
|
}) {
|
|
10104
|
-
const [rows, setRows] =
|
|
10105
|
-
const [columns, setColumns] =
|
|
10106
|
-
const [isDisabled, setIsDisabled] =
|
|
10525
|
+
const [rows, setRows] = useState29("5");
|
|
10526
|
+
const [columns, setColumns] = useState29("5");
|
|
10527
|
+
const [isDisabled, setIsDisabled] = useState29(true);
|
|
10107
10528
|
useEffect29(() => {
|
|
10108
10529
|
const row = Number(rows);
|
|
10109
10530
|
const column = Number(columns);
|
|
@@ -10155,7 +10576,7 @@ import {
|
|
|
10155
10576
|
} from "@lexical/react/LexicalDecoratorBlockNode";
|
|
10156
10577
|
import { useLexicalComposerContext as useLexicalComposerContext32 } from "@lexical/react/LexicalComposerContext";
|
|
10157
10578
|
import { useLexicalEditable as useLexicalEditable6 } from "@lexical/react/useLexicalEditable";
|
|
10158
|
-
import { useCallback as
|
|
10579
|
+
import { useCallback as useCallback22, useRef as useRef11, useState as useState30 } from "react";
|
|
10159
10580
|
import { jsx as jsx35, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
10160
10581
|
function HtmlBlockComponent({
|
|
10161
10582
|
className,
|
|
@@ -10165,15 +10586,15 @@ function HtmlBlockComponent({
|
|
|
10165
10586
|
}) {
|
|
10166
10587
|
const [editor] = useLexicalComposerContext32();
|
|
10167
10588
|
const isEditable = useLexicalEditable6();
|
|
10168
|
-
const [isEditing, setIsEditing] =
|
|
10169
|
-
const [editValue, setEditValue] =
|
|
10170
|
-
const textareaRef =
|
|
10171
|
-
const openEditor =
|
|
10589
|
+
const [isEditing, setIsEditing] = useState30(false);
|
|
10590
|
+
const [editValue, setEditValue] = useState30("");
|
|
10591
|
+
const textareaRef = useRef11(null);
|
|
10592
|
+
const openEditor = useCallback22(() => {
|
|
10172
10593
|
setEditValue(html);
|
|
10173
10594
|
setIsEditing(true);
|
|
10174
10595
|
setTimeout(() => textareaRef.current?.focus(), 50);
|
|
10175
10596
|
}, [html]);
|
|
10176
|
-
const saveHtml =
|
|
10597
|
+
const saveHtml = useCallback22(() => {
|
|
10177
10598
|
editor.update(() => {
|
|
10178
10599
|
const node = $getNodeByKey9(nodeKey);
|
|
10179
10600
|
if ($isHtmlBlockNode(node)) {
|
|
@@ -10182,7 +10603,7 @@ function HtmlBlockComponent({
|
|
|
10182
10603
|
});
|
|
10183
10604
|
setIsEditing(false);
|
|
10184
10605
|
}, [editor, nodeKey, editValue]);
|
|
10185
|
-
const cancelEdit =
|
|
10606
|
+
const cancelEdit = useCallback22(() => {
|
|
10186
10607
|
setIsEditing(false);
|
|
10187
10608
|
}, []);
|
|
10188
10609
|
return /* @__PURE__ */ jsx35(
|
|
@@ -10192,7 +10613,7 @@ function HtmlBlockComponent({
|
|
|
10192
10613
|
format,
|
|
10193
10614
|
nodeKey,
|
|
10194
10615
|
children: /* @__PURE__ */ jsxs25("div", { style: { position: "relative" }, children: [
|
|
10195
|
-
isEditable &&
|
|
10616
|
+
isEditable && /* @__PURE__ */ jsx35(
|
|
10196
10617
|
"button",
|
|
10197
10618
|
{
|
|
10198
10619
|
type: "button",
|
|
@@ -10217,52 +10638,14 @@ function HtmlBlockComponent({
|
|
|
10217
10638
|
children: "Edit HTML"
|
|
10218
10639
|
}
|
|
10219
10640
|
),
|
|
10220
|
-
|
|
10221
|
-
|
|
10222
|
-
/* @__PURE__ */ jsx35("span", { style: { fontSize: 12, fontWeight: 600, color: "#333" }, children: "Edit HTML Source" }),
|
|
10223
|
-
/* @__PURE__ */ jsxs25("div", { style: { display: "flex", gap: 4 }, children: [
|
|
10224
|
-
/* @__PURE__ */ jsx35(
|
|
10225
|
-
"button",
|
|
10226
|
-
{
|
|
10227
|
-
type: "button",
|
|
10228
|
-
onClick: cancelEdit,
|
|
10229
|
-
style: {
|
|
10230
|
-
padding: "2px 10px",
|
|
10231
|
-
fontSize: 12,
|
|
10232
|
-
border: "1px solid #ccc",
|
|
10233
|
-
borderRadius: 4,
|
|
10234
|
-
background: "#fff",
|
|
10235
|
-
cursor: "pointer"
|
|
10236
|
-
},
|
|
10237
|
-
children: "Cancel"
|
|
10238
|
-
}
|
|
10239
|
-
),
|
|
10240
|
-
/* @__PURE__ */ jsx35(
|
|
10241
|
-
"button",
|
|
10242
|
-
{
|
|
10243
|
-
type: "button",
|
|
10244
|
-
onClick: saveHtml,
|
|
10245
|
-
style: {
|
|
10246
|
-
padding: "2px 10px",
|
|
10247
|
-
fontSize: 12,
|
|
10248
|
-
border: "none",
|
|
10249
|
-
borderRadius: 4,
|
|
10250
|
-
background: "#2563eb",
|
|
10251
|
-
color: "#fff",
|
|
10252
|
-
cursor: "pointer"
|
|
10253
|
-
},
|
|
10254
|
-
children: "Save"
|
|
10255
|
-
}
|
|
10256
|
-
)
|
|
10257
|
-
] })
|
|
10258
|
-
] }),
|
|
10641
|
+
/* @__PURE__ */ jsx35("div", { dangerouslySetInnerHTML: { __html: html } }),
|
|
10642
|
+
isEditing && /* @__PURE__ */ jsx35(Modal, { onClose: cancelEdit, title: "Edit HTML Source", children: /* @__PURE__ */ jsxs25("div", { style: { minWidth: 500 }, children: [
|
|
10259
10643
|
/* @__PURE__ */ jsx35(
|
|
10260
10644
|
"textarea",
|
|
10261
10645
|
{
|
|
10262
10646
|
ref: textareaRef,
|
|
10263
10647
|
value: editValue,
|
|
10264
10648
|
onChange: (e) => setEditValue(e.target.value),
|
|
10265
|
-
onMouseDown: (e) => e.stopPropagation(),
|
|
10266
10649
|
style: {
|
|
10267
10650
|
width: "100%",
|
|
10268
10651
|
minHeight: 150,
|
|
@@ -10271,21 +10654,36 @@ function HtmlBlockComponent({
|
|
|
10271
10654
|
padding: 8,
|
|
10272
10655
|
border: "1px solid #ddd",
|
|
10273
10656
|
borderRadius: 4,
|
|
10274
|
-
resize: "vertical"
|
|
10657
|
+
resize: "vertical",
|
|
10658
|
+
marginBottom: 8
|
|
10275
10659
|
}
|
|
10276
10660
|
}
|
|
10277
10661
|
),
|
|
10278
|
-
/* @__PURE__ */ jsxs25(
|
|
10279
|
-
"
|
|
10280
|
-
{
|
|
10281
|
-
|
|
10282
|
-
|
|
10283
|
-
|
|
10284
|
-
|
|
10285
|
-
|
|
10286
|
-
|
|
10287
|
-
|
|
10288
|
-
|
|
10662
|
+
/* @__PURE__ */ jsxs25("div", { style: { padding: 8, border: "1px solid #e5e7eb", borderRadius: 4, background: "#fff", maxHeight: 200, overflow: "auto", marginBottom: 8 }, children: [
|
|
10663
|
+
/* @__PURE__ */ jsx35("span", { style: { fontSize: 11, color: "#888", display: "block", marginBottom: 4 }, children: "Preview:" }),
|
|
10664
|
+
/* @__PURE__ */ jsx35("div", { dangerouslySetInnerHTML: { __html: editValue } })
|
|
10665
|
+
] }),
|
|
10666
|
+
/* @__PURE__ */ jsxs25("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8 }, children: [
|
|
10667
|
+
/* @__PURE__ */ jsx35(
|
|
10668
|
+
"button",
|
|
10669
|
+
{
|
|
10670
|
+
type: "button",
|
|
10671
|
+
onClick: cancelEdit,
|
|
10672
|
+
style: { padding: "6px 16px", fontSize: 13, border: "1px solid #ccc", borderRadius: 4, background: "#fff", cursor: "pointer" },
|
|
10673
|
+
children: "Cancel"
|
|
10674
|
+
}
|
|
10675
|
+
),
|
|
10676
|
+
/* @__PURE__ */ jsx35(
|
|
10677
|
+
"button",
|
|
10678
|
+
{
|
|
10679
|
+
type: "button",
|
|
10680
|
+
onClick: saveHtml,
|
|
10681
|
+
style: { padding: "6px 16px", fontSize: 13, border: "none", borderRadius: 4, background: "#2563eb", color: "#fff", cursor: "pointer" },
|
|
10682
|
+
children: "Save"
|
|
10683
|
+
}
|
|
10684
|
+
)
|
|
10685
|
+
] })
|
|
10686
|
+
] }) })
|
|
10289
10687
|
] })
|
|
10290
10688
|
}
|
|
10291
10689
|
);
|
|
@@ -10661,7 +11059,7 @@ function getBaseOptions(editor, showModal) {
|
|
|
10661
11059
|
function ComponentPickerMenuPlugin() {
|
|
10662
11060
|
const [editor] = useLexicalComposerContext33();
|
|
10663
11061
|
const [modal, showModal] = useModal();
|
|
10664
|
-
const [queryString, setQueryString] =
|
|
11062
|
+
const [queryString, setQueryString] = useState31(null);
|
|
10665
11063
|
const checkForTriggerMatch = useBasicTypeaheadTriggerMatch("/", {
|
|
10666
11064
|
allowWhitespace: true,
|
|
10667
11065
|
minLength: 0
|
|
@@ -10679,7 +11077,7 @@ function ComponentPickerMenuPlugin() {
|
|
|
10679
11077
|
)
|
|
10680
11078
|
];
|
|
10681
11079
|
}, [editor, queryString, showModal]);
|
|
10682
|
-
const onSelectOption =
|
|
11080
|
+
const onSelectOption = useCallback23(
|
|
10683
11081
|
(selectedOption, nodeToRemove, closeMenu, matchingString) => {
|
|
10684
11082
|
editor.update(() => {
|
|
10685
11083
|
nodeToRemove?.remove();
|
|
@@ -10912,7 +11310,7 @@ import {
|
|
|
10912
11310
|
$isParagraphNode as $isParagraphNode4,
|
|
10913
11311
|
$isTextNode as $isTextNode4
|
|
10914
11312
|
} from "lexical";
|
|
10915
|
-
import { useCallback as
|
|
11313
|
+
import { useCallback as useCallback24, useEffect as useEffect31, useMemo as useMemo20, useRef as useRef12, useState as useState32 } from "react";
|
|
10916
11314
|
import * as ReactDOM3 from "react-dom";
|
|
10917
11315
|
import { Fragment as Fragment12, jsx as jsx38, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
10918
11316
|
var DRAGGABLE_BLOCK_MENU_CLASSNAME = "draggable-block-menu";
|
|
@@ -10924,18 +11322,18 @@ function DraggableBlockPlugin({
|
|
|
10924
11322
|
}) {
|
|
10925
11323
|
const [editor] = useLexicalComposerContext36();
|
|
10926
11324
|
const [modal, showModal] = useModal();
|
|
10927
|
-
const menuRef =
|
|
10928
|
-
const pickerRef =
|
|
10929
|
-
const searchInputRef =
|
|
10930
|
-
const targetLineRef =
|
|
10931
|
-
const [draggableElement, setDraggableElement] =
|
|
11325
|
+
const menuRef = useRef12(null);
|
|
11326
|
+
const pickerRef = useRef12(null);
|
|
11327
|
+
const searchInputRef = useRef12(null);
|
|
11328
|
+
const targetLineRef = useRef12(null);
|
|
11329
|
+
const [draggableElement, setDraggableElement] = useState32(
|
|
10932
11330
|
null
|
|
10933
11331
|
);
|
|
10934
|
-
const [pickerState, setPickerState] =
|
|
10935
|
-
const [isPickerOpen, setIsPickerOpen] =
|
|
10936
|
-
const [queryString, setQueryString] =
|
|
10937
|
-
const [highlightedIndex, setHighlightedIndex] =
|
|
10938
|
-
const [pickerPosition, setPickerPosition] =
|
|
11332
|
+
const [pickerState, setPickerState] = useState32(null);
|
|
11333
|
+
const [isPickerOpen, setIsPickerOpen] = useState32(false);
|
|
11334
|
+
const [queryString, setQueryString] = useState32("");
|
|
11335
|
+
const [highlightedIndex, setHighlightedIndex] = useState32(0);
|
|
11336
|
+
const [pickerPosition, setPickerPosition] = useState32(null);
|
|
10939
11337
|
const options = useMemo20(() => {
|
|
10940
11338
|
const baseOptions = getBaseOptions(editor, showModal);
|
|
10941
11339
|
if (!queryString) {
|
|
@@ -10979,7 +11377,7 @@ function DraggableBlockPlugin({
|
|
|
10979
11377
|
document.removeEventListener("mousedown", handleClickOutside);
|
|
10980
11378
|
};
|
|
10981
11379
|
}, [isPickerOpen]);
|
|
10982
|
-
const selectOption =
|
|
11380
|
+
const selectOption = useCallback24(
|
|
10983
11381
|
(option) => {
|
|
10984
11382
|
if (!pickerState) {
|
|
10985
11383
|
setIsPickerOpen(false);
|
|
@@ -11156,7 +11554,7 @@ import {
|
|
|
11156
11554
|
$getSelection as $getSelection11,
|
|
11157
11555
|
$isRangeSelection as $isRangeSelection9
|
|
11158
11556
|
} from "lexical";
|
|
11159
|
-
import { useCallback as
|
|
11557
|
+
import { useCallback as useCallback25, useEffect as useEffect32, useMemo as useMemo21, useState as useState33 } from "react";
|
|
11160
11558
|
import * as ReactDOM4 from "react-dom";
|
|
11161
11559
|
import { jsx as jsx39, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
11162
11560
|
var EmojiOption = class extends MenuOption2 {
|
|
@@ -11204,8 +11602,8 @@ function EmojiMenuItem({
|
|
|
11204
11602
|
var MAX_EMOJI_SUGGESTION_COUNT = 10;
|
|
11205
11603
|
function EmojiPickerPlugin() {
|
|
11206
11604
|
const [editor] = useLexicalComposerContext37();
|
|
11207
|
-
const [queryString, setQueryString] =
|
|
11208
|
-
const [emojis, setEmojis] =
|
|
11605
|
+
const [queryString, setQueryString] = useState33(null);
|
|
11606
|
+
const [emojis, setEmojis] = useState33([]);
|
|
11209
11607
|
useEffect32(() => {
|
|
11210
11608
|
import("./emoji-list-MUV74SND.js").then((file) => setEmojis(file.default));
|
|
11211
11609
|
}, []);
|
|
@@ -11229,7 +11627,7 @@ function EmojiPickerPlugin() {
|
|
|
11229
11627
|
) : false : emojiOptions;
|
|
11230
11628
|
}).slice(0, MAX_EMOJI_SUGGESTION_COUNT);
|
|
11231
11629
|
}, [emojiOptions, queryString]);
|
|
11232
|
-
const onSelectOption =
|
|
11630
|
+
const onSelectOption = useCallback25(
|
|
11233
11631
|
(selectedOption, nodeToRemove, closeMenu) => {
|
|
11234
11632
|
editor.update(() => {
|
|
11235
11633
|
const selection = $getSelection11();
|
|
@@ -11302,7 +11700,7 @@ import {
|
|
|
11302
11700
|
KEY_ESCAPE_COMMAND as KEY_ESCAPE_COMMAND2,
|
|
11303
11701
|
SELECTION_CHANGE_COMMAND as SELECTION_CHANGE_COMMAND2
|
|
11304
11702
|
} from "lexical";
|
|
11305
|
-
import { useCallback as
|
|
11703
|
+
import { useCallback as useCallback26, useEffect as useEffect33, useRef as useRef13, useState as useState34 } from "react";
|
|
11306
11704
|
import { createPortal as createPortal8 } from "react-dom";
|
|
11307
11705
|
|
|
11308
11706
|
// src/utils/getSelectedNode.ts
|
|
@@ -11363,14 +11761,14 @@ function FloatingLinkEditor({
|
|
|
11363
11761
|
isLinkEditMode,
|
|
11364
11762
|
setIsLinkEditMode
|
|
11365
11763
|
}) {
|
|
11366
|
-
const editorRef =
|
|
11367
|
-
const inputRef =
|
|
11368
|
-
const [linkUrl, setLinkUrl] =
|
|
11369
|
-
const [editedLinkUrl, setEditedLinkUrl] =
|
|
11370
|
-
const [lastSelection, setLastSelection] =
|
|
11764
|
+
const editorRef = useRef13(null);
|
|
11765
|
+
const inputRef = useRef13(null);
|
|
11766
|
+
const [linkUrl, setLinkUrl] = useState34("");
|
|
11767
|
+
const [editedLinkUrl, setEditedLinkUrl] = useState34("https://");
|
|
11768
|
+
const [lastSelection, setLastSelection] = useState34(
|
|
11371
11769
|
null
|
|
11372
11770
|
);
|
|
11373
|
-
const $updateLinkEditor =
|
|
11771
|
+
const $updateLinkEditor = useCallback26(() => {
|
|
11374
11772
|
const selection = $getSelection12();
|
|
11375
11773
|
if ($isRangeSelection10(selection)) {
|
|
11376
11774
|
const node = getSelectedNode(selection);
|
|
@@ -11622,8 +12020,8 @@ function FloatingLinkEditor({
|
|
|
11622
12020
|
] }) });
|
|
11623
12021
|
}
|
|
11624
12022
|
function useFloatingLinkEditorToolbar(editor, anchorElem, isLinkEditMode, setIsLinkEditMode) {
|
|
11625
|
-
const [activeEditor, setActiveEditor] =
|
|
11626
|
-
const [isLink, setIsLink] =
|
|
12023
|
+
const [activeEditor, setActiveEditor] = useState34(editor);
|
|
12024
|
+
const [isLink, setIsLink] = useState34(false);
|
|
11627
12025
|
useEffect33(() => {
|
|
11628
12026
|
function $updateToolbar() {
|
|
11629
12027
|
const selection = $getSelection12();
|
|
@@ -11740,7 +12138,7 @@ import {
|
|
|
11740
12138
|
getDOMSelection as getDOMSelection3,
|
|
11741
12139
|
SELECTION_CHANGE_COMMAND as SELECTION_CHANGE_COMMAND3
|
|
11742
12140
|
} from "lexical";
|
|
11743
|
-
import { useCallback as
|
|
12141
|
+
import { useCallback as useCallback27, useEffect as useEffect34, useRef as useRef14, useState as useState35 } from "react";
|
|
11744
12142
|
import { createPortal as createPortal9 } from "react-dom";
|
|
11745
12143
|
|
|
11746
12144
|
// src/utils/getDOMRangeRect.ts
|
|
@@ -11819,8 +12217,8 @@ function TextFormatFloatingToolbar({
|
|
|
11819
12217
|
isSuperscript: isSuperscript2,
|
|
11820
12218
|
setIsLinkEditMode
|
|
11821
12219
|
}) {
|
|
11822
|
-
const popupCharStylesEditorRef =
|
|
11823
|
-
const insertLink =
|
|
12220
|
+
const popupCharStylesEditorRef = useRef14(null);
|
|
12221
|
+
const insertLink = useCallback27(() => {
|
|
11824
12222
|
if (!isLink) {
|
|
11825
12223
|
setIsLinkEditMode(true);
|
|
11826
12224
|
editor.dispatchCommand(TOGGLE_LINK_COMMAND4, "https://");
|
|
@@ -11861,7 +12259,7 @@ function TextFormatFloatingToolbar({
|
|
|
11861
12259
|
};
|
|
11862
12260
|
}
|
|
11863
12261
|
}, [popupCharStylesEditorRef]);
|
|
11864
|
-
const $updateTextFormatFloatingToolbar =
|
|
12262
|
+
const $updateTextFormatFloatingToolbar = useCallback27(() => {
|
|
11865
12263
|
const selection = $getSelection13();
|
|
11866
12264
|
const popupCharStylesEditorElem = popupCharStylesEditorRef.current;
|
|
11867
12265
|
const nativeSelection = getDOMSelection3(editor._window);
|
|
@@ -12075,19 +12473,19 @@ function TextFormatFloatingToolbar({
|
|
|
12075
12473
|
] });
|
|
12076
12474
|
}
|
|
12077
12475
|
function useFloatingTextFormatToolbar(editor, anchorElem, setIsLinkEditMode) {
|
|
12078
|
-
const [isText, setIsText] =
|
|
12079
|
-
const [isLink, setIsLink] =
|
|
12080
|
-
const [isBold, setIsBold] =
|
|
12081
|
-
const [isItalic, setIsItalic] =
|
|
12082
|
-
const [isUnderline, setIsUnderline] =
|
|
12083
|
-
const [isUppercase2, setIsUppercase] =
|
|
12084
|
-
const [isLowercase2, setIsLowercase] =
|
|
12085
|
-
const [isCapitalize2, setIsCapitalize] =
|
|
12086
|
-
const [isStrikethrough, setIsStrikethrough] =
|
|
12087
|
-
const [isSubscript2, setIsSubscript] =
|
|
12088
|
-
const [isSuperscript2, setIsSuperscript] =
|
|
12089
|
-
const [isCode, setIsCode] =
|
|
12090
|
-
const updatePopup =
|
|
12476
|
+
const [isText, setIsText] = useState35(false);
|
|
12477
|
+
const [isLink, setIsLink] = useState35(false);
|
|
12478
|
+
const [isBold, setIsBold] = useState35(false);
|
|
12479
|
+
const [isItalic, setIsItalic] = useState35(false);
|
|
12480
|
+
const [isUnderline, setIsUnderline] = useState35(false);
|
|
12481
|
+
const [isUppercase2, setIsUppercase] = useState35(false);
|
|
12482
|
+
const [isLowercase2, setIsLowercase] = useState35(false);
|
|
12483
|
+
const [isCapitalize2, setIsCapitalize] = useState35(false);
|
|
12484
|
+
const [isStrikethrough, setIsStrikethrough] = useState35(false);
|
|
12485
|
+
const [isSubscript2, setIsSubscript] = useState35(false);
|
|
12486
|
+
const [isSuperscript2, setIsSuperscript] = useState35(false);
|
|
12487
|
+
const [isCode, setIsCode] = useState35(false);
|
|
12488
|
+
const updatePopup = useCallback27(() => {
|
|
12091
12489
|
editor.getEditorState().read(() => {
|
|
12092
12490
|
if (editor.isComposing()) {
|
|
12093
12491
|
return;
|
|
@@ -12963,12 +13361,12 @@ import {
|
|
|
12963
13361
|
isDOMNode as isDOMNode2,
|
|
12964
13362
|
SELECTION_CHANGE_COMMAND as SELECTION_CHANGE_COMMAND4
|
|
12965
13363
|
} from "lexical";
|
|
12966
|
-
import { useCallback as
|
|
13364
|
+
import { useCallback as useCallback28, useEffect as useEffect39, useRef as useRef16, useState as useState37 } from "react";
|
|
12967
13365
|
import { createPortal as createPortal10 } from "react-dom";
|
|
12968
13366
|
|
|
12969
13367
|
// src/ui/ColorPicker.tsx
|
|
12970
13368
|
import { calculateZoomLevel as calculateZoomLevel2 } from "@lexical/utils";
|
|
12971
|
-
import { useMemo as useMemo22, useRef as
|
|
13369
|
+
import { useMemo as useMemo22, useRef as useRef15, useState as useState36 } from "react";
|
|
12972
13370
|
import { jsx as jsx43, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
12973
13371
|
var skipAddingToHistoryStack = false;
|
|
12974
13372
|
var basicColors = [
|
|
@@ -12994,11 +13392,11 @@ function ColorPicker({
|
|
|
12994
13392
|
color,
|
|
12995
13393
|
onChange
|
|
12996
13394
|
}) {
|
|
12997
|
-
const [selfColor, setSelfColor] =
|
|
12998
|
-
const [inputColor, setInputColor] =
|
|
13395
|
+
const [selfColor, setSelfColor] = useState36(transformColor("hex", color));
|
|
13396
|
+
const [inputColor, setInputColor] = useState36(
|
|
12999
13397
|
transformColor("hex", color).hex
|
|
13000
13398
|
);
|
|
13001
|
-
const innerDivRef =
|
|
13399
|
+
const innerDivRef = useRef15(null);
|
|
13002
13400
|
const saturationPosition = useMemo22(
|
|
13003
13401
|
() => ({
|
|
13004
13402
|
x: selfColor.hsv.s / 100 * WIDTH,
|
|
@@ -13108,8 +13506,8 @@ function ColorPicker({
|
|
|
13108
13506
|
);
|
|
13109
13507
|
}
|
|
13110
13508
|
function MoveWrapper({ className, style, onChange, children }) {
|
|
13111
|
-
const divRef =
|
|
13112
|
-
const draggedRef =
|
|
13509
|
+
const divRef = useRef15(null);
|
|
13510
|
+
const draggedRef = useRef15(false);
|
|
13113
13511
|
const move = (e) => {
|
|
13114
13512
|
if (divRef.current) {
|
|
13115
13513
|
const { current: div } = divRef;
|
|
@@ -13282,15 +13680,15 @@ function TableActionMenu({
|
|
|
13282
13680
|
showColorPickerModal
|
|
13283
13681
|
}) {
|
|
13284
13682
|
const [editor] = useLexicalComposerContext43();
|
|
13285
|
-
const dropDownRef =
|
|
13286
|
-
const [tableCellNode, updateTableCellNode] =
|
|
13287
|
-
const [selectionCounts, updateSelectionCounts] =
|
|
13683
|
+
const dropDownRef = useRef16(null);
|
|
13684
|
+
const [tableCellNode, updateTableCellNode] = useState37(_tableCellNode);
|
|
13685
|
+
const [selectionCounts, updateSelectionCounts] = useState37({
|
|
13288
13686
|
columns: 1,
|
|
13289
13687
|
rows: 1
|
|
13290
13688
|
});
|
|
13291
|
-
const [canMergeCells, setCanMergeCells] =
|
|
13292
|
-
const [canUnmergeCell, setCanUnmergeCell] =
|
|
13293
|
-
const [backgroundColor, setBackgroundColor] =
|
|
13689
|
+
const [canMergeCells, setCanMergeCells] = useState37(false);
|
|
13690
|
+
const [canUnmergeCell, setCanUnmergeCell] = useState37(false);
|
|
13691
|
+
const [backgroundColor, setBackgroundColor] = useState37(
|
|
13294
13692
|
() => currentCellBackgroundColor(editor) || ""
|
|
13295
13693
|
);
|
|
13296
13694
|
useEffect39(() => {
|
|
@@ -13354,7 +13752,7 @@ function TableActionMenu({
|
|
|
13354
13752
|
window.addEventListener("click", handleClickOutside);
|
|
13355
13753
|
return () => window.removeEventListener("click", handleClickOutside);
|
|
13356
13754
|
}, [setIsMenuOpen, contextRef]);
|
|
13357
|
-
const clearTableSelection =
|
|
13755
|
+
const clearTableSelection = useCallback28(() => {
|
|
13358
13756
|
editor.update(() => {
|
|
13359
13757
|
if (tableCellNode.isAttached()) {
|
|
13360
13758
|
const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
|
|
@@ -13397,7 +13795,7 @@ function TableActionMenu({
|
|
|
13397
13795
|
$unmergeCell();
|
|
13398
13796
|
});
|
|
13399
13797
|
};
|
|
13400
|
-
const insertTableRowAtSelection =
|
|
13798
|
+
const insertTableRowAtSelection = useCallback28(
|
|
13401
13799
|
(shouldInsertAfter) => {
|
|
13402
13800
|
editor.update(() => {
|
|
13403
13801
|
for (let i = 0; i < selectionCounts.rows; i++) {
|
|
@@ -13408,7 +13806,7 @@ function TableActionMenu({
|
|
|
13408
13806
|
},
|
|
13409
13807
|
[editor, onClose, selectionCounts.rows]
|
|
13410
13808
|
);
|
|
13411
|
-
const insertTableColumnAtSelection =
|
|
13809
|
+
const insertTableColumnAtSelection = useCallback28(
|
|
13412
13810
|
(shouldInsertAfter) => {
|
|
13413
13811
|
editor.update(() => {
|
|
13414
13812
|
for (let i = 0; i < selectionCounts.columns; i++) {
|
|
@@ -13419,13 +13817,13 @@ function TableActionMenu({
|
|
|
13419
13817
|
},
|
|
13420
13818
|
[editor, onClose, selectionCounts.columns]
|
|
13421
13819
|
);
|
|
13422
|
-
const deleteTableRowAtSelection =
|
|
13820
|
+
const deleteTableRowAtSelection = useCallback28(() => {
|
|
13423
13821
|
editor.update(() => {
|
|
13424
13822
|
$deleteTableRowAtSelection();
|
|
13425
13823
|
onClose();
|
|
13426
13824
|
});
|
|
13427
13825
|
}, [editor, onClose]);
|
|
13428
|
-
const deleteTableAtSelection =
|
|
13826
|
+
const deleteTableAtSelection = useCallback28(() => {
|
|
13429
13827
|
editor.update(() => {
|
|
13430
13828
|
const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
|
|
13431
13829
|
tableNode.remove();
|
|
@@ -13433,13 +13831,13 @@ function TableActionMenu({
|
|
|
13433
13831
|
onClose();
|
|
13434
13832
|
});
|
|
13435
13833
|
}, [editor, tableCellNode, clearTableSelection, onClose]);
|
|
13436
|
-
const deleteTableColumnAtSelection =
|
|
13834
|
+
const deleteTableColumnAtSelection = useCallback28(() => {
|
|
13437
13835
|
editor.update(() => {
|
|
13438
13836
|
$deleteTableColumnAtSelection();
|
|
13439
13837
|
onClose();
|
|
13440
13838
|
});
|
|
13441
13839
|
}, [editor, onClose]);
|
|
13442
|
-
const toggleTableRowIsHeader =
|
|
13840
|
+
const toggleTableRowIsHeader = useCallback28(() => {
|
|
13443
13841
|
editor.update(() => {
|
|
13444
13842
|
const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
|
|
13445
13843
|
const tableRowIndex = $getTableRowIndexFromTableCellNode(tableCellNode);
|
|
@@ -13460,7 +13858,7 @@ function TableActionMenu({
|
|
|
13460
13858
|
onClose();
|
|
13461
13859
|
});
|
|
13462
13860
|
}, [editor, tableCellNode, clearTableSelection, onClose]);
|
|
13463
|
-
const toggleTableColumnIsHeader =
|
|
13861
|
+
const toggleTableColumnIsHeader = useCallback28(() => {
|
|
13464
13862
|
editor.update(() => {
|
|
13465
13863
|
const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
|
|
13466
13864
|
const tableColumnIndex = $getTableColumnIndexFromTableCellNode(tableCellNode);
|
|
@@ -13481,7 +13879,7 @@ function TableActionMenu({
|
|
|
13481
13879
|
onClose();
|
|
13482
13880
|
});
|
|
13483
13881
|
}, [editor, tableCellNode, clearTableSelection, onClose]);
|
|
13484
|
-
const toggleRowStriping =
|
|
13882
|
+
const toggleRowStriping = useCallback28(() => {
|
|
13485
13883
|
editor.update(() => {
|
|
13486
13884
|
if (tableCellNode.isAttached()) {
|
|
13487
13885
|
const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
|
|
@@ -13493,7 +13891,7 @@ function TableActionMenu({
|
|
|
13493
13891
|
onClose();
|
|
13494
13892
|
});
|
|
13495
13893
|
}, [editor, tableCellNode, clearTableSelection, onClose]);
|
|
13496
|
-
const toggleFirstRowFreeze =
|
|
13894
|
+
const toggleFirstRowFreeze = useCallback28(() => {
|
|
13497
13895
|
editor.update(() => {
|
|
13498
13896
|
if (tableCellNode.isAttached()) {
|
|
13499
13897
|
const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
|
|
@@ -13505,7 +13903,7 @@ function TableActionMenu({
|
|
|
13505
13903
|
onClose();
|
|
13506
13904
|
});
|
|
13507
13905
|
}, [editor, tableCellNode, clearTableSelection, onClose]);
|
|
13508
|
-
const toggleFirstColumnFreeze =
|
|
13906
|
+
const toggleFirstColumnFreeze = useCallback28(() => {
|
|
13509
13907
|
editor.update(() => {
|
|
13510
13908
|
if (tableCellNode.isAttached()) {
|
|
13511
13909
|
const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
|
|
@@ -13519,7 +13917,7 @@ function TableActionMenu({
|
|
|
13519
13917
|
onClose();
|
|
13520
13918
|
});
|
|
13521
13919
|
}, [editor, tableCellNode, clearTableSelection, onClose]);
|
|
13522
|
-
const handleCellBackgroundColor =
|
|
13920
|
+
const handleCellBackgroundColor = useCallback28(
|
|
13523
13921
|
(value) => {
|
|
13524
13922
|
editor.update(() => {
|
|
13525
13923
|
const selection = $getSelection17();
|
|
@@ -13832,14 +14230,14 @@ function TableCellActionMenuContainer({
|
|
|
13832
14230
|
cellMerge
|
|
13833
14231
|
}) {
|
|
13834
14232
|
const [editor] = useLexicalComposerContext43();
|
|
13835
|
-
const menuButtonRef =
|
|
13836
|
-
const menuRootRef =
|
|
13837
|
-
const [isMenuOpen, setIsMenuOpen] =
|
|
13838
|
-
const [tableCellNode, setTableMenuCellNode] =
|
|
14233
|
+
const menuButtonRef = useRef16(null);
|
|
14234
|
+
const menuRootRef = useRef16(null);
|
|
14235
|
+
const [isMenuOpen, setIsMenuOpen] = useState37(false);
|
|
14236
|
+
const [tableCellNode, setTableMenuCellNode] = useState37(
|
|
13839
14237
|
null
|
|
13840
14238
|
);
|
|
13841
14239
|
const [colorPickerModal, showColorPickerModal] = useModal();
|
|
13842
|
-
const checkTableCellOverflow =
|
|
14240
|
+
const checkTableCellOverflow = useCallback28(
|
|
13843
14241
|
(tableCellParentNodeDOM) => {
|
|
13844
14242
|
const scrollableContainer = tableCellParentNodeDOM.closest(
|
|
13845
14243
|
".PlaygroundEditorTheme__tableScrollableWrapper"
|
|
@@ -13857,7 +14255,7 @@ function TableCellActionMenuContainer({
|
|
|
13857
14255
|
},
|
|
13858
14256
|
[]
|
|
13859
14257
|
);
|
|
13860
|
-
const $moveMenu =
|
|
14258
|
+
const $moveMenu = useCallback28(() => {
|
|
13861
14259
|
const menu = menuButtonRef.current;
|
|
13862
14260
|
const selection = $getSelection17();
|
|
13863
14261
|
const nativeSelection = getDOMSelection4(editor._window);
|
|
@@ -13984,7 +14382,7 @@ function TableCellActionMenuContainer({
|
|
|
13984
14382
|
() => clearTimeout(timeoutId)
|
|
13985
14383
|
);
|
|
13986
14384
|
});
|
|
13987
|
-
const prevTableCellDOM =
|
|
14385
|
+
const prevTableCellDOM = useRef16(tableCellNode);
|
|
13988
14386
|
useEffect39(() => {
|
|
13989
14387
|
if (prevTableCellDOM.current !== tableCellNode) {
|
|
13990
14388
|
setIsMenuOpen(false);
|
|
@@ -14056,11 +14454,11 @@ import {
|
|
|
14056
14454
|
SKIP_SCROLL_INTO_VIEW_TAG
|
|
14057
14455
|
} from "lexical";
|
|
14058
14456
|
import {
|
|
14059
|
-
useCallback as
|
|
14457
|
+
useCallback as useCallback29,
|
|
14060
14458
|
useEffect as useEffect40,
|
|
14061
14459
|
useMemo as useMemo23,
|
|
14062
|
-
useRef as
|
|
14063
|
-
useState as
|
|
14460
|
+
useRef as useRef17,
|
|
14461
|
+
useState as useState38
|
|
14064
14462
|
} from "react";
|
|
14065
14463
|
import { createPortal as createPortal11 } from "react-dom";
|
|
14066
14464
|
import { Fragment as Fragment16, jsx as jsx45, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
@@ -14068,16 +14466,16 @@ var MIN_ROW_HEIGHT = 33;
|
|
|
14068
14466
|
var MIN_COLUMN_WIDTH = 92;
|
|
14069
14467
|
var ACTIVE_RESIZER_COLOR = "#76b6ff";
|
|
14070
14468
|
function TableCellResizer({ editor }) {
|
|
14071
|
-
const targetRef =
|
|
14072
|
-
const resizerRef =
|
|
14073
|
-
const tableRectRef =
|
|
14074
|
-
const [hasTable, setHasTable] =
|
|
14075
|
-
const pointerStartPosRef =
|
|
14076
|
-
const [pointerCurrentPos, updatePointerCurrentPos] =
|
|
14077
|
-
const [activeCell, updateActiveCell] =
|
|
14078
|
-
const [draggingDirection, updateDraggingDirection] =
|
|
14079
|
-
const [hoveredDirection, updateHoveredDirection] =
|
|
14080
|
-
const resetState =
|
|
14469
|
+
const targetRef = useRef17(null);
|
|
14470
|
+
const resizerRef = useRef17(null);
|
|
14471
|
+
const tableRectRef = useRef17(null);
|
|
14472
|
+
const [hasTable, setHasTable] = useState38(false);
|
|
14473
|
+
const pointerStartPosRef = useRef17(null);
|
|
14474
|
+
const [pointerCurrentPos, updatePointerCurrentPos] = useState38(null);
|
|
14475
|
+
const [activeCell, updateActiveCell] = useState38(null);
|
|
14476
|
+
const [draggingDirection, updateDraggingDirection] = useState38(null);
|
|
14477
|
+
const [hoveredDirection, updateHoveredDirection] = useState38(null);
|
|
14478
|
+
const resetState = useCallback29(() => {
|
|
14081
14479
|
updateActiveCell(null);
|
|
14082
14480
|
targetRef.current = null;
|
|
14083
14481
|
updateDraggingDirection(null);
|
|
@@ -14188,7 +14586,7 @@ function TableCellResizer({ editor }) {
|
|
|
14188
14586
|
}
|
|
14189
14587
|
return false;
|
|
14190
14588
|
};
|
|
14191
|
-
const updateRowHeight =
|
|
14589
|
+
const updateRowHeight = useCallback29(
|
|
14192
14590
|
(heightChange) => {
|
|
14193
14591
|
if (!activeCell) {
|
|
14194
14592
|
throw new Error("TableCellResizer: Expected active cell.");
|
|
@@ -14241,7 +14639,7 @@ function TableCellResizer({ editor }) {
|
|
|
14241
14639
|
}
|
|
14242
14640
|
}
|
|
14243
14641
|
};
|
|
14244
|
-
const updateColumnWidth =
|
|
14642
|
+
const updateColumnWidth = useCallback29(
|
|
14245
14643
|
(widthChange) => {
|
|
14246
14644
|
if (!activeCell) {
|
|
14247
14645
|
throw new Error("TableCellResizer: Expected active cell.");
|
|
@@ -14280,7 +14678,7 @@ function TableCellResizer({ editor }) {
|
|
|
14280
14678
|
},
|
|
14281
14679
|
[activeCell, editor]
|
|
14282
14680
|
);
|
|
14283
|
-
const pointerUpHandler =
|
|
14681
|
+
const pointerUpHandler = useCallback29(
|
|
14284
14682
|
(direction) => {
|
|
14285
14683
|
const handler = (event) => {
|
|
14286
14684
|
event.preventDefault();
|
|
@@ -14309,7 +14707,7 @@ function TableCellResizer({ editor }) {
|
|
|
14309
14707
|
},
|
|
14310
14708
|
[activeCell, resetState, updateColumnWidth, updateRowHeight]
|
|
14311
14709
|
);
|
|
14312
|
-
const toggleResize =
|
|
14710
|
+
const toggleResize = useCallback29(
|
|
14313
14711
|
(direction) => (event) => {
|
|
14314
14712
|
event.preventDefault();
|
|
14315
14713
|
event.stopPropagation();
|
|
@@ -14326,7 +14724,7 @@ function TableCellResizer({ editor }) {
|
|
|
14326
14724
|
},
|
|
14327
14725
|
[activeCell, pointerUpHandler]
|
|
14328
14726
|
);
|
|
14329
|
-
const getResizers =
|
|
14727
|
+
const getResizers = useCallback29(() => {
|
|
14330
14728
|
if (activeCell) {
|
|
14331
14729
|
const { height, width, top, left } = activeCell.elem.getBoundingClientRect();
|
|
14332
14730
|
const zoom = calculateZoomLevel3(activeCell.elem);
|
|
@@ -14384,7 +14782,7 @@ function TableCellResizer({ editor }) {
|
|
|
14384
14782
|
top: null
|
|
14385
14783
|
};
|
|
14386
14784
|
}, [activeCell, draggingDirection, hoveredDirection, pointerCurrentPos]);
|
|
14387
|
-
const handlePointerEnter =
|
|
14785
|
+
const handlePointerEnter = useCallback29(
|
|
14388
14786
|
(direction) => () => {
|
|
14389
14787
|
if (!draggingDirection) {
|
|
14390
14788
|
updateHoveredDirection(direction);
|
|
@@ -14392,7 +14790,7 @@ function TableCellResizer({ editor }) {
|
|
|
14392
14790
|
},
|
|
14393
14791
|
[draggingDirection]
|
|
14394
14792
|
);
|
|
14395
|
-
const handlePointerLeave =
|
|
14793
|
+
const handlePointerLeave = useCallback29(() => {
|
|
14396
14794
|
if (!draggingDirection) {
|
|
14397
14795
|
updateHoveredDirection(null);
|
|
14398
14796
|
}
|
|
@@ -14458,7 +14856,7 @@ import {
|
|
|
14458
14856
|
$getSiblingCaret as $getSiblingCaret2,
|
|
14459
14857
|
isHTMLElement as isHTMLElement5
|
|
14460
14858
|
} from "lexical";
|
|
14461
|
-
import { useEffect as useEffect41, useRef as
|
|
14859
|
+
import { useEffect as useEffect41, useRef as useRef18, useState as useState39 } from "react";
|
|
14462
14860
|
import { createPortal as createPortal12 } from "react-dom";
|
|
14463
14861
|
|
|
14464
14862
|
// src/utils/getThemeSelector.ts
|
|
@@ -14562,31 +14960,31 @@ function TableHoverActionsV2({
|
|
|
14562
14960
|
}) {
|
|
14563
14961
|
const [editor, { getTheme }] = useLexicalComposerContext45();
|
|
14564
14962
|
const isEditable = useLexicalEditable9();
|
|
14565
|
-
const [isVisible, setIsVisible] =
|
|
14566
|
-
const [isLeftVisible, setIsLeftVisible] =
|
|
14567
|
-
const virtualRef =
|
|
14963
|
+
const [isVisible, setIsVisible] = useState39(false);
|
|
14964
|
+
const [isLeftVisible, setIsLeftVisible] = useState39(false);
|
|
14965
|
+
const virtualRef = useRef18({
|
|
14568
14966
|
getBoundingClientRect: () => new DOMRect()
|
|
14569
14967
|
});
|
|
14570
|
-
const leftVirtualRef =
|
|
14968
|
+
const leftVirtualRef = useRef18({
|
|
14571
14969
|
getBoundingClientRect: () => new DOMRect()
|
|
14572
14970
|
});
|
|
14573
|
-
const floatingElemRef =
|
|
14574
|
-
const leftFloatingElemRef =
|
|
14575
|
-
const dragHandleRef =
|
|
14576
|
-
const hoveredLeftCellRef =
|
|
14577
|
-
const hoveredTopCellRef =
|
|
14578
|
-
const handleMouseLeaveRef =
|
|
14971
|
+
const floatingElemRef = useRef18(null);
|
|
14972
|
+
const leftFloatingElemRef = useRef18(null);
|
|
14973
|
+
const dragHandleRef = useRef18(null);
|
|
14974
|
+
const hoveredLeftCellRef = useRef18(null);
|
|
14975
|
+
const hoveredTopCellRef = useRef18(null);
|
|
14976
|
+
const handleMouseLeaveRef = useRef18(
|
|
14579
14977
|
null
|
|
14580
14978
|
);
|
|
14581
|
-
const dropIndicatorCleanupRef =
|
|
14582
|
-
const [hoveredTable, setHoveredTable] =
|
|
14979
|
+
const dropIndicatorCleanupRef = useRef18([]);
|
|
14980
|
+
const [hoveredTable, setHoveredTable] = useState39(
|
|
14583
14981
|
null
|
|
14584
14982
|
);
|
|
14585
|
-
const [hoveredColumnIndex, setHoveredColumnIndex] =
|
|
14983
|
+
const [hoveredColumnIndex, setHoveredColumnIndex] = useState39(
|
|
14586
14984
|
null
|
|
14587
14985
|
);
|
|
14588
|
-
const [canReorder, setCanReorder] =
|
|
14589
|
-
const [dropIndicatorState, setDropIndicatorState] =
|
|
14986
|
+
const [canReorder, setCanReorder] = useState39(false);
|
|
14987
|
+
const [dropIndicatorState, setDropIndicatorState] = useState39(null);
|
|
14590
14988
|
const { refs, floatingStyles, update } = useFloating({
|
|
14591
14989
|
middleware: [
|
|
14592
14990
|
offset({ mainAxis: -TOP_BUTTON_OVERHANG }),
|
|
@@ -15011,7 +15409,7 @@ function TableHoverActionsV2Plugin({
|
|
|
15011
15409
|
// src/plugins/TableOfContentsPlugin/index.tsx
|
|
15012
15410
|
import { useLexicalComposerContext as useLexicalComposerContext46 } from "@lexical/react/LexicalComposerContext";
|
|
15013
15411
|
import { TableOfContentsPlugin as LexicalTableOfContentsPlugin } from "@lexical/react/LexicalTableOfContentsPlugin";
|
|
15014
|
-
import { useEffect as useEffect42, useRef as
|
|
15412
|
+
import { useEffect as useEffect42, useRef as useRef19, useState as useState40 } from "react";
|
|
15015
15413
|
import { jsx as jsx47, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
15016
15414
|
var MARGIN_ABOVE_EDITOR = 624;
|
|
15017
15415
|
var HEADING_WIDTH = 9;
|
|
@@ -15037,8 +15435,8 @@ function isHeadingBelowTheTopOfThePage(element) {
|
|
|
15037
15435
|
function TableOfContentsList({
|
|
15038
15436
|
tableOfContents
|
|
15039
15437
|
}) {
|
|
15040
|
-
const [selectedKey, setSelectedKey] =
|
|
15041
|
-
const selectedIndex =
|
|
15438
|
+
const [selectedKey, setSelectedKey] = useState40("");
|
|
15439
|
+
const selectedIndex = useRef19(0);
|
|
15042
15440
|
const [editor] = useLexicalComposerContext46();
|
|
15043
15441
|
function scrollToNode(key, currIndex) {
|
|
15044
15442
|
editor.getEditorState().read(() => {
|
|
@@ -15303,7 +15701,7 @@ import {
|
|
|
15303
15701
|
SKIP_SELECTION_FOCUS_TAG as SKIP_SELECTION_FOCUS_TAG2,
|
|
15304
15702
|
UNDO_COMMAND as UNDO_COMMAND2
|
|
15305
15703
|
} from "lexical";
|
|
15306
|
-
import { useCallback as
|
|
15704
|
+
import { useCallback as useCallback30, useEffect as useEffect45, useState as useState42 } from "react";
|
|
15307
15705
|
|
|
15308
15706
|
// src/ui/DropdownColorPicker.tsx
|
|
15309
15707
|
import { jsx as jsx48 } from "react/jsx-runtime";
|
|
@@ -15737,7 +16135,7 @@ function FontDropDown({
|
|
|
15737
16135
|
style,
|
|
15738
16136
|
disabled = false
|
|
15739
16137
|
}) {
|
|
15740
|
-
const handleClick =
|
|
16138
|
+
const handleClick = useCallback30(
|
|
15741
16139
|
(option) => {
|
|
15742
16140
|
editor.update(() => {
|
|
15743
16141
|
$addUpdateTag3(SKIP_SELECTION_FOCUS_TAG2);
|
|
@@ -15943,11 +16341,11 @@ function ToolbarPlugin({
|
|
|
15943
16341
|
setActiveEditor,
|
|
15944
16342
|
setIsLinkEditMode
|
|
15945
16343
|
}) {
|
|
15946
|
-
const [selectedElementKey, setSelectedElementKey] =
|
|
16344
|
+
const [selectedElementKey, setSelectedElementKey] = useState42(
|
|
15947
16345
|
null
|
|
15948
16346
|
);
|
|
15949
16347
|
const [modal, showModal] = useModal();
|
|
15950
|
-
const [isEditable, setIsEditable] =
|
|
16348
|
+
const [isEditable, setIsEditable] = useState42(() => editor.isEditable());
|
|
15951
16349
|
const { toolbarState, updateToolbarState } = useToolbarState();
|
|
15952
16350
|
const dispatchToolbarCommand = (command, payload = void 0, skipRefocus = false) => {
|
|
15953
16351
|
activeEditor.update(() => {
|
|
@@ -15958,7 +16356,7 @@ function ToolbarPlugin({
|
|
|
15958
16356
|
});
|
|
15959
16357
|
};
|
|
15960
16358
|
const dispatchFormatTextCommand = (payload, skipRefocus = false) => dispatchToolbarCommand(FORMAT_TEXT_COMMAND3, payload, skipRefocus);
|
|
15961
|
-
const $handleHeadingNode =
|
|
16359
|
+
const $handleHeadingNode = useCallback30(
|
|
15962
16360
|
(selectedElement) => {
|
|
15963
16361
|
const type = $isHeadingNode2(selectedElement) ? selectedElement.getTag() : selectedElement.getType();
|
|
15964
16362
|
if (type in blockTypeToBlockName) {
|
|
@@ -15973,7 +16371,7 @@ function ToolbarPlugin({
|
|
|
15973
16371
|
const {
|
|
15974
16372
|
settings: { isCodeHighlighted, isCodeShiki }
|
|
15975
16373
|
} = useSettings();
|
|
15976
|
-
const $handleCodeNode =
|
|
16374
|
+
const $handleCodeNode = useCallback30(
|
|
15977
16375
|
(element) => {
|
|
15978
16376
|
if ($isCodeNode6(element)) {
|
|
15979
16377
|
const language = element.getLanguage();
|
|
@@ -15989,7 +16387,7 @@ function ToolbarPlugin({
|
|
|
15989
16387
|
},
|
|
15990
16388
|
[updateToolbarState, isCodeHighlighted, isCodeShiki]
|
|
15991
16389
|
);
|
|
15992
|
-
const $updateToolbar =
|
|
16390
|
+
const $updateToolbar = useCallback30(() => {
|
|
15993
16391
|
const selection = $getSelection18();
|
|
15994
16392
|
if ($isRangeSelection16(selection)) {
|
|
15995
16393
|
if (activeEditor !== editor && $isEditorIsNestedEditor(activeEditor)) {
|
|
@@ -16162,7 +16560,7 @@ function ToolbarPlugin({
|
|
|
16162
16560
|
)
|
|
16163
16561
|
);
|
|
16164
16562
|
}, [$updateToolbar, activeEditor, editor, updateToolbarState]);
|
|
16165
|
-
const applyStyleText =
|
|
16563
|
+
const applyStyleText = useCallback30(
|
|
16166
16564
|
(styles, skipHistoryStack, skipRefocus = false) => {
|
|
16167
16565
|
activeEditor.update(
|
|
16168
16566
|
() => {
|
|
@@ -16179,13 +16577,13 @@ function ToolbarPlugin({
|
|
|
16179
16577
|
},
|
|
16180
16578
|
[activeEditor]
|
|
16181
16579
|
);
|
|
16182
|
-
const onFontColorSelect =
|
|
16580
|
+
const onFontColorSelect = useCallback30(
|
|
16183
16581
|
(value, skipHistoryStack, skipRefocus) => {
|
|
16184
16582
|
applyStyleText({ color: value }, skipHistoryStack, skipRefocus);
|
|
16185
16583
|
},
|
|
16186
16584
|
[applyStyleText]
|
|
16187
16585
|
);
|
|
16188
|
-
const onBgColorSelect =
|
|
16586
|
+
const onBgColorSelect = useCallback30(
|
|
16189
16587
|
(value, skipHistoryStack, skipRefocus) => {
|
|
16190
16588
|
applyStyleText(
|
|
16191
16589
|
{ "background-color": value },
|
|
@@ -16195,7 +16593,7 @@ function ToolbarPlugin({
|
|
|
16195
16593
|
},
|
|
16196
16594
|
[applyStyleText]
|
|
16197
16595
|
);
|
|
16198
|
-
const insertLink =
|
|
16596
|
+
const insertLink = useCallback30(() => {
|
|
16199
16597
|
if (!toolbarState.isLink) {
|
|
16200
16598
|
setIsLinkEditMode(true);
|
|
16201
16599
|
activeEditor.dispatchCommand(
|
|
@@ -16207,7 +16605,7 @@ function ToolbarPlugin({
|
|
|
16207
16605
|
activeEditor.dispatchCommand(TOGGLE_LINK_COMMAND6, null);
|
|
16208
16606
|
}
|
|
16209
16607
|
}, [activeEditor, setIsLinkEditMode, toolbarState.isLink]);
|
|
16210
|
-
const onCodeLanguageSelect =
|
|
16608
|
+
const onCodeLanguageSelect = useCallback30(
|
|
16211
16609
|
(value) => {
|
|
16212
16610
|
activeEditor.update(() => {
|
|
16213
16611
|
$addUpdateTag3(SKIP_SELECTION_FOCUS_TAG2);
|
|
@@ -16221,7 +16619,7 @@ function ToolbarPlugin({
|
|
|
16221
16619
|
},
|
|
16222
16620
|
[activeEditor, selectedElementKey]
|
|
16223
16621
|
);
|
|
16224
|
-
const onCodeThemeSelect =
|
|
16622
|
+
const onCodeThemeSelect = useCallback30(
|
|
16225
16623
|
(value) => {
|
|
16226
16624
|
activeEditor.update(() => {
|
|
16227
16625
|
if (selectedElementKey !== null) {
|
|
@@ -16955,11 +17353,11 @@ function Editor({ placeholder: placeholderProp, maxLength }) {
|
|
|
16955
17353
|
} = useSettings();
|
|
16956
17354
|
const isEditable = useLexicalEditable10();
|
|
16957
17355
|
const placeholder = placeholderProp ?? (isRichText ? "Enter some rich text..." : "Enter some plain text...");
|
|
16958
|
-
const [floatingAnchorElem, setFloatingAnchorElem] =
|
|
16959
|
-
const [isSmallWidthViewport, setIsSmallWidthViewport] =
|
|
17356
|
+
const [floatingAnchorElem, setFloatingAnchorElem] = useState43(null);
|
|
17357
|
+
const [isSmallWidthViewport, setIsSmallWidthViewport] = useState43(false);
|
|
16960
17358
|
const [editor] = useLexicalComposerContext49();
|
|
16961
|
-
const [activeEditor, setActiveEditor] =
|
|
16962
|
-
const [isLinkEditMode, setIsLinkEditMode] =
|
|
17359
|
+
const [activeEditor, setActiveEditor] = useState43(editor);
|
|
17360
|
+
const [isLinkEditMode, setIsLinkEditMode] = useState43(false);
|
|
16963
17361
|
const onRef = (_floatingAnchorElem) => {
|
|
16964
17362
|
if (_floatingAnchorElem !== null) {
|
|
16965
17363
|
setFloatingAnchorElem(_floatingAnchorElem);
|
|
@@ -17289,9 +17687,9 @@ function HtmlPlugin({
|
|
|
17289
17687
|
debounceMs = 300
|
|
17290
17688
|
}) {
|
|
17291
17689
|
const [editor] = useLexicalComposerContext50();
|
|
17292
|
-
const lastSyncedValue =
|
|
17293
|
-
const hasUserEdited =
|
|
17294
|
-
const debounceTimer =
|
|
17690
|
+
const lastSyncedValue = useRef20(null);
|
|
17691
|
+
const hasUserEdited = useRef20(false);
|
|
17692
|
+
const debounceTimer = useRef20(null);
|
|
17295
17693
|
useEffect48(() => {
|
|
17296
17694
|
return editor.registerCommand(
|
|
17297
17695
|
FOCUS_COMMAND2,
|
|
@@ -17341,7 +17739,7 @@ function HtmlPlugin({
|
|
|
17341
17739
|
{ tag: "historic" }
|
|
17342
17740
|
);
|
|
17343
17741
|
}, [editor, value]);
|
|
17344
|
-
const handleChange =
|
|
17742
|
+
const handleChange = useCallback31(
|
|
17345
17743
|
(_editorState, _editor, tags) => {
|
|
17346
17744
|
if (!tags.has("historic")) {
|
|
17347
17745
|
hasUserEdited.current = true;
|
|
@@ -17392,7 +17790,7 @@ function LexicalEditor20({
|
|
|
17392
17790
|
readOnly,
|
|
17393
17791
|
maxLength
|
|
17394
17792
|
}) {
|
|
17395
|
-
const [isFullscreen, setIsFullscreen] =
|
|
17793
|
+
const [isFullscreen, setIsFullscreen] = useState44(false);
|
|
17396
17794
|
const initialConfig = {
|
|
17397
17795
|
namespace: "LexicalEditor",
|
|
17398
17796
|
nodes: [...PlaygroundNodes_default],
|
|
@@ -17421,7 +17819,7 @@ function LexicalEditor20({
|
|
|
17421
17819
|
document.addEventListener("keydown", handleEsc);
|
|
17422
17820
|
return () => document.removeEventListener("keydown", handleEsc);
|
|
17423
17821
|
}, [isFullscreen]);
|
|
17424
|
-
const toggleFullscreen =
|
|
17822
|
+
const toggleFullscreen = useCallback31(
|
|
17425
17823
|
() => setIsFullscreen((f) => !f),
|
|
17426
17824
|
[]
|
|
17427
17825
|
);
|