@bagelink/vue 0.0.1004 → 0.0.1006
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/dist/components/BglVideo.vue.d.ts +8 -1
- package/dist/components/BglVideo.vue.d.ts.map +1 -1
- package/dist/components/Image.vue.d.ts +5 -0
- package/dist/components/Image.vue.d.ts.map +1 -1
- package/dist/components/TableSchema.vue.d.ts.map +1 -1
- package/dist/components/form/BglField.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/RichText/composables/useEditor.d.ts.map +1 -1
- package/dist/components/form/inputs/RichText/utils/media.d.ts.map +1 -1
- package/dist/components/form/inputs/SelectInput.vue.d.ts +23 -35
- package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
- package/dist/components/layout/SidebarMenu.vue.d.ts.map +1 -1
- package/dist/index.cjs +169 -108
- package/dist/index.mjs +169 -108
- package/dist/style.css +85 -85
- package/package.json +1 -2
- package/src/components/BglVideo.vue +28 -3
- package/src/components/Image.vue +11 -6
- package/src/components/Pill.vue +2 -2
- package/src/components/TableSchema.vue +60 -71
- package/src/components/form/BglField.vue +2 -1
- package/src/components/form/inputs/RichText/composables/useEditor.ts +0 -1
- package/src/components/form/inputs/RichText/utils/media.ts +27 -5
- package/src/components/form/inputs/SelectInput.vue +9 -4
- package/src/components/layout/SidebarMenu.vue +0 -1
|
@@ -5,9 +5,13 @@ import {
|
|
|
5
5
|
MaterialIcon,
|
|
6
6
|
isDate,
|
|
7
7
|
keyToLabel,
|
|
8
|
-
useBglSchema
|
|
8
|
+
useBglSchema
|
|
9
9
|
} from '@bagelink/vue'
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
useVirtualList,
|
|
12
|
+
useIntersectionObserver,
|
|
13
|
+
until
|
|
14
|
+
} from '@vueuse/core'
|
|
11
15
|
import { computed, useSlots, watch } from 'vue'
|
|
12
16
|
|
|
13
17
|
export type SortDirectionsT = 'ASC' | 'DESC'
|
|
@@ -19,7 +23,7 @@ const {
|
|
|
19
23
|
showFields,
|
|
20
24
|
onLastItemVisible,
|
|
21
25
|
useServerSort = false,
|
|
22
|
-
selectable = false
|
|
26
|
+
selectable = false,
|
|
23
27
|
} = defineProps<{
|
|
24
28
|
data: T[]
|
|
25
29
|
schema?: BglFormSchemaT<T> | (() => BglFormSchemaT<T>)
|
|
@@ -36,55 +40,36 @@ const emit = defineEmits<{
|
|
|
36
40
|
'lastItemVisible': []
|
|
37
41
|
}>()
|
|
38
42
|
|
|
39
|
-
const
|
|
40
|
-
const loading = defineModel('loading', { default: false })
|
|
43
|
+
const NON_DIGIT_REGEX = /[^\d.-]/g
|
|
41
44
|
|
|
42
|
-
const
|
|
43
|
-
const computedItemHeight = $computed(() => `${itemHeight.value}px`)
|
|
44
|
-
|
|
45
|
-
let sortField = $ref('')
|
|
46
|
-
let sortDirection = $ref<SortDirectionsT>('ASC')
|
|
45
|
+
const slots: any = useSlots()
|
|
47
46
|
|
|
47
|
+
const loading = defineModel('loading', { default: false })
|
|
48
|
+
const itemHeight = defineModel('itemHeight', { default: 50 })
|
|
48
49
|
const selectedItems = defineModel<string[]>(
|
|
49
50
|
'selectedItems',
|
|
50
51
|
{
|
|
51
52
|
default: [] as string[],
|
|
52
|
-
set: (value: string[]) =>
|
|
53
|
-
setTimeout(updateAllSelectorState, 0)
|
|
54
|
-
return value
|
|
55
|
-
},
|
|
53
|
+
set: (value: string[]) => value,
|
|
56
54
|
}
|
|
57
55
|
)
|
|
58
56
|
|
|
59
|
-
|
|
57
|
+
let sortField = $ref('')
|
|
58
|
+
let sortDirection = $ref<SortDirectionsT>('ASC')
|
|
60
59
|
|
|
61
|
-
const
|
|
60
|
+
const allSelectorEl = $ref<HTMLInputElement | undefined>()
|
|
61
|
+
const lastItemEl = $ref<HTMLTableRowElement | null>()
|
|
62
62
|
|
|
63
|
+
const computedSelectedItems = $computed(() => selectedItems.value)
|
|
64
|
+
const computedItemHeight = $computed(() => `${itemHeight.value}px`)
|
|
65
|
+
const isSelectable = $computed(() => selectable === true && Array.isArray(selectedItems.value))
|
|
66
|
+
const computedSortField = $computed(() => `_transformed_${sortField}`)
|
|
63
67
|
const computedSchema = $computed(() => useBglSchema<T>({
|
|
64
68
|
schema,
|
|
65
69
|
showFields,
|
|
66
70
|
data,
|
|
67
71
|
}))
|
|
68
72
|
|
|
69
|
-
function transform(rowData: any) {
|
|
70
|
-
const obj: { [key: string]: any } = { ...rowData }
|
|
71
|
-
const schemaFields = computedSchema.filter(f => f.id)
|
|
72
|
-
|
|
73
|
-
for (const field of schemaFields) {
|
|
74
|
-
const fieldData = rowData[`${field.id}`]
|
|
75
|
-
|
|
76
|
-
const newFieldVal = field.transform?.(fieldData, rowData)
|
|
77
|
-
|
|
78
|
-
Object.assign(obj, {
|
|
79
|
-
[`${field.id}`]: fieldData,
|
|
80
|
-
[`_transformed_${field.id}`]: newFieldVal,
|
|
81
|
-
})
|
|
82
|
-
}
|
|
83
|
-
return obj
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const NON_DIGIT_REGEX = /[^\d.-]/g
|
|
87
|
-
|
|
88
73
|
const computedData = computed(() => {
|
|
89
74
|
if (!sortField || useServerSort === true) return data.map(transform)
|
|
90
75
|
|
|
@@ -122,6 +107,23 @@ const computedData = computed(() => {
|
|
|
122
107
|
)
|
|
123
108
|
})
|
|
124
109
|
|
|
110
|
+
function transform(rowData: any) {
|
|
111
|
+
const obj: { [key: string]: any } = { ...rowData }
|
|
112
|
+
const schemaFields = computedSchema.filter(f => f.id)
|
|
113
|
+
|
|
114
|
+
for (const field of schemaFields) {
|
|
115
|
+
const fieldData = rowData[`${field.id}`]
|
|
116
|
+
|
|
117
|
+
const newFieldVal = field.transform?.(fieldData, rowData)
|
|
118
|
+
|
|
119
|
+
Object.assign(obj, {
|
|
120
|
+
[`${field.id}`]: fieldData,
|
|
121
|
+
[`_transformed_${field.id}`]: newFieldVal,
|
|
122
|
+
})
|
|
123
|
+
}
|
|
124
|
+
return obj
|
|
125
|
+
}
|
|
126
|
+
|
|
125
127
|
function sort(fieldname: string) {
|
|
126
128
|
if (sortField === fieldname) {
|
|
127
129
|
if (sortDirection === 'ASC') sortDirection = 'DESC'
|
|
@@ -130,11 +132,9 @@ function sort(fieldname: string) {
|
|
|
130
132
|
sortField = fieldname
|
|
131
133
|
sortDirection = 'ASC'
|
|
132
134
|
}
|
|
133
|
-
|
|
134
135
|
emit('orderBy', `${fieldname} ${sortDirection}`.trim() as EmitOrderT)
|
|
135
136
|
}
|
|
136
137
|
|
|
137
|
-
// #region ? VIRTUAL LIST
|
|
138
138
|
const { list, containerProps, wrapperProps, scrollTo } = useVirtualList(
|
|
139
139
|
computedData,
|
|
140
140
|
{
|
|
@@ -143,64 +143,53 @@ const { list, containerProps, wrapperProps, scrollTo } = useVirtualList(
|
|
|
143
143
|
}
|
|
144
144
|
)
|
|
145
145
|
|
|
146
|
-
watch(
|
|
147
|
-
() => computedData.value.length,
|
|
148
|
-
(newLength, oldLength) => {
|
|
149
|
-
if (newLength === oldLength || onLastItemVisible !== undefined) return
|
|
150
|
-
scrollTo(0)
|
|
151
|
-
}
|
|
152
|
-
)
|
|
153
|
-
// #endregion ? VIRTUAL LIST
|
|
154
|
-
|
|
155
|
-
// #region ? SELECT COLUMN
|
|
156
|
-
const allSelector = $ref<HTMLInputElement | undefined>()
|
|
157
|
-
const computedSelectedItems = $computed(() => selectedItems.value)
|
|
158
|
-
|
|
159
146
|
function updateAllSelectorState() {
|
|
160
|
-
if (!
|
|
161
|
-
const allSelected
|
|
162
|
-
= computedData.value.length === computedSelectedItems.length
|
|
147
|
+
if (!allSelectorEl) return
|
|
148
|
+
const allSelected = computedData.value.length === computedSelectedItems.length
|
|
163
149
|
&& computedData.value.every(s => s.id && computedSelectedItems.includes(s.id))
|
|
164
|
-
|
|
165
|
-
|
|
150
|
+
allSelectorEl.checked = allSelected
|
|
151
|
+
allSelectorEl.indeterminate = !allSelected && computedSelectedItems.length > 0
|
|
166
152
|
}
|
|
167
153
|
|
|
168
154
|
function toggleSelectItem(item: { [key: string]: any }) {
|
|
169
155
|
if (computedSelectedItems.length === 0) {
|
|
170
156
|
const obj = { ...item }
|
|
171
|
-
Object.keys(obj).forEach(
|
|
172
|
-
if (key.startsWith('_transformed_')) delete obj[key]
|
|
173
|
-
})
|
|
174
|
-
|
|
157
|
+
Object.keys(obj).forEach(key => key.startsWith('_transformed_') && delete obj[key])
|
|
175
158
|
emit('select', obj as T)
|
|
176
159
|
return
|
|
177
160
|
}
|
|
178
161
|
const index = computedSelectedItems.indexOf(item.id)
|
|
179
|
-
|
|
180
|
-
computedSelectedItems.splice(index, 1)
|
|
181
|
-
} else {
|
|
182
|
-
computedSelectedItems.push(item.id)
|
|
183
|
-
}
|
|
162
|
+
index > -1 ? computedSelectedItems.splice(index, 1) : computedSelectedItems.push(item.id)
|
|
184
163
|
}
|
|
185
164
|
|
|
186
165
|
function toggleSelectAll(event: Event) {
|
|
187
166
|
const value = (event.target as HTMLInputElement).checked
|
|
188
167
|
selectedItems.value = value ? computedData.value.map((d: any) => d.id) : []
|
|
189
168
|
}
|
|
190
|
-
// #endregion ? SELECT COLUMN
|
|
191
|
-
|
|
192
|
-
const lastItem = $ref<HTMLTableRowElement | null>()
|
|
193
169
|
|
|
194
170
|
async function registerLastItemObserver() {
|
|
195
|
-
await until(() =>
|
|
171
|
+
await until(() => lastItemEl).toBeTruthy()
|
|
196
172
|
|
|
197
|
-
useIntersectionObserver(
|
|
173
|
+
useIntersectionObserver(lastItemEl, ([entry]) => {
|
|
198
174
|
if (entry.isIntersecting && computedData.value.length) {
|
|
199
175
|
emit('lastItemVisible')
|
|
200
176
|
}
|
|
201
177
|
})
|
|
202
178
|
}
|
|
203
179
|
|
|
180
|
+
watch(
|
|
181
|
+
() => computedData.value.length,
|
|
182
|
+
(newLength, oldLength) => {
|
|
183
|
+
if (newLength === oldLength || onLastItemVisible !== undefined) return
|
|
184
|
+
scrollTo(0)
|
|
185
|
+
}
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
watch(
|
|
189
|
+
() => computedSelectedItems.length,
|
|
190
|
+
() => { updateAllSelectorState() }
|
|
191
|
+
)
|
|
192
|
+
|
|
204
193
|
watch(
|
|
205
194
|
() => loading.value,
|
|
206
195
|
(newLoadingVal, oldLoadingVal) => {
|
|
@@ -228,7 +217,7 @@ watch(
|
|
|
228
217
|
<thead class="row first-row">
|
|
229
218
|
<th v-if="isSelectable">
|
|
230
219
|
<input
|
|
231
|
-
ref="
|
|
220
|
+
ref="allSelectorEl"
|
|
232
221
|
type="checkbox"
|
|
233
222
|
@click.stop
|
|
234
223
|
@change="toggleSelectAll"
|
|
@@ -292,7 +281,7 @@ watch(
|
|
|
292
281
|
</div>
|
|
293
282
|
</td>
|
|
294
283
|
</tr>
|
|
295
|
-
<tr v-if="onLastItemVisible !== undefined" ref="
|
|
284
|
+
<tr v-if="onLastItemVisible !== undefined" ref="lastItemEl" style="height: 1px;" />
|
|
296
285
|
</tbody>
|
|
297
286
|
</table>
|
|
298
287
|
</div>
|
|
@@ -66,7 +66,8 @@ function setFieldData(key: string, val: any) {
|
|
|
66
66
|
return data
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
function getFieldData(obj:
|
|
69
|
+
function getFieldData(obj: any, key: string) {
|
|
70
|
+
if (typeof obj !== 'object' || obj === null) return obj
|
|
70
71
|
const keys = key.split(objPathRegex)
|
|
71
72
|
let result = obj
|
|
72
73
|
for (const k of keys) {
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import type { EditorState, Modal } from '../richTextTypes'
|
|
2
|
+
import { bagelFormUtils } from '@bagelink/vue'
|
|
3
|
+
|
|
4
|
+
const { frmRow, numField } = bagelFormUtils
|
|
2
5
|
|
|
3
6
|
export function insertImage(modal: Modal, state: EditorState) {
|
|
4
7
|
const { range, doc } = state
|
|
@@ -9,15 +12,34 @@ export function insertImage(modal: Modal, state: EditorState) {
|
|
|
9
12
|
schema: [
|
|
10
13
|
{ id: 'src', $el: 'file', attrs: { bindkey: 'url' } },
|
|
11
14
|
{ id: 'alt', $el: 'text', label: 'Alt Text' },
|
|
15
|
+
frmRow(
|
|
16
|
+
numField('width', 'Width', { min: 1 }),
|
|
17
|
+
numField('height', 'Height', { min: 1 }),
|
|
18
|
+
),
|
|
19
|
+
{ id: 'figcaption', $el: 'check', label: 'Show Caption' },
|
|
12
20
|
],
|
|
13
|
-
onSubmit: (data:
|
|
21
|
+
onSubmit: (data: Record<string, any>) => {
|
|
14
22
|
if (data.src) {
|
|
15
23
|
const img = doc.createElement('img')
|
|
16
|
-
img
|
|
17
|
-
|
|
18
|
-
|
|
24
|
+
Object.assign(img, {
|
|
25
|
+
src: data.src,
|
|
26
|
+
alt: data.alt || '',
|
|
27
|
+
width: data.width || undefined,
|
|
28
|
+
height: data.height || undefined
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
const node = data.figcaption
|
|
32
|
+
? (() => {
|
|
33
|
+
const figcaption = doc.createElement('figcaption')
|
|
34
|
+
figcaption.textContent = data.alt
|
|
35
|
+
const figure = doc.createElement('figure')
|
|
36
|
+
figure.append(img, figcaption)
|
|
37
|
+
return figure
|
|
38
|
+
})()
|
|
39
|
+
: img
|
|
40
|
+
|
|
19
41
|
range.collapse(false)
|
|
20
|
-
range.insertNode(
|
|
42
|
+
range.insertNode(node)
|
|
21
43
|
}
|
|
22
44
|
}
|
|
23
45
|
})
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
import { onMounted, watch } from 'vue'
|
|
13
13
|
import 'floating-vue/style.css'
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
interface PropTypes {
|
|
16
16
|
options: Option[]
|
|
17
17
|
placeholder?: string
|
|
18
18
|
disabled?: boolean
|
|
@@ -28,11 +28,16 @@ const props = defineProps<{
|
|
|
28
28
|
clearable?: boolean
|
|
29
29
|
searchPlaceholder?: string
|
|
30
30
|
onSearch?: (search: string) => Promise<Option[]>
|
|
31
|
-
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const props = withDefaults(defineProps<PropTypes>(), {
|
|
34
|
+
searchPlaceholder: 'Search',
|
|
35
|
+
placeholder: 'Select',
|
|
36
|
+
})
|
|
32
37
|
|
|
33
38
|
const emit = defineEmits(['update:modelValue']) // Add 'search' event
|
|
34
39
|
|
|
35
|
-
const searchPlaceholder = $computed(() => props.searchPlaceholder
|
|
40
|
+
const searchPlaceholder = $computed(() => props.searchPlaceholder)
|
|
36
41
|
|
|
37
42
|
const searchInput = $ref<HTMLElement | undefined>()
|
|
38
43
|
|
|
@@ -46,7 +51,7 @@ let selected = $ref(false)
|
|
|
46
51
|
let open = $ref(false)
|
|
47
52
|
|
|
48
53
|
const selectedLabel = $computed((): string => {
|
|
49
|
-
if (selectedItemCount === 0) return props.placeholder
|
|
54
|
+
if (selectedItemCount === 0) return props.placeholder
|
|
50
55
|
if (selectedItemCount > 4) {
|
|
51
56
|
const str = selectedItems
|
|
52
57
|
.slice(0, 4)
|