@haklex/rich-plugin-toolbar 0.0.65 → 0.0.66

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/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # @haklex/rich-plugin-toolbar
2
+
3
+ Top toolbar plugin with formatting controls for the Haklex rich editor.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @haklex/rich-plugin-toolbar
9
+ ```
10
+
11
+ ## Peer Dependencies
12
+
13
+ | Package | Version |
14
+ | --- | --- |
15
+ | `@lexical/list` | `^0.41.0` |
16
+ | `@lexical/react` | `^0.41.0` |
17
+ | `@lexical/rich-text` | `^0.41.0` |
18
+ | `@lexical/selection` | `^0.41.0` |
19
+ | `@lexical/utils` | `^0.41.0` |
20
+ | `lexical` | `^0.41.0` |
21
+ | `lucide-react` | `^0.574.0` |
22
+ | `react` | `>= 19` |
23
+ | `react-dom` | `>= 19` |
24
+
25
+ ## Usage
26
+
27
+ ```tsx
28
+ import { ToolbarPlugin } from '@haklex/rich-plugin-toolbar'
29
+ import '@haklex/rich-plugin-toolbar/style.css'
30
+
31
+ function Editor() {
32
+ return (
33
+ <RichEditor>
34
+ <ToolbarPlugin />
35
+ </RichEditor>
36
+ )
37
+ }
38
+ ```
39
+
40
+ The toolbar renders at the top of the editor with controls for text formatting (bold, italic, underline, strikethrough, code), block type selection (paragraph, headings, quote, lists), text alignment, and undo/redo.
41
+
42
+ ```tsx
43
+ import type { ToolbarPluginProps } from '@haklex/rich-plugin-toolbar'
44
+
45
+ const props: ToolbarPluginProps = {
46
+ // ...
47
+ }
48
+ ```
49
+
50
+ ## Exports
51
+
52
+ | Export | Type | Description |
53
+ | --- | --- | --- |
54
+ | `ToolbarPlugin` | Component | Main toolbar component to render inside `RichEditor` |
55
+ | `ToolbarPluginProps` | TypeScript type | Props type for `ToolbarPlugin` |
56
+
57
+ ## Sub-path Exports
58
+
59
+ | Path | Description |
60
+ | --- | --- |
61
+ | `@haklex/rich-plugin-toolbar` | Plugin component and types |
62
+ | `@haklex/rich-plugin-toolbar/style.css` | Stylesheet |
63
+
64
+ ## Part of Haklex
65
+
66
+ This package is part of the [Haklex](../../README.md) rich editor ecosystem.
67
+
68
+ ## License
69
+
70
+ MIT
@@ -1,12 +1,12 @@
1
1
  import { ReactNode } from 'react';
2
2
  import { ToolbarTooltipHandle } from './types';
3
3
  export interface ToolbarButtonProps {
4
- icon: ReactNode;
5
- title: string;
6
- shortcut?: string;
7
4
  active?: boolean;
8
5
  disabled?: boolean;
6
+ icon: ReactNode;
9
7
  onClick: () => void;
8
+ shortcut?: string;
9
+ title: string;
10
10
  tooltipHandle?: ToolbarTooltipHandle;
11
11
  }
12
12
  export declare function ToolbarButton({ icon, title, shortcut, active, disabled, onClick, tooltipHandle, }: ToolbarButtonProps): import("react/jsx-runtime").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"ToolbarButton.d.ts","sourceRoot":"","sources":["../src/ToolbarButton.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGtC,OAAO,KAAK,EAAE,oBAAoB,EAAyB,MAAM,SAAS,CAAA;AAE1E,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,SAAS,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,aAAa,CAAC,EAAE,oBAAoB,CAAA;CACrC;AAED,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,OAAO,EACP,aAAa,GACd,EAAE,kBAAkB,2CAoCpB"}
1
+ {"version":3,"file":"ToolbarButton.d.ts","sourceRoot":"","sources":["../src/ToolbarButton.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,OAAO,KAAK,EAAE,oBAAoB,EAAyB,MAAM,SAAS,CAAC;AAE3E,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,oBAAoB,CAAC;CACtC;AAED,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,OAAO,EACP,aAAa,GACd,EAAE,kBAAkB,2CAoCpB"}
@@ -1,18 +1,18 @@
1
1
  import { CSSProperties, ReactNode } from 'react';
2
2
  import { ToolbarTooltipHandle } from './types';
3
3
  export interface ToolbarDropdownItem {
4
- label: string;
5
- icon?: ReactNode;
6
4
  active?: boolean;
7
- style?: CSSProperties;
5
+ icon?: ReactNode;
6
+ label: string;
8
7
  onSelect: () => void;
8
+ style?: CSSProperties;
9
9
  }
10
10
  export interface ToolbarDropdownProps {
11
+ items: ToolbarDropdownItem[];
11
12
  label: string;
12
13
  title: string;
13
- items: ToolbarDropdownItem[];
14
- triggerWidth?: number;
15
14
  tooltipHandle?: ToolbarTooltipHandle;
15
+ triggerWidth?: number;
16
16
  }
17
17
  export declare function ToolbarDropdown({ label, title, items, triggerWidth, tooltipHandle, }: ToolbarDropdownProps): import("react/jsx-runtime").JSX.Element;
18
18
  //# sourceMappingURL=ToolbarDropdown.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ToolbarDropdown.d.ts","sourceRoot":"","sources":["../src/ToolbarDropdown.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGrD,OAAO,KAAK,EAAE,oBAAoB,EAAyB,MAAM,SAAS,CAAA;AAE1E,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,KAAK,CAAC,EAAE,aAAa,CAAA;IACrB,QAAQ,EAAE,MAAM,IAAI,CAAA;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,mBAAmB,EAAE,CAAA;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,oBAAoB,CAAA;CACrC;AAED,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,KAAK,EACL,KAAK,EACL,YAAY,EACZ,aAAa,GACd,EAAE,oBAAoB,2CAyEtB"}
1
+ {"version":3,"file":"ToolbarDropdown.d.ts","sourceRoot":"","sources":["../src/ToolbarDropdown.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGtD,OAAO,KAAK,EAAE,oBAAoB,EAAyB,MAAM,SAAS,CAAC;AAE3E,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,mBAAmB,EAAE,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,oBAAoB,CAAC;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,KAAK,EACL,KAAK,EACL,YAAY,EACZ,aAAa,GACd,EAAE,oBAAoB,2CAyEtB"}
@@ -1,8 +1,8 @@
1
1
  import { ReactElement } from 'react';
2
2
  export interface ToolbarPluginProps {
3
3
  className?: string;
4
- maxVisibleInsertItems?: number;
5
4
  insertItemOrder?: string[];
5
+ maxVisibleInsertItems?: number;
6
6
  }
7
7
  export declare function ToolbarPlugin({ className, maxVisibleInsertItems, insertItemOrder, }: ToolbarPluginProps): ReactElement;
8
8
  //# sourceMappingURL=ToolbarPlugin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ToolbarPlugin.d.ts","sourceRoot":"","sources":["../src/ToolbarPlugin.tsx"],"names":[],"mappings":"AAgEA,OAAO,KAAK,EAAiB,YAAY,EAAE,MAAM,OAAO,CAAA;AA0HxD,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;CAC3B;AAED,wBAAgB,aAAa,CAAC,EAC5B,SAAS,EACT,qBAAwD,EACxD,eAAe,GAChB,EAAE,kBAAkB,GAAG,YAAY,CA4bnC"}
1
+ {"version":3,"file":"ToolbarPlugin.d.ts","sourceRoot":"","sources":["../src/ToolbarPlugin.tsx"],"names":[],"mappings":"AAgEA,OAAO,KAAK,EAAiB,YAAY,EAAE,MAAM,OAAO,CAAC;AAkHzD,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,wBAAgB,aAAa,CAAC,EAC5B,SAAS,EACT,qBAAwD,EACxD,eAAe,GAChB,EAAE,kBAAkB,GAAG,YAAY,CA4YnC"}
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
- import { collectCommandItems } from "@haklex/rich-editor";
2
+ import { collectCommandItems } from "@haklex/rich-editor/commands";
3
3
  import { TooltipTrigger, TooltipRoot, TooltipContent, DropdownMenuContent, DropdownMenuItem, DropdownMenu, DropdownMenuTrigger, createTooltipHandle, TooltipProvider } from "@haklex/rich-editor-ui";
4
4
  import { $isListNode, INSERT_UNORDERED_LIST_COMMAND, INSERT_ORDERED_LIST_COMMAND, INSERT_CHECK_LIST_COMMAND } from "@lexical/list";
5
5
  import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
@@ -30,15 +30,15 @@ function ToolbarButton({
30
30
  const button = /* @__PURE__ */ jsx(
31
31
  "button",
32
32
  {
33
- type: "button",
33
+ "aria-label": title,
34
+ "aria-pressed": active,
34
35
  className: `${toolbarButton}${active ? ` ${toolbarButtonActive}` : ""}`,
35
36
  disabled,
37
+ type: "button",
36
38
  onMouseDown: (e) => {
37
39
  e.preventDefault();
38
40
  onClick();
39
- },
40
- "aria-label": title,
41
- "aria-pressed": active
41
+ }
42
42
  }
43
43
  );
44
44
  if (tooltipHandle) {
@@ -72,8 +72,8 @@ function ToolbarDropdown({
72
72
  DropdownMenuTrigger,
73
73
  {
74
74
  className: toolbarDropdownTrigger,
75
- style: triggerStyle,
76
- render: /* @__PURE__ */ jsx("button", { type: "button" })
75
+ render: /* @__PURE__ */ jsx("button", { type: "button" }),
76
+ style: triggerStyle
77
77
  }
78
78
  );
79
79
  const triggerContent = /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -205,9 +205,7 @@ function ToolbarPlugin({
205
205
  }) {
206
206
  const [editor] = useLexicalComposerContext();
207
207
  const [state, setState] = useState(INITIAL_STATE);
208
- const [tooltipHandle] = useState(
209
- () => createTooltipHandle()
210
- );
208
+ const [tooltipHandle] = useState(() => createTooltipHandle());
211
209
  const toolbarItems = useMemo(() => {
212
210
  const items = collectCommandItems(editor).filter(
213
211
  (item) => item.placement?.includes("toolbar") && item.group === "insert"
@@ -228,20 +226,13 @@ function ToolbarPlugin({
228
226
  return parent !== null && $isRootOrShadowRoot(parent);
229
227
  }) ?? anchorNode.getTopLevelElementOrThrow();
230
228
  if ($isListNode(element)) {
231
- const parentList = $findMatchingParent(
232
- anchorNode,
233
- (node) => $isListNode(node)
234
- );
229
+ const parentList = $findMatchingParent(anchorNode, (node) => $isListNode(node));
235
230
  if (parentList) {
236
231
  element = parentList;
237
232
  }
238
233
  }
239
234
  const blockType = getBlockType(element);
240
- const fontFamily = $getSelectionStyleValueForProperty(
241
- selection,
242
- "font-family",
243
- ""
244
- );
235
+ const fontFamily = $getSelectionStyleValueForProperty(selection, "font-family", "");
245
236
  const elementFormat = $isElementNode(element) ? element.getFormatType() : "left";
246
237
  setState((prev) => ({
247
238
  ...prev,
@@ -273,13 +264,11 @@ function ToolbarPlugin({
273
264
  },
274
265
  COMMAND_PRIORITY_LOW
275
266
  );
276
- const unregisterUpdate = editor.registerUpdateListener(
277
- ({ editorState }) => {
278
- editorState.read(() => {
279
- updateToolbar();
280
- });
281
- }
282
- );
267
+ const unregisterUpdate = editor.registerUpdateListener(({ editorState }) => {
268
+ editorState.read(() => {
269
+ updateToolbar();
270
+ });
271
+ });
283
272
  return () => {
284
273
  unregisterUndo();
285
274
  unregisterRedo();
@@ -366,261 +355,239 @@ function ToolbarPlugin({
366
355
  const containerClassName = className ? `${toolbarContainer} ${className}` : toolbarContainer;
367
356
  const h = tooltipHandle;
368
357
  return /* @__PURE__ */ jsxs(TooltipProvider, { delay: 300, children: [
369
- /* @__PURE__ */ jsx(
370
- TooltipRoot,
371
- {
372
- handle: tooltipHandle,
373
- disableHoverablePopup: true,
374
- children: ((props) => props.payload !== void 0 ? /* @__PURE__ */ jsxs(TooltipContent, { side: "bottom", sideOffset: 4, children: [
375
- props.payload.title,
376
- props.payload.shortcut && /* @__PURE__ */ jsx("span", { className: tooltipShortcut, children: props.payload.shortcut })
377
- ] }) : null)
378
- }
379
- ),
380
- /* @__PURE__ */ jsx(
381
- "div",
382
- {
383
- className: containerClassName,
384
- role: "toolbar",
385
- "aria-label": "Editor toolbar",
386
- children: /* @__PURE__ */ jsxs("div", { className: toolbarRow, children: [
387
- /* @__PURE__ */ jsx(
388
- ToolbarDropdown,
389
- {
390
- label: getFontLabel(state.fontFamily),
391
- title: "Font family",
392
- items: fontFamilyItems,
393
- triggerWidth: 76,
394
- tooltipHandle: h
395
- }
396
- ),
397
- /* @__PURE__ */ jsx(ToolbarSeparator, {}),
398
- /* @__PURE__ */ jsx(
399
- ToolbarDropdown,
400
- {
401
- label: BLOCK_TYPE_LABELS[state.blockType] ?? "Text",
402
- title: "Block type",
403
- items: headingItems,
404
- triggerWidth: 120,
405
- tooltipHandle: h
406
- }
407
- ),
408
- /* @__PURE__ */ jsx(ToolbarSeparator, {}),
409
- /* @__PURE__ */ jsx(
410
- ToolbarButton,
411
- {
412
- icon: /* @__PURE__ */ jsx(Undo, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
413
- title: "Undo",
414
- shortcut: "Ctrl+Z",
415
- disabled: !state.canUndo,
416
- onClick: () => editor.dispatchCommand(UNDO_COMMAND, void 0),
417
- tooltipHandle: h
418
- }
419
- ),
420
- /* @__PURE__ */ jsx(
421
- ToolbarButton,
422
- {
423
- icon: /* @__PURE__ */ jsx(Redo, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
424
- title: "Redo",
425
- shortcut: "Ctrl+Y",
426
- disabled: !state.canRedo,
427
- onClick: () => editor.dispatchCommand(REDO_COMMAND, void 0),
428
- tooltipHandle: h
429
- }
430
- ),
431
- /* @__PURE__ */ jsx(ToolbarSeparator, {}),
432
- /* @__PURE__ */ jsx(
433
- ToolbarButton,
434
- {
435
- icon: /* @__PURE__ */ jsx(Bold, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
436
- title: "Bold",
437
- shortcut: "Ctrl+B",
438
- active: state.isBold,
439
- onClick: () => editor.dispatchCommand(FORMAT_TEXT_COMMAND, "bold"),
440
- tooltipHandle: h
441
- }
442
- ),
443
- /* @__PURE__ */ jsx(
444
- ToolbarButton,
445
- {
446
- icon: /* @__PURE__ */ jsx(Italic, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
447
- title: "Italic",
448
- shortcut: "Ctrl+I",
449
- active: state.isItalic,
450
- onClick: () => editor.dispatchCommand(FORMAT_TEXT_COMMAND, "italic"),
451
- tooltipHandle: h
452
- }
453
- ),
454
- /* @__PURE__ */ jsx(
455
- ToolbarButton,
456
- {
457
- icon: /* @__PURE__ */ jsx(Underline, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
458
- title: "Underline",
459
- shortcut: "Ctrl+U",
460
- active: state.isUnderline,
461
- onClick: () => editor.dispatchCommand(FORMAT_TEXT_COMMAND, "underline"),
462
- tooltipHandle: h
463
- }
464
- ),
465
- /* @__PURE__ */ jsx(
466
- ToolbarButton,
467
- {
468
- icon: /* @__PURE__ */ jsx(Strikethrough, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
469
- title: "Strikethrough",
470
- active: state.isStrikethrough,
471
- onClick: () => editor.dispatchCommand(FORMAT_TEXT_COMMAND, "strikethrough"),
472
- tooltipHandle: h
473
- }
474
- ),
475
- /* @__PURE__ */ jsx(
476
- ToolbarButton,
477
- {
478
- icon: /* @__PURE__ */ jsx(Code, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
479
- title: "Inline Code",
480
- active: state.isCode,
481
- onClick: () => editor.dispatchCommand(FORMAT_TEXT_COMMAND, "code"),
482
- tooltipHandle: h
483
- }
484
- ),
485
- /* @__PURE__ */ jsx(ToolbarSeparator, {}),
486
- /* @__PURE__ */ jsx(
487
- ToolbarButton,
488
- {
489
- icon: /* @__PURE__ */ jsx(Highlighter, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
490
- title: "Highlight",
491
- active: state.isHighlight,
492
- onClick: () => editor.dispatchCommand(FORMAT_TEXT_COMMAND, "highlight"),
493
- tooltipHandle: h
494
- }
495
- ),
496
- /* @__PURE__ */ jsx(ToolbarSeparator, {}),
497
- /* @__PURE__ */ jsx(
498
- ToolbarButton,
499
- {
500
- icon: /* @__PURE__ */ jsx(List, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
501
- title: "Bulleted List",
502
- active: state.blockType === "bullet",
503
- onClick: () => editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, void 0),
504
- tooltipHandle: h
505
- }
506
- ),
507
- /* @__PURE__ */ jsx(
508
- ToolbarButton,
509
- {
510
- icon: /* @__PURE__ */ jsx(ListOrdered, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
511
- title: "Numbered List",
512
- active: state.blockType === "number",
513
- onClick: () => editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, void 0),
514
- tooltipHandle: h
515
- }
516
- ),
517
- /* @__PURE__ */ jsx(
518
- ToolbarButton,
519
- {
520
- icon: /* @__PURE__ */ jsx(ListChecks, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
521
- title: "Checklist",
522
- active: state.blockType === "check",
523
- onClick: () => editor.dispatchCommand(INSERT_CHECK_LIST_COMMAND, void 0),
524
- tooltipHandle: h
525
- }
526
- ),
527
- /* @__PURE__ */ jsx(ToolbarSeparator, {}),
528
- /* @__PURE__ */ jsx(
529
- ToolbarButton,
530
- {
531
- icon: /* @__PURE__ */ jsx(AlignLeft, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
532
- title: "Align Left",
533
- active: state.elementFormat === "left" || state.elementFormat === "",
534
- onClick: () => editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, "left"),
535
- tooltipHandle: h
536
- }
537
- ),
538
- /* @__PURE__ */ jsx(
539
- ToolbarButton,
540
- {
541
- icon: /* @__PURE__ */ jsx(AlignCenter, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
542
- title: "Align Center",
543
- active: state.elementFormat === "center",
544
- onClick: () => editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, "center"),
545
- tooltipHandle: h
546
- }
547
- ),
548
- /* @__PURE__ */ jsx(
549
- ToolbarButton,
550
- {
551
- icon: /* @__PURE__ */ jsx(AlignRight, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
552
- title: "Align Right",
553
- active: state.elementFormat === "right",
554
- onClick: () => editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, "right"),
555
- tooltipHandle: h
556
- }
557
- ),
358
+ /* @__PURE__ */ jsx(TooltipRoot, { disableHoverablePopup: true, handle: tooltipHandle, children: ((props) => props.payload !== void 0 ? /* @__PURE__ */ jsxs(TooltipContent, { side: "bottom", sideOffset: 4, children: [
359
+ props.payload.title,
360
+ props.payload.shortcut && /* @__PURE__ */ jsx("span", { className: tooltipShortcut, children: props.payload.shortcut })
361
+ ] }) : null) }),
362
+ /* @__PURE__ */ jsx("div", { "aria-label": "Editor toolbar", className: containerClassName, role: "toolbar", children: /* @__PURE__ */ jsxs("div", { className: toolbarRow, children: [
363
+ /* @__PURE__ */ jsx(
364
+ ToolbarDropdown,
365
+ {
366
+ items: fontFamilyItems,
367
+ label: getFontLabel(state.fontFamily),
368
+ title: "Font family",
369
+ tooltipHandle: h,
370
+ triggerWidth: 76
371
+ }
372
+ ),
373
+ /* @__PURE__ */ jsx(ToolbarSeparator, {}),
374
+ /* @__PURE__ */ jsx(
375
+ ToolbarDropdown,
376
+ {
377
+ items: headingItems,
378
+ label: BLOCK_TYPE_LABELS[state.blockType] ?? "Text",
379
+ title: "Block type",
380
+ tooltipHandle: h,
381
+ triggerWidth: 120
382
+ }
383
+ ),
384
+ /* @__PURE__ */ jsx(ToolbarSeparator, {}),
385
+ /* @__PURE__ */ jsx(
386
+ ToolbarButton,
387
+ {
388
+ disabled: !state.canUndo,
389
+ icon: /* @__PURE__ */ jsx(Undo, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
390
+ shortcut: "Ctrl+Z",
391
+ title: "Undo",
392
+ tooltipHandle: h,
393
+ onClick: () => editor.dispatchCommand(UNDO_COMMAND, void 0)
394
+ }
395
+ ),
396
+ /* @__PURE__ */ jsx(
397
+ ToolbarButton,
398
+ {
399
+ disabled: !state.canRedo,
400
+ icon: /* @__PURE__ */ jsx(Redo, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
401
+ shortcut: "Ctrl+Y",
402
+ title: "Redo",
403
+ tooltipHandle: h,
404
+ onClick: () => editor.dispatchCommand(REDO_COMMAND, void 0)
405
+ }
406
+ ),
407
+ /* @__PURE__ */ jsx(ToolbarSeparator, {}),
408
+ /* @__PURE__ */ jsx(
409
+ ToolbarButton,
410
+ {
411
+ active: state.isBold,
412
+ icon: /* @__PURE__ */ jsx(Bold, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
413
+ shortcut: "Ctrl+B",
414
+ title: "Bold",
415
+ tooltipHandle: h,
416
+ onClick: () => editor.dispatchCommand(FORMAT_TEXT_COMMAND, "bold")
417
+ }
418
+ ),
419
+ /* @__PURE__ */ jsx(
420
+ ToolbarButton,
421
+ {
422
+ active: state.isItalic,
423
+ icon: /* @__PURE__ */ jsx(Italic, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
424
+ shortcut: "Ctrl+I",
425
+ title: "Italic",
426
+ tooltipHandle: h,
427
+ onClick: () => editor.dispatchCommand(FORMAT_TEXT_COMMAND, "italic")
428
+ }
429
+ ),
430
+ /* @__PURE__ */ jsx(
431
+ ToolbarButton,
432
+ {
433
+ active: state.isUnderline,
434
+ icon: /* @__PURE__ */ jsx(Underline, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
435
+ shortcut: "Ctrl+U",
436
+ title: "Underline",
437
+ tooltipHandle: h,
438
+ onClick: () => editor.dispatchCommand(FORMAT_TEXT_COMMAND, "underline")
439
+ }
440
+ ),
441
+ /* @__PURE__ */ jsx(
442
+ ToolbarButton,
443
+ {
444
+ active: state.isStrikethrough,
445
+ icon: /* @__PURE__ */ jsx(Strikethrough, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
446
+ title: "Strikethrough",
447
+ tooltipHandle: h,
448
+ onClick: () => editor.dispatchCommand(FORMAT_TEXT_COMMAND, "strikethrough")
449
+ }
450
+ ),
451
+ /* @__PURE__ */ jsx(
452
+ ToolbarButton,
453
+ {
454
+ active: state.isCode,
455
+ icon: /* @__PURE__ */ jsx(Code, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
456
+ title: "Inline Code",
457
+ tooltipHandle: h,
458
+ onClick: () => editor.dispatchCommand(FORMAT_TEXT_COMMAND, "code")
459
+ }
460
+ ),
461
+ /* @__PURE__ */ jsx(ToolbarSeparator, {}),
462
+ /* @__PURE__ */ jsx(
463
+ ToolbarButton,
464
+ {
465
+ active: state.isHighlight,
466
+ icon: /* @__PURE__ */ jsx(Highlighter, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
467
+ title: "Highlight",
468
+ tooltipHandle: h,
469
+ onClick: () => editor.dispatchCommand(FORMAT_TEXT_COMMAND, "highlight")
470
+ }
471
+ ),
472
+ /* @__PURE__ */ jsx(ToolbarSeparator, {}),
473
+ /* @__PURE__ */ jsx(
474
+ ToolbarButton,
475
+ {
476
+ active: state.blockType === "bullet",
477
+ icon: /* @__PURE__ */ jsx(List, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
478
+ title: "Bulleted List",
479
+ tooltipHandle: h,
480
+ onClick: () => editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, void 0)
481
+ }
482
+ ),
483
+ /* @__PURE__ */ jsx(
484
+ ToolbarButton,
485
+ {
486
+ active: state.blockType === "number",
487
+ icon: /* @__PURE__ */ jsx(ListOrdered, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
488
+ title: "Numbered List",
489
+ tooltipHandle: h,
490
+ onClick: () => editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, void 0)
491
+ }
492
+ ),
493
+ /* @__PURE__ */ jsx(
494
+ ToolbarButton,
495
+ {
496
+ active: state.blockType === "check",
497
+ icon: /* @__PURE__ */ jsx(ListChecks, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
498
+ title: "Checklist",
499
+ tooltipHandle: h,
500
+ onClick: () => editor.dispatchCommand(INSERT_CHECK_LIST_COMMAND, void 0)
501
+ }
502
+ ),
503
+ /* @__PURE__ */ jsx(ToolbarSeparator, {}),
504
+ /* @__PURE__ */ jsx(
505
+ ToolbarButton,
506
+ {
507
+ active: state.elementFormat === "left" || state.elementFormat === "",
508
+ icon: /* @__PURE__ */ jsx(AlignLeft, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
509
+ title: "Align Left",
510
+ tooltipHandle: h,
511
+ onClick: () => editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, "left")
512
+ }
513
+ ),
514
+ /* @__PURE__ */ jsx(
515
+ ToolbarButton,
516
+ {
517
+ active: state.elementFormat === "center",
518
+ icon: /* @__PURE__ */ jsx(AlignCenter, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
519
+ title: "Align Center",
520
+ tooltipHandle: h,
521
+ onClick: () => editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, "center")
522
+ }
523
+ ),
524
+ /* @__PURE__ */ jsx(
525
+ ToolbarButton,
526
+ {
527
+ active: state.elementFormat === "right",
528
+ icon: /* @__PURE__ */ jsx(AlignRight, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
529
+ title: "Align Right",
530
+ tooltipHandle: h,
531
+ onClick: () => editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, "right")
532
+ }
533
+ ),
534
+ /* @__PURE__ */ jsx(
535
+ ToolbarButton,
536
+ {
537
+ active: state.elementFormat === "justify",
538
+ icon: /* @__PURE__ */ jsx(AlignJustify, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
539
+ title: "Justify",
540
+ tooltipHandle: h,
541
+ onClick: () => editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, "justify")
542
+ }
543
+ ),
544
+ toolbarItems.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
545
+ /* @__PURE__ */ jsx(ToolbarSeparator, {}),
546
+ toolbarItems.slice(0, maxVisibleInsertItems).map((item) => /* @__PURE__ */ jsx(
547
+ ToolbarButton,
548
+ {
549
+ icon: item.icon,
550
+ shortcut: item.shortcut,
551
+ title: item.title,
552
+ tooltipHandle: h,
553
+ onClick: () => item.onSelect(editor, "")
554
+ },
555
+ item.title
556
+ )),
557
+ toolbarItems.length > maxVisibleInsertItems && /* @__PURE__ */ jsxs(DropdownMenu, { modal: false, children: [
558
558
  /* @__PURE__ */ jsx(
559
- ToolbarButton,
559
+ TooltipTrigger,
560
560
  {
561
- icon: /* @__PURE__ */ jsx(AlignJustify, { size: ICON_SIZE, strokeWidth: ICON_STROKE }),
562
- title: "Justify",
563
- active: state.elementFormat === "justify",
564
- onClick: () => editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, "justify"),
565
- tooltipHandle: h
566
- }
567
- ),
568
- toolbarItems.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
569
- /* @__PURE__ */ jsx(ToolbarSeparator, {}),
570
- toolbarItems.slice(0, maxVisibleInsertItems).map((item) => /* @__PURE__ */ jsx(
571
- ToolbarButton,
572
- {
573
- icon: item.icon,
574
- title: item.title,
575
- shortcut: item.shortcut,
576
- onClick: () => item.onSelect(editor, ""),
577
- tooltipHandle: h
578
- },
579
- item.title
580
- )),
581
- toolbarItems.length > maxVisibleInsertItems && /* @__PURE__ */ jsxs(DropdownMenu, { modal: false, children: [
582
- /* @__PURE__ */ jsx(
583
- TooltipTrigger,
561
+ handle: h,
562
+ payload: { title: "More" },
563
+ render: /* @__PURE__ */ jsx(
564
+ DropdownMenuTrigger,
584
565
  {
585
- handle: h,
586
- payload: { title: "More" },
587
- render: /* @__PURE__ */ jsx(
588
- DropdownMenuTrigger,
589
- {
590
- className: toolbarButton,
591
- render: /* @__PURE__ */ jsx("button", { type: "button" })
592
- }
593
- ),
594
- children: /* @__PURE__ */ jsx(Ellipsis, { size: ICON_SIZE, strokeWidth: ICON_STROKE })
566
+ className: toolbarButton,
567
+ render: /* @__PURE__ */ jsx("button", { type: "button" })
595
568
  }
596
569
  ),
597
- /* @__PURE__ */ jsx(DropdownMenuContent, { positionMethod: "fixed", sideOffset: 4, children: toolbarItems.slice(maxVisibleInsertItems).map((item) => /* @__PURE__ */ jsxs(
598
- DropdownMenuItem,
599
- {
600
- onClick: () => item.onSelect(editor, ""),
601
- children: [
602
- item.icon && /* @__PURE__ */ jsx(
603
- "span",
604
- {
605
- style: {
606
- marginRight: 8,
607
- display: "inline-flex",
608
- transform: "scale(0.8)",
609
- transformOrigin: "left center"
610
- },
611
- children: item.icon
612
- }
613
- ),
614
- item.title
615
- ]
570
+ children: /* @__PURE__ */ jsx(Ellipsis, { size: ICON_SIZE, strokeWidth: ICON_STROKE })
571
+ }
572
+ ),
573
+ /* @__PURE__ */ jsx(DropdownMenuContent, { positionMethod: "fixed", sideOffset: 4, children: toolbarItems.slice(maxVisibleInsertItems).map((item) => /* @__PURE__ */ jsxs(DropdownMenuItem, { onClick: () => item.onSelect(editor, ""), children: [
574
+ item.icon && /* @__PURE__ */ jsx(
575
+ "span",
576
+ {
577
+ style: {
578
+ marginRight: 8,
579
+ display: "inline-flex",
580
+ transform: "scale(0.8)",
581
+ transformOrigin: "left center"
616
582
  },
617
- item.title
618
- )) })
619
- ] })
620
- ] })
583
+ children: item.icon
584
+ }
585
+ ),
586
+ item.title
587
+ ] }, item.title)) })
621
588
  ] })
622
- }
623
- )
589
+ ] })
590
+ ] }) })
624
591
  ] });
625
592
  }
626
593
  export {
package/dist/types.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { createTooltipHandle } from '@haklex/rich-editor-ui';
2
2
  export interface ToolbarTooltipPayload {
3
- title: string;
4
3
  shortcut?: string;
4
+ title: string;
5
5
  }
6
6
  export type ToolbarTooltipHandle = ReturnType<typeof createTooltipHandle<ToolbarTooltipPayload>>;
7
7
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAEjE,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,MAAM,oBAAoB,GAAG,UAAU,CAC3C,OAAO,mBAAmB,CAAC,qBAAqB,CAAC,CAClD,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAElE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,oBAAoB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,qBAAqB,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@haklex/rich-plugin-toolbar",
3
3
  "type": "module",
4
- "version": "0.0.65",
4
+ "version": "0.0.66",
5
5
  "description": "Top toolbar plugin for rich editor",
6
6
  "license": "MIT",
7
7
  "exports": {
@@ -27,9 +27,9 @@
27
27
  "react-dom": ">=19"
28
28
  },
29
29
  "dependencies": {
30
- "@haklex/rich-editor": "0.0.65",
31
- "@haklex/rich-editor-ui": "0.0.65",
32
- "@haklex/rich-style-token": "0.0.65"
30
+ "@haklex/rich-editor": "0.0.66",
31
+ "@haklex/rich-editor-ui": "0.0.66",
32
+ "@haklex/rich-style-token": "0.0.66"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@lexical/list": "^0.41.0",
@@ -52,6 +52,11 @@
52
52
  "publishConfig": {
53
53
  "access": "public"
54
54
  },
55
+ "repository": {
56
+ "type": "git",
57
+ "url": "https://github.com/Innei/haklex.git",
58
+ "directory": "packages/rich-plugin-toolbar"
59
+ },
55
60
  "scripts": {
56
61
  "build": "vite build",
57
62
  "dev:build": "vite build --watch"