@vizel/svelte 0.0.1-alpha.1

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 (101) hide show
  1. package/README.md +83 -0
  2. package/dist/components/Vizel.svelte +158 -0
  3. package/dist/components/Vizel.svelte.d.ts +82 -0
  4. package/dist/components/Vizel.svelte.d.ts.map +1 -0
  5. package/dist/components/VizelBubbleMenu.svelte +96 -0
  6. package/dist/components/VizelBubbleMenu.svelte.d.ts +28 -0
  7. package/dist/components/VizelBubbleMenu.svelte.d.ts.map +1 -0
  8. package/dist/components/VizelBubbleMenuButton.svelte +45 -0
  9. package/dist/components/VizelBubbleMenuButton.svelte.d.ts +21 -0
  10. package/dist/components/VizelBubbleMenuButton.svelte.d.ts.map +1 -0
  11. package/dist/components/VizelBubbleMenuColorPicker.svelte +135 -0
  12. package/dist/components/VizelBubbleMenuColorPicker.svelte.d.ts +19 -0
  13. package/dist/components/VizelBubbleMenuColorPicker.svelte.d.ts.map +1 -0
  14. package/dist/components/VizelBubbleMenuDefault.svelte +111 -0
  15. package/dist/components/VizelBubbleMenuDefault.svelte.d.ts +13 -0
  16. package/dist/components/VizelBubbleMenuDefault.svelte.d.ts.map +1 -0
  17. package/dist/components/VizelBubbleMenuDivider.svelte +12 -0
  18. package/dist/components/VizelBubbleMenuDivider.svelte.d.ts +8 -0
  19. package/dist/components/VizelBubbleMenuDivider.svelte.d.ts.map +1 -0
  20. package/dist/components/VizelColorPicker.svelte +269 -0
  21. package/dist/components/VizelColorPicker.svelte.d.ts +25 -0
  22. package/dist/components/VizelColorPicker.svelte.d.ts.map +1 -0
  23. package/dist/components/VizelContext.d.ts +27 -0
  24. package/dist/components/VizelContext.d.ts.map +1 -0
  25. package/dist/components/VizelContext.js +34 -0
  26. package/dist/components/VizelEditor.svelte +61 -0
  27. package/dist/components/VizelEditor.svelte.d.ts +17 -0
  28. package/dist/components/VizelEditor.svelte.d.ts.map +1 -0
  29. package/dist/components/VizelEmbedView.svelte +162 -0
  30. package/dist/components/VizelEmbedView.svelte.d.ts +13 -0
  31. package/dist/components/VizelEmbedView.svelte.d.ts.map +1 -0
  32. package/dist/components/VizelIcon.svelte +54 -0
  33. package/dist/components/VizelIcon.svelte.d.ts +32 -0
  34. package/dist/components/VizelIcon.svelte.d.ts.map +1 -0
  35. package/dist/components/VizelIconContext.d.ts +27 -0
  36. package/dist/components/VizelIconContext.d.ts.map +1 -0
  37. package/dist/components/VizelIconContext.js +31 -0
  38. package/dist/components/VizelIconProvider.svelte +43 -0
  39. package/dist/components/VizelIconProvider.svelte.d.ts +31 -0
  40. package/dist/components/VizelIconProvider.svelte.d.ts.map +1 -0
  41. package/dist/components/VizelLinkEditor.svelte +143 -0
  42. package/dist/components/VizelLinkEditor.svelte.d.ts +15 -0
  43. package/dist/components/VizelLinkEditor.svelte.d.ts.map +1 -0
  44. package/dist/components/VizelNodeSelector.svelte +172 -0
  45. package/dist/components/VizelNodeSelector.svelte.d.ts +13 -0
  46. package/dist/components/VizelNodeSelector.svelte.d.ts.map +1 -0
  47. package/dist/components/VizelPortal.svelte +70 -0
  48. package/dist/components/VizelPortal.svelte.d.ts +19 -0
  49. package/dist/components/VizelPortal.svelte.d.ts.map +1 -0
  50. package/dist/components/VizelProvider.svelte +26 -0
  51. package/dist/components/VizelProvider.svelte.d.ts +14 -0
  52. package/dist/components/VizelProvider.svelte.d.ts.map +1 -0
  53. package/dist/components/VizelSaveIndicator.svelte +94 -0
  54. package/dist/components/VizelSaveIndicator.svelte.d.ts +15 -0
  55. package/dist/components/VizelSaveIndicator.svelte.d.ts.map +1 -0
  56. package/dist/components/VizelSlashMenu.svelte +211 -0
  57. package/dist/components/VizelSlashMenu.svelte.d.ts +31 -0
  58. package/dist/components/VizelSlashMenu.svelte.d.ts.map +1 -0
  59. package/dist/components/VizelSlashMenuEmpty.svelte +22 -0
  60. package/dist/components/VizelSlashMenuEmpty.svelte.d.ts +11 -0
  61. package/dist/components/VizelSlashMenuEmpty.svelte.d.ts.map +1 -0
  62. package/dist/components/VizelSlashMenuItem.svelte +57 -0
  63. package/dist/components/VizelSlashMenuItem.svelte.d.ts +17 -0
  64. package/dist/components/VizelSlashMenuItem.svelte.d.ts.map +1 -0
  65. package/dist/components/VizelThemeProvider.svelte +79 -0
  66. package/dist/components/VizelThemeProvider.svelte.d.ts +11 -0
  67. package/dist/components/VizelThemeProvider.svelte.d.ts.map +1 -0
  68. package/dist/components/index.d.ts +23 -0
  69. package/dist/components/index.d.ts.map +1 -0
  70. package/dist/components/index.js +64 -0
  71. package/dist/iconRenderer.d.ts +6 -0
  72. package/dist/iconRenderer.d.ts.map +1 -0
  73. package/dist/iconRenderer.js +7 -0
  74. package/dist/index.d.ts +9 -0
  75. package/dist/index.d.ts.map +1 -0
  76. package/dist/index.js +31 -0
  77. package/dist/runes/createVizelAutoSave.svelte.d.ts +44 -0
  78. package/dist/runes/createVizelAutoSave.svelte.d.ts.map +1 -0
  79. package/dist/runes/createVizelAutoSave.svelte.js +91 -0
  80. package/dist/runes/createVizelEditor.svelte.d.ts +43 -0
  81. package/dist/runes/createVizelEditor.svelte.d.ts.map +1 -0
  82. package/dist/runes/createVizelEditor.svelte.js +65 -0
  83. package/dist/runes/createVizelEditorState.svelte.d.ts +27 -0
  84. package/dist/runes/createVizelEditorState.svelte.d.ts.map +1 -0
  85. package/dist/runes/createVizelEditorState.svelte.js +35 -0
  86. package/dist/runes/createVizelMarkdown.svelte.d.ts +68 -0
  87. package/dist/runes/createVizelMarkdown.svelte.d.ts.map +1 -0
  88. package/dist/runes/createVizelMarkdown.svelte.js +123 -0
  89. package/dist/runes/createVizelSlashMenuRenderer.d.ts +22 -0
  90. package/dist/runes/createVizelSlashMenuRenderer.d.ts.map +1 -0
  91. package/dist/runes/createVizelSlashMenuRenderer.js +84 -0
  92. package/dist/runes/createVizelState.svelte.d.ts +22 -0
  93. package/dist/runes/createVizelState.svelte.d.ts.map +1 -0
  94. package/dist/runes/createVizelState.svelte.js +50 -0
  95. package/dist/runes/getVizelTheme.svelte.d.ts +23 -0
  96. package/dist/runes/getVizelTheme.svelte.d.ts.map +1 -0
  97. package/dist/runes/getVizelTheme.svelte.js +31 -0
  98. package/dist/runes/index.d.ts +8 -0
  99. package/dist/runes/index.d.ts.map +1 -0
  100. package/dist/runes/index.js +7 -0
  101. package/package.json +64 -0
package/README.md ADDED
@@ -0,0 +1,83 @@
1
+ # @vizel/svelte
2
+
3
+ Svelte 5 components for Vizel block-based Markdown editor.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @vizel/svelte @vizel/core
9
+ ```
10
+
11
+ ## Requirements
12
+
13
+ - Svelte 5+
14
+
15
+ ## Usage
16
+
17
+ ### Basic Setup
18
+
19
+ ```svelte
20
+ <script lang="ts">
21
+ import { Vizel } from "@vizel/svelte";
22
+ import "@vizel/core/styles.css";
23
+ </script>
24
+
25
+ <Vizel />
26
+ ```
27
+
28
+ ### With Editor Control
29
+
30
+ ```svelte
31
+ <script lang="ts">
32
+ import { VizelEditor, VizelBubbleMenu, createVizelEditor } from "@vizel/svelte";
33
+ import "@vizel/core/styles.css";
34
+
35
+ const editor = createVizelEditor();
36
+ </script>
37
+
38
+ <VizelEditor editor={editor.current} />
39
+ <VizelBubbleMenu editor={editor.current} />
40
+ ```
41
+
42
+ ### Markdown Import/Export
43
+
44
+ ```svelte
45
+ <script lang="ts">
46
+ import { createVizelEditor, createVizelMarkdown } from "@vizel/svelte";
47
+
48
+ const editor = createVizelEditor();
49
+ const { getMarkdown, setMarkdown } = createVizelMarkdown(() => editor.current);
50
+
51
+ const handleExport = () => {
52
+ const markdown = getMarkdown();
53
+ console.log(markdown);
54
+ };
55
+ </script>
56
+ ```
57
+
58
+ ## Components
59
+
60
+ | Component | Description |
61
+ |-----------|-------------|
62
+ | `Vizel` | All-in-one editor with bubble menu |
63
+ | `VizelEditor` | Editor component |
64
+ | `VizelBubbleMenu` | Floating formatting toolbar |
65
+ | `VizelSlashMenu` | Slash command menu |
66
+ | `VizelIconProvider` | Custom icon provider |
67
+
68
+ ## Runes
69
+
70
+ | Rune | Description |
71
+ |------|-------------|
72
+ | `createVizelEditor` | Create and manage editor instance |
73
+ | `createVizelMarkdown` | Markdown import/export |
74
+ | `createVizelAutoSave` | Auto-save functionality |
75
+ | `createVizelState` | Editor state management |
76
+
77
+ ## Documentation
78
+
79
+ See the [main repository](https://github.com/seijikohara/vizel) for full documentation.
80
+
81
+ ## License
82
+
83
+ MIT
@@ -0,0 +1,158 @@
1
+ <script lang="ts" module>
2
+ import type { Editor, JSONContent, VizelFeatureOptions } from "@vizel/core";
3
+ import type { Snippet } from "svelte";
4
+
5
+ /**
6
+ * Exposed ref type for Vizel component.
7
+ * Use with `bind:this` and access the `editor` property.
8
+ */
9
+ export interface VizelRef {
10
+ /** The underlying Tiptap editor instance */
11
+ readonly editor: Editor | null;
12
+ }
13
+
14
+ export interface VizelProps {
15
+ /** Initial content in JSON format */
16
+ initialContent?: JSONContent;
17
+ /**
18
+ * Initial content in Markdown format.
19
+ * If both initialContent and initialMarkdown are provided, initialMarkdown takes precedence.
20
+ * @example
21
+ * ```svelte
22
+ * <Vizel initialMarkdown="# Hello World\n\nThis is **bold** text." />
23
+ * ```
24
+ */
25
+ initialMarkdown?: string;
26
+ /**
27
+ * Automatically transform diagram code blocks (mermaid, graphviz) to diagram nodes
28
+ * when importing markdown content. Only applies when initialMarkdown is provided.
29
+ * @default true
30
+ */
31
+ transformDiagramsOnImport?: boolean;
32
+ /**
33
+ * Two-way binding for markdown content (bind:markdown).
34
+ * When set, markdown will be synchronized with the editor content.
35
+ */
36
+ markdown?: string;
37
+ /** Placeholder text when editor is empty */
38
+ placeholder?: string;
39
+ /** Whether the editor is editable (default: true) */
40
+ editable?: boolean;
41
+ /** Auto focus on mount */
42
+ autofocus?: boolean | "start" | "end" | "all" | number;
43
+ /** Feature configuration */
44
+ features?: VizelFeatureOptions;
45
+ /** Custom class name for the editor container */
46
+ class?: string;
47
+ /** Whether to show the bubble menu (default: true) */
48
+ showBubbleMenu?: boolean;
49
+ /** Enable embed option in bubble menu link editor (requires Embed extension) */
50
+ enableEmbed?: boolean;
51
+ /** Custom bubble menu content */
52
+ bubbleMenu?: Snippet<[{ editor: Editor }]>;
53
+ /** Additional children to render inside the editor root */
54
+ children?: Snippet<[{ editor: Editor | null }]>;
55
+ /** Callback when content changes */
56
+ onUpdate?: (props: { editor: Editor }) => void;
57
+ /** Callback when editor is created */
58
+ onCreate?: (props: { editor: Editor }) => void;
59
+ /** Callback when editor is destroyed */
60
+ onDestroy?: () => void;
61
+ /** Callback when selection changes */
62
+ onSelectionUpdate?: (props: { editor: Editor }) => void;
63
+ /** Callback when editor gets focus */
64
+ onFocus?: (props: { editor: Editor }) => void;
65
+ /** Callback when editor loses focus */
66
+ onBlur?: (props: { editor: Editor }) => void;
67
+ }
68
+ </script>
69
+
70
+ <script lang="ts">
71
+ // Vizel - All-in-one editor component
72
+ // A complete editor component that includes EditorContent and BubbleMenu.
73
+ // This is the recommended way to use Vizel for most use cases.
74
+ import { getVizelMarkdown, setVizelMarkdown } from "@vizel/core";
75
+ import { createVizelEditor } from "../runes/createVizelEditor.svelte.ts";
76
+ import VizelBubbleMenu from "./VizelBubbleMenu.svelte";
77
+ import VizelEditor from "./VizelEditor.svelte";
78
+
79
+ // Use $props() without destructuring to avoid state_referenced_locally warnings
80
+ // Props are intentionally captured once at editor creation time
81
+ let {
82
+ class: className,
83
+ showBubbleMenu = true,
84
+ enableEmbed = false,
85
+ bubbleMenu,
86
+ children,
87
+ markdown = $bindable(),
88
+ transformDiagramsOnImport = true,
89
+ ...restProps
90
+ }: VizelProps = $props();
91
+
92
+ // Track whether we're currently updating from external markdown change
93
+ let isUpdatingFromMarkdown = false;
94
+
95
+ // Wrap onUpdate to sync markdown
96
+ const originalOnUpdate = restProps.onUpdate;
97
+ const wrappedOnUpdate = (e: { editor: import("@vizel/core").Editor }) => {
98
+ originalOnUpdate?.(e);
99
+ // Update markdown binding if not updating from external change
100
+ if (!isUpdatingFromMarkdown && markdown !== undefined) {
101
+ markdown = getVizelMarkdown(e.editor);
102
+ }
103
+ };
104
+
105
+ // Capture initial values for editor creation (these are intentionally not reactive)
106
+ // The editor is created once and should not be recreated when props change
107
+ // svelte-ignore state_referenced_locally
108
+ const initialTransformDiagrams = transformDiagramsOnImport;
109
+
110
+ // Create editor with initial props - editor is intentionally created once
111
+ const editorState = createVizelEditor({
112
+ ...(restProps.initialContent !== undefined && { initialContent: restProps.initialContent }),
113
+ ...(restProps.initialMarkdown !== undefined && { initialMarkdown: restProps.initialMarkdown }),
114
+ transformDiagramsOnImport: initialTransformDiagrams,
115
+ ...(restProps.placeholder !== undefined && { placeholder: restProps.placeholder }),
116
+ editable: restProps.editable ?? true,
117
+ autofocus: restProps.autofocus ?? false,
118
+ ...(restProps.features !== undefined && { features: restProps.features }),
119
+ onUpdate: wrappedOnUpdate,
120
+ ...(restProps.onCreate !== undefined && { onCreate: restProps.onCreate }),
121
+ ...(restProps.onDestroy !== undefined && { onDestroy: restProps.onDestroy }),
122
+ ...(restProps.onSelectionUpdate !== undefined && { onSelectionUpdate: restProps.onSelectionUpdate }),
123
+ ...(restProps.onFocus !== undefined && { onFocus: restProps.onFocus }),
124
+ ...(restProps.onBlur !== undefined && { onBlur: restProps.onBlur }),
125
+ });
126
+
127
+ const editor = $derived(editorState.current);
128
+
129
+ // Watch for external markdown changes (bind:markdown)
130
+ $effect(() => {
131
+ if (markdown === undefined || !editor) return;
132
+
133
+ // Get current editor markdown
134
+ const currentMarkdown = getVizelMarkdown(editor);
135
+ if (markdown === currentMarkdown) return;
136
+
137
+ // Set flag to prevent emitting update during this update
138
+ isUpdatingFromMarkdown = true;
139
+ setVizelMarkdown(editor, markdown, {
140
+ transformDiagrams: transformDiagramsOnImport,
141
+ });
142
+ isUpdatingFromMarkdown = false;
143
+ });
144
+ </script>
145
+
146
+ <div class="vizel-root {className ?? ''}" data-vizel-root>
147
+ <VizelEditor {editor} />
148
+ {#if showBubbleMenu && editor && bubbleMenu}
149
+ <VizelBubbleMenu {editor} {enableEmbed}>
150
+ {@render bubbleMenu({ editor })}
151
+ </VizelBubbleMenu>
152
+ {:else if showBubbleMenu && editor}
153
+ <VizelBubbleMenu {editor} {enableEmbed} />
154
+ {/if}
155
+ {#if children}
156
+ {@render children({ editor })}
157
+ {/if}
158
+ </div>
@@ -0,0 +1,82 @@
1
+ import type { Editor, JSONContent, VizelFeatureOptions } from "@vizel/core";
2
+ import type { Snippet } from "svelte";
3
+ /**
4
+ * Exposed ref type for Vizel component.
5
+ * Use with `bind:this` and access the `editor` property.
6
+ */
7
+ export interface VizelRef {
8
+ /** The underlying Tiptap editor instance */
9
+ readonly editor: Editor | null;
10
+ }
11
+ export interface VizelProps {
12
+ /** Initial content in JSON format */
13
+ initialContent?: JSONContent;
14
+ /**
15
+ * Initial content in Markdown format.
16
+ * If both initialContent and initialMarkdown are provided, initialMarkdown takes precedence.
17
+ * @example
18
+ * ```svelte
19
+ * <Vizel initialMarkdown="# Hello World\n\nThis is **bold** text." />
20
+ * ```
21
+ */
22
+ initialMarkdown?: string;
23
+ /**
24
+ * Automatically transform diagram code blocks (mermaid, graphviz) to diagram nodes
25
+ * when importing markdown content. Only applies when initialMarkdown is provided.
26
+ * @default true
27
+ */
28
+ transformDiagramsOnImport?: boolean;
29
+ /**
30
+ * Two-way binding for markdown content (bind:markdown).
31
+ * When set, markdown will be synchronized with the editor content.
32
+ */
33
+ markdown?: string;
34
+ /** Placeholder text when editor is empty */
35
+ placeholder?: string;
36
+ /** Whether the editor is editable (default: true) */
37
+ editable?: boolean;
38
+ /** Auto focus on mount */
39
+ autofocus?: boolean | "start" | "end" | "all" | number;
40
+ /** Feature configuration */
41
+ features?: VizelFeatureOptions;
42
+ /** Custom class name for the editor container */
43
+ class?: string;
44
+ /** Whether to show the bubble menu (default: true) */
45
+ showBubbleMenu?: boolean;
46
+ /** Enable embed option in bubble menu link editor (requires Embed extension) */
47
+ enableEmbed?: boolean;
48
+ /** Custom bubble menu content */
49
+ bubbleMenu?: Snippet<[{
50
+ editor: Editor;
51
+ }]>;
52
+ /** Additional children to render inside the editor root */
53
+ children?: Snippet<[{
54
+ editor: Editor | null;
55
+ }]>;
56
+ /** Callback when content changes */
57
+ onUpdate?: (props: {
58
+ editor: Editor;
59
+ }) => void;
60
+ /** Callback when editor is created */
61
+ onCreate?: (props: {
62
+ editor: Editor;
63
+ }) => void;
64
+ /** Callback when editor is destroyed */
65
+ onDestroy?: () => void;
66
+ /** Callback when selection changes */
67
+ onSelectionUpdate?: (props: {
68
+ editor: Editor;
69
+ }) => void;
70
+ /** Callback when editor gets focus */
71
+ onFocus?: (props: {
72
+ editor: Editor;
73
+ }) => void;
74
+ /** Callback when editor loses focus */
75
+ onBlur?: (props: {
76
+ editor: Editor;
77
+ }) => void;
78
+ }
79
+ declare const Vizel: import("svelte").Component<VizelProps, {}, "markdown">;
80
+ type Vizel = ReturnType<typeof Vizel>;
81
+ export default Vizel;
82
+ //# sourceMappingURL=Vizel.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Vizel.svelte.d.ts","sourceRoot":"","sources":["../../src/components/Vizel.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,4CAA4C;IAC5C,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,UAAU;IACzB,qCAAqC;IACrC,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0BAA0B;IAC1B,SAAS,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IACvD,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gFAAgF;IAChF,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,iCAAiC;IACjC,UAAU,CAAC,EAAE,OAAO,CAAC,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IAC3C,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;QAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC,CAAC;IAChD,oCAAoC;IACpC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC/C,sCAAsC;IACtC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC/C,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,sCAAsC;IACtC,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACxD,sCAAsC;IACtC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC9C,uCAAuC;IACvC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAC9C;AAyGD,QAAA,MAAM,KAAK,wDAAwC,CAAC;AACpD,KAAK,KAAK,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AACtC,eAAe,KAAK,CAAC"}
@@ -0,0 +1,96 @@
1
+ <script lang="ts" module>
2
+ import type { Editor } from "@vizel/core";
3
+ import type { Snippet } from "svelte";
4
+
5
+ export interface VizelBubbleMenuProps {
6
+ /** Override the editor from context */
7
+ editor?: Editor | null;
8
+ /** Custom class name for the menu container */
9
+ class?: string;
10
+ /** Whether to show the default formatting menu */
11
+ showDefaultMenu?: boolean;
12
+ /** Plugin key for the bubble menu */
13
+ pluginKey?: string;
14
+ /** Delay in ms before updating the menu position */
15
+ updateDelay?: number;
16
+ /** Custom shouldShow function */
17
+ shouldShow?: (props: { editor: Editor; from: number; to: number }) => boolean;
18
+ /** Custom menu items (overrides default menu) */
19
+ children?: Snippet;
20
+ /** Enable embed option in link editor (requires Embed extension) */
21
+ enableEmbed?: boolean;
22
+ }
23
+ </script>
24
+
25
+ <script lang="ts">
26
+ import { BubbleMenuPlugin } from "@vizel/core";
27
+ import VizelBubbleMenuDefault from "./VizelBubbleMenuDefault.svelte";
28
+ import { getVizelContextSafe } from "./VizelContext.ts";
29
+
30
+ let {
31
+ editor: editorProp,
32
+ class: className,
33
+ showDefaultMenu = true,
34
+ pluginKey = "vizelBubbleMenu",
35
+ updateDelay = 100,
36
+ shouldShow,
37
+ children,
38
+ enableEmbed,
39
+ }: VizelBubbleMenuProps = $props();
40
+
41
+ const contextEditor = getVizelContextSafe();
42
+ const editor = $derived(editorProp ?? contextEditor?.());
43
+
44
+ let menuElement = $state<HTMLElement | null>(null);
45
+
46
+ // Handle Escape key to hide bubble menu by collapsing selection
47
+ function handleKeyDown(event: KeyboardEvent) {
48
+ if (event.key === "Escape" && editor && !editor.view.state.selection.empty) {
49
+ event.preventDefault();
50
+ editor.commands.setTextSelection(editor.view.state.selection.to);
51
+ }
52
+ }
53
+
54
+ $effect(() => {
55
+ if (!(editor && menuElement)) return;
56
+
57
+ const currentEditor = editor;
58
+ const currentPluginKey = pluginKey;
59
+
60
+ const plugin = BubbleMenuPlugin({
61
+ pluginKey: currentPluginKey,
62
+ editor: currentEditor,
63
+ element: menuElement,
64
+ updateDelay,
65
+ ...(shouldShow && {
66
+ shouldShow: ({ editor: e, from, to }) => shouldShow({ editor: e as Editor, from, to }),
67
+ }),
68
+ options: {
69
+ placement: "top",
70
+ },
71
+ });
72
+
73
+ currentEditor.registerPlugin(plugin);
74
+ document.addEventListener("keydown", handleKeyDown);
75
+
76
+ return () => {
77
+ currentEditor.unregisterPlugin(currentPluginKey);
78
+ document.removeEventListener("keydown", handleKeyDown);
79
+ };
80
+ });
81
+ </script>
82
+
83
+ {#if editor}
84
+ <div
85
+ bind:this={menuElement}
86
+ class="vizel-bubble-menu {className ?? ''}"
87
+ data-vizel-bubble-menu
88
+ style="visibility: hidden"
89
+ >
90
+ {#if children}
91
+ {@render children()}
92
+ {:else if showDefaultMenu}
93
+ <VizelBubbleMenuDefault {editor} {...(enableEmbed ? { enableEmbed } : {})} />
94
+ {/if}
95
+ </div>
96
+ {/if}
@@ -0,0 +1,28 @@
1
+ import type { Editor } from "@vizel/core";
2
+ import type { Snippet } from "svelte";
3
+ export interface VizelBubbleMenuProps {
4
+ /** Override the editor from context */
5
+ editor?: Editor | null;
6
+ /** Custom class name for the menu container */
7
+ class?: string;
8
+ /** Whether to show the default formatting menu */
9
+ showDefaultMenu?: boolean;
10
+ /** Plugin key for the bubble menu */
11
+ pluginKey?: string;
12
+ /** Delay in ms before updating the menu position */
13
+ updateDelay?: number;
14
+ /** Custom shouldShow function */
15
+ shouldShow?: (props: {
16
+ editor: Editor;
17
+ from: number;
18
+ to: number;
19
+ }) => boolean;
20
+ /** Custom menu items (overrides default menu) */
21
+ children?: Snippet;
22
+ /** Enable embed option in link editor (requires Embed extension) */
23
+ enableEmbed?: boolean;
24
+ }
25
+ declare const VizelBubbleMenu: import("svelte").Component<VizelBubbleMenuProps, {}, "">;
26
+ type VizelBubbleMenu = ReturnType<typeof VizelBubbleMenu>;
27
+ export default VizelBubbleMenu;
28
+ //# sourceMappingURL=VizelBubbleMenu.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VizelBubbleMenu.svelte.d.ts","sourceRoot":"","sources":["../../src/components/VizelBubbleMenu.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,MAAM,WAAW,oBAAoB;IACnC,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,+CAA+C;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kDAAkD;IAClD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,qCAAqC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iCAAiC;IACjC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC;IAC9E,iDAAiD;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oEAAoE;IACpE,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AA+ED,QAAA,MAAM,eAAe,0DAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
@@ -0,0 +1,45 @@
1
+ <script lang="ts" module>
2
+ import type { Snippet } from "svelte";
3
+
4
+ export interface VizelBubbleMenuButtonProps {
5
+ /** Whether the button is in active state */
6
+ isActive?: boolean;
7
+ /** Whether the button is disabled */
8
+ disabled?: boolean;
9
+ /** Tooltip title */
10
+ title?: string;
11
+ /** Custom class name */
12
+ class?: string;
13
+ /** Button content */
14
+ children: Snippet;
15
+ /** Click handler */
16
+ onclick?: () => void;
17
+ /** Action identifier for testing */
18
+ action?: string;
19
+ }
20
+ </script>
21
+
22
+ <script lang="ts">
23
+ let {
24
+ isActive = false,
25
+ disabled = false,
26
+ title,
27
+ class: className,
28
+ children,
29
+ onclick,
30
+ action,
31
+ }: VizelBubbleMenuButtonProps = $props();
32
+ </script>
33
+
34
+ <button
35
+ type="button"
36
+ {disabled}
37
+ aria-pressed={isActive}
38
+ class="vizel-bubble-menu-button {isActive ? 'is-active' : ''} {className ?? ''}"
39
+ {title}
40
+ data-active={isActive || undefined}
41
+ data-action={action}
42
+ {onclick}
43
+ >
44
+ {@render children()}
45
+ </button>
@@ -0,0 +1,21 @@
1
+ import type { Snippet } from "svelte";
2
+ export interface VizelBubbleMenuButtonProps {
3
+ /** Whether the button is in active state */
4
+ isActive?: boolean;
5
+ /** Whether the button is disabled */
6
+ disabled?: boolean;
7
+ /** Tooltip title */
8
+ title?: string;
9
+ /** Custom class name */
10
+ class?: string;
11
+ /** Button content */
12
+ children: Snippet;
13
+ /** Click handler */
14
+ onclick?: () => void;
15
+ /** Action identifier for testing */
16
+ action?: string;
17
+ }
18
+ declare const VizelBubbleMenuButton: import("svelte").Component<VizelBubbleMenuButtonProps, {}, "">;
19
+ type VizelBubbleMenuButton = ReturnType<typeof VizelBubbleMenuButton>;
20
+ export default VizelBubbleMenuButton;
21
+ //# sourceMappingURL=VizelBubbleMenuButton.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VizelBubbleMenuButton.svelte.d.ts","sourceRoot":"","sources":["../../src/components/VizelBubbleMenuButton.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,MAAM,WAAW,0BAA0B;IACzC,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oBAAoB;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wBAAwB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,oBAAoB;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAsBD,QAAA,MAAM,qBAAqB,gEAAwC,CAAC;AACpE,KAAK,qBAAqB,GAAG,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACtE,eAAe,qBAAqB,CAAC"}
@@ -0,0 +1,135 @@
1
+ <script lang="ts" module>
2
+ import type { Editor, VizelColorDefinition } from "@vizel/core";
3
+
4
+ export interface VizelBubbleMenuColorPickerProps {
5
+ /** The editor instance */
6
+ editor: Editor;
7
+ /** Color picker type */
8
+ type: "textColor" | "highlight";
9
+ /** Custom color palette */
10
+ colors?: VizelColorDefinition[];
11
+ /** Custom class name */
12
+ class?: string;
13
+ /** Enable custom color input (default: true) */
14
+ allowCustomColor?: boolean;
15
+ /** Enable recent colors (default: true) */
16
+ showRecentColors?: boolean;
17
+ }
18
+ </script>
19
+
20
+ <script lang="ts">
21
+ import {
22
+ addVizelRecentColor,
23
+ getVizelRecentColors,
24
+ VIZEL_HIGHLIGHT_COLORS,
25
+ VIZEL_TEXT_COLORS,
26
+ } from "@vizel/core";
27
+ import VizelColorPicker from "./VizelColorPicker.svelte";
28
+ import VizelIcon from "./VizelIcon.svelte";
29
+
30
+ let {
31
+ editor,
32
+ type,
33
+ colors,
34
+ class: className,
35
+ allowCustomColor = true,
36
+ showRecentColors = true,
37
+ }: VizelBubbleMenuColorPickerProps = $props();
38
+
39
+ let isOpen = $state(false);
40
+ let recentColors = $state<string[]>([]);
41
+ let containerRef: HTMLDivElement | null = $state(null);
42
+
43
+ const colorPalette = $derived(colors ?? (type === "textColor" ? VIZEL_TEXT_COLORS : VIZEL_HIGHLIGHT_COLORS));
44
+
45
+ const currentColor = $derived.by(() => {
46
+ if (type === "textColor") {
47
+ return editor.getAttributes("textStyle").color;
48
+ }
49
+ return editor.getAttributes("highlight").color;
50
+ });
51
+
52
+ const isTextColor = $derived(type === "textColor");
53
+
54
+ const noneValues = $derived(isTextColor ? ["inherit"] : ["transparent"]);
55
+
56
+ // Load recent colors when dropdown opens
57
+ $effect(() => {
58
+ if (isOpen && showRecentColors) {
59
+ recentColors = getVizelRecentColors(type);
60
+ }
61
+ });
62
+
63
+ function handleColorChange(color: string) {
64
+ if (type === "textColor") {
65
+ if (color === "inherit") {
66
+ editor.chain().focus().unsetColor().run();
67
+ } else {
68
+ editor.chain().focus().setColor(color).run();
69
+ addVizelRecentColor(type, color);
70
+ }
71
+ } else if (color === "transparent") {
72
+ editor.chain().focus().unsetHighlight().run();
73
+ } else {
74
+ editor.chain().focus().toggleHighlight({ color }).run();
75
+ addVizelRecentColor(type, color);
76
+ }
77
+ isOpen = false;
78
+ }
79
+
80
+ function handleClickOutside(event: MouseEvent) {
81
+ if (containerRef && !containerRef.contains(event.target as Node)) {
82
+ isOpen = false;
83
+ }
84
+ }
85
+
86
+ $effect(() => {
87
+ document.addEventListener("mousedown", handleClickOutside);
88
+ return () => {
89
+ document.removeEventListener("mousedown", handleClickOutside);
90
+ };
91
+ });
92
+
93
+ function getTriggerStyle(): string {
94
+ if (isTextColor) {
95
+ return `color: ${currentColor || "inherit"}`;
96
+ }
97
+ return `--highlight-color: ${currentColor || "transparent"}`;
98
+ }
99
+ </script>
100
+
101
+ <div
102
+ bind:this={containerRef}
103
+ class="vizel-color-picker {className ?? ''}"
104
+ data-type={type}
105
+ >
106
+ <button
107
+ type="button"
108
+ class="vizel-bubble-menu-button vizel-color-picker-trigger {currentColor ? 'has-color' : ''}"
109
+ title={isTextColor ? "Text Color" : "Highlight"}
110
+ data-action={type}
111
+ style={getTriggerStyle()}
112
+ onclick={() => (isOpen = !isOpen)}
113
+ >
114
+ {#if isTextColor}
115
+ <VizelIcon name="textColor" />
116
+ {:else}
117
+ <VizelIcon name="highlighter" />
118
+ {/if}
119
+ </button>
120
+
121
+ {#if isOpen}
122
+ <div class="vizel-color-picker-dropdown">
123
+ <VizelColorPicker
124
+ colors={colorPalette}
125
+ value={currentColor}
126
+ label={isTextColor ? "Text color palette" : "Highlight color palette"}
127
+ {allowCustomColor}
128
+ {recentColors}
129
+ {showRecentColors}
130
+ {noneValues}
131
+ onchange={handleColorChange}
132
+ />
133
+ </div>
134
+ {/if}
135
+ </div>
@@ -0,0 +1,19 @@
1
+ import type { Editor, VizelColorDefinition } from "@vizel/core";
2
+ export interface VizelBubbleMenuColorPickerProps {
3
+ /** The editor instance */
4
+ editor: Editor;
5
+ /** Color picker type */
6
+ type: "textColor" | "highlight";
7
+ /** Custom color palette */
8
+ colors?: VizelColorDefinition[];
9
+ /** Custom class name */
10
+ class?: string;
11
+ /** Enable custom color input (default: true) */
12
+ allowCustomColor?: boolean;
13
+ /** Enable recent colors (default: true) */
14
+ showRecentColors?: boolean;
15
+ }
16
+ declare const VizelBubbleMenuColorPicker: import("svelte").Component<VizelBubbleMenuColorPickerProps, {}, "">;
17
+ type VizelBubbleMenuColorPicker = ReturnType<typeof VizelBubbleMenuColorPicker>;
18
+ export default VizelBubbleMenuColorPicker;
19
+ //# sourceMappingURL=VizelBubbleMenuColorPicker.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VizelBubbleMenuColorPicker.svelte.d.ts","sourceRoot":"","sources":["../../src/components/VizelBubbleMenuColorPicker.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEhE,MAAM,WAAW,+BAA+B;IAC9C,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,wBAAwB;IACxB,IAAI,EAAE,WAAW,GAAG,WAAW,CAAC;IAChC,2BAA2B;IAC3B,MAAM,CAAC,EAAE,oBAAoB,EAAE,CAAC;IAChC,wBAAwB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,2CAA2C;IAC3C,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AA4GD,QAAA,MAAM,0BAA0B,qEAAwC,CAAC;AACzE,KAAK,0BAA0B,GAAG,UAAU,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAChF,eAAe,0BAA0B,CAAC"}