import { Meta, Story } from '@storybook/react/types-6-0';
import React, { useCallback, useState } from 'react';
import { Descendant, Range, Text } from 'slate';
import { Editable, Slate } from 'slate-react';
import { SlateExtension, useSlateState, useSlateWithExtensions } from '../.';
export default {
title: 'Examples/Highlights',
} as Meta;
export const Default: Story = () => {
const [value, onChange] = useSlateState(initialValue);
// define the extension
const { getSearchBarProps, ...highlightExtension } = useHighlightExtension(
'search'
);
// create slate with the extension
const { getEditableProps, getSlateProps } = useSlateWithExtensions({
onChange,
value,
extensions: [highlightExtension],
});
// render the extension and the search bar
return (
);
};
export const useHighlightExtension = (
initialSearch?: string
): SlateExtension & {
getSearchBarProps: () => SearchBarProps;
} => {
// state for the search text
const [search, setSearch] = useState(initialSearch);
// decorate function for highlighting search text
const decorate = useCallback>(
([node, path]) => {
const ranges: Range[] = [];
if (search && Text.isText(node)) {
const { text } = node;
const parts = text.split(search);
let offset = 0;
parts.forEach((part, i) => {
if (i !== 0) {
ranges.push({
anchor: { path, offset: offset - search.length },
focus: { path, offset },
highlight: true,
});
}
offset = offset + part.length + search.length;
});
}
return ranges;
},
[search]
);
// render leaf for rendering search text
const renderLeaf = useCallback>(
({ leaf, children }) => {
if (leaf.highlight) {
return {children};
}
},
[]
);
// create the search bar props
const getSearchBarProps = useCallback<() => SearchBarProps>(
() => ({
onSearchChange: setSearch,
search: search ?? '',
}),
[search]
);
return {
decorate,
decorateDeps: [decorate],
renderLeaf,
renderLeafDeps: [renderLeaf],
getSearchBarProps,
};
};
interface SearchBarProps {
search: string;
onSearchChange: (search: string) => void;
}
export const SearchBar: React.FC = ({
search,
onSearchChange,
}) => {
return (
);
};
const initialValue: Descendant[] = [
{
children: [
{
text:
'This is editable text that you can search. As you search, it looks for matching strings of text, and adds ',
},
{ text: 'decorations' },
{ text: ' to them in realtime.' },
],
},
{
children: [
{ text: 'Try it out for yourself by typing in the search box above!' },
],
},
];