@monolith-forensics/monolith-ui 1.9.3-dev.1 → 1.9.3-dev.3

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.
@@ -32,6 +32,10 @@ export interface MonolithDefaultTheme {
32
32
  main: string;
33
33
  contrastText: string;
34
34
  };
35
+ warning: {
36
+ main: string;
37
+ contrastText: string;
38
+ };
35
39
  background: {
36
40
  default: string;
37
41
  paper: string;
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import styled, { useTheme } from "styled-components";
3
3
  import { Extensions } from "../Enums";
4
- import { BoldIcon, CodeIcon, ItalicIcon, UnderlineIcon, CaseSensitiveIcon, ListIcon, ListOrderedIcon, SquareCodeIcon, StrikethroughIcon, Heading1Icon, Heading2Icon, Heading3Icon, Heading4Icon, HighlighterIcon, LinkIcon, PaletteIcon, RemoveFormattingIcon, SquircleIcon, } from "lucide-react";
4
+ import { BoldIcon, CodeIcon, ItalicIcon, UnderlineIcon, CaseSensitiveIcon, ListIcon, ListOrderedIcon, SquareCodeIcon, StrikethroughIcon, Heading1Icon, Heading2Icon, Heading3Icon, Heading4Icon, HighlighterIcon, LinkIcon, PaletteIcon, RemoveFormattingIcon, SquircleIcon, TextQuoteIcon, } from "lucide-react";
5
5
  import { DropDownMenu, } from "../../DropDownMenu";
6
6
  import { useEffect, useState } from "react";
7
7
  import { Button } from "../../Button";
@@ -16,15 +16,19 @@ const getMenuItems = (editor, customMenuItems, theme, openLinkEditor) => {
16
16
  const pos = (_e = (_d = editor === null || editor === void 0 ? void 0 : editor.state) === null || _d === void 0 ? void 0 : _d.selection) === null || _e === void 0 ? void 0 : _e.$from;
17
17
  let withinUnorderedList = false;
18
18
  let withinOrderedList = false;
19
+ let withinBlockquote = false;
19
20
  // Traverse the node ancestors
20
21
  pos.path.forEach((node) => {
21
- var _a, _b;
22
+ var _a, _b, _c;
22
23
  if (((_a = node === null || node === void 0 ? void 0 : node.type) === null || _a === void 0 ? void 0 : _a.name) === "bulletList") {
23
24
  withinUnorderedList = true;
24
25
  }
25
26
  else if (((_b = node === null || node === void 0 ? void 0 : node.type) === null || _b === void 0 ? void 0 : _b.name) === "orderedList") {
26
27
  withinOrderedList = true;
27
28
  }
29
+ else if (((_c = node === null || node === void 0 ? void 0 : node.type) === null || _c === void 0 ? void 0 : _c.name) === "blockquote") {
30
+ withinBlockquote = true;
31
+ }
28
32
  });
29
33
  const attrs = node === null || node === void 0 ? void 0 : node.attrs;
30
34
  const supportsSyntaxCodeBlock = hasSyntaxHighlightedCodeBlock(editor);
@@ -32,6 +36,7 @@ const getMenuItems = (editor, customMenuItems, theme, openLinkEditor) => {
32
36
  const supportsColor = Boolean(editor.extensionManager.extensions.find((extension) => extension.name === "color"));
33
37
  const supportsHighlight = Boolean(editor.extensionManager.extensions.find((extension) => extension.name === "highlight"));
34
38
  const supportsLink = Boolean(editor.extensionManager.extensions.find((extension) => extension.name === "link"));
39
+ const supportsBlockquote = Boolean(editor.extensionManager.extensions.find((extension) => extension.name === "blockquote"));
35
40
  let nodeTypeLabel = "Select Type";
36
41
  let nodeTypeIcon = null;
37
42
  if (withinOrderedList) {
@@ -50,6 +55,10 @@ const getMenuItems = (editor, customMenuItems, theme, openLinkEditor) => {
50
55
  nodeTypeLabel = "Code Block";
51
56
  nodeTypeIcon = _jsx(SquareCodeIcon, { size: 16 });
52
57
  }
58
+ else if (withinBlockquote) {
59
+ nodeTypeLabel = "Blockquote";
60
+ nodeTypeIcon = _jsx(TextQuoteIcon, { size: 16 });
61
+ }
53
62
  else if (((_h = node === null || node === void 0 ? void 0 : node.type) === null || _h === void 0 ? void 0 : _h.name) === "heading") {
54
63
  const level = attrs === null || attrs === void 0 ? void 0 : attrs.level;
55
64
  nodeTypeLabel = `Heading ${level}`;
@@ -147,6 +156,20 @@ const getMenuItems = (editor, customMenuItems, theme, openLinkEditor) => {
147
156
  },
148
157
  },
149
158
  },
159
+ ...(supportsBlockquote
160
+ ? [
161
+ {
162
+ label: "Blockquote",
163
+ value: "blockquote",
164
+ data: {
165
+ Icon: TextQuoteIcon,
166
+ command: (editor) => {
167
+ editor.chain().focus().toggleBlockquote().run();
168
+ },
169
+ },
170
+ },
171
+ ]
172
+ : []),
150
173
  ...(supportsSyntaxCodeBlock
151
174
  ? [
152
175
  {
@@ -8,6 +8,7 @@ export declare enum Controls {
8
8
  CLEAR_FORMATTING = "clearFormatting",
9
9
  CODE = "code",
10
10
  CODE_BLOCK = "codeBlock",
11
+ BLOCKQUOTE = "blockquote",
11
12
  HEADING_1 = "heading_1",
12
13
  HEADING_2 = "heading_2",
13
14
  HEADING_3 = "heading_3",
@@ -9,6 +9,7 @@ export var Controls;
9
9
  Controls["CLEAR_FORMATTING"] = "clearFormatting";
10
10
  Controls["CODE"] = "code";
11
11
  Controls["CODE_BLOCK"] = "codeBlock";
12
+ Controls["BLOCKQUOTE"] = "blockquote";
12
13
  Controls["HEADING_1"] = "heading_1";
13
14
  Controls["HEADING_2"] = "heading_2";
14
15
  Controls["HEADING_3"] = "heading_3";
@@ -6,6 +6,7 @@ export declare enum Extensions {
6
6
  Italic = "italic",
7
7
  Code = "code",
8
8
  CodeBlock = "codeBlock",
9
+ Blockquote = "blockquote",
9
10
  Color = "color",
10
11
  Highlight = "highlight",
11
12
  Link = "link",
@@ -7,6 +7,7 @@ export var Extensions;
7
7
  Extensions["Italic"] = "italic";
8
8
  Extensions["Code"] = "code";
9
9
  Extensions["CodeBlock"] = "codeBlock";
10
+ Extensions["Blockquote"] = "blockquote";
10
11
  Extensions["Color"] = "color";
11
12
  Extensions["Highlight"] = "highlight";
12
13
  Extensions["Link"] = "link";
@@ -8,6 +8,7 @@ export declare enum SlashCommands {
8
8
  NumberedList = "Numbered List",
9
9
  Code = "Code",
10
10
  CodeBlock = "Code Block",
11
+ Blockquote = "Blockquote",
11
12
  CurrentDate = "Current Date",
12
13
  CurrentTimestamp = "Current Timestamp",
13
14
  Image = "Image",
@@ -9,6 +9,7 @@ export var SlashCommands;
9
9
  SlashCommands["NumberedList"] = "Numbered List";
10
10
  SlashCommands["Code"] = "Code";
11
11
  SlashCommands["CodeBlock"] = "Code Block";
12
+ SlashCommands["Blockquote"] = "Blockquote";
12
13
  SlashCommands["CurrentDate"] = "Current Date";
13
14
  SlashCommands["CurrentTimestamp"] = "Current Timestamp";
14
15
  SlashCommands["Image"] = "Image";
@@ -11,7 +11,7 @@ import { Extension } from "@tiptap/core";
11
11
  import Suggestion from "@tiptap/suggestion";
12
12
  import { ReactRenderer } from "@tiptap/react";
13
13
  import tippy from "tippy.js";
14
- import { Heading1, Heading2, Heading3, Heading4, List, ListOrdered, Text, Image as ImageIcon, Calendar, CodeIcon, ClockIcon, SquareCodeIcon, Table2Icon, } from "lucide-react";
14
+ import { Heading1, Heading2, Heading3, Heading4, List, ListOrdered, Text, TextQuote, Image as ImageIcon, Calendar, CodeIcon, ClockIcon, SquareCodeIcon, Table2Icon, } from "lucide-react";
15
15
  import { startImageUpload, } from "../Plugins/UploadImagesPlugin.js";
16
16
  import { PluginKey } from "@tiptap/pm/state";
17
17
  import SlashCommandList from "./SlashCommandList";
@@ -139,6 +139,15 @@ const getCommandItems = (values, options) => {
139
139
  .run();
140
140
  },
141
141
  },
142
+ {
143
+ title: SlashCommands.Blockquote,
144
+ description: "Capture a quotation or cited note.",
145
+ searchTerms: ["quote", "blockquote", "callout"],
146
+ icon: TextQuote,
147
+ command: ({ editor, range }) => {
148
+ editor.chain().focus().deleteRange(range).toggleBlockquote().run();
149
+ },
150
+ },
142
151
  {
143
152
  title: SlashCommands.CurrentDate,
144
153
  description: "Insert the current date.",
@@ -70,6 +70,7 @@ export const BASIC_EXTENSIONS = [
70
70
  Extensions.Underline,
71
71
  Extensions.Strike,
72
72
  Extensions.Code,
73
+ Extensions.Blockquote,
73
74
  Extensions.BulletList,
74
75
  Extensions.OrderedList,
75
76
  Extensions.TextStyle,
@@ -164,6 +165,13 @@ const getTipTapExtensions = ({ disabledExtensions = [], extensions = [], slashCo
164
165
  },
165
166
  }
166
167
  : false,
168
+ blockquote: isEnabled(Extensions.Blockquote)
169
+ ? {
170
+ HTMLAttributes: {
171
+ class: "editor-blockquote",
172
+ },
173
+ }
174
+ : false,
167
175
  codeBlock: false,
168
176
  horizontalRule: false,
169
177
  dropcursor: {
@@ -34,6 +34,19 @@ const readFileAsDataUrl = (file) => {
34
34
  reader.readAsDataURL(file);
35
35
  });
36
36
  };
37
+ const getImageExtensionFromMimeType = (mimeType) => {
38
+ var _a;
39
+ const subtype = (_a = mimeType.toLowerCase().split("/")[1]) === null || _a === void 0 ? void 0 : _a.split(";")[0];
40
+ if (!subtype)
41
+ return "png";
42
+ if (subtype === "jpeg" || subtype === "pjpeg")
43
+ return "jpg";
44
+ if (subtype === "svg+xml")
45
+ return "svg";
46
+ if (subtype === "x-icon" || subtype === "vnd.microsoft.icon")
47
+ return "ico";
48
+ return subtype.replace(/[^a-z0-9]/g, "") || "png";
49
+ };
37
50
  export const addImagePlaceholder = ({ view, id, pos, src, label = "Processing image...", }) => {
38
51
  if (!uploadKey.getState(view.state))
39
52
  return;
@@ -71,6 +84,7 @@ export const startImageUpload = (file, view, pos, handleImageUpload) => {
71
84
  }
72
85
  // A fresh object to act as the ID for this upload
73
86
  const id = nanoid(25);
87
+ const uploadName = `${id}.${getImageExtensionFromMimeType(file.type)}`;
74
88
  // Replace the selection with a placeholder
75
89
  (() => __awaiter(void 0, void 0, void 0, function* () {
76
90
  let placeholderAdded = false;
@@ -92,7 +106,7 @@ export const startImageUpload = (file, view, pos, handleImageUpload) => {
92
106
  const hashes = yield calculateFileHash(file);
93
107
  const src = yield handleImageUpload({
94
108
  file,
95
- name: `${id}.png`,
109
+ name: uploadName,
96
110
  id,
97
111
  md5: hashes.md5Hash,
98
112
  sha1: hashes.sha1Hash,
@@ -111,10 +125,10 @@ export const startImageUpload = (file, view, pos, handleImageUpload) => {
111
125
  const imageSrc = typeof src === "object" ? previewSrc : src;
112
126
  const node = view.state.schema.nodes.image.create({
113
127
  src: imageSrc,
114
- alt: `${id}.png`,
128
+ alt: uploadName,
115
129
  "data-uuid": id,
116
130
  crossorigin: "anonymous",
117
- title: `Filename: ${id}.png`,
131
+ title: `Filename: ${uploadName}`,
118
132
  });
119
133
  const insertTransaction = view.state.tr
120
134
  .replaceWith(placeholderPos, placeholderPos, node)
@@ -448,6 +448,20 @@ const StyledContent = styled.div `
448
448
  font-size: 0.9em;
449
449
  box-decoration-break: clone;
450
450
  }
451
+ .editor-blockquote,
452
+ blockquote {
453
+ margin: 0.5rem 0;
454
+ padding: 0.375rem 0 0.375rem 0.875rem;
455
+ border-left: 4px solid ${({ theme }) => theme.palette.primary.main};
456
+ color: ${({ theme }) => theme.palette.text.secondary};
457
+ background-color: ${({ theme }) => theme.palette.action.hover};
458
+ }
459
+
460
+ .editor-blockquote p,
461
+ blockquote p {
462
+ margin: 0;
463
+ }
464
+
451
465
  .editor-code-block {
452
466
  position: relative;
453
467
  margin: 0.5rem 0;
@@ -827,6 +841,9 @@ export const RichTextEditor = ({ className, editorInstanceRef, defaultValue = ""
827
841
  if (command === SlashCommands.CodeBlock) {
828
842
  return resolvedExtensionSet.has(Extensions.CodeBlock);
829
843
  }
844
+ if (command === SlashCommands.Blockquote) {
845
+ return resolvedExtensionSet.has(Extensions.Blockquote);
846
+ }
830
847
  if (command === SlashCommands.Table) {
831
848
  return resolvedExtensionSet.has(Extensions.Table);
832
849
  }
@@ -842,6 +859,7 @@ export const RichTextEditor = ({ className, editorInstanceRef, defaultValue = ""
842
859
  [Controls.STRIKE]: Extensions.Strike,
843
860
  [Controls.CODE]: Extensions.Code,
844
861
  [Controls.CODE_BLOCK]: Extensions.CodeBlock,
862
+ [Controls.BLOCKQUOTE]: Extensions.Blockquote,
845
863
  [Controls.BULLET_LIST]: Extensions.BulletList,
846
864
  [Controls.ORDERED_LIST]: Extensions.OrderedList,
847
865
  [Controls.COLOR]: Extensions.Color,
@@ -14,6 +14,7 @@ export declare const UnderlineControl: ({ editor }: ControlProps) => import("rea
14
14
  export declare const StrikeThroughControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
15
15
  export declare const CodeControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
16
16
  export declare const CodeBlockControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
17
+ export declare const BlockquoteControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
17
18
  export declare const Heading1Control: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
18
19
  export declare const Heading2Control: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
19
20
  export declare const Heading3Control: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { IconBold, IconItalic, IconUnderline, IconStrikethrough, IconH1, IconH2, IconH3, IconH4, IconList, IconListNumbers, IconAlignLeft, IconAlignRight, IconAlignCenter, IconAlignJustified, IconCornerUpLeft, IconCornerUpRight, } from "@tabler/icons-react";
2
+ import { IconBold, IconItalic, IconUnderline, IconStrikethrough, IconH1, IconH2, IconH3, IconH4, IconList, IconListNumbers, IconAlignLeft, IconAlignRight, IconAlignCenter, IconAlignJustified, IconCornerUpLeft, IconCornerUpRight, IconBlockquote, } from "@tabler/icons-react";
3
3
  import { CodeIcon, HighlighterIcon, PaletteIcon, RemoveFormattingIcon, SquircleIcon, TypeIcon, } from "lucide-react";
4
4
  import { SquareCodeIcon } from "lucide-react";
5
5
  import { Control } from "./Control";
@@ -156,6 +156,13 @@ export const CodeBlockControl = ({ editor }) => {
156
156
  name: "codeBlock",
157
157
  }, onClick: toggleCodeBlock, disabled: !hasSyntaxHighlightedCodeBlock(editor), icon: SquareCodeIcon }));
158
158
  };
159
+ export const BlockquoteControl = ({ editor }) => {
160
+ return (_jsx(Control, { editor: editor, label: "blockquoteControlLabel", isActive: {
161
+ name: "blockquote",
162
+ }, operation: {
163
+ name: "toggleBlockquote",
164
+ }, icon: IconBlockquote }));
165
+ };
159
166
  export const Heading1Control = ({ editor }) => {
160
167
  return (_jsx(Control, { editor: editor, label: "h1ControlLabel", isActive: {
161
168
  name: "heading",
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import styled from "styled-components";
3
3
  import ControlsGroup from "./ControlsGroup";
4
- import { UndoControl, RedoControl, FontControl, TextColorControl, HighlightControl, BoldControl, ItalicControl, UnderlineControl, StrikeThroughControl, ClearFormattingControl, CodeControl, CodeBlockControl, Heading1Control, Heading2Control, Heading3Control, Heading4Control, BulletListControl, OrderedListControl, AlignLeftControl, AlignCenterControl, AlignRightControl, AlignJustifiedControl, } from "./Controls";
4
+ import { UndoControl, RedoControl, FontControl, TextColorControl, HighlightControl, BoldControl, ItalicControl, UnderlineControl, StrikeThroughControl, ClearFormattingControl, CodeControl, CodeBlockControl, BlockquoteControl, Heading1Control, Heading2Control, Heading3Control, Heading4Control, BulletListControl, OrderedListControl, AlignLeftControl, AlignCenterControl, AlignRightControl, AlignJustifiedControl, } from "./Controls";
5
5
  import { Controls } from "../Enums";
6
6
  import { DropDownMenu } from "../../DropDownMenu";
7
7
  import { useState } from "react";
@@ -46,5 +46,5 @@ export const Toolbar = ({ editor, toolbarOptions }) => {
46
46
  },
47
47
  } }, item.options, { size: "xs", children: (_b = item === null || item === void 0 ? void 0 : item.options) === null || _b === void 0 ? void 0 : _b.label }), index));
48
48
  }
49
- }), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.UNDO)) && _jsx(UndoControl, { editor: editor }), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.REDO)) && _jsx(RedoControl, { editor: editor })] }), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.FONT)) && _jsx(FontControl, {}), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.COLOR)) && (_jsx(TextColorControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.HIGHLIGHT)) && (_jsx(HighlightControl, { editor: editor }))] }), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.BOLD)) && _jsx(BoldControl, { editor: editor }), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.ITALIC)) && (_jsx(ItalicControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.UNDERLINE)) && (_jsx(UnderlineControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.STRIKE)) && (_jsx(StrikeThroughControl, { editor: editor }))] }), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.HEADING_1)) && (_jsx(Heading1Control, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.HEADING_2)) && (_jsx(Heading2Control, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.HEADING_3)) && (_jsx(Heading3Control, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.HEADING_4)) && (_jsx(Heading4Control, { editor: editor }))] }), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.BULLET_LIST)) && (_jsx(BulletListControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.ORDERED_LIST)) && (_jsx(OrderedListControl, { editor: editor }))] }), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.TEXT_ALIGN_LEFT)) && (_jsx(AlignLeftControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.TEXT_ALIGN_CENTER)) && (_jsx(AlignCenterControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.TEXT_ALIGN_RIGHT)) && (_jsx(AlignRightControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.TEXT_ALIGN_JUSTIFIED)) && (_jsx(AlignJustifiedControl, { editor: editor }))] }), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.LINK)) && (_jsxs(Popover, { opened: linkPopoverOpen, onChange: setLinkPopoverOpen, position: "bottom", width: 330, trapFocus: true, children: [_jsx(Popover.Target, { children: _jsx(Button, { size: "xs", variant: "outlined", title: "Link", "aria-label": "Link", selected: linkPopoverOpen || Boolean(editor === null || editor === void 0 ? void 0 : editor.isActive("link")), disabled: !editor, style: { padding: "1px 6px" }, children: _jsx(LinkIcon, { size: 14 }) }) }), _jsx(Popover.Dropdown, { children: editor && (_jsx(LinkEditor, { editor: editor, autoFocus: linkPopoverOpen, onClose: () => setLinkPopoverOpen(false) })) })] })), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.CODE)) && _jsx(CodeControl, { editor: editor }), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.CODE_BLOCK)) && (_jsx(CodeBlockControl, { editor: editor }))] }), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.TABLE)) && (_jsx(TableToolsPopover, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.CLEAR_FORMATTING)) && (_jsx(ClearFormattingControl, { editor: editor }))] }));
49
+ }), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.UNDO)) && _jsx(UndoControl, { editor: editor }), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.REDO)) && _jsx(RedoControl, { editor: editor })] }), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.FONT)) && _jsx(FontControl, {}), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.COLOR)) && (_jsx(TextColorControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.HIGHLIGHT)) && (_jsx(HighlightControl, { editor: editor }))] }), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.BOLD)) && _jsx(BoldControl, { editor: editor }), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.ITALIC)) && (_jsx(ItalicControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.UNDERLINE)) && (_jsx(UnderlineControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.STRIKE)) && (_jsx(StrikeThroughControl, { editor: editor }))] }), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.HEADING_1)) && (_jsx(Heading1Control, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.HEADING_2)) && (_jsx(Heading2Control, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.HEADING_3)) && (_jsx(Heading3Control, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.HEADING_4)) && (_jsx(Heading4Control, { editor: editor }))] }), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.BULLET_LIST)) && (_jsx(BulletListControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.ORDERED_LIST)) && (_jsx(OrderedListControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.BLOCKQUOTE)) && (_jsx(BlockquoteControl, { editor: editor }))] }), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.TEXT_ALIGN_LEFT)) && (_jsx(AlignLeftControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.TEXT_ALIGN_CENTER)) && (_jsx(AlignCenterControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.TEXT_ALIGN_RIGHT)) && (_jsx(AlignRightControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.TEXT_ALIGN_JUSTIFIED)) && (_jsx(AlignJustifiedControl, { editor: editor }))] }), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.LINK)) && (_jsxs(Popover, { opened: linkPopoverOpen, onChange: setLinkPopoverOpen, position: "bottom", width: 330, trapFocus: true, children: [_jsx(Popover.Target, { children: _jsx(Button, { size: "xs", variant: "outlined", title: "Link", "aria-label": "Link", selected: linkPopoverOpen || Boolean(editor === null || editor === void 0 ? void 0 : editor.isActive("link")), disabled: !editor, style: { padding: "1px 6px" }, children: _jsx(LinkIcon, { size: 14 }) }) }), _jsx(Popover.Dropdown, { children: editor && (_jsx(LinkEditor, { editor: editor, autoFocus: linkPopoverOpen, onClose: () => setLinkPopoverOpen(false) })) })] })), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.CODE)) && _jsx(CodeControl, { editor: editor }), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.CODE_BLOCK)) && (_jsx(CodeBlockControl, { editor: editor }))] }), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.TABLE)) && (_jsx(TableToolsPopover, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.CLEAR_FORMATTING)) && (_jsx(ClearFormattingControl, { editor: editor }))] }));
50
50
  };
@@ -73,6 +73,10 @@ const lightVariant = {
73
73
  main: green[700],
74
74
  contrastText: "#FFF",
75
75
  },
76
+ warning: {
77
+ main: "#ffa726",
78
+ contrastText: "#FFF",
79
+ },
76
80
  background: {
77
81
  default: "#FFF",
78
82
  paper: "#FFF",
@@ -260,6 +264,10 @@ const darkVariant = merge(lightVariant, {
260
264
  main: green[500],
261
265
  contrastText: "#FFF",
262
266
  },
267
+ warning: {
268
+ main: "#ffa726",
269
+ contrastText: "#FFF",
270
+ },
263
271
  background: {
264
272
  default: "#222222",
265
273
  paper: "#333333",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monolith-forensics/monolith-ui",
3
- "version": "1.9.3-dev.1",
3
+ "version": "1.9.3-dev.3",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "author": "Matt Danner (Monolith Forensics LLC)",
@@ -1,78 +0,0 @@
1
- export type ImageOcrProgress = {
2
- status: string;
3
- progress: number;
4
- };
5
- export type ImageOcrLine = {
6
- text: string;
7
- confidence?: number;
8
- bbox?: {
9
- x0: number;
10
- y0: number;
11
- x1: number;
12
- y1: number;
13
- };
14
- };
15
- export type ImageTextContent = {
16
- text: string;
17
- confidence?: number;
18
- language: string;
19
- lines: ImageOcrLine[];
20
- };
21
- export declare const ImageOcrPageSegModes: {
22
- readonly OSD_ONLY: "0";
23
- readonly AUTO_OSD: "1";
24
- readonly AUTO_ONLY: "2";
25
- readonly AUTO: "3";
26
- readonly SINGLE_COLUMN: "4";
27
- readonly SINGLE_BLOCK_VERT_TEXT: "5";
28
- readonly SINGLE_BLOCK: "6";
29
- readonly SINGLE_LINE: "7";
30
- readonly SINGLE_WORD: "8";
31
- readonly CIRCLE_WORD: "9";
32
- readonly SINGLE_CHAR: "10";
33
- readonly SPARSE_TEXT: "11";
34
- readonly SPARSE_TEXT_OSD: "12";
35
- readonly RAW_LINE: "13";
36
- };
37
- export type ImageOcrPageSegMode = (typeof ImageOcrPageSegModes)[keyof typeof ImageOcrPageSegModes];
38
- export type ImageOcrPreprocessOptions = {
39
- grayscale?: boolean;
40
- contrast?: number;
41
- scale?: number;
42
- threshold?: number;
43
- maxDimension?: number;
44
- };
45
- export type ImageOcrRectangle = {
46
- left: number;
47
- top: number;
48
- width: number;
49
- height: number;
50
- };
51
- export type ImageOcrRecognizeOptions = {
52
- rectangle?: ImageOcrRectangle;
53
- rotateAuto?: boolean;
54
- rotateRadians?: number;
55
- };
56
- export type ImageOcrParameters = {
57
- tessedit_pageseg_mode?: ImageOcrPageSegMode;
58
- tessedit_char_whitelist?: string;
59
- tessedit_char_blacklist?: string;
60
- preserve_interword_spaces?: "0" | "1";
61
- user_defined_dpi?: string;
62
- [key: string]: string | undefined;
63
- };
64
- export type ImageOcrPreset = "default" | "document" | "driver-license";
65
- export type GetImageTextContentOptions = {
66
- language?: string;
67
- preset?: ImageOcrPreset;
68
- onProgress?: (progress: ImageOcrProgress) => void;
69
- preprocess?: ImageOcrPreprocessOptions;
70
- recognizeOptions?: ImageOcrRecognizeOptions;
71
- parameters?: ImageOcrParameters;
72
- workerOptions?: {
73
- workerPath?: string;
74
- corePath?: string;
75
- langPath?: string;
76
- };
77
- };
78
- export declare const getImageTextContent: (image: File, options?: GetImageTextContentOptions) => Promise<ImageTextContent>;
@@ -1,222 +0,0 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- export const ImageOcrPageSegModes = {
11
- OSD_ONLY: "0",
12
- AUTO_OSD: "1",
13
- AUTO_ONLY: "2",
14
- AUTO: "3",
15
- SINGLE_COLUMN: "4",
16
- SINGLE_BLOCK_VERT_TEXT: "5",
17
- SINGLE_BLOCK: "6",
18
- SINGLE_LINE: "7",
19
- SINGLE_WORD: "8",
20
- CIRCLE_WORD: "9",
21
- SINGLE_CHAR: "10",
22
- SPARSE_TEXT: "11",
23
- SPARSE_TEXT_OSD: "12",
24
- RAW_LINE: "13",
25
- };
26
- const defaultDocumentOptions = {
27
- preprocess: {
28
- grayscale: true,
29
- contrast: 1.25,
30
- scale: 2,
31
- maxDimension: 2800,
32
- },
33
- recognizeOptions: {
34
- rotateAuto: true,
35
- },
36
- parameters: {
37
- tessedit_pageseg_mode: ImageOcrPageSegModes.AUTO,
38
- preserve_interword_spaces: "1",
39
- user_defined_dpi: "300",
40
- },
41
- };
42
- const defaultDriverLicenseOptions = {
43
- preprocess: {
44
- grayscale: true,
45
- contrast: 1.45,
46
- scale: 2.5,
47
- maxDimension: 3200,
48
- },
49
- recognizeOptions: {
50
- rotateAuto: true,
51
- },
52
- parameters: {
53
- tessedit_pageseg_mode: ImageOcrPageSegModes.SPARSE_TEXT,
54
- preserve_interword_spaces: "1",
55
- user_defined_dpi: "300",
56
- },
57
- };
58
- const mergeOptions = (defaults, options) => {
59
- var _a, _b;
60
- return Object.assign(Object.assign(Object.assign({}, defaults), options), { language: (_b = (_a = options.language) !== null && _a !== void 0 ? _a : defaults.language) !== null && _b !== void 0 ? _b : "eng", preprocess: Object.assign(Object.assign({}, defaults.preprocess), options.preprocess), recognizeOptions: Object.assign(Object.assign({}, defaults.recognizeOptions), options.recognizeOptions), parameters: Object.assign(Object.assign({}, defaults.parameters), options.parameters), workerOptions: Object.assign(Object.assign({}, defaults.workerOptions), options.workerOptions) });
61
- };
62
- const getResolvedOptions = (options) => {
63
- switch (options.preset) {
64
- case "document":
65
- return mergeOptions(defaultDocumentOptions, options);
66
- case "driver-license":
67
- return mergeOptions(defaultDriverLicenseOptions, options);
68
- default:
69
- return mergeOptions({}, options);
70
- }
71
- };
72
- const getFallbackLines = (text) => {
73
- return text
74
- .split(/\r?\n/)
75
- .map((line) => line.trim())
76
- .filter(Boolean)
77
- .map((line) => ({ text: line }));
78
- };
79
- const getLinesFromPage = (page) => {
80
- var _a, _b;
81
- const lines = (_b = (_a = page.blocks) === null || _a === void 0 ? void 0 : _a.flatMap((block) => block.paragraphs.flatMap((paragraph) => paragraph.lines))) !== null && _b !== void 0 ? _b : [];
82
- if (!lines.length) {
83
- return getFallbackLines(page.text);
84
- }
85
- return lines
86
- .filter((line) => line.text.trim().length > 0)
87
- .map((line) => ({
88
- text: line.text,
89
- confidence: line.confidence,
90
- bbox: line.bbox
91
- ? {
92
- x0: line.bbox.x0,
93
- y0: line.bbox.y0,
94
- x1: line.bbox.x1,
95
- y1: line.bbox.y1,
96
- }
97
- : undefined,
98
- }));
99
- };
100
- const loadImageBitmap = (image) => __awaiter(void 0, void 0, void 0, function* () {
101
- if (typeof createImageBitmap === "function") {
102
- return createImageBitmap(image);
103
- }
104
- const objectUrl = URL.createObjectURL(image);
105
- try {
106
- const img = new Image();
107
- img.decoding = "async";
108
- img.src = objectUrl;
109
- yield img.decode();
110
- const canvas = document.createElement("canvas");
111
- canvas.width = img.naturalWidth;
112
- canvas.height = img.naturalHeight;
113
- const context = canvas.getContext("2d");
114
- if (!context) {
115
- throw new Error("Canvas rendering is not available.");
116
- }
117
- context.drawImage(img, 0, 0);
118
- return createImageBitmap(canvas);
119
- }
120
- finally {
121
- URL.revokeObjectURL(objectUrl);
122
- }
123
- });
124
- const hasPreprocessOptions = (preprocess) => {
125
- return Boolean((preprocess === null || preprocess === void 0 ? void 0 : preprocess.grayscale) ||
126
- (preprocess === null || preprocess === void 0 ? void 0 : preprocess.contrast) ||
127
- (preprocess === null || preprocess === void 0 ? void 0 : preprocess.threshold) !== undefined ||
128
- (preprocess === null || preprocess === void 0 ? void 0 : preprocess.scale));
129
- };
130
- const clampByte = (value) => Math.max(0, Math.min(255, value));
131
- const preprocessImage = (image, preprocess) => __awaiter(void 0, void 0, void 0, function* () {
132
- var _a, _b, _c;
133
- if (!hasPreprocessOptions(preprocess)) {
134
- return image;
135
- }
136
- const bitmap = yield loadImageBitmap(image);
137
- const requestedScale = (_a = preprocess === null || preprocess === void 0 ? void 0 : preprocess.scale) !== null && _a !== void 0 ? _a : 1;
138
- const maxDimension = (_b = preprocess === null || preprocess === void 0 ? void 0 : preprocess.maxDimension) !== null && _b !== void 0 ? _b : 3000;
139
- const largestSourceDimension = Math.max(bitmap.width, bitmap.height);
140
- const scale = Math.min(Math.max(requestedScale, 1), maxDimension / largestSourceDimension);
141
- const width = Math.max(1, Math.round(bitmap.width * scale));
142
- const height = Math.max(1, Math.round(bitmap.height * scale));
143
- const canvas = document.createElement("canvas");
144
- canvas.width = width;
145
- canvas.height = height;
146
- const context = canvas.getContext("2d", { willReadFrequently: true });
147
- if (!context) {
148
- throw new Error("Canvas rendering is not available.");
149
- }
150
- context.imageSmoothingEnabled = true;
151
- context.imageSmoothingQuality = "high";
152
- context.drawImage(bitmap, 0, 0, width, height);
153
- bitmap.close();
154
- const imageData = context.getImageData(0, 0, width, height);
155
- const { data } = imageData;
156
- const contrast = (_c = preprocess === null || preprocess === void 0 ? void 0 : preprocess.contrast) !== null && _c !== void 0 ? _c : 1;
157
- const contrastFactor = contrast === 1 ? 1 : (259 * (255 * contrast - 255 + 255)) / (255 * (259 - (255 * contrast - 255)));
158
- for (let index = 0; index < data.length; index += 4) {
159
- let red = data[index];
160
- let green = data[index + 1];
161
- let blue = data[index + 2];
162
- if ((preprocess === null || preprocess === void 0 ? void 0 : preprocess.grayscale) || (preprocess === null || preprocess === void 0 ? void 0 : preprocess.threshold) !== undefined) {
163
- const luminance = 0.299 * red + 0.587 * green + 0.114 * blue;
164
- red = luminance;
165
- green = luminance;
166
- blue = luminance;
167
- }
168
- if (contrast !== 1) {
169
- red = clampByte(contrastFactor * (red - 128) + 128);
170
- green = clampByte(contrastFactor * (green - 128) + 128);
171
- blue = clampByte(contrastFactor * (blue - 128) + 128);
172
- }
173
- if ((preprocess === null || preprocess === void 0 ? void 0 : preprocess.threshold) !== undefined) {
174
- const threshold = clampByte(preprocess.threshold);
175
- const value = red >= threshold ? 255 : 0;
176
- red = value;
177
- green = value;
178
- blue = value;
179
- }
180
- data[index] = red;
181
- data[index + 1] = green;
182
- data[index + 2] = blue;
183
- }
184
- context.putImageData(imageData, 0, 0);
185
- return new Promise((resolve, reject) => {
186
- canvas.toBlob((blob) => {
187
- if (!blob) {
188
- reject(new Error("Unable to prepare image for OCR."));
189
- return;
190
- }
191
- resolve(blob);
192
- }, "image/png");
193
- });
194
- });
195
- export const getImageTextContent = (image_1, ...args_1) => __awaiter(void 0, [image_1, ...args_1], void 0, function* (image, options = {}) {
196
- if (!image.type.startsWith("image/")) {
197
- throw new Error("getImageTextContent requires an image File.");
198
- }
199
- const { language, onProgress, parameters, preprocess, recognizeOptions, workerOptions, } = getResolvedOptions(options);
200
- const { createWorker } = yield import("tesseract.js");
201
- let worker;
202
- try {
203
- worker = yield createWorker(language, undefined, Object.assign(Object.assign({}, workerOptions), { logger: ({ progress, status }) => {
204
- onProgress === null || onProgress === void 0 ? void 0 : onProgress({ progress, status });
205
- } }));
206
- if (parameters && Object.keys(parameters).length > 0) {
207
- yield worker.setParameters(parameters);
208
- }
209
- const ocrImage = yield preprocessImage(image, preprocess);
210
- const result = yield worker.recognize(ocrImage, recognizeOptions, { text: true, blocks: true });
211
- const { data } = result;
212
- return {
213
- text: data.text,
214
- confidence: data.confidence,
215
- language,
216
- lines: getLinesFromPage(data),
217
- };
218
- }
219
- finally {
220
- yield (worker === null || worker === void 0 ? void 0 : worker.terminate());
221
- }
222
- });