@overlap/rte 0.1.10 → 1.0.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 (49) hide show
  1. package/README.md +45 -5
  2. package/dist/components/Dropdown.d.ts +1 -0
  3. package/dist/components/Dropdown.d.ts.map +1 -1
  4. package/dist/components/Editor.d.ts.map +1 -1
  5. package/dist/components/FloatingToolbar.d.ts +4 -0
  6. package/dist/components/FloatingToolbar.d.ts.map +1 -1
  7. package/dist/components/Icons.d.ts +3 -0
  8. package/dist/components/Icons.d.ts.map +1 -1
  9. package/dist/components/LinkTooltip.d.ts +11 -0
  10. package/dist/components/LinkTooltip.d.ts.map +1 -0
  11. package/dist/components/Toolbar.d.ts.map +1 -1
  12. package/dist/hooks/useCheckbox.d.ts +3 -1
  13. package/dist/hooks/useCheckbox.d.ts.map +1 -1
  14. package/dist/hooks/useEditorEvents.d.ts +11 -4
  15. package/dist/hooks/useEditorEvents.d.ts.map +1 -1
  16. package/dist/hooks/useEditorInit.d.ts +7 -3
  17. package/dist/hooks/useEditorInit.d.ts.map +1 -1
  18. package/dist/hooks/useEditorSelection.d.ts +3 -1
  19. package/dist/hooks/useEditorSelection.d.ts.map +1 -1
  20. package/dist/index.d.ts +90 -12
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.esm.js +4235 -3024
  23. package/dist/index.esm.js.map +1 -1
  24. package/dist/index.js +4240 -3023
  25. package/dist/index.js.map +1 -1
  26. package/dist/plugins/blockFormat.d.ts.map +1 -1
  27. package/dist/plugins/colors.d.ts.map +1 -1
  28. package/dist/plugins/image.d.ts +1 -1
  29. package/dist/plugins/image.d.ts.map +1 -1
  30. package/dist/plugins/index.d.ts +4 -0
  31. package/dist/plugins/index.d.ts.map +1 -1
  32. package/dist/plugins/linkDialog.d.ts.map +1 -1
  33. package/dist/plugins/optional.d.ts.map +1 -1
  34. package/dist/styles.css +210 -13
  35. package/dist/types.d.ts +13 -4
  36. package/dist/types.d.ts.map +1 -1
  37. package/dist/utils/autoLink.d.ts +12 -0
  38. package/dist/utils/autoLink.d.ts.map +1 -0
  39. package/dist/utils/content.d.ts +2 -1
  40. package/dist/utils/content.d.ts.map +1 -1
  41. package/dist/utils/history.d.ts +9 -4
  42. package/dist/utils/history.d.ts.map +1 -1
  43. package/dist/utils/markdownShortcuts.d.ts +15 -0
  44. package/dist/utils/markdownShortcuts.d.ts.map +1 -0
  45. package/dist/utils/sanitize.d.ts +20 -0
  46. package/dist/utils/sanitize.d.ts.map +1 -0
  47. package/dist/utils/selection.d.ts +28 -0
  48. package/dist/utils/selection.d.ts.map +1 -0
  49. package/package.json +1 -4
package/README.md CHANGED
@@ -15,16 +15,25 @@ npm install @overlap/rte
15
15
  - **Settings object** -- configure features with a single object instead of assembling plugins manually
16
16
  - **Contenteditable-based** -- uses native browser editing for performance
17
17
  - **Full formatting** -- bold, italic, underline, strikethrough, subscript, superscript, inline code
18
- - **Block formats** -- headings (h1-h6), bullet lists, numbered lists, checkbox lists, blockquote, code block
18
+ - **Block formats** -- headings (h1-h6), bullet lists, numbered lists, checkbox lists, blockquote, code block, horizontal rule
19
19
  - **Tables** -- insert, row/column operations, context menu
20
- - **Images** -- upload via callback, URL insert, drag & drop, paste
21
- - **Links** -- floating editor, advanced attributes, custom fields
22
- - **Colors** -- text color and background color pickers
20
+ - **Images** -- upload via callback, URL insert, drag & drop, paste, alt text support
21
+ - **Links** -- floating editor, advanced attributes, custom fields, hover tooltip
22
+ - **Colors** -- text color and background color pickers with custom hex input
23
23
  - **Font sizes** -- configurable size dropdown
24
24
  - **Alignment** -- left, center, right, justify
25
25
  - **Indent / Outdent** -- nested list support via Tab / Shift+Tab
26
- - **Undo / Redo** -- full history management
26
+ - **Undo / Redo** -- full history management with cursor restoration
27
27
  - **HTML import/export** -- `htmlToContent()` and `contentToHTML()`
28
+ - **Keyboard shortcuts** -- Cmd/Ctrl+B, I, U, E, Shift+X, Shift+7, Shift+8 and more
29
+ - **Markdown shortcuts** -- type `#`, `-`, `>`, `[]`, `---`, `` ``` `` to auto-format
30
+ - **Auto-linking** -- URLs are auto-detected and converted to links on Space/Enter
31
+ - **Read-only mode** -- `readOnly` prop disables editing and hides toolbars
32
+ - **Floating toolbar** -- appears on text selection with formatting options
33
+ - **Word/character count** -- optional `showWordCount` display
34
+ - **Max length** -- enforce character limit with `maxLength` prop
35
+ - **Focus/blur callbacks** -- `onFocus` / `onBlur` props
36
+ - **HTML sanitization** -- built-in XSS protection on paste, import, and JSON rendering
28
37
  - **Theming** -- CSS variables + theme prop for brand colors
29
38
  - **Lexical compatible** -- correctly parses and renders HTML generated by Lexical editors
30
39
  - **TypeScript** -- fully typed, ships `.d.ts`
@@ -391,6 +400,11 @@ function MyEditor() {
391
400
  | `onImageUpload` | `(file: File) => Promise<string>` | Image upload callback |
392
401
  | `onEditorAPIReady` | `(api: EditorAPI) => void` | Callback when editor API is ready |
393
402
  | `theme` | `object?` | Theme overrides (see Theming section) |
403
+ | `readOnly` | `boolean?` | When `true`, hides toolbars and disables editing |
404
+ | `onFocus` | `() => void` | Called when the editor receives focus |
405
+ | `onBlur` | `() => void` | Called when the editor loses focus |
406
+ | `maxLength` | `number?` | Maximum character count; prevents input beyond this limit |
407
+ | `showWordCount` | `boolean?` | Shows a word/character count bar below the editor |
394
408
 
395
409
  ---
396
410
 
@@ -417,6 +431,7 @@ Available via `onEditorAPIReady` callback or passed to plugin functions:
417
431
  | `clearBackgroundColor()` | Remove background color |
418
432
  | `clearFontSize()` | Remove font size |
419
433
  | `clearLinks()` | Remove links (keep text) |
434
+ | `getTextStats()` | Get `{ characters, words }` count |
420
435
 
421
436
  ---
422
437
 
@@ -467,6 +482,7 @@ export { boldPlugin, italicPlugin, underlinePlugin, strikethroughPlugin };
467
482
  export { subscriptPlugin, superscriptPlugin, codeInlinePlugin };
468
483
  export { undoPlugin, redoPlugin, clearFormattingPlugin };
469
484
  export { indentListItemPlugin, outdentListItemPlugin };
485
+ export { horizontalRulePlugin };
470
486
  export { defaultPlugins };
471
487
 
472
488
  // Plugin factories
@@ -481,6 +497,7 @@ export { tablePlugin };
481
497
  // Utilities
482
498
  export { htmlToContent, contentToHTML, contentToDOM, domToContent, createEmptyContent };
483
499
  export { HistoryManager };
500
+ export { sanitizeHtml, isUrlSafe };
484
501
 
485
502
  // Types
486
503
  export { Plugin, EditorAPI, EditorContent, EditorNode, EditorProps, ButtonProps };
@@ -488,6 +505,29 @@ export { Plugin, EditorAPI, EditorContent, EditorNode, EditorProps, ButtonProps
488
505
 
489
506
  ---
490
507
 
508
+ ## Security
509
+
510
+ The editor includes built-in XSS protection:
511
+
512
+ - **HTML sanitization** -- `htmlToContent()` automatically sanitizes incoming HTML, stripping `<script>`, `<iframe>`, event handlers (`onclick`, `onerror`, etc.), and `javascript:` URLs.
513
+ - **URL validation** -- `isUrlSafe(url)` is available as an export to validate URLs against a safe scheme allowlist. It is used internally for links, images, and auto-linking.
514
+ - **Paste protection** -- pasted HTML is sanitized before insertion.
515
+ - **Allowlist-based** -- the sanitizer uses a tag and attribute allowlist approach, removing dangerous elements (`<script>`, `<iframe>`, `<object>`, `<embed>`, `<form>`, `<template>`, `<video>`, `<audio>`, `<marquee>`, etc.) and filtering attributes that start with `on` or contain unsafe values.
516
+
517
+ ```tsx
518
+ import { sanitizeHtml, isUrlSafe } from "@overlap/rte";
519
+
520
+ // Sanitize untrusted HTML
521
+ const clean = sanitizeHtml('<p>Hello</p><script>alert("xss")</script>');
522
+
523
+ // Validate a URL
524
+ if (isUrlSafe(userUrl)) {
525
+ // safe to use
526
+ }
527
+ ```
528
+
529
+ ---
530
+
491
531
  ## Development
492
532
 
493
533
  ```bash
@@ -13,6 +13,7 @@ interface DropdownProps {
13
13
  onSelect: (value: string) => void;
14
14
  currentValue?: string;
15
15
  disabled?: boolean;
16
+ showCustomColorInput?: boolean;
16
17
  }
17
18
  export declare const Dropdown: React.FC<DropdownProps>;
18
19
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"Dropdown.d.ts","sourceRoot":"","sources":["../../src/components/Dropdown.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAG3D,UAAU,aAAa;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3H,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAyF5C,CAAC"}
1
+ {"version":3,"file":"Dropdown.d.ts","sourceRoot":"","sources":["../../src/components/Dropdown.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAG3D,UAAU,aAAa;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3H,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAsJ5C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Editor.d.ts","sourceRoot":"","sources":["../../src/components/Editor.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkD,MAAM,OAAO,CAAC;AAUvE,OAAO,EAA4B,WAAW,EAAE,MAAM,UAAU,CAAC;AAwBjE,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAilBxC,CAAC"}
1
+ {"version":3,"file":"Editor.d.ts","sourceRoot":"","sources":["../../src/components/Editor.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAYjF,OAAO,EAA4B,WAAW,EAAE,MAAM,UAAU,CAAC;AA4BjE,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAktBxC,CAAC"}
@@ -5,6 +5,10 @@ interface FloatingToolbarProps {
5
5
  editorAPI: EditorAPI;
6
6
  editorElement: HTMLElement | null;
7
7
  }
8
+ /**
9
+ * Floating toolbar that appears above the current text selection.
10
+ * Uses position:fixed with viewport coordinates for reliable placement.
11
+ */
8
12
  export declare const FloatingToolbar: React.FC<FloatingToolbarProps>;
9
13
  export {};
10
14
  //# sourceMappingURL=FloatingToolbar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FloatingToolbar.d.ts","sourceRoot":"","sources":["../../src/components/FloatingToolbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAC3D,OAAO,EAAe,SAAS,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAE1D,UAAU,oBAAoB;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,aAAa,EAAE,WAAW,GAAG,IAAI,CAAC;CACrC;AAQD,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAqM1D,CAAC"}
1
+ {"version":3,"file":"FloatingToolbar.d.ts","sourceRoot":"","sources":["../../src/components/FloatingToolbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AACxE,OAAO,EAAe,SAAS,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAE1D,UAAU,oBAAoB;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,aAAa,EAAE,WAAW,GAAG,IAAI,CAAC;CACrC;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA0L1D,CAAC"}
@@ -35,6 +35,9 @@ export declare const AlignCenterIcon: React.FC<IconProps>;
35
35
  export declare const AlignRightIcon: React.FC<IconProps>;
36
36
  export declare const AlignJustifyIcon: React.FC<IconProps>;
37
37
  export declare const TableIcon: React.FC<IconProps>;
38
+ export declare const HorizontalRuleIcon: React.FC<IconProps>;
39
+ export declare const OpenInNewIcon: React.FC<IconProps>;
40
+ export declare const ContentCopyIcon: React.FC<IconProps>;
38
41
  export declare const Icon: React.FC<{
39
42
  icon: string;
40
43
  width?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"Icons.d.ts","sourceRoot":"","sources":["../../src/components/Icons.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Icons.d.ts","sourceRoot":"","sources":["../../src/components/Icons.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import React from "react";
2
+ interface LinkTooltipProps {
3
+ editorElement: HTMLElement | null;
4
+ }
5
+ /**
6
+ * Shows a tooltip with URL, edit link, and open link actions
7
+ * when hovering over an <a> element in the editor.
8
+ */
9
+ export declare const LinkTooltip: React.FC<LinkTooltipProps>;
10
+ export {};
11
+ //# sourceMappingURL=LinkTooltip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LinkTooltip.d.ts","sourceRoot":"","sources":["../../src/components/LinkTooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAIxE,UAAU,gBAAgB;IACtB,aAAa,EAAE,WAAW,GAAG,IAAI,CAAC;CACrC;AAUD;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA4IlD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../../src/components/Toolbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AACnD,OAAO,EAAe,SAAS,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAE1D,UAAU,YAAY;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CA+H1C,CAAC"}
1
+ {"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../../src/components/Toolbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AACxE,OAAO,EAAe,SAAS,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAE1D,UAAU,YAAY;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CA6L1C,CAAC"}
@@ -2,7 +2,9 @@ import { EditorContent } from "../types";
2
2
  import { ensureAllCheckboxes, updateListItemChecked } from "../utils/checkbox";
3
3
  interface UseCheckboxOptions {
4
4
  editorRef: React.RefObject<HTMLDivElement | null>;
5
- isUpdatingRef: React.MutableRefObject<boolean>;
5
+ isUpdatingRef: {
6
+ current: boolean;
7
+ };
6
8
  pushToHistory: (content: EditorContent) => void;
7
9
  notifyChange: (content: EditorContent) => void;
8
10
  getDomContent: () => EditorContent;
@@ -1 +1 @@
1
- {"version":3,"file":"useCheckbox.d.ts","sourceRoot":"","sources":["../../src/hooks/useCheckbox.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EACH,mBAAmB,EAInB,qBAAqB,EACxB,MAAM,mBAAmB,CAAC;AAS3B,UAAU,kBAAkB;IACxB,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAClD,aAAa,EAAE,KAAK,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC/C,aAAa,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;IAChD,YAAY,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C,aAAa,EAAE,MAAM,aAAa,CAAC;CACtC;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EACxB,SAAS,EACT,aAAa,EACb,aAAa,EACb,YAAY,EACZ,aAAa,GAChB,EAAE,kBAAkB;;iCA+NJ,WAAW,KAAG,OAAO;+BAvI1B,aAAa,KAAG,OAAO;6BAkFvB,aAAa,KAAG,OAAO;;EA6JlC"}
1
+ {"version":3,"file":"useCheckbox.d.ts","sourceRoot":"","sources":["../../src/hooks/useCheckbox.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EACH,mBAAmB,EAInB,qBAAqB,EACxB,MAAM,mBAAmB,CAAC;AAS3B,UAAU,kBAAkB;IACxB,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAClD,aAAa,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IACpC,aAAa,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;IAChD,YAAY,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C,aAAa,EAAE,MAAM,aAAa,CAAC;CACtC;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EACxB,SAAS,EACT,aAAa,EACb,aAAa,EACb,YAAY,EACZ,aAAa,GAChB,EAAE,kBAAkB;;iCA4QJ,WAAW,KAAG,OAAO;+BApL1B,aAAa,KAAG,OAAO;6BAkFvB,aAAa,KAAG,OAAO;;EA0MlC"}
@@ -2,8 +2,15 @@ import { EditorContent } from "../types";
2
2
  import { HistoryManager } from "../utils/history";
3
3
  interface UseEditorEventsOptions {
4
4
  editorRef: React.RefObject<HTMLDivElement | null>;
5
- historyRef: React.MutableRefObject<HistoryManager>;
6
- isUpdatingRef: React.MutableRefObject<boolean>;
5
+ historyRef: {
6
+ current: HistoryManager;
7
+ };
8
+ isUpdatingRef: {
9
+ current: boolean;
10
+ };
11
+ mountedRef: {
12
+ current: boolean;
13
+ };
7
14
  notifyChange: (content: EditorContent) => void;
8
15
  handleCheckboxKeyDown: (e: KeyboardEvent) => boolean;
9
16
  handleCheckboxEnter: (e: KeyboardEvent) => boolean;
@@ -11,8 +18,8 @@ interface UseEditorEventsOptions {
11
18
  redo: () => void;
12
19
  }
13
20
  /**
14
- * Hook that sets up input, keyup, and keydown event listeners on the editor.
21
+ * Hook that sets up input and keydown event listeners on the editor.
15
22
  */
16
- export declare function useEditorEvents({ editorRef, historyRef, isUpdatingRef, notifyChange, handleCheckboxKeyDown, handleCheckboxEnter, undo, redo, }: UseEditorEventsOptions): void;
23
+ export declare function useEditorEvents({ editorRef, historyRef, isUpdatingRef, mountedRef, notifyChange, handleCheckboxKeyDown, handleCheckboxEnter, undo, redo, }: UseEditorEventsOptions): void;
17
24
  export {};
18
25
  //# sourceMappingURL=useEditorEvents.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useEditorEvents.d.ts","sourceRoot":"","sources":["../../src/hooks/useEditorEvents.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAIlD,UAAU,sBAAsB;IAC5B,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAClD,UAAU,EAAE,KAAK,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;IACnD,aAAa,EAAE,KAAK,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC/C,YAAY,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C,qBAAqB,EAAE,CAAC,CAAC,EAAE,aAAa,KAAK,OAAO,CAAC;IACrD,mBAAmB,EAAE,CAAC,CAAC,EAAE,aAAa,KAAK,OAAO,CAAC;IACnD,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,IAAI,EAAE,MAAM,IAAI,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAC5B,SAAS,EACT,UAAU,EACV,aAAa,EACb,YAAY,EACZ,qBAAqB,EACrB,mBAAmB,EACnB,IAAI,EACJ,IAAI,GACP,EAAE,sBAAsB,QAqIxB"}
1
+ {"version":3,"file":"useEditorEvents.d.ts","sourceRoot":"","sources":["../../src/hooks/useEditorEvents.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAOlD,UAAU,sBAAsB;IAC5B,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAClD,UAAU,EAAE;QAAE,OAAO,EAAE,cAAc,CAAA;KAAE,CAAC;IACxC,aAAa,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IACpC,UAAU,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IACjC,YAAY,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C,qBAAqB,EAAE,CAAC,CAAC,EAAE,aAAa,KAAK,OAAO,CAAC;IACrD,mBAAmB,EAAE,CAAC,CAAC,EAAE,aAAa,KAAK,OAAO,CAAC;IACnD,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,IAAI,EAAE,MAAM,IAAI,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAC5B,SAAS,EACT,UAAU,EACV,aAAa,EACb,UAAU,EACV,YAAY,EACZ,qBAAqB,EACrB,mBAAmB,EACnB,IAAI,EACJ,IAAI,GACP,EAAE,sBAAsB,QAoOxB"}
@@ -3,8 +3,12 @@ import { EditorContent } from "../types";
3
3
  import { HistoryManager } from "../utils/history";
4
4
  interface UseEditorInitOptions {
5
5
  editorRef: React.RefObject<HTMLDivElement | null>;
6
- historyRef: React.MutableRefObject<HistoryManager>;
7
- isUpdatingRef: React.MutableRefObject<boolean>;
6
+ historyRef: {
7
+ current: HistoryManager;
8
+ };
9
+ isUpdatingRef: {
10
+ current: boolean;
11
+ };
8
12
  initialContent?: EditorContent;
9
13
  notifyChange: (content: EditorContent) => void;
10
14
  customLinkComponent?: React.ComponentType<{
@@ -12,7 +16,7 @@ interface UseEditorInitOptions {
12
16
  children: React.ReactNode;
13
17
  [key: string]: unknown;
14
18
  }>;
15
- customHeadingRenderer?: (level: string, children: React.ReactNode) => React.ReactElement;
19
+ customHeadingRenderer?: (level: string, children: React.ReactNode) => React.ReactNode;
16
20
  }
17
21
  /**
18
22
  * Hook that initializes the editor with initial content and sets up the MutationObserver.
@@ -1 +1 @@
1
- {"version":3,"file":"useEditorInit.d.ts","sourceRoot":"","sources":["../../src/hooks/useEditorInit.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,UAAU,oBAAoB;IAC1B,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAClD,UAAU,EAAE,KAAK,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;IACnD,aAAa,EAAE,KAAK,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC/C,cAAc,CAAC,EAAE,aAAa,CAAC;IAC/B,YAAY,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C,mBAAmB,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QACtC,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;QAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KAC1B,CAAC,CAAC;IACH,qBAAqB,CAAC,EAAE,CACpB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,KAAK,CAAC,SAAS,KACxB,KAAK,CAAC,YAAY,CAAC;CAC3B;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAC1B,SAAS,EACT,UAAU,EACV,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,qBAAqB,GACxB,EAAE,oBAAoB,QAoEtB"}
1
+ {"version":3,"file":"useEditorInit.d.ts","sourceRoot":"","sources":["../../src/hooks/useEditorInit.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,UAAU,oBAAoB;IAC1B,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAClD,UAAU,EAAE;QAAE,OAAO,EAAE,cAAc,CAAA;KAAE,CAAC;IACxC,aAAa,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IACpC,cAAc,CAAC,EAAE,aAAa,CAAC;IAC/B,YAAY,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C,mBAAmB,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QACtC,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;QAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KAC1B,CAAC,CAAC;IACH,qBAAqB,CAAC,EAAE,CACpB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,KAAK,CAAC,SAAS,KACxB,KAAK,CAAC,SAAS,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAC1B,SAAS,EACT,UAAU,EACV,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,qBAAqB,GACxB,EAAE,oBAAoB,QAwEtB"}
@@ -1,7 +1,9 @@
1
+ import { SelectionState } from "../utils/selection";
1
2
  /**
2
3
  * Hook for editor selection management.
4
+ * Wraps restoreSerializedSelection in a stable callback.
3
5
  */
4
6
  export declare function useEditorSelection(): {
5
- restoreSelection: (editor: HTMLElement) => void;
7
+ restoreSelection: (editor: HTMLElement, state?: SelectionState | null) => void;
6
8
  };
7
9
  //# sourceMappingURL=useEditorSelection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useEditorSelection.d.ts","sourceRoot":"","sources":["../../src/hooks/useEditorSelection.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,kBAAkB;+BACgB,WAAW;EAkB5D"}
1
+ {"version":3,"file":"useEditorSelection.d.ts","sourceRoot":"","sources":["../../src/hooks/useEditorSelection.ts"],"names":[],"mappings":"AACA,OAAO,EACH,cAAc,EAEjB,MAAM,oBAAoB,CAAC;AAE5B;;;GAGG;AACH,wBAAgB,kBAAkB;+BAEjB,WAAW,UAAU,cAAc,GAAG,IAAI;EAwB1D"}
package/dist/index.d.ts CHANGED
@@ -14,6 +14,7 @@ interface DropdownProps {
14
14
  onSelect: (value: string) => void;
15
15
  currentValue?: string;
16
16
  disabled?: boolean;
17
+ showCustomColorInput?: boolean;
17
18
  }
18
19
  declare const Dropdown: React$1.FC<DropdownProps>;
19
20
 
@@ -133,7 +134,7 @@ interface Plugin {
133
134
  command?: string;
134
135
  renderButton?: (props: ButtonProps & {
135
136
  [key: string]: unknown;
136
- }) => React.ReactElement;
137
+ }) => React.ReactNode;
137
138
  execute?: (editor: EditorAPI, value?: string) => void;
138
139
  isActive?: (editor: EditorAPI) => boolean;
139
140
  canExecute?: (editor: EditorAPI) => boolean;
@@ -166,10 +167,14 @@ interface EditorAPI {
166
167
  clearLinks: () => void;
167
168
  indentListItem: () => void;
168
169
  outdentListItem: () => void;
170
+ getTextStats: () => {
171
+ characters: number;
172
+ words: number;
173
+ };
169
174
  }
170
175
  interface CustomRenderer {
171
- renderNode?: (node: EditorNode, children: React.ReactNode) => React.ReactElement | null;
172
- renderMark?: (mark: string, attributes: Record<string, string>, children: React.ReactNode) => React.ReactElement | null;
176
+ renderNode?: (node: EditorNode, children: React.ReactNode) => React.ReactNode;
177
+ renderMark?: (mark: string, attributes: Record<string, string>, children: React.ReactNode) => React.ReactNode;
173
178
  }
174
179
  interface EditorProps {
175
180
  initialContent?: EditorContent;
@@ -187,7 +192,7 @@ interface EditorProps {
187
192
  fontSizes?: number[];
188
193
  colors?: string[];
189
194
  headings?: string[];
190
- customHeadingRenderer?: (level: string, children: React.ReactNode) => React.ReactElement;
195
+ customHeadingRenderer?: (level: string, children: React.ReactNode) => React.ReactNode;
191
196
  customRenderer?: CustomRenderer;
192
197
  onEditorAPIReady?: (api: EditorAPI) => void;
193
198
  theme?: {
@@ -201,10 +206,26 @@ interface EditorProps {
201
206
  onImageUpload?: (file: File) => Promise<string>;
202
207
  settings?: EditorSettings;
203
208
  settingsOptions?: BuildPluginsOptions;
209
+ readOnly?: boolean;
210
+ onFocus?: () => void;
211
+ onBlur?: () => void;
212
+ maxLength?: number;
213
+ showWordCount?: boolean;
204
214
  }
205
215
 
206
216
  declare const Editor: React$1.FC<EditorProps>;
207
217
 
218
+ interface FloatingToolbarProps {
219
+ plugins: Plugin[];
220
+ editorAPI: EditorAPI;
221
+ editorElement: HTMLElement | null;
222
+ }
223
+ /**
224
+ * Floating toolbar that appears above the current text selection.
225
+ * Uses position:fixed with viewport coordinates for reliable placement.
226
+ */
227
+ declare const FloatingToolbar: React$1.FC<FloatingToolbarProps>;
228
+
208
229
  interface ToolbarProps {
209
230
  plugins: Plugin[];
210
231
  editorAPI: EditorAPI;
@@ -222,6 +243,10 @@ declare const strikethroughPlugin: Plugin;
222
243
  declare const subscriptPlugin: Plugin;
223
244
  declare const superscriptPlugin: Plugin;
224
245
  declare const codeInlinePlugin: Plugin;
246
+ /**
247
+ * Horizontal Rule Plugin
248
+ */
249
+ declare const horizontalRulePlugin: Plugin;
225
250
  declare const undoPlugin: Plugin;
226
251
  declare const redoPlugin: Plugin;
227
252
  /**
@@ -262,7 +287,7 @@ declare function createFontSizePlugin(fontSizes?: number[]): Plugin;
262
287
  declare function createHeadingsPlugin(headings?: string[]): Plugin;
263
288
 
264
289
  /**
265
- * Image-Plugin mit URL-Eingabe und File-Upload
290
+ * Image plugin with URL input and file upload support.
266
291
  */
267
292
  declare function createImagePlugin(onImageUpload?: (file: File) => Promise<string>): Plugin;
268
293
 
@@ -309,7 +334,7 @@ declare function contentToDOM(content: EditorContent, container: HTMLElement, cu
309
334
  href: string;
310
335
  children: React$1.ReactNode;
311
336
  [key: string]: unknown;
312
- }>, customHeadingRenderer?: (level: string, children: React$1.ReactNode) => React$1.ReactElement): void;
337
+ }>, customHeadingRenderer?: (level: string, children: React$1.ReactNode) => React$1.ReactNode): void;
313
338
  /**
314
339
  * Creates empty editor content with a single paragraph.
315
340
  */
@@ -321,19 +346,52 @@ declare function contentToHTML(content: EditorContent): string;
321
346
  /**
322
347
  * Converts an HTML string to EditorContent.
323
348
  * Supports Lexical, GitHub, and standard HTML formats.
349
+ * Sanitizes HTML before parsing to prevent XSS.
324
350
  */
325
351
  declare function htmlToContent(htmlString: string): EditorContent;
326
352
 
353
+ /**
354
+ * Path-based selection serialization and restoration.
355
+ *
356
+ * DOM Range references become invalid after innerHTML replacement (undo/redo).
357
+ * This module converts a live selection into a serializable path representation
358
+ * (child indices from editor root to target node + character offset) and can
359
+ * restore that path back to a live DOM selection after the DOM has been rebuilt
360
+ * with identical structure.
361
+ */
362
+ interface SelectionPoint {
363
+ path: number[];
364
+ offset: number;
365
+ }
366
+ interface SelectionState {
367
+ anchor: SelectionPoint;
368
+ focus: SelectionPoint;
369
+ }
370
+ /**
371
+ * Serialize the current window selection relative to `editor`.
372
+ * Returns null if there is no selection or it is outside the editor.
373
+ */
374
+ declare function serializeSelection(editor: HTMLElement): SelectionState | null;
375
+ /**
376
+ * Restore a previously serialized selection on `editor`.
377
+ * Silently does nothing if the paths no longer match the DOM.
378
+ */
379
+ declare function restoreSerializedSelection(editor: HTMLElement, state: SelectionState | null): void;
380
+
381
+ interface HistoryEntry {
382
+ content: EditorContent;
383
+ selection: SelectionState | null;
384
+ }
327
385
  declare class HistoryManager {
328
386
  private history;
329
387
  private currentIndex;
330
388
  private maxHistorySize;
331
- push(content: EditorContent): void;
332
- undo(): EditorContent | null;
333
- redo(): EditorContent | null;
389
+ push(content: EditorContent, selection?: SelectionState | null): void;
390
+ undo(): HistoryEntry | null;
391
+ redo(): HistoryEntry | null;
334
392
  canUndo(): boolean;
335
393
  canRedo(): boolean;
336
- getCurrent(): EditorContent | null;
394
+ getCurrent(): HistoryEntry | null;
337
395
  reset(): void;
338
396
  }
339
397
 
@@ -363,6 +421,26 @@ declare function getCurrentBackgroundColor(editor: EditorAPI): string | undefine
363
421
  */
364
422
  declare function getCurrentHeading(editor: EditorAPI, availableHeadings: string[]): string | undefined;
365
423
 
424
+ /**
425
+ * Lightweight HTML sanitizer (no external dependencies).
426
+ *
427
+ * Uses an allowlist approach to strip dangerous elements and attributes
428
+ * from pasted/imported HTML before it enters the editor.
429
+ */
430
+ /**
431
+ * Check if a URL is safe to set as href/src.
432
+ * Blocks javascript:, data:, vbscript:, and unknown schemes.
433
+ * Strips control characters before checking.
434
+ */
435
+ declare function isUrlSafe(url: string): boolean;
436
+ /**
437
+ * Sanitize an HTML string by stripping dangerous tags and attributes.
438
+ *
439
+ * @param html - Raw HTML string
440
+ * @returns Sanitized HTML string
441
+ */
442
+ declare function sanitizeHtml(html: string): string;
443
+
366
444
  /**
367
445
  * Pure DOM utility functions.
368
446
  * No React dependencies - only native browser APIs.
@@ -384,5 +462,5 @@ declare function findClosestCheckboxList(element: HTMLElement): HTMLElement | nu
384
462
  */
385
463
  declare function ensureAllCheckboxes(editor: HTMLElement): void;
386
464
 
387
- export { Dropdown, Editor, HistoryManager, TableContextMenuProvider, Toolbar, advancedLinkPlugin, alignmentPlugin, blockquotePlugin, boldPlugin, buildPluginsFromSettings, clearFormattingPlugin, codeInlinePlugin, contentToDOM, contentToHTML, createAdvancedLinkPlugin, createAlignmentPlugin, createBackgroundColorPlugin, createBlockFormatPlugin, createEmptyContent, createFontSizePlugin, createHeadingsPlugin, createImagePlugin, createLinkPlugin, createTextColorPlugin, Editor as default, defaultEditorSettings, defaultPlugins, domToContent, ensureAllCheckboxes, findClosestCheckboxList, getCurrentBackgroundColor, getCurrentFontSize, getCurrentHeading, getCurrentTextColor, htmlToContent, indentListItem, indentListItemPlugin, isCheckboxList, italicPlugin, linkPlugin, orderedListPlugin, outdentListItem, outdentListItemPlugin, redoPlugin, strikethroughPlugin, subscriptPlugin, superscriptPlugin, tablePlugin, underlinePlugin, undoPlugin, unorderedListPlugin };
388
- export type { AdvancedLinkOptions, BlockFormatOptions, BuildPluginsOptions, ButtonProps, CustomRenderer, EditorAPI, EditorContent, EditorNode, EditorProps, EditorSettings, LinkCustomField, Plugin };
465
+ export { Dropdown, Editor, FloatingToolbar, HistoryManager, TableContextMenuProvider, Toolbar, advancedLinkPlugin, alignmentPlugin, blockquotePlugin, boldPlugin, buildPluginsFromSettings, clearFormattingPlugin, codeInlinePlugin, contentToDOM, contentToHTML, createAdvancedLinkPlugin, createAlignmentPlugin, createBackgroundColorPlugin, createBlockFormatPlugin, createEmptyContent, createFontSizePlugin, createHeadingsPlugin, createImagePlugin, createLinkPlugin, createTextColorPlugin, Editor as default, defaultEditorSettings, defaultPlugins, domToContent, ensureAllCheckboxes, findClosestCheckboxList, getCurrentBackgroundColor, getCurrentFontSize, getCurrentHeading, getCurrentTextColor, horizontalRulePlugin, htmlToContent, indentListItem, indentListItemPlugin, isCheckboxList, isUrlSafe, italicPlugin, linkPlugin, orderedListPlugin, outdentListItem, outdentListItemPlugin, redoPlugin, restoreSerializedSelection, sanitizeHtml, serializeSelection, strikethroughPlugin, subscriptPlugin, superscriptPlugin, tablePlugin, underlinePlugin, undoPlugin, unorderedListPlugin };
466
+ export type { AdvancedLinkOptions, BlockFormatOptions, BuildPluginsOptions, ButtonProps, CustomRenderer, EditorAPI, EditorContent, EditorNode, EditorProps, EditorSettings, HistoryEntry, LinkCustomField, Plugin, SelectionPoint, SelectionState };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAG/C,cAAc,WAAW,CAAC;AAC1B,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AAGrC,cAAc,SAAS,CAAC;AAGxB,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAG/D,cAAc,kBAAkB,CAAC;AAGjC,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrE,cAAc,yBAAyB,CAAC;AAGxC,OAAO,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAGtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAGvD,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAG/C,cAAc,WAAW,CAAC;AAC1B,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AAGrC,cAAc,SAAS,CAAC;AAGxB,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAG/D,cAAc,kBAAkB,CAAC;AAGjC,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AACnF,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrE,cAAc,yBAAyB,CAAC;AAGxC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAG3D,OAAO,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAGtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAGvD,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,qBAAqB,CAAC"}