Skip to content

Commit

Permalink
Manual nowrap
Browse files Browse the repository at this point in the history
  • Loading branch information
cskrov committed Jul 24, 2024
1 parent 08db436 commit bed1c13
Show file tree
Hide file tree
Showing 10 changed files with 68 additions and 168 deletions.
18 changes: 18 additions & 0 deletions frontend/src/plate/components/nowrap.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Tooltip } from '@navikt/ds-react';
import { PlateElement, PlateElementProps } from '@udecode/plate-common';
import { styled } from 'styled-components';
import { EditorValue, NowrapElement } from '../types';

export const Nowrap = ({ children, element, ...props }: PlateElementProps<EditorValue, NowrapElement>) => (
<Tooltip content="Linjeskift forhindret">
<PlateElement as={NowrapStyle} {...props} element={element}>
{children}
</PlateElement>
</Tooltip>
);

const NowrapStyle = styled.span`
white-space: pre;
background-color: rgba(99, 70, 137, 0.2);
border-radius: 4px;
`;
4 changes: 2 additions & 2 deletions frontend/src/plate/hooks/use-is-element-active.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TElement, isBlock, isExpanded, someNode } from '@udecode/plate-common';
import { TElement, isElement, isExpanded, someNode } from '@udecode/plate-common';
import { useMyPlateEditorState } from '../types';

export const useIsElementActive = (element: string) => {
Expand All @@ -9,7 +9,7 @@ export const useIsElementActive = (element: string) => {
}

return someNode<TElement>(editor, {
match: (n) => isBlock(editor, n) && n.type === element,
match: (n) => isElement(n) && n.type === element,
mode: 'lowest',
});
};
2 changes: 0 additions & 2 deletions frontend/src/plate/leaf/leaf.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,6 @@ const getLeafStyles = (leaf: RichText): React.CSSProperties => ({
fontWeight: leaf.bold === true ? '600' : 'inherit',
fontStyle: leaf.italic === true ? 'italic' : 'inherit',
textDecoration: leaf.underline === true ? 'underline' : 'inherit',
whiteSpace: leaf.nowrap === true ? 'pre' : 'inherit',
outline: leaf.nowrap === true ? '1px solid red' : 'inherit',
userSelect: 'text',
});

Expand Down
1 change: 1 addition & 0 deletions frontend/src/plate/plugins/element-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const ELEMENT_FOOTER = 'footer';
export const ELEMENT_LABEL_CONTENT = 'label-content';
export const ELEMENT_SIGNATURE = 'signature';
export const ELEMENT_EMPTY_VOID = 'empty-void';
export const ELEMENT_NOWRAP = 'nowrap';

export const UNCHANGEABLE = [
ELEMENT_HEADER,
Expand Down
158 changes: 4 additions & 154 deletions frontend/src/plate/plugins/normalize-node.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,9 @@
/* eslint-disable max-depth */
import {
TNodeEntry,
createPluginFactory,
getNextNode,
getNode,
getNodeString,
getParentNode,
getPreviousNode,
insertNodes,
isElement,
isText,
setNodes,
} from '@udecode/plate-common';
import { createPluginFactory, getNode, insertNodes, isElement } from '@udecode/plate-common';
import { ELEMENT_H1, ELEMENT_H2, ELEMENT_H3 } from '@udecode/plate-heading';
import { ELEMENT_LI, ELEMENT_LIC, ELEMENT_OL, ELEMENT_UL } from '@udecode/plate-list';
import { ELEMENT_PARAGRAPH } from '@udecode/plate-paragraph';
import { ELEMENT_TABLE, ELEMENT_TD, ELEMENT_TR } from '@udecode/plate-table';
import { Point, Range, Scrubber, isEditor } from 'slate';
import { Scrubber } from 'slate';
import { pushEvent } from '@app/observability';
import {
ELEMENT_CURRENT_DATE,
Expand All @@ -42,39 +29,7 @@ import {
createTableCell,
createTableRow,
} from '@app/plate/templates/helpers';
import {
H1Element,
H2Element,
H3Element,
ListItemContainerElement,
ParagraphElement,
PlaceholderElement,
RichText,
RichTextEditorElement,
} from '@app/plate/types';
import { isOfElementTypesFn } from '@app/plate/utils/queries';

const DATE_REGEX =
/(?:\d{2}(?:\.|-|\/)\d{2}(?:(?:\.|-|\/)\d{4})?)|(?:(?:\d+(?:\.|,| )?)+\d+(?:,-| kr(?:\.|,|:|;| |$)| kroner(?:\.|,|:|;| |$))?)/m;

type RichTextElement =
| H1Element
| H2Element
| H3Element
| ParagraphElement
| ListItemContainerElement
| PlaceholderElement;

const isRichTextElement = isOfElementTypesFn<RichTextElement>([
ELEMENT_H1,
ELEMENT_H2,
ELEMENT_H3,
ELEMENT_LIC,
ELEMENT_PARAGRAPH,
ELEMENT_PLACEHOLDER,
]);

const ENDINGS = ['.', ',', 'kr', 'kroner', ' '];
import { RichText, RichTextEditorElement } from '@app/plate/types';

export const createNormalizeNodePlugin = createPluginFactory({
key: 'normalize',
Expand All @@ -83,112 +38,7 @@ export const createNormalizeNodePlugin = createPluginFactory({

// eslint-disable-next-line complexity
editor.normalizeNode<RichTextEditorElement | RichText> = ([node, path]) => {
if (isText(node)) {
let relevantText = node.text;
let entries: TNodeEntry<RichText>[] = [[node, path]];

while (relevantText.endsWith(' ')) {
const nextEntry = getNextNode<RichText>(editor, { at: path, match: isText });

if (nextEntry !== undefined) {
entries = [...entries, nextEntry];
relevantText += nextEntry[0].text;
} else {
break;
}
}

while (relevantText.startsWith(' ')) {
const prevEntry = getPreviousNode<RichText>(editor, { at: path, match: isText });

if (prevEntry !== undefined) {
entries = [prevEntry, ...entries];
relevantText = prevEntry[0].text + relevantText;
} else {
break;
}
}

const match = relevantText.match(DATE_REGEX);

if (match !== null) {
const { index } = match;
const [matched] = match;

if (matched !== undefined && index !== undefined) {
const end = index + matched.trimEnd().length;

let totalOffset = 0;
entries = entries.filter((entry) => {
const { length } = entry[0].text;

if (totalOffset + length > index && totalOffset + 1 < end) {
totalOffset += length;

return true;
}

return false;
});

const lastOffset = end - entries.slice(0, -1).reduce((acc, [entry]) => acc + entry.text.length, 0);

console.log({ entries, matched: matched.trimEnd(), index, lastOffset, end, totalOffset });
}
}

// if (match === null) {
// if (node.nowrap === true) {
// // console.log('remove nowrap', node);

// return setNodes(
// editor,
// { nowrap: false },
// { at: path, split: true, mode: 'lowest', match: (n) => n === node },
// );
// }
// } else if (node.nowrap === true) {
// // console.log('matched already nowrapped', node);

// if (editor.marks !== null) {
// editor.marks['nowrap'] = false;
// }

// const { index } = match;

// if (index !== undefined) {
// const [matched] = match;

// const at: Range = {
// anchor: { path, offset: index + matched.length },
// focus: { path, offset: node.text.length },
// };

// // console.log('remove nowrap', node, {
// // matched,
// // index,
// // at,
// // });

// return setNodes(editor, { nowrap: false }, { at, split: true, mode: 'lowest', match: (n) => n === node });
// }
// } else {
// const { index } = match;

// if (index !== undefined) {
// const [matched] = match;
// const at: Range = { anchor: { path, offset: index }, focus: { path, offset: index + matched.length } };

// console.log('add nowrap', node, {
// matched,
// index,
// at,
// });

// return setNodes(editor, { nowrap: true }, { at, split: true, mode: 'lowest', match: (n) => n === node });
// }
// }
} else if (isElement(node) && node.children.length === 0) {
if (isElement(node) && node.children.length === 0) {
const [highestAncestorPath] = path;
const highestAncestor =
highestAncestorPath === undefined ? undefined : Scrubber.stringify(getNode(editor, [highestAncestorPath]));
Expand Down
9 changes: 9 additions & 0 deletions frontend/src/plate/plugins/nowrap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { createPluginFactory } from '@udecode/plate-common';
import { ELEMENT_NOWRAP } from './element-types';

export const createNowrapPlugin = createPluginFactory({
key: ELEMENT_NOWRAP,
isElement: true,
isVoid: false,
isInline: true,
});
5 changes: 5 additions & 0 deletions frontend/src/plate/plugins/plugin-sets/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { HeadingOne, HeadingThree, HeadingTwo } from '@app/plate/components/head
import { LabelContent } from '@app/plate/components/label-content';
import { ListItem, OrderedList, UnorderedList } from '@app/plate/components/lists';
import { Maltekst } from '@app/plate/components/maltekst/maltekst';
import { Nowrap } from '@app/plate/components/nowrap';
import { PageBreak } from '@app/plate/components/page-break';
import { Paragraph } from '@app/plate/components/paragraph';
import { Placeholder } from '@app/plate/components/placeholder/placeholder';
Expand All @@ -19,13 +20,15 @@ import {
ELEMENT_EMPTY_VOID,
ELEMENT_LABEL_CONTENT,
ELEMENT_MALTEKST,
ELEMENT_NOWRAP,
ELEMENT_PAGE_BREAK,
ELEMENT_PLACEHOLDER,
ELEMENT_REDIGERBAR_MALTEKST,
} from '@app/plate/plugins/element-types';
import { createEmptyVoidPlugin } from '@app/plate/plugins/empty-void';
import { createLabelContentPlugin } from '@app/plate/plugins/label-content';
import { createMaltekstPlugin } from '@app/plate/plugins/maltekst';
import { createNowrapPlugin } from '@app/plate/plugins/nowrap';
import { createSaksbehandlerPlaceholderPlugin } from '@app/plate/plugins/placeholder/saksbehandler';
import { defaultPlugins } from '@app/plate/plugins/plugin-sets/default';
import { createRedigerbarMaltekstPlugin } from '@app/plate/plugins/redigerbar-maltekst';
Expand All @@ -38,10 +41,12 @@ export const previewPlugins = createPlugins(
createRedigerbarMaltekstPlugin(),
createLabelContentPlugin(),
createEmptyVoidPlugin(),
createNowrapPlugin(),
],
{
components: {
[ELEMENT_PARAGRAPH]: Paragraph,
[ELEMENT_NOWRAP]: Nowrap,
[ELEMENT_PAGE_BREAK]: PageBreak,

// Headings
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/plate/plugins/plugin-sets/saksbehandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { LabelContent } from '@app/plate/components/label-content';
import { ListItem, OrderedList, UnorderedList } from '@app/plate/components/lists';
import { Maltekst } from '@app/plate/components/maltekst/maltekst';
import { Maltekstseksjon } from '@app/plate/components/maltekstseksjon/maltekstseksjon';
import { Nowrap } from '@app/plate/components/nowrap';
import { PageBreak } from '@app/plate/components/page-break';
import { Paragraph } from '@app/plate/components/paragraph';
import { Placeholder } from '@app/plate/components/placeholder/placeholder';
Expand All @@ -31,6 +32,7 @@ import {
ELEMENT_LABEL_CONTENT,
ELEMENT_MALTEKST,
ELEMENT_MALTEKSTSEKSJON,
ELEMENT_NOWRAP,
ELEMENT_PAGE_BREAK,
ELEMENT_PLACEHOLDER,
ELEMENT_REDIGERBAR_MALTEKST,
Expand All @@ -43,6 +45,7 @@ import { createFooterPlugin, createHeaderPlugin } from '@app/plate/plugins/heade
import { createLabelContentPlugin } from '@app/plate/plugins/label-content';
import { createMaltekstPlugin } from '@app/plate/plugins/maltekst';
import { createMaltekstseksjonPlugin } from '@app/plate/plugins/maltekstseksjon';
import { createNowrapPlugin } from '@app/plate/plugins/nowrap';
import { createSaksbehandlerPlaceholderPlugin } from '@app/plate/plugins/placeholder/saksbehandler';
import { defaultPlugins } from '@app/plate/plugins/plugin-sets/default';
import { createRedigerbarMaltekstPlugin } from '@app/plate/plugins/redigerbar-maltekst';
Expand All @@ -66,10 +69,12 @@ export const saksbehandlerPlugins = createPlugins(
createSignaturePlugin(),
createEmptyVoidPlugin(),
createBookmarkPlugin(),
createNowrapPlugin(),
],
{
components: {
[ELEMENT_PARAGRAPH]: Paragraph,
[ELEMENT_NOWRAP]: Nowrap,
[ELEMENT_PAGE_BREAK]: PageBreak,

// Headings
Expand Down
27 changes: 18 additions & 9 deletions frontend/src/plate/toolbar/marks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,21 @@ import { TrendFlatIcon } from '@navikt/aksel-icons';
import { ClearFormatting, TextBold, TextItalic, TextUnderline } from '@styled-icons/fluentui-system-regular';
import { MARK_BOLD, MARK_ITALIC, MARK_UNDERLINE } from '@udecode/plate-basic-marks';
import {
addMark,
getPluginType,
isMarkActive,
isText,
removeMark,
someNode,
unwrapNodes,
useMarkToolbarButton,
useMarkToolbarButtonState,
wrapNodes,
} from '@udecode/plate-common';
import { MARK_COLOR } from '@udecode/plate-font';
import { ELEMENT_H1, ELEMENT_H2, ELEMENT_H3 } from '@udecode/plate-heading';
import { MOD_KEY } from '@app/keys';
import { useIsElementActive } from '@app/plate/hooks/use-is-element-active';
import { useIsUnchangeable } from '@app/plate/hooks/use-is-unchangeable';
import { ELEMENT_PLACEHOLDER } from '@app/plate/plugins/element-types';
import { ELEMENT_NOWRAP, ELEMENT_PLACEHOLDER } from '@app/plate/plugins/element-types';
import { ToolbarIconButton } from '@app/plate/toolbar/toolbarbutton';
import { EditorValue, useMyPlateEditorState } from '@app/plate/types';
import { isOfElementTypesFn } from '@app/plate/utils/queries';
Expand Down Expand Up @@ -44,6 +46,8 @@ export const Marks = () => {
props: { onClick: toggleUnderline, pressed: underlinePressed },
} = useMarkToolbarButton(underlineState);

const nowrapActive = useIsElementActive(ELEMENT_NOWRAP);

return (
<>
<ToolbarIconButton
Expand Down Expand Up @@ -74,13 +78,18 @@ export const Marks = () => {
/>

<ToolbarIconButton
label="Nowrap"
keys={[MOD_KEY, 'N']}
onClick={() =>
isMarkActive(editor, 'nowrap') ? removeMark(editor, { key: 'nowrap' }) : addMark(editor, 'nowrap', true)
}
label="Forhindr linjeskift"
onClick={() => {
if (!nowrapActive) {
wrapNodes(editor, { type: ELEMENT_NOWRAP, children: [] }, { split: true, mode: 'lowest', match: isText });

return;
}

unwrapNodes(editor, { match: { type: ELEMENT_NOWRAP }, split: false, mode: 'lowest' });
}}
icon={<TrendFlatIcon width={24} aria-hidden />}
active={isMarkActive(editor, 'nowrap')}
active={nowrapActive}
disabled={disabled}
/>

Expand Down
Loading

0 comments on commit bed1c13

Please sign in to comment.