@bagelink/vue 0.0.25 → 0.0.35

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 (82) hide show
  1. package/package.json +34 -9
  2. package/src/components/Btn.vue +221 -0
  3. package/src/components/Comments.vue +284 -0
  4. package/src/components/ContactArray.vue +142 -0
  5. package/src/components/ContactSubmissions.vue +45 -0
  6. package/src/components/DataPreview.vue +85 -0
  7. package/src/components/DropDown.vue +122 -0
  8. package/src/components/FileUploader.vue +353 -0
  9. package/src/components/FormKitTable.vue +299 -0
  10. package/src/components/FormSchema.vue +79 -0
  11. package/src/components/LangText.vue +32 -0
  12. package/src/components/ListItem.vue +20 -0
  13. package/src/components/ListView.vue +54 -0
  14. package/src/components/MaterialIcon.vue +19 -0
  15. package/src/components/Modal.vue +62 -0
  16. package/src/components/ModalForm.vue +109 -0
  17. package/src/components/NavBar.vue +353 -0
  18. package/src/components/PageTitle.vue +17 -0
  19. package/src/components/PersonPreview.vue +203 -0
  20. package/src/components/PersonPreviewFormkit.vue +205 -0
  21. package/src/components/RTXEditor.vue +151 -0
  22. package/src/components/RouterWrapper.vue +17 -0
  23. package/src/components/TabbedLayout.vue +83 -0
  24. package/src/components/TableSchema.vue +248 -0
  25. package/src/components/TopBar.vue +5 -0
  26. package/src/components/charts/BarChart.vue +316 -0
  27. package/src/components/dashboard/Lineart.vue +197 -0
  28. package/src/components/form/ItemRef.vue +45 -0
  29. package/src/components/form/MaterialIcon.vue +19 -0
  30. package/src/components/form/PlainInputField.vue +79 -0
  31. package/src/components/form/inputs/CheckInput.vue +143 -0
  32. package/src/components/form/inputs/Checkbox.vue +77 -0
  33. package/src/components/form/inputs/ColorPicker.vue +47 -0
  34. package/src/components/form/inputs/CurrencyInput.vue +137 -0
  35. package/src/components/form/inputs/DateInput.vue +55 -0
  36. package/src/components/form/inputs/DatetimeInput.vue +50 -0
  37. package/src/components/form/inputs/DurationInput.vue +55 -0
  38. package/src/components/form/inputs/DynamicLinkField.vue +142 -0
  39. package/src/components/form/inputs/EmailInput.vue +57 -0
  40. package/src/components/form/inputs/FloatInput.vue +52 -0
  41. package/src/components/form/inputs/IntInput.vue +53 -0
  42. package/src/components/form/inputs/JSONInput.vue +55 -0
  43. package/src/components/form/inputs/LinkField.vue +300 -0
  44. package/src/components/form/inputs/Password.vue +91 -0
  45. package/src/components/form/inputs/PasswordInput.vue +92 -0
  46. package/src/components/form/inputs/PlainText.vue +63 -0
  47. package/src/components/form/inputs/ReadOnlyInput.vue +28 -0
  48. package/src/components/form/inputs/RichTextEditor.vue +56 -0
  49. package/src/components/form/inputs/SelectField.vue +258 -0
  50. package/src/components/form/inputs/TableField.vue +319 -0
  51. package/src/components/form/inputs/TextArea.vue +79 -0
  52. package/src/components/form/inputs/TextInput.vue +63 -0
  53. package/src/components/form/inputs/index.ts +16 -0
  54. package/src/components/formkit/AddressArray.vue +240 -0
  55. package/src/components/formkit/BankDetailsArray.vue +265 -0
  56. package/src/components/formkit/ContactArrayFormKit.vue +192 -0
  57. package/src/components/formkit/FileUploader.vue +391 -0
  58. package/src/components/formkit/MiscFields.vue +74 -0
  59. package/src/components/formkit/Toggle.vue +164 -0
  60. package/src/components/formkit/index.ts +29 -0
  61. package/src/components/index.ts +20 -0
  62. package/src/components/whatsapp/form/MsgTemplate.vue +227 -0
  63. package/src/components/whatsapp/form/TextVariableExamples.vue +79 -0
  64. package/src/components/whatsapp/interfaces.ts +58 -0
  65. package/src/index.ts +1 -26
  66. package/src/plugins/bagel.ts +26 -0
  67. package/src/styles/modal.css +90 -0
  68. package/src/types/BagelField.ts +57 -0
  69. package/src/types/BtnOptions.ts +14 -0
  70. package/src/types/Person.ts +51 -0
  71. package/src/types/file.ts +12 -0
  72. package/src/types/index.ts +4 -0
  73. package/src/types/materialIcons.d.ts +3005 -0
  74. package/src/utils/index.ts +62 -0
  75. package/src/utils/modal.ts +101 -0
  76. package/src/utils/objects.ts +81 -0
  77. package/src/utils/strings.ts +36 -0
  78. package/dist/index.cjs +0 -23
  79. package/dist/index.d.cts +0 -12
  80. package/dist/index.d.mts +0 -12
  81. package/dist/index.d.ts +0 -12
  82. package/dist/index.mjs +0 -19
@@ -0,0 +1,45 @@
1
+ <template>
2
+ <div class="card h-100 thin">
3
+ <TableSchema
4
+ :schema="schema"
5
+ :data="data"
6
+ />
7
+ </div>
8
+ </template>
9
+
10
+ <script setup lang="ts">
11
+ import { onMounted } from 'vue';
12
+ import { useBagel } from 'src/plugins/bagel';
13
+ import { TableSchema } from '@/components';
14
+
15
+ const bagel = useBagel();
16
+
17
+ const props = defineProps({
18
+ person_id: {
19
+ type: String,
20
+ required: true,
21
+ },
22
+ });
23
+
24
+ const schema = [
25
+ {
26
+ id: 'created_at',
27
+ label: 'Date',
28
+ transform: (value: string) => new Date(value).toLocaleDateString(),
29
+ },
30
+ {
31
+ id: 'message',
32
+ label: 'Message',
33
+
34
+ },
35
+ ];
36
+
37
+ let data = $ref<any[]>([]);
38
+
39
+ onMounted(() => {
40
+ const getData = async () => {
41
+ data = await bagel.get(`cms/form-submissions/${props.person_id}`);
42
+ };
43
+ void getData();
44
+ });
45
+ </script>
@@ -0,0 +1,85 @@
1
+ <template>
2
+ <div
3
+ v-if="data"
4
+ class="data"
5
+ >
6
+ <h3
7
+ class="mb-3 mt-0"
8
+ v-if="title"
9
+ >
10
+ {{ title }}
11
+ </h3>
12
+ <div
13
+ v-for="field in schema || []"
14
+ :key="field.id"
15
+ class="data-row"
16
+ >
17
+ <div class="key">
18
+ {{ field.label ? parseLocale(field.label) : keyToLabel(field.id) }}
19
+ </div>
20
+ <component
21
+ :is="field.$el || 'div'"
22
+ class="vlue"
23
+ >
24
+ {{ data[field.id] || field.defaultValue }}
25
+ </component>
26
+ </div>
27
+ <div v-if="!schema?.length">
28
+ <div
29
+ class="data-row"
30
+ v-for="[key, value] in Object.entries(data).filter(
31
+ ([key]) => !keysToIgnore.includes(key),
32
+ )"
33
+ :key="key"
34
+ >
35
+ <div class="key">
36
+ {{ $t(keyToLabel(key)) }}
37
+ </div>
38
+ <div class="vlue">
39
+ {{ value }}
40
+ </div>
41
+ </div>
42
+ </div>
43
+ <slot name="footer" />
44
+ </div>
45
+ </template>
46
+
47
+ <script lang="ts" setup>
48
+ import { keyToLabel, parseLocale } from '@/utils';
49
+
50
+ const keysToIgnore = ['id', 'person_id', 'person', 'created_at', 'updated_at'];
51
+
52
+ const props = withDefaults(defineProps<{
53
+ data: Record<string, any>,
54
+ schema?: Record<string, any>[],
55
+ title?: string,
56
+ $t: (str: string) => string,
57
+ }>(), {
58
+ $t: (str: string) => str,
59
+ });
60
+ </script>
61
+
62
+ <style scoped>
63
+ .data {
64
+ border: 1.1px solid var(--border-color);
65
+ padding: 20px;
66
+ border-radius: var(--input-border-radius);
67
+ }
68
+
69
+ .data-row {
70
+ display: flex;
71
+ justify-content: space-between;
72
+ padding-bottom: 0.5rem;
73
+ margin-bottom: 0.5rem;
74
+ opacity: 0.8;
75
+ border-bottom: 1px solid var(--border-color);
76
+ }
77
+
78
+ .data-link {
79
+ display: block;
80
+ font-size: var(--input-font-size);
81
+ margin-bottom: 2px;
82
+ line-height: 1.3;
83
+ color: var(--input-color);
84
+ }
85
+ </style>
@@ -0,0 +1,122 @@
1
+ <template>
2
+ <div class="dropdown" @click="toggleDropdown" :class="{ opendrop: isOpen }">
3
+ <div class="dropdown-title">
4
+ {{ selectedOption || placeholder }}
5
+ <MaterialIcon icon="keyboard_arrow_down" />
6
+ </div>
7
+ <div class="dropdown-body">
8
+ <p
9
+ v-for="(option, index) in options"
10
+ :key="index"
11
+ @click.stop="selectOption(option as string, index as number)"
12
+ >
13
+ {{ option }}
14
+ </p>
15
+ </div>
16
+ </div>
17
+ </template>
18
+
19
+ <script setup lang="ts">
20
+ import { ref } from 'vue';
21
+ import { MaterialIcon } from '@/components';
22
+
23
+ const props = defineProps({
24
+ modelValue: String,
25
+ options: Array,
26
+ placeholder: String,
27
+ });
28
+ const emit = defineEmits(['update:modelValue']);
29
+
30
+ const isOpen = ref(false);
31
+ const selectedOption = ref(props.modelValue);
32
+
33
+ function toggleDropdown() {
34
+ isOpen.value = !isOpen.value;
35
+ }
36
+
37
+ function selectOption(option: string, index: number) {
38
+ selectedOption.value = option;
39
+ isOpen.value = false;
40
+ emit('update:modelValue', { option, index }); // Emit the selected option value with v-model
41
+ }
42
+ </script>
43
+
44
+ <style>
45
+ .dropdown {
46
+ position: relative;
47
+ font-size: calc(var(--input-font-size) * 1.3);
48
+ width: 50px;
49
+ /* color: var(--bgl-blue); */
50
+ z-index: 1;
51
+ }
52
+
53
+ .dropdown-title {
54
+ white-space: nowrap;
55
+ border-radius: var(--input-border-radius);
56
+ box-shadow: 0 1px 2px 0 rgb(0 0 0 / 10%);
57
+ padding-left: calc(var(--btn-padding) / 2);
58
+ padding-right: calc(var(--btn-padding) / 2);
59
+ display: flex;
60
+ align-items: center;
61
+ min-height: var(--input-height);
62
+ cursor: pointer;
63
+ transition: var(--bgl-transition);
64
+ background: var(--bgl-white);
65
+ justify-content: space-between;
66
+ user-select: none;
67
+ position: relative;
68
+ }
69
+
70
+ .open .dropdown {
71
+ min-width: 120px;
72
+ }
73
+
74
+ .dropdown-title:hover {
75
+ filter: var(--bgl-hover-filter);
76
+ color: var(--bgl-blue);
77
+ }
78
+
79
+ .dropdown-title:active {
80
+ filter: var(--bgl-active-filter);
81
+ }
82
+
83
+ .dropdown-body {
84
+ border-radius: var(--input-border-radius);
85
+ position: absolute;
86
+ transition: var(--bgl-transition);
87
+ max-height: 0;
88
+ overflow: hidden;
89
+ background: var(--bgl-white);
90
+ inset-inline-start: 0;
91
+ inset-inline-end: 0;
92
+ overflow: auto;
93
+ box-shadow: 0 1px 2px 0 rgb(0 0 0 / 10%);
94
+ }
95
+
96
+ .dropdown-body * {
97
+ display: block;
98
+ cursor: pointer;
99
+ padding: calc(var(--btn-padding) / 2);
100
+ padding-bottom: calc(var(--btn-padding) / 4);
101
+ padding-top: calc(var(--btn-padding) / 4);
102
+ color: inherit;
103
+ text-decoration: none;
104
+ line-height: 1;
105
+ transition: var(--bgl-transition);
106
+ box-shadow: 0 -1px 0 0 rgb(0 0 0, 10%);
107
+ z-index: 99999999;
108
+ }
109
+
110
+ .dropdown-body *:hover {
111
+ filter: var(--bgl-hover-filter);
112
+ color: var(--bgl-blue);
113
+ }
114
+
115
+ .dropdown-body *:active {
116
+ filter: var(--bgl-active-filter);
117
+ }
118
+
119
+ .dropdown.opendrop .dropdown-body {
120
+ max-height: 150px;
121
+ }
122
+ </style>
@@ -0,0 +1,353 @@
1
+ <template>
2
+ <div class="files-wrapper flex">
3
+ <div
4
+ ref="dropZoneEl"
5
+ class="drop-zone flex-grow"
6
+ @click="openFileDialog"
7
+ @dragenter="draggingOver = true"
8
+ @drop.prevent.stop="onDrop"
9
+ >
10
+ <Transition name="pop">
11
+ <div
12
+ ref="dropCircle"
13
+ v-if="draggingOver"
14
+ class="drop-circle"
15
+ />
16
+ </Transition>
17
+ <div class="img-label">
18
+ <p>
19
+ {{ form.dragDrop }} <span>{{ form.browse }}</span>
20
+ </p>
21
+ </div>
22
+ <div class="uploading-wrap">
23
+ <div
24
+ v-for="(item, index) in files"
25
+ :class="{ uploading: item.uploading }"
26
+ :key="index"
27
+ >
28
+ <div class="load-file-bar">
29
+ <p>{{ item.file.name }}</p>
30
+ <div
31
+ class="pie"
32
+ :style="`--p:${item.progress}`"
33
+ style="--b: 2px"
34
+ >
35
+ <span>{{ `${item.progress}` }}</span>
36
+ </div>
37
+ </div>
38
+ </div>
39
+ </div>
40
+ </div>
41
+ <input
42
+ class="file-input"
43
+ type="file"
44
+ @change="handleFileInput"
45
+ ref="fileInputEl"
46
+ :multiple="!singleFile"
47
+ >
48
+ </div>
49
+ </template>
50
+
51
+ <script setup lang="ts">
52
+ import { useBagel } from 'src/plugins/bagel';
53
+ import { ref, onMounted, onUnmounted } from 'vue';
54
+
55
+ const bagel = useBagel();
56
+
57
+ const draggingOver = ref(false);
58
+ const dropCircle = ref<HTMLElement>();
59
+ const dropZoneEl = ref<HTMLElement>();
60
+ const fileInputEl = ref<HTMLInputElement>();
61
+ const circleTop = ref('0');
62
+ const circleLeft = ref('0');
63
+ const files = ref<
64
+ {
65
+ progress: string;
66
+ uploading: boolean;
67
+ uid: string;
68
+ file: File;
69
+ }[]
70
+ >([]);
71
+ const props = withDefaults(
72
+ defineProps<{
73
+ id?: string;
74
+ // folder?: string,
75
+ private?: 1 | 0;
76
+ singleFile?: boolean;
77
+ beforeUpload?: () => Promise<any>;
78
+ form: {
79
+ dragDrop: string
80
+ browse: string
81
+ }
82
+ }>(),
83
+ {
84
+ private: 0,
85
+ entity: '',
86
+ id: '',
87
+ beforeUpload: async () => { },
88
+ },
89
+ );
90
+
91
+ /**
92
+ * Drag and drop
93
+ */
94
+
95
+ function openFileDialog() {
96
+ fileInputEl.value?.click();
97
+ }
98
+
99
+ function onDragOver(e: DragEvent) {
100
+ if (!draggingOver.value) return;
101
+ // set the position of the circle to the cursor
102
+ const parentEl = dropZoneEl.value?.getBoundingClientRect?.() || {
103
+ left: 0,
104
+ top: 0,
105
+ width: 0,
106
+ height: 0,
107
+ };
108
+ const x = e.clientX - parentEl.left;
109
+ const y = e.clientY - parentEl.top;
110
+ circleLeft.value = `${x}px`;
111
+ circleTop.value = `${y}px`;
112
+ // if the cursor is outside the dropzone, hide the circle
113
+ if (x < 0 || x > parentEl.width || y < 0 || y > parentEl.height) {
114
+ draggingOver.value = false;
115
+ }
116
+ }
117
+
118
+ function handleFileInput(e: Event) {
119
+ const filesToAdd: FileList = (e.target as any).files;
120
+ addFiles(filesToAdd);
121
+ }
122
+
123
+ function preventDefaults(e: Event) {
124
+ e.preventDefault();
125
+ }
126
+
127
+ function hideCircle(e: DragEvent) {
128
+ console.log({ e });
129
+
130
+ draggingOver.value = false;
131
+ }
132
+
133
+ const events = ['dragenter', 'dragover', 'dragleave', 'drop'];
134
+
135
+ onMounted(() => {
136
+ events.forEach((event) => {
137
+ document.addEventListener(event, preventDefaults);
138
+ });
139
+ document.addEventListener('dragover', onDragOver);
140
+ });
141
+
142
+ onUnmounted(() => {
143
+ document.removeEventListener('dragover', onDragOver);
144
+ events.forEach((event) => {
145
+ document.removeEventListener(event, preventDefaults);
146
+ });
147
+ });
148
+
149
+ /**
150
+ * managing files
151
+ */
152
+
153
+ function addFiles(addedFiles: FileList) {
154
+ if (props.singleFile && files.value.length > 1) return;
155
+ for (let i = 0; i < addedFiles.length; i++) {
156
+ files.value.push({
157
+ file: addedFiles[i],
158
+ uid: Math.random().toString(36).substring(2, 9),
159
+ progress: '',
160
+ uploading: false,
161
+ });
162
+ }
163
+ uploadFiles();
164
+ }
165
+
166
+ /**
167
+ *
168
+ *
169
+ */
170
+ const emit = defineEmits(['complete', 'done']);
171
+
172
+ /**
173
+ *
174
+ * server stuff
175
+ */
176
+
177
+ function uploadFiles() {
178
+ files.value.forEach((item) => {
179
+ item.uploading = true;
180
+ /// TODO upload file
181
+ });
182
+ }
183
+
184
+ // function updateProgress(e: ProgressEvent, uid: string) {
185
+ // files.value.find((item) => item.uid === uid).progress = (
186
+ // (e.loaded / e.total)
187
+ // * 100
188
+ // ).toFixed(0);
189
+ // }
190
+
191
+ // function uploadCompleteCallback(file: any, uid: string) {
192
+ // files.value.forEach((item, index) => {
193
+ // if (item.uid === uid) {
194
+ // files.value.splice(index, 1);
195
+ // }
196
+ // });
197
+ // emit('complete', file);
198
+ // if (files.value.length === 0) {
199
+ // fileInputEl.value.value = '';
200
+ // emit('done');
201
+ // }
202
+ // }
203
+
204
+ async function onDrop(e: DragEvent) {
205
+ hideCircle(e);
206
+ preventDefaults(e);
207
+ const filesToAdd = e.dataTransfer?.files;
208
+ if (filesToAdd) {
209
+ addFiles(filesToAdd);
210
+ const file = await bagel.uploadFile(filesToAdd[0]);
211
+ emit('complete', file);
212
+ }
213
+ }
214
+ </script>
215
+ <style>
216
+ /* .uploading-wrap {
217
+ width: 100%;
218
+ } */
219
+
220
+ /* .uploading {
221
+ margin: 0.5rem;
222
+ } */
223
+
224
+ /* .img-label .icon-font {
225
+ font-size: 30px;
226
+ margin-bottom: 10px;
227
+ } */
228
+
229
+ /* .img-label span {
230
+ text-decoration: underline;
231
+ }
232
+
233
+ .file-input {
234
+ display: none;
235
+ } */
236
+
237
+ .files-wrapper {
238
+ /* flex-direction: column;
239
+ border-radius: 10px; */
240
+ /*overflow: hidden;*/
241
+ /* min-height: 100px;
242
+ font-size: var(--input-font-size); */
243
+ }
244
+
245
+ .drop-zone {
246
+ /* background-color: var(--bgl-bg);
247
+ height: 100%;
248
+ width: 100%;
249
+ flex-grow: 1;
250
+ position: relative;
251
+ overflow: hidden;
252
+ cursor: pointer;
253
+ transition: var(--bgl-transition);
254
+ outline: dashed 1px var(--bgl-black-tint);
255
+ border-radius: 10px;
256
+ padding: 1px;
257
+ display: flex;
258
+ flex-direction: column;
259
+ align-items: center;
260
+ justify-content: center;
261
+ color: var(--input-color); */
262
+ }
263
+
264
+ .drop-zone:hover {
265
+ /* color: var(--bgl-blue);
266
+ outline: dashed 1px var(--bgl-blue-tint); */
267
+ }
268
+
269
+ .drop-circle {
270
+ /* pointer-events: none;
271
+ position: absolute;
272
+ width: 100px;
273
+ height: 100px;
274
+ border-radius: 50%;
275
+ background-color: var(--bgl-blue-tint);
276
+ display: flex;
277
+ top: v-bind(circleTop);
278
+ left: v-bind(circleLeft);
279
+ transform: translate(-50%, -50%) scale(1);
280
+ transform-origin: left top; */
281
+ }
282
+
283
+ /* .drop-circle.active {
284
+ color: red;
285
+ background-color: black;
286
+ transform: translate(-50%, -50%) scale(1);
287
+ transition: transform 0.2s ease-in-out;
288
+ } */
289
+ .load-file-bar {
290
+ /* display: flex;
291
+ align-items: center;
292
+ justify-content: space-between;
293
+ background: var(--bgl-white);
294
+ border-radius: var(--btn-border-radius);
295
+ width: 100%;
296
+ color: var(--input-color);
297
+ height: var(--btn-height);
298
+ padding: 0.5rem;
299
+ box-shadow: 0 1px 2px 0 rgb(0 0 0 / 10%);
300
+ white-space: nowrap; */
301
+ }
302
+
303
+ .load-file-bar p {
304
+ /* width: calc(100% - 40px);
305
+ overflow: hidden;
306
+ text-overflow: ellipsis; */
307
+ }
308
+
309
+ .load-file-bar span {
310
+ /* font-size: 10px; */
311
+ }
312
+
313
+ .pie {
314
+ /* width: 30px;
315
+ height: 30px;
316
+ position: relative;
317
+ display: flex;
318
+ align-items: center;
319
+ justify-content: center; */
320
+ }
321
+
322
+ /* .pie:before {
323
+ content: '';
324
+ position: absolute;
325
+ border-radius: 50%;
326
+ inset: 0;
327
+ background: conic-gradient(var(--bgl-blue) calc(var(--p) * 1%), #0000 0);
328
+ -webkit-mask: radial-gradient(
329
+ farthest-side,
330
+ #0000 calc(99% - var(--b)),
331
+ #000 calc(100% - var(--b))
332
+ );
333
+ mask: radial-gradient(
334
+ farthest-side,
335
+ #0000 calc(99% - var(--b)),
336
+ #000 calc(100% - var(--b))
337
+ );
338
+ } */
339
+ </style>
340
+ <style>
341
+ /* .pop-enter-active {
342
+ transition: scale 0.2s cubic-bezier(0.55, 0, 0.1, 1);
343
+ }
344
+
345
+ .pop-leave-active {
346
+ transition: scale 0.2s cubic-bezier(0.55, 0, 0.1, 1);
347
+ }
348
+
349
+ .pop-enter-from,
350
+ .pop-leave-to {
351
+ scale: 0;
352
+ } */
353
+ </style>