neuphlo-editor 0.3.7 → 0.3.8

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/index.cjs CHANGED
@@ -1,18 +1 @@
1
- 'use strict';
2
-
3
- var StarterKit = require('@tiptap/starter-kit');
4
-
5
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
6
-
7
- var StarterKit__default = /*#__PURE__*/_interopDefault(StarterKit);
8
-
9
- // src/preset.ts
10
- var Preset = [
11
- StarterKit__default.default.configure({
12
- bulletList: { keepMarks: true },
13
- orderedList: { keepMarks: true },
14
- heading: { levels: [1, 2, 3, 4] }
15
- })
16
- ];
17
-
18
- exports.Preset = Preset;
1
+ 'use strict';var e=require('@tiptap/starter-kit');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var e__default=/*#__PURE__*/_interopDefault(e);var r=[e__default.default.configure({bulletList:{keepMarks:true},orderedList:{keepMarks:true},heading:{levels:[1,2,3,4]}})];exports.Preset=r;
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export { Preset } from './chunk-SWNQOIUA.js';
1
+ import e from'@tiptap/starter-kit';var r=[e.configure({bulletList:{keepMarks:true},orderedList:{keepMarks:true},heading:{levels:[1,2,3,4]}})];export{r as Preset};
@@ -1,594 +1,3 @@
1
- 'use strict';
2
-
3
- var react = require('@tiptap/react');
4
- var StarterKit = require('@tiptap/starter-kit');
5
- var clsx = require('clsx');
6
- var tailwindMerge = require('tailwind-merge');
7
- var menus = require('@tiptap/react/menus');
8
- var React = require('react');
9
- var jsxRuntime = require('react/jsx-runtime');
10
- var TooltipPrimitive = require('@radix-ui/react-tooltip');
11
- var iconsReact = require('@tabler/icons-react');
12
- var Dropdown = require('@radix-ui/react-dropdown-menu');
13
-
14
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
15
-
16
- function _interopNamespace(e) {
17
- if (e && e.__esModule) return e;
18
- var n = Object.create(null);
19
- if (e) {
20
- Object.keys(e).forEach(function (k) {
21
- if (k !== 'default') {
22
- var d = Object.getOwnPropertyDescriptor(e, k);
23
- Object.defineProperty(n, k, d.get ? d : {
24
- enumerable: true,
25
- get: function () { return e[k]; }
26
- });
27
- }
28
- });
29
- }
30
- n.default = e;
31
- return Object.freeze(n);
32
- }
33
-
34
- var StarterKit__default = /*#__PURE__*/_interopDefault(StarterKit);
35
- var React__default = /*#__PURE__*/_interopDefault(React);
36
- var TooltipPrimitive__namespace = /*#__PURE__*/_interopNamespace(TooltipPrimitive);
37
- var Dropdown__namespace = /*#__PURE__*/_interopNamespace(Dropdown);
38
-
39
- // src/react/Editor.tsx
40
- var Preset = [
41
- StarterKit__default.default.configure({
42
- bulletList: { keepMarks: true },
43
- orderedList: { keepMarks: true },
44
- heading: { levels: [1, 2, 3, 4] }
45
- })
46
- ];
47
- function cn(...inputs) {
48
- return tailwindMerge.twMerge(clsx.clsx(inputs));
49
- }
50
- var Surface = React.forwardRef(
51
- ({ children, className, withShadow = true, withBorder = true, ...props }, ref) => {
52
- const surfaceClass = cn(
53
- className,
54
- "nph-surface",
55
- withShadow ? "nph-surface--shadow" : "",
56
- withBorder ? "nph-surface--border" : ""
57
- );
58
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: surfaceClass, ...props, ref, children });
59
- }
60
- );
61
- Surface.displayName = "Surface";
62
- var Button = React__default.default.forwardRef(
63
- ({
64
- active,
65
- buttonSize = "medium",
66
- children,
67
- disabled,
68
- variant = "primary",
69
- className,
70
- activeClassname,
71
- ...rest
72
- }, ref) => {
73
- const buttonClassName = cn(
74
- "nph-btn",
75
- variant === "primary" && "nph-btn--primary",
76
- variant === "secondary" && "nph-btn--secondary",
77
- variant === "tertiary" && "nph-btn--tertiary",
78
- variant === "ghost" && "nph-btn--ghost",
79
- active && cn("nph-btn--active", activeClassname),
80
- buttonSize === "medium" && "nph-btn--md",
81
- buttonSize === "small" && "nph-btn--sm",
82
- buttonSize === "icon" && "nph-btn--icon",
83
- buttonSize === "iconSmall" && "nph-btn--icon-sm",
84
- className
85
- );
86
- return /* @__PURE__ */ jsxRuntime.jsx(
87
- "button",
88
- {
89
- ref,
90
- disabled,
91
- className: buttonClassName,
92
- ...rest,
93
- children
94
- }
95
- );
96
- }
97
- );
98
- Button.displayName = "Button";
99
- var isMac = typeof window !== "undefined" ? navigator.userAgent.toLowerCase().includes("mac") : false;
100
- var ShortcutKey = ({ children }) => {
101
- const className = "nph-kbd";
102
- if (children === "Mod") {
103
- return /* @__PURE__ */ jsxRuntime.jsx("kbd", { className, children: isMac ? "\u2318" : "Ctrl" });
104
- }
105
- if (children === "Shift") {
106
- return /* @__PURE__ */ jsxRuntime.jsx("kbd", { className, children: "\u21E7" });
107
- }
108
- if (children === "Alt") {
109
- return /* @__PURE__ */ jsxRuntime.jsx("kbd", { className, children: isMac ? "\u2325" : "Alt" });
110
- }
111
- return /* @__PURE__ */ jsxRuntime.jsx("kbd", { className, children });
112
- };
113
- var Tooltip = ({
114
- children,
115
- enabled = true,
116
- title,
117
- shortcut,
118
- className
119
- }) => {
120
- if (!enabled) {
121
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
122
- }
123
- return /* @__PURE__ */ jsxRuntime.jsx(TooltipPrimitive__namespace.Provider, { delayDuration: 500, children: /* @__PURE__ */ jsxRuntime.jsxs(TooltipPrimitive__namespace.Root, { children: [
124
- /* @__PURE__ */ jsxRuntime.jsx(TooltipPrimitive__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { children }) }),
125
- /* @__PURE__ */ jsxRuntime.jsx(TooltipPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
126
- TooltipPrimitive__namespace.Content,
127
- {
128
- sideOffset: 8,
129
- className: cn("nph-tooltip", className),
130
- children: [
131
- title && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "nph-tooltip-title", children: title }),
132
- shortcut && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "nph-tooltip-shortcut", children: shortcut.map((shortcutKey) => /* @__PURE__ */ jsxRuntime.jsx(ShortcutKey, { children: shortcutKey }, shortcutKey)) })
133
- ]
134
- }
135
- ) })
136
- ] }) });
137
- };
138
- var Tooltip_default = Tooltip;
139
- var ToolbarWrapper = React.forwardRef(
140
- ({
141
- shouldShowContent = true,
142
- children,
143
- isVertical = false,
144
- className,
145
- ...rest
146
- }, ref) => {
147
- const toolbarClassName = cn(
148
- "nph-toolbar",
149
- isVertical ? "nph-toolbar--vertical" : "nph-toolbar--horizontal",
150
- className
151
- );
152
- return shouldShowContent && /* @__PURE__ */ jsxRuntime.jsx(Surface, { className: toolbarClassName, ...rest, ref, children });
153
- }
154
- );
155
- ToolbarWrapper.displayName = "Toolbar";
156
- var ToolbarDivider = React.forwardRef(
157
- ({ horizontal, className, ...rest }, ref) => {
158
- const dividerClassName = cn(
159
- "nph-toolbar-divider",
160
- horizontal ? "nph-toolbar-divider--horizontal" : "nph-toolbar-divider--vertical",
161
- className
162
- );
163
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: dividerClassName, ref, ...rest });
164
- }
165
- );
166
- ToolbarDivider.displayName = "Toolbar.Divider";
167
- var ToolbarButton = React.forwardRef(
168
- ({
169
- children,
170
- buttonSize = "icon",
171
- variant = "ghost",
172
- className,
173
- tooltip,
174
- tooltipShortcut,
175
- activeClassname,
176
- ...rest
177
- }, ref) => {
178
- const buttonClass = cn("nph-toolbar-button", className);
179
- const content = /* @__PURE__ */ jsxRuntime.jsx(
180
- Button,
181
- {
182
- activeClassname,
183
- className: buttonClass,
184
- variant,
185
- buttonSize,
186
- ref,
187
- ...rest,
188
- children
189
- }
190
- );
191
- if (tooltip) {
192
- return /* @__PURE__ */ jsxRuntime.jsx(Tooltip_default, { title: tooltip, shortcut: tooltipShortcut, children: content });
193
- }
194
- return content;
195
- }
196
- );
197
- ToolbarButton.displayName = "ToolbarButton";
198
- var Toolbar = {
199
- Wrapper: ToolbarWrapper,
200
- Button: ToolbarButton
201
- };
202
- var Icon = React.memo(({ name, className, strokeWidth }) => {
203
- const IconComponent = iconsReact.icons[name];
204
- if (!IconComponent) {
205
- return null;
206
- }
207
- return /* @__PURE__ */ jsxRuntime.jsx(
208
- IconComponent,
209
- {
210
- className: cn("nph-icon", className),
211
- strokeWidth: strokeWidth || 2.5
212
- }
213
- );
214
- });
215
- Icon.displayName = "Icon";
216
- var DropdownCategoryTitle = ({
217
- children
218
- }) => {
219
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "nph-dropdown-title", children });
220
- };
221
- var DropdownButton = React__default.default.forwardRef(function DropdownButtonInner({ children, isActive, onClick, disabled, className }, ref) {
222
- const buttonClass = cn("nph-dropdown-button", className);
223
- return /* @__PURE__ */ jsxRuntime.jsx(
224
- "button",
225
- {
226
- className: buttonClass,
227
- disabled,
228
- "data-active": isActive ? "true" : void 0,
229
- onClick,
230
- ref,
231
- children
232
- }
233
- );
234
- });
235
- var isOption = (option) => option.type === "option";
236
- var isCategory = (option) => option.type === "category";
237
- var ContentTypePicker = ({ options }) => {
238
- const activeItem = React.useMemo(
239
- () => options.find((option) => option.type === "option" && option.isActive()),
240
- [options]
241
- );
242
- return /* @__PURE__ */ jsxRuntime.jsxs(Dropdown__namespace.Root, { modal: false, children: [
243
- /* @__PURE__ */ jsxRuntime.jsx(Dropdown__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Toolbar.Button, { buttonSize: "small", children: [
244
- /* @__PURE__ */ jsxRuntime.jsx(
245
- Icon,
246
- {
247
- name: activeItem?.type === "option" && activeItem.icon || "IconPilcrow"
248
- }
249
- ),
250
- /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "IconChevronDown", className: "nph-icon", strokeWidth: 3 })
251
- ] }) }),
252
- /* @__PURE__ */ jsxRuntime.jsx(
253
- Dropdown__namespace.Content,
254
- {
255
- side: "bottom",
256
- align: "start",
257
- alignOffset: -6,
258
- sideOffset: 9,
259
- avoidCollisions: false,
260
- asChild: true,
261
- children: /* @__PURE__ */ jsxRuntime.jsx(Surface, { className: "nph-menu-panel", children: options.map((option) => {
262
- if (isOption(option)) {
263
- return /* @__PURE__ */ jsxRuntime.jsxs(
264
- DropdownButton,
265
- {
266
- onClick: option.onClick,
267
- isActive: option.isActive(),
268
- children: [
269
- /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: option.icon, className: "nph-icon nph-mr-1" }),
270
- option.label
271
- ]
272
- },
273
- option.id
274
- );
275
- } else if (isCategory(option)) {
276
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "nph-category-gap", children: /* @__PURE__ */ jsxRuntime.jsx(DropdownCategoryTitle, { children: option.label }, option.id) }, option.id);
277
- }
278
- }) })
279
- }
280
- )
281
- ] });
282
- };
283
- var useTextmenuContentTypes = (editor) => {
284
- return react.useEditorState({
285
- editor,
286
- selector: (ctx) => [
287
- {
288
- type: "category",
289
- label: "Hierarchy",
290
- id: "hierarchy"
291
- },
292
- {
293
- icon: "IconPilcrow",
294
- onClick: () => ctx.editor.chain().focus().command(({ commands }) => {
295
- try {
296
- commands.lift("taskItem");
297
- } catch {
298
- }
299
- try {
300
- commands.liftListItem("listItem");
301
- } catch {
302
- }
303
- return true;
304
- }).setParagraph().run(),
305
- id: "paragraph",
306
- disabled: () => !ctx.editor.can().setParagraph(),
307
- isActive: () => ctx.editor.isActive("paragraph") && !ctx.editor.isActive("orderedList") && !ctx.editor.isActive("bulletList") && !ctx.editor.isActive("taskList"),
308
- label: "Paragraph",
309
- type: "option"
310
- },
311
- {
312
- icon: "IconH1",
313
- onClick: () => ctx.editor.chain().focus().command(({ commands }) => {
314
- try {
315
- commands.lift("taskItem");
316
- } catch {
317
- }
318
- try {
319
- commands.liftListItem("listItem");
320
- } catch {
321
- }
322
- return true;
323
- }).setHeading({ level: 1 }).run(),
324
- id: "heading1",
325
- disabled: () => !ctx.editor.can().setHeading({ level: 1 }),
326
- isActive: () => ctx.editor.isActive("heading", { level: 1 }),
327
- label: "Heading 1",
328
- type: "option"
329
- },
330
- {
331
- icon: "IconH2",
332
- onClick: () => ctx.editor.chain().focus().command(({ commands }) => {
333
- try {
334
- commands.lift("taskItem");
335
- } catch {
336
- }
337
- try {
338
- commands.liftListItem("listItem");
339
- } catch {
340
- }
341
- return true;
342
- }).setHeading({ level: 2 }).run(),
343
- id: "heading2",
344
- disabled: () => !ctx.editor.can().setHeading({ level: 2 }),
345
- isActive: () => ctx.editor.isActive("heading", { level: 2 }),
346
- label: "Heading 2",
347
- type: "option"
348
- },
349
- {
350
- icon: "IconH3",
351
- onClick: () => ctx.editor.chain().focus().command(({ commands }) => {
352
- try {
353
- commands.lift("taskItem");
354
- } catch {
355
- }
356
- try {
357
- commands.liftListItem("listItem");
358
- } catch {
359
- }
360
- return true;
361
- }).setHeading({ level: 3 }).run(),
362
- id: "heading3",
363
- disabled: () => !ctx.editor.can().setHeading({ level: 3 }),
364
- isActive: () => ctx.editor.isActive("heading", { level: 3 }),
365
- label: "Heading 3",
366
- type: "option"
367
- },
368
- {
369
- type: "category",
370
- label: "Lists",
371
- id: "lists"
372
- },
373
- {
374
- icon: "IconList",
375
- onClick: () => ctx.editor.chain().focus().toggleBulletList().run(),
376
- id: "bulletList",
377
- disabled: () => !ctx.editor.can().toggleBulletList(),
378
- isActive: () => ctx.editor.isActive("bulletList"),
379
- label: "Bullet list",
380
- type: "option"
381
- },
382
- {
383
- icon: "IconListNumbers",
384
- onClick: () => ctx.editor.chain().focus().toggleOrderedList().run(),
385
- id: "orderedList",
386
- disabled: () => !ctx.editor.can().toggleOrderedList(),
387
- isActive: () => ctx.editor.isActive("orderedList") && !ctx.editor.isActive("orderedList", { class: "styled-list" }),
388
- label: "Numbered list",
389
- type: "option"
390
- }
391
- // {
392
- // icon: "ListOrdered",
393
- // onClick: () => ctx.editor.chain().focus().toggleOrderedList({ class: "styled-list" }).run(),
394
- // id: "styledOrderedList",
395
- // disabled: () => !ctx.editor.can().toggleOrderedList(),
396
- // isActive: () => ctx.editor.isActive("orderedList", { class: "styled-list" }),
397
- // label: "Styled numbered list",
398
- // type: "option",
399
- // },
400
- // {
401
- // icon: "ListTodo",
402
- // onClick: () => ctx.editor.chain().focus().toggleTaskList().run(),
403
- // id: "todoList",
404
- // disabled: () => !ctx.editor.can().toggleTaskList(),
405
- // isActive: () => ctx.editor.isActive("taskList"),
406
- // label: "Todo list",
407
- // type: "option",
408
- // },
409
- ]
410
- });
411
- };
412
- var useTextmenuCommands = (editor, sourceId, sourceType) => {
413
- const onBold = React.useCallback(
414
- () => editor.chain().focus().toggleBold().run(),
415
- [editor]
416
- );
417
- const onItalic = React.useCallback(
418
- () => editor.chain().focus().toggleItalic().run(),
419
- [editor]
420
- );
421
- const onStrike = React.useCallback(
422
- () => editor.chain().focus().toggleStrike().run(),
423
- [editor]
424
- );
425
- const onCode = React.useCallback(
426
- () => editor.chain().focus().toggleCode().run(),
427
- [editor]
428
- );
429
- const onCodeBlock = React.useCallback(
430
- () => editor.chain().focus().toggleCodeBlock().run(),
431
- [editor]
432
- );
433
- const onLink = React.useCallback(() => {
434
- if (editor.isActive("link")) {
435
- window.dispatchEvent(new CustomEvent("editor:link"));
436
- return;
437
- }
438
- if (editor.state.selection.empty) {
439
- try {
440
- editor.commands.selectTextblockEnd();
441
- } catch {
442
- }
443
- }
444
- window.dispatchEvent(new CustomEvent("editor:link"));
445
- }, [editor]);
446
- React.useCallback(() => {
447
- const { from, to } = editor.state.selection;
448
- const selectedText = editor.state.doc.textBetween(from, to, "\n");
449
- const lines = selectedText.split("\n");
450
- const firstLine = lines[0].trim() || "Untitled";
451
- let title = firstLine;
452
- const content = `<p>${selectedText.replace(/\n\n/g, "</p><p>").replace(/\n/g, "<br />")}</p>`;
453
- return { title, content };
454
- }, [editor, sourceId, sourceType]);
455
- return {
456
- onBold,
457
- onItalic,
458
- onStrike,
459
- // onUnderline,
460
- onCode,
461
- onCodeBlock,
462
- // onSubscript,
463
- // onSuperscript,
464
- // onAlignLeft,
465
- // onAlignCenter,
466
- // onAlignRight,
467
- // onAlignJustify,
468
- // onChangeColor,
469
- // onClearColor,
470
- // onChangeHighlight,
471
- // onClearHighlight,
472
- // onSetFont,
473
- // onSetFontSize,
474
- onLink
475
- };
476
- };
477
- var useTextmenuStates = (editor) => {
478
- const states = react.useEditorState({
479
- editor,
480
- selector: (ctx) => {
481
- return {
482
- isBold: ctx.editor.isActive("bold"),
483
- isItalic: ctx.editor.isActive("italic"),
484
- isStrike: ctx.editor.isActive("strike"),
485
- isUnderline: ctx.editor.isActive("underline"),
486
- isCode: ctx.editor.isActive("code"),
487
- isSubscript: ctx.editor.isActive("subscript"),
488
- isSuperscript: ctx.editor.isActive("superscript"),
489
- isAlignLeft: ctx.editor.isActive({ textAlign: "left" }),
490
- isAlignCenter: ctx.editor.isActive({ textAlign: "center" }),
491
- isAlignRight: ctx.editor.isActive({ textAlign: "right" }),
492
- isAlignJustify: ctx.editor.isActive({ textAlign: "justify" }),
493
- isLink: ctx.editor.isActive("link"),
494
- currentColor: ctx.editor.getAttributes("textStyle")?.color || void 0,
495
- currentHighlight: ctx.editor.getAttributes("highlight")?.color || void 0,
496
- currentFont: ctx.editor.getAttributes("textStyle")?.fontFamily || void 0,
497
- currentSize: ctx.editor.getAttributes("textStyle")?.fontSize || void 0
498
- };
499
- }
500
- });
501
- return {
502
- ...states
503
- };
504
- };
505
- var MemoButton = React.memo(Toolbar.Button);
506
- var MemoContentTypePicker = React.memo(ContentTypePicker);
507
- function Selection() {
508
- const { editor } = react.useCurrentEditor();
509
- if (!editor) return null;
510
- const commands = useTextmenuCommands(editor);
511
- const states = useTextmenuStates(editor);
512
- const blockOptions = useTextmenuContentTypes(editor);
513
- return /* @__PURE__ */ jsxRuntime.jsx(
514
- menus.BubbleMenu,
515
- {
516
- editor,
517
- options: { placement: "top" },
518
- shouldShow: ({ editor: editor2, from, to }) => {
519
- if (from === to) return false;
520
- if (editor2.isActive("codeBlock")) return false;
521
- return true;
522
- },
523
- className: "nph-bubble",
524
- children: /* @__PURE__ */ jsxRuntime.jsxs(Toolbar.Wrapper, { children: [
525
- /* @__PURE__ */ jsxRuntime.jsx(MemoContentTypePicker, { options: blockOptions }),
526
- /* @__PURE__ */ jsxRuntime.jsx(
527
- MemoButton,
528
- {
529
- tooltip: "Bold",
530
- tooltipShortcut: ["Mod", "B"],
531
- onClick: commands.onBold,
532
- active: states.isBold,
533
- children: /* @__PURE__ */ jsxRuntime.jsx(iconsReact.IconBold, { className: "nph-icon" })
534
- }
535
- ),
536
- /* @__PURE__ */ jsxRuntime.jsx(
537
- MemoButton,
538
- {
539
- tooltip: "Italic",
540
- tooltipShortcut: ["Mod", "I"],
541
- onClick: commands.onItalic,
542
- active: states.isItalic,
543
- children: /* @__PURE__ */ jsxRuntime.jsx(iconsReact.IconItalic, { className: "nph-icon" })
544
- }
545
- )
546
- ] })
547
- }
548
- );
549
- }
550
- function Editor3({
551
- className,
552
- editorContainerProps,
553
- extensions = [],
554
- content,
555
- onUpdate,
556
- editorProps,
557
- editable = true,
558
- showSelectionMenu = true,
559
- selectionMenu,
560
- immediatelyRender = false,
561
- children,
562
- ...rest
563
- }) {
564
- const mergedContainerProps = {
565
- ...editorContainerProps,
566
- className: cn("nph-editor", className)
567
- };
568
- const mergedEditorProps = {
569
- ...editorProps,
570
- attributes: {
571
- ...editorProps?.attributes,
572
- ...!editable ? { "aria-disabled": "true", "data-disabled": "true" } : {}
573
- }
574
- };
575
- return /* @__PURE__ */ jsxRuntime.jsxs(
576
- react.EditorProvider,
577
- {
578
- content,
579
- extensions: [...Preset, ...extensions ?? []],
580
- onUpdate,
581
- editorProps: mergedEditorProps,
582
- editable,
583
- editorContainerProps: mergedContainerProps,
584
- immediatelyRender,
585
- ...rest,
586
- children: [
587
- showSelectionMenu && (selectionMenu ?? /* @__PURE__ */ jsxRuntime.jsx(Selection, {})),
588
- children
589
- ]
590
- }
591
- );
592
- }
593
-
594
- exports.Editor = Editor3;
1
+ 'use strict';var react=require('@tiptap/react'),q=require('@tiptap/starter-kit'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),menus=require('@tiptap/react/menus'),_=require('react'),jsxRuntime=require('react/jsx-runtime'),c=require('@radix-ui/react-tooltip'),iconsReact=require('@tabler/icons-react'),h=require('@radix-ui/react-dropdown-menu');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var q__default=/*#__PURE__*/_interopDefault(q);var ___default=/*#__PURE__*/_interopDefault(_);var c__namespace=/*#__PURE__*/_interopNamespace(c);var h__namespace=/*#__PURE__*/_interopNamespace(h);var w=[q__default.default.configure({bulletList:{keepMarks:true},orderedList:{keepMarks:true},heading:{levels:[1,2,3,4]}})];function s(...e){return tailwindMerge.twMerge(clsx.clsx(e))}var v=_.forwardRef(({children:e,className:o,withShadow:t=true,withBorder:i=true,...r},n)=>{let a=s(o,"nph-surface",t?"nph-surface--shadow":"",i?"nph-surface--border":"");return jsxRuntime.jsx("div",{className:a,...r,ref:n,children:e})});v.displayName="Surface";var A=___default.default.forwardRef(({active:e,buttonSize:o="medium",children:t,disabled:i,variant:r="primary",className:n,activeClassname:a,...p},m)=>{let f=s("nph-btn",r==="primary"&&"nph-btn--primary",r==="secondary"&&"nph-btn--secondary",r==="tertiary"&&"nph-btn--tertiary",r==="ghost"&&"nph-btn--ghost",e&&s("nph-btn--active",a),o==="medium"&&"nph-btn--md",o==="small"&&"nph-btn--sm",o==="icon"&&"nph-btn--icon",o==="iconSmall"&&"nph-btn--icon-sm",n);return jsxRuntime.jsx("button",{ref:m,disabled:i,className:f,...p,children:t})});A.displayName="Button";var M=typeof window<"u"?navigator.userAgent.toLowerCase().includes("mac"):false,tt=({children:e})=>{let o="nph-kbd";return e==="Mod"?jsxRuntime.jsx("kbd",{className:o,children:M?"\u2318":"Ctrl"}):e==="Shift"?jsxRuntime.jsx("kbd",{className:o,children:"\u21E7"}):e==="Alt"?jsxRuntime.jsx("kbd",{className:o,children:M?"\u2325":"Alt"}):jsxRuntime.jsx("kbd",{className:o,children:e})},et=({children:e,enabled:o=true,title:t,shortcut:i,className:r})=>o?jsxRuntime.jsx(c__namespace.Provider,{delayDuration:500,children:jsxRuntime.jsxs(c__namespace.Root,{children:[jsxRuntime.jsx(c__namespace.Trigger,{asChild:true,children:jsxRuntime.jsx("span",{children:e})}),jsxRuntime.jsx(c__namespace.Portal,{children:jsxRuntime.jsxs(c__namespace.Content,{sideOffset:8,className:s("nph-tooltip",r),children:[t&&jsxRuntime.jsx("span",{className:"nph-tooltip-title",children:t}),i&&jsxRuntime.jsx("span",{className:"nph-tooltip-shortcut",children:i.map(n=>jsxRuntime.jsx(tt,{children:n},n))})]})})]})}):jsxRuntime.jsx(jsxRuntime.Fragment,{children:e}),H=et;var D=_.forwardRef(({shouldShowContent:e=true,children:o,isVertical:t=false,className:i,...r},n)=>{let a=s("nph-toolbar",t?"nph-toolbar--vertical":"nph-toolbar--horizontal",i);return e&&jsxRuntime.jsx(v,{className:a,...r,ref:n,children:o})});D.displayName="Toolbar";var R=_.forwardRef(({horizontal:e,className:o,...t},i)=>{let r=s("nph-toolbar-divider",e?"nph-toolbar-divider--horizontal":"nph-toolbar-divider--vertical",o);return jsxRuntime.jsx("div",{className:r,ref:i,...t})});R.displayName="Toolbar.Divider";var O=_.forwardRef(({children:e,buttonSize:o="icon",variant:t="ghost",className:i,tooltip:r,tooltipShortcut:n,activeClassname:a,...p},m)=>{let f=s("nph-toolbar-button",i),b=jsxRuntime.jsx(A,{activeClassname:a,className:f,variant:t,buttonSize:o,ref:m,...p,children:e});return r?jsxRuntime.jsx(H,{title:r,shortcut:n,children:b}):b});O.displayName="ToolbarButton";var y={Wrapper:D,Button:O};var dt={IconPilcrow:iconsReact.IconPilcrow,IconChevronDown:iconsReact.IconChevronDown,IconH1:iconsReact.IconH1,IconH2:iconsReact.IconH2,IconH3:iconsReact.IconH3,IconList:iconsReact.IconList,IconListNumbers:iconsReact.IconListNumbers},C=_.memo(({name:e,className:o,strokeWidth:t})=>{let i=dt[e];return i?jsxRuntime.jsx(i,{className:s("nph-icon",o),strokeWidth:t||2.5}):null});C.displayName="Icon";var z=({children:e})=>jsxRuntime.jsx("div",{className:"nph-dropdown-title",children:e}),W=___default.default.forwardRef(function({children:o,isActive:t,onClick:i,disabled:r,className:n},a){let p=s("nph-dropdown-button",n);return jsxRuntime.jsx("button",{className:p,disabled:r,"data-active":t?"true":void 0,onClick:i,ref:a,children:o})});var bt=e=>e.type==="option",ht=e=>e.type==="category",V=({options:e})=>{let o=_.useMemo(()=>e.find(t=>t.type==="option"&&t.isActive()),[e]);return jsxRuntime.jsxs(h__namespace.Root,{modal:false,children:[jsxRuntime.jsx(h__namespace.Trigger,{asChild:true,children:jsxRuntime.jsxs(y.Button,{buttonSize:"small",children:[jsxRuntime.jsx(C,{name:o?.type==="option"&&o.icon||"IconPilcrow"}),jsxRuntime.jsx(C,{name:"IconChevronDown",className:"nph-icon",strokeWidth:3})]})}),jsxRuntime.jsx(h__namespace.Content,{side:"bottom",align:"start",alignOffset:-6,sideOffset:9,avoidCollisions:false,asChild:true,children:jsxRuntime.jsx(v,{className:"nph-menu-panel",children:e.map(t=>{if(bt(t))return jsxRuntime.jsxs(W,{onClick:t.onClick,isActive:t.isActive(),children:[jsxRuntime.jsx(C,{name:t.icon,className:"nph-icon nph-mr-1"}),t.label]},t.id);if(ht(t))return jsxRuntime.jsx("div",{className:"nph-category-gap",children:jsxRuntime.jsx(z,{children:t.label},t.id)},t.id)})})})]})};var J=e=>react.useEditorState({editor:e,selector:o=>[{type:"category",label:"Hierarchy",id:"hierarchy"},{icon:"IconPilcrow",onClick:()=>o.editor.chain().focus().command(({commands:t})=>{try{t.lift("taskItem");}catch{}try{t.liftListItem("listItem");}catch{}return true}).setParagraph().run(),id:"paragraph",disabled:()=>!o.editor.can().setParagraph(),isActive:()=>o.editor.isActive("paragraph")&&!o.editor.isActive("orderedList")&&!o.editor.isActive("bulletList")&&!o.editor.isActive("taskList"),label:"Paragraph",type:"option"},{icon:"IconH1",onClick:()=>o.editor.chain().focus().command(({commands:t})=>{try{t.lift("taskItem");}catch{}try{t.liftListItem("listItem");}catch{}return true}).setHeading({level:1}).run(),id:"heading1",disabled:()=>!o.editor.can().setHeading({level:1}),isActive:()=>o.editor.isActive("heading",{level:1}),label:"Heading 1",type:"option"},{icon:"IconH2",onClick:()=>o.editor.chain().focus().command(({commands:t})=>{try{t.lift("taskItem");}catch{}try{t.liftListItem("listItem");}catch{}return true}).setHeading({level:2}).run(),id:"heading2",disabled:()=>!o.editor.can().setHeading({level:2}),isActive:()=>o.editor.isActive("heading",{level:2}),label:"Heading 2",type:"option"},{icon:"IconH3",onClick:()=>o.editor.chain().focus().command(({commands:t})=>{try{t.lift("taskItem");}catch{}try{t.liftListItem("listItem");}catch{}return true}).setHeading({level:3}).run(),id:"heading3",disabled:()=>!o.editor.can().setHeading({level:3}),isActive:()=>o.editor.isActive("heading",{level:3}),label:"Heading 3",type:"option"},{type:"category",label:"Lists",id:"lists"},{icon:"IconList",onClick:()=>o.editor.chain().focus().toggleBulletList().run(),id:"bulletList",disabled:()=>!o.editor.can().toggleBulletList(),isActive:()=>o.editor.isActive("bulletList"),label:"Bullet list",type:"option"},{icon:"IconListNumbers",onClick:()=>o.editor.chain().focus().toggleOrderedList().run(),id:"orderedList",disabled:()=>!o.editor.can().toggleOrderedList(),isActive:()=>o.editor.isActive("orderedList")&&!o.editor.isActive("orderedList",{class:"styled-list"}),label:"Numbered list",type:"option"}]});var U=(e,o,t)=>{let i=_.useCallback(()=>e.chain().focus().toggleBold().run(),[e]),r=_.useCallback(()=>e.chain().focus().toggleItalic().run(),[e]),n=_.useCallback(()=>e.chain().focus().toggleStrike().run(),[e]),a=_.useCallback(()=>e.chain().focus().toggleCode().run(),[e]),p=_.useCallback(()=>e.chain().focus().toggleCodeBlock().run(),[e]),m=_.useCallback(()=>{if(e.isActive("link")){window.dispatchEvent(new CustomEvent("editor:link"));return}if(e.state.selection.empty)try{e.commands.selectTextblockEnd();}catch{}window.dispatchEvent(new CustomEvent("editor:link"));},[e]);_.useCallback(()=>{let{from:b,to:k}=e.state.selection,T=e.state.doc.textBetween(b,k,`
2
+ `),S=T.split(`
3
+ `)[0].trim()||"Untitled";let K=`<p>${T.replace(/\n\n/g,"</p><p>").replace(/\n/g,"<br />")}</p>`;return {title:S,content:K}},[e,o,t]);return {onBold:i,onItalic:r,onStrike:n,onCode:a,onCodeBlock:p,onLink:m}};var X=e=>({...react.useEditorState({editor:e,selector:t=>({isBold:t.editor.isActive("bold"),isItalic:t.editor.isActive("italic"),isStrike:t.editor.isActive("strike"),isUnderline:t.editor.isActive("underline"),isCode:t.editor.isActive("code"),isSubscript:t.editor.isActive("subscript"),isSuperscript:t.editor.isActive("superscript"),isAlignLeft:t.editor.isActive({textAlign:"left"}),isAlignCenter:t.editor.isActive({textAlign:"center"}),isAlignRight:t.editor.isActive({textAlign:"right"}),isAlignJustify:t.editor.isActive({textAlign:"justify"}),isLink:t.editor.isActive("link"),currentColor:t.editor.getAttributes("textStyle")?.color||void 0,currentHighlight:t.editor.getAttributes("highlight")?.color||void 0,currentFont:t.editor.getAttributes("textStyle")?.fontFamily||void 0,currentSize:t.editor.getAttributes("textStyle")?.fontSize||void 0})})});var $=_.memo(y.Button),kt=_.memo(V);function N(){let{editor:e}=react.useCurrentEditor();if(!e)return null;let o=U(e),t=X(e),i=J(e);return jsxRuntime.jsx(menus.BubbleMenu,{editor:e,options:{placement:"top"},shouldShow:({editor:r,from:n,to:a})=>!(n===a||r.isActive("codeBlock")),className:"nph-bubble",children:jsxRuntime.jsxs(y.Wrapper,{children:[jsxRuntime.jsx(kt,{options:i}),jsxRuntime.jsx($,{tooltip:"Bold",tooltipShortcut:["Mod","B"],onClick:o.onBold,active:t.isBold,children:jsxRuntime.jsx(iconsReact.IconBold,{className:"nph-icon"})}),jsxRuntime.jsx($,{tooltip:"Italic",tooltipShortcut:["Mod","I"],onClick:o.onItalic,active:t.isItalic,children:jsxRuntime.jsx(iconsReact.IconItalic,{className:"nph-icon"})})]})})}function Xe({className:e,editorContainerProps:o,extensions:t=[],content:i,onUpdate:r,editorProps:n,editable:a=true,showSelectionMenu:p=true,selectionMenu:m,immediatelyRender:f=false,children:b,...k}){let T={...o,className:s("nph-editor",e)},I={...n,attributes:{...n?.attributes,...a?{}:{"aria-disabled":"true","data-disabled":"true"}}};return jsxRuntime.jsxs(react.EditorProvider,{content:i,extensions:[...w,...t??[]],onUpdate:r,editorProps:I,editable:a,editorContainerProps:T,immediatelyRender:f,...k,children:[p&&(m??jsxRuntime.jsx(N,{})),b]})}exports.Editor=Xe;
@@ -1,559 +1,3 @@
1
- import { Preset } from '../chunk-SWNQOIUA.js';
2
- import { EditorProvider, useCurrentEditor, useEditorState } from '@tiptap/react';
3
- import { clsx } from 'clsx';
4
- import { twMerge } from 'tailwind-merge';
5
- import { BubbleMenu } from '@tiptap/react/menus';
6
- import React, { forwardRef, memo, useMemo, useCallback } from 'react';
7
- import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
8
- import * as TooltipPrimitive from '@radix-ui/react-tooltip';
9
- import { icons, IconBold, IconItalic } from '@tabler/icons-react';
10
- import * as Dropdown from '@radix-ui/react-dropdown-menu';
11
-
12
- function cn(...inputs) {
13
- return twMerge(clsx(inputs));
14
- }
15
- var Surface = forwardRef(
16
- ({ children, className, withShadow = true, withBorder = true, ...props }, ref) => {
17
- const surfaceClass = cn(
18
- className,
19
- "nph-surface",
20
- withShadow ? "nph-surface--shadow" : "",
21
- withBorder ? "nph-surface--border" : ""
22
- );
23
- return /* @__PURE__ */ jsx("div", { className: surfaceClass, ...props, ref, children });
24
- }
25
- );
26
- Surface.displayName = "Surface";
27
- var Button = React.forwardRef(
28
- ({
29
- active,
30
- buttonSize = "medium",
31
- children,
32
- disabled,
33
- variant = "primary",
34
- className,
35
- activeClassname,
36
- ...rest
37
- }, ref) => {
38
- const buttonClassName = cn(
39
- "nph-btn",
40
- variant === "primary" && "nph-btn--primary",
41
- variant === "secondary" && "nph-btn--secondary",
42
- variant === "tertiary" && "nph-btn--tertiary",
43
- variant === "ghost" && "nph-btn--ghost",
44
- active && cn("nph-btn--active", activeClassname),
45
- buttonSize === "medium" && "nph-btn--md",
46
- buttonSize === "small" && "nph-btn--sm",
47
- buttonSize === "icon" && "nph-btn--icon",
48
- buttonSize === "iconSmall" && "nph-btn--icon-sm",
49
- className
50
- );
51
- return /* @__PURE__ */ jsx(
52
- "button",
53
- {
54
- ref,
55
- disabled,
56
- className: buttonClassName,
57
- ...rest,
58
- children
59
- }
60
- );
61
- }
62
- );
63
- Button.displayName = "Button";
64
- var isMac = typeof window !== "undefined" ? navigator.userAgent.toLowerCase().includes("mac") : false;
65
- var ShortcutKey = ({ children }) => {
66
- const className = "nph-kbd";
67
- if (children === "Mod") {
68
- return /* @__PURE__ */ jsx("kbd", { className, children: isMac ? "\u2318" : "Ctrl" });
69
- }
70
- if (children === "Shift") {
71
- return /* @__PURE__ */ jsx("kbd", { className, children: "\u21E7" });
72
- }
73
- if (children === "Alt") {
74
- return /* @__PURE__ */ jsx("kbd", { className, children: isMac ? "\u2325" : "Alt" });
75
- }
76
- return /* @__PURE__ */ jsx("kbd", { className, children });
77
- };
78
- var Tooltip = ({
79
- children,
80
- enabled = true,
81
- title,
82
- shortcut,
83
- className
84
- }) => {
85
- if (!enabled) {
86
- return /* @__PURE__ */ jsx(Fragment, { children });
87
- }
88
- return /* @__PURE__ */ jsx(TooltipPrimitive.Provider, { delayDuration: 500, children: /* @__PURE__ */ jsxs(TooltipPrimitive.Root, { children: [
89
- /* @__PURE__ */ jsx(TooltipPrimitive.Trigger, { asChild: true, children: /* @__PURE__ */ jsx("span", { children }) }),
90
- /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
91
- TooltipPrimitive.Content,
92
- {
93
- sideOffset: 8,
94
- className: cn("nph-tooltip", className),
95
- children: [
96
- title && /* @__PURE__ */ jsx("span", { className: "nph-tooltip-title", children: title }),
97
- shortcut && /* @__PURE__ */ jsx("span", { className: "nph-tooltip-shortcut", children: shortcut.map((shortcutKey) => /* @__PURE__ */ jsx(ShortcutKey, { children: shortcutKey }, shortcutKey)) })
98
- ]
99
- }
100
- ) })
101
- ] }) });
102
- };
103
- var Tooltip_default = Tooltip;
104
- var ToolbarWrapper = forwardRef(
105
- ({
106
- shouldShowContent = true,
107
- children,
108
- isVertical = false,
109
- className,
110
- ...rest
111
- }, ref) => {
112
- const toolbarClassName = cn(
113
- "nph-toolbar",
114
- isVertical ? "nph-toolbar--vertical" : "nph-toolbar--horizontal",
115
- className
116
- );
117
- return shouldShowContent && /* @__PURE__ */ jsx(Surface, { className: toolbarClassName, ...rest, ref, children });
118
- }
119
- );
120
- ToolbarWrapper.displayName = "Toolbar";
121
- var ToolbarDivider = forwardRef(
122
- ({ horizontal, className, ...rest }, ref) => {
123
- const dividerClassName = cn(
124
- "nph-toolbar-divider",
125
- horizontal ? "nph-toolbar-divider--horizontal" : "nph-toolbar-divider--vertical",
126
- className
127
- );
128
- return /* @__PURE__ */ jsx("div", { className: dividerClassName, ref, ...rest });
129
- }
130
- );
131
- ToolbarDivider.displayName = "Toolbar.Divider";
132
- var ToolbarButton = forwardRef(
133
- ({
134
- children,
135
- buttonSize = "icon",
136
- variant = "ghost",
137
- className,
138
- tooltip,
139
- tooltipShortcut,
140
- activeClassname,
141
- ...rest
142
- }, ref) => {
143
- const buttonClass = cn("nph-toolbar-button", className);
144
- const content = /* @__PURE__ */ jsx(
145
- Button,
146
- {
147
- activeClassname,
148
- className: buttonClass,
149
- variant,
150
- buttonSize,
151
- ref,
152
- ...rest,
153
- children
154
- }
155
- );
156
- if (tooltip) {
157
- return /* @__PURE__ */ jsx(Tooltip_default, { title: tooltip, shortcut: tooltipShortcut, children: content });
158
- }
159
- return content;
160
- }
161
- );
162
- ToolbarButton.displayName = "ToolbarButton";
163
- var Toolbar = {
164
- Wrapper: ToolbarWrapper,
165
- Button: ToolbarButton
166
- };
167
- var Icon = memo(({ name, className, strokeWidth }) => {
168
- const IconComponent = icons[name];
169
- if (!IconComponent) {
170
- return null;
171
- }
172
- return /* @__PURE__ */ jsx(
173
- IconComponent,
174
- {
175
- className: cn("nph-icon", className),
176
- strokeWidth: strokeWidth || 2.5
177
- }
178
- );
179
- });
180
- Icon.displayName = "Icon";
181
- var DropdownCategoryTitle = ({
182
- children
183
- }) => {
184
- return /* @__PURE__ */ jsx("div", { className: "nph-dropdown-title", children });
185
- };
186
- var DropdownButton = React.forwardRef(function DropdownButtonInner({ children, isActive, onClick, disabled, className }, ref) {
187
- const buttonClass = cn("nph-dropdown-button", className);
188
- return /* @__PURE__ */ jsx(
189
- "button",
190
- {
191
- className: buttonClass,
192
- disabled,
193
- "data-active": isActive ? "true" : void 0,
194
- onClick,
195
- ref,
196
- children
197
- }
198
- );
199
- });
200
- var isOption = (option) => option.type === "option";
201
- var isCategory = (option) => option.type === "category";
202
- var ContentTypePicker = ({ options }) => {
203
- const activeItem = useMemo(
204
- () => options.find((option) => option.type === "option" && option.isActive()),
205
- [options]
206
- );
207
- return /* @__PURE__ */ jsxs(Dropdown.Root, { modal: false, children: [
208
- /* @__PURE__ */ jsx(Dropdown.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(Toolbar.Button, { buttonSize: "small", children: [
209
- /* @__PURE__ */ jsx(
210
- Icon,
211
- {
212
- name: activeItem?.type === "option" && activeItem.icon || "IconPilcrow"
213
- }
214
- ),
215
- /* @__PURE__ */ jsx(Icon, { name: "IconChevronDown", className: "nph-icon", strokeWidth: 3 })
216
- ] }) }),
217
- /* @__PURE__ */ jsx(
218
- Dropdown.Content,
219
- {
220
- side: "bottom",
221
- align: "start",
222
- alignOffset: -6,
223
- sideOffset: 9,
224
- avoidCollisions: false,
225
- asChild: true,
226
- children: /* @__PURE__ */ jsx(Surface, { className: "nph-menu-panel", children: options.map((option) => {
227
- if (isOption(option)) {
228
- return /* @__PURE__ */ jsxs(
229
- DropdownButton,
230
- {
231
- onClick: option.onClick,
232
- isActive: option.isActive(),
233
- children: [
234
- /* @__PURE__ */ jsx(Icon, { name: option.icon, className: "nph-icon nph-mr-1" }),
235
- option.label
236
- ]
237
- },
238
- option.id
239
- );
240
- } else if (isCategory(option)) {
241
- return /* @__PURE__ */ jsx("div", { className: "nph-category-gap", children: /* @__PURE__ */ jsx(DropdownCategoryTitle, { children: option.label }, option.id) }, option.id);
242
- }
243
- }) })
244
- }
245
- )
246
- ] });
247
- };
248
- var useTextmenuContentTypes = (editor) => {
249
- return useEditorState({
250
- editor,
251
- selector: (ctx) => [
252
- {
253
- type: "category",
254
- label: "Hierarchy",
255
- id: "hierarchy"
256
- },
257
- {
258
- icon: "IconPilcrow",
259
- onClick: () => ctx.editor.chain().focus().command(({ commands }) => {
260
- try {
261
- commands.lift("taskItem");
262
- } catch {
263
- }
264
- try {
265
- commands.liftListItem("listItem");
266
- } catch {
267
- }
268
- return true;
269
- }).setParagraph().run(),
270
- id: "paragraph",
271
- disabled: () => !ctx.editor.can().setParagraph(),
272
- isActive: () => ctx.editor.isActive("paragraph") && !ctx.editor.isActive("orderedList") && !ctx.editor.isActive("bulletList") && !ctx.editor.isActive("taskList"),
273
- label: "Paragraph",
274
- type: "option"
275
- },
276
- {
277
- icon: "IconH1",
278
- onClick: () => ctx.editor.chain().focus().command(({ commands }) => {
279
- try {
280
- commands.lift("taskItem");
281
- } catch {
282
- }
283
- try {
284
- commands.liftListItem("listItem");
285
- } catch {
286
- }
287
- return true;
288
- }).setHeading({ level: 1 }).run(),
289
- id: "heading1",
290
- disabled: () => !ctx.editor.can().setHeading({ level: 1 }),
291
- isActive: () => ctx.editor.isActive("heading", { level: 1 }),
292
- label: "Heading 1",
293
- type: "option"
294
- },
295
- {
296
- icon: "IconH2",
297
- onClick: () => ctx.editor.chain().focus().command(({ commands }) => {
298
- try {
299
- commands.lift("taskItem");
300
- } catch {
301
- }
302
- try {
303
- commands.liftListItem("listItem");
304
- } catch {
305
- }
306
- return true;
307
- }).setHeading({ level: 2 }).run(),
308
- id: "heading2",
309
- disabled: () => !ctx.editor.can().setHeading({ level: 2 }),
310
- isActive: () => ctx.editor.isActive("heading", { level: 2 }),
311
- label: "Heading 2",
312
- type: "option"
313
- },
314
- {
315
- icon: "IconH3",
316
- onClick: () => ctx.editor.chain().focus().command(({ commands }) => {
317
- try {
318
- commands.lift("taskItem");
319
- } catch {
320
- }
321
- try {
322
- commands.liftListItem("listItem");
323
- } catch {
324
- }
325
- return true;
326
- }).setHeading({ level: 3 }).run(),
327
- id: "heading3",
328
- disabled: () => !ctx.editor.can().setHeading({ level: 3 }),
329
- isActive: () => ctx.editor.isActive("heading", { level: 3 }),
330
- label: "Heading 3",
331
- type: "option"
332
- },
333
- {
334
- type: "category",
335
- label: "Lists",
336
- id: "lists"
337
- },
338
- {
339
- icon: "IconList",
340
- onClick: () => ctx.editor.chain().focus().toggleBulletList().run(),
341
- id: "bulletList",
342
- disabled: () => !ctx.editor.can().toggleBulletList(),
343
- isActive: () => ctx.editor.isActive("bulletList"),
344
- label: "Bullet list",
345
- type: "option"
346
- },
347
- {
348
- icon: "IconListNumbers",
349
- onClick: () => ctx.editor.chain().focus().toggleOrderedList().run(),
350
- id: "orderedList",
351
- disabled: () => !ctx.editor.can().toggleOrderedList(),
352
- isActive: () => ctx.editor.isActive("orderedList") && !ctx.editor.isActive("orderedList", { class: "styled-list" }),
353
- label: "Numbered list",
354
- type: "option"
355
- }
356
- // {
357
- // icon: "ListOrdered",
358
- // onClick: () => ctx.editor.chain().focus().toggleOrderedList({ class: "styled-list" }).run(),
359
- // id: "styledOrderedList",
360
- // disabled: () => !ctx.editor.can().toggleOrderedList(),
361
- // isActive: () => ctx.editor.isActive("orderedList", { class: "styled-list" }),
362
- // label: "Styled numbered list",
363
- // type: "option",
364
- // },
365
- // {
366
- // icon: "ListTodo",
367
- // onClick: () => ctx.editor.chain().focus().toggleTaskList().run(),
368
- // id: "todoList",
369
- // disabled: () => !ctx.editor.can().toggleTaskList(),
370
- // isActive: () => ctx.editor.isActive("taskList"),
371
- // label: "Todo list",
372
- // type: "option",
373
- // },
374
- ]
375
- });
376
- };
377
- var useTextmenuCommands = (editor, sourceId, sourceType) => {
378
- const onBold = useCallback(
379
- () => editor.chain().focus().toggleBold().run(),
380
- [editor]
381
- );
382
- const onItalic = useCallback(
383
- () => editor.chain().focus().toggleItalic().run(),
384
- [editor]
385
- );
386
- const onStrike = useCallback(
387
- () => editor.chain().focus().toggleStrike().run(),
388
- [editor]
389
- );
390
- const onCode = useCallback(
391
- () => editor.chain().focus().toggleCode().run(),
392
- [editor]
393
- );
394
- const onCodeBlock = useCallback(
395
- () => editor.chain().focus().toggleCodeBlock().run(),
396
- [editor]
397
- );
398
- const onLink = useCallback(() => {
399
- if (editor.isActive("link")) {
400
- window.dispatchEvent(new CustomEvent("editor:link"));
401
- return;
402
- }
403
- if (editor.state.selection.empty) {
404
- try {
405
- editor.commands.selectTextblockEnd();
406
- } catch {
407
- }
408
- }
409
- window.dispatchEvent(new CustomEvent("editor:link"));
410
- }, [editor]);
411
- useCallback(() => {
412
- const { from, to } = editor.state.selection;
413
- const selectedText = editor.state.doc.textBetween(from, to, "\n");
414
- const lines = selectedText.split("\n");
415
- const firstLine = lines[0].trim() || "Untitled";
416
- let title = firstLine;
417
- const content = `<p>${selectedText.replace(/\n\n/g, "</p><p>").replace(/\n/g, "<br />")}</p>`;
418
- return { title, content };
419
- }, [editor, sourceId, sourceType]);
420
- return {
421
- onBold,
422
- onItalic,
423
- onStrike,
424
- // onUnderline,
425
- onCode,
426
- onCodeBlock,
427
- // onSubscript,
428
- // onSuperscript,
429
- // onAlignLeft,
430
- // onAlignCenter,
431
- // onAlignRight,
432
- // onAlignJustify,
433
- // onChangeColor,
434
- // onClearColor,
435
- // onChangeHighlight,
436
- // onClearHighlight,
437
- // onSetFont,
438
- // onSetFontSize,
439
- onLink
440
- };
441
- };
442
- var useTextmenuStates = (editor) => {
443
- const states = useEditorState({
444
- editor,
445
- selector: (ctx) => {
446
- return {
447
- isBold: ctx.editor.isActive("bold"),
448
- isItalic: ctx.editor.isActive("italic"),
449
- isStrike: ctx.editor.isActive("strike"),
450
- isUnderline: ctx.editor.isActive("underline"),
451
- isCode: ctx.editor.isActive("code"),
452
- isSubscript: ctx.editor.isActive("subscript"),
453
- isSuperscript: ctx.editor.isActive("superscript"),
454
- isAlignLeft: ctx.editor.isActive({ textAlign: "left" }),
455
- isAlignCenter: ctx.editor.isActive({ textAlign: "center" }),
456
- isAlignRight: ctx.editor.isActive({ textAlign: "right" }),
457
- isAlignJustify: ctx.editor.isActive({ textAlign: "justify" }),
458
- isLink: ctx.editor.isActive("link"),
459
- currentColor: ctx.editor.getAttributes("textStyle")?.color || void 0,
460
- currentHighlight: ctx.editor.getAttributes("highlight")?.color || void 0,
461
- currentFont: ctx.editor.getAttributes("textStyle")?.fontFamily || void 0,
462
- currentSize: ctx.editor.getAttributes("textStyle")?.fontSize || void 0
463
- };
464
- }
465
- });
466
- return {
467
- ...states
468
- };
469
- };
470
- var MemoButton = memo(Toolbar.Button);
471
- var MemoContentTypePicker = memo(ContentTypePicker);
472
- function Selection() {
473
- const { editor } = useCurrentEditor();
474
- if (!editor) return null;
475
- const commands = useTextmenuCommands(editor);
476
- const states = useTextmenuStates(editor);
477
- const blockOptions = useTextmenuContentTypes(editor);
478
- return /* @__PURE__ */ jsx(
479
- BubbleMenu,
480
- {
481
- editor,
482
- options: { placement: "top" },
483
- shouldShow: ({ editor: editor2, from, to }) => {
484
- if (from === to) return false;
485
- if (editor2.isActive("codeBlock")) return false;
486
- return true;
487
- },
488
- className: "nph-bubble",
489
- children: /* @__PURE__ */ jsxs(Toolbar.Wrapper, { children: [
490
- /* @__PURE__ */ jsx(MemoContentTypePicker, { options: blockOptions }),
491
- /* @__PURE__ */ jsx(
492
- MemoButton,
493
- {
494
- tooltip: "Bold",
495
- tooltipShortcut: ["Mod", "B"],
496
- onClick: commands.onBold,
497
- active: states.isBold,
498
- children: /* @__PURE__ */ jsx(IconBold, { className: "nph-icon" })
499
- }
500
- ),
501
- /* @__PURE__ */ jsx(
502
- MemoButton,
503
- {
504
- tooltip: "Italic",
505
- tooltipShortcut: ["Mod", "I"],
506
- onClick: commands.onItalic,
507
- active: states.isItalic,
508
- children: /* @__PURE__ */ jsx(IconItalic, { className: "nph-icon" })
509
- }
510
- )
511
- ] })
512
- }
513
- );
514
- }
515
- function Editor3({
516
- className,
517
- editorContainerProps,
518
- extensions = [],
519
- content,
520
- onUpdate,
521
- editorProps,
522
- editable = true,
523
- showSelectionMenu = true,
524
- selectionMenu,
525
- immediatelyRender = false,
526
- children,
527
- ...rest
528
- }) {
529
- const mergedContainerProps = {
530
- ...editorContainerProps,
531
- className: cn("nph-editor", className)
532
- };
533
- const mergedEditorProps = {
534
- ...editorProps,
535
- attributes: {
536
- ...editorProps?.attributes,
537
- ...!editable ? { "aria-disabled": "true", "data-disabled": "true" } : {}
538
- }
539
- };
540
- return /* @__PURE__ */ jsxs(
541
- EditorProvider,
542
- {
543
- content,
544
- extensions: [...Preset, ...extensions ?? []],
545
- onUpdate,
546
- editorProps: mergedEditorProps,
547
- editable,
548
- editorContainerProps: mergedContainerProps,
549
- immediatelyRender,
550
- ...rest,
551
- children: [
552
- showSelectionMenu && (selectionMenu ?? /* @__PURE__ */ jsx(Selection, {})),
553
- children
554
- ]
555
- }
556
- );
557
- }
558
-
559
- export { Editor3 as Editor };
1
+ import {EditorProvider,useCurrentEditor,useEditorState}from'@tiptap/react';import q from'@tiptap/starter-kit';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {BubbleMenu}from'@tiptap/react/menus';import _,{forwardRef,memo,useMemo,useCallback}from'react';import {jsx,jsxs,Fragment}from'react/jsx-runtime';import*as c from'@radix-ui/react-tooltip';import {IconListNumbers,IconList,IconH3,IconH2,IconH1,IconChevronDown,IconPilcrow,IconBold,IconItalic}from'@tabler/icons-react';import*as h from'@radix-ui/react-dropdown-menu';var w=[q.configure({bulletList:{keepMarks:true},orderedList:{keepMarks:true},heading:{levels:[1,2,3,4]}})];function s(...e){return twMerge(clsx(e))}var v=forwardRef(({children:e,className:o,withShadow:t=true,withBorder:i=true,...r},n)=>{let a=s(o,"nph-surface",t?"nph-surface--shadow":"",i?"nph-surface--border":"");return jsx("div",{className:a,...r,ref:n,children:e})});v.displayName="Surface";var A=_.forwardRef(({active:e,buttonSize:o="medium",children:t,disabled:i,variant:r="primary",className:n,activeClassname:a,...p},m)=>{let f=s("nph-btn",r==="primary"&&"nph-btn--primary",r==="secondary"&&"nph-btn--secondary",r==="tertiary"&&"nph-btn--tertiary",r==="ghost"&&"nph-btn--ghost",e&&s("nph-btn--active",a),o==="medium"&&"nph-btn--md",o==="small"&&"nph-btn--sm",o==="icon"&&"nph-btn--icon",o==="iconSmall"&&"nph-btn--icon-sm",n);return jsx("button",{ref:m,disabled:i,className:f,...p,children:t})});A.displayName="Button";var M=typeof window<"u"?navigator.userAgent.toLowerCase().includes("mac"):false,tt=({children:e})=>{let o="nph-kbd";return e==="Mod"?jsx("kbd",{className:o,children:M?"\u2318":"Ctrl"}):e==="Shift"?jsx("kbd",{className:o,children:"\u21E7"}):e==="Alt"?jsx("kbd",{className:o,children:M?"\u2325":"Alt"}):jsx("kbd",{className:o,children:e})},et=({children:e,enabled:o=true,title:t,shortcut:i,className:r})=>o?jsx(c.Provider,{delayDuration:500,children:jsxs(c.Root,{children:[jsx(c.Trigger,{asChild:true,children:jsx("span",{children:e})}),jsx(c.Portal,{children:jsxs(c.Content,{sideOffset:8,className:s("nph-tooltip",r),children:[t&&jsx("span",{className:"nph-tooltip-title",children:t}),i&&jsx("span",{className:"nph-tooltip-shortcut",children:i.map(n=>jsx(tt,{children:n},n))})]})})]})}):jsx(Fragment,{children:e}),H=et;var D=forwardRef(({shouldShowContent:e=true,children:o,isVertical:t=false,className:i,...r},n)=>{let a=s("nph-toolbar",t?"nph-toolbar--vertical":"nph-toolbar--horizontal",i);return e&&jsx(v,{className:a,...r,ref:n,children:o})});D.displayName="Toolbar";var R=forwardRef(({horizontal:e,className:o,...t},i)=>{let r=s("nph-toolbar-divider",e?"nph-toolbar-divider--horizontal":"nph-toolbar-divider--vertical",o);return jsx("div",{className:r,ref:i,...t})});R.displayName="Toolbar.Divider";var O=forwardRef(({children:e,buttonSize:o="icon",variant:t="ghost",className:i,tooltip:r,tooltipShortcut:n,activeClassname:a,...p},m)=>{let f=s("nph-toolbar-button",i),b=jsx(A,{activeClassname:a,className:f,variant:t,buttonSize:o,ref:m,...p,children:e});return r?jsx(H,{title:r,shortcut:n,children:b}):b});O.displayName="ToolbarButton";var y={Wrapper:D,Button:O};var dt={IconPilcrow:IconPilcrow,IconChevronDown:IconChevronDown,IconH1:IconH1,IconH2:IconH2,IconH3:IconH3,IconList:IconList,IconListNumbers:IconListNumbers},C=memo(({name:e,className:o,strokeWidth:t})=>{let i=dt[e];return i?jsx(i,{className:s("nph-icon",o),strokeWidth:t||2.5}):null});C.displayName="Icon";var z=({children:e})=>jsx("div",{className:"nph-dropdown-title",children:e}),W=_.forwardRef(function({children:o,isActive:t,onClick:i,disabled:r,className:n},a){let p=s("nph-dropdown-button",n);return jsx("button",{className:p,disabled:r,"data-active":t?"true":void 0,onClick:i,ref:a,children:o})});var bt=e=>e.type==="option",ht=e=>e.type==="category",V=({options:e})=>{let o=useMemo(()=>e.find(t=>t.type==="option"&&t.isActive()),[e]);return jsxs(h.Root,{modal:false,children:[jsx(h.Trigger,{asChild:true,children:jsxs(y.Button,{buttonSize:"small",children:[jsx(C,{name:o?.type==="option"&&o.icon||"IconPilcrow"}),jsx(C,{name:"IconChevronDown",className:"nph-icon",strokeWidth:3})]})}),jsx(h.Content,{side:"bottom",align:"start",alignOffset:-6,sideOffset:9,avoidCollisions:false,asChild:true,children:jsx(v,{className:"nph-menu-panel",children:e.map(t=>{if(bt(t))return jsxs(W,{onClick:t.onClick,isActive:t.isActive(),children:[jsx(C,{name:t.icon,className:"nph-icon nph-mr-1"}),t.label]},t.id);if(ht(t))return jsx("div",{className:"nph-category-gap",children:jsx(z,{children:t.label},t.id)},t.id)})})})]})};var J=e=>useEditorState({editor:e,selector:o=>[{type:"category",label:"Hierarchy",id:"hierarchy"},{icon:"IconPilcrow",onClick:()=>o.editor.chain().focus().command(({commands:t})=>{try{t.lift("taskItem");}catch{}try{t.liftListItem("listItem");}catch{}return true}).setParagraph().run(),id:"paragraph",disabled:()=>!o.editor.can().setParagraph(),isActive:()=>o.editor.isActive("paragraph")&&!o.editor.isActive("orderedList")&&!o.editor.isActive("bulletList")&&!o.editor.isActive("taskList"),label:"Paragraph",type:"option"},{icon:"IconH1",onClick:()=>o.editor.chain().focus().command(({commands:t})=>{try{t.lift("taskItem");}catch{}try{t.liftListItem("listItem");}catch{}return true}).setHeading({level:1}).run(),id:"heading1",disabled:()=>!o.editor.can().setHeading({level:1}),isActive:()=>o.editor.isActive("heading",{level:1}),label:"Heading 1",type:"option"},{icon:"IconH2",onClick:()=>o.editor.chain().focus().command(({commands:t})=>{try{t.lift("taskItem");}catch{}try{t.liftListItem("listItem");}catch{}return true}).setHeading({level:2}).run(),id:"heading2",disabled:()=>!o.editor.can().setHeading({level:2}),isActive:()=>o.editor.isActive("heading",{level:2}),label:"Heading 2",type:"option"},{icon:"IconH3",onClick:()=>o.editor.chain().focus().command(({commands:t})=>{try{t.lift("taskItem");}catch{}try{t.liftListItem("listItem");}catch{}return true}).setHeading({level:3}).run(),id:"heading3",disabled:()=>!o.editor.can().setHeading({level:3}),isActive:()=>o.editor.isActive("heading",{level:3}),label:"Heading 3",type:"option"},{type:"category",label:"Lists",id:"lists"},{icon:"IconList",onClick:()=>o.editor.chain().focus().toggleBulletList().run(),id:"bulletList",disabled:()=>!o.editor.can().toggleBulletList(),isActive:()=>o.editor.isActive("bulletList"),label:"Bullet list",type:"option"},{icon:"IconListNumbers",onClick:()=>o.editor.chain().focus().toggleOrderedList().run(),id:"orderedList",disabled:()=>!o.editor.can().toggleOrderedList(),isActive:()=>o.editor.isActive("orderedList")&&!o.editor.isActive("orderedList",{class:"styled-list"}),label:"Numbered list",type:"option"}]});var U=(e,o,t)=>{let i=useCallback(()=>e.chain().focus().toggleBold().run(),[e]),r=useCallback(()=>e.chain().focus().toggleItalic().run(),[e]),n=useCallback(()=>e.chain().focus().toggleStrike().run(),[e]),a=useCallback(()=>e.chain().focus().toggleCode().run(),[e]),p=useCallback(()=>e.chain().focus().toggleCodeBlock().run(),[e]),m=useCallback(()=>{if(e.isActive("link")){window.dispatchEvent(new CustomEvent("editor:link"));return}if(e.state.selection.empty)try{e.commands.selectTextblockEnd();}catch{}window.dispatchEvent(new CustomEvent("editor:link"));},[e]);useCallback(()=>{let{from:b,to:k}=e.state.selection,T=e.state.doc.textBetween(b,k,`
2
+ `),S=T.split(`
3
+ `)[0].trim()||"Untitled";let K=`<p>${T.replace(/\n\n/g,"</p><p>").replace(/\n/g,"<br />")}</p>`;return {title:S,content:K}},[e,o,t]);return {onBold:i,onItalic:r,onStrike:n,onCode:a,onCodeBlock:p,onLink:m}};var X=e=>({...useEditorState({editor:e,selector:t=>({isBold:t.editor.isActive("bold"),isItalic:t.editor.isActive("italic"),isStrike:t.editor.isActive("strike"),isUnderline:t.editor.isActive("underline"),isCode:t.editor.isActive("code"),isSubscript:t.editor.isActive("subscript"),isSuperscript:t.editor.isActive("superscript"),isAlignLeft:t.editor.isActive({textAlign:"left"}),isAlignCenter:t.editor.isActive({textAlign:"center"}),isAlignRight:t.editor.isActive({textAlign:"right"}),isAlignJustify:t.editor.isActive({textAlign:"justify"}),isLink:t.editor.isActive("link"),currentColor:t.editor.getAttributes("textStyle")?.color||void 0,currentHighlight:t.editor.getAttributes("highlight")?.color||void 0,currentFont:t.editor.getAttributes("textStyle")?.fontFamily||void 0,currentSize:t.editor.getAttributes("textStyle")?.fontSize||void 0})})});var $=memo(y.Button),kt=memo(V);function N(){let{editor:e}=useCurrentEditor();if(!e)return null;let o=U(e),t=X(e),i=J(e);return jsx(BubbleMenu,{editor:e,options:{placement:"top"},shouldShow:({editor:r,from:n,to:a})=>!(n===a||r.isActive("codeBlock")),className:"nph-bubble",children:jsxs(y.Wrapper,{children:[jsx(kt,{options:i}),jsx($,{tooltip:"Bold",tooltipShortcut:["Mod","B"],onClick:o.onBold,active:t.isBold,children:jsx(IconBold,{className:"nph-icon"})}),jsx($,{tooltip:"Italic",tooltipShortcut:["Mod","I"],onClick:o.onItalic,active:t.isItalic,children:jsx(IconItalic,{className:"nph-icon"})})]})})}function Xe({className:e,editorContainerProps:o,extensions:t=[],content:i,onUpdate:r,editorProps:n,editable:a=true,showSelectionMenu:p=true,selectionMenu:m,immediatelyRender:f=false,children:b,...k}){let T={...o,className:s("nph-editor",e)},I={...n,attributes:{...n?.attributes,...a?{}:{"aria-disabled":"true","data-disabled":"true"}}};return jsxs(EditorProvider,{content:i,extensions:[...w,...t??[]],onUpdate:r,editorProps:I,editable:a,editorContainerProps:T,immediatelyRender:f,...k,children:[p&&(m??jsx(N,{})),b]})}export{Xe as Editor};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neuphlo-editor",
3
- "version": "0.3.7",
3
+ "version": "0.3.8",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -1,12 +0,0 @@
1
- import StarterKit from '@tiptap/starter-kit';
2
-
3
- // src/preset.ts
4
- var Preset = [
5
- StarterKit.configure({
6
- bulletList: { keepMarks: true },
7
- orderedList: { keepMarks: true },
8
- heading: { levels: [1, 2, 3, 4] }
9
- })
10
- ];
11
-
12
- export { Preset };