@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,8 @@
|
|
|
1
|
+
import type { PsOptionCardData } from '../interfaces/ps-option-card-data';
|
|
2
|
+
export interface PsOptionCardGroupProps {
|
|
3
|
+
label: string;
|
|
4
|
+
onChange: (value: string) => void;
|
|
5
|
+
options: PsOptionCardData[];
|
|
6
|
+
value: string;
|
|
7
|
+
}
|
|
8
|
+
export declare const PsOptionCardGroup: ({ label, onChange, options, value }: PsOptionCardGroupProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsOptionCardGroup = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const ps_design_system_1 = require("@pallasoft/ps-design-system");
|
|
6
|
+
const PsOptionCardGroup = ({ label, onChange, options, value }) => ((0, jsx_runtime_1.jsx)("div", { "aria-label": label, className: 'grid gap-3 sm:grid-cols-2', role: 'radiogroup', children: options.map((option) => {
|
|
7
|
+
const isSelected = option.value === value;
|
|
8
|
+
return ((0, jsx_runtime_1.jsxs)("button", { "aria-checked": isSelected, className: ps_design_system_1.PallasoftClassNameService.merge('ps-focus-ring flex flex-col gap-1 rounded-ps-card border px-4 py-3 text-left transition-colors', isSelected
|
|
9
|
+
? 'border-primary bg-primary/5 ring-2 ring-primary/25'
|
|
10
|
+
: 'border-line hover:border-primary/40'), onClick: () => onChange(option.value), role: 'radio', type: 'button', children: [(0, jsx_runtime_1.jsx)("span", { className: 'text-sm font-semibold text-ink', children: option.label }), (0, jsx_runtime_1.jsx)("span", { className: 'text-xs text-ink/60', children: option.description })] }, option.value));
|
|
11
|
+
}) }));
|
|
12
|
+
exports.PsOptionCardGroup = PsOptionCardGroup;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { PsPortableTextEditorLabels } from '../interfaces/ps-portable-text-editor-labels';
|
|
1
|
+
import type { PortableTextBlock } from '@portabletext/editor';
|
|
2
|
+
import type { PsPortableTextEditorLabels } from '../portable-text-core/interfaces/ps-portable-text-editor-labels';
|
|
3
3
|
export interface PsPortableTextEditorProps {
|
|
4
4
|
className?: string;
|
|
5
5
|
disabled?: boolean;
|
|
@@ -2,37 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PsPortableTextEditor = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
-
const react_1 = require("react");
|
|
6
5
|
const ps_design_system_1 = require("@pallasoft/ps-design-system");
|
|
7
|
-
const editor_1 = require("@portabletext/editor");
|
|
8
|
-
const plugins_1 = require("@portabletext/editor/plugins");
|
|
9
6
|
const ps_portable_text_editor_config_1 = require("../constants/ps-portable-text-editor-config");
|
|
10
7
|
const ps_portable_text_editor_renderers_1 = require("../constants/ps-portable-text-editor-renderers");
|
|
11
|
-
const
|
|
8
|
+
const ps_portable_text_core_1 = require("../portable-text-core/components/ps-portable-text-core");
|
|
9
|
+
const ps_portable_text_core_config_1 = require("../portable-text-core/constants/ps-portable-text-core-config");
|
|
10
|
+
const ps_portable_text_editor_service_1 = require("../portable-text-core/services/ps-portable-text-editor-service");
|
|
12
11
|
const ps_portable_text_toolbar_1 = require("./ps-portable-text-toolbar");
|
|
13
|
-
const PsPortableTextEditor = ({ className, disabled = false, labels =
|
|
14
|
-
const [isMounted, setIsMounted] = (0, react_1.useState)(false);
|
|
15
|
-
const [version, setVersion] = (0, react_1.useState)(0);
|
|
16
|
-
const lastValue = (0, react_1.useRef)(value);
|
|
17
|
-
(0, react_1.useEffect)(() => {
|
|
18
|
-
setIsMounted(true);
|
|
19
|
-
}, []);
|
|
20
|
-
(0, react_1.useEffect)(() => {
|
|
21
|
-
if (ps_portable_text_editor_service_1.PsPortableTextEditorService.isSame(value, lastValue.current))
|
|
22
|
-
return;
|
|
23
|
-
lastValue.current = value;
|
|
24
|
-
setVersion((current) => current + 1);
|
|
25
|
-
}, [value]);
|
|
26
|
-
return ((0, jsx_runtime_1.jsx)("div", { className: ps_design_system_1.PallasoftClassNameService.merge(ps_portable_text_editor_config_1.PsPortableTextEditorConfig.classNames.root, className), children: isMounted ? ((0, jsx_runtime_1.jsxs)(editor_1.EditorProvider, { initialConfig: {
|
|
27
|
-
initialValue: value,
|
|
28
|
-
readOnly: disabled,
|
|
29
|
-
schemaDefinition: ps_portable_text_editor_config_1.PsPortableTextEditorConfig.schemaDefinition,
|
|
30
|
-
}, children: [(0, jsx_runtime_1.jsx)(plugins_1.EventListenerPlugin, { on: (event) => {
|
|
31
|
-
if (event.type !== 'mutation')
|
|
32
|
-
return;
|
|
33
|
-
const next = Array.isArray(event.value) ? event.value : [];
|
|
34
|
-
lastValue.current = next;
|
|
35
|
-
onChange(next);
|
|
36
|
-
} }), (0, jsx_runtime_1.jsx)(ps_portable_text_toolbar_1.PsPortableTextToolbar, { disabled: disabled, labels: labels }), (0, jsx_runtime_1.jsx)(editor_1.PortableTextEditable, { ...ps_portable_text_editor_renderers_1.PsPortableTextEditorRenderers, className: ps_portable_text_editor_config_1.PsPortableTextEditorConfig.classNames.editable, readOnly: disabled, renderPlaceholder: () => (0, jsx_runtime_1.jsx)("span", { className: 'text-ink/45', children: placeholder }), style: { minHeight: ps_portable_text_editor_service_1.PsPortableTextEditorService.minHeight(minRows) } })] }, version)) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { "aria-hidden": 'true', className: ps_portable_text_editor_config_1.PsPortableTextEditorConfig.classNames.toolbar, children: (0, jsx_runtime_1.jsx)("span", { className: 'h-9' }) }), (0, jsx_runtime_1.jsx)("div", { "aria-hidden": 'true', className: ps_portable_text_editor_config_1.PsPortableTextEditorConfig.classNames.editable, style: { minHeight: ps_portable_text_editor_service_1.PsPortableTextEditorService.minHeight(minRows) } })] })) }));
|
|
37
|
-
};
|
|
12
|
+
const PsPortableTextEditor = ({ className, disabled = false, labels = ps_portable_text_core_config_1.PsPortableTextCoreConfig.labels, minRows = 4, onChange, placeholder, value, }) => ((0, jsx_runtime_1.jsx)(ps_portable_text_core_1.PsPortableTextCore, { ...ps_portable_text_editor_renderers_1.PsPortableTextEditorRenderers, className: ps_design_system_1.PallasoftClassNameService.merge(ps_portable_text_editor_config_1.PsPortableTextEditorConfig.classNames.root, className), disabled: disabled, editableClassName: ps_portable_text_editor_config_1.PsPortableTextEditorConfig.classNames.editable, fallback: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { "aria-hidden": 'true', className: ps_portable_text_editor_config_1.PsPortableTextEditorConfig.classNames.toolbar, children: (0, jsx_runtime_1.jsx)("span", { className: 'h-9' }) }), (0, jsx_runtime_1.jsx)("div", { "aria-hidden": 'true', className: ps_portable_text_editor_config_1.PsPortableTextEditorConfig.classNames.editable, style: { minHeight: ps_portable_text_editor_service_1.PsPortableTextEditorService.minHeight(minRows) } })] }), minRows: minRows, onChange: onChange, renderPlaceholder: () => (0, jsx_runtime_1.jsx)("span", { className: 'text-ink/45', children: placeholder }), toolbar: (0, jsx_runtime_1.jsx)(ps_portable_text_toolbar_1.PsPortableTextToolbar, { disabled: disabled, labels: labels }), value: value }));
|
|
38
13
|
exports.PsPortableTextEditor = PsPortableTextEditor;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PsPortableTextEditorLabels } from '../interfaces/ps-portable-text-editor-labels';
|
|
1
|
+
import type { PsPortableTextEditorLabels } from '../portable-text-core/interfaces/ps-portable-text-editor-labels';
|
|
2
2
|
export interface PsPortableTextLinkDialogProps {
|
|
3
3
|
isOpen: boolean;
|
|
4
4
|
labels: PsPortableTextEditorLabels;
|
|
@@ -2,34 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PsPortableTextLinkDialog = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
-
const react_1 = require("react");
|
|
6
5
|
const ps_popovers_1 = require("@pallasoft/ps-popovers");
|
|
7
|
-
const
|
|
8
|
-
const
|
|
6
|
+
const ps_portable_text_core_config_1 = require("../portable-text-core/constants/ps-portable-text-core-config");
|
|
7
|
+
const use_ps_portable_text_link_form_1 = require("../portable-text-core/hooks/use-ps-portable-text-link-form");
|
|
9
8
|
const ps_url_input_1 = require("./ps-url-input");
|
|
10
9
|
const PsPortableTextLinkDialog = ({ isOpen, labels, onClose, onSubmit, }) => {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
const close = () => {
|
|
14
|
-
setAddress('');
|
|
15
|
-
setHasError(false);
|
|
16
|
-
onClose();
|
|
17
|
-
};
|
|
18
|
-
const submit = (event) => {
|
|
19
|
-
event.preventDefault();
|
|
20
|
-
event.stopPropagation();
|
|
21
|
-
const href = ps_portable_text_editor_service_1.PsPortableTextEditorService.normalizeLink(address);
|
|
22
|
-
if (href === null) {
|
|
23
|
-
setHasError(true);
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
setAddress('');
|
|
27
|
-
setHasError(false);
|
|
28
|
-
onSubmit(href);
|
|
29
|
-
};
|
|
30
|
-
return ((0, jsx_runtime_1.jsx)(ps_popovers_1.PsFormModal, { cancelLabel: labels.cancel, isOpen: isOpen, isSubmitDisabled: address.trim() === '', onClose: close, onSubmit: submit, size: 'sm', submitLabel: labels.saveLink, title: labels.linkDialogTitle, children: (0, jsx_runtime_1.jsx)(ps_url_input_1.PsUrlInput, { "aria-invalid": hasError, autoFocus: true, helperText: hasError ? labels.invalidLink : undefined, label: labels.linkUrl, name: ps_portable_text_editor_config_1.PsPortableTextEditorConfig.linkAnnotation, onChange: (event) => {
|
|
31
|
-
setAddress(event.target.value);
|
|
32
|
-
setHasError(false);
|
|
33
|
-
}, value: address }) }));
|
|
10
|
+
const form = (0, use_ps_portable_text_link_form_1.usePsPortableTextLinkForm)({ onClose, onSubmit });
|
|
11
|
+
return ((0, jsx_runtime_1.jsx)(ps_popovers_1.PsFormModal, { cancelLabel: labels.cancel, isOpen: isOpen, isSubmitDisabled: form.isSubmitDisabled, onClose: form.close, onSubmit: form.submit, size: 'sm', submitLabel: labels.saveLink, title: labels.linkDialogTitle, children: (0, jsx_runtime_1.jsx)(ps_url_input_1.PsUrlInput, { "aria-invalid": form.hasError, autoFocus: true, helperText: form.hasError ? labels.invalidLink : undefined, label: labels.linkUrl, name: ps_portable_text_core_config_1.PsPortableTextCoreConfig.linkAnnotation, onChange: (event) => form.setAddress(event.target.value), value: form.address }) }));
|
|
34
12
|
};
|
|
35
13
|
exports.PsPortableTextLinkDialog = PsPortableTextLinkDialog;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PsPortableTextEditorLabels } from '../interfaces/ps-portable-text-editor-labels';
|
|
1
|
+
import type { PsPortableTextEditorLabels } from '../portable-text-core/interfaces/ps-portable-text-editor-labels';
|
|
2
2
|
export interface PsPortableTextToolbarProps {
|
|
3
3
|
disabled: boolean;
|
|
4
4
|
labels: PsPortableTextEditorLabels;
|
|
@@ -3,60 +3,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.PsPortableTextToolbar = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const react_1 = require("react");
|
|
6
|
-
const editor_1 = require("@portabletext/editor");
|
|
7
|
-
const selectors_1 = require("@portabletext/editor/selectors");
|
|
8
6
|
const ps_portable_text_editor_config_1 = require("../constants/ps-portable-text-editor-config");
|
|
7
|
+
const ps_portable_text_core_config_1 = require("../portable-text-core/constants/ps-portable-text-core-config");
|
|
8
|
+
const use_ps_portable_text_toolbar_1 = require("../portable-text-core/hooks/use-ps-portable-text-toolbar");
|
|
9
9
|
const ps_portable_text_link_dialog_1 = require("./ps-portable-text-link-dialog");
|
|
10
10
|
const ps_portable_text_toolbar_button_1 = require("./ps-portable-text-toolbar-button");
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
return ((0, jsx_runtime_1.jsx)(ps_portable_text_toolbar_button_1.PsPortableTextToolbarButton, { className: className, disabled: disabled, isActive: isActive, label: label, onClick: () => {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
const PsPortableTextToolbar = ({ disabled, labels }) => {
|
|
12
|
+
const toolbar = (0, use_ps_portable_text_toolbar_1.usePsPortableTextToolbar)();
|
|
13
|
+
const [isLinkOpen, setIsLinkOpen] = (0, react_1.useState)(false);
|
|
14
|
+
return ((0, jsx_runtime_1.jsxs)("div", { "aria-label": labels.toolbar, className: ps_portable_text_editor_config_1.PsPortableTextEditorConfig.classNames.toolbar, role: 'toolbar', children: [(0, jsx_runtime_1.jsx)(ps_portable_text_toolbar_button_1.PsPortableTextToolbarButton, { className: 'font-bold', disabled: disabled, isActive: toolbar.active.bold, label: labels.bold, onClick: () => toolbar.toggleDecorator(ps_portable_text_core_config_1.PsPortableTextCoreConfig.decorators.bold), children: "B" }), (0, jsx_runtime_1.jsx)(ps_portable_text_toolbar_button_1.PsPortableTextToolbarButton, { className: 'italic', disabled: disabled, isActive: toolbar.active.italic, label: labels.italic, onClick: () => toolbar.toggleDecorator(ps_portable_text_core_config_1.PsPortableTextCoreConfig.decorators.italic), children: "I" }), (0, jsx_runtime_1.jsx)(ps_portable_text_toolbar_button_1.PsPortableTextToolbarButton, { className: 'underline', disabled: disabled, isActive: toolbar.active.underline, label: labels.underline, onClick: () => toolbar.toggleDecorator(ps_portable_text_core_config_1.PsPortableTextCoreConfig.decorators.underline), children: "U" }), (0, jsx_runtime_1.jsx)(ps_portable_text_toolbar_button_1.PsPortableTextToolbarButton, { className: 'font-mono', disabled: disabled, isActive: toolbar.active.code, label: labels.code, onClick: () => toolbar.toggleDecorator(ps_portable_text_core_config_1.PsPortableTextCoreConfig.decorators.code), children: '</>' }), (0, jsx_runtime_1.jsx)(ps_portable_text_toolbar_button_1.PsPortableTextToolbarButton, { disabled: disabled, isActive: toolbar.active.link, label: toolbar.active.link ? labels.removeLink : labels.link, onClick: () => (toolbar.active.link ? toolbar.removeLink() : setIsLinkOpen(true)), children: (0, jsx_runtime_1.jsx)("span", { className: 'underline', children: labels.link }) }), (0, jsx_runtime_1.jsx)(ps_portable_text_link_dialog_1.PsPortableTextLinkDialog, { isOpen: isLinkOpen, labels: labels, onClose: () => {
|
|
15
|
+
setIsLinkOpen(false);
|
|
16
|
+
toolbar.focus();
|
|
17
|
+
}, onSubmit: (href) => {
|
|
18
|
+
toolbar.addLink(href);
|
|
19
|
+
setIsLinkOpen(false);
|
|
20
|
+
} }), (0, jsx_runtime_1.jsx)("span", { "aria-hidden": 'true', className: ps_portable_text_editor_config_1.PsPortableTextEditorConfig.classNames.separator }), (0, jsx_runtime_1.jsx)(ps_portable_text_toolbar_button_1.PsPortableTextToolbarButton, { disabled: disabled, isActive: toolbar.active.bulletedList, label: labels.bulletedList, onClick: () => toolbar.toggleListItem(ps_portable_text_core_config_1.PsPortableTextCoreConfig.listItems.bullet), children: "\u2022" }), (0, jsx_runtime_1.jsx)(ps_portable_text_toolbar_button_1.PsPortableTextToolbarButton, { disabled: disabled, isActive: toolbar.active.numberedList, label: labels.numberedList, onClick: () => toolbar.toggleListItem(ps_portable_text_core_config_1.PsPortableTextCoreConfig.listItems.number), children: "1." }), (0, jsx_runtime_1.jsx)(ps_portable_text_toolbar_button_1.PsPortableTextToolbarButton, { disabled: disabled, isActive: toolbar.active.quote, label: labels.quote, onClick: toolbar.toggleQuote, children: "\u201D" })] }));
|
|
18
21
|
};
|
|
19
|
-
const ListButton = ({ children, disabled, label, listItem, }) => {
|
|
20
|
-
const editor = (0, editor_1.useEditor)();
|
|
21
|
-
const isActive = (0, editor_1.useEditorSelector)(editor, (0, selectors_1.isActiveListItem)(listItem));
|
|
22
|
-
return ((0, jsx_runtime_1.jsx)(ps_portable_text_toolbar_button_1.PsPortableTextToolbarButton, { disabled: disabled, isActive: isActive, label: label, onClick: () => {
|
|
23
|
-
editor.send({ type: 'list item.toggle', listItem });
|
|
24
|
-
editor.send({ type: 'focus' });
|
|
25
|
-
}, children: children }));
|
|
26
|
-
};
|
|
27
|
-
const QuoteButton = ({ children, disabled, label }) => {
|
|
28
|
-
const editor = (0, editor_1.useEditor)();
|
|
29
|
-
const isActive = (0, editor_1.useEditorSelector)(editor, (0, selectors_1.isActiveStyle)(ps_portable_text_editor_config_1.PsPortableTextEditorConfig.styles.blockquote));
|
|
30
|
-
return ((0, jsx_runtime_1.jsx)(ps_portable_text_toolbar_button_1.PsPortableTextToolbarButton, { disabled: disabled, isActive: isActive, label: label, onClick: () => {
|
|
31
|
-
editor.send({ type: 'style.toggle', style: ps_portable_text_editor_config_1.PsPortableTextEditorConfig.styles.blockquote });
|
|
32
|
-
editor.send({ type: 'focus' });
|
|
33
|
-
}, children: children }));
|
|
34
|
-
};
|
|
35
|
-
const LinkButton = ({ disabled, labels }) => {
|
|
36
|
-
const editor = (0, editor_1.useEditor)();
|
|
37
|
-
const [isOpen, setIsOpen] = (0, react_1.useState)(false);
|
|
38
|
-
const isActive = (0, editor_1.useEditorSelector)(editor, (0, selectors_1.isActiveAnnotation)(ps_portable_text_editor_config_1.PsPortableTextEditorConfig.linkAnnotation));
|
|
39
|
-
const close = () => {
|
|
40
|
-
setIsOpen(false);
|
|
41
|
-
editor.send({ type: 'focus' });
|
|
42
|
-
};
|
|
43
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ps_portable_text_toolbar_button_1.PsPortableTextToolbarButton, { disabled: disabled, isActive: isActive, label: isActive ? labels.removeLink : labels.link, onClick: () => {
|
|
44
|
-
if (isActive) {
|
|
45
|
-
editor.send({
|
|
46
|
-
type: 'annotation.remove',
|
|
47
|
-
annotation: { name: ps_portable_text_editor_config_1.PsPortableTextEditorConfig.linkAnnotation },
|
|
48
|
-
});
|
|
49
|
-
editor.send({ type: 'focus' });
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
setIsOpen(true);
|
|
53
|
-
}, children: (0, jsx_runtime_1.jsx)("span", { className: 'underline', children: labels.link }) }), (0, jsx_runtime_1.jsx)(ps_portable_text_link_dialog_1.PsPortableTextLinkDialog, { isOpen: isOpen, labels: labels, onClose: close, onSubmit: (href) => {
|
|
54
|
-
editor.send({
|
|
55
|
-
type: 'annotation.add',
|
|
56
|
-
annotation: { name: ps_portable_text_editor_config_1.PsPortableTextEditorConfig.linkAnnotation, value: { href } },
|
|
57
|
-
});
|
|
58
|
-
close();
|
|
59
|
-
} })] }));
|
|
60
|
-
};
|
|
61
|
-
const PsPortableTextToolbar = ({ disabled, labels }) => ((0, jsx_runtime_1.jsxs)("div", { "aria-label": labels.toolbar, className: ps_portable_text_editor_config_1.PsPortableTextEditorConfig.classNames.toolbar, role: 'toolbar', children: [(0, jsx_runtime_1.jsx)(DecoratorButton, { className: 'font-bold', decorator: ps_portable_text_editor_config_1.PsPortableTextEditorConfig.decorators.bold, disabled: disabled, label: labels.bold, children: "B" }), (0, jsx_runtime_1.jsx)(DecoratorButton, { className: 'italic', decorator: ps_portable_text_editor_config_1.PsPortableTextEditorConfig.decorators.italic, disabled: disabled, label: labels.italic, children: "I" }), (0, jsx_runtime_1.jsx)(DecoratorButton, { className: 'underline', decorator: ps_portable_text_editor_config_1.PsPortableTextEditorConfig.decorators.underline, disabled: disabled, label: labels.underline, children: "U" }), (0, jsx_runtime_1.jsx)(DecoratorButton, { className: 'font-mono', decorator: ps_portable_text_editor_config_1.PsPortableTextEditorConfig.decorators.code, disabled: disabled, label: labels.code, children: '</>' }), (0, jsx_runtime_1.jsx)(LinkButton, { disabled: disabled, labels: labels }), (0, jsx_runtime_1.jsx)("span", { "aria-hidden": 'true', className: ps_portable_text_editor_config_1.PsPortableTextEditorConfig.classNames.separator }), (0, jsx_runtime_1.jsx)(ListButton, { disabled: disabled, label: labels.bulletedList, listItem: ps_portable_text_editor_config_1.PsPortableTextEditorConfig.listItems.bullet, children: "\u2022" }), (0, jsx_runtime_1.jsx)(ListButton, { disabled: disabled, label: labels.numberedList, listItem: ps_portable_text_editor_config_1.PsPortableTextEditorConfig.listItems.number, children: "1." }), (0, jsx_runtime_1.jsx)(QuoteButton, { disabled: disabled, label: labels.quote, children: "\u201D" })] }));
|
|
62
22
|
exports.PsPortableTextToolbar = PsPortableTextToolbar;
|
|
@@ -1,59 +1,4 @@
|
|
|
1
1
|
export declare const PsPortableTextEditorConfig: {
|
|
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
2
|
readonly classNames: {
|
|
58
3
|
readonly editable: "ps-input-control w-full resize-none overflow-y-auto rounded-t-none border-t-0 leading-6 outline-none";
|
|
59
4
|
readonly root: "block";
|
|
@@ -1,47 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PsPortableTextEditorConfig = 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
4
|
exports.PsPortableTextEditorConfig = {
|
|
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
5
|
classNames: {
|
|
46
6
|
editable: 'ps-input-control w-full resize-none overflow-y-auto rounded-t-none border-t-0 leading-6 outline-none',
|
|
47
7
|
root: 'block',
|
|
@@ -2,28 +2,28 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PsPortableTextEditorRenderers = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
-
const
|
|
5
|
+
const ps_portable_text_core_config_1 = require("../portable-text-core/constants/ps-portable-text-core-config");
|
|
6
6
|
exports.PsPortableTextEditorRenderers = {
|
|
7
7
|
renderBlock: ({ children, listItem, style }) => {
|
|
8
|
-
if (listItem ===
|
|
8
|
+
if (listItem === ps_portable_text_core_config_1.PsPortableTextCoreConfig.listItems.bullet) {
|
|
9
9
|
return ((0, jsx_runtime_1.jsx)("div", { className: "relative pl-6 before:absolute before:left-1 before:content-['\u2022']", children: children }));
|
|
10
10
|
}
|
|
11
|
-
if (listItem ===
|
|
11
|
+
if (listItem === ps_portable_text_core_config_1.PsPortableTextCoreConfig.listItems.number) {
|
|
12
12
|
return ((0, jsx_runtime_1.jsx)("div", { className: "relative pl-6 before:absolute before:left-0 before:content-[counter(ps-list)'.']", style: { counterIncrement: 'ps-list' }, children: children }));
|
|
13
13
|
}
|
|
14
|
-
if (style ===
|
|
14
|
+
if (style === ps_portable_text_core_config_1.PsPortableTextCoreConfig.styles.blockquote) {
|
|
15
15
|
return ((0, jsx_runtime_1.jsx)("div", { className: 'border-l-2 border-primary pl-3 text-ink/80', style: { counterReset: 'ps-list' }, children: children }));
|
|
16
16
|
}
|
|
17
17
|
return (0, jsx_runtime_1.jsx)("div", { style: { counterReset: 'ps-list' }, children: children });
|
|
18
18
|
},
|
|
19
19
|
renderDecorator: ({ children, value }) => {
|
|
20
|
-
if (value ===
|
|
20
|
+
if (value === ps_portable_text_core_config_1.PsPortableTextCoreConfig.decorators.bold)
|
|
21
21
|
return (0, jsx_runtime_1.jsx)("strong", { children: children });
|
|
22
|
-
if (value ===
|
|
22
|
+
if (value === ps_portable_text_core_config_1.PsPortableTextCoreConfig.decorators.italic)
|
|
23
23
|
return (0, jsx_runtime_1.jsx)("em", { children: children });
|
|
24
|
-
if (value ===
|
|
24
|
+
if (value === ps_portable_text_core_config_1.PsPortableTextCoreConfig.decorators.underline)
|
|
25
25
|
return (0, jsx_runtime_1.jsx)("u", { children: children });
|
|
26
|
-
if (value ===
|
|
26
|
+
if (value === ps_portable_text_core_config_1.PsPortableTextCoreConfig.decorators.code) {
|
|
27
27
|
return (0, jsx_runtime_1.jsx)("code", { className: 'rounded bg-ink/10 px-1 font-mono text-[0.9em]', children: children });
|
|
28
28
|
}
|
|
29
29
|
return children;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
3
|
+
export const PsOptionCardGroup = ({ label, onChange, options, value }) => (_jsx("div", { "aria-label": label, className: 'grid gap-3 sm:grid-cols-2', role: 'radiogroup', children: options.map((option) => {
|
|
4
|
+
const isSelected = option.value === value;
|
|
5
|
+
return (_jsxs("button", { "aria-checked": isSelected, className: PallasoftClassNameService.merge('ps-focus-ring flex flex-col gap-1 rounded-ps-card border px-4 py-3 text-left transition-colors', isSelected
|
|
6
|
+
? 'border-primary bg-primary/5 ring-2 ring-primary/25'
|
|
7
|
+
: 'border-line hover:border-primary/40'), onClick: () => onChange(option.value), role: 'radio', type: 'button', children: [_jsx("span", { className: 'text-sm font-semibold text-ink', children: option.label }), _jsx("span", { className: 'text-xs text-ink/60', children: option.description })] }, option.value));
|
|
8
|
+
}) }));
|
|
@@ -1,34 +1,9 @@
|
|
|
1
|
-
import { jsx as _jsx,
|
|
2
|
-
import { useEffect, useRef, useState } from 'react';
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
2
|
import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
4
|
-
import { EditorProvider, PortableTextEditable } from '@portabletext/editor';
|
|
5
|
-
import { EventListenerPlugin } from '@portabletext/editor/plugins';
|
|
6
3
|
import { PsPortableTextEditorConfig } from '../constants/ps-portable-text-editor-config';
|
|
7
4
|
import { PsPortableTextEditorRenderers } from '../constants/ps-portable-text-editor-renderers';
|
|
8
|
-
import {
|
|
5
|
+
import { PsPortableTextCore } from '../portable-text-core/components/ps-portable-text-core';
|
|
6
|
+
import { PsPortableTextCoreConfig } from '../portable-text-core/constants/ps-portable-text-core-config';
|
|
7
|
+
import { PsPortableTextEditorService } from '../portable-text-core/services/ps-portable-text-editor-service';
|
|
9
8
|
import { PsPortableTextToolbar } from './ps-portable-text-toolbar';
|
|
10
|
-
export const PsPortableTextEditor = ({ className, disabled = false, labels =
|
|
11
|
-
const [isMounted, setIsMounted] = useState(false);
|
|
12
|
-
const [version, setVersion] = useState(0);
|
|
13
|
-
const lastValue = useRef(value);
|
|
14
|
-
useEffect(() => {
|
|
15
|
-
setIsMounted(true);
|
|
16
|
-
}, []);
|
|
17
|
-
useEffect(() => {
|
|
18
|
-
if (PsPortableTextEditorService.isSame(value, lastValue.current))
|
|
19
|
-
return;
|
|
20
|
-
lastValue.current = value;
|
|
21
|
-
setVersion((current) => current + 1);
|
|
22
|
-
}, [value]);
|
|
23
|
-
return (_jsx("div", { className: PallasoftClassNameService.merge(PsPortableTextEditorConfig.classNames.root, className), children: isMounted ? (_jsxs(EditorProvider, { initialConfig: {
|
|
24
|
-
initialValue: value,
|
|
25
|
-
readOnly: disabled,
|
|
26
|
-
schemaDefinition: PsPortableTextEditorConfig.schemaDefinition,
|
|
27
|
-
}, children: [_jsx(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
|
-
} }), _jsx(PsPortableTextToolbar, { disabled: disabled, labels: labels }), _jsx(PortableTextEditable, { ...PsPortableTextEditorRenderers, className: PsPortableTextEditorConfig.classNames.editable, readOnly: disabled, renderPlaceholder: () => _jsx("span", { className: 'text-ink/45', children: placeholder }), style: { minHeight: PsPortableTextEditorService.minHeight(minRows) } })] }, version)) : (_jsxs(_Fragment, { children: [_jsx("div", { "aria-hidden": 'true', className: PsPortableTextEditorConfig.classNames.toolbar, children: _jsx("span", { className: 'h-9' }) }), _jsx("div", { "aria-hidden": 'true', className: PsPortableTextEditorConfig.classNames.editable, style: { minHeight: PsPortableTextEditorService.minHeight(minRows) } })] })) }));
|
|
34
|
-
};
|
|
9
|
+
export const PsPortableTextEditor = ({ className, disabled = false, labels = PsPortableTextCoreConfig.labels, minRows = 4, onChange, placeholder, value, }) => (_jsx(PsPortableTextCore, { ...PsPortableTextEditorRenderers, className: PallasoftClassNameService.merge(PsPortableTextEditorConfig.classNames.root, className), disabled: disabled, editableClassName: PsPortableTextEditorConfig.classNames.editable, fallback: _jsxs(_Fragment, { children: [_jsx("div", { "aria-hidden": 'true', className: PsPortableTextEditorConfig.classNames.toolbar, children: _jsx("span", { className: 'h-9' }) }), _jsx("div", { "aria-hidden": 'true', className: PsPortableTextEditorConfig.classNames.editable, style: { minHeight: PsPortableTextEditorService.minHeight(minRows) } })] }), minRows: minRows, onChange: onChange, renderPlaceholder: () => _jsx("span", { className: 'text-ink/45', children: placeholder }), toolbar: _jsx(PsPortableTextToolbar, { disabled: disabled, labels: labels }), value: value }));
|
|
@@ -1,31 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from 'react';
|
|
3
2
|
import { PsFormModal } from '@pallasoft/ps-popovers';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { PsPortableTextCoreConfig } from '../portable-text-core/constants/ps-portable-text-core-config';
|
|
4
|
+
import { usePsPortableTextLinkForm } from '../portable-text-core/hooks/use-ps-portable-text-link-form';
|
|
6
5
|
import { PsUrlInput } from './ps-url-input';
|
|
7
6
|
export const PsPortableTextLinkDialog = ({ isOpen, labels, onClose, onSubmit, }) => {
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
const close = () => {
|
|
11
|
-
setAddress('');
|
|
12
|
-
setHasError(false);
|
|
13
|
-
onClose();
|
|
14
|
-
};
|
|
15
|
-
const submit = (event) => {
|
|
16
|
-
event.preventDefault();
|
|
17
|
-
event.stopPropagation();
|
|
18
|
-
const href = PsPortableTextEditorService.normalizeLink(address);
|
|
19
|
-
if (href === null) {
|
|
20
|
-
setHasError(true);
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
setAddress('');
|
|
24
|
-
setHasError(false);
|
|
25
|
-
onSubmit(href);
|
|
26
|
-
};
|
|
27
|
-
return (_jsx(PsFormModal, { cancelLabel: labels.cancel, isOpen: isOpen, isSubmitDisabled: address.trim() === '', onClose: close, onSubmit: submit, size: 'sm', submitLabel: labels.saveLink, title: labels.linkDialogTitle, children: _jsx(PsUrlInput, { "aria-invalid": hasError, autoFocus: true, helperText: hasError ? labels.invalidLink : undefined, label: labels.linkUrl, name: PsPortableTextEditorConfig.linkAnnotation, onChange: (event) => {
|
|
28
|
-
setAddress(event.target.value);
|
|
29
|
-
setHasError(false);
|
|
30
|
-
}, value: address }) }));
|
|
7
|
+
const form = usePsPortableTextLinkForm({ onClose, onSubmit });
|
|
8
|
+
return (_jsx(PsFormModal, { cancelLabel: labels.cancel, isOpen: isOpen, isSubmitDisabled: form.isSubmitDisabled, onClose: form.close, onSubmit: form.submit, size: 'sm', submitLabel: labels.saveLink, title: labels.linkDialogTitle, children: _jsx(PsUrlInput, { "aria-invalid": form.hasError, autoFocus: true, helperText: form.hasError ? labels.invalidLink : undefined, label: labels.linkUrl, name: PsPortableTextCoreConfig.linkAnnotation, onChange: (event) => form.setAddress(event.target.value), value: form.address }) }));
|
|
31
9
|
};
|
|
@@ -1,58 +1,18 @@
|
|
|
1
|
-
import { jsx as _jsx,
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState } from 'react';
|
|
3
|
-
import { useEditor, useEditorSelector } from '@portabletext/editor';
|
|
4
|
-
import { isActiveAnnotation, isActiveDecorator, isActiveListItem, isActiveStyle, } from '@portabletext/editor/selectors';
|
|
5
3
|
import { PsPortableTextEditorConfig } from '../constants/ps-portable-text-editor-config';
|
|
4
|
+
import { PsPortableTextCoreConfig } from '../portable-text-core/constants/ps-portable-text-core-config';
|
|
5
|
+
import { usePsPortableTextToolbar } from '../portable-text-core/hooks/use-ps-portable-text-toolbar';
|
|
6
6
|
import { PsPortableTextLinkDialog } from './ps-portable-text-link-dialog';
|
|
7
7
|
import { PsPortableTextToolbarButton } from './ps-portable-text-toolbar-button';
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
return (_jsx(PsPortableTextToolbarButton, { className: className, disabled: disabled, isActive: isActive, label: label, onClick: () => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
export const PsPortableTextToolbar = ({ disabled, labels }) => {
|
|
9
|
+
const toolbar = usePsPortableTextToolbar();
|
|
10
|
+
const [isLinkOpen, setIsLinkOpen] = useState(false);
|
|
11
|
+
return (_jsxs("div", { "aria-label": labels.toolbar, className: PsPortableTextEditorConfig.classNames.toolbar, role: 'toolbar', children: [_jsx(PsPortableTextToolbarButton, { className: 'font-bold', disabled: disabled, isActive: toolbar.active.bold, label: labels.bold, onClick: () => toolbar.toggleDecorator(PsPortableTextCoreConfig.decorators.bold), children: "B" }), _jsx(PsPortableTextToolbarButton, { className: 'italic', disabled: disabled, isActive: toolbar.active.italic, label: labels.italic, onClick: () => toolbar.toggleDecorator(PsPortableTextCoreConfig.decorators.italic), children: "I" }), _jsx(PsPortableTextToolbarButton, { className: 'underline', disabled: disabled, isActive: toolbar.active.underline, label: labels.underline, onClick: () => toolbar.toggleDecorator(PsPortableTextCoreConfig.decorators.underline), children: "U" }), _jsx(PsPortableTextToolbarButton, { className: 'font-mono', disabled: disabled, isActive: toolbar.active.code, label: labels.code, onClick: () => toolbar.toggleDecorator(PsPortableTextCoreConfig.decorators.code), children: '</>' }), _jsx(PsPortableTextToolbarButton, { disabled: disabled, isActive: toolbar.active.link, label: toolbar.active.link ? labels.removeLink : labels.link, onClick: () => (toolbar.active.link ? toolbar.removeLink() : setIsLinkOpen(true)), children: _jsx("span", { className: 'underline', children: labels.link }) }), _jsx(PsPortableTextLinkDialog, { isOpen: isLinkOpen, labels: labels, onClose: () => {
|
|
12
|
+
setIsLinkOpen(false);
|
|
13
|
+
toolbar.focus();
|
|
14
|
+
}, onSubmit: (href) => {
|
|
15
|
+
toolbar.addLink(href);
|
|
16
|
+
setIsLinkOpen(false);
|
|
17
|
+
} }), _jsx("span", { "aria-hidden": 'true', className: PsPortableTextEditorConfig.classNames.separator }), _jsx(PsPortableTextToolbarButton, { disabled: disabled, isActive: toolbar.active.bulletedList, label: labels.bulletedList, onClick: () => toolbar.toggleListItem(PsPortableTextCoreConfig.listItems.bullet), children: "\u2022" }), _jsx(PsPortableTextToolbarButton, { disabled: disabled, isActive: toolbar.active.numberedList, label: labels.numberedList, onClick: () => toolbar.toggleListItem(PsPortableTextCoreConfig.listItems.number), children: "1." }), _jsx(PsPortableTextToolbarButton, { disabled: disabled, isActive: toolbar.active.quote, label: labels.quote, onClick: toolbar.toggleQuote, children: "\u201D" })] }));
|
|
15
18
|
};
|
|
16
|
-
const ListButton = ({ children, disabled, label, listItem, }) => {
|
|
17
|
-
const editor = useEditor();
|
|
18
|
-
const isActive = useEditorSelector(editor, isActiveListItem(listItem));
|
|
19
|
-
return (_jsx(PsPortableTextToolbarButton, { disabled: disabled, isActive: isActive, label: label, onClick: () => {
|
|
20
|
-
editor.send({ type: 'list item.toggle', listItem });
|
|
21
|
-
editor.send({ type: 'focus' });
|
|
22
|
-
}, children: children }));
|
|
23
|
-
};
|
|
24
|
-
const QuoteButton = ({ children, disabled, label }) => {
|
|
25
|
-
const editor = useEditor();
|
|
26
|
-
const isActive = useEditorSelector(editor, isActiveStyle(PsPortableTextEditorConfig.styles.blockquote));
|
|
27
|
-
return (_jsx(PsPortableTextToolbarButton, { disabled: disabled, isActive: isActive, label: label, onClick: () => {
|
|
28
|
-
editor.send({ type: 'style.toggle', style: PsPortableTextEditorConfig.styles.blockquote });
|
|
29
|
-
editor.send({ type: 'focus' });
|
|
30
|
-
}, children: children }));
|
|
31
|
-
};
|
|
32
|
-
const LinkButton = ({ disabled, labels }) => {
|
|
33
|
-
const editor = useEditor();
|
|
34
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
35
|
-
const isActive = useEditorSelector(editor, isActiveAnnotation(PsPortableTextEditorConfig.linkAnnotation));
|
|
36
|
-
const close = () => {
|
|
37
|
-
setIsOpen(false);
|
|
38
|
-
editor.send({ type: 'focus' });
|
|
39
|
-
};
|
|
40
|
-
return (_jsxs(_Fragment, { children: [_jsx(PsPortableTextToolbarButton, { disabled: disabled, isActive: isActive, label: isActive ? labels.removeLink : labels.link, onClick: () => {
|
|
41
|
-
if (isActive) {
|
|
42
|
-
editor.send({
|
|
43
|
-
type: 'annotation.remove',
|
|
44
|
-
annotation: { name: PsPortableTextEditorConfig.linkAnnotation },
|
|
45
|
-
});
|
|
46
|
-
editor.send({ type: 'focus' });
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
setIsOpen(true);
|
|
50
|
-
}, children: _jsx("span", { className: 'underline', children: labels.link }) }), _jsx(PsPortableTextLinkDialog, { isOpen: isOpen, labels: labels, onClose: close, onSubmit: (href) => {
|
|
51
|
-
editor.send({
|
|
52
|
-
type: 'annotation.add',
|
|
53
|
-
annotation: { name: PsPortableTextEditorConfig.linkAnnotation, value: { href } },
|
|
54
|
-
});
|
|
55
|
-
close();
|
|
56
|
-
} })] }));
|
|
57
|
-
};
|
|
58
|
-
export const PsPortableTextToolbar = ({ disabled, labels }) => (_jsxs("div", { "aria-label": labels.toolbar, className: PsPortableTextEditorConfig.classNames.toolbar, role: 'toolbar', children: [_jsx(DecoratorButton, { className: 'font-bold', decorator: PsPortableTextEditorConfig.decorators.bold, disabled: disabled, label: labels.bold, children: "B" }), _jsx(DecoratorButton, { className: 'italic', decorator: PsPortableTextEditorConfig.decorators.italic, disabled: disabled, label: labels.italic, children: "I" }), _jsx(DecoratorButton, { className: 'underline', decorator: PsPortableTextEditorConfig.decorators.underline, disabled: disabled, label: labels.underline, children: "U" }), _jsx(DecoratorButton, { className: 'font-mono', decorator: PsPortableTextEditorConfig.decorators.code, disabled: disabled, label: labels.code, children: '</>' }), _jsx(LinkButton, { disabled: disabled, labels: labels }), _jsx("span", { "aria-hidden": 'true', className: PsPortableTextEditorConfig.classNames.separator }), _jsx(ListButton, { disabled: disabled, label: labels.bulletedList, listItem: PsPortableTextEditorConfig.listItems.bullet, children: "\u2022" }), _jsx(ListButton, { disabled: disabled, label: labels.numberedList, listItem: PsPortableTextEditorConfig.listItems.number, children: "1." }), _jsx(QuoteButton, { disabled: disabled, label: labels.quote, children: "\u201D" })] }));
|
|
@@ -1,44 +1,4 @@
|
|
|
1
|
-
import { Common } from '@pallasoft/ps-models';
|
|
2
|
-
import { defineSchema } from '@portabletext/editor';
|
|
3
|
-
const Models = Common.PortableTextConfig;
|
|
4
1
|
export const PsPortableTextEditorConfig = {
|
|
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
2
|
classNames: {
|
|
43
3
|
editable: 'ps-input-control w-full resize-none overflow-y-auto rounded-t-none border-t-0 leading-6 outline-none',
|
|
44
4
|
root: 'block',
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { PsPortableTextCoreConfig } from '../portable-text-core/constants/ps-portable-text-core-config';
|
|
3
3
|
export const PsPortableTextEditorRenderers = {
|
|
4
4
|
renderBlock: ({ children, listItem, style }) => {
|
|
5
|
-
if (listItem ===
|
|
5
|
+
if (listItem === PsPortableTextCoreConfig.listItems.bullet) {
|
|
6
6
|
return (_jsx("div", { className: "relative pl-6 before:absolute before:left-1 before:content-['\u2022']", children: children }));
|
|
7
7
|
}
|
|
8
|
-
if (listItem ===
|
|
8
|
+
if (listItem === PsPortableTextCoreConfig.listItems.number) {
|
|
9
9
|
return (_jsx("div", { className: "relative pl-6 before:absolute before:left-0 before:content-[counter(ps-list)'.']", style: { counterIncrement: 'ps-list' }, children: children }));
|
|
10
10
|
}
|
|
11
|
-
if (style ===
|
|
11
|
+
if (style === PsPortableTextCoreConfig.styles.blockquote) {
|
|
12
12
|
return (_jsx("div", { className: 'border-l-2 border-primary pl-3 text-ink/80', style: { counterReset: 'ps-list' }, children: children }));
|
|
13
13
|
}
|
|
14
14
|
return _jsx("div", { style: { counterReset: 'ps-list' }, children: children });
|
|
15
15
|
},
|
|
16
16
|
renderDecorator: ({ children, value }) => {
|
|
17
|
-
if (value ===
|
|
17
|
+
if (value === PsPortableTextCoreConfig.decorators.bold)
|
|
18
18
|
return _jsx("strong", { children: children });
|
|
19
|
-
if (value ===
|
|
19
|
+
if (value === PsPortableTextCoreConfig.decorators.italic)
|
|
20
20
|
return _jsx("em", { children: children });
|
|
21
|
-
if (value ===
|
|
21
|
+
if (value === PsPortableTextCoreConfig.decorators.underline)
|
|
22
22
|
return _jsx("u", { children: children });
|
|
23
|
-
if (value ===
|
|
23
|
+
if (value === PsPortableTextCoreConfig.decorators.code) {
|
|
24
24
|
return _jsx("code", { className: 'rounded bg-ink/10 px-1 font-mono text-[0.9em]', children: children });
|
|
25
25
|
}
|
|
26
26
|
return children;
|