@bagelink/vue 0.0.318 → 0.0.331

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 (61) hide show
  1. package/dist/components/Badge.vue.d.ts +2 -2
  2. package/dist/components/Badge.vue.d.ts.map +1 -1
  3. package/dist/components/Card.vue.d.ts +2 -2
  4. package/dist/components/ComboBox.vue.d.ts +13 -2
  5. package/dist/components/ComboBox.vue.d.ts.map +1 -1
  6. package/dist/components/ListView.vue.d.ts.map +1 -1
  7. package/dist/components/Modal.vue.d.ts +0 -1
  8. package/dist/components/Modal.vue.d.ts.map +1 -1
  9. package/dist/components/ModalBglForm.vue.d.ts.map +1 -1
  10. package/dist/components/Popover.vue.d.ts +10 -0
  11. package/dist/components/Popover.vue.d.ts.map +1 -0
  12. package/dist/components/form/BglField.vue.d.ts.map +1 -1
  13. package/dist/components/form/BglForm.vue.d.ts +1 -5
  14. package/dist/components/form/BglForm.vue.d.ts.map +1 -1
  15. package/dist/components/form/inputs/DateInput.vue.d.ts +0 -1
  16. package/dist/components/form/inputs/TextArea.vue.d.ts +3 -1
  17. package/dist/components/form/inputs/TextArea.vue.d.ts.map +1 -1
  18. package/dist/components/form/inputs/TextInput.vue.d.ts +2 -0
  19. package/dist/components/form/inputs/TextInput.vue.d.ts.map +1 -1
  20. package/dist/components/formkit/index.d.ts +1 -14
  21. package/dist/components/formkit/index.d.ts.map +1 -1
  22. package/dist/components/index.d.ts +0 -1
  23. package/dist/components/index.d.ts.map +1 -1
  24. package/dist/components/layout/SidebarMenu.vue.d.ts.map +1 -1
  25. package/dist/components/whatsapp/index.d.ts +0 -2
  26. package/dist/components/whatsapp/index.d.ts.map +1 -1
  27. package/dist/index.cjs +419 -569
  28. package/dist/index.d.ts +0 -1
  29. package/dist/index.mjs +419 -569
  30. package/dist/style.css +1815 -331
  31. package/dist/types/BagelForm.d.ts +1 -1
  32. package/dist/types/BagelForm.d.ts.map +1 -1
  33. package/dist/types/materialIcon.d.ts +2 -0
  34. package/dist/types/materialIcon.d.ts.map +1 -0
  35. package/dist/types/materialIcons.d.ts +1 -1
  36. package/dist/types/materialIcons.d.ts.map +1 -1
  37. package/dist/utils/BagelFormUtils.d.ts +23 -0
  38. package/dist/utils/BagelFormUtils.d.ts.map +1 -0
  39. package/dist/utils/index.d.ts +1 -0
  40. package/dist/utils/index.d.ts.map +1 -1
  41. package/package.json +1 -1
  42. package/src/components/Badge.vue +2 -2
  43. package/src/components/Carousel.vue +137 -137
  44. package/src/components/ComboBox.vue +79 -50
  45. package/src/components/ListView.vue +28 -27
  46. package/src/components/Modal.vue +25 -23
  47. package/src/components/form/BglField.vue +33 -48
  48. package/src/components/form/BglForm.vue +65 -49
  49. package/src/components/form/inputs/TextInput.vue +20 -4
  50. package/src/components/index.ts +1 -1
  51. package/src/components/layout/SidebarMenu.vue +4 -5
  52. package/src/components/whatsapp/index.ts +2 -2
  53. package/src/styles/appearance.css +39 -0
  54. package/src/styles/bagel.css +2 -0
  55. package/src/styles/layout.css +112 -6
  56. package/src/styles/mobilLayout.css +1416 -0
  57. package/src/styles/text.css +4 -0
  58. package/src/types/BagelForm.ts +7 -7
  59. package/src/types/materialIcons.ts +1183 -3006
  60. package/src/utils/BagelFormUtils.ts +58 -0
  61. package/src/utils/index.ts +3 -0
@@ -1,26 +1,34 @@
1
1
  <template>
2
- <Dropdown placement="auto-start" class="bagel-input combobox">
3
- <button type="button" class="combobox-btn" @click="toggle">
4
- {{ valueToLabel(selectedItem) || placeholder || 'Select' }}
5
- <MaterialIcon v-bind="{ 'icon': open ? 'unfold_less' : 'unfold_more' }" />
6
- </button>
7
- <input style="width: 0; height: 0; position: absolute; opacity: 0; z-index: -1;" v-if="required"
8
- v-model="selectedItem" required>
9
- <template #popper="{ hide }">
10
- <Card thin class="combobox-options">
11
- <TextInput v-if="searchable" ref="searchInput" dense :placeholder="'Search'" icon="search" v-model="search" />
12
- <div class="combobox-option" v-for="(option, i) in filteredOptions" :key="`${option}${i}`" @click="() => {
13
- select(option)
14
- hide();
15
- }" :class="{ selected: option === selectedItem }">
16
- <span>
17
- {{ label(option) }}
18
- </span>
19
- <Icon v-if="isSelected(option)" icon="check" />
20
- </div>
21
- </Card>
22
- </template>
23
- </Dropdown>
2
+ <Dropdown placement="bottom-start" class="bagel-input combobox">
3
+ <label>
4
+ {{ label }}
5
+ <button type="button" class="combobox-btn" @click="toggle">
6
+ {{ valueToLabel(selectedItem) || placeholder || 'Select' }}
7
+ <MaterialIcon v-bind="{ 'icon': open ? 'unfold_less' : 'unfold_more' }" />
8
+ </button>
9
+ <input
10
+ style="width: 0; height: 0; position: absolute; opacity: 0; z-index: -1;" v-if="required"
11
+ v-model="selectedItem" required
12
+ >
13
+ </label>
14
+ <template #popper="{ hide }">
15
+ <Card class="combobox-options p-05" :style="{width: fullWidth?'100%':'auto'}">
16
+ <TextInput v-if="searchable" ref="searchInput" dense :placeholder="'Search'" icon="search" v-model="search" />
17
+ <div
18
+ class="combobox-option hover gap-1" v-for="(option, i) in filteredOptions" :key="`${option}${i}`" @click="() => {
19
+ select(option); hide();
20
+ }" :class="{ selected: option === selectedItem }"
21
+ >
22
+ <Icon v-if="isSelected(option)" icon="check" />
23
+ <Icon class="opacity-3" v-if="!isSelected(option)" icon="fiber_manual_record" />
24
+ <span >
25
+ {{ getLabel(option) }}
26
+ </span>
27
+ </div>
28
+ <slot name="last" />
29
+ </Card>
30
+ </template>
31
+ </Dropdown>
24
32
  </template>
25
33
 
26
34
  <script lang="ts" setup>
@@ -28,7 +36,7 @@ import { watch } from 'vue';
28
36
  import { Dropdown } from 'floating-vue';
29
37
  import 'floating-vue/style.css';
30
38
  import {
31
- TextInput, Card, Icon, MaterialIcon,
39
+ TextInput, Card, Icon, MaterialIcon,
32
40
  } from '@bagelink/vue';
33
41
 
34
42
  type Option = string | number | Record<string, any> | { label: string, value: string | number };
@@ -43,56 +51,58 @@ const props = defineProps<{
43
51
  modelValue?: Option;
44
52
  searchable?: boolean;
45
53
  required?: boolean;
54
+ label?: string;
55
+ fullWidth?: boolean;
46
56
  }>();
47
57
  let selectedItem = $ref<Option>();
48
58
  let search = $ref('');
49
59
 
50
60
  const toggle = () => {
51
- open = !open;
52
- if (!open) search = '';
53
- if (open) setTimeout(() => (searchInput as any)?.$el?.querySelector('input')?.focus(), 100);
61
+ open = !open;
62
+ if (!open) search = '';
63
+ if (open) setTimeout(() => (searchInput as any)?.$el?.querySelector('input')?.focus(), 100);
54
64
  };
55
65
 
56
66
  const valueToLabel = (value?: Option) => {
57
- if (!value) return '';
58
- const option = props.options.find((option) => {
59
- if (typeof option === 'string' || typeof option === 'number') return option === value;
60
- return option.value === value;
61
- });
62
- if (!option) return value;
63
- return label(option);
67
+ if (!value) return '';
68
+ const option = props.options.find((option) => {
69
+ if (typeof option === 'string' || typeof option === 'number') return option === value;
70
+ return option.value === value;
71
+ });
72
+ if (!option) return value;
73
+ return getLabel(option);
64
74
  };
65
75
 
66
76
  const emit = defineEmits(['update:modelValue']);
67
77
 
68
- const label = (option: Option) => {
69
- if (typeof option === 'string') return option;
70
- if (typeof option === 'number') return `${option}`;
71
- return option.label;
78
+ const getLabel = (option: Option) => {
79
+ if (typeof option === 'string') return option;
80
+ if (typeof option === 'number') return `${option}`;
81
+ return option.label;
72
82
  };
73
83
 
74
84
  const isSelected = (option: Option) => {
75
- if (typeof option === 'string' || typeof option === 'number') return option === selectedItem;
76
- return option.value === selectedItem;
85
+ if (typeof option === 'string' || typeof option === 'number') return option === selectedItem;
86
+ return option.value === selectedItem;
77
87
  };
78
88
 
79
89
  const filteredOptions = $computed(() => props.options.filter((option) => {
80
- const searchTerm = new RegExp(search, 'gi');
81
- if (typeof option === 'string') return option.match(searchTerm);
82
- if (typeof option === 'number') return `${option}`.match(searchTerm);
83
- return option.label.match(searchTerm);
90
+ const searchTerm = new RegExp(search, 'gi');
91
+ if (typeof option === 'string') return option.match(searchTerm);
92
+ if (typeof option === 'number') return `${option}`.match(searchTerm);
93
+ return option.label.match(searchTerm);
84
94
  }));
85
95
 
86
96
  const select = (option: Option) => {
87
- if (typeof option === 'string') selectedItem = option;
88
- else if (typeof option === 'number') selectedItem = option;
89
- else selectedItem = option.value;
90
- emit('update:modelValue', selectedItem);
91
- open = false;
97
+ if (typeof option === 'string') selectedItem = option;
98
+ else if (typeof option === 'number') selectedItem = option;
99
+ else selectedItem = option.value;
100
+ emit('update:modelValue', selectedItem);
101
+ open = false;
92
102
  };
93
103
 
94
104
  watch(() => props.modelValue, (value) => {
95
- if (value !== selectedItem) selectedItem = value;
105
+ if (value !== selectedItem) selectedItem = value;
96
106
  }, { immediate: true });
97
107
  </script>
98
108
 
@@ -106,9 +116,11 @@ watch(() => props.modelValue, (value) => {
106
116
  cursor: pointer;
107
117
  border-radius: 5px;
108
118
  transition: all 0.2s;
109
- display: flex;
119
+ display: grid;
120
+ grid-template-columns: 10px 1fr;
110
121
  justify-content: space-between;
111
122
  width: 100%;
123
+ font-size: var(--input-font-size);
112
124
  }
113
125
 
114
126
  .combobox-options {
@@ -122,12 +134,29 @@ watch(() => props.modelValue, (value) => {
122
134
  </style>
123
135
 
124
136
  <style>
137
+ [data-popper-shown]{
138
+ color: var(--bgl-primary) !important;
139
+ }
140
+ .bagel-input label {
141
+ font-size: var(--label-font-size);
142
+ }
125
143
  .combobox-btn {
126
144
  display: flex;
127
145
  justify-content: space-between;
128
146
  align-items: center;
129
147
  height: var(--input-height);
130
148
  border-radius: var(--input-border-radius);
149
+ border: none;
150
+ background: var(--input-bg);
151
+ padding: 0.7rem;
152
+ color: var(--input-color);
153
+ width: 100%;
154
+ font-family: inherit;
155
+ }
156
+
157
+ .combobox-btn:focus {
158
+ outline: none;
159
+ box-shadow: inset 0 0 10px #00000012;
131
160
  }
132
161
 
133
162
  .v-popper__arrow-container {
@@ -1,8 +1,9 @@
1
1
  <template>
2
2
  <div class="list-wrap bgl_card thin grid overflow-hidden h-100 p-0">
3
3
  <div class="p-1">
4
- <slot name="header" />
5
- </div> <div class="list-content auto-flow-rows align-items-start overflow-y h-100">
4
+ <slot name="header" />
5
+ </div>
6
+ <div class="list-content auto-flow-rows align-items-start overflow-y h-100">
6
7
  <slot />
7
8
  </div>
8
9
  </div>
@@ -14,46 +15,46 @@ import Card from './Card.vue';
14
15
  </script>
15
16
 
16
17
  <style>
17
- .list-wrap{
18
- grid-template-rows: auto 1fr;
18
+ .list-wrap {
19
+ grid-template-rows: auto 1fr;
19
20
  }
20
21
 
21
22
  .list-item {
22
- padding: 0.5rem 1rem;
23
- min-height: -webkit-fit-content;
24
- min-height: -moz-fit-content;
25
- min-height: fit-content;
26
- margin: 0.25rem 0;
27
- border-radius: 10px;
28
- cursor: pointer;
29
- transition: var(--bgl-transition);
30
- color: var(--bgl-black);
31
- text-decoration: none;
32
- position: relative;
23
+ padding: 0.5rem 1rem;
24
+ min-height: -webkit-fit-content;
25
+ min-height: -moz-fit-content;
26
+ min-height: fit-content;
27
+ margin: 0.25rem 0;
28
+ cursor: pointer;
29
+ transition: var(--bgl-transition);
30
+ color: var(--bgl-black);
31
+ text-decoration: none;
32
+ position: relative;
33
33
  }
34
34
 
35
35
  .list-item::after {
36
- content: "";
37
- position: absolute;
38
- left: 0;
39
- right: 0;
40
- bottom: -0.15rem;
41
- border-bottom: 1px solid var(--border-color);
36
+ content: "";
37
+ position: absolute;
38
+ left: 0;
39
+ right: 0;
40
+ bottom: -0.15rem;
41
+ border-bottom: 1px solid var(--border-color);
42
42
  }
43
43
 
44
44
  .list-item:hover,
45
45
  .list-item.router-link-active {
46
- background-color: var(--bgl-blue-light);
46
+ background-color: var(--bgl-blue-light);
47
47
  }
48
48
 
49
49
  .list-item:active {
50
- -webkit-filter: var(--bgl-hover-filter);
51
- filter: var(--bgl-hover-filter);
50
+ -webkit-filter: var(--bgl-hover-filter);
51
+ filter: var(--bgl-hover-filter);
52
52
  }
53
+
53
54
  @media screen and (max-width: 910px) {
54
55
 
55
- .list-item {
56
- padding: 0.5rem;
57
- }
56
+ .list-item {
57
+ padding: 0.5rem;
58
+ }
58
59
  }
59
60
  </style>
@@ -1,25 +1,27 @@
1
1
  <template>
2
- <div class="bg-dark" :class="{ 'is-side': side, 'is-active': isVisible, 'bg-lignt': false }"
3
- @click="() => (dismissable ? closeModal() : '')" @keydown.esc="closeModal">
4
- <Card class="modal" @click.stop>
5
- <header class="tool-bar">
6
- <slot name="toolbar" />
7
- <Btn :style="{ float: side ? 'left' : 'right' }" flat icon="close" @click="closeModal" />
8
- <Title class="modal-title" tag="h3" v-if="title" :label="title" />
9
- </header>
10
- <slot />
11
- <footer class="modal-footer mt-3">
12
- <Btn v-for="(action, i) in actions" :key="i" @click="closeModal" color="gray" v-bind="action" />
13
- <slot name="footer" />
14
- </footer>
15
- </Card>
16
- </div>
2
+ <div
3
+ class="bg-dark" :class="{ 'is-side': side, 'is-active': isVisible, 'bg-lignt': false }"
4
+ @click="() => (dismissable ? closeModal() : '')" @keydown.esc="closeModal"
5
+ >
6
+ <Card class="modal" @click.stop>
7
+ <header class="tool-bar">
8
+ <slot name="toolbar" />
9
+ <Btn :style="{ float: side ? 'left' : 'right' }" flat icon="close" @click="closeModal" />
10
+ <Title class="modal-title" tag="h3" v-if="title" :label="title" />
11
+ </header>
12
+ <slot />
13
+ <footer class="modal-footer mt-3">
14
+ <Btn v-for="(action, i) in actions" :key="i" @click="closeModal" color="gray" v-bind="action" />
15
+ <slot name="footer" />
16
+ </footer>
17
+ </Card>
18
+ </div>
17
19
  </template>
18
20
 
19
21
  <script lang="ts" setup>
20
22
  import { onMounted, onUnmounted, watch } from 'vue';
21
23
  import {
22
- type BtnOptions, Btn, useEscape, Title, Card,
24
+ type BtnOptions, Btn, useEscape, Title, Card,
23
25
  } from '@bagelink/vue';
24
26
  import '../styles/modal.css';
25
27
 
@@ -34,16 +36,16 @@ const props = defineProps<{
34
36
  let isVisible = $ref<boolean>(false);
35
37
 
36
38
  watch(() => props.visible, (val) => {
37
- if (val === isVisible || val === undefined) return;
38
- if (val) openModal();
39
- else closeModal();
39
+ if (val === isVisible || val === undefined) return;
40
+ if (val) openModal();
41
+ else closeModal();
40
42
  }, { immediate: true });
41
43
 
42
44
  const emit = defineEmits(['update:visible']);
43
45
 
44
46
  const closeModal = () => {
45
- isVisible = false;
46
- setTimeout(() => emit('update:visible', false), 200);
47
+ isVisible = false;
48
+ setTimeout(() => emit('update:visible', false), 200);
47
49
  };
48
50
 
49
51
  defineExpose({ closeModal });
@@ -51,13 +53,13 @@ defineExpose({ closeModal });
51
53
  const escapeKeyClose = (e: KeyboardEvent) => props?.dismissable && useEscape(e, () => closeModal());
52
54
 
53
55
  function openModal() {
54
- setTimeout(() => isVisible = true, 1);
56
+ setTimeout(() => isVisible = true, 1);
55
57
  }
56
58
 
57
59
  onMounted(() => document.addEventListener('keydown', escapeKeyClose));
58
60
 
59
61
  onUnmounted(() => {
60
- document.removeEventListener('keydown', escapeKeyClose);
62
+ document.removeEventListener('keydown', escapeKeyClose);
61
63
  });
62
64
  </script>
63
65
 
@@ -1,73 +1,58 @@
1
1
  <template>
2
- <component
3
- :required="field.required"
4
- v-bind="bindAttrs(field?.attrs || {}, fieldData, modelValue)"
5
- :class="classify(fieldData, modelValue, field.class, field.attrs?.class)"
6
- v-if="vIf"
7
- :is="is"
8
- :label="field.label"
9
- :id="field.id"
10
- :placeholder="field.placeholder || field.label"
11
- v-model="fieldData"
12
- :defaultValue="field.defaultValue"
13
- :options="field.options"
14
- :helptext="field.helptext"
15
- @update:modelValue="($event: any) => field?.onUpdate?.($event, formData)"
16
- >
17
- {{ field.transform?.(fieldData, modelValue) || fieldData || '' }}
18
- <BglField
19
- v-model="formData"
20
- v-for="(child, ii) in field.children"
21
- :key="child.id || ii"
22
- :field="child"
23
- />
24
- </component>
2
+ <component :required="field.required" v-bind="bindAttrs(field?.attrs || {}, fieldData, modelValue)"
3
+ :class="classify(fieldData, modelValue, field.class, field.attrs?.class)" v-if="vIf" :is="is" :label="field.label"
4
+ :id="field.id" :placeholder="field.placeholder || field.label" v-model="fieldData"
5
+ :defaultValue="field.defaultValue" :options="bindAttrs({ options: field.options }, fieldData, modelValue).options"
6
+ :helptext="field.helptext" @update:modelValue="($event: any) => field?.onUpdate?.($event, formData)">
7
+ {{ field.transform?.(fieldData, modelValue) || fieldData || '' }}
8
+ <BglField v-model="formData" v-for="(child, ii) in field.children" :key="child.id || ii" :field="child" />
9
+ </component>
25
10
  </template>
26
11
 
27
12
  <script lang="ts" setup>
28
13
  import {
29
- type Field, bindAttrs, classify, SelectInput, TextInput, ToggleInput, CheckInput,
14
+ type Field, bindAttrs, classify, ComboBox, TextInput, ToggleInput, CheckInput,
30
15
  } from '@bagelink/vue';
31
16
 
32
17
  const props = withDefaults(defineProps<{
33
- field: Field
34
- modelValue: Record<string, any>
18
+ field: Field
19
+ modelValue: Record<string, any>
35
20
  }>(), {
36
- modelValue: () => ({}),
21
+ modelValue: () => ({}),
37
22
  });
38
23
 
39
24
  const is = $computed(() => {
40
- if (props.field.$el === 'text') return TextInput;
41
- if (props.field.$el === 'select') return SelectInput;
42
- if (props.field.$el === 'toggle') return ToggleInput;
43
- if (props.field.$el === 'check') return CheckInput;
44
- return props.field.$el || 'div';
25
+ if (props.field.$el === 'text') return TextInput;
26
+ if (props.field.$el === 'select') return ComboBox;
27
+ if (props.field.$el === 'toggle') return ToggleInput;
28
+ if (props.field.$el === 'check') return CheckInput;
29
+ return props.field.$el || 'div';
45
30
  });
46
31
 
47
32
  const emit = defineEmits(['update:modelValue']);
48
33
 
49
34
  const formData = $computed({
50
- get: () => props.modelValue,
51
- set: (val: any) => emit('update:modelValue', val),
35
+ get: () => props.modelValue,
36
+ set: (val: any) => emit('update:modelValue', val),
52
37
  });
53
38
 
54
39
  const fieldData = $computed({
55
- set: (val: any) => {
56
- if (!props.field.id) return;
57
- const data = { ...props.modelValue } || {};
58
- data[props.field.id] = val;
59
- emit('update:modelValue', data);
60
- },
61
- get: () => (props.field.id ? props.modelValue[props.field.id] : props.field.defaultValue || ''),
40
+ set: (val: any) => {
41
+ if (!props.field.id) return;
42
+ const data = { ...props.modelValue } || {};
43
+ data[props.field.id] = val;
44
+ emit('update:modelValue', data);
45
+ },
46
+ get: () => (props.field.id ? props.modelValue[props.field.id] : props.field.defaultValue || ''),
62
47
  });
63
48
 
64
49
  const vIf = $computed(() => {
65
- if (props.field['v-if'] === undefined) return true;
66
- if (typeof props.field['v-if'] === 'boolean') return props.field['v-if'];
67
- if (typeof props.field['v-if'] === 'string') return true;
68
- if (typeof props.field['v-if'] === 'function') {
69
- return props.field['v-if']?.(fieldData, formData);
70
- }
71
- return true;
50
+ if (props.field['v-if'] === undefined) return true;
51
+ if (typeof props.field['v-if'] === 'boolean') return props.field['v-if'];
52
+ if (typeof props.field['v-if'] === 'string') return true;
53
+ if (typeof props.field['v-if'] === 'function') {
54
+ return props.field['v-if']?.(fieldData, formData);
55
+ }
56
+ return true;
72
57
  });
73
58
  </script>
@@ -1,52 +1,57 @@
1
1
  <template>
2
- <template v-if="id">
3
- <BglField v-for="(field, i) in schema" :key="field.id || `${i}p`" :field="field" v-model="data" />
4
- </template>
5
- <form v-else ref="form" @submit.prevent="runSubmit">
6
- <Title tag="h4" :label="label" v-if="label" />
7
- <BglField v-for="(field, i) in schema" :key="field.id || `${i}p`" :field="field" v-model="data" />
8
- <slot name="submit" />
9
- <input type="submit" hidden v-if="onSubmit" />
10
- </form>
2
+ <template v-if="id">
3
+ <BglField v-for="(field, i) in schema" :key="field.id || `${i}p`" :field="field" v-model="data" />
4
+ </template>
5
+ <form v-else-if="(!slots.success || formStatus !== 'success')" ref="form" @submit.prevent="runSubmit">
6
+ <Title tag="h4" :label="label" v-if="label" />
7
+ <BglField v-for="(field, i) in schema" :key="field.id || `${i}p`" :field="field" v-model="data" />
8
+ <slot name="submit" />
9
+ </form>
10
+ <slot v-if="formStatus === 'success'" name="success" />
11
+ <slot v-if="formStatus === 'error'" name="error" />
11
12
  </template>
12
13
 
13
14
  <script lang="ts" setup>
15
+ import { useSlots } from 'vue';
14
16
  import {
15
- useModal, BglField, Title,
17
+ useModal, BglField, Title,
16
18
  } from '@bagelink/vue';
17
19
 
18
20
  import { type BglFormSchemaT } from '@bagelink/vue';
19
21
 
22
+ const slots = useSlots();
23
+
20
24
  const { showModal } = useModal();
21
25
 
22
26
  const props = withDefaults(
23
- defineProps<{
24
- label?: string;
25
- id?: string;
26
- schema: BglFormSchemaT<any>;
27
- modelValue?: Record<string, any>;
28
- onDelete?: ((id: string) => void);
29
- onSubmit?: ((data: any) => void);
30
- }>(),
31
- {
32
- modelValue: () => ({}),
33
- },
27
+ defineProps<{
28
+ label?: string;
29
+ id?: string;
30
+ schema: BglFormSchemaT<any>;
31
+ modelValue?: Record<string, any>;
32
+ onDelete?: ((id: string) => void);
33
+ onSubmit?: ((data: any) => void);
34
+ }>(),
35
+ {
36
+ modelValue: () => ({}),
37
+ },
34
38
  );
35
39
 
36
40
  const instAt = new Date();
37
41
  const timeSinceInst = () => new Date().getTime() - instAt.getTime();
38
-
42
+ let formData = $ref(props.modelValue);
39
43
  const emit = defineEmits(['update:modelValue', 'submit', 'dirty']);
40
44
  let isDirty = $ref(false);
41
45
  const data = $computed({
42
- set: (val: any) => {
43
- if (timeSinceInst() > 100) {
44
- emit('dirty');
45
- isDirty = true;
46
- }
47
- emit('update:modelValue', val);
48
- },
49
- get: () => props.modelValue || {},
46
+ set: (val: any) => {
47
+ if (timeSinceInst() > 100) {
48
+ emit('dirty');
49
+ isDirty = true;
50
+ }
51
+ formData = val;
52
+ emit('update:modelValue', val);
53
+ },
54
+ get: () => props.modelValue || formData,
50
55
  });
51
56
  const form = $ref<HTMLFormElement>();
52
57
 
@@ -54,30 +59,41 @@ const validateForm = () => form?.reportValidity?.();
54
59
 
55
60
  const clearForm = () => Object.assign(data, {});
56
61
 
62
+ type FormStatus = 'idle' | 'loading' | 'success' | 'error';
63
+
64
+ let formStatus = $ref<FormStatus>('idle');
65
+
57
66
  const runSubmit = () => {
58
- validateForm();
59
- emit('submit', data);
60
- clearForm();
67
+ console.log('runSubmit');
68
+ try {
69
+ validateForm();
70
+ props.onSubmit?.(data);
71
+ // emit('submit', data);
72
+ clearForm();
73
+ formStatus = 'success';
74
+ } catch (e) {
75
+ formStatus = 'error';
76
+ }
61
77
  };
62
78
 
63
79
  const i18nT = (val: string) => val;
64
80
 
65
81
  const deleteItem = () => {
66
- showModal(
67
- {
68
- class: 'small-modal',
69
- title: i18nT('Are you sure?'),
70
- actions: [
71
- {
72
- value: 'Confirm',
73
- color: 'red',
74
- onClick: () => props.onDelete?.(data.value.id),
75
- },
76
- { value: 'Cancel', color: 'gray' },
77
- ],
78
- },
79
- { default: i18nT('form.deleteMessage') },
80
- );
82
+ showModal(
83
+ {
84
+ class: 'small-modal',
85
+ title: i18nT('Are you sure?'),
86
+ actions: [
87
+ {
88
+ value: 'Confirm',
89
+ color: 'red',
90
+ onClick: () => props.onDelete?.(data.value.id),
91
+ },
92
+ { value: 'Cancel', color: 'gray' },
93
+ ],
94
+ },
95
+ { default: i18nT('form.deleteMessage') },
96
+ );
81
97
  };
82
98
 
83
99
  defineExpose({ validateForm, deleteItem, isDirty });
@@ -85,6 +101,6 @@ defineExpose({ validateForm, deleteItem, isDirty });
85
101
 
86
102
  <style>
87
103
  .del-top {
88
- transform: translateY(-2.6rem);
104
+ transform: translateY(-2.6rem);
89
105
  }
90
106
  </style>