blixify-ui-web 1.2.143 → 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.
@@ -37,6 +37,13 @@ interface Props {
37
37
  * usage is unchanged.
38
38
  */
39
39
  borderless?: boolean;
40
+ /**
41
+ * `"sm"` draws the text at 14px on every screen. Default is 14px on phones
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 scaled to 87.5%, so it
44
+ * looks 14px while iOS Safari still sees 16px and does not zoom on focus.
45
+ */
46
+ textSize?: "sm";
40
47
  onChange: (id: string, value?: string) => void;
41
48
  compress?: {
42
49
  maxFileSize?: number;
@@ -116,6 +123,11 @@ interface MarkdownStaticProps {
116
123
  * renders an outline beside the page.
117
124
  */
118
125
  onHeadingsChange?: (headings: MarkdownHeading[]) => void;
126
+ /**
127
+ * `"sm"` keeps the text at 14px on every screen, matching an editor given
128
+ * the same prop. Default is 14px on phones and 16px from md up.
129
+ */
130
+ textSize?: "sm";
119
131
  lib?: {
120
132
  /**
121
133
  * Loads mermaid, e.g. `() => import("mermaid")`. When given, ```mermaid
@@ -131,7 +143,7 @@ interface MarkdownStaticProps {
131
143
  * many markdown fields stay responsive instead of freezing from 50+ ProseMirror
132
144
  * instances or a heavy re-parse.
133
145
  */
134
- export declare const MarkdownStatic: ({ id, label, labelExtra, subLabel, value, darkMode, containerClassName, onHeadingsChange, lib, }: MarkdownStaticProps) => React.JSX.Element;
146
+ export declare const MarkdownStatic: ({ id, label, labelExtra, subLabel, value, darkMode, containerClassName, onHeadingsChange, textSize, lib, }: MarkdownStaticProps) => React.JSX.Element;
135
147
  export declare const MarkdownInput: React.ForwardRefExoticComponent<Omit<Props, "ref"> & React.RefAttributes<unknown>>;
136
148
  export {};
137
149
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/input/markdown/index.tsx"],"names":[],"mappings":"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"}
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");
@@ -1311,7 +1317,7 @@ var SlashMenuList = function (_a) {
1311
1317
  react_2.default.createElement("span", { className: "text-sm ".concat(darkMode ? "text-gray-200" : "text-gray-700") }, item.label))); })) : (react_2.default.createElement("div", { className: "px-4 py-2 text-sm text-gray-500" }, "No results"))));
1312
1318
  };
1313
1319
  var MarkdownInputContent = function (_a) {
1314
- var innerRef = _a.innerRef, id = _a.id, value = _a.value, label = _a.label, subLabel = _a.subLabel, labelExtra = _a.labelExtra, infoElement = _a.infoElement, placeholder = _a.placeholder, optional = _a.optional, disabled = _a.disabled, containerClassName = _a.containerClassName, heightClassName = _a.heightClassName, borderless = _a.borderless, onChange = _a.onChange, compress = _a.compress, lib = _a.lib, uploadEndpoint = _a.uploadEndpoint, enableImageUpload = _a.enableImageUpload, enableVideoUpload = _a.enableVideoUpload, enableFileUpload = _a.enableFileUpload, darkMode = _a.darkMode, readOnly = _a.readOnly, customElement = _a.customElement, renderEmbed = _a.renderEmbed, onRequestRemove = _a.onRequestRemove, onHeadingsChange = _a.onHeadingsChange, customCommands = _a.customCommands;
1320
+ var innerRef = _a.innerRef, id = _a.id, value = _a.value, label = _a.label, subLabel = _a.subLabel, labelExtra = _a.labelExtra, infoElement = _a.infoElement, placeholder = _a.placeholder, optional = _a.optional, disabled = _a.disabled, containerClassName = _a.containerClassName, heightClassName = _a.heightClassName, borderless = _a.borderless, textSize = _a.textSize, onChange = _a.onChange, compress = _a.compress, lib = _a.lib, uploadEndpoint = _a.uploadEndpoint, enableImageUpload = _a.enableImageUpload, enableVideoUpload = _a.enableVideoUpload, enableFileUpload = _a.enableFileUpload, darkMode = _a.darkMode, readOnly = _a.readOnly, customElement = _a.customElement, renderEmbed = _a.renderEmbed, onRequestRemove = _a.onRequestRemove, onHeadingsChange = _a.onHeadingsChange, customCommands = _a.customCommands;
1315
1321
  var _b = (0, react_2.useState)(""), error = _b[0], setError = _b[1];
1316
1322
  var _c = (0, react_2.useState)(false), showTableMenu = _c[0], setShowTableMenu = _c[1];
1317
1323
  var _d = (0, react_2.useState)(3), tableCols = _d[0], setTableCols = _d[1];
@@ -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();
@@ -1530,7 +1541,10 @@ var MarkdownInputContent = function (_a) {
1530
1541
  // any focused editable below 16px. The mobile 16px override lives in
1531
1542
  // index.css (.tiptap-table-editor.ProseMirror) so it can reliably beat
1532
1543
  // prose-sm's font-size on the same element without a class-order race.
1533
- class: "prose prose-sm md:prose-base prose-p:my-1.5 prose-p:leading-normal prose-li:leading-normal prose-headings:mb-1.5 prose-headings:mt-4 prose-ul:my-1.5 prose-ol:my-1.5 prose-li:my-0.5 prose-blockquote:my-2 prose-pre:my-2 prose-hr:my-4 ".concat(borderless ? "" : "overflow-y-auto ", "max-w-none focus:outline-none ").concat(darkMode ? "dark:prose-invert" : "", " ").concat(borderless
1544
+ // INFO: textSize "sm" stays prose-sm (14px) from md up instead of
1545
+ // stepping to prose-base, and markdown-text-sm is what index.css zooms
1546
+ // on phones — see the iOS rule there
1547
+ class: "prose prose-sm ".concat(textSize === "sm" ? "markdown-text-sm" : "md:prose-base", " prose-p:my-1.5 prose-p:leading-normal prose-li:leading-normal prose-headings:mb-1.5 prose-headings:mt-4 prose-ul:my-1.5 prose-ol:my-1.5 prose-li:my-0.5 prose-blockquote:my-2 prose-pre:my-2 prose-hr:my-4 ").concat(borderless ? "" : "overflow-y-auto ", "max-w-none focus:outline-none ").concat(darkMode ? "dark:prose-invert" : "", " ").concat(borderless
1534
1548
  ? "".concat(heightClassName !== null && heightClassName !== void 0 ? heightClassName : "min-h-[12rem]", " p-0")
1535
1549
  : "".concat(heightClassName !== null && heightClassName !== void 0 ? heightClassName : "h-72", " p-4"), " tiptap-table-editor"),
1536
1550
  },
@@ -1702,6 +1716,28 @@ var MarkdownInputContent = function (_a) {
1702
1716
  };
1703
1717
  input.click();
1704
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]);
1705
1741
  (0, react_2.useEffect)(function () {
1706
1742
  if (editor) {
1707
1743
  editorRef.current = editor;
@@ -1991,6 +2027,69 @@ var MarkdownInputContent = function (_a) {
1991
2027
  editor.off("selectionUpdate", handleSelectionUpdate);
1992
2028
  };
1993
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
+ };
1994
2093
  // Update editor content when value prop changes
1995
2094
  (0, react_2.useEffect)(function () {
1996
2095
  if (editor) {
@@ -2181,6 +2280,88 @@ var MarkdownInputContent = function (_a) {
2181
2280
  // Only borderless opts into skipping it; boxed usage renders as it always has.
2182
2281
  var showLabelRow = !borderless ||
2183
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
+ };
2184
2365
  return (react_2.default.createElement("div", { className: defaultClassName },
2185
2366
  showLabelRow && (react_2.default.createElement("div", { className: "flex w-full" },
2186
2367
  react_2.default.createElement("div", { className: "flex flex-col".concat(disabledClassName) },
@@ -2385,6 +2566,7 @@ var MarkdownInputContent = function (_a) {
2385
2566
  ? "text-red-400 hover:bg-gray-700"
2386
2567
  : "text-red-600 hover:bg-gray-200"), title: "Delete Table" }, "Del"))))),
2387
2568
  react_2.default.createElement(react_1.EditorContent, { editor: editor }),
2569
+ renderSelectionToolbar(),
2388
2570
  suggestionState.show && !readOnly && suggestionState.position && (react_2.default.createElement("div", { className: "absolute z-50", style: {
2389
2571
  top: "".concat(suggestionState.position.top, "px"),
2390
2572
  left: "".concat(suggestionState.position.left, "px"),
@@ -2418,7 +2600,7 @@ var MarkdownInputContent = function (_a) {
2418
2600
  * instances or a heavy re-parse.
2419
2601
  */
2420
2602
  var MarkdownStatic = function (_a) {
2421
- var id = _a.id, label = _a.label, labelExtra = _a.labelExtra, subLabel = _a.subLabel, value = _a.value, darkMode = _a.darkMode, containerClassName = _a.containerClassName, onHeadingsChange = _a.onHeadingsChange, lib = _a.lib;
2603
+ var id = _a.id, label = _a.label, labelExtra = _a.labelExtra, subLabel = _a.subLabel, value = _a.value, darkMode = _a.darkMode, containerClassName = _a.containerClassName, onHeadingsChange = _a.onHeadingsChange, textSize = _a.textSize, lib = _a.lib;
2422
2604
  var contentRef = (0, react_2.useRef)(null);
2423
2605
  var labelColor = darkMode ? "text-white" : "text-gray-700";
2424
2606
  var subColor = darkMode ? "text-gray-300" : "text-gray-500";
@@ -2487,7 +2669,7 @@ var MarkdownStatic = function (_a) {
2487
2669
  " ",
2488
2670
  labelExtra),
2489
2671
  subLabel && (react_2.default.createElement("label", { className: "block text-xs font-medium ".concat(subColor, " mb-2") }, subLabel))),
2490
- react_2.default.createElement("div", { id: id, ref: contentRef, className: "prose prose-sm md:prose-base prose-p:my-1.5 prose-p:leading-normal prose-li:leading-normal prose-headings:mb-1.5 prose-headings:mt-4 prose-ul:my-1.5 prose-ol:my-1.5 prose-li:my-0.5 prose-blockquote:my-2 prose-pre:my-2 prose-hr:my-4 max-w-none mt-2 ".concat(darkMode ? "prose-invert" : ""), dangerouslySetInnerHTML: innerHtml })));
2672
+ react_2.default.createElement("div", { id: id, ref: contentRef, className: "prose prose-sm ".concat(textSize === "sm" ? "" : "md:prose-base", " prose-p:my-1.5 prose-p:leading-normal prose-li:leading-normal prose-headings:mb-1.5 prose-headings:mt-4 prose-ul:my-1.5 prose-ol:my-1.5 prose-li:my-0.5 prose-blockquote:my-2 prose-pre:my-2 prose-hr:my-4 max-w-none mt-2 ").concat(darkMode ? "prose-invert" : ""), dangerouslySetInnerHTML: innerHtml })));
2491
2673
  };
2492
2674
  exports.MarkdownStatic = MarkdownStatic;
2493
2675
  exports.MarkdownInput = (0, react_2.forwardRef)(function (props, ref) {