mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-15 05:37:32 +00:00
init: the first public commit for AFFiNE
This commit is contained in:
6
libs/components/board-draw/src/hooks/index.ts
Normal file
6
libs/components/board-draw/src/hooks/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export * from './use-keyboard-shortcuts';
|
||||
export * from './use-tldraw-app';
|
||||
// export * from './useTheme';
|
||||
export * from './use-stylesheet';
|
||||
export * from './use-file-system-handlers';
|
||||
// export * from './useFileSystem';
|
||||
@@ -0,0 +1,54 @@
|
||||
import * as React from 'react';
|
||||
import { useTldrawApp } from './use-tldraw-app';
|
||||
|
||||
export function useFileSystemHandlers() {
|
||||
const app = useTldrawApp();
|
||||
|
||||
const onNewProject = React.useCallback(
|
||||
async (e?: React.MouseEvent | React.KeyboardEvent | KeyboardEvent) => {
|
||||
if (e && app.callbacks.onOpenProject) e.preventDefault();
|
||||
app.callbacks.onNewProject?.(app);
|
||||
},
|
||||
[app]
|
||||
);
|
||||
|
||||
const onSaveProject = React.useCallback(
|
||||
(e?: React.MouseEvent | React.KeyboardEvent | KeyboardEvent) => {
|
||||
if (e && app.callbacks.onOpenProject) e.preventDefault();
|
||||
app.callbacks.onSaveProject?.(app);
|
||||
},
|
||||
[app]
|
||||
);
|
||||
|
||||
const onSaveProjectAs = React.useCallback(
|
||||
(e?: React.MouseEvent | React.KeyboardEvent | KeyboardEvent) => {
|
||||
if (e && app.callbacks.onOpenProject) e.preventDefault();
|
||||
app.callbacks.onSaveProjectAs?.(app);
|
||||
},
|
||||
[app]
|
||||
);
|
||||
|
||||
const onOpenProject = React.useCallback(
|
||||
async (e?: React.MouseEvent | React.KeyboardEvent | KeyboardEvent) => {
|
||||
if (e && app.callbacks.onOpenProject) e.preventDefault();
|
||||
app.callbacks.onOpenProject?.(app);
|
||||
},
|
||||
[app]
|
||||
);
|
||||
|
||||
const onOpenMedia = React.useCallback(
|
||||
async (e?: React.MouseEvent | React.KeyboardEvent | KeyboardEvent) => {
|
||||
if (e && app.callbacks.onOpenMedia) e.preventDefault();
|
||||
app.callbacks.onOpenMedia?.(app);
|
||||
},
|
||||
[app]
|
||||
);
|
||||
|
||||
return {
|
||||
onNewProject,
|
||||
onSaveProject,
|
||||
onSaveProjectAs,
|
||||
onOpenProject,
|
||||
onOpenMedia,
|
||||
};
|
||||
}
|
||||
679
libs/components/board-draw/src/hooks/use-keyboard-shortcuts.tsx
Normal file
679
libs/components/board-draw/src/hooks/use-keyboard-shortcuts.tsx
Normal file
@@ -0,0 +1,679 @@
|
||||
import * as React from 'react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { AlignStyle, TDShapeType } from '@toeverything/components/board-types';
|
||||
import { useTldrawApp } from './use-tldraw-app';
|
||||
import { useFileSystemHandlers } from './use-file-system-handlers';
|
||||
|
||||
export function useKeyboardShortcuts(ref: React.RefObject<HTMLDivElement>) {
|
||||
const app = useTldrawApp();
|
||||
|
||||
const canHandleEvent = React.useCallback(
|
||||
(ignoreMenus = false) => {
|
||||
const elm = ref.current;
|
||||
if (
|
||||
ignoreMenus &&
|
||||
(app.isMenuOpen || app.settings.keepStyleMenuOpen)
|
||||
)
|
||||
return true;
|
||||
return (
|
||||
elm &&
|
||||
(document.activeElement === elm ||
|
||||
elm.contains(document.activeElement))
|
||||
);
|
||||
},
|
||||
[ref]
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!app) return;
|
||||
|
||||
const handleCut = (e: ClipboardEvent) => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
|
||||
if (app.readOnly) {
|
||||
app.copy(undefined, undefined, e);
|
||||
return;
|
||||
}
|
||||
|
||||
app.cut(undefined, undefined, e);
|
||||
};
|
||||
|
||||
const handleCopy = (e: ClipboardEvent) => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
|
||||
app.copy(undefined, undefined, e);
|
||||
};
|
||||
|
||||
const handlePaste = (e: ClipboardEvent) => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
if (app.readOnly) return;
|
||||
|
||||
app.paste(undefined, e);
|
||||
};
|
||||
|
||||
document.addEventListener('cut', handleCut);
|
||||
document.addEventListener('copy', handleCopy);
|
||||
document.addEventListener('paste', handlePaste);
|
||||
return () => {
|
||||
document.removeEventListener('cut', handleCut);
|
||||
document.removeEventListener('copy', handleCopy);
|
||||
document.removeEventListener('paste', handlePaste);
|
||||
};
|
||||
}, [app]);
|
||||
|
||||
/* ---------------------- Tools --------------------- */
|
||||
|
||||
useHotkeys(
|
||||
'v,1',
|
||||
() => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
app.selectTool('select');
|
||||
},
|
||||
[app, ref.current]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'd,p,2',
|
||||
() => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
app.selectTool(TDShapeType.Draw);
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'e,3',
|
||||
() => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
app.selectTool('erase');
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'r,4',
|
||||
() => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
app.selectTool(TDShapeType.Rectangle);
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'o,5',
|
||||
() => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
app.selectTool(TDShapeType.Ellipse);
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'g,6',
|
||||
() => {
|
||||
if (!canHandleEvent()) return;
|
||||
app.selectTool(TDShapeType.Triangle);
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'l,7',
|
||||
() => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
app.selectTool(TDShapeType.Line);
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'a,8',
|
||||
() => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
app.selectTool(TDShapeType.Arrow);
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
/* ---------------------- Misc ---------------------- */
|
||||
|
||||
// Dark Mode
|
||||
|
||||
useHotkeys(
|
||||
'ctrl+shift+d,⌘+shift+d',
|
||||
e => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
app.toggleDarkMode();
|
||||
e.preventDefault();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
// Focus Mode
|
||||
|
||||
useHotkeys(
|
||||
'ctrl+.,⌘+.',
|
||||
() => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
app.toggleFocusMode();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'ctrl+shift+g,⌘+shift+g',
|
||||
() => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
app.toggleGrid();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
// File System
|
||||
|
||||
const {
|
||||
onNewProject,
|
||||
onOpenProject,
|
||||
onSaveProject,
|
||||
onSaveProjectAs,
|
||||
onOpenMedia,
|
||||
} = useFileSystemHandlers();
|
||||
|
||||
useHotkeys(
|
||||
'ctrl+n,⌘+n',
|
||||
e => {
|
||||
if (!canHandleEvent()) return;
|
||||
|
||||
onNewProject(e);
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
useHotkeys(
|
||||
'ctrl+s,⌘+s',
|
||||
e => {
|
||||
if (!canHandleEvent()) return;
|
||||
|
||||
onSaveProject(e);
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'ctrl+shift+s,⌘+shift+s',
|
||||
e => {
|
||||
if (!canHandleEvent()) return;
|
||||
|
||||
onSaveProjectAs(e);
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
useHotkeys(
|
||||
'ctrl+o,⌘+o',
|
||||
e => {
|
||||
if (!canHandleEvent()) return;
|
||||
|
||||
onOpenProject(e);
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
useHotkeys(
|
||||
'ctrl+u,⌘+u',
|
||||
e => {
|
||||
if (!canHandleEvent()) return;
|
||||
onOpenMedia(e);
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
// Undo Redo
|
||||
|
||||
useHotkeys(
|
||||
'⌘+z,ctrl+z',
|
||||
() => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
|
||||
if (app.session) {
|
||||
app.cancelSession();
|
||||
} else {
|
||||
app.undo();
|
||||
}
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'ctrl+shift+z,⌘+shift+z',
|
||||
() => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
|
||||
if (app.session) {
|
||||
app.cancelSession();
|
||||
} else {
|
||||
app.redo();
|
||||
}
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
// Undo Redo
|
||||
|
||||
useHotkeys(
|
||||
'⌘+u,ctrl+u',
|
||||
() => {
|
||||
if (!canHandleEvent()) return;
|
||||
app.undoSelect();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'ctrl+shift-u,⌘+shift+u',
|
||||
() => {
|
||||
if (!canHandleEvent()) return;
|
||||
app.redoSelect();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
/* -------------------- Commands -------------------- */
|
||||
|
||||
// Camera
|
||||
|
||||
useHotkeys(
|
||||
'ctrl+=,⌘+=,ctrl+num_subtract,⌘+num_subtract',
|
||||
e => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
app.zoomIn();
|
||||
e.preventDefault();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'ctrl+-,⌘+-,ctrl+num_add,⌘+num_add',
|
||||
e => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
|
||||
app.zoomOut();
|
||||
e.preventDefault();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'shift+0,ctrl+numpad_0,⌘+numpad_0',
|
||||
() => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
app.resetZoom();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'shift+1',
|
||||
() => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
app.zoomToFit();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'shift+2',
|
||||
() => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
app.zoomToSelection();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
// Duplicate
|
||||
|
||||
useHotkeys(
|
||||
'ctrl+d,⌘+d',
|
||||
e => {
|
||||
if (!canHandleEvent()) return;
|
||||
|
||||
app.duplicate();
|
||||
e.preventDefault();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
// Flip
|
||||
|
||||
useHotkeys(
|
||||
'shift+h',
|
||||
() => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
app.flipHorizontal();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'shift+v',
|
||||
() => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
app.flipVertical();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
// Cancel
|
||||
|
||||
useHotkeys(
|
||||
'escape',
|
||||
() => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
|
||||
app.cancel();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
// Delete
|
||||
|
||||
useHotkeys(
|
||||
'backspace,del',
|
||||
() => {
|
||||
if (!canHandleEvent()) return;
|
||||
app.delete();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
// Select All
|
||||
|
||||
useHotkeys(
|
||||
'⌘+a,ctrl+a',
|
||||
() => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
app.selectAll();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
// Nudge
|
||||
|
||||
useHotkeys(
|
||||
'up',
|
||||
() => {
|
||||
if (!canHandleEvent()) return;
|
||||
app.nudge([0, -1], false);
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'right',
|
||||
() => {
|
||||
if (!canHandleEvent()) return;
|
||||
app.nudge([1, 0], false);
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'down',
|
||||
() => {
|
||||
if (!canHandleEvent()) return;
|
||||
app.nudge([0, 1], false);
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'left',
|
||||
() => {
|
||||
if (!canHandleEvent()) return;
|
||||
app.nudge([-1, 0], false);
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'shift+up',
|
||||
() => {
|
||||
if (!canHandleEvent()) return;
|
||||
app.nudge([0, -1], true);
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'shift+right',
|
||||
() => {
|
||||
if (!canHandleEvent()) return;
|
||||
app.nudge([1, 0], true);
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'shift+down',
|
||||
() => {
|
||||
if (!canHandleEvent()) return;
|
||||
app.nudge([0, 1], true);
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'shift+left',
|
||||
() => {
|
||||
if (!canHandleEvent()) return;
|
||||
app.nudge([-1, 0], true);
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'⌘+shift+l,ctrl+shift+l',
|
||||
() => {
|
||||
if (!canHandleEvent()) return;
|
||||
app.toggleLocked();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
// Copy, Cut & Paste
|
||||
|
||||
// useHotkeys(
|
||||
// '⌘+c,ctrl+c',
|
||||
// () => {
|
||||
// if (!canHandleEvent()) return
|
||||
// app.copy()
|
||||
// },
|
||||
// undefined,
|
||||
// [app]
|
||||
// )
|
||||
|
||||
useHotkeys(
|
||||
'⌘+shift+c,ctrl+shift+c',
|
||||
e => {
|
||||
if (!canHandleEvent()) return;
|
||||
|
||||
app.copySvg();
|
||||
e.preventDefault();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
// useHotkeys(
|
||||
// '⌘+x,ctrl+x',
|
||||
// () => {
|
||||
// if (!canHandleEvent()) return
|
||||
// app.cut()
|
||||
// },
|
||||
// undefined,
|
||||
// [app]
|
||||
// )
|
||||
|
||||
// useHotkeys(
|
||||
// '⌘+v,ctrl+v',
|
||||
// () => {
|
||||
// if (!canHandleEvent()) return
|
||||
|
||||
// app.paste()
|
||||
// },
|
||||
// undefined,
|
||||
// [app]
|
||||
// )
|
||||
|
||||
// Group & Ungroup
|
||||
|
||||
useHotkeys(
|
||||
'⌘+g,ctrl+g',
|
||||
e => {
|
||||
if (!canHandleEvent()) return;
|
||||
|
||||
app.group();
|
||||
e.preventDefault();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'⌘+shift+g,ctrl+shift+g',
|
||||
e => {
|
||||
if (!canHandleEvent()) return;
|
||||
|
||||
app.ungroup();
|
||||
e.preventDefault();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
// Move
|
||||
|
||||
useHotkeys(
|
||||
'[',
|
||||
() => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
app.moveBackward();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
']',
|
||||
() => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
app.moveForward();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'shift+[',
|
||||
() => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
app.moveToBack();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'shift+]',
|
||||
() => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
app.moveToFront();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'ctrl+shift+backspace,⌘+shift+backspace',
|
||||
e => {
|
||||
if (!canHandleEvent()) return;
|
||||
if (app.settings.isDebugMode) {
|
||||
app.resetDocument();
|
||||
}
|
||||
e.preventDefault();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
// Text Align
|
||||
|
||||
useHotkeys(
|
||||
'alt+command+l,alt+ctrl+l',
|
||||
e => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
app.style({ textAlign: AlignStyle.Start });
|
||||
e.preventDefault();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'alt+command+t,alt+ctrl+t',
|
||||
e => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
app.style({ textAlign: AlignStyle.Middle });
|
||||
e.preventDefault();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'alt+command+r,alt+ctrl+r',
|
||||
e => {
|
||||
if (!canHandleEvent(true)) return;
|
||||
app.style({ textAlign: AlignStyle.End });
|
||||
e.preventDefault();
|
||||
},
|
||||
undefined,
|
||||
[app]
|
||||
);
|
||||
}
|
||||
60
libs/components/board-draw/src/hooks/use-stylesheet.ts
Normal file
60
libs/components/board-draw/src/hooks/use-stylesheet.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import * as React from 'react';
|
||||
|
||||
const styles = new Map<string, HTMLStyleElement>();
|
||||
|
||||
const UID = `tldraw-fonts`;
|
||||
|
||||
const CSS = `
|
||||
@import url('https://fonts.googleapis.com/css2?family=Caveat+Brush&family=Source+Code+Pro&family=Source+Sans+Pro&family=Crimson+Pro&display=block');
|
||||
|
||||
@font-face {
|
||||
font-family: 'Recursive';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/recursive/v23/8vI-7wMr0mhh-RQChyHEH06TlXhq_gukbYrFMk1QuAIcyEwG_X-dpEfaE5YaERmK-CImKsvxvU-MXGX2fSqasNfUlTGZnI14ZeY.woff2)
|
||||
format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
|
||||
U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Recursive';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/recursive/v23/8vI-7wMr0mhh-RQChyHEH06TlXhq_gukbYrFMk1QuAIcyEwG_X-dpEfaE5YaERmK-CImKsvxvU-MXGX2fSqasNfUlTGZnI14ZeY.woff2)
|
||||
format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
|
||||
U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Recursive Mono';
|
||||
font-style: normal;
|
||||
font-weight: 420;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/recursive/v23/8vI-7wMr0mhh-RQChyHEH06TlXhq_gukbYrFMk1QuAIcyEwG_X-dpEfaE5YaERmK-CImqvTxvU-MXGX2fSqasNfUlTGZnI14ZeY.woff2)
|
||||
format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
|
||||
U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
`;
|
||||
|
||||
export function useStylesheet() {
|
||||
React.useLayoutEffect(() => {
|
||||
if (styles.get(UID)) return;
|
||||
const style = document.createElement('style');
|
||||
style.innerHTML = CSS;
|
||||
style.setAttribute('id', UID);
|
||||
document.head.appendChild(style);
|
||||
styles.set(UID, style);
|
||||
|
||||
return () => {
|
||||
if (style && document.head.contains(style)) {
|
||||
document.head.removeChild(style);
|
||||
styles.delete(UID);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
}
|
||||
9
libs/components/board-draw/src/hooks/use-tldraw-app.ts
Normal file
9
libs/components/board-draw/src/hooks/use-tldraw-app.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import * as React from 'react';
|
||||
import type { TldrawApp } from '@toeverything/components/board-state';
|
||||
|
||||
export const TldrawContext = React.createContext<TldrawApp>({} as TldrawApp);
|
||||
|
||||
export function useTldrawApp() {
|
||||
const context = React.useContext(TldrawContext);
|
||||
return context;
|
||||
}
|
||||
Reference in New Issue
Block a user