blixify-ui-web 1.2.144 → 1.2.145
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.
|
@@ -40,7 +40,7 @@ interface Props {
|
|
|
40
40
|
/**
|
|
41
41
|
* `"sm"` draws the text at 14px on every screen. Default is 14px on phones
|
|
42
42
|
* and 16px from md up for MarkdownStatic, and 16px everywhere for the editor.
|
|
43
|
-
* The editor keeps a real 16px font on phones and is
|
|
43
|
+
* The editor keeps a real 16px font on phones and is scaled to 87.5%, so it
|
|
44
44
|
* looks 14px while iOS Safari still sees 16px and does not zoom on focus.
|
|
45
45
|
*/
|
|
46
46
|
textSize?: "sm";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/input/markdown/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/input/markdown/index.tsx"],"names":[],"mappings":"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"}
|
|
@@ -85,6 +85,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
85
85
|
exports.MarkdownInput = exports.MarkdownStatic = exports.handleResolveInheritedView = exports.handleParseEmbedView = void 0;
|
|
86
86
|
var solid_1 = require("@heroicons/react/20/solid");
|
|
87
87
|
var PhotoIcon_1 = __importDefault(require("@heroicons/react/24/outline/PhotoIcon"));
|
|
88
|
+
var BoldIcon_1 = __importDefault(require("@heroicons/react/24/outline/BoldIcon"));
|
|
89
|
+
var ItalicIcon_1 = __importDefault(require("@heroicons/react/24/outline/ItalicIcon"));
|
|
90
|
+
var UnderlineIcon_1 = __importDefault(require("@heroicons/react/24/outline/UnderlineIcon"));
|
|
91
|
+
var StrikethroughIcon_1 = __importDefault(require("@heroicons/react/24/outline/StrikethroughIcon"));
|
|
92
|
+
var CodeBracketIcon_1 = __importDefault(require("@heroicons/react/24/outline/CodeBracketIcon"));
|
|
93
|
+
var LinkIcon_1 = __importDefault(require("@heroicons/react/24/outline/LinkIcon"));
|
|
88
94
|
var QuestionMarkCircleIcon_1 = __importDefault(require("@heroicons/react/24/solid/QuestionMarkCircleIcon"));
|
|
89
95
|
var TableCellsIcon_1 = __importDefault(require("@heroicons/react/24/solid/TableCellsIcon"));
|
|
90
96
|
var core_1 = require("@tiptap/core");
|
|
@@ -1333,6 +1339,11 @@ var MarkdownInputContent = function (_a) {
|
|
|
1333
1339
|
range: null,
|
|
1334
1340
|
position: null,
|
|
1335
1341
|
}), suggestionState = _g[0], setSuggestionState = _g[1];
|
|
1342
|
+
// INFO: where the selection toolbar sits, in viewport px, or null when hidden
|
|
1343
|
+
var _h = (0, react_2.useState)(null), selectionToolbar = _h[0], setSelectionToolbar = _h[1];
|
|
1344
|
+
// INFO: the url being typed for a link, or null when the link field is closed
|
|
1345
|
+
var _j = (0, react_2.useState)(null), linkDraft = _j[0], setLinkDraft = _j[1];
|
|
1346
|
+
var selectionToolbarRef = (0, react_2.useRef)(null);
|
|
1336
1347
|
var isInternalUpdateRef = (0, react_2.useRef)(false);
|
|
1337
1348
|
var isHeicFile = function (file) {
|
|
1338
1349
|
var fileName = file.name.toLowerCase();
|
|
@@ -1705,6 +1716,28 @@ var MarkdownInputContent = function (_a) {
|
|
|
1705
1716
|
};
|
|
1706
1717
|
input.click();
|
|
1707
1718
|
}, [updatePendingImages]);
|
|
1719
|
+
// INFO: a scaled editor keeps its unscaled height in the layout, so the
|
|
1720
|
+
// empty band below it is pulled back with a negative margin — see index.css
|
|
1721
|
+
(0, react_2.useEffect)(function () {
|
|
1722
|
+
if (textSize !== "sm" || !editor)
|
|
1723
|
+
return;
|
|
1724
|
+
var dom = editor.view.dom;
|
|
1725
|
+
var phoneQuery = window.matchMedia("(max-width: 767px)");
|
|
1726
|
+
var handleFitHeight = function () {
|
|
1727
|
+
dom.style.marginBottom = phoneQuery.matches
|
|
1728
|
+
? "-".concat(dom.offsetHeight * 0.125, "px")
|
|
1729
|
+
: "";
|
|
1730
|
+
};
|
|
1731
|
+
handleFitHeight();
|
|
1732
|
+
var observer = new ResizeObserver(handleFitHeight);
|
|
1733
|
+
observer.observe(dom);
|
|
1734
|
+
phoneQuery.addEventListener("change", handleFitHeight);
|
|
1735
|
+
return function () {
|
|
1736
|
+
observer.disconnect();
|
|
1737
|
+
phoneQuery.removeEventListener("change", handleFitHeight);
|
|
1738
|
+
dom.style.marginBottom = "";
|
|
1739
|
+
};
|
|
1740
|
+
}, [editor, textSize]);
|
|
1708
1741
|
(0, react_2.useEffect)(function () {
|
|
1709
1742
|
if (editor) {
|
|
1710
1743
|
editorRef.current = editor;
|
|
@@ -1994,6 +2027,69 @@ var MarkdownInputContent = function (_a) {
|
|
|
1994
2027
|
editor.off("selectionUpdate", handleSelectionUpdate);
|
|
1995
2028
|
};
|
|
1996
2029
|
}, [editor, readOnly, disabled, suggestionState.show]);
|
|
2030
|
+
// INFO: borderless mode has no static toolbar, so formatting is offered on
|
|
2031
|
+
// the selection instead. Fixed to the viewport, so it does not depend on
|
|
2032
|
+
// which ancestor the host has positioned.
|
|
2033
|
+
(0, react_2.useEffect)(function () {
|
|
2034
|
+
if (!editor || !borderless || readOnly || disabled)
|
|
2035
|
+
return;
|
|
2036
|
+
var handlePlaceToolbar = function () {
|
|
2037
|
+
var _a;
|
|
2038
|
+
var state = editor.state, view = editor.view;
|
|
2039
|
+
var selection = state.selection;
|
|
2040
|
+
// INFO: the link field takes focus from the editor, and a phone keyboard
|
|
2041
|
+
// opening fires resize — neither should close the toolbar mid-typing
|
|
2042
|
+
var toolbarFocused = !!((_a = selectionToolbarRef.current) === null || _a === void 0 ? void 0 : _a.contains(document.activeElement));
|
|
2043
|
+
if (selection.empty ||
|
|
2044
|
+
selection instanceof state_1.NodeSelection ||
|
|
2045
|
+
editor.isActive("codeBlock") ||
|
|
2046
|
+
(!view.hasFocus() && !toolbarFocused)) {
|
|
2047
|
+
setSelectionToolbar(null);
|
|
2048
|
+
setLinkDraft(null);
|
|
2049
|
+
return;
|
|
2050
|
+
}
|
|
2051
|
+
var start = view.coordsAtPos(selection.from);
|
|
2052
|
+
var end = view.coordsAtPos(selection.to);
|
|
2053
|
+
var top = Math.min(start.top, end.top);
|
|
2054
|
+
var center = (start.left + end.left) / 2;
|
|
2055
|
+
setSelectionToolbar({
|
|
2056
|
+
top: top > 56 ? top - 48 : Math.max(start.bottom, end.bottom) + 8,
|
|
2057
|
+
left: Math.min(Math.max(center, 150), window.innerWidth - 150),
|
|
2058
|
+
});
|
|
2059
|
+
};
|
|
2060
|
+
var handleBlur = function (_a) {
|
|
2061
|
+
var _b;
|
|
2062
|
+
var event = _a.event;
|
|
2063
|
+
var next = event.relatedTarget;
|
|
2064
|
+
if (next && ((_b = selectionToolbarRef.current) === null || _b === void 0 ? void 0 : _b.contains(next)))
|
|
2065
|
+
return;
|
|
2066
|
+
setSelectionToolbar(null);
|
|
2067
|
+
setLinkDraft(null);
|
|
2068
|
+
};
|
|
2069
|
+
editor.on("selectionUpdate", handlePlaceToolbar);
|
|
2070
|
+
editor.on("focus", handlePlaceToolbar);
|
|
2071
|
+
editor.on("blur", handleBlur);
|
|
2072
|
+
window.addEventListener("scroll", handlePlaceToolbar, true);
|
|
2073
|
+
window.addEventListener("resize", handlePlaceToolbar);
|
|
2074
|
+
return function () {
|
|
2075
|
+
editor.off("selectionUpdate", handlePlaceToolbar);
|
|
2076
|
+
editor.off("focus", handlePlaceToolbar);
|
|
2077
|
+
editor.off("blur", handleBlur);
|
|
2078
|
+
window.removeEventListener("scroll", handlePlaceToolbar, true);
|
|
2079
|
+
window.removeEventListener("resize", handlePlaceToolbar);
|
|
2080
|
+
};
|
|
2081
|
+
}, [editor, borderless, readOnly, disabled]);
|
|
2082
|
+
var handleApplyLink = function () {
|
|
2083
|
+
if (!editor || linkDraft === null)
|
|
2084
|
+
return;
|
|
2085
|
+
var href = linkDraft.trim();
|
|
2086
|
+
var chain = editor.chain().focus().extendMarkRange("link");
|
|
2087
|
+
if (href)
|
|
2088
|
+
chain.setLink({ href: href }).run();
|
|
2089
|
+
else
|
|
2090
|
+
chain.unsetLink().run();
|
|
2091
|
+
setLinkDraft(null);
|
|
2092
|
+
};
|
|
1997
2093
|
// Update editor content when value prop changes
|
|
1998
2094
|
(0, react_2.useEffect)(function () {
|
|
1999
2095
|
if (editor) {
|
|
@@ -2184,6 +2280,88 @@ var MarkdownInputContent = function (_a) {
|
|
|
2184
2280
|
// Only borderless opts into skipping it; boxed usage renders as it always has.
|
|
2185
2281
|
var showLabelRow = !borderless ||
|
|
2186
2282
|
Boolean(label || subLabel || (!readOnly && (customElement || infoElement)));
|
|
2283
|
+
var renderSelectionToolbar = function () {
|
|
2284
|
+
if (!editor || !selectionToolbar)
|
|
2285
|
+
return null;
|
|
2286
|
+
var surface = darkMode
|
|
2287
|
+
? "bg-gray-800 border-gray-600 text-gray-200"
|
|
2288
|
+
: "bg-white border-gray-200 text-gray-700";
|
|
2289
|
+
var hover = darkMode ? "hover:bg-gray-700" : "hover:bg-gray-100";
|
|
2290
|
+
var active = darkMode
|
|
2291
|
+
? "bg-gray-700 text-white"
|
|
2292
|
+
: "bg-primary-50 text-primary-600";
|
|
2293
|
+
var marks = [
|
|
2294
|
+
{
|
|
2295
|
+
id: "bold",
|
|
2296
|
+
title: "Bold",
|
|
2297
|
+
icon: BoldIcon_1.default,
|
|
2298
|
+
run: function () { return editor.chain().focus().toggleBold().run(); },
|
|
2299
|
+
},
|
|
2300
|
+
{
|
|
2301
|
+
id: "italic",
|
|
2302
|
+
title: "Italic",
|
|
2303
|
+
icon: ItalicIcon_1.default,
|
|
2304
|
+
run: function () { return editor.chain().focus().toggleItalic().run(); },
|
|
2305
|
+
},
|
|
2306
|
+
{
|
|
2307
|
+
id: "underline",
|
|
2308
|
+
title: "Underline",
|
|
2309
|
+
icon: UnderlineIcon_1.default,
|
|
2310
|
+
run: function () { return editor.chain().focus().toggleUnderline().run(); },
|
|
2311
|
+
},
|
|
2312
|
+
{
|
|
2313
|
+
id: "strike",
|
|
2314
|
+
title: "Strikethrough",
|
|
2315
|
+
icon: StrikethroughIcon_1.default,
|
|
2316
|
+
run: function () { return editor.chain().focus().toggleStrike().run(); },
|
|
2317
|
+
},
|
|
2318
|
+
{
|
|
2319
|
+
id: "code",
|
|
2320
|
+
title: "Inline code",
|
|
2321
|
+
icon: CodeBracketIcon_1.default,
|
|
2322
|
+
run: function () { return editor.chain().focus().toggleCode().run(); },
|
|
2323
|
+
},
|
|
2324
|
+
];
|
|
2325
|
+
return (react_2.default.createElement("div", { ref: selectionToolbarRef, "data-testid": "markdown-selection-toolbar", className: "fixed z-50 flex -translate-x-1/2 flex-row items-center gap-x-0.5 rounded-lg border p-1 shadow-lg ".concat(surface), style: { top: selectionToolbar.top, left: selectionToolbar.left },
|
|
2326
|
+
// INFO: keeps the editor focused and the selection intact while a
|
|
2327
|
+
// button is pressed; the link field is the one control that takes focus
|
|
2328
|
+
onMouseDown: function (event) {
|
|
2329
|
+
if (event.target.tagName !== "INPUT")
|
|
2330
|
+
event.preventDefault();
|
|
2331
|
+
} }, linkDraft !== null ? (
|
|
2332
|
+
// INFO: a form so a phone keyboard's Done submits; stopPropagation
|
|
2333
|
+
// keeps it from submitting a form the editor sits inside
|
|
2334
|
+
react_2.default.createElement("form", { className: "flex flex-row items-center gap-x-1", onBlur: function (event) {
|
|
2335
|
+
var _a;
|
|
2336
|
+
var next = event.relatedTarget;
|
|
2337
|
+
if (next && ((_a = selectionToolbarRef.current) === null || _a === void 0 ? void 0 : _a.contains(next)))
|
|
2338
|
+
return;
|
|
2339
|
+
if (next && editor.view.dom.contains(next))
|
|
2340
|
+
return;
|
|
2341
|
+
setSelectionToolbar(null);
|
|
2342
|
+
setLinkDraft(null);
|
|
2343
|
+
}, onSubmit: function (event) {
|
|
2344
|
+
event.preventDefault();
|
|
2345
|
+
event.stopPropagation();
|
|
2346
|
+
handleApplyLink();
|
|
2347
|
+
} },
|
|
2348
|
+
react_2.default.createElement("input", { autoFocus: true, type: "url", enterKeyHint: "done", value: linkDraft, placeholder: "Paste a link", onChange: function (event) { return setLinkDraft(event.target.value); }, onKeyDown: function (event) {
|
|
2349
|
+
if (event.key === "Escape")
|
|
2350
|
+
setLinkDraft(null);
|
|
2351
|
+
}, className: "w-56 rounded border-0 px-2 py-1 text-base focus:ring-1 focus:ring-primary-500 sm:text-sm ".concat(darkMode ? "bg-gray-700 text-white" : "bg-gray-50") }),
|
|
2352
|
+
react_2.default.createElement("button", { type: "submit", className: "rounded px-2 py-1 text-sm font-medium text-primary-600 ".concat(hover) }, "Apply"))) : (react_2.default.createElement(react_2.default.Fragment, null,
|
|
2353
|
+
marks.map(function (eachMark) {
|
|
2354
|
+
var Icon = eachMark.icon;
|
|
2355
|
+
return (react_2.default.createElement("button", { key: eachMark.id, type: "button", title: eachMark.title, "aria-label": eachMark.title, "aria-pressed": editor.isActive(eachMark.id), onClick: eachMark.run, className: "rounded p-1.5 ".concat(editor.isActive(eachMark.id) ? active : hover) },
|
|
2356
|
+
react_2.default.createElement(Icon, { className: "h-4 w-4" })));
|
|
2357
|
+
}),
|
|
2358
|
+
react_2.default.createElement("button", { type: "button", title: "Link", "aria-label": "Link", "aria-pressed": editor.isActive("link"), onClick: function () { var _a; return setLinkDraft((_a = editor.getAttributes("link").href) !== null && _a !== void 0 ? _a : ""); }, className: "rounded p-1.5 ".concat(editor.isActive("link") ? active : hover) },
|
|
2359
|
+
react_2.default.createElement(LinkIcon_1.default, { className: "h-4 w-4" })),
|
|
2360
|
+
react_2.default.createElement("span", { className: "mx-0.5 h-5 w-px ".concat(darkMode ? "bg-gray-600" : "bg-gray-200") }),
|
|
2361
|
+
react_2.default.createElement("button", { type: "button", title: "Clear formatting", "aria-label": "Clear formatting", onClick: function () { return editor.chain().focus().unsetAllMarks().run(); }, className: "rounded px-1.5 py-1 text-sm font-medium ".concat(hover) },
|
|
2362
|
+
"T",
|
|
2363
|
+
react_2.default.createElement("sub", { className: "text-[10px]" }, "x"))))));
|
|
2364
|
+
};
|
|
2187
2365
|
return (react_2.default.createElement("div", { className: defaultClassName },
|
|
2188
2366
|
showLabelRow && (react_2.default.createElement("div", { className: "flex w-full" },
|
|
2189
2367
|
react_2.default.createElement("div", { className: "flex flex-col".concat(disabledClassName) },
|
|
@@ -2388,6 +2566,7 @@ var MarkdownInputContent = function (_a) {
|
|
|
2388
2566
|
? "text-red-400 hover:bg-gray-700"
|
|
2389
2567
|
: "text-red-600 hover:bg-gray-200"), title: "Delete Table" }, "Del"))))),
|
|
2390
2568
|
react_2.default.createElement(react_1.EditorContent, { editor: editor }),
|
|
2569
|
+
renderSelectionToolbar(),
|
|
2391
2570
|
suggestionState.show && !readOnly && suggestionState.position && (react_2.default.createElement("div", { className: "absolute z-50", style: {
|
|
2392
2571
|
top: "".concat(suggestionState.position.top, "px"),
|
|
2393
2572
|
left: "".concat(suggestionState.position.left, "px"),
|