@medway-ui/native 1.9.2 → 1.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/lib/commonjs/components/Alert.js +36 -25
- package/lib/commonjs/components/Alert.js.map +1 -1
- package/lib/commonjs/components/AlertDialog.js +22 -23
- package/lib/commonjs/components/AlertDialog.js.map +1 -1
- package/lib/commonjs/components/Avatar.js +4 -4
- package/lib/commonjs/components/Badge.js +22 -15
- package/lib/commonjs/components/Badge.js.map +1 -1
- package/lib/commonjs/components/Button.js +56 -42
- package/lib/commonjs/components/Button.js.map +1 -1
- package/lib/commonjs/components/CardNews.js +18 -13
- package/lib/commonjs/components/CardNews.js.map +1 -1
- package/lib/commonjs/components/Carousel.js +12 -8
- package/lib/commonjs/components/Carousel.js.map +1 -1
- package/lib/commonjs/components/Checkbox.js +5 -5
- package/lib/commonjs/components/Checkbox.js.map +1 -1
- package/lib/commonjs/components/Chip.js +52 -23
- package/lib/commonjs/components/Chip.js.map +1 -1
- package/lib/commonjs/components/Choice.js +26 -12
- package/lib/commonjs/components/Choice.js.map +1 -1
- package/lib/commonjs/components/Dialog.js +16 -8
- package/lib/commonjs/components/Dialog.js.map +1 -1
- package/lib/commonjs/components/DropdownMenu.js +35 -14
- package/lib/commonjs/components/DropdownMenu.js.map +1 -1
- package/lib/commonjs/components/EmptyState.js +5 -5
- package/lib/commonjs/components/EmptyState.js.map +1 -1
- package/lib/commonjs/components/FallbackImage.js +42 -35
- package/lib/commonjs/components/FallbackImage.js.map +1 -1
- package/lib/commonjs/components/Feed.js +6 -5
- package/lib/commonjs/components/Feed.js.map +1 -1
- package/lib/commonjs/components/FeedNotice.js +3 -3
- package/lib/commonjs/components/Feedback.js +2 -4
- package/lib/commonjs/components/Feedback.js.map +1 -1
- package/lib/commonjs/components/Filter.js +6 -9
- package/lib/commonjs/components/Filter.js.map +1 -1
- package/lib/commonjs/components/IndexLevel.js +4 -4
- package/lib/commonjs/components/Input.js +25 -20
- package/lib/commonjs/components/Input.js.map +1 -1
- package/lib/commonjs/components/InvitePopover.js +19 -8
- package/lib/commonjs/components/InvitePopover.js.map +1 -1
- package/lib/commonjs/components/Label.js +2 -2
- package/lib/commonjs/components/LeaderboardCard.js +3 -2
- package/lib/commonjs/components/LeaderboardCard.js.map +1 -1
- package/lib/commonjs/components/Loading.js +18 -15
- package/lib/commonjs/components/Loading.js.map +1 -1
- package/lib/commonjs/components/LoadingOverlay.js +36 -43
- package/lib/commonjs/components/LoadingOverlay.js.map +1 -1
- package/lib/commonjs/components/MemberRow.js +7 -6
- package/lib/commonjs/components/MemberRow.js.map +1 -1
- package/lib/commonjs/components/PageHeader.js +3 -2
- package/lib/commonjs/components/PageHeader.js.map +1 -1
- package/lib/commonjs/components/Popover.js +1 -1
- package/lib/commonjs/components/PostForm.js +38 -24
- package/lib/commonjs/components/PostForm.js.map +1 -1
- package/lib/commonjs/components/PrizeCollection.js +5 -5
- package/lib/commonjs/components/PrizeCollection.js.map +1 -1
- package/lib/commonjs/components/RadioGroup.js +65 -15
- package/lib/commonjs/components/RadioGroup.js.map +1 -1
- package/lib/commonjs/components/SectionHeader.js +3 -2
- package/lib/commonjs/components/SectionHeader.js.map +1 -1
- package/lib/commonjs/components/SegmentControl.js +4 -4
- package/lib/commonjs/components/Select.js +7 -6
- package/lib/commonjs/components/Select.js.map +1 -1
- package/lib/commonjs/components/Separator.js +2 -2
- package/lib/commonjs/components/Separator.js.map +1 -1
- package/lib/commonjs/components/Sheet.js +17 -11
- package/lib/commonjs/components/Sheet.js.map +1 -1
- package/lib/commonjs/components/Skeleton.js +2 -2
- package/lib/commonjs/components/Skeleton.js.map +1 -1
- package/lib/commonjs/components/Switch.js +3 -3
- package/lib/commonjs/components/Tabs.js +3 -2
- package/lib/commonjs/components/Tabs.js.map +1 -1
- package/lib/commonjs/components/Tag.js +52 -32
- package/lib/commonjs/components/Tag.js.map +1 -1
- package/lib/commonjs/components/Text.js +1 -1
- package/lib/commonjs/components/ThemedIcon.js +1 -1
- package/lib/commonjs/components/Toast.js +12 -12
- package/lib/commonjs/components/Toast.js.map +1 -1
- package/lib/commonjs/components/Tooltip.js +2 -2
- package/lib/commonjs/editor/NoteEditor.js +190 -67
- package/lib/commonjs/editor/NoteEditor.js.map +1 -1
- package/lib/commonjs/editor/editorHtml.generated.js +1 -1
- package/lib/commonjs/editor/editorHtml.generated.js.map +1 -1
- package/lib/commonjs/editor/index.js.map +1 -1
- package/lib/commonjs/editor/protocol.js +1 -2
- package/lib/commonjs/editor/protocol.js.map +1 -1
- package/lib/commonjs/hooks/useThemeColor.js +41 -19
- package/lib/commonjs/hooks/useThemeColor.js.map +1 -1
- package/lib/commonjs/index.js +46 -46
- package/lib/commonjs/lib/backdrop.js +18 -0
- package/lib/commonjs/lib/backdrop.js.map +1 -0
- package/lib/commonjs/lib/overlay-host.js +5 -3
- package/lib/commonjs/lib/overlay-host.js.map +1 -1
- package/lib/commonjs/lib/raised-surface.js +1 -1
- package/lib/module/components/Alert.js +36 -25
- package/lib/module/components/Alert.js.map +1 -1
- package/lib/module/components/AlertDialog.js +21 -22
- package/lib/module/components/AlertDialog.js.map +1 -1
- package/lib/module/components/Avatar.js +4 -4
- package/lib/module/components/Badge.js +22 -15
- package/lib/module/components/Badge.js.map +1 -1
- package/lib/module/components/Button.js +56 -42
- package/lib/module/components/Button.js.map +1 -1
- package/lib/module/components/CardNews.js +18 -13
- package/lib/module/components/CardNews.js.map +1 -1
- package/lib/module/components/Carousel.js +12 -8
- package/lib/module/components/Carousel.js.map +1 -1
- package/lib/module/components/Checkbox.js +5 -5
- package/lib/module/components/Checkbox.js.map +1 -1
- package/lib/module/components/Chip.js +52 -23
- package/lib/module/components/Chip.js.map +1 -1
- package/lib/module/components/Choice.js +26 -12
- package/lib/module/components/Choice.js.map +1 -1
- package/lib/module/components/Dialog.js +16 -8
- package/lib/module/components/Dialog.js.map +1 -1
- package/lib/module/components/DropdownMenu.js +36 -15
- package/lib/module/components/DropdownMenu.js.map +1 -1
- package/lib/module/components/EmptyState.js +5 -5
- package/lib/module/components/EmptyState.js.map +1 -1
- package/lib/module/components/FallbackImage.js +42 -35
- package/lib/module/components/FallbackImage.js.map +1 -1
- package/lib/module/components/Feed.js +6 -5
- package/lib/module/components/Feed.js.map +1 -1
- package/lib/module/components/FeedNotice.js +3 -3
- package/lib/module/components/Feedback.js +2 -4
- package/lib/module/components/Feedback.js.map +1 -1
- package/lib/module/components/Filter.js +6 -9
- package/lib/module/components/Filter.js.map +1 -1
- package/lib/module/components/IndexLevel.js +4 -4
- package/lib/module/components/Input.js +24 -18
- package/lib/module/components/Input.js.map +1 -1
- package/lib/module/components/InvitePopover.js +20 -9
- package/lib/module/components/InvitePopover.js.map +1 -1
- package/lib/module/components/Label.js +2 -2
- package/lib/module/components/LeaderboardCard.js +3 -2
- package/lib/module/components/LeaderboardCard.js.map +1 -1
- package/lib/module/components/Loading.js +18 -15
- package/lib/module/components/Loading.js.map +1 -1
- package/lib/module/components/LoadingOverlay.js +37 -44
- package/lib/module/components/LoadingOverlay.js.map +1 -1
- package/lib/module/components/MemberRow.js +7 -6
- package/lib/module/components/MemberRow.js.map +1 -1
- package/lib/module/components/PageHeader.js +3 -2
- package/lib/module/components/PageHeader.js.map +1 -1
- package/lib/module/components/Popover.js +1 -1
- package/lib/module/components/PostForm.js +38 -24
- package/lib/module/components/PostForm.js.map +1 -1
- package/lib/module/components/PrizeCollection.js +5 -5
- package/lib/module/components/PrizeCollection.js.map +1 -1
- package/lib/module/components/RadioGroup.js +65 -15
- package/lib/module/components/RadioGroup.js.map +1 -1
- package/lib/module/components/SectionHeader.js +3 -2
- package/lib/module/components/SectionHeader.js.map +1 -1
- package/lib/module/components/SegmentControl.js +4 -4
- package/lib/module/components/Select.js +6 -5
- package/lib/module/components/Select.js.map +1 -1
- package/lib/module/components/Separator.js +2 -2
- package/lib/module/components/Separator.js.map +1 -1
- package/lib/module/components/Sheet.js +17 -11
- package/lib/module/components/Sheet.js.map +1 -1
- package/lib/module/components/Skeleton.js +2 -2
- package/lib/module/components/Skeleton.js.map +1 -1
- package/lib/module/components/Switch.js +3 -3
- package/lib/module/components/Tabs.js +3 -2
- package/lib/module/components/Tabs.js.map +1 -1
- package/lib/module/components/Tag.js +52 -32
- package/lib/module/components/Tag.js.map +1 -1
- package/lib/module/components/Text.js +1 -1
- package/lib/module/components/ThemedIcon.js +1 -1
- package/lib/module/components/Toast.js +12 -12
- package/lib/module/components/Toast.js.map +1 -1
- package/lib/module/components/Tooltip.js +2 -2
- package/lib/module/editor/NoteEditor.js +193 -69
- package/lib/module/editor/NoteEditor.js.map +1 -1
- package/lib/module/editor/editorHtml.generated.js +1 -1
- package/lib/module/editor/editorHtml.generated.js.map +1 -1
- package/lib/module/editor/index.js.map +1 -1
- package/lib/module/editor/protocol.js +1 -2
- package/lib/module/editor/protocol.js.map +1 -1
- package/lib/module/hooks/useThemeColor.js +41 -19
- package/lib/module/hooks/useThemeColor.js.map +1 -1
- package/lib/module/index.js +46 -46
- package/lib/module/lib/backdrop.js +15 -0
- package/lib/module/lib/backdrop.js.map +1 -0
- package/lib/module/lib/overlay-host.js +6 -4
- package/lib/module/lib/overlay-host.js.map +1 -1
- package/lib/module/lib/raised-surface.js +1 -1
- package/lib/typescript/components/Alert.d.ts +1 -1
- package/lib/typescript/components/Alert.d.ts.map +1 -1
- package/lib/typescript/components/AlertDialog.d.ts +1 -1
- package/lib/typescript/components/AlertDialog.d.ts.map +1 -1
- package/lib/typescript/components/Badge.d.ts.map +1 -1
- package/lib/typescript/components/Button.d.ts +1 -0
- package/lib/typescript/components/Button.d.ts.map +1 -1
- package/lib/typescript/components/CardNews.d.ts +7 -2
- package/lib/typescript/components/CardNews.d.ts.map +1 -1
- package/lib/typescript/components/Checkbox.d.ts +3 -1
- package/lib/typescript/components/Checkbox.d.ts.map +1 -1
- package/lib/typescript/components/Chip.d.ts.map +1 -1
- package/lib/typescript/components/Choice.d.ts +4 -1
- package/lib/typescript/components/Choice.d.ts.map +1 -1
- package/lib/typescript/components/Dialog.d.ts +2 -1
- package/lib/typescript/components/Dialog.d.ts.map +1 -1
- package/lib/typescript/components/DropdownMenu.d.ts +3 -2
- package/lib/typescript/components/DropdownMenu.d.ts.map +1 -1
- package/lib/typescript/components/FallbackImage.d.ts.map +1 -1
- package/lib/typescript/components/Feed.d.ts.map +1 -1
- package/lib/typescript/components/Feedback.d.ts.map +1 -1
- package/lib/typescript/components/Filter.d.ts.map +1 -1
- package/lib/typescript/components/IndexLevel.d.ts +1 -1
- package/lib/typescript/components/Input.d.ts +5 -5
- package/lib/typescript/components/Input.d.ts.map +1 -1
- package/lib/typescript/components/InvitePopover.d.ts +1 -1
- package/lib/typescript/components/InvitePopover.d.ts.map +1 -1
- package/lib/typescript/components/LeaderboardCard.d.ts.map +1 -1
- package/lib/typescript/components/Loading.d.ts +1 -1
- package/lib/typescript/components/Loading.d.ts.map +1 -1
- package/lib/typescript/components/LoadingOverlay.d.ts +9 -9
- package/lib/typescript/components/LoadingOverlay.d.ts.map +1 -1
- package/lib/typescript/components/PageHeader.d.ts.map +1 -1
- package/lib/typescript/components/PostForm.d.ts.map +1 -1
- package/lib/typescript/components/RadioGroup.d.ts +4 -2
- package/lib/typescript/components/RadioGroup.d.ts.map +1 -1
- package/lib/typescript/components/SectionHeader.d.ts.map +1 -1
- package/lib/typescript/components/SegmentControl.d.ts +1 -1
- package/lib/typescript/components/Select.d.ts +2 -1
- package/lib/typescript/components/Select.d.ts.map +1 -1
- package/lib/typescript/components/Separator.d.ts.map +1 -1
- package/lib/typescript/components/Sheet.d.ts +2 -1
- package/lib/typescript/components/Sheet.d.ts.map +1 -1
- package/lib/typescript/components/Tabs.d.ts +4 -3
- package/lib/typescript/components/Tabs.d.ts.map +1 -1
- package/lib/typescript/components/Tag.d.ts +3 -1
- package/lib/typescript/components/Tag.d.ts.map +1 -1
- package/lib/typescript/components/ThemedIcon.d.ts +1 -1
- package/lib/typescript/components/Toast.d.ts +1 -1
- package/lib/typescript/components/Toast.d.ts.map +1 -1
- package/lib/typescript/editor/NoteEditor.d.ts +28 -8
- package/lib/typescript/editor/NoteEditor.d.ts.map +1 -1
- package/lib/typescript/editor/editorHtml.generated.d.ts.map +1 -1
- package/lib/typescript/editor/index.d.ts +1 -1
- package/lib/typescript/editor/index.d.ts.map +1 -1
- package/lib/typescript/editor/protocol.d.ts +4 -14
- package/lib/typescript/editor/protocol.d.ts.map +1 -1
- package/lib/typescript/hooks/use-toast.d.ts +1 -1
- package/lib/typescript/hooks/useThemeColor.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +91 -91
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/lib/backdrop.d.ts +4 -0
- package/lib/typescript/lib/backdrop.d.ts.map +1 -0
- package/lib/typescript/lib/overlay-host.d.ts +1 -0
- package/lib/typescript/lib/overlay-host.d.ts.map +1 -1
- package/package.json +9 -14
- package/setup/tailwind.js +16 -8
- package/setup/tokens.native.css +181 -80
- package/src/components/Alert.tsx +37 -20
- package/src/components/AlertDialog.tsx +18 -19
- package/src/components/Badge.tsx +16 -15
- package/src/components/Button.tsx +64 -31
- package/src/components/CardNews.tsx +17 -6
- package/src/components/Carousel.tsx +5 -5
- package/src/components/Checkbox.tsx +17 -7
- package/src/components/Chip.tsx +49 -21
- package/src/components/Choice.tsx +34 -14
- package/src/components/Dialog.tsx +15 -5
- package/src/components/DropdownMenu.tsx +62 -14
- package/src/components/EmptyState.tsx +3 -3
- package/src/components/FallbackImage.tsx +32 -23
- package/src/components/Feed.tsx +2 -1
- package/src/components/Feedback.tsx +0 -1
- package/src/components/Filter.tsx +2 -3
- package/src/components/Input.tsx +83 -64
- package/src/components/InvitePopover.tsx +11 -3
- package/src/components/LeaderboardCard.tsx +4 -1
- package/src/components/Loading.tsx +17 -14
- package/src/components/LoadingOverlay.tsx +33 -50
- package/src/components/MemberRow.tsx +3 -3
- package/src/components/PageHeader.tsx +4 -1
- package/src/components/PostForm.tsx +28 -16
- package/src/components/PrizeCollection.tsx +3 -3
- package/src/components/RadioGroup.tsx +69 -12
- package/src/components/SectionHeader.tsx +4 -1
- package/src/components/Select.tsx +4 -3
- package/src/components/Separator.tsx +2 -2
- package/src/components/Sheet.tsx +15 -8
- package/src/components/Skeleton.tsx +1 -1
- package/src/components/Tabs.tsx +5 -4
- package/src/components/Tag.tsx +56 -35
- package/src/components/Toast.tsx +10 -6
- package/src/editor/NoteEditor.tsx +246 -72
- package/src/editor/editorHtml.generated.ts +1 -1
- package/src/editor/index.ts +8 -4
- package/src/editor/protocol.ts +4 -12
- package/src/hooks/useThemeColor.ts +41 -19
- package/src/index.ts +1 -1
- package/src/lib/backdrop.ts +16 -0
- package/src/lib/overlay-host.tsx +5 -5
|
@@ -4,25 +4,28 @@ import { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useMemo,
|
|
|
4
4
|
import { Platform, Pressable, ScrollView, StyleSheet, Text as RNText, TextInput, View } from "react-native";
|
|
5
5
|
import UntypedWebView from "react-native-webview";
|
|
6
6
|
import { useColorScheme } from "nativewind";
|
|
7
|
-
import {
|
|
8
|
-
import { EMPTY_DOCUMENT, EMPTY_SLASH_STATE, INITIAL_EDITOR_STATE, getSlashCommand, normalizeDocument } from "@medway-ui/notes-core";
|
|
7
|
+
import { EMPTY_DOCUMENT, EMPTY_SLASH_STATE, INITIAL_EDITOR_STATE, getSlashCommand, normalizeDocument, normalizeLinkInput, sanitizeImageSrc } from "@medway-ui/notes-core";
|
|
9
8
|
import { ArrowUndoUpLeft, Bold, Code, DoubleQuotesL, HeadingH2, HeadingH3, Image as ImageIcon, Italic, Link as LinkIcon, ListOrdered, ListUnordered, Redo, Strikethrough, Underline, WindowCodeBlock } from "@medway-ui/icons/native";
|
|
10
|
-
import { Button } from "
|
|
11
|
-
import { Input } from "
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
9
|
+
import { Button } from "../components/Button";
|
|
10
|
+
import { Input } from "../components/Input";
|
|
11
|
+
import { Text } from "../components/Text";
|
|
12
|
+
import { Dialog, DialogContainer, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "../components/Dialog";
|
|
13
|
+
import { EDITOR_HTML } from "./editorHtml.generated";
|
|
14
|
+
import { EDITOR_PROTOCOL_VERSION, EDITOR_RECEIVE_HANDLER, isEditorMessage } from "./protocol";
|
|
15
|
+
import { DEFAULT_COLOR, useThemeColor } from "../hooks/useThemeColor";
|
|
16
|
+
import { getMinTouchHitSlop } from "../lib/touch-target";
|
|
17
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
14
18
|
function useEditorThemeColor(token, fallback) {
|
|
15
19
|
const value = useThemeColor(token);
|
|
16
20
|
return value === DEFAULT_COLOR ? fallback : value;
|
|
17
21
|
}
|
|
18
|
-
import { EDITOR_PROTOCOL_VERSION, EDITOR_RECEIVE_HANDLER, isEditorMessage } from "./protocol";
|
|
19
22
|
|
|
20
23
|
/**
|
|
21
24
|
* The ref surface of `react-native-webview`, kept local so consumers need not
|
|
22
25
|
* depend on internal WebView types. Internal only — `NoteEditorHandle` below is
|
|
23
26
|
* the public ref shape.
|
|
24
27
|
*/
|
|
25
|
-
|
|
28
|
+
|
|
26
29
|
/**
|
|
27
30
|
* Retyped locally: the library's own `WebView` resolves to `Component<never>`
|
|
28
31
|
* under `strict` and rejects every JSX prop.
|
|
@@ -43,7 +46,35 @@ const WebView = UntypedWebView;
|
|
|
43
46
|
|
|
44
47
|
/** The title is single-line; newlines can still arrive via paste. */
|
|
45
48
|
const sanitizeTitle = value => value.replace(/\r?\n/g, " ");
|
|
46
|
-
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Enter in the multiline title still commits a "\n" (`onKeyPress` cannot
|
|
52
|
+
* cancel it): one newline added to the previous title is that key, dropped
|
|
53
|
+
* instead of becoming a trailing space. Pasted newlines still become spaces.
|
|
54
|
+
*/
|
|
55
|
+
const nextTitle = (previous, value) => value.replace(/\r?\n/, "") === previous ? previous : sanitizeTitle(value);
|
|
56
|
+
const TOOLBAR_BUTTON_SIZE = 32;
|
|
57
|
+
const SLASH_MENU_WIDTH = 256;
|
|
58
|
+
const SLASH_MENU_GAP = 6;
|
|
59
|
+
|
|
60
|
+
/** Starts at the caret, pulled left so the menu never crosses the editor's right edge. */
|
|
61
|
+
const getSlashMenuLeft = (caretX, editorWidth) => editorWidth > 0 ? Math.max(SLASH_MENU_GAP, Math.min(caretX, editorWidth - SLASH_MENU_WIDTH - SLASH_MENU_GAP)) : caretX;
|
|
62
|
+
const TOOLBAR_BUTTON_HIT_SLOP = getMinTouchHitSlop(TOOLBAR_BUTTON_SIZE);
|
|
63
|
+
const MAX_WEBVIEW_REMOUNTS = 3;
|
|
64
|
+
const WEBVIEW_REMOUNT_WINDOW_MS = 60_000;
|
|
65
|
+
const collectImageSrcs = doc => {
|
|
66
|
+
const srcs = new Set();
|
|
67
|
+
const walk = nodes => {
|
|
68
|
+
nodes.forEach(node => {
|
|
69
|
+
if (node.type === "image" && typeof node.attrs?.src === "string") {
|
|
70
|
+
srcs.add(node.attrs.src);
|
|
71
|
+
}
|
|
72
|
+
if (node.content) walk(node.content);
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
walk(doc.content);
|
|
76
|
+
return srcs;
|
|
77
|
+
};
|
|
47
78
|
let requestCounter = 0;
|
|
48
79
|
/** Correlates a `getDocument` request with the `document` response that answers it. */
|
|
49
80
|
const nextRequestId = () => {
|
|
@@ -62,10 +93,11 @@ const useNoteEditorTheme = () => {
|
|
|
62
93
|
} = useColorScheme();
|
|
63
94
|
const background = useThemeColor("surface-card");
|
|
64
95
|
const text = useThemeColor("content-paragraph");
|
|
65
|
-
const heading = useThemeColor("
|
|
96
|
+
const heading = useThemeColor("gray-foreground");
|
|
66
97
|
const muted = useThemeColor("gray-foreground-muted");
|
|
67
98
|
const border = useThemeColor("gray-stroke-muted");
|
|
68
99
|
const accent = useThemeColor("primary-foreground");
|
|
100
|
+
const link = useThemeColor("content-link");
|
|
69
101
|
const codeBackground = useEditorThemeColor("gray-background-soft", "#F0F1F5");
|
|
70
102
|
return useMemo(() => ({
|
|
71
103
|
colorScheme: colorScheme === "dark" ? "dark" : "light",
|
|
@@ -76,6 +108,7 @@ const useNoteEditorTheme = () => {
|
|
|
76
108
|
placeholder: muted,
|
|
77
109
|
border,
|
|
78
110
|
accent,
|
|
111
|
+
link,
|
|
79
112
|
caret: accent,
|
|
80
113
|
selection: border,
|
|
81
114
|
codeBackground,
|
|
@@ -86,7 +119,7 @@ const useNoteEditorTheme = () => {
|
|
|
86
119
|
paddingHorizontal: 16,
|
|
87
120
|
paddingTop: 12,
|
|
88
121
|
paddingBottom: 32
|
|
89
|
-
}), [colorScheme, background, text, heading, muted, border, accent, codeBackground]);
|
|
122
|
+
}), [colorScheme, background, text, heading, muted, border, accent, link, codeBackground]);
|
|
90
123
|
};
|
|
91
124
|
|
|
92
125
|
/** Every icon exported from `@medway-ui/icons/native` shares this component shape. */
|
|
@@ -219,14 +252,13 @@ const visibleSlashCommandIds = (commandIds, canUploadImage) => canUploadImage ?
|
|
|
219
252
|
const NoteEditor = /*#__PURE__*/forwardRef(({
|
|
220
253
|
document: initialDocument,
|
|
221
254
|
initialTitle,
|
|
222
|
-
titlePlaceholder = "
|
|
255
|
+
titlePlaceholder = "Título",
|
|
223
256
|
onChange,
|
|
224
257
|
editable = true,
|
|
225
258
|
autofocus = false,
|
|
226
259
|
toolbar = false,
|
|
227
260
|
onImageUpload,
|
|
228
261
|
onImageRemoved,
|
|
229
|
-
imageDeleteGraceMs = DEFAULT_IMAGE_DELETE_GRACE_MS,
|
|
230
262
|
onLinkPress,
|
|
231
263
|
height,
|
|
232
264
|
backgroundColor,
|
|
@@ -243,11 +275,9 @@ const NoteEditor = /*#__PURE__*/forwardRef(({
|
|
|
243
275
|
const [title, setTitle] = useState(() => sanitizeTitle(initialTitle ?? ""));
|
|
244
276
|
const titleInputRef = useRef(null);
|
|
245
277
|
const [titleSelection, setTitleSelection] = useState(undefined);
|
|
246
|
-
const autofocusTitleRef = useRef(autofocus
|
|
278
|
+
const autofocusTitleRef = useRef(Boolean(autofocus) && title.length === 0);
|
|
247
279
|
useEffect(() => {
|
|
248
280
|
if (autofocusTitleRef.current) titleInputRef.current?.focus();
|
|
249
|
-
// Mount-only: the one-time "new note" autofocus decision.
|
|
250
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
251
281
|
}, []);
|
|
252
282
|
const focusTitleAtEnd = useCallback(() => {
|
|
253
283
|
titleInputRef.current?.focus();
|
|
@@ -273,11 +303,41 @@ const NoteEditor = /*#__PURE__*/forwardRef(({
|
|
|
273
303
|
setIsReady(false);
|
|
274
304
|
setSlashState(EMPTY_SLASH_STATE);
|
|
275
305
|
}, []);
|
|
306
|
+
const [webViewKey, setWebViewKey] = useState(0);
|
|
307
|
+
const recentCrashesRef = useRef([]);
|
|
308
|
+
|
|
309
|
+
// A WebView whose content/render process died can't be reused (Android
|
|
310
|
+
// tears it down after `onRenderProcessGone`), so a fresh one is mounted.
|
|
311
|
+
// Capped, so a document that crashes it on every load doesn't loop.
|
|
312
|
+
const handleWebViewCrash = useCallback(() => {
|
|
313
|
+
handleWebViewReset();
|
|
314
|
+
const now = Date.now();
|
|
315
|
+
const recent = recentCrashesRef.current.filter(crashedAt => now - crashedAt < WEBVIEW_REMOUNT_WINDOW_MS);
|
|
316
|
+
if (recent.length >= MAX_WEBVIEW_REMOUNTS) {
|
|
317
|
+
recentCrashesRef.current = recent;
|
|
318
|
+
console.error(`@medway-ui/native NoteEditor: the editor WebView crashed ${MAX_WEBVIEW_REMOUNTS + 1} times within ${WEBVIEW_REMOUNT_WINDOW_MS / 1000}s; not remounting it again.`);
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
recentCrashesRef.current = [...recent, now];
|
|
322
|
+
setWebViewKey(key => key + 1);
|
|
323
|
+
}, [handleWebViewReset]);
|
|
324
|
+
|
|
325
|
+
// What `setContent` sends on every `ready`, so a remount after a crash comes
|
|
326
|
+
// back with the latest content the host has seen rather than `initialDocument`.
|
|
327
|
+
const lastKnownContentRef = useRef(initialDocument ?? EMPTY_DOCUMENT);
|
|
328
|
+
const uploadedThisSessionRef = useRef(new Set());
|
|
329
|
+
const isMountedRef = useRef(true);
|
|
330
|
+
const hasLoadedContentRef = useRef(false);
|
|
331
|
+
// Bumped by `setDocument`: a `document` answering a request made before it
|
|
332
|
+
// describes the replaced note.
|
|
333
|
+
const documentGenerationRef = useRef(0);
|
|
276
334
|
const pendingDocumentRequests = useRef(new Map());
|
|
277
335
|
const requestDocument = useCallback(() => {
|
|
278
336
|
const requestId = nextRequestId();
|
|
337
|
+
const generation = documentGenerationRef.current;
|
|
279
338
|
return new Promise((resolve, reject) => {
|
|
280
339
|
pendingDocumentRequests.current.set(requestId, {
|
|
340
|
+
generation,
|
|
281
341
|
resolve,
|
|
282
342
|
reject
|
|
283
343
|
});
|
|
@@ -308,23 +368,35 @@ const NoteEditor = /*#__PURE__*/forwardRef(({
|
|
|
308
368
|
useEffect(() => {
|
|
309
369
|
onLinkPressRef.current = onLinkPress;
|
|
310
370
|
}, [onLinkPress]);
|
|
371
|
+
useEffect(() => {
|
|
372
|
+
isMountedRef.current = true;
|
|
373
|
+
return () => {
|
|
374
|
+
isMountedRef.current = false;
|
|
375
|
+
};
|
|
376
|
+
}, []);
|
|
311
377
|
const insertImage = useCallback(async () => {
|
|
312
378
|
const upload = onImageUploadRef.current;
|
|
313
379
|
if (!upload || !editableRef.current) return;
|
|
314
380
|
try {
|
|
315
381
|
const result = await upload();
|
|
316
382
|
if (!result) return;
|
|
317
|
-
if (!editableRef.current) {
|
|
383
|
+
if (!isMountedRef.current || !editableRef.current) {
|
|
384
|
+
onImageRemovedRef.current?.(result.src);
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
const src = sanitizeImageSrc(result.src);
|
|
388
|
+
if (!src) {
|
|
389
|
+
console.error("@medway-ui/native NoteEditor: onImageUpload resolved with an unsupported URL (only absolute http(s): or data:)", result.src);
|
|
318
390
|
onImageRemovedRef.current?.(result.src);
|
|
319
391
|
return;
|
|
320
392
|
}
|
|
393
|
+
uploadedThisSessionRef.current.add(src);
|
|
321
394
|
sendMutation({
|
|
322
395
|
type: "insertImage",
|
|
323
|
-
src
|
|
396
|
+
src,
|
|
324
397
|
alt: result.alt ?? null
|
|
325
398
|
});
|
|
326
399
|
} catch (error) {
|
|
327
|
-
// eslint-disable-next-line no-console
|
|
328
400
|
console.error("@medway-ui/native NoteEditor: onImageUpload failed", error);
|
|
329
401
|
}
|
|
330
402
|
}, [sendMutation]);
|
|
@@ -343,7 +415,6 @@ const NoteEditor = /*#__PURE__*/forwardRef(({
|
|
|
343
415
|
// Refused loudly rather than letting commands quietly not match
|
|
344
416
|
// what the bundle understands.
|
|
345
417
|
if (editorMessage.protocol !== EDITOR_PROTOCOL_VERSION) {
|
|
346
|
-
// eslint-disable-next-line no-console
|
|
347
418
|
console.error(`@medway-ui/native NoteEditor: editor bundle reports protocol ${editorMessage.protocol}, expected ${EDITOR_PROTOCOL_VERSION}. Rebuild editor-bundle (its generated HTML is stale).`);
|
|
348
419
|
return;
|
|
349
420
|
}
|
|
@@ -360,7 +431,11 @@ const NoteEditor = /*#__PURE__*/forwardRef(({
|
|
|
360
431
|
// round trip happens only when a host asked for `onChange`, which
|
|
361
432
|
// keeps serialization per-settled-keystroke, not per-keystroke.
|
|
362
433
|
if (onChangeRef.current) {
|
|
363
|
-
|
|
434
|
+
const generation = documentGenerationRef.current;
|
|
435
|
+
requestDocument().then(doc => {
|
|
436
|
+
if (generation !== documentGenerationRef.current) return;
|
|
437
|
+
onChangeRef.current?.(doc);
|
|
438
|
+
}).catch(() => {});
|
|
364
439
|
}
|
|
365
440
|
return;
|
|
366
441
|
case "document":
|
|
@@ -372,7 +447,13 @@ const NoteEditor = /*#__PURE__*/forwardRef(({
|
|
|
372
447
|
// whitelist/depth pass is what makes it an `EditorDocument`, and it
|
|
373
448
|
// runs on the way out too, not just on `setContent` — the WebView
|
|
374
449
|
// renders student content, so what it hands back is untrusted.
|
|
375
|
-
|
|
450
|
+
const doc = normalizeDocument(editorMessage.doc);
|
|
451
|
+
// Still the answer to what was asked, but no longer the content
|
|
452
|
+
// to restore after a crash.
|
|
453
|
+
if (pending.generation === documentGenerationRef.current) {
|
|
454
|
+
lastKnownContentRef.current = doc;
|
|
455
|
+
}
|
|
456
|
+
pending.resolve(doc);
|
|
376
457
|
return;
|
|
377
458
|
}
|
|
378
459
|
case "resize":
|
|
@@ -384,11 +465,7 @@ const NoteEditor = /*#__PURE__*/forwardRef(({
|
|
|
384
465
|
case "backspaceAtDocStart":
|
|
385
466
|
focusTitleAtEnd();
|
|
386
467
|
return;
|
|
387
|
-
case "imageRemoved":
|
|
388
|
-
onImageRemovedRef.current?.(editorMessage.src);
|
|
389
|
-
return;
|
|
390
468
|
case "error":
|
|
391
|
-
// eslint-disable-next-line no-console
|
|
392
469
|
console.error("@medway-ui/native NoteEditor:", editorMessage.message);
|
|
393
470
|
return;
|
|
394
471
|
default:
|
|
@@ -396,25 +473,24 @@ const NoteEditor = /*#__PURE__*/forwardRef(({
|
|
|
396
473
|
}
|
|
397
474
|
}, [focusTitleAtEnd, isEmbedded, requestDocument]);
|
|
398
475
|
|
|
399
|
-
// Fires
|
|
400
|
-
//
|
|
476
|
+
// Fires on every `ready`: the first load, and the remount after a crash.
|
|
477
|
+
// `editable`/`autofocus` stay out of deps on purpose: they seed the editor
|
|
478
|
+
// the bundle builds on load; `editable` is kept in sync by the next effect.
|
|
401
479
|
useEffect(() => {
|
|
402
480
|
if (!isReady) return;
|
|
481
|
+
const isFirstLoad = !hasLoadedContentRef.current;
|
|
482
|
+
hasLoadedContentRef.current = true;
|
|
403
483
|
send({
|
|
404
484
|
type: "setContent",
|
|
405
|
-
doc:
|
|
485
|
+
doc: lastKnownContentRef.current,
|
|
406
486
|
editable,
|
|
407
|
-
focus: autofocusTitleRef.current
|
|
408
|
-
focusPosition: typeof autofocus === "string" ? autofocus : undefined
|
|
409
|
-
imageDeleteGraceMs
|
|
487
|
+
focus: isFirstLoad && !autofocusTitleRef.current && Boolean(autofocus),
|
|
488
|
+
focusPosition: typeof autofocus === "string" ? autofocus : undefined
|
|
410
489
|
});
|
|
411
490
|
if (isEmbedded) send({
|
|
412
491
|
type: "setLayout",
|
|
413
492
|
embedded: true
|
|
414
493
|
});
|
|
415
|
-
// `editable`/`autofocus`/`imageDeleteGraceMs` are excluded from deps on
|
|
416
|
-
// purpose: they seed the *initial* editor, like `document`.
|
|
417
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
418
494
|
}, [isReady, send]);
|
|
419
495
|
|
|
420
496
|
// `editable` is the one prop that stays reactive after mount.
|
|
@@ -442,37 +518,72 @@ const NoteEditor = /*#__PURE__*/forwardRef(({
|
|
|
442
518
|
type: "blur"
|
|
443
519
|
}),
|
|
444
520
|
getDocument: () => requestDocument(),
|
|
445
|
-
getSaveData: async () =>
|
|
446
|
-
|
|
447
|
-
json
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
521
|
+
getSaveData: async () => {
|
|
522
|
+
const generation = documentGenerationRef.current;
|
|
523
|
+
const json = await requestDocument();
|
|
524
|
+
// After a `setDocument` the session uploads belong to the new note.
|
|
525
|
+
if (generation !== documentGenerationRef.current) {
|
|
526
|
+
return {
|
|
527
|
+
title,
|
|
528
|
+
json,
|
|
529
|
+
removedImages: []
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
const kept = collectImageSrcs(json);
|
|
533
|
+
const removedImages = [...uploadedThisSessionRef.current].filter(src => !kept.has(src));
|
|
534
|
+
return {
|
|
535
|
+
title,
|
|
536
|
+
json,
|
|
537
|
+
removedImages
|
|
538
|
+
};
|
|
539
|
+
},
|
|
540
|
+
setDocument: (doc, options) => {
|
|
541
|
+
documentGenerationRef.current += 1;
|
|
542
|
+
lastKnownContentRef.current = doc;
|
|
543
|
+
uploadedThisSessionRef.current.clear();
|
|
544
|
+
send({
|
|
545
|
+
type: "setContent",
|
|
546
|
+
doc,
|
|
547
|
+
editable,
|
|
548
|
+
focus: Boolean(options?.focus),
|
|
549
|
+
reset: false
|
|
550
|
+
});
|
|
551
|
+
}
|
|
456
552
|
}), [title, editable, requestDocument, send]);
|
|
457
553
|
const [linkDialogOpen, setLinkDialogOpen] = useState(false);
|
|
458
554
|
const [linkValue, setLinkValue] = useState("");
|
|
555
|
+
const [linkInvalid, setLinkInvalid] = useState(false);
|
|
459
556
|
const openLinkDialog = useCallback(() => {
|
|
460
557
|
setLinkValue(selectionState.linkHref ?? "");
|
|
558
|
+
setLinkInvalid(false);
|
|
461
559
|
setLinkDialogOpen(true);
|
|
462
560
|
}, [selectionState.linkHref]);
|
|
561
|
+
const handleLinkValueChange = useCallback(value => {
|
|
562
|
+
setLinkValue(value);
|
|
563
|
+
setLinkInvalid(false);
|
|
564
|
+
}, []);
|
|
463
565
|
const confirmLink = useCallback(() => {
|
|
464
|
-
|
|
465
|
-
|
|
566
|
+
if (!linkValue.trim()) {
|
|
567
|
+
sendMutation({
|
|
568
|
+
type: "command",
|
|
569
|
+
command: {
|
|
570
|
+
name: "unsetLink"
|
|
571
|
+
}
|
|
572
|
+
});
|
|
573
|
+
setLinkDialogOpen(false);
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
const href = normalizeLinkInput(linkValue);
|
|
577
|
+
if (!href) {
|
|
578
|
+
setLinkInvalid(true);
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
sendMutation({
|
|
466
582
|
type: "command",
|
|
467
583
|
command: {
|
|
468
584
|
name: "setLink",
|
|
469
585
|
href
|
|
470
586
|
}
|
|
471
|
-
} : {
|
|
472
|
-
type: "command",
|
|
473
|
-
command: {
|
|
474
|
-
name: "unsetLink"
|
|
475
|
-
}
|
|
476
587
|
});
|
|
477
588
|
setLinkDialogOpen(false);
|
|
478
589
|
}, [linkValue, sendMutation]);
|
|
@@ -490,6 +601,10 @@ const NoteEditor = /*#__PURE__*/forwardRef(({
|
|
|
490
601
|
if (id === "image") insertImage();
|
|
491
602
|
}, [editable, send, insertImage]);
|
|
492
603
|
const containerHeight = isEmbedded ? contentHeight : undefined;
|
|
604
|
+
const [editorWidth, setEditorWidth] = useState(0);
|
|
605
|
+
const handleEditorLayout = useCallback(event => {
|
|
606
|
+
setEditorWidth(event.nativeEvent.layout.width);
|
|
607
|
+
}, []);
|
|
493
608
|
const resolvedBackground = backgroundColor ?? theme.background;
|
|
494
609
|
return /*#__PURE__*/_jsxs(View, {
|
|
495
610
|
style: [isEmbedded ? styles.containerEmbedded : styles.container, {
|
|
@@ -505,11 +620,10 @@ const NoteEditor = /*#__PURE__*/forwardRef(({
|
|
|
505
620
|
ref: titleInputRef,
|
|
506
621
|
multiline: true,
|
|
507
622
|
value: title,
|
|
508
|
-
onChangeText: value => setTitle(
|
|
623
|
+
onChangeText: value => setTitle(previous => nextTitle(previous, value)),
|
|
509
624
|
onKeyPress: event => {
|
|
510
|
-
// Enter moves focus into the content's first block
|
|
511
|
-
//
|
|
512
|
-
// commits the `\n` before this handler runs.
|
|
625
|
+
// Enter moves focus into the content's first block; the `\n` it
|
|
626
|
+
// still commits is dropped by `nextTitle`.
|
|
513
627
|
if (event.nativeEvent.key !== "Enter") return;
|
|
514
628
|
send({
|
|
515
629
|
type: "focus",
|
|
@@ -532,6 +646,7 @@ const NoteEditor = /*#__PURE__*/forwardRef(({
|
|
|
532
646
|
style: {
|
|
533
647
|
flex: isEmbedded ? undefined : 1
|
|
534
648
|
},
|
|
649
|
+
onLayout: handleEditorLayout,
|
|
535
650
|
children: [/*#__PURE__*/_jsx(WebView, {
|
|
536
651
|
ref: webViewRef,
|
|
537
652
|
testID: testID,
|
|
@@ -549,8 +664,8 @@ const NoteEditor = /*#__PURE__*/forwardRef(({
|
|
|
549
664
|
originWhitelist: ["^about:blank$"],
|
|
550
665
|
onMessage: handleMessage,
|
|
551
666
|
onLoadStart: handleWebViewReset,
|
|
552
|
-
onContentProcessDidTerminate:
|
|
553
|
-
onRenderProcessGone:
|
|
667
|
+
onContentProcessDidTerminate: handleWebViewCrash,
|
|
668
|
+
onRenderProcessGone: handleWebViewCrash
|
|
554
669
|
// Links already leave the editor via the `linkPress` message, so
|
|
555
670
|
// nothing rendered here needs to navigate. Allowing only the
|
|
556
671
|
// initial `about:blank` load closes off `data:`/script-driven
|
|
@@ -586,8 +701,9 @@ const NoteEditor = /*#__PURE__*/forwardRef(({
|
|
|
586
701
|
} : null, {
|
|
587
702
|
backgroundColor: resolvedBackground
|
|
588
703
|
}]
|
|
589
|
-
}), slashState.active && slashState.caret ? /*#__PURE__*/_jsx(NoteEditorSlashMenu, {
|
|
704
|
+
}, webViewKey), slashState.active && slashState.caret ? /*#__PURE__*/_jsx(NoteEditorSlashMenu, {
|
|
590
705
|
slash: slashState,
|
|
706
|
+
editorWidth: editorWidth,
|
|
591
707
|
canUploadImage: Boolean(onImageUpload),
|
|
592
708
|
onSelect: handleSlashSelect
|
|
593
709
|
}) : null]
|
|
@@ -599,16 +715,21 @@ const NoteEditor = /*#__PURE__*/forwardRef(({
|
|
|
599
715
|
children: /*#__PURE__*/_jsx(DialogTitle, {
|
|
600
716
|
children: "Inserir link"
|
|
601
717
|
})
|
|
602
|
-
}), /*#__PURE__*/
|
|
603
|
-
children: /*#__PURE__*/_jsx(Input, {
|
|
718
|
+
}), /*#__PURE__*/_jsxs(DialogContent, {
|
|
719
|
+
children: [/*#__PURE__*/_jsx(Input, {
|
|
604
720
|
value: linkValue,
|
|
605
|
-
onChangeText:
|
|
721
|
+
onChangeText: handleLinkValueChange,
|
|
722
|
+
invalid: linkInvalid,
|
|
606
723
|
placeholder: "https://",
|
|
607
724
|
label: "URL",
|
|
608
725
|
autoCapitalize: "none",
|
|
609
726
|
autoCorrect: false,
|
|
610
727
|
keyboardType: "url"
|
|
611
|
-
})
|
|
728
|
+
}), linkInvalid ? /*#__PURE__*/_jsx(Text, {
|
|
729
|
+
accessibilityRole: "alert",
|
|
730
|
+
className: "mt-1 text-xs text-feedback-error-foreground",
|
|
731
|
+
children: "Link inv\xE1lido. Use um endere\xE7o como medway.com.br"
|
|
732
|
+
}) : null]
|
|
612
733
|
}), /*#__PURE__*/_jsx(DialogFooter, {
|
|
613
734
|
children: /*#__PURE__*/_jsx(Button, {
|
|
614
735
|
onPress: confirmLink,
|
|
@@ -656,6 +777,7 @@ function NoteEditorToolbar({
|
|
|
656
777
|
selected: active
|
|
657
778
|
},
|
|
658
779
|
disabled: disabled,
|
|
780
|
+
hitSlop: TOOLBAR_BUTTON_HIT_SLOP,
|
|
659
781
|
onPress: item.onPress ?? (() => item.command && onCommand(item.command)),
|
|
660
782
|
style: buttonStyle,
|
|
661
783
|
children: /*#__PURE__*/_jsx(Icon, {
|
|
@@ -678,6 +800,7 @@ function NoteEditorToolbar({
|
|
|
678
800
|
disabled: allDisabled
|
|
679
801
|
},
|
|
680
802
|
disabled: allDisabled,
|
|
803
|
+
hitSlop: TOOLBAR_BUTTON_HIT_SLOP,
|
|
681
804
|
onPress: onImagePress,
|
|
682
805
|
style: [styles.toolbarButton, allDisabled ? styles.toolbarButtonDisabled : null],
|
|
683
806
|
children: /*#__PURE__*/_jsx(ImageIcon, {
|
|
@@ -699,6 +822,7 @@ function NoteEditorToolbar({
|
|
|
699
822
|
*/
|
|
700
823
|
function NoteEditorSlashMenu({
|
|
701
824
|
slash,
|
|
825
|
+
editorWidth,
|
|
702
826
|
canUploadImage,
|
|
703
827
|
onSelect
|
|
704
828
|
}) {
|
|
@@ -711,8 +835,8 @@ function NoteEditorSlashMenu({
|
|
|
711
835
|
const commandIds = visibleSlashCommandIds(slash.commandIds, canUploadImage);
|
|
712
836
|
return /*#__PURE__*/_jsx(View, {
|
|
713
837
|
style: [styles.slashMenuShadow, {
|
|
714
|
-
left: slash.caret.x,
|
|
715
|
-
top: slash.caret.y + slash.caret.height +
|
|
838
|
+
left: getSlashMenuLeft(slash.caret.x, editorWidth),
|
|
839
|
+
top: slash.caret.y + slash.caret.height + SLASH_MENU_GAP
|
|
716
840
|
}],
|
|
717
841
|
children: /*#__PURE__*/_jsx(View, {
|
|
718
842
|
style: [styles.slashMenu, {
|
|
@@ -798,8 +922,8 @@ const styles = StyleSheet.create({
|
|
|
798
922
|
marginHorizontal: 4
|
|
799
923
|
},
|
|
800
924
|
toolbarButton: {
|
|
801
|
-
width:
|
|
802
|
-
height:
|
|
925
|
+
width: TOOLBAR_BUTTON_SIZE,
|
|
926
|
+
height: TOOLBAR_BUTTON_SIZE,
|
|
803
927
|
alignItems: "center",
|
|
804
928
|
justifyContent: "center",
|
|
805
929
|
borderRadius: 6
|
|
@@ -810,7 +934,7 @@ const styles = StyleSheet.create({
|
|
|
810
934
|
slashMenuShadow: {
|
|
811
935
|
position: "absolute",
|
|
812
936
|
zIndex: 50,
|
|
813
|
-
width:
|
|
937
|
+
width: SLASH_MENU_WIDTH,
|
|
814
938
|
shadowColor: "#000",
|
|
815
939
|
shadowOffset: {
|
|
816
940
|
width: 0,
|