@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.
Files changed (86) hide show
  1. package/dist/components/ps-combobox-input.d.ts +3 -1
  2. package/dist/components/ps-combobox-input.js +2 -2
  3. package/dist/components/ps-portable-text-editor.d.ts +1 -1
  4. package/dist/components/ps-portable-text-editor.js +1 -2
  5. package/dist/components/ps-portable-text-link-dialog.d.ts +2 -1
  6. package/dist/components/ps-portable-text-link-dialog.js +2 -2
  7. package/dist/components/ps-portable-text-toolbar.js +2 -7
  8. package/dist/constants/ps-portable-text-editor-config.d.ts +8 -0
  9. package/dist/constants/ps-portable-text-editor-config.js +8 -0
  10. package/dist/esm/components/ps-combobox-input.js +2 -2
  11. package/dist/esm/components/ps-portable-text-editor.js +1 -2
  12. package/dist/esm/components/ps-portable-text-link-dialog.js +2 -2
  13. package/dist/esm/components/ps-portable-text-toolbar.js +2 -7
  14. package/dist/esm/constants/ps-portable-text-editor-config.js +8 -0
  15. package/dist/esm/portable-text-core/components/ps-portable-text-core-editor-stub.js +2 -0
  16. package/dist/esm/portable-text-core/components/ps-portable-text-core-editor.js +64 -0
  17. package/dist/esm/portable-text-core/components/ps-portable-text-core.js +5 -26
  18. package/dist/esm/portable-text-core/constants/ps-portable-text-core-config.js +29 -9
  19. package/dist/esm/portable-text-core/contexts/ps-portable-text-core-context.js +9 -0
  20. package/dist/esm/portable-text-core/hooks/use-ps-portable-text-link-form.js +11 -5
  21. package/dist/esm/portable-text-core/hooks/use-ps-portable-text-toolbar.js +17 -49
  22. package/dist/esm/portable-text-core/index.js +4 -0
  23. package/dist/esm/portable-text-core/interfaces/ps-portable-text-active-formats.js +1 -0
  24. package/dist/esm/portable-text-core/interfaces/ps-portable-text-block-draft.js +1 -0
  25. package/dist/esm/portable-text-core/interfaces/ps-portable-text-core-class-names.js +1 -0
  26. package/dist/esm/portable-text-core/interfaces/ps-portable-text-core-context-data.js +1 -0
  27. package/dist/esm/portable-text-core/interfaces/ps-portable-text-core-props.js +1 -0
  28. package/dist/esm/portable-text-core/interfaces/ps-portable-text-extension-options.js +1 -0
  29. package/dist/esm/portable-text-core/interfaces/ps-portable-text-span-draft.js +1 -0
  30. package/dist/esm/portable-text-core/interfaces/ps-portable-text-toolbar-state.js +1 -0
  31. package/dist/esm/portable-text-core/services/ps-portable-text-command-service.js +73 -0
  32. package/dist/esm/portable-text-core/services/ps-portable-text-converter-service.js +196 -0
  33. package/dist/esm/portable-text-core/services/ps-portable-text-editor-service.js +4 -0
  34. package/dist/esm/portable-text-core/services/ps-portable-text-extension-service.js +89 -0
  35. package/dist/esm/portable-text-engine/index.js +1 -0
  36. package/dist/esm/portable-text-engine/worker.js +1 -0
  37. package/dist/portable-text/index.d.ts +1 -1
  38. package/dist/portable-text-core/components/ps-portable-text-core-editor-stub.d.ts +2 -0
  39. package/dist/portable-text-core/components/ps-portable-text-core-editor-stub.js +6 -0
  40. package/dist/portable-text-core/components/ps-portable-text-core-editor.d.ts +2 -0
  41. package/dist/portable-text-core/components/ps-portable-text-core-editor.js +68 -0
  42. package/dist/portable-text-core/components/ps-portable-text-core.d.ts +2 -17
  43. package/dist/portable-text-core/components/ps-portable-text-core.js +3 -24
  44. package/dist/portable-text-core/constants/ps-portable-text-core-config.d.ts +36 -19
  45. package/dist/portable-text-core/constants/ps-portable-text-core-config.js +29 -9
  46. package/dist/portable-text-core/contexts/ps-portable-text-core-context.d.ts +2 -0
  47. package/dist/portable-text-core/contexts/ps-portable-text-core-context.js +12 -0
  48. package/dist/portable-text-core/hooks/use-ps-portable-text-link-form.d.ts +3 -1
  49. package/dist/portable-text-core/hooks/use-ps-portable-text-link-form.js +10 -4
  50. package/dist/portable-text-core/hooks/use-ps-portable-text-toolbar.d.ts +5 -10
  51. package/dist/portable-text-core/hooks/use-ps-portable-text-toolbar.js +17 -49
  52. package/dist/portable-text-core/index.d.ts +5 -1
  53. package/dist/portable-text-core/index.js +4 -0
  54. package/dist/portable-text-core/interfaces/ps-portable-text-active-formats.d.ts +10 -0
  55. package/dist/portable-text-core/interfaces/ps-portable-text-active-formats.js +2 -0
  56. package/dist/portable-text-core/interfaces/ps-portable-text-block-draft.d.ts +7 -0
  57. package/dist/portable-text-core/interfaces/ps-portable-text-block-draft.js +2 -0
  58. package/dist/portable-text-core/interfaces/ps-portable-text-core-class-names.d.ts +8 -0
  59. package/dist/portable-text-core/interfaces/ps-portable-text-core-class-names.js +2 -0
  60. package/dist/portable-text-core/interfaces/ps-portable-text-core-context-data.d.ts +9 -0
  61. package/dist/portable-text-core/interfaces/ps-portable-text-core-context-data.js +2 -0
  62. package/dist/portable-text-core/interfaces/ps-portable-text-core-props.d.ts +16 -0
  63. package/dist/portable-text-core/interfaces/ps-portable-text-core-props.js +2 -0
  64. package/dist/portable-text-core/interfaces/ps-portable-text-editor-labels.d.ts +1 -0
  65. package/dist/portable-text-core/interfaces/ps-portable-text-extension-options.d.ts +6 -0
  66. package/dist/portable-text-core/interfaces/ps-portable-text-extension-options.js +2 -0
  67. package/dist/portable-text-core/interfaces/ps-portable-text-span-draft.d.ts +4 -0
  68. package/dist/portable-text-core/interfaces/ps-portable-text-span-draft.js +2 -0
  69. package/dist/portable-text-core/interfaces/ps-portable-text-toolbar-state.d.ts +5 -0
  70. package/dist/portable-text-core/interfaces/ps-portable-text-toolbar-state.js +2 -0
  71. package/dist/portable-text-core/services/ps-portable-text-command-service.d.ts +14 -0
  72. package/dist/portable-text-core/services/ps-portable-text-command-service.js +77 -0
  73. package/dist/portable-text-core/services/ps-portable-text-converter-service.d.ts +18 -0
  74. package/dist/portable-text-core/services/ps-portable-text-converter-service.js +200 -0
  75. package/dist/portable-text-core/services/ps-portable-text-editor-service.d.ts +1 -0
  76. package/dist/portable-text-core/services/ps-portable-text-editor-service.js +4 -0
  77. package/dist/portable-text-core/services/ps-portable-text-extension-service.d.ts +8 -0
  78. package/dist/portable-text-core/services/ps-portable-text-extension-service.js +93 -0
  79. package/dist/portable-text-engine/index.d.ts +1 -0
  80. package/dist/portable-text-engine/index.js +17 -0
  81. package/dist/portable-text-engine/worker.d.ts +1 -0
  82. package/dist/portable-text-engine/worker.js +17 -0
  83. package/package.json +29 -5
  84. package/dist/constants/ps-portable-text-editor-renderers.d.ts +0 -6
  85. package/dist/constants/ps-portable-text-editor-renderers.js +0 -32
  86. package/dist/esm/constants/ps-portable-text-editor-renderers.js +0 -29
@@ -0,0 +1,73 @@
1
+ import { PsPortableTextCoreConfig } from '../constants/ps-portable-text-core-config';
2
+ import { PsPortableTextEditorService } from './ps-portable-text-editor-service';
3
+ export class PsPortableTextCommandService {
4
+ static state(editor) {
5
+ return { active: this.active(editor), linkHref: this.linkHref(editor) };
6
+ }
7
+ static active(editor) {
8
+ const isActive = (name) => (editor === null ? false : editor.isActive(name));
9
+ const marks = PsPortableTextCoreConfig.decoratorMarks;
10
+ const decorators = PsPortableTextCoreConfig.decorators;
11
+ return {
12
+ bold: isActive(marks[decorators.bold]),
13
+ bulletedList: isActive(PsPortableTextCoreConfig.nodes.bulletList),
14
+ code: isActive(marks[decorators.code]),
15
+ italic: isActive(marks[decorators.italic]),
16
+ link: isActive(PsPortableTextCoreConfig.linkMark),
17
+ numberedList: isActive(PsPortableTextCoreConfig.nodes.orderedList),
18
+ quote: isActive(PsPortableTextCoreConfig.nodes.blockquote),
19
+ underline: isActive(marks[decorators.underline]),
20
+ };
21
+ }
22
+ static linkHref(editor) {
23
+ const href = editor === null ? undefined : editor.getAttributes(PsPortableTextCoreConfig.linkMark).href;
24
+ return typeof href === 'string' ? href : '';
25
+ }
26
+ static toggleDecorator(editor, decorator) {
27
+ const mark = PsPortableTextEditorService.lookup(PsPortableTextCoreConfig.decoratorMarks, decorator);
28
+ if (editor !== null && mark !== null)
29
+ editor.chain().focus().toggleMark(mark).run();
30
+ }
31
+ static toggleListItem(editor, listItem) {
32
+ const list = PsPortableTextEditorService.lookup(PsPortableTextCoreConfig.listNodes, listItem);
33
+ if (editor !== null && list !== null) {
34
+ editor.chain().focus().toggleList(list, PsPortableTextCoreConfig.nodes.listItem).run();
35
+ }
36
+ }
37
+ static toggleQuote(editor) {
38
+ if (editor !== null)
39
+ editor.chain().focus().toggleBlockquote().run();
40
+ }
41
+ static setLink(editor, href) {
42
+ if (editor === null)
43
+ return;
44
+ if (editor.state.selection.empty && !editor.isActive(PsPortableTextCoreConfig.linkMark)) {
45
+ editor
46
+ .chain()
47
+ .focus()
48
+ .insertContent({
49
+ type: PsPortableTextCoreConfig.nodes.text,
50
+ text: href.replace(PsPortableTextCoreConfig.mailtoPrefix, ''),
51
+ marks: [{ type: PsPortableTextCoreConfig.linkMark, attrs: { href } }],
52
+ })
53
+ .unsetMark(PsPortableTextCoreConfig.linkMark)
54
+ .run();
55
+ return;
56
+ }
57
+ editor
58
+ .chain()
59
+ .focus()
60
+ .extendMarkRange(PsPortableTextCoreConfig.linkMark)
61
+ .setLink({ href })
62
+ .run();
63
+ }
64
+ static removeLink(editor) {
65
+ if (editor !== null) {
66
+ editor.chain().focus().extendMarkRange(PsPortableTextCoreConfig.linkMark).unsetLink().run();
67
+ }
68
+ }
69
+ static focus(editor) {
70
+ if (editor !== null)
71
+ editor.commands.focus();
72
+ }
73
+ }
@@ -0,0 +1,196 @@
1
+ import { Common } from '@pallasoft/ps-models';
2
+ import { PsPortableTextCoreConfig } from '../constants/ps-portable-text-core-config';
3
+ import { PsPortableTextEditorService } from './ps-portable-text-editor-service';
4
+ export class PsPortableTextConverterService {
5
+ static toDocument(blocks) {
6
+ const content = [];
7
+ let lists = [];
8
+ let quote = null;
9
+ (Array.isArray(blocks) ? blocks : [])
10
+ .filter((block) => block._type === Common.PortableTextConfig.blockType)
11
+ .forEach((block) => {
12
+ const paragraph = this.paragraph(block);
13
+ const listNode = this.listNode(block.listItem);
14
+ if (listNode === null) {
15
+ lists = [];
16
+ if (block.style !== PsPortableTextCoreConfig.styles.blockquote) {
17
+ quote = null;
18
+ content.push(paragraph);
19
+ return;
20
+ }
21
+ if (quote === null) {
22
+ quote = { type: PsPortableTextCoreConfig.nodes.blockquote, content: [] };
23
+ content.push(quote);
24
+ }
25
+ this.children(quote).push(paragraph);
26
+ return;
27
+ }
28
+ quote = null;
29
+ const level = Math.min(this.level(block.level), lists.length + 1);
30
+ const open = lists.slice(0, level);
31
+ lists =
32
+ open.length === level && open[level - 1].type !== listNode ? open.slice(0, -1) : open;
33
+ if (lists.length < level) {
34
+ const list = { type: listNode, content: [] };
35
+ const parent = lists[lists.length - 1];
36
+ if (parent === undefined)
37
+ content.push(list);
38
+ else
39
+ this.children(this.children(parent)[this.children(parent).length - 1]).push(list);
40
+ lists = [...lists, list];
41
+ }
42
+ this.children(lists[level - 1]).push({
43
+ type: PsPortableTextCoreConfig.nodes.listItem,
44
+ content: [paragraph],
45
+ });
46
+ });
47
+ return {
48
+ type: PsPortableTextCoreConfig.nodes.document,
49
+ content: content.length === 0 ? [{ type: PsPortableTextCoreConfig.nodes.paragraph }] : content,
50
+ };
51
+ }
52
+ static toBlocks(document) {
53
+ const drafts = this.children(document).flatMap((node) => this.drafts(node, 1));
54
+ const isBlank = drafts.length === 1 &&
55
+ drafts[0].listItem === undefined &&
56
+ drafts[0].style === PsPortableTextCoreConfig.styles.normal &&
57
+ this.children(drafts[0].paragraph).length === 0;
58
+ return isBlank
59
+ ? []
60
+ : drafts.map((draft, index) => this.block(draft, `${PsPortableTextCoreConfig.keyPrefix.block}${index}`));
61
+ }
62
+ static drafts(node, level) {
63
+ if (node.type === PsPortableTextCoreConfig.nodes.paragraph) {
64
+ return [{ paragraph: node, style: PsPortableTextCoreConfig.styles.normal }];
65
+ }
66
+ if (node.type === PsPortableTextCoreConfig.nodes.blockquote) {
67
+ return this.children(node)
68
+ .filter((child) => child.type === PsPortableTextCoreConfig.nodes.paragraph)
69
+ .map((paragraph) => ({ paragraph, style: PsPortableTextCoreConfig.styles.blockquote }));
70
+ }
71
+ const listItem = this.listItem(node.type);
72
+ if (listItem === null)
73
+ return [];
74
+ return this.children(node).flatMap((item) => this.children(item).flatMap((child) => child.type === PsPortableTextCoreConfig.nodes.paragraph
75
+ ? [
76
+ {
77
+ level: Math.min(level, Common.PortableTextConfig.maxListLevel),
78
+ listItem,
79
+ paragraph: child,
80
+ style: PsPortableTextCoreConfig.styles.normal,
81
+ },
82
+ ]
83
+ : this.drafts(child, level + 1)));
84
+ }
85
+ static block(draft, key) {
86
+ const hrefs = Array.from(new Set(this.children(draft.paragraph).flatMap((node) => this.marks(node)
87
+ .filter((mark) => mark.type === PsPortableTextCoreConfig.linkMark)
88
+ .map((mark) => this.href(mark))
89
+ .filter((href) => href !== null))));
90
+ const markDefs = hrefs.map((href, index) => ({
91
+ _key: `${key}${PsPortableTextCoreConfig.keyPrefix.link}${index}`,
92
+ _type: PsPortableTextCoreConfig.linkAnnotation,
93
+ href,
94
+ }));
95
+ const spans = this.spans(draft.paragraph, markDefs);
96
+ const children = (spans.length === 0 ? [{ marks: [], text: '' }] : spans).map((span, index) => ({
97
+ _key: `${key}${PsPortableTextCoreConfig.keyPrefix.span}${index}`,
98
+ _type: Common.PortableTextConfig.spanType,
99
+ marks: span.marks,
100
+ text: span.text,
101
+ }));
102
+ const base = {
103
+ _key: key,
104
+ _type: Common.PortableTextConfig.blockType,
105
+ children,
106
+ markDefs,
107
+ style: draft.style,
108
+ };
109
+ return draft.listItem === undefined
110
+ ? base
111
+ : { ...base, level: draft.level, listItem: draft.listItem };
112
+ }
113
+ static spans(paragraph, markDefs) {
114
+ return this.children(paragraph).reduce((spans, node) => {
115
+ const previous = spans[spans.length - 1];
116
+ const isBreak = node.type === PsPortableTextCoreConfig.nodes.hardBreak;
117
+ if (!isBreak && (node.type !== PsPortableTextCoreConfig.nodes.text || !node.text)) {
118
+ return spans;
119
+ }
120
+ const marks = this.spanMarks(node, markDefs);
121
+ const text = isBreak ? PsPortableTextCoreConfig.lineBreak : String(node.text);
122
+ return previous !== undefined && this.isSame(previous.marks, marks)
123
+ ? [...spans.slice(0, -1), { marks, text: previous.text + text }]
124
+ : [...spans, { marks, text }];
125
+ }, []);
126
+ }
127
+ static spanMarks(node, markDefs) {
128
+ const types = this.marks(node).map((mark) => mark.type);
129
+ const decorators = Common.PortableTextConfig.decorators.filter((decorator) => types.includes(PsPortableTextCoreConfig.decoratorMarks[decorator]));
130
+ const links = this.marks(node)
131
+ .filter((mark) => mark.type === PsPortableTextCoreConfig.linkMark)
132
+ .map((mark) => markDefs.find((definition) => definition.href === this.href(mark)))
133
+ .filter((definition) => definition !== undefined)
134
+ .map((definition) => definition._key);
135
+ return [...decorators, ...links];
136
+ }
137
+ static paragraph(block) {
138
+ const links = new Map((Array.isArray(block.markDefs) ? block.markDefs : [])
139
+ .filter((definition) => definition._type === PsPortableTextCoreConfig.linkAnnotation)
140
+ .map((definition) => [
141
+ definition._key,
142
+ typeof definition.href === 'string'
143
+ ? PsPortableTextEditorService.normalizeLink(definition.href)
144
+ : null,
145
+ ]));
146
+ const content = (Array.isArray(block.children) ? block.children : [])
147
+ .filter((child) => child._type === Common.PortableTextConfig.spanType && typeof child.text === 'string')
148
+ .flatMap((child) => {
149
+ const marks = (Array.isArray(child.marks) ? child.marks : [])
150
+ .filter((mark) => typeof mark === 'string')
151
+ .flatMap((mark) => {
152
+ const decorator = PsPortableTextEditorService.lookup(PsPortableTextCoreConfig.decoratorMarks, mark);
153
+ const href = links.get(mark);
154
+ if (decorator !== null)
155
+ return [{ type: decorator }];
156
+ return typeof href === 'string'
157
+ ? [{ type: PsPortableTextCoreConfig.linkMark, attrs: { href } }]
158
+ : [];
159
+ });
160
+ return String(child.text)
161
+ .split(PsPortableTextCoreConfig.lineBreak)
162
+ .flatMap((text, index) => [
163
+ ...(index === 0 ? [] : [{ type: PsPortableTextCoreConfig.nodes.hardBreak, marks }]),
164
+ ...(text === '' ? [] : [{ type: PsPortableTextCoreConfig.nodes.text, text, marks }]),
165
+ ]);
166
+ });
167
+ return content.length === 0
168
+ ? { type: PsPortableTextCoreConfig.nodes.paragraph }
169
+ : { type: PsPortableTextCoreConfig.nodes.paragraph, content };
170
+ }
171
+ static listNode(listItem) {
172
+ return PsPortableTextEditorService.lookup(PsPortableTextCoreConfig.listNodes, listItem);
173
+ }
174
+ static listItem(type) {
175
+ const match = Object.entries(PsPortableTextCoreConfig.listNodes).find(([, node]) => node === type);
176
+ return match === undefined ? null : match[0];
177
+ }
178
+ static level(level) {
179
+ return typeof level === 'number' && Number.isInteger(level)
180
+ ? Math.max(1, Math.min(level, Common.PortableTextConfig.maxListLevel))
181
+ : 1;
182
+ }
183
+ static href(mark) {
184
+ const href = mark.attrs === undefined ? undefined : mark.attrs.href;
185
+ return typeof href === 'string' ? PsPortableTextEditorService.normalizeLink(href) : null;
186
+ }
187
+ static marks(node) {
188
+ return Array.isArray(node.marks) ? node.marks : [];
189
+ }
190
+ static children(node) {
191
+ return Array.isArray(node.content) ? node.content : [];
192
+ }
193
+ static isSame(first, second) {
194
+ return first.length === second.length && first.every((mark, index) => mark === second[index]);
195
+ }
196
+ }
@@ -27,4 +27,8 @@ export class PsPortableTextEditorService {
27
27
  static isSame(first, second) {
28
28
  return JSON.stringify(first) === JSON.stringify(second);
29
29
  }
30
+ static lookup(record, key) {
31
+ const match = Object.entries(record).find(([name]) => name === key);
32
+ return match === undefined ? null : match[1];
33
+ }
30
34
  }
@@ -0,0 +1,89 @@
1
+ import { Common } from '@pallasoft/ps-models';
2
+ import { Extension } from '@tiptap/core';
3
+ import { Blockquote } from '@tiptap/extension-blockquote';
4
+ import { Bold } from '@tiptap/extension-bold';
5
+ import { Code } from '@tiptap/extension-code';
6
+ import { Document } from '@tiptap/extension-document';
7
+ import { HardBreak } from '@tiptap/extension-hard-break';
8
+ import { Italic } from '@tiptap/extension-italic';
9
+ import { Link } from '@tiptap/extension-link';
10
+ import { BulletList, ListItem, ListKeymap, OrderedList } from '@tiptap/extension-list';
11
+ import { Paragraph } from '@tiptap/extension-paragraph';
12
+ import { Text } from '@tiptap/extension-text';
13
+ import { Underline } from '@tiptap/extension-underline';
14
+ import { Placeholder, UndoRedo } from '@tiptap/extensions';
15
+ import { PsPortableTextCoreConfig } from '../constants/ps-portable-text-core-config';
16
+ import { PsPortableTextEditorService } from './ps-portable-text-editor-service';
17
+ export class PsPortableTextExtensionService {
18
+ static extensions({ classNames, onLinkShortcut, placeholder, }) {
19
+ return [
20
+ Document,
21
+ Paragraph,
22
+ Text,
23
+ HardBreak,
24
+ Bold,
25
+ Italic,
26
+ Underline,
27
+ Code.extend({ excludes: Code.name }).configure({
28
+ HTMLAttributes: { class: classNames.code },
29
+ }),
30
+ Blockquote.extend({ content: PsPortableTextCoreConfig.blockquoteContent }).configure({
31
+ HTMLAttributes: { class: classNames.blockquote },
32
+ }),
33
+ BulletList.configure({ HTMLAttributes: { class: classNames.bulletList } }),
34
+ OrderedList.configure({ HTMLAttributes: { class: classNames.orderedList } }),
35
+ ListItem.extend({
36
+ content: PsPortableTextCoreConfig.listItemContent,
37
+ addKeyboardShortcuts() {
38
+ return {
39
+ ...this.parent?.(),
40
+ [PsPortableTextCoreConfig.shortcuts.nest]: () => PsPortableTextExtensionService.nest(this.editor),
41
+ [PsPortableTextCoreConfig.shortcuts.unnest]: () => PsPortableTextExtensionService.unnest(this.editor),
42
+ };
43
+ },
44
+ }),
45
+ ListKeymap,
46
+ Link.configure({
47
+ autolink: true,
48
+ defaultProtocol: PsPortableTextCoreConfig.defaultLinkProtocol,
49
+ HTMLAttributes: { class: classNames.link },
50
+ isAllowedUri: (url, context) => context.defaultValidate(url) && PsPortableTextEditorService.normalizeLink(url) !== null,
51
+ linkOnPaste: true,
52
+ openOnClick: false,
53
+ }),
54
+ Placeholder.configure({
55
+ emptyEditorClass: classNames.placeholder,
56
+ placeholder: ({ editor }) => (editor.isEmpty ? placeholder : ''),
57
+ }),
58
+ UndoRedo,
59
+ Extension.create({
60
+ name: PsPortableTextCoreConfig.linkShortcutExtension,
61
+ addKeyboardShortcuts: () => ({
62
+ [PsPortableTextCoreConfig.shortcuts.link]: () => {
63
+ onLinkShortcut();
64
+ return true;
65
+ },
66
+ }),
67
+ }),
68
+ ];
69
+ }
70
+ static listDepth(editor) {
71
+ const { $from } = editor.state.selection;
72
+ return Array.from({ length: $from.depth }, (_, index) => $from.node(index + 1)).filter((node) => node.type.name === PsPortableTextCoreConfig.nodes.listItem).length;
73
+ }
74
+ static nest(editor) {
75
+ const depth = PsPortableTextExtensionService.listDepth(editor);
76
+ if (depth === 0)
77
+ return false;
78
+ if (depth < Common.PortableTextConfig.maxListLevel) {
79
+ editor.commands.sinkListItem(PsPortableTextCoreConfig.nodes.listItem);
80
+ }
81
+ return true;
82
+ }
83
+ static unnest(editor) {
84
+ if (PsPortableTextExtensionService.listDepth(editor) === 0)
85
+ return false;
86
+ editor.commands.liftListItem(PsPortableTextCoreConfig.nodes.listItem);
87
+ return true;
88
+ }
89
+ }
@@ -0,0 +1 @@
1
+ export * from '../portable-text-core/components/ps-portable-text-core-editor';
@@ -0,0 +1 @@
1
+ export * from '../portable-text-core/components/ps-portable-text-core-editor-stub';
@@ -1,3 +1,3 @@
1
1
  export * from '../components/ps-portable-text-editor';
2
2
  export * from '../portable-text-core/interfaces/ps-portable-text-editor-labels';
3
- export type { PortableTextBlock } from '@portabletext/editor';
3
+ export type { PortableTextBlock } from '@portabletext/schema';
@@ -0,0 +1,2 @@
1
+ import type { PsPortableTextCoreProps } from '../interfaces/ps-portable-text-core-props';
2
+ export declare const PsPortableTextCoreEditor: ({ className, fallback }: PsPortableTextCoreProps) => import("react").JSX.Element;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsPortableTextCoreEditor = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const PsPortableTextCoreEditor = ({ className, fallback }) => ((0, jsx_runtime_1.jsx)("div", { className: className, children: fallback }));
6
+ exports.PsPortableTextCoreEditor = PsPortableTextCoreEditor;
@@ -0,0 +1,2 @@
1
+ import type { PsPortableTextCoreProps } from '../interfaces/ps-portable-text-core-props';
2
+ export declare const PsPortableTextCoreEditor: ({ className, classNames, disabled, editableClassName, label, minRows, onChange, placeholder, toolbar, value, }: PsPortableTextCoreProps) => import("react").JSX.Element;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsPortableTextCoreEditor = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const react_2 = require("@tiptap/react");
7
+ const ps_portable_text_core_context_1 = require("../contexts/ps-portable-text-core-context");
8
+ const ps_portable_text_command_service_1 = require("../services/ps-portable-text-command-service");
9
+ const ps_portable_text_converter_service_1 = require("../services/ps-portable-text-converter-service");
10
+ const ps_portable_text_editor_service_1 = require("../services/ps-portable-text-editor-service");
11
+ const ps_portable_text_extension_service_1 = require("../services/ps-portable-text-extension-service");
12
+ const PsPortableTextCoreEditor = ({ className, classNames, disabled = false, editableClassName = '', label, minRows = 4, onChange, placeholder = '', toolbar, value, }) => {
13
+ const [isLinkOpen, setIsLinkOpen] = (0, react_1.useState)(false);
14
+ const lastValue = (0, react_1.useRef)(value);
15
+ const editor = (0, react_2.useEditor)({
16
+ content: ps_portable_text_converter_service_1.PsPortableTextConverterService.toDocument(value),
17
+ editable: !disabled,
18
+ editorProps: {
19
+ attributes: {
20
+ ...(label === undefined ? {} : { 'aria-label': label }),
21
+ 'aria-multiline': 'true',
22
+ 'class': editableClassName,
23
+ 'role': 'textbox',
24
+ 'style': `min-height: ${ps_portable_text_editor_service_1.PsPortableTextEditorService.minHeight(minRows)}`,
25
+ },
26
+ },
27
+ extensions: ps_portable_text_extension_service_1.PsPortableTextExtensionService.extensions({
28
+ classNames,
29
+ onLinkShortcut: () => setIsLinkOpen(true),
30
+ placeholder,
31
+ }),
32
+ immediatelyRender: true,
33
+ }, []);
34
+ const state = (0, react_2.useEditorState)({
35
+ editor,
36
+ selector: ({ editor: current }) => ps_portable_text_command_service_1.PsPortableTextCommandService.state(current),
37
+ });
38
+ (0, react_1.useEffect)(() => {
39
+ editor.setEditable(!disabled, false);
40
+ }, [editor, disabled]);
41
+ (0, react_1.useEffect)(() => {
42
+ const update = () => {
43
+ const next = ps_portable_text_converter_service_1.PsPortableTextConverterService.toBlocks(editor.getJSON());
44
+ lastValue.current = next;
45
+ onChange(next);
46
+ };
47
+ editor.on('update', update);
48
+ return () => {
49
+ editor.off('update', update);
50
+ };
51
+ }, [editor, onChange]);
52
+ (0, react_1.useEffect)(() => {
53
+ if (ps_portable_text_editor_service_1.PsPortableTextEditorService.isSame(value, lastValue.current))
54
+ return;
55
+ lastValue.current = value;
56
+ editor.commands.setContent(ps_portable_text_converter_service_1.PsPortableTextConverterService.toDocument(value), {
57
+ emitUpdate: false,
58
+ });
59
+ }, [editor, value]);
60
+ return ((0, jsx_runtime_1.jsx)("div", { className: className, children: (0, jsx_runtime_1.jsxs)(ps_portable_text_core_context_1.PsPortableTextCoreContext.Provider, { value: {
61
+ closeLink: () => setIsLinkOpen(false),
62
+ editor,
63
+ isLinkOpen,
64
+ openLink: () => setIsLinkOpen(true),
65
+ state,
66
+ }, children: [toolbar, (0, jsx_runtime_1.jsx)(react_2.EditorContent, { editor: editor })] }) }));
67
+ };
68
+ exports.PsPortableTextCoreEditor = PsPortableTextCoreEditor;
@@ -1,17 +1,2 @@
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;
1
+ import type { PsPortableTextCoreProps } from '../interfaces/ps-portable-text-core-props';
2
+ export declare const PsPortableTextCore: (props: PsPortableTextCoreProps) => import("react").JSX.Element;
@@ -3,33 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PsPortableTextCore = 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 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, }) => {
6
+ const portable_text_engine_1 = require("@pallasoft/ps-input-components/portable-text-engine");
7
+ const PsPortableTextCore = (props) => {
11
8
  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
9
  (0, react_1.useEffect)(() => {
15
10
  setIsMounted(true);
16
11
  }, []);
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) }));
12
+ return isMounted ? ((0, jsx_runtime_1.jsx)(portable_text_engine_1.PsPortableTextCoreEditor, { ...props })) : ((0, jsx_runtime_1.jsx)("div", { className: props.className, children: props.fallback }));
34
13
  };
35
14
  exports.PsPortableTextCore = PsPortableTextCore;
@@ -3,6 +3,13 @@ export declare const PsPortableTextCoreConfig: {
3
3
  readonly mailtoPrefix: "mailto:";
4
4
  readonly emailPattern: RegExp;
5
5
  readonly lineHeightRem: 1.5;
6
+ readonly lineBreak: "\n";
7
+ readonly defaultLinkProtocol: "https";
8
+ readonly keyPrefix: {
9
+ readonly block: "b";
10
+ readonly link: "l";
11
+ readonly span: "s";
12
+ };
6
13
  readonly decorators: {
7
14
  readonly bold: "strong";
8
15
  readonly code: "code";
@@ -17,31 +24,41 @@ export declare const PsPortableTextCoreConfig: {
17
24
  readonly bullet: "bullet";
18
25
  readonly number: "number";
19
26
  };
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
- }[];
27
+ readonly decoratorMarks: {
28
+ readonly strong: "bold";
29
+ readonly em: "italic";
30
+ readonly underline: "underline";
31
+ readonly code: "code";
32
+ };
33
+ readonly listNodes: {
34
+ readonly bullet: "bulletList";
35
+ readonly number: "orderedList";
36
+ };
37
+ readonly nodes: {
38
+ readonly blockquote: "blockquote";
39
+ readonly bulletList: "bulletList";
40
+ readonly document: "doc";
41
+ readonly hardBreak: "hardBreak";
42
+ readonly listItem: "listItem";
43
+ readonly orderedList: "orderedList";
44
+ readonly paragraph: "paragraph";
45
+ readonly text: "text";
46
+ };
47
+ readonly linkMark: "link";
48
+ readonly linkShortcutExtension: "psLinkShortcut";
49
+ readonly listItemContent: "paragraph (bulletList | orderedList)*";
50
+ readonly blockquoteContent: "paragraph+";
51
+ readonly shortcuts: {
52
+ readonly link: "Mod-k";
53
+ readonly nest: "Tab";
54
+ readonly unnest: "Shift-Tab";
39
55
  };
40
56
  readonly labels: {
41
57
  bold: string;
42
58
  bulletedList: string;
43
59
  cancel: string;
44
60
  code: string;
61
+ editor: string;
45
62
  invalidLink: string;
46
63
  italic: string;
47
64
  link: string;