@bagelink/vue 0.0.427 → 0.0.431

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 (37) hide show
  1. package/dist/components/Alert.vue.d.ts +4 -1
  2. package/dist/components/Alert.vue.d.ts.map +1 -1
  3. package/dist/components/TableSchema.vue.d.ts +2 -5
  4. package/dist/components/TableSchema.vue.d.ts.map +1 -1
  5. package/dist/components/form/inputs/DatePicker.vue.d.ts +4 -0
  6. package/dist/components/form/inputs/DatePicker.vue.d.ts.map +1 -1
  7. package/dist/components/form/inputs/FileUpload.vue.d.ts +6 -2
  8. package/dist/components/form/inputs/FileUpload.vue.d.ts.map +1 -1
  9. package/dist/components/form/inputs/RadioPillsInput.vue.d.ts.map +1 -1
  10. package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
  11. package/dist/components/form/inputs/TextInput.vue.d.ts +0 -3
  12. package/dist/components/form/inputs/TextInput.vue.d.ts.map +1 -1
  13. package/dist/components/layout/Tabs.vue.d.ts +6 -2
  14. package/dist/components/layout/Tabs.vue.d.ts.map +1 -1
  15. package/dist/components/layout/TabsNav.vue.d.ts.map +1 -1
  16. package/dist/index.cjs +193 -113
  17. package/dist/index.mjs +194 -114
  18. package/dist/plugins/bagel.d.ts +3 -0
  19. package/dist/plugins/bagel.d.ts.map +1 -1
  20. package/dist/style.css +145 -127
  21. package/dist/utils/index.d.ts +1 -0
  22. package/dist/utils/index.d.ts.map +1 -1
  23. package/dist/utils/lang.d.ts +7 -0
  24. package/dist/utils/lang.d.ts.map +1 -0
  25. package/package.json +1 -1
  26. package/src/components/Alert.vue +4 -2
  27. package/src/components/TableSchema.vue +19 -9
  28. package/src/components/form/inputs/DatePicker.vue +8 -2
  29. package/src/components/form/inputs/FileUpload.vue +54 -23
  30. package/src/components/form/inputs/RadioPillsInput.vue +5 -4
  31. package/src/components/form/inputs/SelectInput.vue +212 -204
  32. package/src/components/form/inputs/TextInput.vue +1 -1
  33. package/src/components/layout/Tabs.vue +14 -5
  34. package/src/components/layout/TabsNav.vue +34 -14
  35. package/src/plugins/bagel.ts +13 -4
  36. package/src/utils/index.ts +2 -0
  37. package/src/utils/lang.ts +39 -0
@@ -6,15 +6,18 @@
6
6
  class="col"
7
7
  v-for="field in computedSchema"
8
8
  :key="field.id"
9
- @click="sort(field?.id || '')">
9
+ @click="sort(field?.id || '')"
10
+ >
10
11
  <div class="flex">
11
12
  {{ field.label || keyToLabel(field.id) }}
12
13
  <div
13
14
  class="list-arrows"
14
- :class="{ sorted: sortField === field.id }">
15
+ :class="{ sorted: sortField === field.id }"
16
+ >
15
17
  <MaterialIcon
16
18
  :class="{ desc: sortDirection === 'DESC' }"
17
- icon="keyboard_arrow_up" />
19
+ icon="keyboard_arrow_up"
20
+ />
18
21
  </div>
19
22
  </div>
20
23
  </th>
@@ -24,25 +27,29 @@
24
27
  v-for="row in computedData"
25
28
  :key="row.id"
26
29
  @click="selectElement(row)"
27
- class="row row-item position-relative">
30
+ class="row row-item position-relative"
31
+ >
28
32
  <td
29
33
  class="col"
30
34
  v-for="field in computedSchema.map((c) => ({
31
35
  ...c,
32
36
  transform: undefined,
33
37
  }))"
34
- :key="`${field.id}-${row.id}`">
38
+ :key="`${field.id}-${row.id}`"
39
+ >
35
40
  <slot
36
41
  v-if="field.id && slots[field.id]"
37
42
  :name="field.id"
38
43
  :row="row"
39
- :field="field" />
44
+ :field="field"
45
+ />
40
46
  <div v-else>
41
47
  <BglField
42
48
  class="embedded-field"
43
49
  :field="field"
44
50
  :modelValue="row"
45
- label="" />
51
+ label=""
52
+ />
46
53
  </div>
47
54
  </td>
48
55
  </tr>
@@ -65,14 +72,17 @@ const loading = $ref(true);
65
72
 
66
73
  const props = defineProps<{
67
74
  data: any[];
68
- schema: BglFormSchemaT | (() => BglFormSchemaT);
75
+ schema?: BglFormSchemaT | (() => BglFormSchemaT);
69
76
  }>();
70
77
 
71
78
  const computedSchema = $computed(() => {
72
79
  if (typeof props.schema === 'function') {
73
80
  return props.schema();
74
81
  }
75
- return props.schema;
82
+ if (props.schema) return props.schema;
83
+ const keys = [...new Set((props.data || []).map(Object.keys).flat())] as string[];
84
+ const schema: BglFormSchemaT = keys.map((id) => ({ id, label: keyToLabel(id) }));
85
+ return schema;
76
86
  });
77
87
 
78
88
  const emit = defineEmits(['select', 'orderBy']);
@@ -5,11 +5,14 @@
5
5
  inline
6
6
  week-start="0"
7
7
  v-model="selectedDate"
8
+ :allowed-dates="allowedDates"
9
+ :disabled-dates="disabledDates"
8
10
  :auto-apply="true"
9
11
  :highlight-week-days="[6]"
10
12
  :enable-time-picker="false"
11
13
  :month-change-on-scroll="false"
12
- v-bind="options">
14
+ v-bind="options"
15
+ >
13
16
  <template #action-buttons />
14
17
  <template #action-preview />
15
18
  </VDatepicker>
@@ -21,7 +24,8 @@
21
24
  :id="`${hr}_${id}`"
22
25
  :name="label"
23
26
  :value="hr"
24
- v-model="selectedHour" />
27
+ v-model="selectedHour"
28
+ />
25
29
  <label :for="`${hr}_${id}`">{{ hr }}</label>
26
30
  </template>
27
31
  </div>
@@ -38,6 +42,8 @@ const props = defineProps<{
38
42
  options?: Record<string, any>;
39
43
  showTimeWrap?: boolean;
40
44
  modelValue?: Date;
45
+ allowedDates?: string[] | Date[];
46
+ disabledDates?: string[] | Date[];
41
47
  }>();
42
48
 
43
49
  const emit = defineEmits(['update:modelValue']);
@@ -12,18 +12,14 @@
12
12
  :class="{
13
13
  fileDropZone: !storageFiles.length && !fileQueue.length,
14
14
  dragover: isDragOver,
15
- }">
15
+ }"
16
+ >
16
17
  <template v-for="file in storageFiles" :key="file.id">
17
18
  <div class="imagePreviewWrap" v-if="!multiple">
18
19
  <img class="preview" :src="file.url" alt="" />
19
20
  </div>
20
21
  <div class="previewName">
21
- <img
22
- height="60"
23
- v-if="multiple"
24
- class="preview"
25
- :src="file.url"
26
- alt="" />
22
+ <img v-if="multiple" class="preview" :src="file.url" alt="" />
27
23
  <p class="no-margin">
28
24
  {{ file.name }}
29
25
  </p>
@@ -32,7 +28,8 @@
32
28
  @click.stop="removeFile(file)"
33
29
  flat
34
30
  icon="delete"
35
- color="red" />
31
+ color="red"
32
+ />
36
33
  </div>
37
34
  </template>
38
35
  <template v-for="fileQ in fileQueue" :key="fileQ.file">
@@ -41,11 +38,12 @@
41
38
  </div>
42
39
  <div class="previewName">
43
40
  <img
44
- height="60"
41
+ :width="width || '220'"
45
42
  v-if="multiple"
46
43
  class="preview"
47
44
  :src="fileToUrl(fileQ.file)"
48
- alt="" />
45
+ alt=""
46
+ />
49
47
  <p class="no-margin">
50
48
  {{ fileQ.name }}
51
49
  </p>
@@ -53,7 +51,8 @@
53
51
  class="pie"
54
52
  :style="`--p:${fileQ.progress}`"
55
53
  style="--b: 2px"
56
- :class="{ complete: fileQ.progress === 100 }">
54
+ :class="{ complete: fileQ.progress === 100 }"
55
+ >
57
56
  <span class="progress" v-if="fileQ.progress < 100">
58
57
  {{ `${fileQ.progress.toFixed(0)}` }}
59
58
  </span>
@@ -66,7 +65,7 @@
66
65
  </template>
67
66
 
68
67
  <script setup lang="ts">
69
- import { watch } from 'vue';
68
+ import { onMounted, watch } from 'vue';
70
69
  import { Btn, type StorageFile, useBagel, MaterialIcon } from '@bagelink/vue';
71
70
 
72
71
  const bagel = useBagel();
@@ -84,11 +83,12 @@ type StrKey = keyof StorageFile;
84
83
  type FSValue = string[] | string | number;
85
84
 
86
85
  const props = defineProps<{
87
- label: string;
86
+ label?: string;
88
87
  multiple?: boolean;
89
88
  files?: StorageFile | StorageFile[];
90
89
  deleteEndpoint?: string;
91
90
  bindkey?: StrKey;
91
+ width?: string;
92
92
  }>();
93
93
 
94
94
  const bindKey: StrKey = props.bindkey || 'id';
@@ -99,12 +99,36 @@ const storageFiles = $ref<StorageFile[]>([]);
99
99
  const compareIds = (v1?: FSValue, v2?: FSValue) =>
100
100
  [v1].flat().join(',') === [v2].flat().join(',');
101
101
 
102
+ onMounted(() => {
103
+ if (!props.files && [file_bindkeys.value].flat().length) {
104
+ const ids = [file_bindkeys.value].flat();
105
+ if (props.multiple) {
106
+ ids.forEach((id) => {
107
+ void bagel.get<StorageFile>(`/files/${id}`).then((file) => {
108
+ storageFiles.push(file);
109
+ });
110
+ });
111
+ } else {
112
+ void bagel.get<StorageFile>(`/files/${ids[0]}`).then((file) => {
113
+ storageFiles.push(file);
114
+ });
115
+ }
116
+ }
117
+ });
118
+
102
119
  watch(
103
120
  () => props.files,
104
121
  (newFiles) => {
105
- if (newFiles) storageFiles.push(...[newFiles].flat());
122
+ if (newFiles) {
123
+ const filesToAdd = [newFiles]
124
+ .flat()
125
+ .filter((f) => !storageFiles.find((sf) => sf[bindKey] === f[bindKey]));
126
+ for (const file of filesToAdd) {
127
+ storageFiles.push(file);
128
+ }
129
+ }
106
130
  },
107
- { immediate: true }
131
+ { immediate: true },
108
132
  );
109
133
 
110
134
  watch(
@@ -119,7 +143,7 @@ watch(
119
143
  file_bindkeys.value = idValue;
120
144
  }
121
145
  },
122
- { deep: true }
146
+ { deep: true },
123
147
  );
124
148
 
125
149
  const fileQueue = $ref<QueueFile[]>([]);
@@ -159,7 +183,7 @@ const browse = () => {
159
183
  const target = e?.target as HTMLInputElement;
160
184
  if (target?.files) {
161
185
  Array.from(target.files).forEach((file: File) =>
162
- fileQueue.push({ name: file.name, file, progress: 0 })
186
+ fileQueue.push({ name: file.name, file, progress: 0 }),
163
187
  );
164
188
  }
165
189
  flushQueue();
@@ -183,7 +207,7 @@ const drop = (e: DragEvent) => {
183
207
  preventDefault(e);
184
208
  if (e.dataTransfer) {
185
209
  Array.from(e.dataTransfer.files).forEach((file: File) =>
186
- fileQueue.push({ name: file.name, file, progress: 0 })
210
+ fileQueue.push({ name: file.name, file, progress: 0 }),
187
211
  );
188
212
  }
189
213
  isDragOver = false;
@@ -193,14 +217,18 @@ const drop = (e: DragEvent) => {
193
217
 
194
218
  <style scoped>
195
219
  .bagel-input .fileUploadWrap {
220
+ --width: 320px;
196
221
  outline: 1px solid var(--border-color);
197
222
  border-radius: var(--input-border-radius);
198
223
  text-align: center;
199
224
  cursor: pointer;
200
225
  transition: var(--bgl-transition);
201
226
  position: relative;
202
- height: 132px;
227
+ min-height: 132px;
228
+ max-height: 500px;
203
229
  font-size: var(--input-font-size);
230
+ overflow-y: auto;
231
+ background: var(--input-bg);
204
232
  }
205
233
 
206
234
  .previewName {
@@ -208,7 +236,8 @@ const drop = (e: DragEvent) => {
208
236
  text-align: start;
209
237
  color: var(--input-color);
210
238
  display: grid;
211
- grid-template-columns: 1fr 22px;
239
+ grid-template-columns: auto 1fr 22px;
240
+ gap: 1rem;
212
241
  align-items: center;
213
242
  padding-inline: 14px;
214
243
  }
@@ -222,14 +251,16 @@ const drop = (e: DragEvent) => {
222
251
  .imagePreviewWrap {
223
252
  background: var(--input-bg);
224
253
  border-radius: var(--input-border-radius);
225
- height: 90px;
226
254
  padding: 5px;
255
+ min-height: 90px;
227
256
  }
228
257
 
229
258
  img.preview {
230
- height: 80px;
259
+ width: var(--width);
260
+ /* max-width: calc(var(--width) * 2); */
231
261
  border-radius: var(--input-border-radius);
232
- object-fit: contain;
262
+ object-fit: cover;
263
+ background: var(--bgl-white);
233
264
  }
234
265
 
235
266
  .fileUploadWrap.dragover,
@@ -11,7 +11,8 @@
11
11
  :name="id"
12
12
  :value="getValue(option)"
13
13
  :checked="selectedValue === getValue(option)"
14
- @change="handleSelect" />
14
+ @change="handleSelect"
15
+ />
15
16
  <label :for="`${id}-${getValue(option)}`">{{ getLabel(option) }}</label>
16
17
  </div>
17
18
  </div>
@@ -50,9 +51,9 @@ const props = withDefaults(
50
51
  }>(),
51
52
  {
52
53
  modelValue: '',
53
- id: () => `radio-pill-${Math.random().toString(36).substr(2, 9)}`,
54
+ id: () => `radio-pill-${Math.random().toString(36).substring(2, 9)}`,
54
55
  label: '',
55
- }
56
+ },
56
57
  );
57
58
 
58
59
  let selectedValue = $ref('');
@@ -68,7 +69,7 @@ watch(
68
69
  if (newVal === oldVal || oldVal === undefined) return;
69
70
  if (selectedValue !== newVal) selectedValue = newVal;
70
71
  },
71
- { immediate: true }
72
+ { immediate: true },
72
73
  );
73
74
 
74
75
  onMounted(() => {