@bagelink/vue 1.6.43 → 1.6.49
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.
- package/bin/experimentalGenTypedRoutes.ts +18 -19
- package/bin/utils.ts +4 -4
- package/dist/components/AddressSearch.vue.d.ts.map +1 -1
- package/dist/components/Alert.vue.d.ts.map +1 -1
- package/dist/components/BglVideo.vue.d.ts.map +1 -1
- package/dist/components/Card.vue.d.ts.map +1 -1
- package/dist/components/Carousel.vue.d.ts +2 -2
- package/dist/components/Carousel.vue.d.ts.map +1 -1
- package/dist/components/Dropdown.vue.d.ts.map +1 -1
- package/dist/components/Flag.vue.d.ts.map +1 -1
- package/dist/components/IframeVue.vue.d.ts.map +1 -1
- package/dist/components/ListItem.vue.d.ts.map +1 -1
- package/dist/components/Loading.vue.d.ts.map +1 -1
- package/dist/components/Modal.vue.d.ts.map +1 -1
- package/dist/components/ModalForm.vue.d.ts.map +1 -1
- package/dist/components/NavBar.vue.d.ts +1 -1
- package/dist/components/Pill.vue.d.ts.map +1 -1
- package/dist/components/Swiper.vue.d.ts +12 -4
- package/dist/components/Swiper.vue.d.ts.map +1 -1
- package/dist/components/Zoomer.vue.d.ts.map +1 -1
- package/dist/components/analytics/LineChart.vue.d.ts.map +1 -1
- package/dist/components/analytics/PieChart.vue.d.ts +2 -1
- package/dist/components/analytics/PieChart.vue.d.ts.map +1 -1
- package/dist/components/analytics/index.d.ts +1 -1
- package/dist/components/analytics/index.d.ts.map +1 -1
- package/dist/components/calendar/CalendarPopover.vue.d.ts.map +1 -1
- package/dist/components/form/BglMultiStepForm.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/ColorInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/DateInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/PasswordInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/RadioGroup.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/RangeInput.vue.d.ts +11 -11
- package/dist/components/form/inputs/RichText/components/EditorToolbar.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/RichText/components/TableGridSelector.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/RichText/utils/commands.d.ts.map +1 -1
- package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/TelInput.vue.d.ts.map +1 -1
- package/dist/components/layout/AppContent.vue.d.ts.map +1 -1
- package/dist/components/layout/AppSidebar.vue.d.ts +1 -0
- package/dist/components/layout/AppSidebar.vue.d.ts.map +1 -1
- package/dist/components/layout/Layout.vue.d.ts.map +1 -1
- package/dist/components/layout/Tabs.vue.d.ts.map +1 -1
- package/dist/components/layout/index.d.ts +3 -3
- package/dist/components/layout/index.d.ts.map +1 -1
- package/dist/components/lightbox/Lightbox.vue.d.ts.map +1 -1
- package/dist/index.cjs +24 -15
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +1530 -1404
- package/dist/plugins/modalTypes.d.ts +1 -8
- package/dist/plugins/modalTypes.d.ts.map +1 -1
- package/dist/plugins/useModal.d.ts.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -2
- package/src/components/AccordionItem.vue +13 -13
- package/src/components/AddToCalendar.vue +1 -1
- package/src/components/AddressSearch.vue +9 -8
- package/src/components/Alert.vue +2 -1
- package/src/components/Badge.vue +5 -5
- package/src/components/BglVideo.vue +44 -45
- package/src/components/Btn.vue +15 -15
- package/src/components/Card.vue +10 -8
- package/src/components/Carousel.vue +159 -162
- package/src/components/DataPreview.vue +1 -1
- package/src/components/DragOver.vue +6 -6
- package/src/components/Dropdown.vue +39 -38
- package/src/components/Flag.vue +7 -6
- package/src/components/Icon/Icon.vue +22 -22
- package/src/components/IframeVue.vue +5 -5
- package/src/components/Image.vue +17 -17
- package/src/components/ImportData.vue +79 -79
- package/src/components/ListItem.vue +12 -11
- package/src/components/Loading.vue +10 -9
- package/src/components/MapEmbed/Index.vue +24 -24
- package/src/components/Modal.vue +11 -9
- package/src/components/ModalForm.vue +15 -11
- package/src/components/NavBar.vue +6 -6
- package/src/components/Pagination.vue +27 -27
- package/src/components/Pill.vue +11 -12
- package/src/components/Rating.vue +2 -2
- package/src/components/Slider.vue +75 -75
- package/src/components/Spreadsheet/Index.vue +34 -34
- package/src/components/Spreadsheet/SpreadsheetTable.vue +3 -3
- package/src/components/Swiper.vue +4 -4
- package/src/components/Zoomer.vue +282 -182
- package/src/components/analytics/BarChart.vue +6 -6
- package/src/components/analytics/KpiCard.vue +2 -2
- package/src/components/analytics/LineChart.vue +63 -61
- package/src/components/analytics/PieChart.vue +104 -90
- package/src/components/analytics/index.ts +2 -2
- package/src/components/calendar/CalendarPopover.vue +1 -1
- package/src/components/calendar/Index.vue +1 -1
- package/src/components/calendar/views/AgendaView.vue +3 -3
- package/src/components/calendar/views/DayView.vue +6 -6
- package/src/components/calendar/views/MonthView.vue +2 -2
- package/src/components/calendar/views/WeekView.vue +18 -18
- package/src/components/dataTable/DataTable.vue +4 -4
- package/src/components/dataTable/useSorting.ts +1 -1
- package/src/components/dataTable/useTableData.ts +15 -15
- package/src/components/dataTable/useTableSelection.ts +15 -15
- package/src/components/dataTable/useTableVirtualization.ts +1 -1
- package/src/components/draggable/useDraggable.ts +42 -42
- package/src/components/form/BagelForm.vue +15 -15
- package/src/components/form/BglFieldSet.vue +5 -3
- package/src/components/form/BglMultiStepForm.vue +20 -21
- package/src/components/form/inputs/CheckInput.vue +2 -2
- package/src/components/form/inputs/CodeEditor/format.ts +7 -7
- package/src/components/form/inputs/CodeEditor/useHighlight.ts +6 -6
- package/src/components/form/inputs/ColorInput.vue +5 -4
- package/src/components/form/inputs/DateInput.vue +8 -9
- package/src/components/form/inputs/DatePicker.vue +24 -24
- package/src/components/form/inputs/EmailInput.vue +24 -24
- package/src/components/form/inputs/NumberInput.vue +26 -26
- package/src/components/form/inputs/OTP.vue +7 -7
- package/src/components/form/inputs/PasswordInput.vue +3 -2
- package/src/components/form/inputs/RadioGroup.vue +28 -25
- package/src/components/form/inputs/RadioPillsInput.vue +12 -12
- package/src/components/form/inputs/RangeInput.vue +21 -21
- package/src/components/form/inputs/RichText/components/EditorToolbar.vue +107 -92
- package/src/components/form/inputs/RichText/components/TableGridSelector.vue +64 -64
- package/src/components/form/inputs/RichText/components/gridBox.vue +10 -8
- package/src/components/form/inputs/RichText/composables/useCommands.ts +1 -1
- package/src/components/form/inputs/RichText/composables/useEditor.ts +12 -12
- package/src/components/form/inputs/RichText/composables/useEditorKeyboard.ts +1 -1
- package/src/components/form/inputs/RichText/index.vue +138 -138
- package/src/components/form/inputs/RichText/utils/commands.ts +84 -85
- package/src/components/form/inputs/RichText/utils/debug.ts +1 -1
- package/src/components/form/inputs/RichText/utils/formatting.ts +39 -39
- package/src/components/form/inputs/RichText/utils/media.ts +7 -7
- package/src/components/form/inputs/RichText/utils/selection.ts +28 -28
- package/src/components/form/inputs/RichText/utils/table.ts +19 -19
- package/src/components/form/inputs/SelectBtn.vue +1 -1
- package/src/components/form/inputs/SelectInput.vue +54 -54
- package/src/components/form/inputs/SignaturePad.vue +40 -40
- package/src/components/form/inputs/TableField.vue +1 -1
- package/src/components/form/inputs/TelInput.vue +54 -53
- package/src/components/form/inputs/TextInput.vue +19 -19
- package/src/components/form/inputs/ToggleInput.vue +2 -2
- package/src/components/form/inputs/Upload/useFileUpload.ts +6 -6
- package/src/components/form/useBagelFormState.ts +5 -5
- package/src/components/layout/AppContent.vue +6 -3
- package/src/components/layout/AppLayout.vue +2 -2
- package/src/components/layout/AppSidebar.vue +83 -16
- package/src/components/layout/Layout.vue +12 -10
- package/src/components/layout/SidebarMenu.vue +4 -4
- package/src/components/layout/TabbedLayout.vue +17 -17
- package/src/components/layout/Tabs.vue +4 -5
- package/src/components/layout/TabsNav.vue +14 -14
- package/src/components/layout/index.ts +3 -5
- package/src/components/lightbox/Lightbox.vue +276 -126
- package/src/components/lightbox/index.ts +8 -8
- package/src/composables/index.ts +8 -8
- package/src/composables/useAddToCalendar.ts +13 -13
- package/src/composables/useDevice.ts +2 -2
- package/src/composables/useFormField.ts +4 -4
- package/src/composables/usePolling.ts +8 -8
- package/src/composables/useSchemaField.ts +38 -38
- package/src/composables/useTheme.ts +9 -9
- package/src/composables/useValidateFieldValue.ts +2 -2
- package/src/directives/pattern.ts +25 -25
- package/src/directives/ripple.ts +4 -4
- package/src/directives/vResize.ts +6 -6
- package/src/index.ts +1 -0
- package/src/plugins/bagel.ts +4 -4
- package/src/plugins/modalTypes.ts +1 -8
- package/src/plugins/useModal.ts +43 -18
- package/src/styles/layout.css +1 -1
- package/src/types/index.ts +1 -1
- package/src/utils/BagelFormUtils.ts +7 -7
- package/src/utils/calendar/Helpers.ts +8 -8
- package/src/utils/calendar/dateUtils.ts +22 -22
- package/src/utils/calendar/time.ts +25 -25
- package/src/utils/calendar/week.ts +25 -25
- package/src/utils/elementUtils.ts +27 -27
- package/src/utils/sizeParsing.ts +2 -2
- package/src/utils/strings.ts +5 -5
- package/src/utils/tapDetector.ts +11 -11
- package/src/utils/useSearch.ts +29 -29
- package/vite.config.ts +0 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import type { Option } from '@bagelink/vue'
|
|
3
3
|
|
|
4
|
-
import { onMounted, watch } from 'vue'
|
|
4
|
+
import { onMounted, ref, watch } from 'vue'
|
|
5
5
|
|
|
6
6
|
const props = withDefaults(
|
|
7
7
|
defineProps<{
|
|
@@ -20,38 +20,38 @@ const props = withDefaults(
|
|
|
20
20
|
const emits = defineEmits(['update:modelValue'])
|
|
21
21
|
|
|
22
22
|
function getLabel(option: Option) {
|
|
23
|
-
if ('string'
|
|
24
|
-
if ('number'
|
|
25
|
-
if ('boolean'
|
|
23
|
+
if (typeof option === 'string') { return option }
|
|
24
|
+
if (typeof option === 'number') { return `${option}` }
|
|
25
|
+
if (typeof option === 'boolean') { return option ? 'Yes' : 'No' }
|
|
26
26
|
return option.label
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
function getValue(option: Option) {
|
|
30
|
-
if ('string'
|
|
31
|
-
if ('number'
|
|
32
|
-
if ('boolean'
|
|
30
|
+
if (typeof option === 'string') { return option }
|
|
31
|
+
if (typeof option === 'number') { return option }
|
|
32
|
+
if (typeof option === 'boolean') { return option ? 'Yes' : 'No' }
|
|
33
33
|
return option.value
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
const selectedValue = ref(props.modelValue)
|
|
37
37
|
|
|
38
38
|
function handleSelect(e: Event) {
|
|
39
39
|
const newVal = (e.target as any)?.value
|
|
40
40
|
emits('update:modelValue', newVal)
|
|
41
|
-
selectedValue = newVal
|
|
41
|
+
selectedValue.value = newVal
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
watch(
|
|
45
45
|
() => props.modelValue,
|
|
46
46
|
(newVal, oldVal) => {
|
|
47
|
-
if (newVal === oldVal || oldVal === undefined) {return}
|
|
48
|
-
if (selectedValue !== newVal) {selectedValue = newVal}
|
|
47
|
+
if (newVal === oldVal || oldVal === undefined) { return }
|
|
48
|
+
if (selectedValue.value !== newVal) { selectedValue.value = newVal }
|
|
49
49
|
},
|
|
50
50
|
{ immediate: true },
|
|
51
51
|
)
|
|
52
52
|
|
|
53
53
|
onMounted(() => {
|
|
54
|
-
selectedValue = props.modelValue
|
|
54
|
+
selectedValue.value = props.modelValue
|
|
55
55
|
})
|
|
56
56
|
</script>
|
|
57
57
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { watch } from 'vue'
|
|
2
|
+
import { computed, ref, watch } from 'vue'
|
|
3
3
|
|
|
4
4
|
export interface RangeInputProps {
|
|
5
5
|
modelValue: number | [number, number]
|
|
@@ -26,48 +26,48 @@ const {
|
|
|
26
26
|
formatValue = (value: number) => value.toString()
|
|
27
27
|
} = props
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
const from = ref<number>(Array.isArray(props.modelValue) ? props.modelValue[0] : (props.modelValue ?? min))
|
|
30
|
+
const to = ref<number>(Array.isArray(props.modelValue) ? props.modelValue[1] : max)
|
|
31
31
|
|
|
32
|
-
const validFrom =
|
|
33
|
-
const validTo =
|
|
32
|
+
const validFrom = computed(() => Math.min(Math.max(from.value, min), multiRange ? to.value : max))
|
|
33
|
+
const validTo = computed(() => Math.max(Math.min(to.value, max), from.value))
|
|
34
34
|
|
|
35
|
-
const fromPercentage =
|
|
36
|
-
const toPercentage =
|
|
35
|
+
const fromPercentage = computed(() => ((validFrom.value - min) / (max - min)) * 100)
|
|
36
|
+
const toPercentage = computed(() => ((validTo.value - min) / (max - min)) * 100)
|
|
37
37
|
|
|
38
38
|
watch(() => props.modelValue, (newVal) => {
|
|
39
39
|
if (Array.isArray(newVal) && multiRange) {
|
|
40
|
-
from = newVal[0] ?? min
|
|
41
|
-
to = newVal[1] ?? max
|
|
40
|
+
from.value = newVal[0] ?? min
|
|
41
|
+
to.value = newVal[1] ?? max
|
|
42
42
|
} else if (!Array.isArray(newVal)) {
|
|
43
|
-
from = newVal ?? min
|
|
44
|
-
to = max
|
|
43
|
+
from.value = newVal ?? min
|
|
44
|
+
to.value = max
|
|
45
45
|
}
|
|
46
46
|
}, { immediate: true })
|
|
47
47
|
|
|
48
48
|
function handleInput(value: number, isFromInput: boolean) {
|
|
49
49
|
if (isFromInput) {
|
|
50
|
-
from = value
|
|
50
|
+
from.value = value
|
|
51
51
|
} else {
|
|
52
|
-
to = value
|
|
52
|
+
to.value = value
|
|
53
53
|
}
|
|
54
|
-
emit('update:modelValue', multiRange ? [validFrom, validTo] : validFrom)
|
|
54
|
+
emit('update:modelValue', multiRange ? [validFrom.value, validTo.value] : validFrom.value)
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
const rangeStyle =
|
|
57
|
+
const rangeStyle = computed(() => {
|
|
58
58
|
if (multiRange) {
|
|
59
59
|
return {
|
|
60
|
-
left: `${fromPercentage}%`,
|
|
61
|
-
width: `${toPercentage - fromPercentage}%`
|
|
60
|
+
left: `${fromPercentage.value}%`,
|
|
61
|
+
width: `${toPercentage.value - fromPercentage.value}%`
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
return props.rtl
|
|
65
|
-
? { left: `${100 - fromPercentage}%`, width: `${fromPercentage}%` }
|
|
66
|
-
: { left: '0', width: `${fromPercentage}%` }
|
|
65
|
+
? { left: `${100 - fromPercentage.value}%`, width: `${fromPercentage.value}%` }
|
|
66
|
+
: { left: '0', width: `${fromPercentage.value}%` }
|
|
67
67
|
})
|
|
68
68
|
|
|
69
|
-
const displayFrom =
|
|
70
|
-
const displayTo =
|
|
69
|
+
const displayFrom = computed(() => formatValue(validFrom.value))
|
|
70
|
+
const displayTo = computed(() => formatValue(validTo.value))
|
|
71
71
|
</script>
|
|
72
72
|
|
|
73
73
|
<template>
|
|
@@ -31,42 +31,42 @@ const emit = defineEmits(['action'])
|
|
|
31
31
|
|
|
32
32
|
// Function to get the current alignment icon based on active styles
|
|
33
33
|
function getCurrentAlignmentIcon(): string {
|
|
34
|
-
if (selectedStyles.has('alignLeft')) {return 'format_align_left'}
|
|
35
|
-
if (selectedStyles.has('alignCenter')) {return 'format_align_center'}
|
|
36
|
-
if (selectedStyles.has('alignRight')) {return 'format_align_right'}
|
|
37
|
-
if (selectedStyles.has('alignJustify')) {return 'format_align_justify'}
|
|
34
|
+
if (selectedStyles.has('alignLeft')) { return 'format_align_left' }
|
|
35
|
+
if (selectedStyles.has('alignCenter')) { return 'format_align_center' }
|
|
36
|
+
if (selectedStyles.has('alignRight')) { return 'format_align_right' }
|
|
37
|
+
if (selectedStyles.has('alignJustify')) { return 'format_align_justify' }
|
|
38
38
|
return 'format_align_left' // default
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
// Function to check if any alignment is active
|
|
42
42
|
function isAlignmentActive(): boolean {
|
|
43
|
-
return selectedStyles.has('alignLeft')
|
|
44
|
-
selectedStyles.has('alignCenter')
|
|
45
|
-
selectedStyles.has('alignRight')
|
|
46
|
-
selectedStyles.has('alignJustify')
|
|
43
|
+
return selectedStyles.has('alignLeft')
|
|
44
|
+
|| selectedStyles.has('alignCenter')
|
|
45
|
+
|| selectedStyles.has('alignRight')
|
|
46
|
+
|| selectedStyles.has('alignJustify')
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
// Helper function to check if an action should be hidden
|
|
50
50
|
function shouldHideAction(actionName: string): boolean {
|
|
51
51
|
// Check if it's in the hide array - this covers ALL items including:
|
|
52
|
-
// bold, italic, underline, h1, h2, h3, h4, h5, h6, link, image, video, embed,
|
|
52
|
+
// bold, italic, underline, h1, h2, h3, h4, h5, h6, link, image, video, embed,
|
|
53
53
|
// ul, ol, blockquote, code, clear, direction, table, fullScreen
|
|
54
|
-
if (hide.includes(actionName)) {return true}
|
|
54
|
+
if (hide.includes(actionName)) { return true }
|
|
55
55
|
|
|
56
56
|
// Alternative name mappings for some actions
|
|
57
57
|
const alternativeNames: Record<string, string[]> = {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
58
|
+
image: ['insertImage', 'image'],
|
|
59
|
+
video: ['insertVideo', 'video'],
|
|
60
|
+
embed: ['insertEmbed', 'embed'],
|
|
61
|
+
table: ['insertTable'],
|
|
62
|
+
direction: ['textDirection'],
|
|
63
|
+
fullScreen: ['fullScreen'],
|
|
64
|
+
ul: ['unorderedList'],
|
|
65
|
+
ol: ['orderedList'],
|
|
66
|
+
splitView: ['splitView'],
|
|
67
|
+
p: ['p'],
|
|
68
|
+
align: ['alignMenu'],
|
|
69
|
+
alignment: ['alignMenu']
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
// Check alternative names
|
|
@@ -78,28 +78,30 @@ function shouldHideAction(actionName: string): boolean {
|
|
|
78
78
|
|
|
79
79
|
// Map action names to check against specific hide props (for backward compatibility)
|
|
80
80
|
const actionMap: Record<string, boolean> = {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
81
|
+
insertImage: hideImages,
|
|
82
|
+
insertVideo: hideVideos,
|
|
83
|
+
insertEmbed: hideEmbeds,
|
|
84
|
+
insertTable: hideTables,
|
|
85
|
+
alignMenu: hideAlignment,
|
|
86
|
+
textDirection: hideDirections,
|
|
87
|
+
h5: hideH5H6,
|
|
88
|
+
h6: hideH5H6
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
return actionMap[actionName] || false
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
const configToOption = (action: ToolbarConfigOption) => toolbarOptions.find(option => option.name === action) as ToolbarOption
|
|
95
|
+
|
|
94
96
|
// Helper function to check if a separator should be shown
|
|
95
97
|
function shouldShowSeparator(currentIndex: number): boolean {
|
|
96
98
|
const allActions = config.map(configToOption).filter(Boolean)
|
|
97
99
|
|
|
98
100
|
// Simple approach: find the last visible item before this separator
|
|
99
101
|
let lastVisibleBeforeIndex = -1
|
|
100
|
-
for (let i = currentIndex - 1;
|
|
102
|
+
for (let i = currentIndex - 1; i >= 0; i--) {
|
|
101
103
|
const action = allActions[i]
|
|
102
|
-
if (action && 'separator'
|
|
104
|
+
if (action && action.name !== 'separator' && !shouldHideAction(action.name)) {
|
|
103
105
|
lastVisibleBeforeIndex = i
|
|
104
106
|
break
|
|
105
107
|
}
|
|
@@ -109,28 +111,28 @@ function shouldShowSeparator(currentIndex: number): boolean {
|
|
|
109
111
|
let firstVisibleAfterIndex = -1
|
|
110
112
|
for (let i = currentIndex + 1; i < allActions.length; i++) {
|
|
111
113
|
const action = allActions[i]
|
|
112
|
-
if (action && 'separator'
|
|
114
|
+
if (action && action.name !== 'separator' && !shouldHideAction(action.name)) {
|
|
113
115
|
firstVisibleAfterIndex = i
|
|
114
116
|
break
|
|
115
117
|
}
|
|
116
118
|
}
|
|
117
119
|
|
|
118
120
|
// Don't show if we don't have visible items on both sides
|
|
119
|
-
if (
|
|
121
|
+
if (lastVisibleBeforeIndex === -1 || firstVisibleAfterIndex === -1) {
|
|
120
122
|
return false
|
|
121
123
|
}
|
|
122
124
|
|
|
123
125
|
// Check if there's already a visible separator between these items
|
|
124
126
|
for (let i = lastVisibleBeforeIndex + 1; i < currentIndex; i++) {
|
|
125
127
|
const action = allActions[i]
|
|
126
|
-
if (action && 'separator'
|
|
128
|
+
if (action && action.name === 'separator') {
|
|
127
129
|
// There's already a separator closer to the visible items
|
|
128
130
|
return false
|
|
129
131
|
}
|
|
130
132
|
}
|
|
131
133
|
|
|
132
134
|
return true
|
|
133
|
-
}
|
|
135
|
+
}
|
|
134
136
|
|
|
135
137
|
function runAction(name: ToolbarConfigOption, value?: string) {
|
|
136
138
|
console.log('EditorToolbar: runAction called', { name, value })
|
|
@@ -181,61 +183,75 @@ function handleOpenAdvanced() {
|
|
|
181
183
|
</script>
|
|
182
184
|
|
|
183
185
|
<template>
|
|
184
|
-
<div class="toolbar flex gap-025 pb-05 flex-wrap" role="toolbar" style="position: relative;">
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
186
|
+
<div class="toolbar flex gap-025 pb-05 flex-wrap" role="toolbar" style="position: relative;">
|
|
187
|
+
<template v-for="(action, index) in config.map(configToOption).filter(Boolean)" :key="index">
|
|
188
|
+
<!-- Tables -->
|
|
189
|
+
<TableGridSelector v-if="action.name === 'insertTable' && !shouldHideAction('insertTable')" @insert="handleQuickTableInsert" @open-advanced="handleOpenAdvanced" />
|
|
190
|
+
<!-- Images -->
|
|
191
|
+
<Btn
|
|
192
|
+
v-else-if="action.name === 'insertImage' && !shouldHideAction('insertImage')" v-tooltip="action.label" :icon="action.icon" thin flat :aria-label="action.name"
|
|
193
|
+
:class="[action.class, { active: selectedStyles.has(action.name) }]" class="" tabindex="-1" @click="runAction(action.name)"
|
|
194
|
+
/>
|
|
195
|
+
|
|
196
|
+
<!-- Videos -->
|
|
197
|
+
<Btn
|
|
198
|
+
v-else-if="action.name === 'insertVideo' && !shouldHideAction('insertVideo')" v-tooltip="action.label" :icon="action.icon" thin flat :aria-label="action.name"
|
|
199
|
+
:class="[action.class, { active: selectedStyles.has(action.name) }]" class="" tabindex="-1" @click="runAction(action.name)"
|
|
200
|
+
/>
|
|
201
|
+
|
|
202
|
+
<!-- Embeds -->
|
|
203
|
+
<Btn
|
|
204
|
+
v-else-if="action.name === 'insertEmbed' && !shouldHideAction('insertEmbed')" v-tooltip="action.label" :icon="action.icon" thin flat :aria-label="action.name"
|
|
205
|
+
:class="[action.class, { active: selectedStyles.has(action.name) }]" class="" tabindex="-1" @click="runAction(action.name)"
|
|
206
|
+
/>
|
|
207
|
+
|
|
208
|
+
<!-- Alignment Menu -->
|
|
209
|
+
<Dropdown
|
|
210
|
+
v-else-if="action.name === 'alignMenu' && !shouldHideAction('alignMenu')" placement="bottom-start" thin flat :icon="getCurrentAlignmentIcon()"
|
|
211
|
+
:class="{ 'alignment-active': isAlignmentActive() }"
|
|
212
|
+
>
|
|
213
|
+
<template #default="{ hide }">
|
|
214
|
+
<div class="flex flex-column p-025">
|
|
215
|
+
<Btn thin flat icon="format_align_left" :class="{ active: selectedStyles.has('alignLeft') }" @click="runAction('alignLeft'); hide()" />
|
|
216
|
+
<Btn thin flat icon="format_align_center" :class="{ active: selectedStyles.has('alignCenter') }" @click="runAction('alignCenter'); hide()" />
|
|
217
|
+
<Btn thin flat icon="format_align_right" :class="{ active: selectedStyles.has('alignRight') }" @click="runAction('alignRight'); hide()" />
|
|
218
|
+
<Btn thin flat icon="format_align_justify" :class="{ active: selectedStyles.has('alignJustify') }" @click="runAction('alignJustify'); hide()" />
|
|
219
|
+
</div>
|
|
220
|
+
</template>
|
|
221
|
+
</Dropdown>
|
|
222
|
+
|
|
223
|
+
<!-- Text Direction -->
|
|
224
|
+
<Btn
|
|
225
|
+
v-else-if="action.name === 'textDirection' && !shouldHideAction('textDirection')" v-tooltip="action.label"
|
|
226
|
+
:icon="selectedStyles.has('textDirection') ? 'format_textdirection_l_to_r' : 'format_textdirection_r_to_l'" thin flat :aria-label="action.name"
|
|
227
|
+
:class="[action.class, { active: selectedStyles.has('textDirection') }]" class="" tabindex="-1" @click="runAction(action.name)"
|
|
228
|
+
/>
|
|
229
|
+
|
|
230
|
+
<!-- H5 and H6 -->
|
|
231
|
+
<Btn
|
|
232
|
+
v-else-if="(action.name === 'h5' || action.name === 'h6') && !shouldHideAction(action.name)" v-tooltip="action.label" :icon="action.icon" thin flat :aria-label="action.name"
|
|
233
|
+
:class="[action.class, { active: selectedStyles.has(action.name) }]" class="" tabindex="-1" @click="runAction(action.name)"
|
|
234
|
+
/>
|
|
235
|
+
|
|
236
|
+
<!-- All other buttons - check if they should be hidden by the hide array -->
|
|
237
|
+
<Btn
|
|
238
|
+
v-else-if="action.name !== 'separator'
|
|
239
|
+
&& action.name !== 'insertTable'
|
|
240
|
+
&& action.name !== 'insertImage'
|
|
241
|
+
&& action.name !== 'insertVideo'
|
|
242
|
+
&& action.name !== 'insertEmbed'
|
|
243
|
+
&& action.name !== 'alignMenu'
|
|
244
|
+
&& action.name !== 'textDirection'
|
|
245
|
+
&& action.name !== 'h5'
|
|
246
|
+
&& action.name !== 'h6'
|
|
247
|
+
&& !shouldHideAction(action.name)" v-tooltip="action.label" :icon="action.icon" thin flat :aria-label="action.name" :class="[action.class, { active: selectedStyles.has(action.name) }]" class=""
|
|
248
|
+
tabindex="-1" @click="runAction(action.name)"
|
|
249
|
+
/>
|
|
250
|
+
|
|
251
|
+
<!-- Separator -->
|
|
252
|
+
<span v-else-if="action.name === 'separator' && shouldShowSeparator(index)" :key="`separator-${index}`" class="opacity-2 mb-025">|</span>
|
|
253
|
+
</template>
|
|
254
|
+
</div>
|
|
239
255
|
</template>
|
|
240
256
|
|
|
241
257
|
<style scoped>
|
|
@@ -268,4 +284,3 @@ function handleOpenAdvanced() {
|
|
|
268
284
|
color: white !important;
|
|
269
285
|
}
|
|
270
286
|
</style>
|
|
271
|
-
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { ref, computed } from 'vue'
|
|
3
2
|
import { Btn, Dropdown } from '@bagelink/vue'
|
|
4
|
-
|
|
3
|
+
import { ref, computed } from 'vue'
|
|
5
4
|
|
|
6
5
|
const emit = defineEmits<{
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
insert: [rows: number, cols: number]
|
|
7
|
+
openAdvanced: []
|
|
9
8
|
}>()
|
|
10
9
|
|
|
11
10
|
const hoveredRow = ref(0)
|
|
@@ -15,80 +14,81 @@ const maxRows = 10
|
|
|
15
14
|
const maxCols = 10
|
|
16
15
|
|
|
17
16
|
const gridCells = computed(() => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
17
|
+
const cells = []
|
|
18
|
+
for (let row = 1; row <= maxRows; row++) {
|
|
19
|
+
for (let col = 1; col <= maxCols; col++) {
|
|
20
|
+
cells.push({
|
|
21
|
+
row,
|
|
22
|
+
col,
|
|
23
|
+
isActive: row <= hoveredRow.value && col <= hoveredCol.value
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return cells
|
|
29
28
|
})
|
|
30
29
|
|
|
31
30
|
const selectionText = computed(() => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
if (hoveredRow.value === 0 || hoveredCol.value === 0) {
|
|
32
|
+
return 'Select table size'
|
|
33
|
+
}
|
|
34
|
+
return `${hoveredRow.value} × ${hoveredCol.value}`
|
|
36
35
|
})
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
function handleCellHover(row: number, col: number) {
|
|
38
|
+
hoveredRow.value = row
|
|
39
|
+
hoveredCol.value = col
|
|
41
40
|
}
|
|
42
41
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
function handleCellClick(row: number, col: number, hide: () => void) {
|
|
43
|
+
emit('insert', row, col)
|
|
44
|
+
hide()
|
|
46
45
|
}
|
|
47
46
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
function handleAdvanced(hide: () => void) {
|
|
48
|
+
emit('openAdvanced')
|
|
49
|
+
hide()
|
|
51
50
|
}
|
|
52
51
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
function handleMouseLeave() {
|
|
53
|
+
hoveredRow.value = 0
|
|
54
|
+
hoveredCol.value = 0
|
|
56
55
|
}
|
|
57
56
|
</script>
|
|
58
57
|
|
|
59
58
|
<template>
|
|
60
|
-
<Dropdown placement="bottom-start" thin flat icon="table">
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
59
|
+
<Dropdown placement="bottom-start" thin flat icon="table">
|
|
60
|
+
<template #default="{ hide }">
|
|
61
|
+
<div class="table-grid-selector p-075">
|
|
62
|
+
<!-- Header -->
|
|
63
|
+
<div class="txt-center mb-075">
|
|
64
|
+
<div style="font-size: 14px; font-weight: 500; color: #333; margin-bottom: 4px;">
|
|
65
|
+
{{ selectionText }}
|
|
66
|
+
</div>
|
|
67
|
+
<div style="font-size: 12px; color: #666;">
|
|
68
|
+
Hover to select size
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
<!-- Grid -->
|
|
73
|
+
<div style="display: grid; grid-template-columns: repeat(10, 20px); grid-template-rows: repeat(10, 20px); gap: 2px; margin-bottom: 12px; direction: ltr;" @mouseleave="handleMouseLeave" @blur="handleMouseLeave">
|
|
74
|
+
<div
|
|
75
|
+
v-for="cell in gridCells" :key="`${cell.row}-${cell.col}`" tabindex="0" :style="{
|
|
76
|
+
width: '20px',
|
|
77
|
+
height: '20px',
|
|
78
|
+
border: '1px solid #ddd',
|
|
79
|
+
backgroundColor: cell.isActive ? 'var(--bgl-primary)' : '#fff',
|
|
80
|
+
cursor: 'pointer',
|
|
81
|
+
borderRadius: '2px',
|
|
82
|
+
transition: 'background-color 0.1s ease',
|
|
83
|
+
}" @focus="handleCellHover(cell)" @mouseenter="handleCellHover(cell.row, cell.col)" @click="handleCellClick(cell.row, cell.col, hide)"
|
|
84
|
+
/>
|
|
85
|
+
</div>
|
|
72
86
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
cursor: 'pointer',
|
|
81
|
-
borderRadius: '2px',
|
|
82
|
-
transition: 'background-color 0.1s ease'
|
|
83
|
-
}">
|
|
84
|
-
</div>
|
|
85
|
-
</div>
|
|
86
|
-
|
|
87
|
-
<!-- Advanced button -->
|
|
88
|
-
<div class="border-top pt-075">
|
|
89
|
-
<Btn @click="handleAdvanced(hide)" value="Advanced Settings" icon="settings" class="bg-gray-30 color-black" />
|
|
90
|
-
</div>
|
|
91
|
-
</div>
|
|
92
|
-
</template>
|
|
93
|
-
</Dropdown>
|
|
87
|
+
<!-- Advanced button -->
|
|
88
|
+
<div class="border-top pt-075">
|
|
89
|
+
<Btn value="Advanced Settings" icon="settings" class="bg-gray-30 color-black" @click="handleAdvanced(hide)" />
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
</template>
|
|
93
|
+
</Dropdown>
|
|
94
94
|
</template>
|
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { computed, ref } from 'vue'
|
|
3
|
+
|
|
2
4
|
const props = defineProps<{
|
|
3
5
|
gridSize?: number
|
|
4
6
|
}>()
|
|
5
7
|
const emit = defineEmits(['select'])
|
|
6
8
|
const fb = 1
|
|
7
9
|
const base = props.gridSize || 5
|
|
8
|
-
const hoveredRow =
|
|
9
|
-
const hoveredCol =
|
|
10
|
+
const hoveredRow = ref(fb)
|
|
11
|
+
const hoveredCol = ref(fb)
|
|
10
12
|
|
|
11
|
-
const rowSize =
|
|
12
|
-
const enlarge = Math.min(hoveredRow + 1, 20)
|
|
13
|
-
return hoveredRow > (base - 1) ? enlarge : base
|
|
13
|
+
const rowSize = computed(() => {
|
|
14
|
+
const enlarge = Math.min(hoveredRow.value + 1, 20)
|
|
15
|
+
return hoveredRow.value > (base - 1) ? enlarge : base
|
|
14
16
|
})
|
|
15
|
-
const colSize =
|
|
16
|
-
const enlarge = Math.min(hoveredCol + 1, 20)
|
|
17
|
-
return hoveredCol > (base - 1) ? enlarge : base
|
|
17
|
+
const colSize = computed(() => {
|
|
18
|
+
const enlarge = Math.min(hoveredCol.value + 1, 20)
|
|
19
|
+
return hoveredCol.value > (base - 1) ? enlarge : base
|
|
18
20
|
})
|
|
19
21
|
</script>
|
|
20
22
|
|
|
@@ -8,7 +8,7 @@ export function useCommands(state: EditorState, debug?: { logCommand: (command:
|
|
|
8
8
|
|
|
9
9
|
// Function to immediately update styles
|
|
10
10
|
const updateStylesImmediately = () => {
|
|
11
|
-
if (!state.doc) {return}
|
|
11
|
+
if (!state.doc) { return }
|
|
12
12
|
|
|
13
13
|
const styles = new Set<string>()
|
|
14
14
|
const styleTypes = [
|