@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.
@@ -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 { useVirtualList, useIntersectionObserver, until } from '@vueuse/core'
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 slots = useSlots()
40
- const loading = defineModel('loading', { default: false })
43
+ const NON_DIGIT_REGEX = /[^\d.-]/g
41
44
 
42
- const itemHeight = defineModel('itemHeight', { default: 50 })
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
- const isSelectable = $computed(() => selectable === true && Array.isArray(selectedItems.value))
57
+ let sortField = $ref('')
58
+ let sortDirection = $ref<SortDirectionsT>('ASC')
60
59
 
61
- const computedSortField = $computed(() => `_transformed_${sortField}`)
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 (!allSelector) return
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
- allSelector.checked = allSelected
165
- allSelector.indeterminate = !allSelected && computedSelectedItems.length > 0
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((key) => {
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
- if (index > -1) {
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(() => lastItem).toBeTruthy()
171
+ await until(() => lastItemEl).toBeTruthy()
196
172
 
197
- useIntersectionObserver(lastItem, ([entry]) => {
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="allSelector"
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="lastItem" />
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: Record<string, any>, key: string) {
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) {
@@ -60,7 +60,6 @@ export function useEditor() {
60
60
  styles.add(style)
61
61
  }
62
62
  })
63
-
64
63
  updateListStyles(styles)
65
64
  state.selectedStyles = styles
66
65
  }
@@ -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: { src: string, alt: string }) => {
21
+ onSubmit: (data: Record<string, any>) => {
14
22
  if (data.src) {
15
23
  const img = doc.createElement('img')
16
- img.src = data.src
17
- img.alt = data.alt
18
- // range.deleteContents()
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(img)
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
- const props = defineProps<{
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 || 'Search')
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 || 'Select'
54
+ if (selectedItemCount === 0) return props.placeholder
50
55
  if (selectedItemCount > 4) {
51
56
  const str = selectedItems
52
57
  .slice(0, 4)
@@ -43,7 +43,6 @@ function toggleMenu() {
43
43
  v-tooltip.right="{
44
44
  content: nav.label,
45
45
  disabled: open,
46
- class: ['nav-tooltip'],
47
46
  }"
48
47
  :to="nav.to"
49
48
  class="nav-button px-075 me-auto w-100"