@bagelink/vue 0.0.25 → 0.0.32

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