@pallasoft/ps-input-components 1.22.0 → 1.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ps-option-card-group.d.ts +8 -0
- package/dist/components/ps-option-card-group.js +12 -0
- package/dist/components/ps-portable-text-editor.d.ts +2 -2
- package/dist/components/ps-portable-text-editor.js +4 -29
- package/dist/components/ps-portable-text-link-dialog.d.ts +1 -1
- package/dist/components/ps-portable-text-link-dialog.js +4 -26
- package/dist/components/ps-portable-text-toolbar.d.ts +1 -1
- package/dist/components/ps-portable-text-toolbar.js +12 -52
- package/dist/constants/ps-portable-text-editor-config.d.ts +0 -55
- package/dist/constants/ps-portable-text-editor-config.js +0 -40
- package/dist/constants/ps-portable-text-editor-renderers.js +8 -8
- package/dist/esm/components/ps-option-card-group.js +8 -0
- package/dist/esm/components/ps-portable-text-editor.js +5 -30
- package/dist/esm/components/ps-portable-text-link-dialog.js +4 -26
- package/dist/esm/components/ps-portable-text-toolbar.js +13 -53
- package/dist/esm/constants/ps-portable-text-editor-config.js +0 -40
- package/dist/esm/constants/ps-portable-text-editor-renderers.js +8 -8
- package/dist/esm/form/components/ps-form-name-modal.js +16 -0
- package/dist/esm/form/index.js +2 -0
- package/dist/esm/index.js +3 -1
- package/dist/esm/interfaces/ps-option-card-data.js +1 -0
- package/dist/esm/portable-text-core/components/ps-portable-text-core.js +31 -0
- package/dist/esm/portable-text-core/constants/ps-portable-text-core-config.js +42 -0
- package/dist/esm/portable-text-core/hooks/use-ps-portable-text-link-form.js +32 -0
- package/dist/esm/portable-text-core/hooks/use-ps-portable-text-toolbar.js +54 -0
- package/dist/esm/portable-text-core/index.js +6 -0
- package/dist/esm/portable-text-core/interfaces/ps-portable-text-editor-labels.js +1 -0
- package/dist/esm/{services → portable-text-core/services}/ps-portable-text-editor-service.js +6 -6
- package/dist/form/components/ps-form-name-modal.d.ts +15 -0
- package/dist/form/components/ps-form-name-modal.js +20 -0
- package/dist/form/index.d.ts +2 -0
- package/dist/form/index.js +2 -0
- package/dist/form/models/ps-form-name-data.d.ts +3 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/interfaces/ps-option-card-data.d.ts +5 -0
- package/dist/interfaces/ps-option-card-data.js +2 -0
- package/dist/portable-text-core/components/ps-portable-text-core.d.ts +17 -0
- package/dist/portable-text-core/components/ps-portable-text-core.js +35 -0
- package/dist/portable-text-core/constants/ps-portable-text-core-config.d.ts +57 -0
- package/dist/portable-text-core/constants/ps-portable-text-core-config.js +45 -0
- package/dist/portable-text-core/hooks/use-ps-portable-text-link-form.d.ts +13 -0
- package/dist/portable-text-core/hooks/use-ps-portable-text-link-form.js +36 -0
- package/dist/portable-text-core/hooks/use-ps-portable-text-toolbar.d.ts +18 -0
- package/dist/portable-text-core/hooks/use-ps-portable-text-toolbar.js +58 -0
- package/dist/portable-text-core/index.d.ts +7 -0
- package/dist/portable-text-core/index.js +22 -0
- package/dist/portable-text-core/interfaces/ps-portable-text-editor-labels.js +2 -0
- package/dist/{services → portable-text-core/services}/ps-portable-text-editor-service.js +6 -6
- package/package.json +10 -1
- /package/dist/esm/{interfaces/ps-portable-text-editor-labels.js → form/models/ps-form-name-data.js} +0 -0
- /package/dist/{interfaces/ps-portable-text-editor-labels.js → form/models/ps-form-name-data.js} +0 -0
- /package/dist/{interfaces → portable-text-core/interfaces}/ps-portable-text-editor-labels.d.ts +0 -0
- /package/dist/{services → portable-text-core/services}/ps-portable-text-editor-service.d.ts +0 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
import { PsFormModal } from '@pallasoft/ps-popovers';
|
|
4
|
+
import { useForm } from 'react-hook-form';
|
|
5
|
+
import { PsFormTextField } from './ps-form-text-field';
|
|
6
|
+
export const PsFormNameModal = ({ cancelLabel, initialName, isOpen, isSubmitting = false, label, maxLength = 80, onClose, onSave, placeholder, requiredMessage, submitLabel, title, }) => {
|
|
7
|
+
const { control, formState: { isDirty, isValid }, handleSubmit, reset, } = useForm({ mode: 'onChange' });
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
if (isOpen)
|
|
10
|
+
reset({ name: initialName });
|
|
11
|
+
}, [initialName, isOpen, reset]);
|
|
12
|
+
return (_jsx(PsFormModal, { cancelLabel: cancelLabel, isOpen: isOpen, isSubmitDisabled: !isValid || (initialName !== '' && !isDirty), isSubmitting: isSubmitting, onClose: onClose, onSubmit: handleSubmit((values) => onSave(values.name.trim())), size: 'sm', submitLabel: submitLabel, title: title, children: _jsx(PsFormTextField, { control: control, label: label, maxLength: maxLength, name: 'name', placeholder: placeholder, rules: {
|
|
13
|
+
required: requiredMessage,
|
|
14
|
+
validate: (value) => value.trim() !== '' || requiredMessage,
|
|
15
|
+
} }) }));
|
|
16
|
+
};
|
package/dist/esm/form/index.js
CHANGED
|
@@ -9,3 +9,5 @@ export * from './components/ps-form-year-field';
|
|
|
9
9
|
export * from './constants/ps-form-text-kind';
|
|
10
10
|
export * from './models/ps-form-field-rules';
|
|
11
11
|
export * from './services/ps-form-field-service';
|
|
12
|
+
export * from './components/ps-form-name-modal';
|
|
13
|
+
export * from './models/ps-form-name-data';
|
package/dist/esm/index.js
CHANGED
|
@@ -46,4 +46,6 @@ export * from './components/ps-select-with-create';
|
|
|
46
46
|
export * from './constants/ps-select-with-create-config';
|
|
47
47
|
export * from './interfaces/ps-date-preset-data';
|
|
48
48
|
export * from './components/ps-portable-text-editor';
|
|
49
|
-
export * from './interfaces/ps-portable-text-editor-labels';
|
|
49
|
+
export * from './portable-text-core/interfaces/ps-portable-text-editor-labels';
|
|
50
|
+
export * from './components/ps-option-card-group';
|
|
51
|
+
export * from './interfaces/ps-option-card-data';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { EditorProvider, PortableTextEditable, } from '@portabletext/editor';
|
|
4
|
+
import { EventListenerPlugin } from '@portabletext/editor/plugins';
|
|
5
|
+
import { PsPortableTextCoreConfig } from '../constants/ps-portable-text-core-config';
|
|
6
|
+
import { PsPortableTextEditorService } from '../services/ps-portable-text-editor-service';
|
|
7
|
+
export const PsPortableTextCore = ({ className, disabled = false, editableClassName, fallback, minRows = 4, onChange, renderAnnotation, renderBlock, renderDecorator, renderPlaceholder, toolbar, value, }) => {
|
|
8
|
+
const [isMounted, setIsMounted] = useState(false);
|
|
9
|
+
const [version, setVersion] = useState(0);
|
|
10
|
+
const lastValue = useRef(value);
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
setIsMounted(true);
|
|
13
|
+
}, []);
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
if (PsPortableTextEditorService.isSame(value, lastValue.current))
|
|
16
|
+
return;
|
|
17
|
+
lastValue.current = value;
|
|
18
|
+
setVersion((current) => current + 1);
|
|
19
|
+
}, [value]);
|
|
20
|
+
return (_jsx("div", { className: className, children: isMounted ? (_jsxs(EditorProvider, { initialConfig: {
|
|
21
|
+
initialValue: value,
|
|
22
|
+
readOnly: disabled,
|
|
23
|
+
schemaDefinition: PsPortableTextCoreConfig.schemaDefinition,
|
|
24
|
+
}, children: [_jsx(EventListenerPlugin, { on: (event) => {
|
|
25
|
+
if (event.type !== 'mutation')
|
|
26
|
+
return;
|
|
27
|
+
const next = Array.isArray(event.value) ? event.value : [];
|
|
28
|
+
lastValue.current = next;
|
|
29
|
+
onChange(next);
|
|
30
|
+
} }), toolbar, _jsx(PortableTextEditable, { className: editableClassName, readOnly: disabled, renderAnnotation: renderAnnotation, renderBlock: renderBlock, renderDecorator: renderDecorator, renderPlaceholder: renderPlaceholder, style: { minHeight: PsPortableTextEditorService.minHeight(minRows) } })] }, version)) : (fallback) }));
|
|
31
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Common } from '@pallasoft/ps-models';
|
|
2
|
+
import { defineSchema } from '@portabletext/editor';
|
|
3
|
+
const Models = Common.PortableTextConfig;
|
|
4
|
+
export const PsPortableTextCoreConfig = {
|
|
5
|
+
linkAnnotation: Models.linkType,
|
|
6
|
+
mailtoPrefix: 'mailto:',
|
|
7
|
+
emailPattern: /^[^\s@/:]+@[^\s@/:]+\.[^\s@/:]+$/,
|
|
8
|
+
lineHeightRem: 1.5,
|
|
9
|
+
decorators: {
|
|
10
|
+
bold: Models.decorators[0],
|
|
11
|
+
code: Models.decorators[3],
|
|
12
|
+
italic: Models.decorators[1],
|
|
13
|
+
underline: Models.decorators[2],
|
|
14
|
+
},
|
|
15
|
+
styles: { blockquote: Models.styles[1], normal: Models.styles[0] },
|
|
16
|
+
listItems: { bullet: Models.listItems[0], number: Models.listItems[1] },
|
|
17
|
+
schemaDefinition: defineSchema({
|
|
18
|
+
annotations: [{ name: Models.linkType, fields: [{ name: 'href', type: 'string' }] }],
|
|
19
|
+
blockObjects: [],
|
|
20
|
+
decorators: Models.decorators.map((name) => ({ name })),
|
|
21
|
+
inlineObjects: [],
|
|
22
|
+
lists: Models.listItems.map((name) => ({ name })),
|
|
23
|
+
styles: Models.styles.map((name) => ({ name })),
|
|
24
|
+
}),
|
|
25
|
+
labels: {
|
|
26
|
+
bold: 'Bold',
|
|
27
|
+
bulletedList: 'Bulleted list',
|
|
28
|
+
cancel: 'Cancel',
|
|
29
|
+
code: 'Code',
|
|
30
|
+
invalidLink: 'Enter a web address or email address',
|
|
31
|
+
italic: 'Italic',
|
|
32
|
+
link: 'Link',
|
|
33
|
+
linkDialogTitle: 'Link',
|
|
34
|
+
linkUrl: 'Address',
|
|
35
|
+
numberedList: 'Numbered list',
|
|
36
|
+
quote: 'Quote',
|
|
37
|
+
removeLink: 'Remove link',
|
|
38
|
+
saveLink: 'Save',
|
|
39
|
+
toolbar: 'Formatting',
|
|
40
|
+
underline: 'Underline',
|
|
41
|
+
},
|
|
42
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { PsPortableTextEditorService } from '../services/ps-portable-text-editor-service';
|
|
3
|
+
export const usePsPortableTextLinkForm = ({ onClose, onSubmit, }) => {
|
|
4
|
+
const [address, setAddress] = useState('');
|
|
5
|
+
const [hasError, setHasError] = useState(false);
|
|
6
|
+
return {
|
|
7
|
+
address,
|
|
8
|
+
close: () => {
|
|
9
|
+
setAddress('');
|
|
10
|
+
setHasError(false);
|
|
11
|
+
onClose();
|
|
12
|
+
},
|
|
13
|
+
hasError,
|
|
14
|
+
isSubmitDisabled: address.trim() === '',
|
|
15
|
+
setAddress: (next) => {
|
|
16
|
+
setAddress(next);
|
|
17
|
+
setHasError(false);
|
|
18
|
+
},
|
|
19
|
+
submit: (event) => {
|
|
20
|
+
event.preventDefault();
|
|
21
|
+
event.stopPropagation();
|
|
22
|
+
const href = PsPortableTextEditorService.normalizeLink(address);
|
|
23
|
+
if (href === null) {
|
|
24
|
+
setHasError(true);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
setAddress('');
|
|
28
|
+
setHasError(false);
|
|
29
|
+
onSubmit(href);
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { useEditor, useEditorSelector } from '@portabletext/editor';
|
|
2
|
+
import { isActiveAnnotation, isActiveDecorator, isActiveListItem, isActiveStyle, } from '@portabletext/editor/selectors';
|
|
3
|
+
import { PsPortableTextCoreConfig } from '../constants/ps-portable-text-core-config';
|
|
4
|
+
export const usePsPortableTextToolbar = () => {
|
|
5
|
+
const editor = useEditor();
|
|
6
|
+
const isBold = useEditorSelector(editor, isActiveDecorator(PsPortableTextCoreConfig.decorators.bold));
|
|
7
|
+
const isItalic = useEditorSelector(editor, isActiveDecorator(PsPortableTextCoreConfig.decorators.italic));
|
|
8
|
+
const isUnderline = useEditorSelector(editor, isActiveDecorator(PsPortableTextCoreConfig.decorators.underline));
|
|
9
|
+
const isCode = useEditorSelector(editor, isActiveDecorator(PsPortableTextCoreConfig.decorators.code));
|
|
10
|
+
const isBulletedList = useEditorSelector(editor, isActiveListItem(PsPortableTextCoreConfig.listItems.bullet));
|
|
11
|
+
const isNumberedList = useEditorSelector(editor, isActiveListItem(PsPortableTextCoreConfig.listItems.number));
|
|
12
|
+
const isQuote = useEditorSelector(editor, isActiveStyle(PsPortableTextCoreConfig.styles.blockquote));
|
|
13
|
+
const isLink = useEditorSelector(editor, isActiveAnnotation(PsPortableTextCoreConfig.linkAnnotation));
|
|
14
|
+
const focus = () => editor.send({ type: 'focus' });
|
|
15
|
+
return {
|
|
16
|
+
active: {
|
|
17
|
+
bold: isBold,
|
|
18
|
+
bulletedList: isBulletedList,
|
|
19
|
+
code: isCode,
|
|
20
|
+
italic: isItalic,
|
|
21
|
+
link: isLink,
|
|
22
|
+
numberedList: isNumberedList,
|
|
23
|
+
quote: isQuote,
|
|
24
|
+
underline: isUnderline,
|
|
25
|
+
},
|
|
26
|
+
addLink: (href) => {
|
|
27
|
+
editor.send({
|
|
28
|
+
type: 'annotation.add',
|
|
29
|
+
annotation: { name: PsPortableTextCoreConfig.linkAnnotation, value: { href } },
|
|
30
|
+
});
|
|
31
|
+
focus();
|
|
32
|
+
},
|
|
33
|
+
focus,
|
|
34
|
+
removeLink: () => {
|
|
35
|
+
editor.send({
|
|
36
|
+
type: 'annotation.remove',
|
|
37
|
+
annotation: { name: PsPortableTextCoreConfig.linkAnnotation },
|
|
38
|
+
});
|
|
39
|
+
focus();
|
|
40
|
+
},
|
|
41
|
+
toggleDecorator: (decorator) => {
|
|
42
|
+
editor.send({ type: 'decorator.toggle', decorator });
|
|
43
|
+
focus();
|
|
44
|
+
},
|
|
45
|
+
toggleListItem: (listItem) => {
|
|
46
|
+
editor.send({ type: 'list item.toggle', listItem });
|
|
47
|
+
focus();
|
|
48
|
+
},
|
|
49
|
+
toggleQuote: () => {
|
|
50
|
+
editor.send({ type: 'style.toggle', style: PsPortableTextCoreConfig.styles.blockquote });
|
|
51
|
+
focus();
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export * from './components/ps-portable-text-core';
|
|
2
|
+
export * from './constants/ps-portable-text-core-config';
|
|
3
|
+
export * from './hooks/use-ps-portable-text-link-form';
|
|
4
|
+
export * from './hooks/use-ps-portable-text-toolbar';
|
|
5
|
+
export * from './interfaces/ps-portable-text-editor-labels';
|
|
6
|
+
export * from './services/ps-portable-text-editor-service';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/esm/{services → portable-text-core/services}/ps-portable-text-editor-service.js
RENAMED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { Common } from '@pallasoft/ps-models';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { PsTextFormatService } from '../../services/ps-text-format-service';
|
|
3
|
+
import { PsPortableTextCoreConfig } from '../constants/ps-portable-text-core-config';
|
|
4
4
|
export class PsPortableTextEditorService {
|
|
5
5
|
static normalizeLink(raw) {
|
|
6
6
|
const trimmed = raw.trim();
|
|
7
7
|
if (trimmed === '')
|
|
8
8
|
return null;
|
|
9
|
-
const candidate =
|
|
10
|
-
? `${
|
|
11
|
-
: trimmed.toLowerCase().startsWith(
|
|
9
|
+
const candidate = PsPortableTextCoreConfig.emailPattern.test(trimmed)
|
|
10
|
+
? `${PsPortableTextCoreConfig.mailtoPrefix}${trimmed}`
|
|
11
|
+
: trimmed.toLowerCase().startsWith(PsPortableTextCoreConfig.mailtoPrefix)
|
|
12
12
|
? trimmed
|
|
13
13
|
: PsTextFormatService.url(trimmed);
|
|
14
14
|
try {
|
|
@@ -22,7 +22,7 @@ export class PsPortableTextEditorService {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
static minHeight(minRows) {
|
|
25
|
-
return `${minRows *
|
|
25
|
+
return `${minRows * PsPortableTextCoreConfig.lineHeightRem}rem`;
|
|
26
26
|
}
|
|
27
27
|
static isSame(first, second) {
|
|
28
28
|
return JSON.stringify(first) === JSON.stringify(second);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface PsFormNameModalProps {
|
|
2
|
+
cancelLabel: string;
|
|
3
|
+
initialName: string;
|
|
4
|
+
isOpen: boolean;
|
|
5
|
+
isSubmitting?: boolean;
|
|
6
|
+
label: string;
|
|
7
|
+
maxLength?: number;
|
|
8
|
+
onClose: () => void;
|
|
9
|
+
onSave: (name: string) => void;
|
|
10
|
+
placeholder?: string;
|
|
11
|
+
requiredMessage: string;
|
|
12
|
+
submitLabel: string;
|
|
13
|
+
title: string;
|
|
14
|
+
}
|
|
15
|
+
export declare const PsFormNameModal: ({ cancelLabel, initialName, isOpen, isSubmitting, label, maxLength, onClose, onSave, placeholder, requiredMessage, submitLabel, title, }: PsFormNameModalProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsFormNameModal = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const ps_popovers_1 = require("@pallasoft/ps-popovers");
|
|
7
|
+
const react_hook_form_1 = require("react-hook-form");
|
|
8
|
+
const ps_form_text_field_1 = require("./ps-form-text-field");
|
|
9
|
+
const PsFormNameModal = ({ cancelLabel, initialName, isOpen, isSubmitting = false, label, maxLength = 80, onClose, onSave, placeholder, requiredMessage, submitLabel, title, }) => {
|
|
10
|
+
const { control, formState: { isDirty, isValid }, handleSubmit, reset, } = (0, react_hook_form_1.useForm)({ mode: 'onChange' });
|
|
11
|
+
(0, react_1.useEffect)(() => {
|
|
12
|
+
if (isOpen)
|
|
13
|
+
reset({ name: initialName });
|
|
14
|
+
}, [initialName, isOpen, reset]);
|
|
15
|
+
return ((0, jsx_runtime_1.jsx)(ps_popovers_1.PsFormModal, { cancelLabel: cancelLabel, isOpen: isOpen, isSubmitDisabled: !isValid || (initialName !== '' && !isDirty), isSubmitting: isSubmitting, onClose: onClose, onSubmit: handleSubmit((values) => onSave(values.name.trim())), size: 'sm', submitLabel: submitLabel, title: title, children: (0, jsx_runtime_1.jsx)(ps_form_text_field_1.PsFormTextField, { control: control, label: label, maxLength: maxLength, name: 'name', placeholder: placeholder, rules: {
|
|
16
|
+
required: requiredMessage,
|
|
17
|
+
validate: (value) => value.trim() !== '' || requiredMessage,
|
|
18
|
+
} }) }));
|
|
19
|
+
};
|
|
20
|
+
exports.PsFormNameModal = PsFormNameModal;
|
package/dist/form/index.d.ts
CHANGED
|
@@ -9,3 +9,5 @@ export * from './components/ps-form-year-field';
|
|
|
9
9
|
export * from './constants/ps-form-text-kind';
|
|
10
10
|
export * from './models/ps-form-field-rules';
|
|
11
11
|
export * from './services/ps-form-field-service';
|
|
12
|
+
export * from './components/ps-form-name-modal';
|
|
13
|
+
export * from './models/ps-form-name-data';
|
package/dist/form/index.js
CHANGED
|
@@ -25,3 +25,5 @@ __exportStar(require("./components/ps-form-year-field"), exports);
|
|
|
25
25
|
__exportStar(require("./constants/ps-form-text-kind"), exports);
|
|
26
26
|
__exportStar(require("./models/ps-form-field-rules"), exports);
|
|
27
27
|
__exportStar(require("./services/ps-form-field-service"), exports);
|
|
28
|
+
__exportStar(require("./components/ps-form-name-modal"), exports);
|
|
29
|
+
__exportStar(require("./models/ps-form-name-data"), exports);
|
package/dist/index.d.ts
CHANGED
|
@@ -46,5 +46,7 @@ export * from './components/ps-select-with-create';
|
|
|
46
46
|
export * from './constants/ps-select-with-create-config';
|
|
47
47
|
export * from './interfaces/ps-date-preset-data';
|
|
48
48
|
export * from './components/ps-portable-text-editor';
|
|
49
|
-
export * from './interfaces/ps-portable-text-editor-labels';
|
|
49
|
+
export * from './portable-text-core/interfaces/ps-portable-text-editor-labels';
|
|
50
50
|
export type { PortableTextBlock } from '@portabletext/editor';
|
|
51
|
+
export * from './components/ps-option-card-group';
|
|
52
|
+
export * from './interfaces/ps-option-card-data';
|
package/dist/index.js
CHANGED
|
@@ -62,4 +62,6 @@ __exportStar(require("./components/ps-select-with-create"), exports);
|
|
|
62
62
|
__exportStar(require("./constants/ps-select-with-create-config"), exports);
|
|
63
63
|
__exportStar(require("./interfaces/ps-date-preset-data"), exports);
|
|
64
64
|
__exportStar(require("./components/ps-portable-text-editor"), exports);
|
|
65
|
-
__exportStar(require("./interfaces/ps-portable-text-editor-labels"), exports);
|
|
65
|
+
__exportStar(require("./portable-text-core/interfaces/ps-portable-text-editor-labels"), exports);
|
|
66
|
+
__exportStar(require("./components/ps-option-card-group"), exports);
|
|
67
|
+
__exportStar(require("./interfaces/ps-option-card-data"), exports);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type PortableTextBlock, type RenderAnnotationFunction, type RenderBlockFunction, type RenderDecoratorFunction, type RenderPlaceholderFunction } from '@portabletext/editor';
|
|
3
|
+
export interface PsPortableTextCoreProps {
|
|
4
|
+
className?: string;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
editableClassName?: string;
|
|
7
|
+
fallback?: ReactNode;
|
|
8
|
+
minRows?: number;
|
|
9
|
+
onChange: (value: PortableTextBlock[]) => void;
|
|
10
|
+
renderAnnotation?: RenderAnnotationFunction;
|
|
11
|
+
renderBlock?: RenderBlockFunction;
|
|
12
|
+
renderDecorator?: RenderDecoratorFunction;
|
|
13
|
+
renderPlaceholder?: RenderPlaceholderFunction;
|
|
14
|
+
toolbar?: ReactNode;
|
|
15
|
+
value: PortableTextBlock[];
|
|
16
|
+
}
|
|
17
|
+
export declare const PsPortableTextCore: ({ className, disabled, editableClassName, fallback, minRows, onChange, renderAnnotation, renderBlock, renderDecorator, renderPlaceholder, toolbar, value, }: PsPortableTextCoreProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsPortableTextCore = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const editor_1 = require("@portabletext/editor");
|
|
7
|
+
const plugins_1 = require("@portabletext/editor/plugins");
|
|
8
|
+
const ps_portable_text_core_config_1 = require("../constants/ps-portable-text-core-config");
|
|
9
|
+
const ps_portable_text_editor_service_1 = require("../services/ps-portable-text-editor-service");
|
|
10
|
+
const PsPortableTextCore = ({ className, disabled = false, editableClassName, fallback, minRows = 4, onChange, renderAnnotation, renderBlock, renderDecorator, renderPlaceholder, toolbar, value, }) => {
|
|
11
|
+
const [isMounted, setIsMounted] = (0, react_1.useState)(false);
|
|
12
|
+
const [version, setVersion] = (0, react_1.useState)(0);
|
|
13
|
+
const lastValue = (0, react_1.useRef)(value);
|
|
14
|
+
(0, react_1.useEffect)(() => {
|
|
15
|
+
setIsMounted(true);
|
|
16
|
+
}, []);
|
|
17
|
+
(0, react_1.useEffect)(() => {
|
|
18
|
+
if (ps_portable_text_editor_service_1.PsPortableTextEditorService.isSame(value, lastValue.current))
|
|
19
|
+
return;
|
|
20
|
+
lastValue.current = value;
|
|
21
|
+
setVersion((current) => current + 1);
|
|
22
|
+
}, [value]);
|
|
23
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: className, children: isMounted ? ((0, jsx_runtime_1.jsxs)(editor_1.EditorProvider, { initialConfig: {
|
|
24
|
+
initialValue: value,
|
|
25
|
+
readOnly: disabled,
|
|
26
|
+
schemaDefinition: ps_portable_text_core_config_1.PsPortableTextCoreConfig.schemaDefinition,
|
|
27
|
+
}, children: [(0, jsx_runtime_1.jsx)(plugins_1.EventListenerPlugin, { on: (event) => {
|
|
28
|
+
if (event.type !== 'mutation')
|
|
29
|
+
return;
|
|
30
|
+
const next = Array.isArray(event.value) ? event.value : [];
|
|
31
|
+
lastValue.current = next;
|
|
32
|
+
onChange(next);
|
|
33
|
+
} }), toolbar, (0, jsx_runtime_1.jsx)(editor_1.PortableTextEditable, { className: editableClassName, readOnly: disabled, renderAnnotation: renderAnnotation, renderBlock: renderBlock, renderDecorator: renderDecorator, renderPlaceholder: renderPlaceholder, style: { minHeight: ps_portable_text_editor_service_1.PsPortableTextEditorService.minHeight(minRows) } })] }, version)) : (fallback) }));
|
|
34
|
+
};
|
|
35
|
+
exports.PsPortableTextCore = PsPortableTextCore;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export declare const PsPortableTextCoreConfig: {
|
|
2
|
+
readonly linkAnnotation: "link";
|
|
3
|
+
readonly mailtoPrefix: "mailto:";
|
|
4
|
+
readonly emailPattern: RegExp;
|
|
5
|
+
readonly lineHeightRem: 1.5;
|
|
6
|
+
readonly decorators: {
|
|
7
|
+
readonly bold: "strong";
|
|
8
|
+
readonly code: "code";
|
|
9
|
+
readonly italic: "em";
|
|
10
|
+
readonly underline: "underline";
|
|
11
|
+
};
|
|
12
|
+
readonly styles: {
|
|
13
|
+
readonly blockquote: "blockquote";
|
|
14
|
+
readonly normal: "normal";
|
|
15
|
+
};
|
|
16
|
+
readonly listItems: {
|
|
17
|
+
readonly bullet: "bullet";
|
|
18
|
+
readonly number: "number";
|
|
19
|
+
};
|
|
20
|
+
readonly schemaDefinition: {
|
|
21
|
+
readonly annotations: readonly [{
|
|
22
|
+
readonly name: "link";
|
|
23
|
+
readonly fields: readonly [{
|
|
24
|
+
readonly name: "href";
|
|
25
|
+
readonly type: "string";
|
|
26
|
+
}];
|
|
27
|
+
}];
|
|
28
|
+
readonly blockObjects: readonly [];
|
|
29
|
+
readonly decorators: {
|
|
30
|
+
name: "code" | "em" | "strong" | "underline";
|
|
31
|
+
}[];
|
|
32
|
+
readonly inlineObjects: readonly [];
|
|
33
|
+
readonly lists: {
|
|
34
|
+
name: "number" | "bullet";
|
|
35
|
+
}[];
|
|
36
|
+
readonly styles: {
|
|
37
|
+
name: "blockquote" | "normal";
|
|
38
|
+
}[];
|
|
39
|
+
};
|
|
40
|
+
readonly labels: {
|
|
41
|
+
bold: string;
|
|
42
|
+
bulletedList: string;
|
|
43
|
+
cancel: string;
|
|
44
|
+
code: string;
|
|
45
|
+
invalidLink: string;
|
|
46
|
+
italic: string;
|
|
47
|
+
link: string;
|
|
48
|
+
linkDialogTitle: string;
|
|
49
|
+
linkUrl: string;
|
|
50
|
+
numberedList: string;
|
|
51
|
+
quote: string;
|
|
52
|
+
removeLink: string;
|
|
53
|
+
saveLink: string;
|
|
54
|
+
toolbar: string;
|
|
55
|
+
underline: string;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsPortableTextCoreConfig = void 0;
|
|
4
|
+
const ps_models_1 = require("@pallasoft/ps-models");
|
|
5
|
+
const editor_1 = require("@portabletext/editor");
|
|
6
|
+
const Models = ps_models_1.Common.PortableTextConfig;
|
|
7
|
+
exports.PsPortableTextCoreConfig = {
|
|
8
|
+
linkAnnotation: Models.linkType,
|
|
9
|
+
mailtoPrefix: 'mailto:',
|
|
10
|
+
emailPattern: /^[^\s@/:]+@[^\s@/:]+\.[^\s@/:]+$/,
|
|
11
|
+
lineHeightRem: 1.5,
|
|
12
|
+
decorators: {
|
|
13
|
+
bold: Models.decorators[0],
|
|
14
|
+
code: Models.decorators[3],
|
|
15
|
+
italic: Models.decorators[1],
|
|
16
|
+
underline: Models.decorators[2],
|
|
17
|
+
},
|
|
18
|
+
styles: { blockquote: Models.styles[1], normal: Models.styles[0] },
|
|
19
|
+
listItems: { bullet: Models.listItems[0], number: Models.listItems[1] },
|
|
20
|
+
schemaDefinition: (0, editor_1.defineSchema)({
|
|
21
|
+
annotations: [{ name: Models.linkType, fields: [{ name: 'href', type: 'string' }] }],
|
|
22
|
+
blockObjects: [],
|
|
23
|
+
decorators: Models.decorators.map((name) => ({ name })),
|
|
24
|
+
inlineObjects: [],
|
|
25
|
+
lists: Models.listItems.map((name) => ({ name })),
|
|
26
|
+
styles: Models.styles.map((name) => ({ name })),
|
|
27
|
+
}),
|
|
28
|
+
labels: {
|
|
29
|
+
bold: 'Bold',
|
|
30
|
+
bulletedList: 'Bulleted list',
|
|
31
|
+
cancel: 'Cancel',
|
|
32
|
+
code: 'Code',
|
|
33
|
+
invalidLink: 'Enter a web address or email address',
|
|
34
|
+
italic: 'Italic',
|
|
35
|
+
link: 'Link',
|
|
36
|
+
linkDialogTitle: 'Link',
|
|
37
|
+
linkUrl: 'Address',
|
|
38
|
+
numberedList: 'Numbered list',
|
|
39
|
+
quote: 'Quote',
|
|
40
|
+
removeLink: 'Remove link',
|
|
41
|
+
saveLink: 'Save',
|
|
42
|
+
toolbar: 'Formatting',
|
|
43
|
+
underline: 'Underline',
|
|
44
|
+
},
|
|
45
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type FormEvent } from 'react';
|
|
2
|
+
export interface UsePsPortableTextLinkFormOptions {
|
|
3
|
+
onClose: () => void;
|
|
4
|
+
onSubmit: (href: string) => void;
|
|
5
|
+
}
|
|
6
|
+
export declare const usePsPortableTextLinkForm: ({ onClose, onSubmit, }: UsePsPortableTextLinkFormOptions) => {
|
|
7
|
+
address: string;
|
|
8
|
+
close: () => void;
|
|
9
|
+
hasError: boolean;
|
|
10
|
+
isSubmitDisabled: boolean;
|
|
11
|
+
setAddress: (next: string) => void;
|
|
12
|
+
submit: (event: FormEvent) => void;
|
|
13
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.usePsPortableTextLinkForm = void 0;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const ps_portable_text_editor_service_1 = require("../services/ps-portable-text-editor-service");
|
|
6
|
+
const usePsPortableTextLinkForm = ({ onClose, onSubmit, }) => {
|
|
7
|
+
const [address, setAddress] = (0, react_1.useState)('');
|
|
8
|
+
const [hasError, setHasError] = (0, react_1.useState)(false);
|
|
9
|
+
return {
|
|
10
|
+
address,
|
|
11
|
+
close: () => {
|
|
12
|
+
setAddress('');
|
|
13
|
+
setHasError(false);
|
|
14
|
+
onClose();
|
|
15
|
+
},
|
|
16
|
+
hasError,
|
|
17
|
+
isSubmitDisabled: address.trim() === '',
|
|
18
|
+
setAddress: (next) => {
|
|
19
|
+
setAddress(next);
|
|
20
|
+
setHasError(false);
|
|
21
|
+
},
|
|
22
|
+
submit: (event) => {
|
|
23
|
+
event.preventDefault();
|
|
24
|
+
event.stopPropagation();
|
|
25
|
+
const href = ps_portable_text_editor_service_1.PsPortableTextEditorService.normalizeLink(address);
|
|
26
|
+
if (href === null) {
|
|
27
|
+
setHasError(true);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
setAddress('');
|
|
31
|
+
setHasError(false);
|
|
32
|
+
onSubmit(href);
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
exports.usePsPortableTextLinkForm = usePsPortableTextLinkForm;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare const usePsPortableTextToolbar: () => {
|
|
2
|
+
active: {
|
|
3
|
+
bold: boolean;
|
|
4
|
+
bulletedList: boolean;
|
|
5
|
+
code: boolean;
|
|
6
|
+
italic: boolean;
|
|
7
|
+
link: boolean;
|
|
8
|
+
numberedList: boolean;
|
|
9
|
+
quote: boolean;
|
|
10
|
+
underline: boolean;
|
|
11
|
+
};
|
|
12
|
+
addLink: (href: string) => void;
|
|
13
|
+
focus: () => void;
|
|
14
|
+
removeLink: () => void;
|
|
15
|
+
toggleDecorator: (decorator: string) => void;
|
|
16
|
+
toggleListItem: (listItem: string) => void;
|
|
17
|
+
toggleQuote: () => void;
|
|
18
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.usePsPortableTextToolbar = void 0;
|
|
4
|
+
const editor_1 = require("@portabletext/editor");
|
|
5
|
+
const selectors_1 = require("@portabletext/editor/selectors");
|
|
6
|
+
const ps_portable_text_core_config_1 = require("../constants/ps-portable-text-core-config");
|
|
7
|
+
const usePsPortableTextToolbar = () => {
|
|
8
|
+
const editor = (0, editor_1.useEditor)();
|
|
9
|
+
const isBold = (0, editor_1.useEditorSelector)(editor, (0, selectors_1.isActiveDecorator)(ps_portable_text_core_config_1.PsPortableTextCoreConfig.decorators.bold));
|
|
10
|
+
const isItalic = (0, editor_1.useEditorSelector)(editor, (0, selectors_1.isActiveDecorator)(ps_portable_text_core_config_1.PsPortableTextCoreConfig.decorators.italic));
|
|
11
|
+
const isUnderline = (0, editor_1.useEditorSelector)(editor, (0, selectors_1.isActiveDecorator)(ps_portable_text_core_config_1.PsPortableTextCoreConfig.decorators.underline));
|
|
12
|
+
const isCode = (0, editor_1.useEditorSelector)(editor, (0, selectors_1.isActiveDecorator)(ps_portable_text_core_config_1.PsPortableTextCoreConfig.decorators.code));
|
|
13
|
+
const isBulletedList = (0, editor_1.useEditorSelector)(editor, (0, selectors_1.isActiveListItem)(ps_portable_text_core_config_1.PsPortableTextCoreConfig.listItems.bullet));
|
|
14
|
+
const isNumberedList = (0, editor_1.useEditorSelector)(editor, (0, selectors_1.isActiveListItem)(ps_portable_text_core_config_1.PsPortableTextCoreConfig.listItems.number));
|
|
15
|
+
const isQuote = (0, editor_1.useEditorSelector)(editor, (0, selectors_1.isActiveStyle)(ps_portable_text_core_config_1.PsPortableTextCoreConfig.styles.blockquote));
|
|
16
|
+
const isLink = (0, editor_1.useEditorSelector)(editor, (0, selectors_1.isActiveAnnotation)(ps_portable_text_core_config_1.PsPortableTextCoreConfig.linkAnnotation));
|
|
17
|
+
const focus = () => editor.send({ type: 'focus' });
|
|
18
|
+
return {
|
|
19
|
+
active: {
|
|
20
|
+
bold: isBold,
|
|
21
|
+
bulletedList: isBulletedList,
|
|
22
|
+
code: isCode,
|
|
23
|
+
italic: isItalic,
|
|
24
|
+
link: isLink,
|
|
25
|
+
numberedList: isNumberedList,
|
|
26
|
+
quote: isQuote,
|
|
27
|
+
underline: isUnderline,
|
|
28
|
+
},
|
|
29
|
+
addLink: (href) => {
|
|
30
|
+
editor.send({
|
|
31
|
+
type: 'annotation.add',
|
|
32
|
+
annotation: { name: ps_portable_text_core_config_1.PsPortableTextCoreConfig.linkAnnotation, value: { href } },
|
|
33
|
+
});
|
|
34
|
+
focus();
|
|
35
|
+
},
|
|
36
|
+
focus,
|
|
37
|
+
removeLink: () => {
|
|
38
|
+
editor.send({
|
|
39
|
+
type: 'annotation.remove',
|
|
40
|
+
annotation: { name: ps_portable_text_core_config_1.PsPortableTextCoreConfig.linkAnnotation },
|
|
41
|
+
});
|
|
42
|
+
focus();
|
|
43
|
+
},
|
|
44
|
+
toggleDecorator: (decorator) => {
|
|
45
|
+
editor.send({ type: 'decorator.toggle', decorator });
|
|
46
|
+
focus();
|
|
47
|
+
},
|
|
48
|
+
toggleListItem: (listItem) => {
|
|
49
|
+
editor.send({ type: 'list item.toggle', listItem });
|
|
50
|
+
focus();
|
|
51
|
+
},
|
|
52
|
+
toggleQuote: () => {
|
|
53
|
+
editor.send({ type: 'style.toggle', style: ps_portable_text_core_config_1.PsPortableTextCoreConfig.styles.blockquote });
|
|
54
|
+
focus();
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
exports.usePsPortableTextToolbar = usePsPortableTextToolbar;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from './components/ps-portable-text-core';
|
|
2
|
+
export * from './constants/ps-portable-text-core-config';
|
|
3
|
+
export * from './hooks/use-ps-portable-text-link-form';
|
|
4
|
+
export * from './hooks/use-ps-portable-text-toolbar';
|
|
5
|
+
export * from './interfaces/ps-portable-text-editor-labels';
|
|
6
|
+
export * from './services/ps-portable-text-editor-service';
|
|
7
|
+
export type { BlockAnnotationRenderProps, BlockDecoratorRenderProps, BlockRenderProps, PortableTextBlock, } from '@portabletext/editor';
|