@bagelink/vue 0.0.1145 → 0.0.1151

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 (53) hide show
  1. package/dist/components/DataPreview.vue.d.ts +12 -35
  2. package/dist/components/DataPreview.vue.d.ts.map +1 -1
  3. package/dist/components/DataTable/DataTable.vue.d.ts +1 -1
  4. package/dist/components/DataTable/DataTable.vue.d.ts.map +1 -1
  5. package/dist/components/DataTable/useTableData.d.ts +10 -2
  6. package/dist/components/DataTable/useTableData.d.ts.map +1 -1
  7. package/dist/components/Draggable/Draggable.vue.d.ts +45 -0
  8. package/dist/components/Draggable/Draggable.vue.d.ts.map +1 -0
  9. package/dist/components/Draggable/index.d.ts +5 -0
  10. package/dist/components/Draggable/index.d.ts.map +1 -0
  11. package/dist/components/Draggable/useDraggable.d.ts +31 -0
  12. package/dist/components/Draggable/useDraggable.d.ts.map +1 -0
  13. package/dist/components/Draggable/vDraggable.d.ts +4 -0
  14. package/dist/components/Draggable/vDraggable.d.ts.map +1 -0
  15. package/dist/components/ListView.vue.d.ts.map +1 -1
  16. package/dist/components/form/BagelForm.vue.d.ts.map +1 -1
  17. package/dist/components/form/FieldArray.vue.d.ts.map +1 -1
  18. package/dist/components/form/index.d.ts +0 -1
  19. package/dist/components/form/index.d.ts.map +1 -1
  20. package/dist/components/form/inputs/FileUpload.vue.d.ts +3 -0
  21. package/dist/components/form/inputs/FileUpload.vue.d.ts.map +1 -1
  22. package/dist/components/form/inputs/NumberInput.vue.d.ts.map +1 -1
  23. package/dist/components/form/inputs/Upload/UploadInput.vue.d.ts +3 -0
  24. package/dist/components/form/inputs/Upload/UploadInput.vue.d.ts.map +1 -1
  25. package/dist/components/index.d.ts +2 -0
  26. package/dist/components/index.d.ts.map +1 -1
  27. package/dist/composables/useSchemaField.d.ts +15 -0
  28. package/dist/composables/useSchemaField.d.ts.map +1 -0
  29. package/dist/index.cjs +1256 -802
  30. package/dist/index.mjs +1258 -804
  31. package/dist/style.css +272 -285
  32. package/package.json +1 -1
  33. package/src/components/DataPreview.vue +45 -116
  34. package/src/components/DataTable/DataTable.vue +18 -12
  35. package/src/components/DataTable/useTableData.ts +50 -16
  36. package/src/components/Draggable/Draggable.vue +64 -0
  37. package/src/components/Draggable/index.ts +4 -0
  38. package/src/components/Draggable/useDraggable.ts +632 -0
  39. package/src/components/Draggable/vDraggable.ts +17 -0
  40. package/src/components/ListView.vue +6 -2
  41. package/src/components/Pill.vue +1 -1
  42. package/src/components/form/BagelForm.vue +16 -101
  43. package/src/components/form/FieldArray.vue +45 -17
  44. package/src/components/form/index.ts +0 -1
  45. package/src/components/form/inputs/FileUpload.vue +10 -6
  46. package/src/components/form/inputs/NumberInput.vue +3 -1
  47. package/src/components/form/inputs/RichText/index.vue +1 -1
  48. package/src/components/form/inputs/Upload/UploadInput.vue +12 -7
  49. package/src/components/index.ts +5 -1
  50. package/src/composables/useSchemaField.ts +193 -0
  51. package/src/styles/text.css +15 -11
  52. package/src/components/form/BglField.vue +0 -132
  53. package/src/components/form/BglForm.vue +0 -157
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bagelink/vue",
3
3
  "type": "module",
4
- "version": "0.0.1145",
4
+ "version": "0.0.1151",
5
5
  "description": "Bagel core sdk packages",
6
6
  "author": {
7
7
  "name": "Neveh Allon",
@@ -1,133 +1,62 @@
1
- <script lang="ts" setup>
2
- import type { BglFormSchemaT } from '@bagelink/vue'
3
- import {
4
- BglField,
5
- Title,
6
- getFallbackSchema,
7
- iffer,
8
- isDate,
9
- keyToLabel,
10
- } from '@bagelink/vue'
11
-
12
- const props = defineProps<{
13
- showFields?: string[]
14
- schema?: BglFormSchemaT
15
- title?: string
16
- excludeUnset?: boolean
17
- }>()
18
-
19
- const itemData = defineModel<{ [key: string]: any }>('data', { default: {} })
20
-
21
- function dataTransform(dataValue: any): any {
22
- if (!dataValue) return dataValue
23
- if (Array.isArray(dataValue)) return dataValue.map(dataTransform)
24
- if (typeof dataValue === 'object') {
25
- Object.keys(dataValue).forEach((key) => {
26
- dataValue[key] = dataTransform(dataValue[key])
27
- })
28
- }
29
-
30
- if (isDate(dataValue)) {
31
- const date = new Date(dataValue)
32
- return date.toDateString()
33
- }
34
-
35
- return dataValue
36
- }
37
-
38
- function isUnset(value: any) {
39
- if (!props.excludeUnset) return false
40
- return (
41
- value === undefined || value === null || value === '' || value.length === 0
42
- )
43
- }
44
-
45
- const computedSchema = $computed(() => getFallbackSchema([itemData.value], props.showFields))
1
+ <script setup lang="ts" generic="T extends Record<string, any>">
2
+ import type { BaseBagelField } from '@bagelink/vue'
3
+ import type { Slots } from 'vue'
4
+ import type { TableSchemaProps } from '../types/TableSchema'
5
+ import { computed, useSlots } from 'vue'
6
+ import { useSchemaField } from '../composables/useSchemaField'
7
+ import { useTableData } from './DataTable/useTableData'
8
+
9
+ const props = defineProps<TableSchemaProps<T>>()
10
+ const slots = useSlots() as Slots & Record<string, (props: { row: T, field: BaseBagelField<T> }) => any>
11
+
12
+ const data = computed(() => Array.isArray(props.data) ? props.data : [props.data])
13
+
14
+ const {
15
+ computedSchema,
16
+ computedData,
17
+ } = useTableData<T>({
18
+ data,
19
+ schema: props.schema,
20
+ showFields: props.showFields,
21
+ useServerSort: false
22
+ })
23
+
24
+ const firstItem = computed(() => computedData.value[0] || {} as T)
25
+
26
+ const { renderField } = useSchemaField<T>({
27
+ mode: 'preview',
28
+ getRowData: () => firstItem.value
29
+ })
46
30
  </script>
47
31
 
48
32
  <template>
49
- <div v-if="data" class="data">
50
- <Title v-if="title" :label="title" />
51
- <template v-for="field in schema" :key="field.id">
52
- <div v-if="iffer(field, itemData)" class="data-row m_py-05">
53
- <div class="key">
54
- <p class="m-0">
55
- {{ field?.label || keyToLabel(field.id) }}
56
- </p>
57
- </div>
58
- <BglField
59
- v-model="itemData"
60
- label=""
61
- style="width: min-content; min-width: 140px"
62
- :field
63
- />
64
- </div>
33
+ <div class="data-preview">
34
+ <template v-for="field in computedSchema" :key="field.id">
35
+ <component :is="renderField(field, slots)" />
65
36
  </template>
66
- <div v-if="!schema?.length">
67
- <template v-for="{ id, label } in computedSchema" :key="id">
68
- <div v-if="!isUnset(itemData[id as any])" class="data-row">
69
- <div class="key">
70
- <p class="m-0">
71
- {{ label }}
72
- </p>
73
- </div>
74
- <div>
75
- <p v-if="id" class="m-0">
76
- {{ dataTransform(itemData[id]) }}
77
- </p>
78
- </div>
79
- </div>
80
- </template>
81
- </div>
82
- <slot name="footer" />
83
37
  </div>
84
38
  </template>
85
39
 
86
40
  <style scoped>
87
- data {
88
- font-size: var(--input-font-size);
89
- border: 1.1px solid var(--border-color);
90
- padding: 20px;
91
- border-radius: var(--input-border-radius);
92
- }
93
-
94
- .data-row {
41
+ .data-preview {
95
42
  display: flex;
96
- justify-content: space-between;
97
- border-bottom: 1px solid var(--border-color);
98
- align-items: center;
99
- min-height: 50px;
100
- }
101
- .data-row .bagel-input.shrink,
102
- .data-row .bagel-input.shrink input {
103
- min-width: 140px !important;
104
- /* margin-top: -0.45rem !important; */
43
+ flex-direction: column;
44
+ gap: 0.5rem;
105
45
  }
106
46
 
107
- .data-link {
108
- display: block;
109
- font-size: var(--input-font-size);
110
- margin-bottom: 2px;
111
- line-height: 1.3;
112
- color: var(--input-color);
113
- }
114
- @media screen and (max-width: 910px) {
115
- .data-row {
116
- display: block;
117
- /* min-height: 80px; */
118
- padding-bottom: 1rem;
119
- }
47
+ .preview-field {
48
+ display: flex;
49
+ flex-direction: column;
50
+ gap: 0.5rem;
120
51
  }
121
- </style>
122
52
 
123
- <style>
124
- .data-row .bagel-input,
125
- .data-row .bagel-input input {
126
- min-width: 140px !important;
127
- height: calc(var(--input-height) - 0.25rem) !important;
53
+ .field-label {
54
+ font-size: 0.8rem;
55
+ color: var(--bgl-black-tint);
56
+ font-weight: 500;
128
57
  }
129
58
 
130
- .data-row .bagel-input.bgl-toggle input {
131
- height:20px !important;
59
+ .field-value {
60
+ font-size: 0.95rem;
132
61
  }
133
62
  </style>
@@ -1,12 +1,13 @@
1
1
  <script setup lang="ts" generic="T extends Record<string, any>">
2
+ import type { BaseBagelField } from '@bagelink/vue'
3
+ import type { Slots } from 'vue'
2
4
  import type { TableSchemaProps } from '../../types/TableSchema'
3
5
  import {
4
- BglComponent,
5
6
  Icon,
6
7
  keyToLabel,
7
8
  } from '@bagelink/vue'
8
-
9
- import { useSlots, watch, computed } from 'vue'
9
+ import { useSlots, watch, computed, ref } from 'vue'
10
+ import { useSchemaField } from '../../composables/useSchemaField'
10
11
  import { useTableData } from './useTableData'
11
12
  import { useTableSelection } from './useTableSelection'
12
13
  import { useTableVirtualization } from './useTableVirtualization'
@@ -23,7 +24,7 @@ const emit = defineEmits<{
23
24
  'lastItemVisible': []
24
25
  }>()
25
26
 
26
- const slots: any = useSlots()
27
+ const slots = useSlots() as Slots & Record<string, (props: { row: T, field: BaseBagelField<T> }) => any>
27
28
 
28
29
  const loading = defineModel('loading', { default: false })
29
30
  const itemHeight = defineModel('itemHeight', { default: 50 })
@@ -36,6 +37,7 @@ const selectedItems = defineModel<string[]>(
36
37
  )
37
38
 
38
39
  const data = computed(() => props.data)
40
+ const currentRowId = ref<string>('')
39
41
 
40
42
  const {
41
43
  computedSchema,
@@ -82,6 +84,14 @@ const {
82
84
  }
83
85
  })
84
86
 
87
+ function renderFieldForRow(field: BaseBagelField<T>, row: T) {
88
+ const { renderField } = useSchemaField<T>({
89
+ mode: 'table',
90
+ getRowData: () => row
91
+ })
92
+ return renderField(field, slots)
93
+ }
94
+
85
95
  const computedItemHeight = $computed(() => `${itemHeight.value}px`)
86
96
 
87
97
  watch(
@@ -175,16 +185,12 @@ watch(
175
185
  <slot
176
186
  v-if="field.id && slots[field.id]"
177
187
  :name="field.id"
178
- :row
179
- :field
188
+ :row="row"
189
+ :field="field"
180
190
  />
181
191
  <div v-else>
182
- <BglComponent
183
- :id="field.id"
184
- class="embedded-field"
185
- :field
186
- :modelValue="row"
187
- label=""
192
+ <component
193
+ :is="renderFieldForRow(field, row)"
188
194
  />
189
195
  </div>
190
196
  </td>
@@ -4,10 +4,25 @@ import { computed, ref } from 'vue'
4
4
 
5
5
  const NON_DIGIT_REGEX = /[^\d.-]/g
6
6
 
7
+ // Components that should receive their value as a child/slot instead of a prop
8
+ const SLOT_VALUE_COMPONENTS = new Set(['div', 'span', 'p'])
9
+
10
+ // Components that should receive their value as src attribute
11
+ const SRC_VALUE_COMPONENTS = new Set(['img', 'iframe'])
12
+
7
13
  export interface UseTableDataOptions<T> extends Omit<TableDataOptions<T>, 'sortField' | 'sortDirection'> {
8
14
  onSort?: (field: string, direction: SortDirectionsT) => void
9
15
  }
10
16
 
17
+ interface TransformedDataBase {
18
+ [key: `_transformed_${string}`]: any
19
+ [key: `_slot_${string}`]: boolean
20
+ [key: `_src_${string}`]: boolean
21
+ [key: `_original_${string}`]: any
22
+ }
23
+
24
+ type TransformedData<T> = T & TransformedDataBase
25
+
11
26
  export function useTableData<T extends Record<string, any>>(options: UseTableDataOptions<T>) {
12
27
  // Create reactive reference to data prop
13
28
 
@@ -21,19 +36,40 @@ export function useTableData<T extends Record<string, any>>(options: UseTableDat
21
36
  data: options.data.value,
22
37
  }))
23
38
 
24
- function transform(rowData: T): T {
25
- const transformed = { ...rowData }
39
+ function transform(rowData: T): TransformedData<T> {
40
+ const transformed = { ...rowData } as TransformedData<T>
26
41
  const schemaFields = computedSchema.value.filter((f: any) => f.id)
27
42
 
28
43
  for (const field of schemaFields) {
29
- const fieldData = rowData[`${field.id}`]
30
- const newFieldVal = field.transform?.(fieldData, rowData)
31
- ;(transformed as any)[`_transformed_${field.id}`] = newFieldVal
44
+ const fieldId = field.id as keyof T
45
+ const fieldData = rowData[fieldId]
46
+ const transformKey = `_transformed_${String(fieldId)}` as keyof TransformedDataBase
47
+ const slotKey = `_slot_${String(fieldId)}` as keyof TransformedDataBase
48
+ const srcKey = `_src_${String(fieldId)}` as keyof TransformedDataBase
49
+ const originalKey = `_original_${String(fieldId)}` as keyof TransformedDataBase
50
+
51
+ // Store the original value
52
+ ;(transformed as TransformedDataBase)[originalKey] = fieldData
53
+
54
+ // Determine if this component should receive value as slot or src
55
+ const isSlotValueComponent = typeof field.$el === 'string' && SLOT_VALUE_COMPONENTS.has(field.$el)
56
+ const isSrcValueComponent = typeof field.$el === 'string' && SRC_VALUE_COMPONENTS.has(field.$el)
57
+
58
+ ;(transformed as TransformedDataBase)[slotKey] = isSlotValueComponent
59
+ ;(transformed as TransformedDataBase)[srcKey] = isSrcValueComponent
60
+
61
+ if (field.transform) {
62
+ const newFieldVal = field.transform(fieldData, rowData)
63
+ // Store transformed value in _transformed_ key but keep original in the main field
64
+ ;(transformed as TransformedDataBase)[transformKey] = newFieldVal
65
+ } else {
66
+ ;(transformed as TransformedDataBase)[transformKey] = fieldData
67
+ }
32
68
  }
33
69
  return transformed
34
70
  }
35
71
 
36
- const computedSortField = computed(() => `_transformed_${sortField.value}`)
72
+ const computedSortField = computed(() => sortField.value ? `_transformed_${sortField.value}` : '')
37
73
 
38
74
  const computedData = computed(() => {
39
75
  const currentData = options.data.value
@@ -44,29 +80,27 @@ export function useTableData<T extends Record<string, any>>(options: UseTableDat
44
80
  return currentData
45
81
  .map(transform)
46
82
  .sort((a, z) => {
47
- let aValue = (a as any)[computedSortField.value] ?? a[sortField.value] ?? ''
48
- let bValue = (z as any)[computedSortField.value] ?? z[sortField.value] ?? ''
83
+ const aValue = (a as any)[computedSortField.value] ?? ''
84
+ const bValue = (z as any)[computedSortField.value] ?? ''
49
85
 
50
86
  if (isDate(aValue) && isDate(bValue)) {
51
- aValue = new Date(aValue).getTime()
52
- bValue = new Date(bValue).getTime()
87
+ return sortDirection.value === 'ASC'
88
+ ? new Date(aValue).getTime() - new Date(bValue).getTime()
89
+ : new Date(bValue).getTime() - new Date(aValue).getTime()
53
90
  }
54
91
 
55
92
  const numAValue = Number.parseInt(`${aValue}`.replaceAll(NON_DIGIT_REGEX, ''), 10)
56
93
  const numBValue = Number.parseInt(`${bValue}`.replaceAll(NON_DIGIT_REGEX, ''), 10)
57
94
 
58
95
  if (!Number.isNaN(numAValue) && !Number.isNaN(numBValue)) {
59
- if (sortDirection.value === 'ASC') return numAValue - numBValue
60
- return numBValue - numAValue
96
+ return sortDirection.value === 'ASC' ? numAValue - numBValue : numBValue - numAValue
61
97
  }
62
98
 
63
99
  if (typeof aValue === 'string') {
64
- if (sortDirection.value === 'ASC') return aValue.localeCompare(bValue)
65
- return bValue.localeCompare(aValue)
100
+ return sortDirection.value === 'ASC' ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue)
66
101
  }
67
102
 
68
- if (sortDirection.value === 'ASC') return aValue < bValue ? -1 : 1
69
- return aValue < bValue ? 1 : -1
103
+ return sortDirection.value === 'ASC' ? (aValue < bValue ? -1 : 1) : (aValue < bValue ? 1 : -1)
70
104
  })
71
105
  })
72
106
 
@@ -0,0 +1,64 @@
1
+ <script lang="ts" setup>
2
+ import { ref, watch, onMounted, nextTick } from 'vue'
3
+ import type { DraggableEvent } from './useDraggable'
4
+ import { useDraggable } from './useDraggable'
5
+
6
+ const props = withDefaults(defineProps<{
7
+ modelValue?: any[]
8
+ group?: string
9
+ handle?: string
10
+ mode?: 'ghost' | 'line'
11
+ disabled?: boolean
12
+ }>(), {
13
+ mode: 'line',
14
+ disabled: false
15
+ })
16
+
17
+ const emit = defineEmits<{
18
+ 'update:modelValue': [value: any[]]
19
+ 'start': [event: MouseEvent]
20
+ 'end': [event: DraggableEvent]
21
+ }>()
22
+
23
+ const dragContainer = ref<HTMLElement>()
24
+
25
+ const { initDraggableContainer } = useDraggable({
26
+ group: props.group,
27
+ handle: props.handle,
28
+ mode: props.mode,
29
+ disabled: props.disabled,
30
+ items: props.modelValue,
31
+ onStart: (event) => { emit('start', event) },
32
+ onEnd: (event: DraggableEvent) => {
33
+ const newList = [...props.modelValue!]
34
+ const [removed] = newList.splice(event.oldIndex, 1)
35
+ newList.splice(event.newIndex, 0, removed)
36
+ emit('update:modelValue', newList)
37
+
38
+ emit('end', event)
39
+ nextTick(() => {
40
+ if (dragContainer.value) {
41
+ initDraggableContainer(dragContainer.value)
42
+ }
43
+ })
44
+ }
45
+ })
46
+
47
+ watch(() => props.modelValue, () => {
48
+ if (dragContainer.value) {
49
+ initDraggableContainer(dragContainer.value)
50
+ }
51
+ }, { deep: true })
52
+
53
+ onMounted(() => {
54
+ if (dragContainer.value) {
55
+ initDraggableContainer(dragContainer.value)
56
+ }
57
+ })
58
+ </script>
59
+
60
+ <template>
61
+ <div ref="dragContainer">
62
+ <slot v-for="(item, index) in modelValue" :key="index" :item="item" :index="index" />
63
+ </div>
64
+ </template>
@@ -0,0 +1,4 @@
1
+ export { default as Draggable } from './Draggable.vue'
2
+ export { useDraggable } from './useDraggable'
3
+ export type { DraggableEvent, DraggableOptions } from './useDraggable'
4
+ export { vDraggable } from './vDraggable'