refactor(web): remove typescript
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
import Variable from './Variable';
|
||||
|
||||
export default function Element(props: any) {
|
||||
export default function Element(props) {
|
||||
const { attributes, children, element, disabled } = props;
|
||||
|
||||
switch (element.type) {
|
||||
case 'variable':
|
||||
return <Variable {...props} disabled={disabled} />;
|
@@ -1,16 +1,15 @@
|
||||
import Chip from '@mui/material/Chip';
|
||||
import { useSelected, useFocused } from 'slate-react';
|
||||
|
||||
export default function Variable({ attributes, children, element, disabled }: any) {
|
||||
export default function Variable({ attributes, children, element, disabled }) {
|
||||
const selected = useSelected();
|
||||
const focused = useFocused();
|
||||
const label = (
|
||||
<>
|
||||
<span style={{ fontWeight: 500 }}>{element.name}</span>: <span style={{ fontWeight: 300 }}>{element.sampleValue}</span>
|
||||
<span style={{ fontWeight: 500 }}>{element.name}</span>:{' '}
|
||||
<span style={{ fontWeight: 300 }}>{element.sampleValue}</span>
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<Chip
|
||||
{...attributes}
|
||||
@@ -24,5 +23,4 @@ export default function Variable({ attributes, children, element, disabled }: an
|
||||
label={label}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
}
|
@@ -1,3 +1,2 @@
|
||||
import { Slate } from 'slate-react';
|
||||
|
||||
export default Slate;
|
1
packages/web/src/components/Slate/types.js
Normal file
1
packages/web/src/components/Slate/types.js
Normal file
@@ -0,0 +1 @@
|
||||
export {};
|
@@ -1,32 +0,0 @@
|
||||
import type { BaseEditor, Text, Descendant } from 'slate';
|
||||
import type { ReactEditor } from 'slate-react';
|
||||
|
||||
export type VariableElement = {
|
||||
type: 'variable';
|
||||
value?: unknown;
|
||||
name?: string;
|
||||
sampleValue?: unknown;
|
||||
children: Text[];
|
||||
};
|
||||
|
||||
export type ParagraphElement = {
|
||||
type: 'paragraph';
|
||||
value?: string;
|
||||
children: Descendant[];
|
||||
};
|
||||
|
||||
export type CustomText = {
|
||||
text: string;
|
||||
value: string;
|
||||
};
|
||||
|
||||
export type CustomEditor = BaseEditor & ReactEditor;
|
||||
|
||||
export type CustomElement = VariableElement | ParagraphElement;
|
||||
|
||||
declare module 'slate' {
|
||||
interface CustomTypes {
|
||||
Editor: CustomEditor;
|
||||
Element: CustomElement;
|
||||
}
|
||||
}
|
@@ -1,115 +1,65 @@
|
||||
import { Text, Descendant } from 'slate';
|
||||
import { Text } from 'slate';
|
||||
import { withHistory } from 'slate-history';
|
||||
import { ReactEditor, withReact } from 'slate-react';
|
||||
import { IFieldDropdownOption } from 'types';
|
||||
|
||||
import type {
|
||||
CustomEditor,
|
||||
CustomElement,
|
||||
CustomText,
|
||||
ParagraphElement,
|
||||
VariableElement,
|
||||
} from './types';
|
||||
|
||||
type StepWithVariables = {
|
||||
id: string;
|
||||
name: string;
|
||||
output: {
|
||||
label: string;
|
||||
sampleValue: string;
|
||||
value: string;
|
||||
}[];
|
||||
};
|
||||
|
||||
type StepsWithVariables = StepWithVariables[];
|
||||
|
||||
function isCustomText(value: any): value is CustomText {
|
||||
function isCustomText(value) {
|
||||
const isText = Text.isText(value);
|
||||
const hasValueProperty = 'value' in value;
|
||||
|
||||
if (isText && hasValueProperty) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function getStepPosition(id: string, stepsWithVariables: StepsWithVariables) {
|
||||
function getStepPosition(id, stepsWithVariables) {
|
||||
const stepIndex = stepsWithVariables.findIndex((stepWithVariables) => {
|
||||
return stepWithVariables.id === id;
|
||||
});
|
||||
|
||||
return stepIndex + 1;
|
||||
}
|
||||
|
||||
function getVariableName(variable: string) {
|
||||
function getVariableName(variable) {
|
||||
return variable.replace(/{{|}}/g, '');
|
||||
}
|
||||
|
||||
function getVariableStepId(variable: string) {
|
||||
function getVariableStepId(variable) {
|
||||
const nameWithoutCurlies = getVariableName(variable);
|
||||
const stepId = nameWithoutCurlies.match(stepIdRegExp)?.[1] || '';
|
||||
|
||||
return stepId;
|
||||
}
|
||||
|
||||
function getVariableSampleValue(
|
||||
variable: string,
|
||||
stepsWithVariables: StepsWithVariables
|
||||
) {
|
||||
function getVariableSampleValue(variable, stepsWithVariables) {
|
||||
const variableStepId = getVariableStepId(variable);
|
||||
const stepWithVariables = stepsWithVariables.find(
|
||||
({ id }: { id: string }) => id === variableStepId
|
||||
({ id }) => id === variableStepId
|
||||
);
|
||||
|
||||
if (!stepWithVariables) return null;
|
||||
|
||||
const variableName = getVariableName(variable);
|
||||
const variableData = stepWithVariables.output.find(
|
||||
({ value }) => variableName === value
|
||||
);
|
||||
|
||||
if (!variableData) return null;
|
||||
|
||||
return variableData.sampleValue;
|
||||
}
|
||||
|
||||
function getVariableDetails(
|
||||
variable: string,
|
||||
stepsWithVariables: StepsWithVariables
|
||||
) {
|
||||
function getVariableDetails(variable, stepsWithVariables) {
|
||||
const variableName = getVariableName(variable);
|
||||
const stepId = getVariableStepId(variableName);
|
||||
const stepPosition = getStepPosition(stepId, stepsWithVariables);
|
||||
const sampleValue = getVariableSampleValue(variable, stepsWithVariables);
|
||||
const label = variableName.replace(`step.${stepId}.`, `step${stepPosition}.`);
|
||||
|
||||
return {
|
||||
sampleValue,
|
||||
label,
|
||||
};
|
||||
}
|
||||
|
||||
const variableRegExp = /({{.*?}})/;
|
||||
const stepIdRegExp = /^step.([\da-zA-Z-]*)/;
|
||||
|
||||
export const deserialize = (
|
||||
value: boolean | string | number,
|
||||
options: readonly IFieldDropdownOption[],
|
||||
stepsWithVariables: StepsWithVariables
|
||||
): Descendant[] => {
|
||||
export const deserialize = (value, options, stepsWithVariables) => {
|
||||
const selectedNativeOption = options?.find(
|
||||
(option) => value === option.value
|
||||
);
|
||||
|
||||
if (selectedNativeOption) {
|
||||
return [
|
||||
{
|
||||
type: 'paragraph',
|
||||
value: selectedNativeOption.value as string,
|
||||
value: selectedNativeOption.value,
|
||||
children: [{ text: selectedNativeOption.label }],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
if (value === null || value === undefined || value === '')
|
||||
return [
|
||||
{
|
||||
@@ -117,13 +67,11 @@ export const deserialize = (
|
||||
children: [{ text: '' }],
|
||||
},
|
||||
];
|
||||
|
||||
return value
|
||||
.toString()
|
||||
.split('\n')
|
||||
.map((line) => {
|
||||
const nodes = line.split(variableRegExp);
|
||||
|
||||
if (nodes.length > 1) {
|
||||
return {
|
||||
type: 'paragraph',
|
||||
@@ -133,7 +81,6 @@ export const deserialize = (
|
||||
node,
|
||||
stepsWithVariables
|
||||
);
|
||||
|
||||
return {
|
||||
type: 'variable',
|
||||
name: variableDetails.label,
|
||||
@@ -142,26 +89,21 @@ export const deserialize = (
|
||||
children: [{ text: '' }],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
text: node,
|
||||
};
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'paragraph',
|
||||
children: [{ text: line }],
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
export const serialize = (value: Descendant[]): string | number | null => {
|
||||
export const serialize = (value) => {
|
||||
const serializedNodes = value.map((node) => serializeNode(node));
|
||||
|
||||
const hasSingleNode = value.length === 1;
|
||||
|
||||
/**
|
||||
* return single serialize node alone so that we don't stringify.
|
||||
* booleans stay booleans, numbers stay number
|
||||
@@ -169,28 +111,20 @@ export const serialize = (value: Descendant[]): string | number | null => {
|
||||
if (hasSingleNode) {
|
||||
return serializedNodes[0];
|
||||
}
|
||||
|
||||
const serializedValue = serializedNodes.join('\n');
|
||||
return serializedValue;
|
||||
};
|
||||
|
||||
const serializeNode = (
|
||||
node: CustomElement | Descendant
|
||||
): string | number | null => {
|
||||
const serializeNode = (node) => {
|
||||
if (isCustomText(node)) {
|
||||
return node.value;
|
||||
}
|
||||
|
||||
if (Text.isText(node)) {
|
||||
return node.text;
|
||||
}
|
||||
|
||||
if (node.type === 'variable') {
|
||||
return node.value as string;
|
||||
return node.value;
|
||||
}
|
||||
|
||||
const hasSingleChild = node.children.length === 1;
|
||||
|
||||
/**
|
||||
* serialize alone so that we don't stringify.
|
||||
* booleans stay booleans, numbers stay number
|
||||
@@ -198,89 +132,62 @@ const serializeNode = (
|
||||
if (hasSingleChild) {
|
||||
return serializeNode(node.children[0]);
|
||||
}
|
||||
|
||||
return node.children.map((n) => serializeNode(n)).join('');
|
||||
};
|
||||
|
||||
export const withVariables = (editor: CustomEditor) => {
|
||||
export const withVariables = (editor) => {
|
||||
const { isInline, isVoid } = editor;
|
||||
|
||||
editor.isInline = (element: CustomElement) => {
|
||||
editor.isInline = (element) => {
|
||||
return element.type === 'variable' ? true : isInline(element);
|
||||
};
|
||||
|
||||
editor.isVoid = (element: CustomElement) => {
|
||||
editor.isVoid = (element) => {
|
||||
return element.type === 'variable' ? true : isVoid(element);
|
||||
};
|
||||
|
||||
return editor;
|
||||
};
|
||||
|
||||
export const insertVariable = (
|
||||
editor: CustomEditor,
|
||||
variableData: Record<string, unknown>,
|
||||
stepsWithVariables: StepsWithVariables
|
||||
) => {
|
||||
export const insertVariable = (editor, variableData, stepsWithVariables) => {
|
||||
const variableDetails = getVariableDetails(
|
||||
`{{${variableData.value}}}`,
|
||||
stepsWithVariables
|
||||
);
|
||||
|
||||
const variable: VariableElement = {
|
||||
const variable = {
|
||||
type: 'variable',
|
||||
name: variableDetails.label,
|
||||
sampleValue: variableDetails.sampleValue,
|
||||
value: `{{${variableData.value}}}`,
|
||||
children: [{ text: '' }],
|
||||
};
|
||||
|
||||
editor.insertNodes(variable, { select: false });
|
||||
|
||||
focusEditor(editor);
|
||||
};
|
||||
|
||||
export const focusEditor = (editor: CustomEditor) => {
|
||||
export const focusEditor = (editor) => {
|
||||
ReactEditor.focus(editor);
|
||||
editor.move();
|
||||
};
|
||||
|
||||
export const resetEditor = (
|
||||
editor: CustomEditor,
|
||||
options?: { focus: boolean }
|
||||
) => {
|
||||
export const resetEditor = (editor, options) => {
|
||||
const focus = options?.focus || false;
|
||||
|
||||
editor.removeNodes({
|
||||
at: {
|
||||
anchor: editor.start([]),
|
||||
focus: editor.end([]),
|
||||
},
|
||||
});
|
||||
|
||||
// `editor.normalize({ force: true })` doesn't add an empty node in the editor
|
||||
editor.insertNode(createTextNode(''));
|
||||
|
||||
if (focus) {
|
||||
focusEditor(editor);
|
||||
}
|
||||
};
|
||||
|
||||
export const overrideEditorValue = (
|
||||
editor: CustomEditor,
|
||||
options: { option: IFieldDropdownOption; focus: boolean }
|
||||
) => {
|
||||
export const overrideEditorValue = (editor, options) => {
|
||||
const { option, focus } = options;
|
||||
|
||||
const variable: ParagraphElement = {
|
||||
const variable = {
|
||||
type: 'paragraph',
|
||||
children: [
|
||||
{
|
||||
value: option.value as string,
|
||||
text: option.label as string,
|
||||
value: option.value,
|
||||
text: option.label,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
editor.withoutNormalizing(() => {
|
||||
editor.removeNodes({
|
||||
at: {
|
||||
@@ -288,16 +195,13 @@ export const overrideEditorValue = (
|
||||
focus: editor.end([]),
|
||||
},
|
||||
});
|
||||
|
||||
editor.insertNode(variable);
|
||||
|
||||
if (focus) {
|
||||
focusEditor(editor);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const createTextNode = (text: string): ParagraphElement => ({
|
||||
export const createTextNode = (text) => ({
|
||||
type: 'paragraph',
|
||||
children: [
|
||||
{
|
||||
@@ -305,7 +209,6 @@ export const createTextNode = (text: string): ParagraphElement => ({
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
export const customizeEditor = (editor: CustomEditor): CustomEditor => {
|
||||
export const customizeEditor = (editor) => {
|
||||
return withVariables(withReact(withHistory(editor)));
|
||||
};
|
Reference in New Issue
Block a user