@pallasoft/ps-input-components 2.2.0 → 3.1.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-combobox-input.d.ts +3 -1
- package/dist/components/ps-combobox-input.js +2 -2
- package/dist/components/ps-portable-text-editor.d.ts +1 -1
- package/dist/components/ps-portable-text-editor.js +1 -2
- package/dist/components/ps-portable-text-link-dialog.d.ts +2 -1
- package/dist/components/ps-portable-text-link-dialog.js +2 -2
- package/dist/components/ps-portable-text-toolbar.js +2 -7
- package/dist/constants/ps-portable-text-editor-config.d.ts +8 -0
- package/dist/constants/ps-portable-text-editor-config.js +8 -0
- package/dist/esm/components/ps-combobox-input.js +2 -2
- package/dist/esm/components/ps-portable-text-editor.js +1 -2
- package/dist/esm/components/ps-portable-text-link-dialog.js +2 -2
- package/dist/esm/components/ps-portable-text-toolbar.js +2 -7
- package/dist/esm/constants/ps-portable-text-editor-config.js +8 -0
- package/dist/esm/portable-text-core/components/ps-portable-text-core-editor-stub.js +2 -0
- package/dist/esm/portable-text-core/components/ps-portable-text-core-editor.js +64 -0
- package/dist/esm/portable-text-core/components/ps-portable-text-core.js +5 -26
- package/dist/esm/portable-text-core/constants/ps-portable-text-core-config.js +29 -9
- package/dist/esm/portable-text-core/contexts/ps-portable-text-core-context.js +9 -0
- package/dist/esm/portable-text-core/hooks/use-ps-portable-text-link-form.js +11 -5
- package/dist/esm/portable-text-core/hooks/use-ps-portable-text-toolbar.js +17 -49
- package/dist/esm/portable-text-core/index.js +4 -0
- package/dist/esm/portable-text-core/interfaces/ps-portable-text-active-formats.js +1 -0
- package/dist/esm/portable-text-core/interfaces/ps-portable-text-block-draft.js +1 -0
- package/dist/esm/portable-text-core/interfaces/ps-portable-text-core-class-names.js +1 -0
- package/dist/esm/portable-text-core/interfaces/ps-portable-text-core-context-data.js +1 -0
- package/dist/esm/portable-text-core/interfaces/ps-portable-text-core-props.js +1 -0
- package/dist/esm/portable-text-core/interfaces/ps-portable-text-extension-options.js +1 -0
- package/dist/esm/portable-text-core/interfaces/ps-portable-text-span-draft.js +1 -0
- package/dist/esm/portable-text-core/interfaces/ps-portable-text-toolbar-state.js +1 -0
- package/dist/esm/portable-text-core/services/ps-portable-text-command-service.js +73 -0
- package/dist/esm/portable-text-core/services/ps-portable-text-converter-service.js +196 -0
- package/dist/esm/portable-text-core/services/ps-portable-text-editor-service.js +4 -0
- package/dist/esm/portable-text-core/services/ps-portable-text-extension-service.js +89 -0
- package/dist/esm/portable-text-engine/index.js +1 -0
- package/dist/esm/portable-text-engine/worker.js +1 -0
- package/dist/portable-text/index.d.ts +1 -1
- package/dist/portable-text-core/components/ps-portable-text-core-editor-stub.d.ts +2 -0
- package/dist/portable-text-core/components/ps-portable-text-core-editor-stub.js +6 -0
- package/dist/portable-text-core/components/ps-portable-text-core-editor.d.ts +2 -0
- package/dist/portable-text-core/components/ps-portable-text-core-editor.js +68 -0
- package/dist/portable-text-core/components/ps-portable-text-core.d.ts +2 -17
- package/dist/portable-text-core/components/ps-portable-text-core.js +3 -24
- package/dist/portable-text-core/constants/ps-portable-text-core-config.d.ts +36 -19
- package/dist/portable-text-core/constants/ps-portable-text-core-config.js +29 -9
- package/dist/portable-text-core/contexts/ps-portable-text-core-context.d.ts +2 -0
- package/dist/portable-text-core/contexts/ps-portable-text-core-context.js +12 -0
- package/dist/portable-text-core/hooks/use-ps-portable-text-link-form.d.ts +3 -1
- package/dist/portable-text-core/hooks/use-ps-portable-text-link-form.js +10 -4
- package/dist/portable-text-core/hooks/use-ps-portable-text-toolbar.d.ts +5 -10
- package/dist/portable-text-core/hooks/use-ps-portable-text-toolbar.js +17 -49
- package/dist/portable-text-core/index.d.ts +5 -1
- package/dist/portable-text-core/index.js +4 -0
- package/dist/portable-text-core/interfaces/ps-portable-text-active-formats.d.ts +10 -0
- package/dist/portable-text-core/interfaces/ps-portable-text-active-formats.js +2 -0
- package/dist/portable-text-core/interfaces/ps-portable-text-block-draft.d.ts +7 -0
- package/dist/portable-text-core/interfaces/ps-portable-text-block-draft.js +2 -0
- package/dist/portable-text-core/interfaces/ps-portable-text-core-class-names.d.ts +8 -0
- package/dist/portable-text-core/interfaces/ps-portable-text-core-class-names.js +2 -0
- package/dist/portable-text-core/interfaces/ps-portable-text-core-context-data.d.ts +9 -0
- package/dist/portable-text-core/interfaces/ps-portable-text-core-context-data.js +2 -0
- package/dist/portable-text-core/interfaces/ps-portable-text-core-props.d.ts +16 -0
- package/dist/portable-text-core/interfaces/ps-portable-text-core-props.js +2 -0
- package/dist/portable-text-core/interfaces/ps-portable-text-editor-labels.d.ts +1 -0
- package/dist/portable-text-core/interfaces/ps-portable-text-extension-options.d.ts +6 -0
- package/dist/portable-text-core/interfaces/ps-portable-text-extension-options.js +2 -0
- package/dist/portable-text-core/interfaces/ps-portable-text-span-draft.d.ts +4 -0
- package/dist/portable-text-core/interfaces/ps-portable-text-span-draft.js +2 -0
- package/dist/portable-text-core/interfaces/ps-portable-text-toolbar-state.d.ts +5 -0
- package/dist/portable-text-core/interfaces/ps-portable-text-toolbar-state.js +2 -0
- package/dist/portable-text-core/services/ps-portable-text-command-service.d.ts +14 -0
- package/dist/portable-text-core/services/ps-portable-text-command-service.js +77 -0
- package/dist/portable-text-core/services/ps-portable-text-converter-service.d.ts +18 -0
- package/dist/portable-text-core/services/ps-portable-text-converter-service.js +200 -0
- package/dist/portable-text-core/services/ps-portable-text-editor-service.d.ts +1 -0
- package/dist/portable-text-core/services/ps-portable-text-editor-service.js +4 -0
- package/dist/portable-text-core/services/ps-portable-text-extension-service.d.ts +8 -0
- package/dist/portable-text-core/services/ps-portable-text-extension-service.js +93 -0
- package/dist/portable-text-engine/index.d.ts +1 -0
- package/dist/portable-text-engine/index.js +17 -0
- package/dist/portable-text-engine/worker.d.ts +1 -0
- package/dist/portable-text-engine/worker.js +17 -0
- package/package.json +29 -5
- package/dist/constants/ps-portable-text-editor-renderers.d.ts +0 -6
- package/dist/constants/ps-portable-text-editor-renderers.js +0 -32
- package/dist/esm/constants/ps-portable-text-editor-renderers.js +0 -29
|
@@ -6,9 +6,11 @@ export interface PsComboboxInputProps<T> {
|
|
|
6
6
|
getItemLabel: (item: T) => string;
|
|
7
7
|
hideLabel?: boolean;
|
|
8
8
|
inputValue?: string;
|
|
9
|
+
isDisabled?: boolean;
|
|
9
10
|
isLoading?: boolean;
|
|
10
11
|
items: T[];
|
|
11
12
|
label?: string;
|
|
13
|
+
menuTrigger?: 'focus' | 'input' | 'manual';
|
|
12
14
|
onInputChange?: (value: string) => void;
|
|
13
15
|
onSelectionChange?: (item: T | null) => void;
|
|
14
16
|
placeholder?: string;
|
|
@@ -16,4 +18,4 @@ export interface PsComboboxInputProps<T> {
|
|
|
16
18
|
required?: boolean;
|
|
17
19
|
selectedKey?: string | null;
|
|
18
20
|
}
|
|
19
|
-
export declare const PsComboboxInput: <T>({ className, emptyText, getItemKey, getItemLabel, hideLabel, inputValue, isLoading, items, label, onInputChange, onSelectionChange, placeholder, renderItem, required, selectedKey, }: PsComboboxInputProps<T>) => import("react").JSX.Element;
|
|
21
|
+
export declare const PsComboboxInput: <T>({ className, emptyText, getItemKey, getItemLabel, hideLabel, inputValue, isDisabled, isLoading, items, label, menuTrigger, onInputChange, onSelectionChange, placeholder, renderItem, required, selectedKey, }: PsComboboxInputProps<T>) => import("react").JSX.Element;
|
|
@@ -7,8 +7,8 @@ const ps_design_system_1 = require("@pallasoft/ps-design-system");
|
|
|
7
7
|
const react_aria_components_1 = require("react-aria-components");
|
|
8
8
|
const ps_combobox_input_service_1 = require("../services/ps-combobox-input-service");
|
|
9
9
|
const ps_required_mark_1 = require("./ps-required-mark");
|
|
10
|
-
const PsComboboxInput = ({ className, emptyText, getItemKey, getItemLabel, hideLabel = false, inputValue, isLoading = false, items, label, onInputChange, onSelectionChange, placeholder, renderItem, required, selectedKey, }) => {
|
|
10
|
+
const PsComboboxInput = ({ className, emptyText, getItemKey, getItemLabel, hideLabel = false, inputValue, isDisabled = false, isLoading = false, items, label, menuTrigger = 'input', onInputChange, onSelectionChange, placeholder, renderItem, required, selectedKey, }) => {
|
|
11
11
|
const itemsByKey = new Map(items.map((item) => [getItemKey(item), item]));
|
|
12
|
-
return ((0, jsx_runtime_1.jsxs)(react_aria_components_1.ComboBox, { allowsEmptyCollection: true, "aria-label": hideLabel ? label : undefined, className: ps_design_system_1.PallasoftClassNameService.merge('block', className), defaultFilter: () => true, inputValue: inputValue, items: items, onInputChange: onInputChange, selectedKey: selectedKey, onSelectionChange: (key) => onSelectionChange?.(key === null ? null : ps_combobox_input_service_1.PsComboboxInputService.getItem(itemsByKey, key)), children: [label && !hideLabel ? ((0, jsx_runtime_1.jsxs)(react_aria_components_1.Label, { className: 'ps-input-label', children: [label, (0, jsx_runtime_1.jsx)(ps_required_mark_1.PsRequiredMark, { isRequired: required })] })) : null, (0, jsx_runtime_1.jsx)("span", { className: hideLabel || !label ? 'relative block' : 'relative mt-2 block', children: (0, jsx_runtime_1.jsx)(react_aria_components_1.Input, { className: 'ps-input-control ps-focus-ring w-full text-sm font-semibold', placeholder: placeholder }) }), (0, jsx_runtime_1.jsx)(react_aria_components_1.Popover, { className: 'w-[--trigger-width] rounded-2xl border border-line bg-white/95 p-1.5 shadow-lg dark:border-white/10 dark:bg-slate-900/95', children: isLoading ? ((0, jsx_runtime_1.jsx)("div", { className: 'flex items-center justify-center py-4', children: (0, jsx_runtime_1.jsx)(ps_core_components_1.PsSpinner, { label: 'Loading results', size: 'small' }) })) : ((0, jsx_runtime_1.jsx)(react_aria_components_1.ListBox, { className: 'max-h-72 overflow-y-auto outline-none', items: items, renderEmptyState: () => emptyText ? (0, jsx_runtime_1.jsx)("div", { className: 'px-3 py-2 text-sm text-ink/55', children: emptyText }) : null, children: (item) => ((0, jsx_runtime_1.jsx)(react_aria_components_1.ListBoxItem, { className: 'ps-focus-ring cursor-pointer rounded-ps-control px-3 py-2 text-sm font-semibold text-ink selected:bg-primary-soft selected:text-primary hover:bg-slate-50 dark:hover:bg-white/6', id: getItemKey(item), textValue: getItemLabel(item), children: renderItem ? renderItem(item) : getItemLabel(item) })) })) })] }));
|
|
12
|
+
return ((0, jsx_runtime_1.jsxs)(react_aria_components_1.ComboBox, { allowsEmptyCollection: true, "aria-label": hideLabel ? label : undefined, className: ps_design_system_1.PallasoftClassNameService.merge('block', className), defaultFilter: () => true, inputValue: inputValue, isDisabled: isDisabled, items: items, menuTrigger: menuTrigger, onInputChange: onInputChange, selectedKey: selectedKey, onSelectionChange: (key) => onSelectionChange?.(key === null ? null : ps_combobox_input_service_1.PsComboboxInputService.getItem(itemsByKey, key)), children: [label && !hideLabel ? ((0, jsx_runtime_1.jsxs)(react_aria_components_1.Label, { className: 'ps-input-label', children: [label, (0, jsx_runtime_1.jsx)(ps_required_mark_1.PsRequiredMark, { isRequired: required })] })) : null, (0, jsx_runtime_1.jsx)("span", { className: hideLabel || !label ? 'relative block' : 'relative mt-2 block', children: (0, jsx_runtime_1.jsx)(react_aria_components_1.Input, { className: 'ps-input-control ps-focus-ring w-full text-sm font-semibold', placeholder: placeholder }) }), (0, jsx_runtime_1.jsx)(react_aria_components_1.Popover, { className: 'w-[--trigger-width] rounded-2xl border border-line bg-white/95 p-1.5 shadow-lg dark:border-white/10 dark:bg-slate-900/95', children: isLoading && items.length === 0 ? ((0, jsx_runtime_1.jsx)("div", { className: 'flex items-center justify-center py-4', children: (0, jsx_runtime_1.jsx)(ps_core_components_1.PsSpinner, { label: 'Loading results', size: 'small' }) })) : ((0, jsx_runtime_1.jsx)(react_aria_components_1.ListBox, { "aria-busy": isLoading, className: 'max-h-72 overflow-y-auto outline-none', items: items, renderEmptyState: () => emptyText ? (0, jsx_runtime_1.jsx)("div", { className: 'px-3 py-2 text-sm text-ink/55', children: emptyText }) : null, children: (item) => ((0, jsx_runtime_1.jsx)(react_aria_components_1.ListBoxItem, { className: 'ps-focus-ring cursor-pointer rounded-ps-control px-3 py-2 text-sm font-semibold text-ink selected:bg-primary-soft selected:text-primary hover:bg-slate-50 dark:hover:bg-white/6', id: getItemKey(item), textValue: getItemLabel(item), children: renderItem ? renderItem(item) : getItemLabel(item) })) })) })] }));
|
|
13
13
|
};
|
|
14
14
|
exports.PsComboboxInput = PsComboboxInput;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PortableTextBlock } from '@portabletext/
|
|
1
|
+
import type { PortableTextBlock } from '@portabletext/schema';
|
|
2
2
|
import type { PsPortableTextEditorLabels } from '../portable-text-core/interfaces/ps-portable-text-editor-labels';
|
|
3
3
|
export interface PsPortableTextEditorProps {
|
|
4
4
|
className?: string;
|
|
@@ -4,10 +4,9 @@ exports.PsPortableTextEditor = void 0;
|
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const ps_design_system_1 = require("@pallasoft/ps-design-system");
|
|
6
6
|
const ps_portable_text_editor_config_1 = require("../constants/ps-portable-text-editor-config");
|
|
7
|
-
const ps_portable_text_editor_renderers_1 = require("../constants/ps-portable-text-editor-renderers");
|
|
8
7
|
const ps_portable_text_core_1 = require("../portable-text-core/components/ps-portable-text-core");
|
|
9
8
|
const ps_portable_text_core_config_1 = require("../portable-text-core/constants/ps-portable-text-core-config");
|
|
10
9
|
const ps_portable_text_editor_service_1 = require("../portable-text-core/services/ps-portable-text-editor-service");
|
|
11
10
|
const ps_portable_text_toolbar_1 = require("./ps-portable-text-toolbar");
|
|
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, {
|
|
11
|
+
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, { className: ps_design_system_1.PallasoftClassNameService.merge(ps_portable_text_editor_config_1.PsPortableTextEditorConfig.classNames.root, className), classNames: ps_portable_text_editor_config_1.PsPortableTextEditorConfig.contentClassNames, 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) } })] }), label: labels.editor, minRows: minRows, onChange: onChange, placeholder: placeholder, toolbar: (0, jsx_runtime_1.jsx)(ps_portable_text_toolbar_1.PsPortableTextToolbar, { disabled: disabled, labels: labels }), value: value }));
|
|
13
12
|
exports.PsPortableTextEditor = PsPortableTextEditor;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { PsPortableTextEditorLabels } from '../portable-text-core/interfaces/ps-portable-text-editor-labels';
|
|
2
2
|
export interface PsPortableTextLinkDialogProps {
|
|
3
|
+
href?: string;
|
|
3
4
|
isOpen: boolean;
|
|
4
5
|
labels: PsPortableTextEditorLabels;
|
|
5
6
|
onClose: () => void;
|
|
6
7
|
onSubmit: (href: string) => void;
|
|
7
8
|
}
|
|
8
|
-
export declare const PsPortableTextLinkDialog: ({ isOpen, labels, onClose, onSubmit, }: PsPortableTextLinkDialogProps) => import("react").JSX.Element;
|
|
9
|
+
export declare const PsPortableTextLinkDialog: ({ href, isOpen, labels, onClose, onSubmit, }: PsPortableTextLinkDialogProps) => import("react").JSX.Element;
|
|
@@ -6,8 +6,8 @@ const ps_popovers_1 = require("@pallasoft/ps-popovers");
|
|
|
6
6
|
const ps_portable_text_core_config_1 = require("../portable-text-core/constants/ps-portable-text-core-config");
|
|
7
7
|
const use_ps_portable_text_link_form_1 = require("../portable-text-core/hooks/use-ps-portable-text-link-form");
|
|
8
8
|
const ps_url_input_1 = require("./ps-url-input");
|
|
9
|
-
const PsPortableTextLinkDialog = ({ isOpen, labels, onClose, onSubmit, }) => {
|
|
10
|
-
const form = (0, use_ps_portable_text_link_form_1.usePsPortableTextLinkForm)({ onClose, onSubmit });
|
|
9
|
+
const PsPortableTextLinkDialog = ({ href, isOpen, labels, onClose, onSubmit, }) => {
|
|
10
|
+
const form = (0, use_ps_portable_text_link_form_1.usePsPortableTextLinkForm)({ href, isOpen, onClose, onSubmit });
|
|
11
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 }) }));
|
|
12
12
|
};
|
|
13
13
|
exports.PsPortableTextLinkDialog = PsPortableTextLinkDialog;
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PsPortableTextToolbar = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
-
const react_1 = require("react");
|
|
6
5
|
const ps_portable_text_editor_config_1 = require("../constants/ps-portable-text-editor-config");
|
|
7
6
|
const ps_portable_text_core_config_1 = require("../portable-text-core/constants/ps-portable-text-core-config");
|
|
8
7
|
const use_ps_portable_text_toolbar_1 = require("../portable-text-core/hooks/use-ps-portable-text-toolbar");
|
|
@@ -10,13 +9,9 @@ const ps_portable_text_link_dialog_1 = require("./ps-portable-text-link-dialog")
|
|
|
10
9
|
const ps_portable_text_toolbar_button_1 = require("./ps-portable-text-toolbar-button");
|
|
11
10
|
const PsPortableTextToolbar = ({ disabled, labels }) => {
|
|
12
11
|
const toolbar = (0, use_ps_portable_text_toolbar_1.usePsPortableTextToolbar)();
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
setIsLinkOpen(false);
|
|
16
|
-
toolbar.focus();
|
|
17
|
-
}, onSubmit: (href) => {
|
|
12
|
+
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() : toolbar.openLink()), children: (0, jsx_runtime_1.jsx)("span", { className: 'underline', children: labels.link }) }), (0, jsx_runtime_1.jsx)(ps_portable_text_link_dialog_1.PsPortableTextLinkDialog, { href: toolbar.linkHref, isOpen: toolbar.isLinkOpen, labels: labels, onClose: toolbar.closeLink, onSubmit: (href) => {
|
|
13
|
+
toolbar.closeLink();
|
|
18
14
|
toolbar.addLink(href);
|
|
19
|
-
setIsLinkOpen(false);
|
|
20
15
|
} }), (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" })] }));
|
|
21
16
|
};
|
|
22
17
|
exports.PsPortableTextToolbar = PsPortableTextToolbar;
|
|
@@ -7,4 +7,12 @@ export declare const PsPortableTextEditorConfig: {
|
|
|
7
7
|
readonly buttonActive: "bg-primary text-white hover:bg-primary hover:text-white";
|
|
8
8
|
readonly separator: "mx-1 h-5 w-px bg-line";
|
|
9
9
|
};
|
|
10
|
+
readonly contentClassNames: {
|
|
11
|
+
readonly blockquote: "border-l-2 border-primary pl-3 text-ink/80";
|
|
12
|
+
readonly bulletList: "list-disc pl-6";
|
|
13
|
+
readonly code: "rounded bg-ink/10 px-1 font-mono text-[0.9em]";
|
|
14
|
+
readonly link: "text-primary underline";
|
|
15
|
+
readonly orderedList: "list-decimal pl-6";
|
|
16
|
+
readonly placeholder: "before:pointer-events-none before:float-left before:h-0 before:text-ink/45 before:content-[attr(data-placeholder)]";
|
|
17
|
+
};
|
|
10
18
|
};
|
|
@@ -10,4 +10,12 @@ exports.PsPortableTextEditorConfig = {
|
|
|
10
10
|
buttonActive: 'bg-primary text-white hover:bg-primary hover:text-white',
|
|
11
11
|
separator: 'mx-1 h-5 w-px bg-line',
|
|
12
12
|
},
|
|
13
|
+
contentClassNames: {
|
|
14
|
+
blockquote: 'border-l-2 border-primary pl-3 text-ink/80',
|
|
15
|
+
bulletList: 'list-disc pl-6',
|
|
16
|
+
code: 'rounded bg-ink/10 px-1 font-mono text-[0.9em]',
|
|
17
|
+
link: 'text-primary underline',
|
|
18
|
+
orderedList: 'list-decimal pl-6',
|
|
19
|
+
placeholder: 'before:pointer-events-none before:float-left before:h-0 before:text-ink/45 before:content-[attr(data-placeholder)]',
|
|
20
|
+
},
|
|
13
21
|
};
|
|
@@ -4,7 +4,7 @@ import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
|
4
4
|
import { ComboBox, Input, Label, ListBox, ListBoxItem, Popover } from 'react-aria-components';
|
|
5
5
|
import { PsComboboxInputService } from '../services/ps-combobox-input-service';
|
|
6
6
|
import { PsRequiredMark } from './ps-required-mark';
|
|
7
|
-
export const PsComboboxInput = ({ className, emptyText, getItemKey, getItemLabel, hideLabel = false, inputValue, isLoading = false, items, label, onInputChange, onSelectionChange, placeholder, renderItem, required, selectedKey, }) => {
|
|
7
|
+
export const PsComboboxInput = ({ className, emptyText, getItemKey, getItemLabel, hideLabel = false, inputValue, isDisabled = false, isLoading = false, items, label, menuTrigger = 'input', onInputChange, onSelectionChange, placeholder, renderItem, required, selectedKey, }) => {
|
|
8
8
|
const itemsByKey = new Map(items.map((item) => [getItemKey(item), item]));
|
|
9
|
-
return (_jsxs(ComboBox, { allowsEmptyCollection: true, "aria-label": hideLabel ? label : undefined, className: PallasoftClassNameService.merge('block', className), defaultFilter: () => true, inputValue: inputValue, items: items, onInputChange: onInputChange, selectedKey: selectedKey, onSelectionChange: (key) => onSelectionChange?.(key === null ? null : PsComboboxInputService.getItem(itemsByKey, key)), children: [label && !hideLabel ? (_jsxs(Label, { className: 'ps-input-label', children: [label, _jsx(PsRequiredMark, { isRequired: required })] })) : null, _jsx("span", { className: hideLabel || !label ? 'relative block' : 'relative mt-2 block', children: _jsx(Input, { className: 'ps-input-control ps-focus-ring w-full text-sm font-semibold', placeholder: placeholder }) }), _jsx(Popover, { className: 'w-[--trigger-width] rounded-2xl border border-line bg-white/95 p-1.5 shadow-lg dark:border-white/10 dark:bg-slate-900/95', children: isLoading ? (_jsx("div", { className: 'flex items-center justify-center py-4', children: _jsx(PsSpinner, { label: 'Loading results', size: 'small' }) })) : (_jsx(ListBox, { className: 'max-h-72 overflow-y-auto outline-none', items: items, renderEmptyState: () => emptyText ? _jsx("div", { className: 'px-3 py-2 text-sm text-ink/55', children: emptyText }) : null, children: (item) => (_jsx(ListBoxItem, { className: 'ps-focus-ring cursor-pointer rounded-ps-control px-3 py-2 text-sm font-semibold text-ink selected:bg-primary-soft selected:text-primary hover:bg-slate-50 dark:hover:bg-white/6', id: getItemKey(item), textValue: getItemLabel(item), children: renderItem ? renderItem(item) : getItemLabel(item) })) })) })] }));
|
|
9
|
+
return (_jsxs(ComboBox, { allowsEmptyCollection: true, "aria-label": hideLabel ? label : undefined, className: PallasoftClassNameService.merge('block', className), defaultFilter: () => true, inputValue: inputValue, isDisabled: isDisabled, items: items, menuTrigger: menuTrigger, onInputChange: onInputChange, selectedKey: selectedKey, onSelectionChange: (key) => onSelectionChange?.(key === null ? null : PsComboboxInputService.getItem(itemsByKey, key)), children: [label && !hideLabel ? (_jsxs(Label, { className: 'ps-input-label', children: [label, _jsx(PsRequiredMark, { isRequired: required })] })) : null, _jsx("span", { className: hideLabel || !label ? 'relative block' : 'relative mt-2 block', children: _jsx(Input, { className: 'ps-input-control ps-focus-ring w-full text-sm font-semibold', placeholder: placeholder }) }), _jsx(Popover, { className: 'w-[--trigger-width] rounded-2xl border border-line bg-white/95 p-1.5 shadow-lg dark:border-white/10 dark:bg-slate-900/95', children: isLoading && items.length === 0 ? (_jsx("div", { className: 'flex items-center justify-center py-4', children: _jsx(PsSpinner, { label: 'Loading results', size: 'small' }) })) : (_jsx(ListBox, { "aria-busy": isLoading, className: 'max-h-72 overflow-y-auto outline-none', items: items, renderEmptyState: () => emptyText ? _jsx("div", { className: 'px-3 py-2 text-sm text-ink/55', children: emptyText }) : null, children: (item) => (_jsx(ListBoxItem, { className: 'ps-focus-ring cursor-pointer rounded-ps-control px-3 py-2 text-sm font-semibold text-ink selected:bg-primary-soft selected:text-primary hover:bg-slate-50 dark:hover:bg-white/6', id: getItemKey(item), textValue: getItemLabel(item), children: renderItem ? renderItem(item) : getItemLabel(item) })) })) })] }));
|
|
10
10
|
};
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
3
3
|
import { PsPortableTextEditorConfig } from '../constants/ps-portable-text-editor-config';
|
|
4
|
-
import { PsPortableTextEditorRenderers } from '../constants/ps-portable-text-editor-renderers';
|
|
5
4
|
import { PsPortableTextCore } from '../portable-text-core/components/ps-portable-text-core';
|
|
6
5
|
import { PsPortableTextCoreConfig } from '../portable-text-core/constants/ps-portable-text-core-config';
|
|
7
6
|
import { PsPortableTextEditorService } from '../portable-text-core/services/ps-portable-text-editor-service';
|
|
8
7
|
import { PsPortableTextToolbar } from './ps-portable-text-toolbar';
|
|
9
|
-
export const PsPortableTextEditor = ({ className, disabled = false, labels = PsPortableTextCoreConfig.labels, minRows = 4, onChange, placeholder, value, }) => (_jsx(PsPortableTextCore, {
|
|
8
|
+
export const PsPortableTextEditor = ({ className, disabled = false, labels = PsPortableTextCoreConfig.labels, minRows = 4, onChange, placeholder, value, }) => (_jsx(PsPortableTextCore, { className: PallasoftClassNameService.merge(PsPortableTextEditorConfig.classNames.root, className), classNames: PsPortableTextEditorConfig.contentClassNames, 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) } })] }), label: labels.editor, minRows: minRows, onChange: onChange, placeholder: placeholder, toolbar: _jsx(PsPortableTextToolbar, { disabled: disabled, labels: labels }), value: value }));
|
|
@@ -3,7 +3,7 @@ import { PsFormModal } from '@pallasoft/ps-popovers';
|
|
|
3
3
|
import { PsPortableTextCoreConfig } from '../portable-text-core/constants/ps-portable-text-core-config';
|
|
4
4
|
import { usePsPortableTextLinkForm } from '../portable-text-core/hooks/use-ps-portable-text-link-form';
|
|
5
5
|
import { PsUrlInput } from './ps-url-input';
|
|
6
|
-
export const PsPortableTextLinkDialog = ({ isOpen, labels, onClose, onSubmit, }) => {
|
|
7
|
-
const form = usePsPortableTextLinkForm({ onClose, onSubmit });
|
|
6
|
+
export const PsPortableTextLinkDialog = ({ href, isOpen, labels, onClose, onSubmit, }) => {
|
|
7
|
+
const form = usePsPortableTextLinkForm({ href, isOpen, onClose, onSubmit });
|
|
8
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 }) }));
|
|
9
9
|
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from 'react';
|
|
3
2
|
import { PsPortableTextEditorConfig } from '../constants/ps-portable-text-editor-config';
|
|
4
3
|
import { PsPortableTextCoreConfig } from '../portable-text-core/constants/ps-portable-text-core-config';
|
|
5
4
|
import { usePsPortableTextToolbar } from '../portable-text-core/hooks/use-ps-portable-text-toolbar';
|
|
@@ -7,12 +6,8 @@ import { PsPortableTextLinkDialog } from './ps-portable-text-link-dialog';
|
|
|
7
6
|
import { PsPortableTextToolbarButton } from './ps-portable-text-toolbar-button';
|
|
8
7
|
export const PsPortableTextToolbar = ({ disabled, labels }) => {
|
|
9
8
|
const toolbar = usePsPortableTextToolbar();
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
setIsLinkOpen(false);
|
|
13
|
-
toolbar.focus();
|
|
14
|
-
}, onSubmit: (href) => {
|
|
9
|
+
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() : toolbar.openLink()), children: _jsx("span", { className: 'underline', children: labels.link }) }), _jsx(PsPortableTextLinkDialog, { href: toolbar.linkHref, isOpen: toolbar.isLinkOpen, labels: labels, onClose: toolbar.closeLink, onSubmit: (href) => {
|
|
10
|
+
toolbar.closeLink();
|
|
15
11
|
toolbar.addLink(href);
|
|
16
|
-
setIsLinkOpen(false);
|
|
17
12
|
} }), _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" })] }));
|
|
18
13
|
};
|
|
@@ -7,4 +7,12 @@ export const PsPortableTextEditorConfig = {
|
|
|
7
7
|
buttonActive: 'bg-primary text-white hover:bg-primary hover:text-white',
|
|
8
8
|
separator: 'mx-1 h-5 w-px bg-line',
|
|
9
9
|
},
|
|
10
|
+
contentClassNames: {
|
|
11
|
+
blockquote: 'border-l-2 border-primary pl-3 text-ink/80',
|
|
12
|
+
bulletList: 'list-disc pl-6',
|
|
13
|
+
code: 'rounded bg-ink/10 px-1 font-mono text-[0.9em]',
|
|
14
|
+
link: 'text-primary underline',
|
|
15
|
+
orderedList: 'list-decimal pl-6',
|
|
16
|
+
placeholder: 'before:pointer-events-none before:float-left before:h-0 before:text-ink/45 before:content-[attr(data-placeholder)]',
|
|
17
|
+
},
|
|
10
18
|
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { EditorContent, useEditor, useEditorState } from '@tiptap/react';
|
|
4
|
+
import { PsPortableTextCoreContext } from '../contexts/ps-portable-text-core-context';
|
|
5
|
+
import { PsPortableTextCommandService } from '../services/ps-portable-text-command-service';
|
|
6
|
+
import { PsPortableTextConverterService } from '../services/ps-portable-text-converter-service';
|
|
7
|
+
import { PsPortableTextEditorService } from '../services/ps-portable-text-editor-service';
|
|
8
|
+
import { PsPortableTextExtensionService } from '../services/ps-portable-text-extension-service';
|
|
9
|
+
export const PsPortableTextCoreEditor = ({ className, classNames, disabled = false, editableClassName = '', label, minRows = 4, onChange, placeholder = '', toolbar, value, }) => {
|
|
10
|
+
const [isLinkOpen, setIsLinkOpen] = useState(false);
|
|
11
|
+
const lastValue = useRef(value);
|
|
12
|
+
const editor = useEditor({
|
|
13
|
+
content: PsPortableTextConverterService.toDocument(value),
|
|
14
|
+
editable: !disabled,
|
|
15
|
+
editorProps: {
|
|
16
|
+
attributes: {
|
|
17
|
+
...(label === undefined ? {} : { 'aria-label': label }),
|
|
18
|
+
'aria-multiline': 'true',
|
|
19
|
+
'class': editableClassName,
|
|
20
|
+
'role': 'textbox',
|
|
21
|
+
'style': `min-height: ${PsPortableTextEditorService.minHeight(minRows)}`,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
extensions: PsPortableTextExtensionService.extensions({
|
|
25
|
+
classNames,
|
|
26
|
+
onLinkShortcut: () => setIsLinkOpen(true),
|
|
27
|
+
placeholder,
|
|
28
|
+
}),
|
|
29
|
+
immediatelyRender: true,
|
|
30
|
+
}, []);
|
|
31
|
+
const state = useEditorState({
|
|
32
|
+
editor,
|
|
33
|
+
selector: ({ editor: current }) => PsPortableTextCommandService.state(current),
|
|
34
|
+
});
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
editor.setEditable(!disabled, false);
|
|
37
|
+
}, [editor, disabled]);
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
const update = () => {
|
|
40
|
+
const next = PsPortableTextConverterService.toBlocks(editor.getJSON());
|
|
41
|
+
lastValue.current = next;
|
|
42
|
+
onChange(next);
|
|
43
|
+
};
|
|
44
|
+
editor.on('update', update);
|
|
45
|
+
return () => {
|
|
46
|
+
editor.off('update', update);
|
|
47
|
+
};
|
|
48
|
+
}, [editor, onChange]);
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
if (PsPortableTextEditorService.isSame(value, lastValue.current))
|
|
51
|
+
return;
|
|
52
|
+
lastValue.current = value;
|
|
53
|
+
editor.commands.setContent(PsPortableTextConverterService.toDocument(value), {
|
|
54
|
+
emitUpdate: false,
|
|
55
|
+
});
|
|
56
|
+
}, [editor, value]);
|
|
57
|
+
return (_jsx("div", { className: className, children: _jsxs(PsPortableTextCoreContext.Provider, { value: {
|
|
58
|
+
closeLink: () => setIsLinkOpen(false),
|
|
59
|
+
editor,
|
|
60
|
+
isLinkOpen,
|
|
61
|
+
openLink: () => setIsLinkOpen(true),
|
|
62
|
+
state,
|
|
63
|
+
}, children: [toolbar, _jsx(EditorContent, { editor: editor })] }) }));
|
|
64
|
+
};
|
|
@@ -1,31 +1,10 @@
|
|
|
1
|
-
import { jsx as _jsx
|
|
2
|
-
import { useEffect,
|
|
3
|
-
import {
|
|
4
|
-
|
|
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, }) => {
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import { PsPortableTextCoreEditor } from '@pallasoft/ps-input-components/portable-text-engine';
|
|
4
|
+
export const PsPortableTextCore = (props) => {
|
|
8
5
|
const [isMounted, setIsMounted] = useState(false);
|
|
9
|
-
const [version, setVersion] = useState(0);
|
|
10
|
-
const lastValue = useRef(value);
|
|
11
6
|
useEffect(() => {
|
|
12
7
|
setIsMounted(true);
|
|
13
8
|
}, []);
|
|
14
|
-
|
|
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) }));
|
|
9
|
+
return isMounted ? (_jsx(PsPortableTextCoreEditor, { ...props })) : (_jsx("div", { className: props.className, children: props.fallback }));
|
|
31
10
|
};
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { Common } from '@pallasoft/ps-models';
|
|
2
|
-
import { defineSchema } from '@portabletext/editor';
|
|
3
2
|
const Models = Common.PortableTextConfig;
|
|
4
3
|
export const PsPortableTextCoreConfig = {
|
|
5
4
|
linkAnnotation: Models.linkType,
|
|
6
5
|
mailtoPrefix: 'mailto:',
|
|
7
6
|
emailPattern: /^[^\s@/:]+@[^\s@/:]+\.[^\s@/:]+$/,
|
|
8
7
|
lineHeightRem: 1.5,
|
|
8
|
+
lineBreak: '\n',
|
|
9
|
+
defaultLinkProtocol: 'https',
|
|
10
|
+
keyPrefix: { block: 'b', link: 'l', span: 's' },
|
|
9
11
|
decorators: {
|
|
10
12
|
bold: Models.decorators[0],
|
|
11
13
|
code: Models.decorators[3],
|
|
@@ -14,19 +16,37 @@ export const PsPortableTextCoreConfig = {
|
|
|
14
16
|
},
|
|
15
17
|
styles: { blockquote: Models.styles[1], normal: Models.styles[0] },
|
|
16
18
|
listItems: { bullet: Models.listItems[0], number: Models.listItems[1] },
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
decoratorMarks: {
|
|
20
|
+
[Models.decorators[0]]: 'bold',
|
|
21
|
+
[Models.decorators[1]]: 'italic',
|
|
22
|
+
[Models.decorators[2]]: 'underline',
|
|
23
|
+
[Models.decorators[3]]: 'code',
|
|
24
|
+
},
|
|
25
|
+
listNodes: {
|
|
26
|
+
[Models.listItems[0]]: 'bulletList',
|
|
27
|
+
[Models.listItems[1]]: 'orderedList',
|
|
28
|
+
},
|
|
29
|
+
nodes: {
|
|
30
|
+
blockquote: 'blockquote',
|
|
31
|
+
bulletList: 'bulletList',
|
|
32
|
+
document: 'doc',
|
|
33
|
+
hardBreak: 'hardBreak',
|
|
34
|
+
listItem: 'listItem',
|
|
35
|
+
orderedList: 'orderedList',
|
|
36
|
+
paragraph: 'paragraph',
|
|
37
|
+
text: 'text',
|
|
38
|
+
},
|
|
39
|
+
linkMark: 'link',
|
|
40
|
+
linkShortcutExtension: 'psLinkShortcut',
|
|
41
|
+
listItemContent: 'paragraph (bulletList | orderedList)*',
|
|
42
|
+
blockquoteContent: 'paragraph+',
|
|
43
|
+
shortcuts: { link: 'Mod-k', nest: 'Tab', unnest: 'Shift-Tab' },
|
|
25
44
|
labels: {
|
|
26
45
|
bold: 'Bold',
|
|
27
46
|
bulletedList: 'Bulleted list',
|
|
28
47
|
cancel: 'Cancel',
|
|
29
48
|
code: 'Code',
|
|
49
|
+
editor: 'Text',
|
|
30
50
|
invalidLink: 'Enter a web address or email address',
|
|
31
51
|
italic: 'Italic',
|
|
32
52
|
link: 'Link',
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createContext } from 'react';
|
|
2
|
+
import { PsPortableTextCommandService } from '../services/ps-portable-text-command-service';
|
|
3
|
+
export const PsPortableTextCoreContext = createContext({
|
|
4
|
+
closeLink: () => undefined,
|
|
5
|
+
editor: null,
|
|
6
|
+
isLinkOpen: false,
|
|
7
|
+
openLink: () => undefined,
|
|
8
|
+
state: PsPortableTextCommandService.state(null),
|
|
9
|
+
});
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import { useState } from 'react';
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
2
|
import { PsPortableTextEditorService } from '../services/ps-portable-text-editor-service';
|
|
3
|
-
export const usePsPortableTextLinkForm = ({ onClose, onSubmit, }) => {
|
|
3
|
+
export const usePsPortableTextLinkForm = ({ href, isOpen = false, onClose, onSubmit, }) => {
|
|
4
4
|
const [address, setAddress] = useState('');
|
|
5
5
|
const [hasError, setHasError] = useState(false);
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
if (!isOpen)
|
|
8
|
+
return;
|
|
9
|
+
setAddress(href === undefined ? '' : href);
|
|
10
|
+
setHasError(false);
|
|
11
|
+
}, [isOpen]);
|
|
6
12
|
return {
|
|
7
13
|
address,
|
|
8
14
|
close: () => {
|
|
@@ -19,14 +25,14 @@ export const usePsPortableTextLinkForm = ({ onClose, onSubmit, }) => {
|
|
|
19
25
|
submit: (event) => {
|
|
20
26
|
event.preventDefault();
|
|
21
27
|
event.stopPropagation();
|
|
22
|
-
const
|
|
23
|
-
if (
|
|
28
|
+
const normalized = PsPortableTextEditorService.normalizeLink(address);
|
|
29
|
+
if (normalized === null) {
|
|
24
30
|
setHasError(true);
|
|
25
31
|
return;
|
|
26
32
|
}
|
|
27
33
|
setAddress('');
|
|
28
34
|
setHasError(false);
|
|
29
|
-
onSubmit(
|
|
35
|
+
onSubmit(normalized);
|
|
30
36
|
},
|
|
31
37
|
};
|
|
32
38
|
};
|
|
@@ -1,54 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { useContext } from 'react';
|
|
2
|
+
import { PsPortableTextCoreContext } from '../contexts/ps-portable-text-core-context';
|
|
3
|
+
import { PsPortableTextCommandService } from '../services/ps-portable-text-command-service';
|
|
4
4
|
export const usePsPortableTextToolbar = () => {
|
|
5
|
-
const editor =
|
|
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' });
|
|
5
|
+
const { closeLink, editor, isLinkOpen, openLink, state } = useContext(PsPortableTextCoreContext);
|
|
15
6
|
return {
|
|
16
|
-
active:
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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();
|
|
7
|
+
active: state.active,
|
|
8
|
+
addLink: (href) => PsPortableTextCommandService.setLink(editor, href),
|
|
9
|
+
closeLink: () => {
|
|
10
|
+
closeLink();
|
|
11
|
+
PsPortableTextCommandService.focus(editor);
|
|
52
12
|
},
|
|
13
|
+
focus: () => PsPortableTextCommandService.focus(editor),
|
|
14
|
+
isLinkOpen,
|
|
15
|
+
linkHref: state.linkHref,
|
|
16
|
+
openLink,
|
|
17
|
+
removeLink: () => PsPortableTextCommandService.removeLink(editor),
|
|
18
|
+
toggleDecorator: (decorator) => PsPortableTextCommandService.toggleDecorator(editor, decorator),
|
|
19
|
+
toggleListItem: (listItem) => PsPortableTextCommandService.toggleListItem(editor, listItem),
|
|
20
|
+
toggleQuote: () => PsPortableTextCommandService.toggleQuote(editor),
|
|
53
21
|
};
|
|
54
22
|
};
|
|
@@ -2,5 +2,9 @@ export * from './components/ps-portable-text-core';
|
|
|
2
2
|
export * from './constants/ps-portable-text-core-config';
|
|
3
3
|
export * from './hooks/use-ps-portable-text-link-form';
|
|
4
4
|
export * from './hooks/use-ps-portable-text-toolbar';
|
|
5
|
+
export * from './interfaces/ps-portable-text-active-formats';
|
|
6
|
+
export * from './interfaces/ps-portable-text-core-class-names';
|
|
7
|
+
export * from './interfaces/ps-portable-text-core-props';
|
|
5
8
|
export * from './interfaces/ps-portable-text-editor-labels';
|
|
9
|
+
export * from './services/ps-portable-text-converter-service';
|
|
6
10
|
export * from './services/ps-portable-text-editor-service';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|