onchain-lexical-context 0.0.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/package.json +85 -0
- package/src/Collaboration.ts +43 -0
- package/src/FlashMessage.tsx +69 -0
- package/src/InstanceConfig.tsx +39 -0
- package/src/Settings.tsx +77 -0
- package/src/SharedHistory.tsx +36 -0
- package/src/Toolbar.tsx +136 -0
- package/src/Upload.ts +105 -0
- package/src/appSettings.ts +39 -0
- package/src/index.ts +11 -0
- package/src/types.d.ts +21 -0
package/package.json
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "onchain-lexical-context",
|
|
3
|
+
"license": "MIT",
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"dependencies": {
|
|
6
|
+
"@lexical/react": "^0.30.0",
|
|
7
|
+
"@lexical/yjs": "^0.30.0",
|
|
8
|
+
"lexical": "0.30.0",
|
|
9
|
+
"onchain-lexical-ui": "^0.0.1",
|
|
10
|
+
"onchain-utility": "^0.0.1",
|
|
11
|
+
"y-websocket": "^1.5.4"
|
|
12
|
+
},
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"import": {
|
|
16
|
+
"types": "./src/index.ts",
|
|
17
|
+
"default": "./dist/OnchainLexicalContext.mjs"
|
|
18
|
+
},
|
|
19
|
+
"require": {
|
|
20
|
+
"types": "./src/index.ts",
|
|
21
|
+
"default": "./dist/OnchainLexicalContext.js"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"./collaboration": {
|
|
25
|
+
"import": {
|
|
26
|
+
"types": "./src/Collaboration.ts",
|
|
27
|
+
"default": "./dist/Collaboration.mjs"
|
|
28
|
+
},
|
|
29
|
+
"require": {
|
|
30
|
+
"types": "./src/Collaboration.ts",
|
|
31
|
+
"default": "./dist/Toolbar.js"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"./flashMessage": {
|
|
35
|
+
"import": {
|
|
36
|
+
"types": "./src/FlashMessage.tsx",
|
|
37
|
+
"default": "./dist/FlashMessage.mjs"
|
|
38
|
+
},
|
|
39
|
+
"require": {
|
|
40
|
+
"types": "./src/FlashMessage.tsx",
|
|
41
|
+
"default": "./dist/FlashMessage.js"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"./instanceConfig": {
|
|
45
|
+
"import": {
|
|
46
|
+
"types": "./src/InstanceConfig.tsx",
|
|
47
|
+
"default": "./dist/InstanceConfig.mjs"
|
|
48
|
+
},
|
|
49
|
+
"require": {
|
|
50
|
+
"types": "./src/InstanceConfig.tsx",
|
|
51
|
+
"default": "./dist/InstanceConfig.js"
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"./settings": {
|
|
55
|
+
"import": {
|
|
56
|
+
"types": "./src/Settings.tsx",
|
|
57
|
+
"default": "./dist/Settings.mjs"
|
|
58
|
+
},
|
|
59
|
+
"require": {
|
|
60
|
+
"types": "./src/Settings.tsx",
|
|
61
|
+
"default": "./dist/Settings.js"
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"./sharedHistory": {
|
|
65
|
+
"import": {
|
|
66
|
+
"types": "./src/SharedHistory.tsx",
|
|
67
|
+
"default": "./dist/SharedHistory.mjs"
|
|
68
|
+
},
|
|
69
|
+
"require": {
|
|
70
|
+
"types": "./src/SharedHistory.tsx",
|
|
71
|
+
"default": "./dist/SharedHistory.js"
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"./toolBar": {
|
|
75
|
+
"import": {
|
|
76
|
+
"types": "./src/Toolbar.tsx",
|
|
77
|
+
"default": "./dist/Toolbar.mjs"
|
|
78
|
+
},
|
|
79
|
+
"require": {
|
|
80
|
+
"types": "./src/Toolbar.tsx",
|
|
81
|
+
"default": "./dist/Toolbar.js"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import {Provider} from '@lexical/yjs';
|
|
10
|
+
import {WebsocketProvider} from 'y-websocket';
|
|
11
|
+
import {Doc} from 'yjs';
|
|
12
|
+
|
|
13
|
+
const url = new URL(window.location.href);
|
|
14
|
+
const params = new URLSearchParams(url.search);
|
|
15
|
+
const WEBSOCKET_ENDPOINT =
|
|
16
|
+
params.get('collabEndpoint') || 'ws://localhost:1234';
|
|
17
|
+
const WEBSOCKET_SLUG = 'playground';
|
|
18
|
+
const WEBSOCKET_ID = params.get('collabId') || '0';
|
|
19
|
+
|
|
20
|
+
// parent dom -> child doc
|
|
21
|
+
export function createWebsocketProvider(
|
|
22
|
+
id: string,
|
|
23
|
+
yjsDocMap: Map<string, Doc>,
|
|
24
|
+
): Provider {
|
|
25
|
+
let doc = yjsDocMap.get(id);
|
|
26
|
+
|
|
27
|
+
if (doc === undefined) {
|
|
28
|
+
doc = new Doc();
|
|
29
|
+
yjsDocMap.set(id, doc);
|
|
30
|
+
} else {
|
|
31
|
+
doc.load();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// @ts-expect-error
|
|
35
|
+
return new WebsocketProvider(
|
|
36
|
+
WEBSOCKET_ENDPOINT,
|
|
37
|
+
WEBSOCKET_SLUG + '/' + WEBSOCKET_ID + '/' + id,
|
|
38
|
+
doc,
|
|
39
|
+
{
|
|
40
|
+
connect: false,
|
|
41
|
+
},
|
|
42
|
+
);
|
|
43
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type {JSX} from 'react';
|
|
10
|
+
|
|
11
|
+
import FlashMessage from 'onchain-lexical-ui/FlashMessage';
|
|
12
|
+
import {
|
|
13
|
+
createContext,
|
|
14
|
+
ReactNode,
|
|
15
|
+
useCallback,
|
|
16
|
+
useContext,
|
|
17
|
+
useEffect,
|
|
18
|
+
useState,
|
|
19
|
+
} from 'react';
|
|
20
|
+
|
|
21
|
+
export type ShowFlashMessage = (
|
|
22
|
+
message?: React.ReactNode,
|
|
23
|
+
duration?: number,
|
|
24
|
+
) => void;
|
|
25
|
+
|
|
26
|
+
interface FlashMessageProps {
|
|
27
|
+
message?: React.ReactNode;
|
|
28
|
+
duration?: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const Context = createContext<ShowFlashMessage | undefined>(undefined);
|
|
32
|
+
const INITIAL_STATE: FlashMessageProps = {};
|
|
33
|
+
const DEFAULT_DURATION = 1000;
|
|
34
|
+
|
|
35
|
+
export const FlashMessageContext = ({
|
|
36
|
+
children,
|
|
37
|
+
}: {
|
|
38
|
+
children: ReactNode;
|
|
39
|
+
}): JSX.Element => {
|
|
40
|
+
const [props, setProps] = useState(INITIAL_STATE);
|
|
41
|
+
const showFlashMessage = useCallback<ShowFlashMessage>(
|
|
42
|
+
(message, duration) =>
|
|
43
|
+
setProps(message ? {duration, message} : INITIAL_STATE),
|
|
44
|
+
[],
|
|
45
|
+
);
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
if (props.message) {
|
|
48
|
+
const timeoutId = setTimeout(
|
|
49
|
+
() => setProps(INITIAL_STATE),
|
|
50
|
+
props.duration ?? DEFAULT_DURATION,
|
|
51
|
+
);
|
|
52
|
+
return () => clearTimeout(timeoutId);
|
|
53
|
+
}
|
|
54
|
+
}, [props]);
|
|
55
|
+
return (
|
|
56
|
+
<Context.Provider value={showFlashMessage}>
|
|
57
|
+
{children}
|
|
58
|
+
{props.message && <FlashMessage>{props.message}</FlashMessage>}
|
|
59
|
+
</Context.Provider>
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const useFlashMessageContext = (): ShowFlashMessage => {
|
|
64
|
+
const ctx = useContext(Context);
|
|
65
|
+
if (!ctx) {
|
|
66
|
+
throw new Error('Missing FlashMessageContext');
|
|
67
|
+
}
|
|
68
|
+
return ctx;
|
|
69
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
9
|
+
|
|
10
|
+
import type {BuiltInInstanceConfig, InstanceConfig} from './types';
|
|
11
|
+
import type {JSX} from 'react';
|
|
12
|
+
|
|
13
|
+
import * as React from 'react';
|
|
14
|
+
import {createContext, ReactNode, useContext, useMemo} from 'react';
|
|
15
|
+
|
|
16
|
+
type InstanceConfigContext = InstanceConfig & BuiltInInstanceConfig;
|
|
17
|
+
|
|
18
|
+
const Context: React.Context<InstanceConfigContext> = createContext({} as any);
|
|
19
|
+
|
|
20
|
+
export const InstanceConfigContext = ({
|
|
21
|
+
children,
|
|
22
|
+
value,
|
|
23
|
+
}: {
|
|
24
|
+
children: ReactNode;
|
|
25
|
+
value: InstanceConfig;
|
|
26
|
+
}): JSX.Element => {
|
|
27
|
+
const [selectedInstance, setSelectedInstance] = React.useState<
|
|
28
|
+
BuiltInInstanceConfig['selectedInstance']
|
|
29
|
+
>([]);
|
|
30
|
+
const contextValue = useMemo(() => {
|
|
31
|
+
return {...value, selectedInstance, setSelectedInstance};
|
|
32
|
+
}, [value, selectedInstance]);
|
|
33
|
+
|
|
34
|
+
return <Context.Provider value={contextValue}>{children}</Context.Provider>;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const useInstanceConfig = (): InstanceConfigContext => {
|
|
38
|
+
return useContext(Context);
|
|
39
|
+
};
|
package/src/Settings.tsx
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type {SettingName} from './appSettings';
|
|
10
|
+
import type {ExtraSettings} from './types';
|
|
11
|
+
import type {JSX} from 'react';
|
|
12
|
+
|
|
13
|
+
import * as React from 'react';
|
|
14
|
+
import {
|
|
15
|
+
createContext,
|
|
16
|
+
ReactNode,
|
|
17
|
+
useCallback,
|
|
18
|
+
useContext,
|
|
19
|
+
useMemo,
|
|
20
|
+
useState,
|
|
21
|
+
} from 'react';
|
|
22
|
+
|
|
23
|
+
import {DEFAULT_SETTINGS, INITIAL_SETTINGS} from './appSettings';
|
|
24
|
+
|
|
25
|
+
type SettingsContextShape = {
|
|
26
|
+
setOption: (name: SettingName, value: boolean) => void;
|
|
27
|
+
settings: Record<SettingName, boolean>;
|
|
28
|
+
extra: ExtraSettings;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const Context: React.Context<SettingsContextShape> = createContext({
|
|
32
|
+
extra: {},
|
|
33
|
+
setOption: (name: SettingName, value: boolean) => {
|
|
34
|
+
return;
|
|
35
|
+
},
|
|
36
|
+
settings: INITIAL_SETTINGS,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
export const SettingsContext = ({
|
|
40
|
+
children,
|
|
41
|
+
extra,
|
|
42
|
+
}: {
|
|
43
|
+
children: ReactNode;
|
|
44
|
+
extra: ExtraSettings;
|
|
45
|
+
}): JSX.Element => {
|
|
46
|
+
const [settings, setSettings] = useState(INITIAL_SETTINGS);
|
|
47
|
+
|
|
48
|
+
const setOption = useCallback((setting: SettingName, value: boolean) => {
|
|
49
|
+
setSettings((options) => ({
|
|
50
|
+
...options,
|
|
51
|
+
[setting]: value,
|
|
52
|
+
}));
|
|
53
|
+
setURLParam(setting, value);
|
|
54
|
+
}, []);
|
|
55
|
+
|
|
56
|
+
const contextValue = useMemo(() => {
|
|
57
|
+
return {extra, setOption, settings};
|
|
58
|
+
}, [setOption, settings, extra]);
|
|
59
|
+
|
|
60
|
+
return <Context.Provider value={contextValue}>{children}</Context.Provider>;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const useSettings = (): SettingsContextShape => {
|
|
64
|
+
return useContext(Context);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
function setURLParam(param: SettingName, value: null | boolean) {
|
|
68
|
+
const url = new URL(window.location.href);
|
|
69
|
+
const params = new URLSearchParams(url.search);
|
|
70
|
+
if (value !== DEFAULT_SETTINGS[param]) {
|
|
71
|
+
params.set(param, String(value));
|
|
72
|
+
} else {
|
|
73
|
+
params.delete(param);
|
|
74
|
+
}
|
|
75
|
+
url.search = params.toString();
|
|
76
|
+
window.history.pushState(null, '', url.toString());
|
|
77
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type {HistoryState} from '@lexical/react/LexicalHistoryPlugin';
|
|
10
|
+
import type {JSX} from 'react';
|
|
11
|
+
|
|
12
|
+
import {createEmptyHistoryState} from '@lexical/react/LexicalHistoryPlugin';
|
|
13
|
+
import * as React from 'react';
|
|
14
|
+
import {createContext, ReactNode, useContext, useMemo} from 'react';
|
|
15
|
+
|
|
16
|
+
type ContextShape = {
|
|
17
|
+
historyState?: HistoryState;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const Context: React.Context<ContextShape> = createContext({});
|
|
21
|
+
|
|
22
|
+
export const SharedHistoryContext = ({
|
|
23
|
+
children,
|
|
24
|
+
}: {
|
|
25
|
+
children: ReactNode;
|
|
26
|
+
}): JSX.Element => {
|
|
27
|
+
const historyContext = useMemo(
|
|
28
|
+
() => ({historyState: createEmptyHistoryState()}),
|
|
29
|
+
[],
|
|
30
|
+
);
|
|
31
|
+
return <Context.Provider value={historyContext}>{children}</Context.Provider>;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const useSharedHistoryContext = (): ContextShape => {
|
|
35
|
+
return useContext(Context);
|
|
36
|
+
};
|
package/src/Toolbar.tsx
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type {JSX} from 'react';
|
|
10
|
+
|
|
11
|
+
import {ElementFormatType} from 'lexical';
|
|
12
|
+
import React, {
|
|
13
|
+
createContext,
|
|
14
|
+
ReactNode,
|
|
15
|
+
useCallback,
|
|
16
|
+
useContext,
|
|
17
|
+
useEffect,
|
|
18
|
+
useMemo,
|
|
19
|
+
useState,
|
|
20
|
+
} from 'react';
|
|
21
|
+
|
|
22
|
+
export const MIN_ALLOWED_FONT_SIZE = 8;
|
|
23
|
+
export const MAX_ALLOWED_FONT_SIZE = 72;
|
|
24
|
+
export const DEFAULT_FONT_SIZE = 15;
|
|
25
|
+
|
|
26
|
+
const rootTypeToRootName = {
|
|
27
|
+
root: 'Root',
|
|
28
|
+
table: 'Table',
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const blockTypeToBlockName = {
|
|
32
|
+
Paragraph: '正文',
|
|
33
|
+
Quote: '引用',
|
|
34
|
+
bullet: '列表',
|
|
35
|
+
check: '待办列表',
|
|
36
|
+
code: '代码块',
|
|
37
|
+
h1: '标题 1',
|
|
38
|
+
h2: '标题 2',
|
|
39
|
+
h3: '标题 3',
|
|
40
|
+
h4: '标题 4',
|
|
41
|
+
h5: '标题 5',
|
|
42
|
+
h6: '标题 6',
|
|
43
|
+
number: '列表',
|
|
44
|
+
paragraph: '正文',
|
|
45
|
+
quote: '引用',
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
//disable eslint sorting rule for quick reference to toolbar state
|
|
49
|
+
/* eslint-disable sort-keys-fix/sort-keys-fix */
|
|
50
|
+
const INITIAL_TOOLBAR_STATE = {
|
|
51
|
+
bgColor: '#fff',
|
|
52
|
+
blockType: 'Paragraph' as keyof typeof blockTypeToBlockName,
|
|
53
|
+
canRedo: false,
|
|
54
|
+
canUndo: false,
|
|
55
|
+
codeLanguage: '',
|
|
56
|
+
elementFormat: 'left' as ElementFormatType,
|
|
57
|
+
fontColor: '#000',
|
|
58
|
+
fontFamily: 'Arial',
|
|
59
|
+
// Current font size in px
|
|
60
|
+
fontSize: `${DEFAULT_FONT_SIZE}px`,
|
|
61
|
+
// Font size input value - for controlled input
|
|
62
|
+
fontSizeInputValue: `${DEFAULT_FONT_SIZE}`,
|
|
63
|
+
isBold: false,
|
|
64
|
+
isCode: false,
|
|
65
|
+
isHighlight: false,
|
|
66
|
+
isImageCaption: false,
|
|
67
|
+
isItalic: false,
|
|
68
|
+
isLink: false,
|
|
69
|
+
isRTL: false,
|
|
70
|
+
isStrikethrough: false,
|
|
71
|
+
isSubscript: false,
|
|
72
|
+
isSuperscript: false,
|
|
73
|
+
isUnderline: false,
|
|
74
|
+
isLowercase: false,
|
|
75
|
+
isUppercase: false,
|
|
76
|
+
isCapitalize: false,
|
|
77
|
+
rootType: 'root' as keyof typeof rootTypeToRootName,
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
type ToolbarState = typeof INITIAL_TOOLBAR_STATE;
|
|
81
|
+
|
|
82
|
+
// Utility type to get keys and infer value types
|
|
83
|
+
type ToolbarStateKey = keyof ToolbarState;
|
|
84
|
+
type ToolbarStateValue<Key extends ToolbarStateKey> = ToolbarState[Key];
|
|
85
|
+
|
|
86
|
+
type ContextShape = {
|
|
87
|
+
toolbarState: ToolbarState;
|
|
88
|
+
updateToolbarState<Key extends ToolbarStateKey>(
|
|
89
|
+
key: Key,
|
|
90
|
+
value: ToolbarStateValue<Key>,
|
|
91
|
+
): void;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const Context = createContext<ContextShape | undefined>(undefined);
|
|
95
|
+
|
|
96
|
+
export const ToolbarContext = ({
|
|
97
|
+
children,
|
|
98
|
+
}: {
|
|
99
|
+
children: ReactNode;
|
|
100
|
+
}): JSX.Element => {
|
|
101
|
+
const [toolbarState, setToolbarState] = useState(INITIAL_TOOLBAR_STATE);
|
|
102
|
+
const selectionFontSize = toolbarState.fontSize;
|
|
103
|
+
|
|
104
|
+
const updateToolbarState = useCallback(
|
|
105
|
+
<Key extends ToolbarStateKey>(key: Key, value: ToolbarStateValue<Key>) => {
|
|
106
|
+
setToolbarState((prev) => ({
|
|
107
|
+
...prev,
|
|
108
|
+
[key]: value,
|
|
109
|
+
}));
|
|
110
|
+
},
|
|
111
|
+
[],
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
useEffect(() => {
|
|
115
|
+
updateToolbarState('fontSizeInputValue', selectionFontSize.slice(0, -2));
|
|
116
|
+
}, [selectionFontSize, updateToolbarState]);
|
|
117
|
+
|
|
118
|
+
const contextValue = useMemo(() => {
|
|
119
|
+
return {
|
|
120
|
+
toolbarState,
|
|
121
|
+
updateToolbarState,
|
|
122
|
+
};
|
|
123
|
+
}, [toolbarState, updateToolbarState]);
|
|
124
|
+
|
|
125
|
+
return <Context.Provider value={contextValue}>{children}</Context.Provider>;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
export const useToolbarState = () => {
|
|
129
|
+
const context = useContext(Context);
|
|
130
|
+
|
|
131
|
+
if (context === undefined) {
|
|
132
|
+
throw new Error('useToolbarState must be used within a ToolbarProvider');
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return context;
|
|
136
|
+
};
|
package/src/Upload.ts
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type {InternalSerializedNode} from 'lexical';
|
|
10
|
+
|
|
11
|
+
import {base64ToMimeType, getBase64Regular} from 'onchain-utility/base64';
|
|
12
|
+
import {asyncDfs} from 'onchain-utility/traversal';
|
|
13
|
+
|
|
14
|
+
import {InstanceConfig} from './types';
|
|
15
|
+
|
|
16
|
+
type Base64Src = string;
|
|
17
|
+
type NodeKey = string;
|
|
18
|
+
|
|
19
|
+
const uploadMap = new Map<
|
|
20
|
+
Base64Src,
|
|
21
|
+
{
|
|
22
|
+
upload(): Promise<string[]>;
|
|
23
|
+
result: Promise<string[]>;
|
|
24
|
+
}
|
|
25
|
+
>();
|
|
26
|
+
const base64SrcMap = new Map<NodeKey, Base64Src>();
|
|
27
|
+
|
|
28
|
+
export function deleteUpload(nodeKey: string) {
|
|
29
|
+
return base64SrcMap.delete(nodeKey);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function getUpload(nodeKey: string) {
|
|
33
|
+
const base64Src = base64SrcMap.get(nodeKey);
|
|
34
|
+
if (base64Src) {
|
|
35
|
+
return uploadMap.get(base64Src);
|
|
36
|
+
} else {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function hasUpload(nodeKey: string) {
|
|
42
|
+
const base64Src = base64SrcMap.get(nodeKey);
|
|
43
|
+
if (base64Src) {
|
|
44
|
+
return uploadMap.has(base64Src);
|
|
45
|
+
} else {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function upload({
|
|
51
|
+
nodeKey,
|
|
52
|
+
src,
|
|
53
|
+
hasError,
|
|
54
|
+
uploadFiles,
|
|
55
|
+
}: {
|
|
56
|
+
nodeKey: string;
|
|
57
|
+
src: string;
|
|
58
|
+
hasError?: boolean;
|
|
59
|
+
uploadFiles: InstanceConfig['uploadFiles'];
|
|
60
|
+
}) {
|
|
61
|
+
const {type, suffix} = base64ToMimeType(src);
|
|
62
|
+
if (!hasError && type && suffix) {
|
|
63
|
+
const _upload = () => {
|
|
64
|
+
const result = uploadFiles([{suffix, text: src, type}]);
|
|
65
|
+
base64SrcMap.set(nodeKey, src);
|
|
66
|
+
uploadMap.set(src, {
|
|
67
|
+
result,
|
|
68
|
+
upload: _upload,
|
|
69
|
+
});
|
|
70
|
+
return result;
|
|
71
|
+
};
|
|
72
|
+
if (!uploadMap.has(src)) {
|
|
73
|
+
_upload();
|
|
74
|
+
} else {
|
|
75
|
+
base64SrcMap.set(nodeKey, src);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export async function markdownBase64StringToUpLoadUrl(markdown: string) {
|
|
81
|
+
const base64Regular = getBase64Regular();
|
|
82
|
+
const base64List = Array.from(markdown.match(base64Regular) || []);
|
|
83
|
+
for (const base64 of base64List) {
|
|
84
|
+
if (uploadMap.has(base64)) {
|
|
85
|
+
markdown = markdown.replace(
|
|
86
|
+
base64,
|
|
87
|
+
(await uploadMap.get(base64)!.result)[0],
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return markdown;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export async function jsonBase64StringToUpLoadUrl(
|
|
95
|
+
node: InternalSerializedNode,
|
|
96
|
+
) {
|
|
97
|
+
await asyncDfs([node], async (node) => {
|
|
98
|
+
const src = node.src;
|
|
99
|
+
if (src && uploadMap.has(src)) {
|
|
100
|
+
node.src = (await uploadMap.get(src)!.result)[0];
|
|
101
|
+
}
|
|
102
|
+
return node.children || [];
|
|
103
|
+
});
|
|
104
|
+
return node;
|
|
105
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export const DEFAULT_SETTINGS = {
|
|
10
|
+
disableBeforeInput: false,
|
|
11
|
+
emptyEditor: VITE_IS_DEVELOPMENT,
|
|
12
|
+
hasLinkAttributes: false,
|
|
13
|
+
isAutocomplete: false,
|
|
14
|
+
isCharLimit: false,
|
|
15
|
+
isCharLimitUtf8: false,
|
|
16
|
+
isCollab: false,
|
|
17
|
+
isMaxLength: false,
|
|
18
|
+
isRichText: true,
|
|
19
|
+
listStrictIndent: false,
|
|
20
|
+
measureTypingPerf: false,
|
|
21
|
+
selectionAlwaysOnDisplay: false,
|
|
22
|
+
shouldAllowHighlightingWithBrackets: false,
|
|
23
|
+
shouldPreserveNewLinesInMarkdown: false,
|
|
24
|
+
shouldUseLexicalContextMenu: false,
|
|
25
|
+
showNestedEditorTreeView: false,
|
|
26
|
+
showTableOfContents: false,
|
|
27
|
+
tableCellBackgroundColor: true,
|
|
28
|
+
tableCellMerge: true,
|
|
29
|
+
tableHorizontalScroll: true,
|
|
30
|
+
} as const;
|
|
31
|
+
|
|
32
|
+
// These are mutated in setupEnv
|
|
33
|
+
export const INITIAL_SETTINGS: Record<SettingName, boolean> = {
|
|
34
|
+
...DEFAULT_SETTINGS,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type SettingName = keyof typeof DEFAULT_SETTINGS;
|
|
38
|
+
|
|
39
|
+
export type Settings = typeof INITIAL_SETTINGS;
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export * from './appSettings';
|
|
10
|
+
export type * from './types';
|
|
11
|
+
export * from './Upload';
|
package/src/types.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface ExtraSettings {
|
|
2
|
+
iconScriptUrl?: string;
|
|
3
|
+
isShowActions?: boolean;
|
|
4
|
+
showTreeView?: boolean;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface BuiltInInstanceConfig {
|
|
8
|
+
selectedInstance: {
|
|
9
|
+
number: string;
|
|
10
|
+
nodeKey: string;
|
|
11
|
+
}[];
|
|
12
|
+
setSelectedInstance(params: InstanceConfig['selectedInstance']): void;
|
|
13
|
+
}
|
|
14
|
+
export interface InstanceConfig {
|
|
15
|
+
preview?: boolean;
|
|
16
|
+
getInstanceIcon: (objectApicode: string) => string;
|
|
17
|
+
uploadFiles(
|
|
18
|
+
params: {type: string; text: string; suffix: string}[],
|
|
19
|
+
): Promise<string[]>;
|
|
20
|
+
generateNumber(nodeKey?: string): Promise<string>;
|
|
21
|
+
}
|