@pallasoft/ps-input-components 1.23.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.
Files changed (39) hide show
  1. package/dist/components/ps-portable-text-editor.d.ts +2 -2
  2. package/dist/components/ps-portable-text-editor.js +4 -29
  3. package/dist/components/ps-portable-text-link-dialog.d.ts +1 -1
  4. package/dist/components/ps-portable-text-link-dialog.js +4 -26
  5. package/dist/components/ps-portable-text-toolbar.d.ts +1 -1
  6. package/dist/components/ps-portable-text-toolbar.js +12 -52
  7. package/dist/constants/ps-portable-text-editor-config.d.ts +0 -55
  8. package/dist/constants/ps-portable-text-editor-config.js +0 -40
  9. package/dist/constants/ps-portable-text-editor-renderers.js +8 -8
  10. package/dist/esm/components/ps-portable-text-editor.js +5 -30
  11. package/dist/esm/components/ps-portable-text-link-dialog.js +4 -26
  12. package/dist/esm/components/ps-portable-text-toolbar.js +13 -53
  13. package/dist/esm/constants/ps-portable-text-editor-config.js +0 -40
  14. package/dist/esm/constants/ps-portable-text-editor-renderers.js +8 -8
  15. package/dist/esm/index.js +1 -1
  16. package/dist/esm/portable-text-core/components/ps-portable-text-core.js +31 -0
  17. package/dist/esm/portable-text-core/constants/ps-portable-text-core-config.js +42 -0
  18. package/dist/esm/portable-text-core/hooks/use-ps-portable-text-link-form.js +32 -0
  19. package/dist/esm/portable-text-core/hooks/use-ps-portable-text-toolbar.js +54 -0
  20. package/dist/esm/portable-text-core/index.js +6 -0
  21. package/dist/esm/{services → portable-text-core/services}/ps-portable-text-editor-service.js +6 -6
  22. package/dist/index.d.ts +1 -1
  23. package/dist/index.js +1 -1
  24. package/dist/portable-text-core/components/ps-portable-text-core.d.ts +17 -0
  25. package/dist/portable-text-core/components/ps-portable-text-core.js +35 -0
  26. package/dist/portable-text-core/constants/ps-portable-text-core-config.d.ts +57 -0
  27. package/dist/portable-text-core/constants/ps-portable-text-core-config.js +45 -0
  28. package/dist/portable-text-core/hooks/use-ps-portable-text-link-form.d.ts +13 -0
  29. package/dist/portable-text-core/hooks/use-ps-portable-text-link-form.js +36 -0
  30. package/dist/portable-text-core/hooks/use-ps-portable-text-toolbar.d.ts +18 -0
  31. package/dist/portable-text-core/hooks/use-ps-portable-text-toolbar.js +58 -0
  32. package/dist/portable-text-core/index.d.ts +7 -0
  33. package/dist/portable-text-core/index.js +22 -0
  34. package/dist/{services → portable-text-core/services}/ps-portable-text-editor-service.js +6 -6
  35. package/package.json +10 -1
  36. /package/dist/esm/{interfaces → portable-text-core/interfaces}/ps-portable-text-editor-labels.js +0 -0
  37. /package/dist/{interfaces → portable-text-core/interfaces}/ps-portable-text-editor-labels.d.ts +0 -0
  38. /package/dist/{interfaces → portable-text-core/interfaces}/ps-portable-text-editor-labels.js +0 -0
  39. /package/dist/{services → portable-text-core/services}/ps-portable-text-editor-service.d.ts +0 -0
@@ -1,5 +1,5 @@
1
- import { type PortableTextBlock } from '@portabletext/editor';
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 ps_portable_text_editor_service_1 = require("../services/ps-portable-text-editor-service");
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 = ps_portable_text_editor_config_1.PsPortableTextEditorConfig.labels, minRows = 4, onChange, placeholder, value, }) => {
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 ps_portable_text_editor_config_1 = require("../constants/ps-portable-text-editor-config");
8
- const ps_portable_text_editor_service_1 = require("../services/ps-portable-text-editor-service");
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 [address, setAddress] = (0, react_1.useState)('');
12
- const [hasError, setHasError] = (0, react_1.useState)(false);
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 DecoratorButton = ({ children, className, decorator, disabled, label, }) => {
12
- const editor = (0, editor_1.useEditor)();
13
- const isActive = (0, editor_1.useEditorSelector)(editor, (0, selectors_1.isActiveDecorator)(decorator));
14
- return ((0, jsx_runtime_1.jsx)(ps_portable_text_toolbar_button_1.PsPortableTextToolbarButton, { className: className, disabled: disabled, isActive: isActive, label: label, onClick: () => {
15
- editor.send({ type: 'decorator.toggle', decorator });
16
- editor.send({ type: 'focus' });
17
- }, children: children }));
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 ps_portable_text_editor_config_1 = require("./ps-portable-text-editor-config");
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 === ps_portable_text_editor_config_1.PsPortableTextEditorConfig.listItems.bullet) {
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 === ps_portable_text_editor_config_1.PsPortableTextEditorConfig.listItems.number) {
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 === ps_portable_text_editor_config_1.PsPortableTextEditorConfig.styles.blockquote) {
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 === ps_portable_text_editor_config_1.PsPortableTextEditorConfig.decorators.bold)
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 === ps_portable_text_editor_config_1.PsPortableTextEditorConfig.decorators.italic)
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 === ps_portable_text_editor_config_1.PsPortableTextEditorConfig.decorators.underline)
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 === ps_portable_text_editor_config_1.PsPortableTextEditorConfig.decorators.code) {
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;
@@ -1,34 +1,9 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
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 { PsPortableTextEditorService } from '../services/ps-portable-text-editor-service';
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 = PsPortableTextEditorConfig.labels, minRows = 4, onChange, placeholder, value, }) => {
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 { PsPortableTextEditorConfig } from '../constants/ps-portable-text-editor-config';
5
- import { PsPortableTextEditorService } from '../services/ps-portable-text-editor-service';
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 [address, setAddress] = useState('');
9
- const [hasError, setHasError] = useState(false);
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, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
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 DecoratorButton = ({ children, className, decorator, disabled, label, }) => {
9
- const editor = useEditor();
10
- const isActive = useEditorSelector(editor, isActiveDecorator(decorator));
11
- return (_jsx(PsPortableTextToolbarButton, { className: className, disabled: disabled, isActive: isActive, label: label, onClick: () => {
12
- editor.send({ type: 'decorator.toggle', decorator });
13
- editor.send({ type: 'focus' });
14
- }, children: children }));
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 { PsPortableTextEditorConfig } from './ps-portable-text-editor-config';
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 === PsPortableTextEditorConfig.listItems.bullet) {
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 === PsPortableTextEditorConfig.listItems.number) {
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 === PsPortableTextEditorConfig.styles.blockquote) {
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 === PsPortableTextEditorConfig.decorators.bold)
17
+ if (value === PsPortableTextCoreConfig.decorators.bold)
18
18
  return _jsx("strong", { children: children });
19
- if (value === PsPortableTextEditorConfig.decorators.italic)
19
+ if (value === PsPortableTextCoreConfig.decorators.italic)
20
20
  return _jsx("em", { children: children });
21
- if (value === PsPortableTextEditorConfig.decorators.underline)
21
+ if (value === PsPortableTextCoreConfig.decorators.underline)
22
22
  return _jsx("u", { children: children });
23
- if (value === PsPortableTextEditorConfig.decorators.code) {
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;
package/dist/esm/index.js CHANGED
@@ -46,6 +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
50
  export * from './components/ps-option-card-group';
51
51
  export * from './interfaces/ps-option-card-data';
@@ -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';
@@ -1,14 +1,14 @@
1
1
  import { Common } from '@pallasoft/ps-models';
2
- import { PsPortableTextEditorConfig } from '../constants/ps-portable-text-editor-config';
3
- import { PsTextFormatService } from './ps-text-format-service';
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 = PsPortableTextEditorConfig.emailPattern.test(trimmed)
10
- ? `${PsPortableTextEditorConfig.mailtoPrefix}${trimmed}`
11
- : trimmed.toLowerCase().startsWith(PsPortableTextEditorConfig.mailtoPrefix)
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 * PsPortableTextEditorConfig.lineHeightRem}rem`;
25
+ return `${minRows * PsPortableTextCoreConfig.lineHeightRem}rem`;
26
26
  }
27
27
  static isSame(first, second) {
28
28
  return JSON.stringify(first) === JSON.stringify(second);
package/dist/index.d.ts CHANGED
@@ -46,7 +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
51
  export * from './components/ps-option-card-group';
52
52
  export * from './interfaces/ps-option-card-data';
package/dist/index.js CHANGED
@@ -62,6 +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
66
  __exportStar(require("./components/ps-option-card-group"), exports);
67
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';
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./components/ps-portable-text-core"), exports);
18
+ __exportStar(require("./constants/ps-portable-text-core-config"), exports);
19
+ __exportStar(require("./hooks/use-ps-portable-text-link-form"), exports);
20
+ __exportStar(require("./hooks/use-ps-portable-text-toolbar"), exports);
21
+ __exportStar(require("./interfaces/ps-portable-text-editor-labels"), exports);
22
+ __exportStar(require("./services/ps-portable-text-editor-service"), exports);
@@ -2,16 +2,16 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PsPortableTextEditorService = void 0;
4
4
  const ps_models_1 = require("@pallasoft/ps-models");
5
- const ps_portable_text_editor_config_1 = require("../constants/ps-portable-text-editor-config");
6
- const ps_text_format_service_1 = require("./ps-text-format-service");
5
+ const ps_text_format_service_1 = require("../../services/ps-text-format-service");
6
+ const ps_portable_text_core_config_1 = require("../constants/ps-portable-text-core-config");
7
7
  class PsPortableTextEditorService {
8
8
  static normalizeLink(raw) {
9
9
  const trimmed = raw.trim();
10
10
  if (trimmed === '')
11
11
  return null;
12
- const candidate = ps_portable_text_editor_config_1.PsPortableTextEditorConfig.emailPattern.test(trimmed)
13
- ? `${ps_portable_text_editor_config_1.PsPortableTextEditorConfig.mailtoPrefix}${trimmed}`
14
- : trimmed.toLowerCase().startsWith(ps_portable_text_editor_config_1.PsPortableTextEditorConfig.mailtoPrefix)
12
+ const candidate = ps_portable_text_core_config_1.PsPortableTextCoreConfig.emailPattern.test(trimmed)
13
+ ? `${ps_portable_text_core_config_1.PsPortableTextCoreConfig.mailtoPrefix}${trimmed}`
14
+ : trimmed.toLowerCase().startsWith(ps_portable_text_core_config_1.PsPortableTextCoreConfig.mailtoPrefix)
15
15
  ? trimmed
16
16
  : ps_text_format_service_1.PsTextFormatService.url(trimmed);
17
17
  try {
@@ -25,7 +25,7 @@ class PsPortableTextEditorService {
25
25
  }
26
26
  }
27
27
  static minHeight(minRows) {
28
- return `${minRows * ps_portable_text_editor_config_1.PsPortableTextEditorConfig.lineHeightRem}rem`;
28
+ return `${minRows * ps_portable_text_core_config_1.PsPortableTextCoreConfig.lineHeightRem}rem`;
29
29
  }
30
30
  static isSame(first, second) {
31
31
  return JSON.stringify(first) === JSON.stringify(second);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pallasoft/ps-input-components",
3
- "version": "1.23.0",
3
+ "version": "1.24.0",
4
4
  "private": false,
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -18,6 +18,12 @@
18
18
  "module": "./dist/esm/form/index.js",
19
19
  "require": "./dist/form/index.js",
20
20
  "default": "./dist/form/index.js"
21
+ },
22
+ "./portable-text-core": {
23
+ "types": "./dist/portable-text-core/index.d.ts",
24
+ "module": "./dist/esm/portable-text-core/index.js",
25
+ "require": "./dist/portable-text-core/index.js",
26
+ "default": "./dist/portable-text-core/index.js"
21
27
  }
22
28
  },
23
29
  "files": [
@@ -102,6 +108,9 @@
102
108
  "*": {
103
109
  "form": [
104
110
  "./dist/form/index.d.ts"
111
+ ],
112
+ "portable-text-core": [
113
+ "./dist/portable-text-core/index.d.ts"
105
114
  ]
106
115
  }
107
116
  },