((props, ref) => {
blocks={blocksWithFilters}
pressThreshold={300}
/>
- {!props.autoFocus && }
+ {/* {!props.autoFocus && } */}
);
});
@@ -366,14 +362,15 @@ function AutoFocusInput() {
);
}
+const BlockListWrapper = styled('div', {
+ width: '100%',
+ position: 'relative',
+});
+
const SortableBlockList = SortableContainer(
({ blockCss, blocks }: { blockCss: any; blocks: BlockAtom[] }) => {
return (
-
+
{blocks.map((blockAtom, i) => (
))}
-
+
);
},
);
@@ -390,8 +387,8 @@ const SortableBlockList = SortableContainer(
export const Editor = forwardRef(
(props, ref) => {
const defaultBlock = props.defaultBlock || {
- type: TextBlock.block.type,
- data: TextBlock.block.defaultValue,
+ type: ParagraphBlock.block.type,
+ data: ParagraphBlock.block.defaultValue,
};
const initDataAtom = useMemo(() => {
@@ -408,7 +405,7 @@ export const Editor = forwardRef(
[
[editorDefaultBlockAtom, defaultBlock],
[editorIdAtom, v4()],
- [blockMapAtom, props.blockMap],
+ [blockScopeAtom, props.scope],
[_blocksAtom, initData],
] as const
}
diff --git a/packages/editor/src/components/inline-toolbar/code/index.tsx b/packages/editor/src/components/inline-toolbar/code/index.tsx
index 5ff2ca2..7bc63ea 100644
--- a/packages/editor/src/components/inline-toolbar/code/index.tsx
+++ b/packages/editor/src/components/inline-toolbar/code/index.tsx
@@ -3,8 +3,10 @@ import SvgCode from '../../icons/code';
import { useEventChangeSelection, useInlineTool } from '../hooks';
import { surround } from '../../../utils/find-blocks';
import { getSelectionRange } from '../../../utils/ranges';
-import { StitchesProps } from '@hexx/theme';
-export function InlineCode(props: StitchesProps) {
+import { ComponentProps } from 'react';
+export function InlineCode(
+ props: ComponentProps,
+) {
const { getProps, setIsActive } = useInlineTool({
shortcut: '⌘ + e',
onToggle: (isActive) => {
diff --git a/packages/editor/src/components/inline-toolbar/inline-toolbar.tsx b/packages/editor/src/components/inline-toolbar/inline-toolbar.tsx
index 45ed387..b4d967c 100644
--- a/packages/editor/src/components/inline-toolbar/inline-toolbar.tsx
+++ b/packages/editor/src/components/inline-toolbar/inline-toolbar.tsx
@@ -1,5 +1,5 @@
-import { StitchesProps, styled } from '@hexx/theme';
-import { ReactNode, useCallback } from 'react';
+import { styled } from '@hexx/theme';
+import { ComponentProps, ReactNode, useCallback } from 'react';
import { SelectionChangePlugin } from '../../plugins';
import { generateGetBoundingClientRect } from '../../utils/virtual-element';
import Bold from '../icons/bold';
@@ -60,7 +60,7 @@ function DefaultInlineTool({
...props
}: UseInlineToolConfig & {
children: ReactNode;
-} & StitchesProps) {
+} & ComponentProps) {
const { getProps } = useDefaultInlineTool({
type,
shortcut,
@@ -76,11 +76,13 @@ function DefaultInlineTool({
export function InlineToolBar({
children,
...props
-}: { children?: ReactNode } & StitchesProps) {
+}: { children?: ReactNode } & ComponentProps) {
return {children};
}
-export function InlineBold(props: StitchesProps) {
+export function InlineBold(
+ props: ComponentProps,
+) {
return (
) {
}
export function InlineItalic(
- props: StitchesProps,
+ props: ComponentProps,
) {
return (
,
+ props: ComponentProps,
) {
return (
) {
+}: { children?: ReactNode } & ComponentProps) {
return (
@@ -145,7 +147,7 @@ export function InlineToolBarPreset({
);
}
-export function InlineTool({ children }: { children?: ReactNode }) {
+export function InlineTool({ children }: { children?: ReactNode }) {
const popper = useReactPopper({
placement: 'bottom-start',
modifiers: [
diff --git a/packages/editor/src/components/inline-toolbar/link/link.tsx b/packages/editor/src/components/inline-toolbar/link/link.tsx
index 8f44200..7d9ef44 100644
--- a/packages/editor/src/components/inline-toolbar/link/link.tsx
+++ b/packages/editor/src/components/inline-toolbar/link/link.tsx
@@ -1,9 +1,9 @@
-import { StitchesProps, styled } from '@hexx/theme';
+import { styled } from '@hexx/theme';
import { useAtom } from 'jotai';
-import { useEffect, useRef, useState } from 'react';
+import { ComponentProps, useEffect, useRef, useState } from 'react';
import {
ActiveBlock,
- activeBlockAtom,
+ activeBlockAtom
} from '../../../constants/atom';
import { getSelectionRange } from '../../../utils/ranges';
import Link from '../../icons/link';
@@ -12,7 +12,7 @@ import { useReactPopper } from '../../popper/use-react-popper';
import {
isAnchorElement,
useEventChangeSelection,
- useInlineTool,
+ useInlineTool
} from '../hooks';
import { IconWrapper } from '../inline-toolbar';
@@ -58,13 +58,13 @@ function highlight(r: Range | null) {
return el;
}
-export function InlineLink(props: StitchesProps) {
+export function InlineLink(
+ props: ComponentProps,
+) {
const [activeBlock] = useAtom(activeBlockAtom);
const [initialValue, setInitialValue] = useState('');
- const [
- currentActiveBlock,
- setCurrentActiveBlock,
- ] = useState(null);
+ const [currentActiveBlock, setCurrentActiveBlock] =
+ useState(null);
const snapHTML = useRef();
const editableSnap = useRef();
const [hasChanged, setHasChanged] = useState(false);
@@ -131,9 +131,10 @@ export function InlineLink(props: StitchesProps) {
return;
}
// @ts-ignore
- const target = currentActiveBlock?.blockEl?.querySelector(
- '.hexx-link-target',
- );
+ const target =
+ currentActiveBlock?.blockEl?.querySelector(
+ '.hexx-link-target',
+ );
if (!target) return;
r.selectNodeContents(target);
selection.removeAllRanges();
diff --git a/packages/editor/src/components/plus-button.tsx b/packages/editor/src/components/plus-button.tsx
index d51a83f..b614494 100644
--- a/packages/editor/src/components/plus-button.tsx
+++ b/packages/editor/src/components/plus-button.tsx
@@ -1,12 +1,19 @@
-import { StitchesProps, styled } from '@hexx/theme';
+import { styled } from '@hexx/theme';
import { useAtom } from 'jotai';
-import { useEffect, useState } from 'react';
+import { ComponentProps, useEffect, useState } from 'react';
import { BlockAtom } from '../constants/atom';
import { useEditor, useEventListener } from '../hooks';
import { usePlugin } from '../plugins';
import { BlockType, isBlockEmpty } from '../utils/blocks';
import { findBlockById } from '../utils/find-blocks';
import { BlockMenu, BlockMenuItem } from './block-menu';
+import {
+ divider as DividerSvg,
+ header as HeaderSvg,
+ list as ListSvg,
+ quote as QuoteSvg,
+ text as TextIcon,
+} from './icons';
import { PortalPopper } from './popper/portal-popper';
import {
useReactPopper,
@@ -68,8 +75,8 @@ const AddMenu = styled('div', {
interface PlusButtonProps {
popper?: UseReactPopperProps;
menuPopper?: UseReactPopperProps;
- iconProps?: StitchesProps;
- menuProps?: StitchesProps;
+ iconProps?: ComponentProps;
+ menuProps?: ComponentProps;
menu?: BlockMenuItem[];
}
@@ -84,8 +91,7 @@ function useTabMenu(
block: BlockType | null,
) {
const { wrapperRef } = usePlugin();
- const { blockMap } = useEditor();
-;
+ const { blockScope } = useEditor();
useEventListener(
'keydown',
(e) => {
@@ -95,7 +101,7 @@ function useTabMenu(
if (e.key === 'Tab' && !e.shiftKey) {
if (block) {
const isEmpty = isBlockEmpty(
- blockMap[block.type],
+ blockScope[block.type],
block.data,
);
if (isEmpty) {
@@ -148,9 +154,59 @@ function _PlusButton({
return null;
}
+export const presetPlusButtonMenu = [
+ {
+ type: 'paragraph',
+ icon: {
+ text: 'text',
+ svg: TextIcon,
+ },
+ },
+ {
+ type: 'header',
+ icon: {
+ text: 'Header',
+ svg: HeaderSvg,
+ },
+ },
+ {
+ type: 'quote',
+ icon: {
+ text: 'Quote',
+ svg: QuoteSvg,
+ },
+ },
+ {
+ type: 'delimiter',
+ icon: {
+ text: 'Divider',
+ svg: DividerSvg,
+ },
+ },
+ {
+ type: 'list',
+ icon: {
+ text: 'Unordered List',
+ svg: ListSvg,
+ },
+ },
+ {
+ type: 'list',
+ icon: {
+ text: 'Ordered List',
+ svg: ListSvg,
+ },
+ defaultValue: {
+ style: 'ordered',
+ },
+ },
+];
+
export function PlusButton(props: PlusButtonProps) {
+ const { menu = presetPlusButtonMenu } = props;
const { hoverBlockAtom } = useEditor();
- const [activeAddingBlockAtom, setActiveAddingBlockAtom] = useState();
+ const [activeAddingBlockAtom, setActiveAddingBlockAtom] =
+ useState();
const popper = useReactPopper({
defaultActive: false,
@@ -206,7 +262,7 @@ export function PlusButton(props: PlusButtonProps) {
menuPopper.setActive(false)}
/>
diff --git a/packages/editor/src/components/tune-button.tsx b/packages/editor/src/components/tune-button.tsx
index 9079af1..aeecb68 100644
--- a/packages/editor/src/components/tune-button.tsx
+++ b/packages/editor/src/components/tune-button.tsx
@@ -1,14 +1,29 @@
-import { StitchesProps, styled } from '@hexx/theme';
+import { styled } from '@hexx/theme';
import { useAtom } from 'jotai';
-import { forwardRef, ReactNode, useEffect } from 'react';
+import {
+ ComponentProps,
+ forwardRef,
+ ReactNode,
+ useEffect
+} from 'react';
import { $lastHoverAtom, BlockAtom } from '../constants/atom';
import { useEditor } from '../hooks';
import { findBlockById } from '../utils/find-blocks';
+import {
+ AlignCenter,
+ AlignLeft,
+ AlignRight,
+ h1,
+ h2,
+ h3,
+ IcNumList,
+ list as ListSvg
+} from './icons';
import { PortalPopper } from './popper/portal-popper';
import {
useReactPopper,
UseReactPopperProps,
- UseReactPopperReturn,
+ UseReactPopperReturn
} from './popper/use-react-popper';
const Tune = styled('div', {
@@ -51,8 +66,9 @@ const Icon = styled('svg', {
interface TuneButtonProps {
popper?: UseReactPopperProps;
- buttonProps?: StitchesProps;
+ buttonProps?: ComponentProps;
icon?: ReactNode;
+ config?: TuneConfig;
}
const Tunes = ({
@@ -60,20 +76,22 @@ const Tunes = ({
icon,
popper,
isSelecting,
+ config,
}: {
blockAtom: BlockAtom;
icon?: ReactNode;
popper: UseReactPopperReturn;
isSelecting?: boolean;
+ config: TuneConfig;
}) => {
- const { blockMap, removeBlock, selectBlock } = useEditor();
+ const { removeBlock, selectBlock } = useEditor();
const [currentBlockData, setBlockData] = useAtom(blockAtom);
const tunes =
currentBlockData &&
currentBlockData.type &&
typeof currentBlockData.type === 'string' &&
- blockMap[currentBlockData.type]?.block?.tune;
+ config[currentBlockData.type];
useEffect(() => {
if (currentBlockData) {
@@ -95,30 +113,31 @@ const Tunes = ({
<>
{isSelecting ? (
<>
- {tunes?.map((tune, i) => {
- return (
- {
- if (!currentBlockData) return;
- setBlockData((s) => ({
- ...s,
- data: tune.updater(currentBlockData?.data),
- }));
- selectBlock();
- popper.popperJs.update?.();
- e.stopPropagation();
- }}
- />
- );
- })}
+ {Array.isArray(tunes) &&
+ tunes.map((tune, i) => {
+ return (
+ {
+ if (!currentBlockData) return;
+ setBlockData((s) => ({
+ ...s,
+ data: tune.updater(currentBlockData?.data),
+ }));
+ selectBlock();
+ popper.popperJs.update?.();
+ e.stopPropagation();
+ }}
+ />
+ );
+ })}