@bagelink/vue 0.0.1260 → 0.0.1268

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 (56) hide show
  1. package/dist/components/AddressSearch.vue.d.ts +6 -0
  2. package/dist/components/AddressSearch.vue.d.ts.map +1 -1
  3. package/dist/components/DataTable/DataTable.vue.d.ts.map +1 -1
  4. package/dist/components/DropDown.vue.d.ts +51 -48
  5. package/dist/components/DropDown.vue.d.ts.map +1 -1
  6. package/dist/components/form/BagelForm.vue.d.ts.map +1 -1
  7. package/dist/components/form/FieldArray.vue.d.ts.map +1 -1
  8. package/dist/components/form/inputs/DateInput.vue.d.ts +4 -1
  9. package/dist/components/form/inputs/DateInput.vue.d.ts.map +1 -1
  10. package/dist/components/form/inputs/PasswordInput.vue.d.ts.map +1 -1
  11. package/dist/components/form/inputs/RadioGroup.vue.d.ts +1 -1
  12. package/dist/components/form/inputs/RichText/composables/useCommands.d.ts.map +1 -1
  13. package/dist/components/form/inputs/RichText/composables/useEditor.d.ts +31 -23
  14. package/dist/components/form/inputs/RichText/composables/useEditor.d.ts.map +1 -1
  15. package/dist/components/form/inputs/RichText/composables/useEditorKeyboard.d.ts +2 -1
  16. package/dist/components/form/inputs/RichText/composables/useEditorKeyboard.d.ts.map +1 -1
  17. package/dist/components/form/inputs/RichText/config.d.ts +2 -1
  18. package/dist/components/form/inputs/RichText/config.d.ts.map +1 -1
  19. package/dist/components/form/inputs/RichText/index.vue.d.ts.map +1 -1
  20. package/dist/components/form/inputs/RichText/utils/commands.d.ts +1 -0
  21. package/dist/components/form/inputs/RichText/utils/commands.d.ts.map +1 -1
  22. package/dist/components/form/inputs/RichText/utils/media.d.ts +5 -3
  23. package/dist/components/form/inputs/RichText/utils/media.d.ts.map +1 -1
  24. package/dist/components/form/inputs/RichText/utils/selection.d.ts.map +1 -1
  25. package/dist/components/form/inputs/SelectInput.vue.d.ts +12 -0
  26. package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
  27. package/dist/components/form/inputs/TelInput.vue.d.ts +9 -3
  28. package/dist/components/form/inputs/TelInput.vue.d.ts.map +1 -1
  29. package/dist/components/form/useBagelFormState.d.ts.map +1 -1
  30. package/dist/editor-7QC0nG_c.js +4 -0
  31. package/dist/editor-CpMNx6Eo.cjs +4 -0
  32. package/dist/index.cjs +1731 -1191
  33. package/dist/index.mjs +1732 -1192
  34. package/dist/style.css +90 -83
  35. package/dist/utils/index.d.ts +1 -0
  36. package/dist/utils/index.d.ts.map +1 -1
  37. package/package.json +1 -1
  38. package/src/components/DataTable/DataTable.vue +7 -1
  39. package/src/components/Dropdown.vue +5 -2
  40. package/src/components/form/BagelForm.vue +2 -13
  41. package/src/components/form/FieldArray.vue +3 -0
  42. package/src/components/form/inputs/DateInput.vue +341 -162
  43. package/src/components/form/inputs/PasswordInput.vue +5 -1
  44. package/src/components/form/inputs/RichText/components/EditorToolbar.vue +2 -2
  45. package/src/components/form/inputs/RichText/composables/useCommands.ts +53 -97
  46. package/src/components/form/inputs/RichText/composables/useEditor.ts +377 -270
  47. package/src/components/form/inputs/RichText/composables/useEditorKeyboard.ts +124 -58
  48. package/src/components/form/inputs/RichText/config.ts +27 -3
  49. package/src/components/form/inputs/RichText/editor.css +29 -0
  50. package/src/components/form/inputs/RichText/index.vue +129 -55
  51. package/src/components/form/inputs/RichText/richTextTypes.d.ts +35 -49
  52. package/src/components/form/inputs/RichText/utils/commands.ts +181 -0
  53. package/src/components/form/inputs/RichText/utils/media.ts +64 -3
  54. package/src/components/form/inputs/RichText/utils/selection.ts +40 -5
  55. package/src/components/form/useBagelFormState.ts +2 -14
  56. package/src/utils/index.ts +15 -0
@@ -1,66 +1,132 @@
1
- export function useEditorKeyboard(doc: Document, handleToolbarAction: (action: string, value?: string) => void): void {
1
+ import type { CommandExecutor } from '../utils/commands'
2
+
3
+ interface KeyboardShortcut {
4
+ key: string
5
+ modifiers?: {
6
+ ctrl?: boolean
7
+ alt?: boolean
8
+ shift?: boolean
9
+ }
10
+ command: string
11
+ }
12
+
13
+ const shortcuts: KeyboardShortcut[] = [
14
+ { key: 'b', command: 'bold' },
15
+ { key: 'i', command: 'italic' },
16
+ { key: 'u', command: 'underline' },
17
+ { key: 'z', command: 'undo' },
18
+ { key: 'z', modifiers: { shift: true }, command: 'redo' },
19
+ { key: 'y', command: 'redo' },
20
+ { key: '.', modifiers: { shift: true }, command: 'orderedList' },
21
+ { key: '/', modifiers: { shift: true }, command: 'unorderedList' },
22
+ { key: ']', command: 'indent' },
23
+ { key: '[', command: 'outdent' },
24
+ ...Array.from({ length: 6 }, (_, i) => ({
25
+ key: String(i + 1),
26
+ modifiers: { alt: true },
27
+ command: `h${i + 1}`
28
+ }))
29
+ ]
30
+
31
+ export function useEditorKeyboard(doc: Document, executor: CommandExecutor): void {
32
+ // Handle keyboard shortcuts
2
33
  doc.addEventListener('keydown', (e) => {
3
- if (e.ctrlKey || e.metaKey) {
4
- switch (e.key) {
5
- case 'b':
6
- e.preventDefault()
7
- handleToolbarAction('bold')
8
- break
9
- case 'i':
10
- e.preventDefault()
11
- handleToolbarAction('italic')
12
- break
13
- case 'u':
14
- e.preventDefault()
15
- handleToolbarAction('underline')
16
- break
17
- case 'z':
18
- e.preventDefault()
19
- if (e.shiftKey) {
20
- handleToolbarAction('redo')
21
- } else {
22
- handleToolbarAction('undo')
23
- }
24
- break
25
- case 'y':
26
- e.preventDefault()
27
- handleToolbarAction('redo')
28
- break
29
- // List shortcuts
30
- case '.':
31
- if (e.shiftKey) {
32
- e.preventDefault()
33
- handleToolbarAction('orderedList')
34
- }
35
- break
36
- case '/':
37
- if (e.shiftKey) {
34
+ // Handle Enter key in lists
35
+ if (e.key === 'Enter' && !e.shiftKey) {
36
+ const selection = doc.getSelection()
37
+ if (!selection || !selection.rangeCount) return
38
+
39
+ const range = selection.getRangeAt(0)
40
+ const container = range.commonAncestorContainer
41
+ const listItem = (container.nodeType === 3 ? container.parentElement : container as Element)?.closest('li')
42
+
43
+ if (listItem) {
44
+ // If we're at the end of a list item
45
+ if (range.collapsed && isAtEndOfNode(listItem, range)) {
46
+ // If the list item is empty, break out of the list
47
+ if (isNodeEmpty(listItem)) {
38
48
  e.preventDefault()
39
- handleToolbarAction('unorderedList')
40
- }
41
- break
42
- // Heading shortcuts
43
- case '1':
44
- case '2':
45
- case '3':
46
- case '4':
47
- case '5':
48
- case '6':
49
- if (e.altKey) {
49
+ // Create a new paragraph after the list
50
+ const list = listItem.parentElement
51
+ if (!list) return
52
+
53
+ // Remove the empty list item
54
+ listItem.remove()
55
+
56
+ // If the list is now empty, remove it
57
+ if (!list.querySelector('li')) {
58
+ const p = doc.createElement('p')
59
+ p.innerHTML = '<br>'
60
+ list.parentNode?.replaceChild(p, list)
61
+
62
+ // Set cursor in the new paragraph
63
+ range.selectNodeContents(p)
64
+ range.collapse(true)
65
+ selection.removeAllRanges()
66
+ selection.addRange(range)
67
+ }
68
+ } else {
69
+ // Create a new list item
50
70
  e.preventDefault()
51
- handleToolbarAction(`h${e.key}`)
71
+ const newLi = doc.createElement('li')
72
+ newLi.innerHTML = '&nbsp;<br>' // Use non-breaking space with br
73
+ listItem.insertAdjacentElement('afterend', newLi)
74
+
75
+ // Move cursor to new list item
76
+ range.selectNodeContents(newLi)
77
+ range.collapse(true)
78
+ selection.removeAllRanges()
79
+ selection.addRange(range)
52
80
  }
53
- break
54
- // Indentation
55
- case ']':
56
- e.preventDefault()
57
- handleToolbarAction('indent')
58
- break
59
- case '[':
60
- e.preventDefault()
61
- handleToolbarAction('outdent')
62
- break
81
+ }
63
82
  }
64
83
  }
84
+
85
+ // Handle other keyboard shortcuts
86
+ if (!e.ctrlKey && !e.metaKey) return
87
+
88
+ const matchingShortcut = shortcuts.find((shortcut) => {
89
+ const keyMatch = shortcut.key === e.key
90
+ const modifiersMatch = !shortcut.modifiers || (
91
+ (!shortcut.modifiers.ctrl || e.ctrlKey || e.metaKey)
92
+ && (!shortcut.modifiers.alt || e.altKey)
93
+ && (!shortcut.modifiers.shift || e.shiftKey)
94
+ )
95
+ return keyMatch && modifiersMatch
96
+ })
97
+
98
+ if (matchingShortcut) {
99
+ e.preventDefault()
100
+ executor.execute(matchingShortcut.command)
101
+ }
65
102
  })
66
103
  }
104
+
105
+ // Helper function to check if we're at the end of a node
106
+ function isAtEndOfNode(node: Node, range: Range): boolean {
107
+ if (node.nodeType === 3) { // Text node
108
+ return range.startOffset === (node as Text).length
109
+ }
110
+
111
+ const { lastChild } = node
112
+ if (!lastChild) return true
113
+
114
+ if (lastChild.nodeType === 3) { // Text node
115
+ return range.startContainer === lastChild && range.startOffset === lastChild.textContent?.length
116
+ }
117
+
118
+ return range.startContainer === node && range.startOffset === node.childNodes.length
119
+ }
120
+
121
+ // Helper function to check if a node is empty (contains only whitespace or <br> or &nbsp;)
122
+ function isNodeEmpty(node: Node): boolean {
123
+ const text = node.textContent?.replace(/\s/g, '') || '' // Remove non-breaking spaces and whitespace
124
+ if (text) return false
125
+
126
+ // Check for <br> tags
127
+ const brElements = (node as Element).getElementsByTagName('br')
128
+ if (brElements.length === 0) return true
129
+
130
+ // If there's only one <br> and it's the only content (besides potential &nbsp;), consider it empty
131
+ return brElements.length === 1 && node.childNodes.length <= 2 // Allow for &nbsp; + <br>
132
+ }
@@ -16,7 +16,31 @@ export const tableTools: ToolbarConfig = [
16
16
  'deleteTable'
17
17
  ]
18
18
 
19
- export const defaultToolbarConfig: ToolbarConfig = [
19
+ export const basicToolbarConfig: ToolbarConfig = [
20
+ 'h2',
21
+ 'h3',
22
+ 'h4',
23
+ 'h5',
24
+ 'h6',
25
+ 'separator',
26
+ 'p',
27
+ 'blockquote',
28
+ 'orderedList',
29
+ 'unorderedList',
30
+ 'separator',
31
+ 'bold',
32
+ 'italic',
33
+ 'underline',
34
+ 'separator',
35
+ 'link',
36
+ 'image',
37
+ 'embed',
38
+ 'clear',
39
+ 'splitView',
40
+ 'fullScreen',
41
+ ]
42
+
43
+ export const fullToolbarConfig: ToolbarConfig = [
20
44
  'h2',
21
45
  'h3',
22
46
  'h4',
@@ -39,7 +63,7 @@ export const defaultToolbarConfig: ToolbarConfig = [
39
63
  'separator',
40
64
  'link',
41
65
  'image',
42
- // 'youtube',
66
+ 'embed',
43
67
  'separator',
44
68
  'splitView',
45
69
  'clear',
@@ -66,7 +90,7 @@ export const toolbarOptions: ToolbarOption[] = [
66
90
  { name: 'unorderedList', label: 'Unordered List', icon: 'format_list_bulleted' },
67
91
  { name: 'link', label: 'Link', icon: 'add_link' },
68
92
  { name: 'image', label: 'Image', icon: 'add_photo_alternate' },
69
- { name: 'youtube', label: 'YouTube', icon: 'youtube_activity' },
93
+ { name: 'embed', label: 'Embed', icon: 'media_link' },
70
94
  { name: 'splitView', label: 'Split View', icon: 'code' },
71
95
  { name: 'clear', label: 'Clear Formatting', icon: 'format_clear' },
72
96
  { name: 'alignLeft', label: 'Align Left', icon: 'format_align_left' },
@@ -26,3 +26,32 @@ td {
26
26
  th {
27
27
  background-color: #f4f4f4;
28
28
  }
29
+
30
+ /* Add styles for embedded content */
31
+ iframe {
32
+ max-width: 100%;
33
+ border: none;
34
+ display: block;
35
+ margin: 1em auto;
36
+ }
37
+
38
+ /* Responsive iframe wrapper */
39
+ div:has(> iframe) {
40
+ position: relative;
41
+ width: 100%;
42
+ margin: 1em 0;
43
+ text-align: center;
44
+ }
45
+
46
+ /* Ensure iframes don't overflow their containers */
47
+ div:has(> iframe) iframe {
48
+ max-width: 100%;
49
+ margin: 0;
50
+ }
51
+
52
+ /* Add a subtle border to distinguish embedded content */
53
+ iframe:not([class*='editableContent']) {
54
+ border: 1px solid var(--border-color);
55
+ border-radius: 4px;
56
+ background: white;
57
+ }
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import type { ToolbarConfig } from './richTextTypes'
3
3
  import { CodeEditor, copyText, Btn } from '@bagelink/vue'
4
- import { watch } from 'vue'
4
+ import { watch, onUnmounted, ref } from 'vue'
5
5
  import EditorToolbar from './components/EditorToolbar.vue'
6
6
  import { useCommands } from './composables/useCommands'
7
7
  import { useEditor } from './composables/useEditor'
@@ -10,70 +10,134 @@ import { useEditorKeyboard } from './composables/useEditorKeyboard'
10
10
  const props = defineProps<{ modelValue: string, toolbarConfig?: ToolbarConfig, debug?: boolean, label?: string }>()
11
11
  const emit = defineEmits(['update:modelValue'])
12
12
 
13
- const iframe = $ref<HTMLIFrameElement>()
13
+ const iframe = ref<HTMLIFrameElement>()
14
14
  const editor = useEditor()
15
- const commands = useCommands(editor.state, props.debug ? editor.debug : undefined)
15
+ const isInitializing = ref(false)
16
+ const hasInitialized = ref(false)
17
+
18
+ // Initialize debugger if debug mode is enabled
19
+ if (props.debug) {
20
+ editor.initDebugger()
21
+ }
22
+
23
+ const commands = useCommands(editor.state, editor.state.debug)
16
24
 
17
25
  // Expose debug methods if debug mode is enabled
18
- const debugMethods = $computed(() => props.debug ? editor.debug : undefined)
26
+ const debugMethods = $computed(() => editor.state.debug)
19
27
  const hasRTL = $computed(() => /[\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC]/.test(props.modelValue))
28
+
29
+ // Cleanup on component unmount
30
+ onUnmounted(() => {
31
+ editor.cleanup()
32
+ })
33
+
20
34
  async function initEditor() {
21
- if (!iframe) {
22
- setTimeout(initEditor, 100)
35
+ console.log('[initEditor] Starting, isInitializing:', isInitializing.value, 'hasInitialized:', hasInitialized.value)
36
+ if (isInitializing.value || !iframe.value || hasInitialized.value) {
37
+ console.log('[initEditor] Skipped - already initializing/initialized or no iframe')
23
38
  return
24
39
  }
25
- editor.state.content = props.modelValue || ''
26
- const doc = iframe.contentDocument || iframe.contentWindow?.document
27
- if (!doc) return
28
-
29
- doc.designMode = 'on'
30
- doc.body.contentEditable = 'true'
31
-
32
- // Set default direction based on content
33
- doc.body.dir = hasRTL ? 'rtl' : 'ltr'
34
-
35
- const style = doc.createElement('style')
36
- style.textContent = (await import('./editor.css?inline')).default
37
- doc.head.appendChild(style)
38
-
39
- editor.init(doc)
40
- useEditorKeyboard(doc, commands.execute)
41
-
42
- // Initial cleanup and ensure there's at least one paragraph
43
- if (!doc.body.firstElementChild) {
44
- const p = doc.createElement('p')
45
- p.dir = doc.body.dir
46
- p.innerHTML = '<br>'
47
- doc.body.appendChild(p)
48
- } else {
49
- // Convert any direct text nodes to paragraphs
50
- const walker = doc.createTreeWalker(doc.body, NodeFilter.SHOW_TEXT)
51
- const textNodes: Text[] = []
52
- let node: Node | null
53
- while ((node = walker.nextNode())) {
54
- if (node.parentElement === doc.body) {
55
- textNodes.push(node as Text)
56
- }
40
+
41
+ isInitializing.value = true
42
+
43
+ try {
44
+ // Load styles first
45
+ const editorStyles = await import('./editor.css?inline')
46
+
47
+ // Create a complete HTML document with proper doctype and meta tags
48
+ const htmlContent = `
49
+ <!DOCTYPE html>
50
+ <html>
51
+ <head>
52
+ <meta charset="UTF-8">
53
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
54
+ <meta http-equiv="Content-Security-Policy" content="
55
+ default-src * data: blob: 'unsafe-inline' 'unsafe-eval';
56
+ img-src * data: blob:;
57
+ style-src * 'unsafe-inline';
58
+ script-src * 'unsafe-inline' 'unsafe-eval';
59
+ frame-src * data: blob:;
60
+ connect-src *;
61
+ media-src *;
62
+ ">
63
+ <base target="_blank">
64
+ <style id="editor-styles">${editorStyles.default}</style>
65
+ </head>
66
+ <body>${props.modelValue || ''}</body>
67
+ </html>
68
+ `
69
+
70
+ // Write the complete HTML document to the iframe
71
+ const doc = iframe.value.contentDocument || iframe.value.contentWindow?.document
72
+ if (!doc) {
73
+ console.warn('[initEditor] No document found')
74
+ return
57
75
  }
58
- textNodes.forEach((textNode) => {
59
- if (textNode.textContent?.trim()) {
60
- const p = doc.createElement('p')
61
- p.dir = doc.body.dir
62
- p.appendChild(textNode.cloneNode())
63
- doc.body.replaceChild(p, textNode)
64
- } else {
65
- doc.body.removeChild(textNode)
76
+
77
+ // First write the content
78
+ doc.open()
79
+ doc.write(htmlContent)
80
+ doc.close()
81
+
82
+ // Then make it editable after a short delay
83
+ await new Promise(resolve => setTimeout(resolve, 0))
84
+
85
+ doc.designMode = 'on'
86
+ doc.body.contentEditable = 'true'
87
+
88
+ // Set default direction based on content
89
+ doc.body.dir = hasRTL ? 'rtl' : 'ltr'
90
+
91
+ editor.init(doc)
92
+ useEditorKeyboard(doc, commands)
93
+
94
+ // Initial cleanup and ensure there's at least one paragraph
95
+ if (!doc.body.firstElementChild) {
96
+ const p = doc.createElement('p')
97
+ p.dir = doc.body.dir
98
+ p.innerHTML = '<br>'
99
+ doc.body.appendChild(p)
100
+ } else {
101
+ // Convert any direct text nodes to paragraphs
102
+ const walker = doc.createTreeWalker(doc.body, NodeFilter.SHOW_TEXT)
103
+ const textNodes: Text[] = []
104
+ let node: Node | null
105
+ while ((node = walker.nextNode())) {
106
+ if (node.parentElement === doc.body) {
107
+ textNodes.push(node as Text)
108
+ }
66
109
  }
67
- })
68
- }
110
+ textNodes.forEach((textNode) => {
111
+ if (textNode.textContent?.trim()) {
112
+ const p = doc.createElement('p')
113
+ p.dir = doc.body.dir
114
+ p.appendChild(textNode.cloneNode())
115
+ doc.body.replaceChild(p, textNode)
116
+ } else {
117
+ doc.body.removeChild(textNode)
118
+ }
119
+ })
120
+ }
69
121
 
70
- doc.body.focus()
122
+ doc.body.focus()
123
+ hasInitialized.value = true
124
+ } catch (error) {
125
+ console.error('[initEditor] Error during initialization:', error)
126
+ } finally {
127
+ isInitializing.value = false
128
+ }
71
129
  }
72
130
 
73
- watch(() => props.modelValue, (newValue) => {
131
+ // Reset initialization state when content changes significantly
132
+ watch(() => props.modelValue, (newValue, oldValue) => {
74
133
  if (newValue !== editor.state.content) {
75
- editor.state.content = newValue
76
- editor.updateContent('html')
134
+ // Only reset if content change is significant (not just minor edits)
135
+ if (!oldValue || Math.abs(newValue.length - oldValue.length) > 50) {
136
+ console.log('[watch] Significant content change, resetting initialization state')
137
+ hasInitialized.value = false
138
+ editor.state.content = newValue
139
+ editor.updateState.content('html')
140
+ }
77
141
  }
78
142
  })
79
143
 
@@ -95,11 +159,21 @@ watch(() => editor.state.content, (newValue) => {
95
159
  />
96
160
  <div class="editor-container" :class="{ 'split-view': editor.state.isSplitView }">
97
161
  <div class="content-area radius-05">
98
- <iframe id="rich-text-iframe" ref="iframe" class="editableContent" title="Editor" @load="initEditor" />
162
+ <iframe
163
+ id="rich-text-iframe"
164
+ ref="iframe"
165
+ class="editableContent"
166
+ title="Editor"
167
+ sandbox="allow-same-origin allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-scripts allow-top-navigation allow-top-navigation-by-user-activation"
168
+ src="about:blank"
169
+ @load="initEditor"
170
+ />
99
171
  </div>
100
172
  <CodeEditor
101
- v-if="editor.state.isSplitView" v-model="editor.state.content" language="html"
102
- @update:modelValue="editor.updateContent('html')"
173
+ v-if="editor.state.isSplitView"
174
+ v-model="editor.state.content"
175
+ language="html"
176
+ @update:modelValue="editor.updateState.content('html')"
103
177
  />
104
178
  </div>
105
179
  <div v-if="debug" class="flex">
@@ -1,27 +1,42 @@
1
- import type { IconType } from '@bagelink/vue'
1
+ import type { Modal as BagelModal } from '@bagelink/vue'
2
2
 
3
- export interface Modal {
4
- showModalForm: (options: {
5
- title: string
6
- schema: any[]
7
- onSubmit: (data: any) => void
8
- }) => void
3
+ export interface EditorDebuggerInstance {
4
+ logCommand: (command: string, value: string | undefined, state: any) => void
5
+ logPaste: (data: DataTransfer, state: any) => void
6
+ logKeyboard: (event: KeyboardEvent, state: any) => void
7
+ logSelection: (state: any) => void
8
+ logInput: (inputType: string, data: string | null, state: any) => void
9
+ getSession: () => any
10
+ clearSession: () => void
11
+ downloadSession: () => void
12
+ exportSession: () => string
13
+ exportSessionWithPrompt: (userMessage?: string) => string
14
+ }
15
+
16
+ export interface EditorDebugInterface {
17
+ debugger: EditorDebuggerInstance
18
+ logCommand: (command: string, value?: string) => void
19
+ getSession: () => any
20
+ clearSession: () => void
21
+ downloadSession: () => void
22
+ exportDebugWithPrompt: (message?: string) => string | undefined
9
23
  }
10
24
 
11
25
  export interface EditorState {
12
- isFullscreen: boolean
13
- hasInit: boolean
14
- isCodeView: boolean
15
- isSplitView: boolean
16
- selectedStyles: Set<string>
17
26
  content: string
18
- rangeCount: number
19
- selection?: Selection | null
20
- range?: Range | null
21
27
  doc?: Document
22
- modal?: Modal
28
+ selection: Selection | null
29
+ selectedStyles: Set<string>
30
+ isFullscreen: boolean
31
+ isSplitView: boolean
32
+ isCodeView: boolean
33
+ hasInit: boolean
23
34
  undoStack: string[]
24
35
  redoStack: string[]
36
+ rangeCount: number
37
+ range: Range | null
38
+ modal: BagelModal
39
+ debug?: EditorDebugInterface
25
40
  }
26
41
 
27
42
  export type FormattingCommand =
@@ -33,49 +48,20 @@ export type FormattingCommand =
33
48
  | 'unorderedList'
34
49
  | 'link'
35
50
  | 'image'
36
- | 'youtube'
51
+ | 'embed'
37
52
  | 'table'
38
53
  | 'splitView'
39
54
  | 'codeView'
40
55
 
41
56
  export type HeadingLevel = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'
42
57
 
43
- export type ToolbarConfigOption =
44
- | FormattingCommand
45
- | HeadingLevel
46
- | 'p'
47
- | 'blockquote'
48
- | 'separator'
49
- | 'fullScreen'
50
- | 'clear'
51
- | 'mergeCells'
52
- | 'splitCells'
53
- | 'addRowBefore'
54
- | 'addRowAfter'
55
- | 'deleteRow'
56
- | 'alignLeft'
57
- | 'alignCenter'
58
- | 'alignRight'
59
- | 'alignJustify'
60
- | 'indent'
61
- | 'outdent'
62
- | 'fontColor'
63
- | 'bgColor'
64
- | 'insertTable'
65
- | 'deleteTable'
66
- | 'insertRowAbove'
67
- | 'insertRowBelow'
68
- | 'insertColumnLeft'
69
- | 'insertColumnRight'
70
- | 'deleteColumn'
71
- | 'undo'
72
- | 'redo'
58
+ export type ToolbarConfigOption = string
73
59
 
74
60
  export type ToolbarConfig = ToolbarConfigOption[]
75
61
 
76
62
  export interface ToolbarOption {
77
- name: ToolbarConfigOption
63
+ name: string
78
64
  label?: string
79
- icon?: IconType
65
+ icon?: string
80
66
  class?: string
81
67
  }