@bagelink/vue 0.0.865 → 0.0.871

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 (27) hide show
  1. package/dist/components/Carousel.vue.d.ts.map +1 -1
  2. package/dist/components/MapEmbed.vue.d.ts +4 -3
  3. package/dist/components/MapEmbed.vue.d.ts.map +1 -1
  4. package/dist/components/form/inputs/RichText2/Toolbar.vue.d.ts.map +1 -1
  5. package/dist/components/form/inputs/RichText2/formatting.d.ts +6 -0
  6. package/dist/components/form/inputs/RichText2/formatting.d.ts.map +1 -1
  7. package/dist/components/form/inputs/RichText2/index.vue.d.ts.map +1 -1
  8. package/dist/components/form/inputs/RichText2/richtext-types.d.ts +1 -1
  9. package/dist/components/form/inputs/RichText2/richtext-types.d.ts.map +1 -1
  10. package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
  11. package/dist/components/form/inputs/index.d.ts +2 -2
  12. package/dist/components/form/inputs/index.d.ts.map +1 -1
  13. package/dist/components/layout/BottomMenu.vue.d.ts +1 -0
  14. package/dist/components/layout/BottomMenu.vue.d.ts.map +1 -1
  15. package/dist/index.cjs +159 -86
  16. package/dist/index.mjs +159 -86
  17. package/dist/style.css +32 -28
  18. package/package.json +1 -1
  19. package/src/components/Carousel.vue +5 -3
  20. package/src/components/MapEmbed.vue +41 -14
  21. package/src/components/form/inputs/RichText.zip +0 -0
  22. package/src/components/form/inputs/RichText2/Toolbar.vue +10 -15
  23. package/src/components/form/inputs/RichText2/formatting.ts +69 -25
  24. package/src/components/form/inputs/RichText2/index.vue +40 -33
  25. package/src/components/form/inputs/RichText2/richtext-types.ts +1 -0
  26. package/src/components/form/inputs/index.ts +2 -2
  27. package/src/components/layout/BottomMenu.vue +1 -0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bagelink/vue",
3
3
  "type": "module",
4
- "version": "0.0.865",
4
+ "version": "0.0.871",
5
5
  "description": "Bagel core sdk packages",
6
6
  "author": {
7
7
  "name": "Neveh Allon",
@@ -40,9 +40,11 @@ function disableDrag() {
40
40
 
41
41
  function updateHeight() {
42
42
  if (!props.autoHeight || !bglSlider) return
43
- const children = Array.from(bglSlider.children[activeSlideIndex].children)
44
- const totalHeight = children.reduce((sum, el) => sum + el.clientHeight, 0)
45
- yHeight = `${totalHeight}px`
43
+ setTimeout(() => {
44
+ const children = Array.from(bglSlider.children[activeSlideIndex].children)
45
+ const totalHeight = children.reduce((sum, el) => sum + el.clientHeight, 0)
46
+ yHeight = `${totalHeight}px`
47
+ }, 200)
46
48
  }
47
49
 
48
50
  function easeScroll(target: number, duration = 500) {
@@ -5,9 +5,10 @@ import { onMounted, watch } from 'vue'
5
5
  import './leaflet/leaflet.css'
6
6
 
7
7
  type MapMarker = {
8
- lat: number
9
- lon: number
10
- } | [number, number]
8
+ lat: number | string
9
+ lon: number | string
10
+ label?: string
11
+ } | [(number | string), (number | string), string?]
11
12
 
12
13
  const props = withDefaults(
13
14
  defineProps<{
@@ -20,7 +21,7 @@ const props = withDefaults(
20
21
  }>(),
21
22
  {
22
23
  center: () => [31.7683, 35.2137],
23
- zoom: 13,
24
+ zoom: 15,
24
25
  height: 400,
25
26
  zoomControl: true,
26
27
  markerIcon: '',
@@ -32,7 +33,7 @@ let map = $ref<Map>()
32
33
  const _markers = $ref<Marker[]>([])
33
34
  const id = $ref(Math.random().toString(36).slice(2, 10))
34
35
 
35
- const defaultMarkerSVG = '<svg id="eCJDQPwuXje1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 36 36" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" project-id="ac827abc0a8c4922b76bac4df7bd7646" export-id="2cc86932ccbc4825a31fd063b3e75478" cached="false"><style><![CDATA[#eCJDQPwuXje3_ts {animation: eCJDQPwuXje3_ts__ts 3000ms linear infinite normal forwards}@keyframes eCJDQPwuXje3_ts__ts { 0% {transform: translate(18px,18px) scale(1,1)} 3.333333% {transform: translate(18px,18px) scale(1,1);animation-timing-function: cubic-bezier(0.42,0,0.58,1)} 100% {transform: translate(18px,18px) scale(1.8,1.8)}} #eCJDQPwuXje3 {animation: eCJDQPwuXje3_c_o 3000ms linear infinite normal forwards}@keyframes eCJDQPwuXje3_c_o { 0% {opacity: 0} 3.333333% {opacity: 1;animation-timing-function: cubic-bezier(0.42,0,0.58,1)} 100% {opacity: 0}}]]></style><ellipse rx="10.049312" ry="10.049312" transform="translate(18 18)" fill="#2e5bff" stroke-width="0"/><g id="eCJDQPwuXje3_ts" transform="translate(18,18) scale(1,1)"><ellipse id="eCJDQPwuXje3" rx="10.049312" ry="10.049312" transform="translate(0,0)" opacity="0" fill="#2e5bff" stroke-width="0"/></g></svg>'
36
+ const defaultMarkerSVG = '<svg width="28" height="38" viewBox="0 0 28 38" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M14.2263 37.7955C17.0897 37.7955 19.4109 37.0138 19.4109 36.0496C19.4109 35.0854 17.0897 34.3037 14.2263 34.3037C11.363 34.3037 9.04175 35.0854 9.04175 36.0496C9.04175 37.0138 11.363 37.7955 14.2263 37.7955Z" fill="black" fill-opacity="0.1"/><path d="M14.2265 0.549591C21.2842 0.549591 27.0131 6.23786 27.0787 13.28V13.4024C27.0787 19.3328 24.4759 24.4306 21.5627 28.2764C18.6511 32.12 15.4577 34.6754 14.3457 35.5097C14.2748 35.5629 14.1778 35.5629 14.1068 35.5097C12.9947 34.675 9.80135 32.1197 6.88984 28.2762C3.97665 24.4304 1.37378 19.3328 1.37378 13.4024C1.37378 6.30387 7.12806 0.549591 14.2265 0.549591Z" fill="#ED1b3E" stroke="#ED6C6F"/><path d="M14.2263 21.6185C18.7639 21.6185 22.4424 17.94 22.4424 13.4024C22.4424 8.86477 18.7639 5.18631 14.2263 5.18631C9.68872 5.18631 6.01025 8.86477 6.01025 13.4024C6.01025 17.94 9.68872 21.6185 14.2263 21.6185Z" fill="white"/></svg>'
36
37
  const leafletScriptUrl = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.js'
37
38
 
38
39
  async function loadGlobalL() {
@@ -53,20 +54,37 @@ async function initializeMap() {
53
54
  }
54
55
  }
55
56
 
56
- function addMarker(L: any, latlng: LatLngExpression) {
57
+ function addMarker(L: any, latlng: LatLngExpression, label?: string) {
57
58
  const iconSVG = props.markerIcon || defaultMarkerSVG
58
59
  const customIcon = L?.icon({
59
60
  iconUrl: `data:image/svg+xml;utf8,${encodeURIComponent(iconSVG)}`,
60
61
  iconSize: [32, 32],
61
62
  })
62
-
63
63
  const marker = L?.marker(latlng, { icon: customIcon }).addTo(map as Map)
64
+
65
+ if (label) {
66
+ marker.bindTooltip(label, { direction: 'top' }) // Use `bindPopup` if you want a click-to-show label
67
+ }
68
+
69
+ marker.on('click', () => {
70
+ console.log('Marker clicked:', latlng)
71
+ marker.openPopup()
72
+ })
73
+
64
74
  _markers.push(marker)
65
75
  }
66
76
 
67
77
  function fitMarkers(L: any) {
68
78
  if (_markers.length > 0) {
69
- map?.fitBounds(L.featureGroup(_markers as unknown as Layer[]).getBounds())
79
+ const latLngs = _markers.map(marker => marker.getLatLng())
80
+ const bounds = L.latLngBounds(latLngs)
81
+ console.log(props.zoom, bounds.getCenter())
82
+ map?.setView(bounds.getCenter(), props.zoom) // A
83
+ map?.fitBounds(bounds, {
84
+ animate: true,
85
+ maxZoom: props.zoom, // B
86
+ padding: [20, 20], // Adjust padding as needed
87
+ })
70
88
  }
71
89
  }
72
90
 
@@ -74,12 +92,16 @@ async function watchMarkers(markers?: MapMarker[]) {
74
92
  if (!L) L = await loadGlobalL()
75
93
  _markers.forEach(marker => marker.remove())
76
94
  if (!markers) return
95
+
77
96
  for (const marker of markers) {
78
- const [lat, lon] = Array.isArray(marker) ? marker : [marker.lat, marker.lon]
97
+ const [lat, lon, label] = Array.isArray(marker)
98
+ ? [marker[0], marker[1], marker[2] as string]
99
+ : [marker.lat, marker.lon, marker.label]
100
+
79
101
  if (!map) initializeMap()
80
- addMarker(L, [lat, lon])
81
- fitMarkers(L)
102
+ addMarker(L, [+lat, +lon], label)
82
103
  }
104
+ fitMarkers(L)
83
105
  }
84
106
 
85
107
  watch(() => props.markers, watchMarkers, { immediate: true })
@@ -89,7 +111,7 @@ onMounted(initializeMap)
89
111
  </script>
90
112
 
91
113
  <template>
92
- <div :id="id" class="leaflet-map" :style="{ height: `${props.height || 400}px` }" />
114
+ <div :id="id" class="leaflet-map" :style="{ height: `${props.height || 400}px` }" dir="ltr" />
93
115
  </template>
94
116
 
95
117
  <style>
@@ -97,7 +119,8 @@ onMounted(initializeMap)
97
119
  height: 100%;
98
120
  border-radius: var(--input-border-radius);
99
121
  position: relative;
100
- background: var(--bgl-bg)
122
+ background: var(--bgl-bg);
123
+ direction: ltr;
101
124
  }
102
125
 
103
126
  .leaflet-map::after {
@@ -117,7 +140,7 @@ onMounted(initializeMap)
117
140
  }
118
141
 
119
142
  .leaflet-pane.leaflet-marker-pane img {
120
- filter: drop-shadow(0px 8px 3px rgba(0, 0, 0, 0.2));
143
+ /* filter: drop-shadow(0px 8px 3px rgba(0, 0, 0, 0.2)); */
121
144
  }
122
145
 
123
146
  .leaflet-touch .leaflet-control-zoom-in,
@@ -160,4 +183,8 @@ onMounted(initializeMap)
160
183
  .leaflet-bar a:focus {
161
184
  filter: var(--bgl-active-filter);
162
185
  }
186
+
187
+ .leaflet-marker-icon {
188
+ cursor: pointer;
189
+ }
163
190
  </style>
@@ -16,6 +16,11 @@ interface toolbarOption {
16
16
  class?: string
17
17
  }
18
18
  const toolbarOptions: toolbarOption[] = [
19
+ { name: 'formatBlock', label: 'h2', icon: 'format_h2' },
20
+ { name: 'formatBlock', label: 'h3', icon: 'format_h3' },
21
+ { name: 'formatBlock', label: 'h4', icon: 'format_h4' },
22
+ { name: 'formatBlock', label: 'h5', icon: 'format_h5' },
23
+ { name: 'formatBlock', label: 'h6', icon: 'format_h6' },
19
24
  { name: 'separator' },
20
25
  { name: 'bold', label: 'Bold', icon: 'format_bold' },
21
26
  { name: 'italic', label: 'Italic', icon: 'format_italic' },
@@ -46,34 +51,24 @@ const toolbarOptions: toolbarOption[] = [
46
51
  // emit('action', 'fontSize', size)
47
52
  // }
48
53
  // }
49
- function handleSelectChange(selectedOption: string) {
50
- emit('action', 'formatBlock', selectedOption)
51
- }
52
54
  </script>
53
55
 
54
56
  <template>
55
57
  <div class="toolbar flex gap-025 pb-05 flex-wrap" role="toolbar">
56
- <SelectInput
57
- class="m-0 w150"
58
- :options="['Text', 'Heading 1', 'Heading 2', 'Heading 3', 'Heading 4', 'Heading 5', 'Heading 6', 'Blockquote', 'Code']"
59
- @change="handleSelectChange"
60
- />
61
-
62
- <template v-for="(action, index) in toolbarOptions">
58
+ <template v-for="(action, index) in toolbarOptions" :key="index">
63
59
  <Btn
64
60
  v-if="action.name !== 'separator' && config.includes(action.name)"
65
- :key="action.name"
66
61
  v-tooltip="action.label"
62
+ :icon="action.icon"
67
63
  thin
68
64
  flat
65
+ :aria-label="action.name"
69
66
  :class="action.class"
70
67
  class="radius-05"
71
- :aria-label="action.name"
72
- :icon="action.icon"
73
- @click="emit('action', action.name)"
68
+ @click="emit('action', action.name, action.label)"
74
69
  />
75
70
  <span
76
- v-if="action.name === 'separator'"
71
+ v-else-if="action.name === 'separator'"
77
72
  :key="`separator-${index}`"
78
73
  class=" opacity-2 mb-025"
79
74
  >|</span>
@@ -1,4 +1,4 @@
1
- import { useModal } from '@bagelink/vue'
1
+ let modal: any
2
2
 
3
3
  export function applyFormatting(command: string, value: string = '') {
4
4
  const selection = window.getSelection()
@@ -7,6 +7,9 @@ export function applyFormatting(command: string, value: string = '') {
7
7
  const span = document.createElement('span')
8
8
 
9
9
  switch (command) {
10
+ case 'formatBlock':
11
+ formatBlock(value)
12
+ break
10
13
  case 'bold':
11
14
  span.style.fontWeight = 'bold'
12
15
  break
@@ -73,7 +76,7 @@ export function applyFormatting(command: string, value: string = '') {
73
76
  case 'decreaseFontSize':
74
77
  decreaseFontSize()
75
78
  break
76
- case 'insertLink':
79
+ case 'link':
77
80
  insertLink()
78
81
  break
79
82
  case 'image':
@@ -91,6 +94,16 @@ export function applyFormatting(command: string, value: string = '') {
91
94
  }
92
95
  }
93
96
 
97
+ function formatBlock(value: string) {
98
+ if (!value) return
99
+ const selection = window.getSelection()
100
+ const range = selection?.getRangeAt(0)
101
+ if (!range) return
102
+ range.selectNodeContents(range.startContainer)
103
+ const el = document.createElement(value)
104
+ range.surroundContents(el)
105
+ }
106
+
94
107
  function increaseFontSize() {
95
108
  const selection = window.getSelection()
96
109
  if (selection && selection.rangeCount > 0) {
@@ -104,7 +117,15 @@ function increaseFontSize() {
104
117
  }
105
118
 
106
119
  function decreaseFontSize() {
107
- // TODO:
120
+ const selection = window.getSelection()
121
+ if (selection && selection.rangeCount > 0) {
122
+ const range = selection.getRangeAt(0)
123
+ const span = document.createElement('span')
124
+ const currentFontSize = Number.parseInt((range.startContainer.parentNode as HTMLElement).style.fontSize || '16', 10)
125
+ const newFontSize = currentFontSize - 2
126
+ span.style.fontSize = `${newFontSize}px`
127
+ range.surroundContents(span)
128
+ }
108
129
  }
109
130
 
110
131
  function removeFormatting() {
@@ -142,36 +163,40 @@ function insertList(type: string) {
142
163
  }
143
164
 
144
165
  export function insertLink() {
145
- const url = prompt('Enter the URL:')
146
- if (url) {
147
- const selection = window.getSelection()
148
- if (selection && selection.rangeCount > 0) {
149
- const range = selection.getRangeAt(0)
166
+ const selection = window.getSelection()
167
+ if (!selection || selection.rangeCount < 1) return
168
+ const range = selection.getRangeAt(0)
169
+ modal.showModalForm({ title: 'Insert Link', schema: [
170
+ { id: 'url', $el: 'text', label: 'URL' },
171
+ { id: 'openInNewTab', $el: 'check', label: 'Open in new tab' },
172
+ ], onSubmit: (data: any) => {
173
+ const { url, openInNewTab } = data
174
+ if (url) {
150
175
  const anchor = document.createElement('a')
151
176
  anchor.href = url
152
177
  range.surroundContents(anchor)
178
+ if (openInNewTab) anchor.target = '_blank'
153
179
  }
154
- }
180
+ } })
155
181
  }
156
182
 
157
183
  export function insertImage() {
158
- console.log('image')
159
- const { showModalForm } = useModal()
160
- console.log(showModalForm)
161
- showModalForm({ title: 'Upload Image', schema: [{ id: 'image', type: 'file' }], onSubmit: (_data) => {
162
- //
184
+ const selection = window.getSelection()
185
+ if (!selection || selection.rangeCount < 1) return
186
+ const range = selection.getRangeAt(0)
187
+ modal.showModalForm({ title: 'Upload Image', schema: [
188
+ { id: 'src', $el: 'file', attrs: { bindkey: 'url' } },
189
+ { id: 'alt', $el: 'text', label: 'Alt Text' },
190
+ ], onSubmit: (_data: any) => {
191
+ const { src } = _data
192
+ if (src) {
193
+ const img = document.createElement('img')
194
+ img.src = src
195
+ img.alt = _data.alt
196
+ range.deleteContents()
197
+ range.insertNode(img)
198
+ }
163
199
  } })
164
- // const url = prompt('Enter the image URL:')
165
- // if (url) {
166
- // const selection = window.getSelection()
167
- // if (selection && selection.rangeCount > 0) {
168
- // const range = selection.getRangeAt(0)
169
- // const img = document.createElement('img')
170
- // img.src = url
171
- // range.deleteContents()
172
- // range.insertNode(img)
173
- // }
174
- // }
175
200
  }
176
201
 
177
202
  export function createTable() {
@@ -200,3 +225,22 @@ export function createTable() {
200
225
  }
201
226
  }
202
227
  }
228
+
229
+ function clearFormatting() {
230
+ const selection = window.getSelection()
231
+ const range = selection?.getRangeAt(0)
232
+ if (!range) return
233
+ range.selectNodeContents(range.startContainer)
234
+ const contents = range.extractContents()
235
+ const text = contents.textContent
236
+ if (text !== null && text !== '') {
237
+ range.deleteContents()
238
+ const textNode = document.createTextNode(`${text}`)
239
+ setTimeout(() => { range.insertNode(textNode) }, 1)
240
+ }
241
+ }
242
+
243
+ export function useFormatting(modalInstance?: any) {
244
+ modal = modalInstance
245
+ return { applyFormatting, clearFormatting }
246
+ }
@@ -1,14 +1,19 @@
1
1
  <script lang="ts" setup>
2
2
  import type { ToolbarConfig } from './richtext-types'
3
+ import { useModal } from '@bagelink/vue'
3
4
  import { onMounted, watch } from 'vue'
4
- import { applyFormatting } from './formatting'
5
+ import { useFormatting } from './formatting'
5
6
  import Toolbar from './Toolbar.vue'
6
7
 
7
8
  const props = defineProps<{ modelValue: string, toolbarConfig?: ToolbarConfig }>()
8
9
  const emit = defineEmits(['update:modelValue'])
9
10
 
11
+ const modal = useModal()
12
+ const { applyFormatting, clearFormatting } = useFormatting(modal)
13
+
10
14
  const editableContent = $ref<HTMLElement | undefined>()
11
15
  const defaultConfig: ToolbarConfig = [
16
+ 'formatBlock',
12
17
  'bold',
13
18
  'italic',
14
19
  'underline',
@@ -47,41 +52,37 @@ function updateContent() {
47
52
  emit('update:modelValue', contentHtml)
48
53
  }
49
54
 
55
+ function updateToolbarHighlight() {
56
+ if (document.getSelection()) {
57
+ const selection = document.getSelection()
58
+ const range = selection?.rangeCount ? selection.getRangeAt(0) : null
59
+ const container = range?.commonAncestorContainer as HTMLElement
60
+ if (container) {
61
+ let currentElement = container.nodeType === 3 ? container.parentElement : container
62
+ while (currentElement && currentElement !== editableContent) {
63
+ if (['H1', 'H2', 'H3'].includes(currentElement.tagName)) {
64
+ // emit('action', { type: currentElement.tagName.toLowerCase() }); // Emit the tag to highlight button
65
+ break
66
+ }
67
+ currentElement = currentElement.parentElement
68
+ }
69
+ }
70
+ }
71
+ }
72
+
73
+ document.addEventListener('selectionchange', updateToolbarHighlight)
74
+
50
75
  type ToolbarAction = 'link' | 'image' | 'table' | 'youtube' | 'fontSize' | 'fontFamily' | 'textColor' | 'backgroundColor' | 'bold' | 'italic' | 'underline' | 'alignLeft' | 'alignCenter' | 'alignRight' | 'alignJustify' | 'orderedList' | 'unorderedList' | 'indent' | 'outdent' | 'blockquote' | 'codeBlock' | 'splitView' | 'codeView' | 'clear' | 'fullScreen'
51
76
 
52
77
  function handleToolbarAction(action: string, value?: string) {
53
78
  if (!editableContent) return
54
79
  if (['alignLeft', 'alignCenter', 'alignRight', 'alignJustify'].includes(action))
55
80
  value = action.replace('align', '').toLowerCase()
56
- switch (action) {
57
- case 'link':
58
- applyFormatting('insertLink')
59
- break
60
- case 'orderedList':
61
- applyFormatting('insertOrderedList')
62
- break
63
- case 'unorderedList':
64
- applyFormatting('insertUnorderedList')
65
- break
66
- case 'blockquote':
67
- applyFormatting('formatBlock', '<blockquote>')
68
- break
69
- case 'codeBlock':
70
- applyFormatting('formatBlock', '<pre>')
71
- break
72
- case 'splitView':
73
- isSplitView = !isSplitView
74
- break
75
- case 'codeView':
76
- isCodeView = !isCodeView
77
- break
78
- case 'fullScreen':
79
- toggleFullScreen()
80
- break
81
- default:
82
- applyFormatting(action, value)
83
- break
84
- }
81
+ if (action === 'splitView') isSplitView = !isSplitView
82
+ else if (action === 'codeView') isCodeView = !isCodeView
83
+ else if (action === 'fullScreen') toggleFullScreen()
84
+ else if (action === 'clear') clearFormatting()
85
+ else applyFormatting(action, value)
85
86
  updateContent()
86
87
  }
87
88
 
@@ -143,10 +144,10 @@ function logInput(e: InputEvent) {
143
144
  </script>
144
145
 
145
146
  <template>
146
- <div class="rich-text-editor rounded pt-05 px-1 pb-1">
147
+ <div class="rich-text-editor rounded pt-05 px-05 pb-1">
147
148
  <Toolbar :config @action="handleToolbarAction" />
148
149
  <div class="editor-container flex flex-stretch gap-1 m_column">
149
- <div class="content-area radius-05 p-1 shadow-light w-100 grid">
150
+ <div class="content-area radius-05 p-1 w-100 grid">
150
151
  <textarea v-if="isCodeView" v-model="contentHtml" @input="updateContent" />
151
152
  <div
152
153
  v-else
@@ -160,7 +161,13 @@ function logInput(e: InputEvent) {
160
161
  @keydown="handleKeyDown"
161
162
  />
162
163
  </div>
163
- <code v-if="isSplitView" contenteditable="true" class="preview-area w-100 radius-05 p-1" @input="logInput" v-text="contentHtml" />
164
+ <code
165
+ v-if="isSplitView"
166
+ contenteditable="true"
167
+ class="preview-area w-100 radius-05 p-1"
168
+ @input="(e) => logInput(e as InputEvent)"
169
+ v-text="contentHtml"
170
+ />
164
171
  </div>
165
172
  </div>
166
173
  </template>
@@ -24,5 +24,6 @@ export type ToolbarConfigOption = 'bold'
24
24
  | 'youtube'
25
25
  | 'clear'
26
26
  | 'fullScreen'
27
+ | 'formatBlock'
27
28
 
28
29
  export type ToolbarConfig = ToolbarConfigOption[]
@@ -10,8 +10,8 @@ export { default as PasswordInput } from './PasswordInput.vue'
10
10
  export { default as RadioGroup } from './RadioGroup.vue'
11
11
  export { default as RadioPillsInput } from './RadioPillsInput.vue'
12
12
  export { default as RangeInput } from './RangeInput.vue'
13
- export { default as RichText } from './RichText.vue'
14
- export { default as RichText2 } from './RichText2/index.vue'
13
+ export { default as RichText2 } from './RichText.vue'
14
+ export { default as RichText } from './RichText2/index.vue'
15
15
  export { default as SelectInput } from './SelectInput.vue'
16
16
  export { default as SignaturePad } from './SignaturePad.vue'
17
17
  export { default as TableField } from './TableField.vue'
@@ -26,6 +26,7 @@ defineProps<{
26
26
  {{ nav.label }}
27
27
  </p>
28
28
  </Btn>
29
+ <slot name="end" />
29
30
  </Card>
30
31
  </template>
31
32