@bagelink/vue 1.17.2 → 1.18.3

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 (97) hide show
  1. package/dist/assetTransport.d.ts +9 -31
  2. package/dist/assetTransport.d.ts.map +1 -1
  3. package/dist/assets.d.ts +39 -20
  4. package/dist/assets.d.ts.map +1 -1
  5. package/dist/components/AddressSearch.vue.d.ts +40 -36
  6. package/dist/components/AddressSearch.vue.d.ts.map +1 -1
  7. package/dist/components/ContextMenu.vue.d.ts +518 -0
  8. package/dist/components/ContextMenu.vue.d.ts.map +1 -0
  9. package/dist/components/Dropdown.types.d.ts +25 -0
  10. package/dist/components/Dropdown.types.d.ts.map +1 -0
  11. package/dist/components/Dropdown.vue.d.ts +20 -15
  12. package/dist/components/Dropdown.vue.d.ts.map +1 -1
  13. package/dist/components/FilterQuery.vue.d.ts +1 -1
  14. package/dist/components/FilterQuery.vue.d.ts.map +1 -1
  15. package/dist/components/Icon/Icon.vue.d.ts +0 -1
  16. package/dist/components/Icon/Icon.vue.d.ts.map +1 -1
  17. package/dist/components/Icon/constants.d.ts +0 -1
  18. package/dist/components/Icon/constants.d.ts.map +1 -1
  19. package/dist/components/Icon/types.d.ts +2 -3
  20. package/dist/components/Icon/types.d.ts.map +1 -1
  21. package/dist/components/Swiper.vue.d.ts +1 -1
  22. package/dist/components/draggable/useDraggable.d.ts.map +1 -1
  23. package/dist/components/form/inputs/IconPickerInput.vue.d.ts +48 -37
  24. package/dist/components/form/inputs/IconPickerInput.vue.d.ts.map +1 -1
  25. package/dist/components/form/inputs/RichText/components/EditorToolbar.vue.d.ts.map +1 -1
  26. package/dist/components/form/inputs/RichText/composables/useCommands.d.ts.map +1 -1
  27. package/dist/components/form/inputs/RichText/composables/useEditor.d.ts +3 -0
  28. package/dist/components/form/inputs/RichText/composables/useEditor.d.ts.map +1 -1
  29. package/dist/components/form/inputs/RichText/composables/useEditorKeyboard.d.ts +1 -1
  30. package/dist/components/form/inputs/RichText/composables/useEditorKeyboard.d.ts.map +1 -1
  31. package/dist/components/form/inputs/RichText/index.vue.d.ts.map +1 -1
  32. package/dist/components/form/inputs/RichText/utils/commands.d.ts.map +1 -1
  33. package/dist/components/form/inputs/RichText/utils/selection.d.ts +2 -0
  34. package/dist/components/form/inputs/RichText/utils/selection.d.ts.map +1 -1
  35. package/dist/components/form/inputs/RichText/utils/table.d.ts +34 -8
  36. package/dist/components/form/inputs/RichText/utils/table.d.ts.map +1 -1
  37. package/dist/components/form/inputs/SelectInput.vue.d.ts +74 -65
  38. package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
  39. package/dist/components/form/inputs/TelInput.vue.d.ts +2 -2
  40. package/dist/components/index.d.ts +3 -1
  41. package/dist/components/index.d.ts.map +1 -1
  42. package/dist/composables/index.d.ts +1 -1
  43. package/dist/composables/index.d.ts.map +1 -1
  44. package/dist/composables/useBoundedRectDrag.d.ts.map +1 -1
  45. package/dist/composables/usePointerSession.d.ts +14 -3
  46. package/dist/composables/usePointerSession.d.ts.map +1 -1
  47. package/dist/core.css +3 -3
  48. package/dist/directives/vResize.d.ts.map +1 -1
  49. package/dist/form-flow/FormFlow.vue.d.ts.map +1 -1
  50. package/dist/form-flow/form-flow.d.ts +4 -2
  51. package/dist/form-flow/form-flow.d.ts.map +1 -1
  52. package/dist/form-flow/schema-fields.d.ts +4 -1
  53. package/dist/form-flow/schema-fields.d.ts.map +1 -1
  54. package/dist/index.cjs +240 -153
  55. package/dist/index.css +1 -1
  56. package/dist/index.mjs +18461 -18283
  57. package/dist/style.css +3 -3
  58. package/dist/types/BagelForm.d.ts +2 -0
  59. package/dist/types/BagelForm.d.ts.map +1 -1
  60. package/package.json +1 -1
  61. package/src/assetTransport.test.ts +33 -83
  62. package/src/assetTransport.ts +24 -90
  63. package/src/assets.test.ts +58 -99
  64. package/src/assets.ts +78 -161
  65. package/src/components/ContextMenu.vue +113 -0
  66. package/src/components/Dropdown.types.ts +27 -0
  67. package/src/components/Dropdown.vue +129 -64
  68. package/src/components/FilterQuery.vue +1 -1
  69. package/src/components/Icon/Icon.vue +8 -30
  70. package/src/components/Icon/constants.ts +0 -166
  71. package/src/components/Icon/types.ts +2 -3
  72. package/src/components/draggable/useDraggable.ts +67 -100
  73. package/src/components/form/inputs/IconPickerInput.vue +14 -9
  74. package/src/components/form/inputs/RichText/components/EditorToolbar.vue +43 -111
  75. package/src/components/form/inputs/RichText/composables/useCommands.ts +32 -54
  76. package/src/components/form/inputs/RichText/composables/useEditor.ts +45 -171
  77. package/src/components/form/inputs/RichText/composables/useEditorKeyboard.ts +90 -14
  78. package/src/components/form/inputs/RichText/index.vue +1195 -1210
  79. package/src/components/form/inputs/RichText/utils/commands.ts +689 -1028
  80. package/src/components/form/inputs/RichText/utils/selection.ts +66 -41
  81. package/src/components/form/inputs/RichText/utils/table.ts +798 -136
  82. package/src/components/form/inputs/SelectInput.vue +6 -4
  83. package/src/components/form/inputs/Upload/AssetUploadInput.vue +2 -2
  84. package/src/components/index.ts +3 -1
  85. package/src/composables/index.ts +1 -1
  86. package/src/composables/useBoundedRectDrag.ts +9 -12
  87. package/src/composables/usePointerSession.ts +57 -12
  88. package/src/directives/vResize.ts +6 -7
  89. package/src/form-flow/FormFlow.vue +4 -0
  90. package/src/form-flow/form-flow.ts +8 -3
  91. package/src/form-flow/schema-fields.ts +9 -4
  92. package/src/styles/core.css +1 -18
  93. package/src/types/BagelForm.ts +2 -0
  94. package/dist/components/form/inputs/RichText/utils/formatting.d.ts +0 -10
  95. package/dist/components/form/inputs/RichText/utils/formatting.d.ts.map +0 -1
  96. package/src/components/form/inputs/RichText/components/gridBox.vue +0 -58
  97. package/src/components/form/inputs/RichText/utils/formatting.ts +0 -331
@@ -1,331 +0,0 @@
1
- import type { EditorState } from '../richTextTypes'
2
- import { analyzeSelection, restoreSelection, getBlocksBetween } from './selection'
3
-
4
- export function formatting(state: EditorState) {
5
- const { doc } = state
6
- if (!doc) { return { text: () => {}, block: () => {}, list: () => {}, clear: () => {} } }
7
-
8
- const text = (command: string) => {
9
- const selection = doc.getSelection()
10
- if (!selection || !selection.rangeCount) { return }
11
-
12
- const range = selection.getRangeAt(0)
13
- const container = range.commonAncestorContainer
14
- const parentBlock = container.nodeType === 3 ? container.parentElement : container as HTMLElement
15
-
16
- // Preserve RTL direction when applying text formatting
17
- const isRTL = parentBlock?.closest('[dir="rtl"]') !== null
18
-
19
- // Don't apply inline styles directly to block elements
20
- if (parentBlock?.tagName.match(/^H[1-6]|P|BLOCKQUOTE|LI$/)) {
21
- if (!range.collapsed && range.toString().trim()) {
22
- let element: HTMLElement
23
- if (command === 'underline') { element = doc.createElement('u') }
24
- else if (command === 'bold') { element = doc.createElement('b') }
25
- else if (command === 'italic') { element = doc.createElement('i') }
26
- else { return }
27
-
28
- if (isRTL) { element.dir = 'rtl' }
29
- range.surroundContents(element)
30
- }
31
- } else {
32
- if (range.collapsed) { return } // No selection, nothing to format
33
-
34
- let element: HTMLElement
35
- if (command === 'bold') { element = doc.createElement('b') }
36
- else if (command === 'italic') { element = doc.createElement('i') }
37
- else if (command === 'underline') { element = doc.createElement('u') }
38
- else { return }
39
-
40
- try {
41
- range.surroundContents(element)
42
- } catch {
43
- // If surroundContents fails (e.g., for selections across multiple nodes)
44
- // Extract the fragment, wrap it, and insert it back
45
- const fragment = range.extractContents()
46
- element.appendChild(fragment)
47
- range.insertNode(element)
48
- }
49
- }
50
- }
51
-
52
- const block = (command: string, tag: string) => {
53
- const selection = doc.getSelection()
54
- if (!selection || !selection.rangeCount) { return }
55
-
56
- const range = selection.getRangeAt(0)
57
- const container = range.commonAncestorContainer
58
- const parentBlock = container.nodeType === 3 ? container.parentElement : container as HTMLElement
59
- const isRTL = parentBlock?.closest('[dir="rtl"]') !== null
60
-
61
- // Remove any invalid inline style wrapping
62
- if (parentBlock?.closest('u, b, i')) {
63
- const wrapper = parentBlock.closest('u, b, i')
64
- if (wrapper) {
65
- const parent = wrapper.parentNode
66
- while (wrapper.firstChild) {
67
- parent?.insertBefore(wrapper.firstChild, wrapper)
68
- }
69
- wrapper.remove()
70
- }
71
- }
72
-
73
- // Create a new block element of the desired type
74
- const newBlock = doc.createElement(tag)
75
- if (isRTL) { newBlock.dir = 'rtl' }
76
-
77
- // Find the current block to replace
78
- const currentBlock = parentBlock?.closest('p,h1,h2,h3,h4,h5,h6,blockquote,div') || parentBlock
79
-
80
- if (currentBlock) {
81
- // Copy content to the new block
82
- while (currentBlock.firstChild) {
83
- newBlock.appendChild(currentBlock.firstChild)
84
- }
85
-
86
- // Replace the current block with the new one
87
- currentBlock.parentNode?.replaceChild(newBlock, currentBlock)
88
-
89
- // Move cursor into the new block
90
- range.selectNodeContents(newBlock)
91
- range.collapse(false)
92
- selection.removeAllRanges()
93
- selection.addRange(range)
94
- }
95
- }
96
-
97
- const list = (command: string) => {
98
- if (!state.doc || !state.range || !state.selection) { return }
99
-
100
- const listTag = command === 'orderedList' ? 'ol' : 'ul'
101
- const selectionInfo = analyzeSelection(state.doc, state.range)
102
- if (!selectionInfo) { return }
103
-
104
- const isRTL = selectionInfo.parent.closest('[dir="rtl"]') !== null
105
-
106
- // If we're inside a list item, handle toggling off or switching list type
107
- const listItem = selectionInfo.parent.closest('li')
108
- if (listItem) {
109
- const listParent = listItem.parentElement
110
- if (!listParent) { return }
111
-
112
- // If it's the same list type, toggle off
113
- if (listParent.tagName.toLowerCase() === listTag) {
114
- // Create a paragraph from the list item content
115
- const p = state.doc.createElement('p') as HTMLParagraphElement
116
- if (isRTL) { p.dir = 'rtl' }
117
- while (listItem.firstChild) {
118
- p.appendChild(listItem.firstChild)
119
- }
120
-
121
- listParent.parentNode?.insertBefore(p, listParent)
122
- listItem.remove()
123
-
124
- if (!listParent.querySelector('li')) {
125
- listParent.remove()
126
- }
127
-
128
- restoreSelection(state.doc, state.range, state.selection, selectionInfo, p)
129
- return
130
- }
131
-
132
- // Convert to the other list type
133
- const newList = state.doc.createElement(listTag) as HTMLElement
134
- if (isRTL) { newList.dir = 'rtl' }
135
- const allItems = Array.from(listParent.children)
136
- allItems.forEach(item => newList.appendChild(item.cloneNode(true)))
137
- listParent.parentNode?.replaceChild(newList, listParent)
138
-
139
- const newListItem = newList.children[Array.from(allItems).indexOf(listItem)]
140
- restoreSelection(state.doc, state.range, state.selection, selectionInfo, newListItem)
141
- return
142
- }
143
-
144
- // For single block conversion
145
- if (!selectionInfo.isMultiBlock) {
146
- const li = state.doc.createElement('li')
147
- const listEl = state.doc.createElement(listTag) as HTMLElement
148
- if (isRTL) { listEl.dir = 'rtl' }
149
-
150
- while (selectionInfo.startBlock.firstChild) {
151
- li.appendChild(selectionInfo.startBlock.firstChild)
152
- }
153
-
154
- listEl.appendChild(li)
155
- selectionInfo.startBlock.parentNode?.replaceChild(listEl, selectionInfo.startBlock)
156
- restoreSelection(state.doc, state.range, state.selection, selectionInfo, li)
157
- return
158
- }
159
-
160
- // Handle multi-block selection
161
- const blocks = getBlocksBetween(selectionInfo.startBlock, selectionInfo.endBlock)
162
- if (!blocks.length) { return }
163
-
164
- const listEl = state.doc.createElement(listTag) as HTMLElement
165
- if (isRTL) { listEl.dir = 'rtl' }
166
-
167
- const firstBlock = blocks[0]
168
- firstBlock.parentNode?.insertBefore(listEl, firstBlock)
169
-
170
- blocks.forEach((block) => {
171
- if (!state.doc) { return }
172
- const li = state.doc.createElement('li')
173
- while (block.firstChild) {
174
- li.appendChild(block.firstChild)
175
- }
176
- listEl.appendChild(li)
177
- block.remove()
178
- })
179
-
180
- restoreSelection(state.doc, state.range, state.selection, selectionInfo, listEl)
181
- }
182
-
183
- const clear = () => {
184
- console.log('[Clear Format] Starting clear format process', state)
185
- console.assert(!!state, '[Clear Format] State must exist')
186
- console.assert(!!state.doc, '[Clear Format] Document must exist')
187
- console.assert(!!state.range, '[Clear Format] Range must exist')
188
- console.assert(!!state.selection, '[Clear Format] Selection must exist')
189
-
190
- if (!state.doc || !state.range || !state.selection) {
191
- console.log('[Clear Format] No document or selection')
192
- return
193
- }
194
-
195
- const selectionInfo = analyzeSelection(state.doc, state.range)
196
- console.log('[Clear Format] Selection info:', selectionInfo)
197
- if (!selectionInfo) {
198
- console.log('[Clear Format] No valid selection info')
199
- return
200
- }
201
-
202
- // If selection is collapsed (just a cursor), return
203
- if (state.range.collapsed) {
204
- console.log('[Clear Format] Selection is collapsed, nothing to clear')
205
- return
206
- }
207
-
208
- console.log('[Clear Format] Processing selection:', {
209
- startContainer: state.range.startContainer,
210
- endContainer: state.range.endContainer,
211
- selectedText: state.range.toString()
212
- })
213
-
214
- // Get the selected content
215
- const fragment = state.range.cloneContents()
216
- const tempDiv = state.doc.createElement('div')
217
- tempDiv.appendChild(fragment)
218
-
219
- console.log('[Clear Format] Original HTML:', tempDiv.innerHTML)
220
-
221
- // Function to recursively clean a node and its children
222
- const cleanNode = (node: Node): Node => {
223
- if (!state.doc) { return node }
224
-
225
- // Text nodes can be returned as-is
226
- if (node.nodeType === 3) {
227
- return node.cloneNode(true)
228
- }
229
-
230
- if (node.nodeType === 1) { // Element node
231
- const el = node as HTMLElement
232
- const nodeName = el.nodeName.toLowerCase()
233
- const inlineTags = ['b', 'i', 'u', 'strong', 'em', 'span', 'font', 'strike', 'sub', 'sup']
234
-
235
- console.log('[Clear Format] Processing element:', nodeName, {
236
- hasStyle: el.hasAttribute('style'),
237
- style: el.getAttribute('style'),
238
- className: el.className
239
- })
240
-
241
- // For inline formatting elements, just extract the text content
242
- if (inlineTags.includes(nodeName)) {
243
- // Create a text node with the element's content
244
- const textContent = el.textContent || ''
245
- console.log('[Clear Format] Extracting text from inline element:', textContent)
246
- return state.doc.createTextNode(textContent)
247
- }
248
-
249
- // For block elements, preserve the element type but remove formatting
250
- const newEl = state.doc.createElement(nodeName)
251
-
252
- // Remove any style and class attributes
253
- if (el.hasAttribute('style')) {
254
- console.log('[Clear Format] Removing style attribute:', el.getAttribute('style'))
255
- }
256
- if (el.className) {
257
- console.log('[Clear Format] Removing class:', el.className)
258
- }
259
-
260
- // Transfer only specific attributes we want to keep (like href for links)
261
- if (nodeName === 'a' && el.hasAttribute('href')) {
262
- newEl.setAttribute('href', el.getAttribute('href') || '')
263
- if (el.hasAttribute('target')) {
264
- newEl.setAttribute('target', el.getAttribute('target') || '')
265
- }
266
- console.log('[Clear Format] Preserving link attributes')
267
- }
268
-
269
- // For images, preserve src and alt
270
- if (nodeName === 'img') {
271
- if (el.hasAttribute('src')) { newEl.setAttribute('src', el.getAttribute('src') || '') }
272
- if (el.hasAttribute('alt')) { newEl.setAttribute('alt', el.getAttribute('alt') || '') }
273
- console.log('[Clear Format] Preserving image attributes')
274
- }
275
-
276
- // Clean and append all child nodes
277
- Array.from(el.childNodes).forEach((child) => {
278
- newEl.appendChild(cleanNode(child))
279
- })
280
-
281
- return newEl
282
- }
283
-
284
- return node.cloneNode(true)
285
- }
286
-
287
- // Clean all nodes in the fragment
288
- const cleanedFragment = state.doc.createDocumentFragment()
289
- Array.from(tempDiv.childNodes).forEach((node) => {
290
- cleanedFragment.appendChild(cleanNode(node))
291
- })
292
-
293
- // For debugging: check what the cleaned HTML looks like
294
- const debugDiv = state.doc.createElement('div')
295
- debugDiv.appendChild(cleanedFragment.cloneNode(true))
296
- console.log('[Clear Format] Cleaned HTML:', debugDiv.innerHTML)
297
-
298
- // Replace the content
299
- state.range.deleteContents()
300
- state.range.insertNode(cleanedFragment)
301
-
302
- // Restore selection
303
- restoreSelection(state.doc, state.range, state.selection, selectionInfo)
304
-
305
- // Update content state
306
- state.content = state.doc.body.innerHTML
307
- console.log('[Clear Format] Updated document HTML:', state.content)
308
- }
309
-
310
- return { text, block, list, clear }
311
- }
312
-
313
- export function getBlockElement(node: Node): HTMLElement | null {
314
- const element = node.nodeType === 3 ? node.parentElement : node as HTMLElement
315
- if (!element) { return null }
316
- return element.closest('p,h1,h2,h3,h4,h5,h6,blockquote,li') || element
317
- }
318
-
319
- export function adjustIndentation(state: EditorState, increase: boolean) {
320
- const { doc, range } = state
321
- if (!doc || !range) { return }
322
-
323
- const blockElement = getBlockElement(range.commonAncestorContainer)
324
- if (!blockElement) { return }
325
-
326
- const currentMargin = Number.parseInt(blockElement.style.marginLeft || '0', 10)
327
- const step = 20 // pixels to indent/outdent
328
- const newMargin = increase ? currentMargin + step : Math.max(0, currentMargin - step)
329
-
330
- blockElement.style.marginLeft = `${newMargin}px`
331
- }