@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,143 @@
1
+ <template>
2
+ <div
3
+ class="bagel-input checkbox"
4
+ :title="field.description"
5
+ :class="{ small: small, 'no-edit': !editMode }"
6
+ >
7
+ <label :for="field.id">
8
+ {{ field.label }}
9
+ </label>
10
+ <label class="switch">
11
+ <input
12
+ :id="field.id"
13
+ type="checkbox"
14
+ v-model="inputVal"
15
+ :class="{ 'no-edit': !editMode }"
16
+ >
17
+ <span class="slider round" />
18
+ </label>
19
+ </div>
20
+ </template>
21
+
22
+ <script setup lang="ts">
23
+ import { watch, ref, onMounted } from 'vue';
24
+ import { BagelField } from '@/types';
25
+
26
+ const emits = defineEmits(['update:modelValue']);
27
+ const props = withDefaults(
28
+ defineProps<{
29
+ field: BagelField;
30
+ modelValue: any;
31
+ editMode?: boolean;
32
+ small?: boolean;
33
+ }>(),
34
+ {
35
+ editMode: true,
36
+ },
37
+ );
38
+
39
+ const inputVal = ref(false);
40
+ watch(inputVal, (newVal) => {
41
+ if (newVal === undefined) return;
42
+ emits('update:modelValue', newVal);
43
+ });
44
+ watch(
45
+ () => props.modelValue,
46
+ (newVal) => {
47
+ if (inputVal.value !== newVal) inputVal.value = newVal;
48
+ },
49
+ );
50
+ onMounted(() => (inputVal.value = !!props.modelValue));
51
+ </script>
52
+
53
+ <style scoped>
54
+ .no-edit {
55
+ pointer-events: none;
56
+ }
57
+
58
+ .radio-wrap p {
59
+ display: inline-block;
60
+ color: var(--input-bg);
61
+ font-size: var(--input-font-size);
62
+ margin-inline-end: 10px;
63
+ }
64
+
65
+ .radio-wrap label {
66
+ padding: 3px 5px;
67
+ display: inline-block;
68
+ border-radius: var(--input-border-radius);
69
+ font-size: var(--input-font-size);
70
+ background: var(--input-bg);
71
+ color: var(--bgl-black);
72
+ text-align: center;
73
+ margin: 8px 5px;
74
+ cursor: pointer;
75
+ user-select: none;
76
+ }
77
+
78
+ .bagel-input .radio-wrap label::after {
79
+ background: transparent;
80
+ }
81
+
82
+ .radio-wrap input {
83
+ display: none;
84
+ }
85
+
86
+ .radio-wrap input:checked:checked+label {
87
+ background: var(--bgl-blue);
88
+ color: var(--bgl-white);
89
+ }
90
+
91
+ .checkbox {
92
+ position: relative;
93
+ }
94
+
95
+ .switch {
96
+ position: relative;
97
+ display: inline-block;
98
+ height: calc(var(--input-height) / 2);
99
+ width: var(--input-height);
100
+ border-radius: var(--input-height);
101
+ }
102
+
103
+ .switch input {
104
+ opacity: 0;
105
+ width: 0;
106
+ height: 0;
107
+ }
108
+
109
+ .slider {
110
+ position: absolute;
111
+ cursor: pointer;
112
+ top: 0;
113
+ left: 0;
114
+ right: 0;
115
+ bottom: 0;
116
+ background: var(--input-bg);
117
+ -webkit-transition: 0.4s;
118
+ transition: 0.4s;
119
+ border-radius: calc(var(--input-height) / 2);
120
+ box-shadow: inset 0 0 10px #00000020;
121
+ }
122
+
123
+ .slider:before {
124
+ position: absolute;
125
+ content: '';
126
+ height: calc(var(--input-height) / 2 - 4px);
127
+ width: calc(var(--input-height) / 2 - 4px);
128
+ left: 2px;
129
+ bottom: 2px;
130
+ border-radius: 50%;
131
+ background: var(--bgl-white);
132
+ -webkit-transition: 0.4s;
133
+ transition: 0.4s;
134
+ }
135
+
136
+ input:checked+.slider {
137
+ background: var(--bgl-blue);
138
+ }
139
+
140
+ input:checked+.slider:before {
141
+ transform: translateX(calc(var(--input-height) / 2));
142
+ }
143
+ </style>
@@ -0,0 +1,77 @@
1
+ <template>
2
+ <label class="primary-checkbox">
3
+ <input
4
+ type="checkbox"
5
+ v-model="val"
6
+ >
7
+ <span>
8
+ <MaterialIcon icon="check" />
9
+ </span>
10
+ </label>
11
+ </template>
12
+
13
+ <script setup lang="ts">
14
+ import { watch } from 'vue';
15
+ import { MaterialIcon } from '@/components';
16
+
17
+ const props = defineProps({
18
+ modelValue: Boolean,
19
+ });
20
+
21
+ const emits = defineEmits(['update:modelValue']);
22
+
23
+ let val = $ref<boolean>();
24
+
25
+ watch(
26
+ () => props.modelValue,
27
+ (v: boolean) => {
28
+ if (v === undefined || v === val) return;
29
+ val = v;
30
+ },
31
+ { immediate: true },
32
+ );
33
+
34
+ watch(
35
+ () => val,
36
+ (v) => emits('update:modelValue', v),
37
+ );
38
+ </script>
39
+
40
+ <style scoped>
41
+ .primary-checkbox input {
42
+ display: none;
43
+ }
44
+
45
+ .primary-checkbox {
46
+ margin-top: 8px;
47
+ }
48
+
49
+ .primary-checkbox span {
50
+ display: flex;
51
+ padding-top: 1px;
52
+ align-items: center;
53
+ justify-content: center;
54
+ color: var(--bgl-white);
55
+ border-radius: 100%;
56
+ width: 26px;
57
+ height: 26px;
58
+ background: white;
59
+ border: 4px solid var(--bgl-gray-light);
60
+ cursor: pointer;
61
+ transition: var(--bgl-transition);
62
+ user-select: none;
63
+ }
64
+
65
+ .primary-checkbox span:hover {
66
+ filter: brightness(90%);
67
+ }
68
+
69
+ .primary-checkbox span:active {
70
+ filter: brightness(80%);
71
+ }
72
+
73
+ .primary-checkbox input:checked+span {
74
+ background: var(--bgl-blue);
75
+ border: none;
76
+ }
77
+ </style>
@@ -0,0 +1,47 @@
1
+ <template>
2
+ <div
3
+ class="bagel-input"
4
+ :class="{ small }"
5
+ :title="field.description"
6
+ v-if="field.id"
7
+ >
8
+ <label :for="field.id">
9
+ {{ field.label }}
10
+ <input
11
+ :id="field.id"
12
+ v-model="inputVal"
13
+ type="color"
14
+ :placeholder="field.placeholder || field.label"
15
+ :class="{ 'no-edit': !editMode }"
16
+ :required="required"
17
+ v-bind="nativeInputAttrs"
18
+ >
19
+ </label>
20
+ </div>
21
+ </template>
22
+
23
+ <script setup lang="ts">
24
+ import { watch } from 'vue';
25
+ import { type BagelField } from '@/types';
26
+
27
+ const emits = defineEmits(['update:modelValue']);
28
+ const props = withDefaults(
29
+ defineProps<{
30
+ field: BagelField;
31
+ modelValue: any;
32
+ editMode?: boolean;
33
+ small?: boolean;
34
+ required?: boolean;
35
+ nativeInputAttrs?: Record<string, any>;
36
+ }>(),
37
+ {
38
+ editMode: true,
39
+ },
40
+ );
41
+ const inputVal = $ref<string>(props.modelValue);
42
+
43
+ watch(
44
+ () => inputVal,
45
+ (newVal) => emits('update:modelValue', newVal),
46
+ );
47
+ </script>
@@ -0,0 +1,137 @@
1
+ <template>
2
+ <div
3
+ class="bagel-input"
4
+ :title="field.description"
5
+ :class="{ small: small }"
6
+ >
7
+ <label v-if="field.label">
8
+ {{ field.label }}
9
+ </label>
10
+ <div class="flex gap-3">
11
+ <input
12
+ :value="modelValue"
13
+ type="number"
14
+ @input="handleInput"
15
+ :placeholder="placeholder"
16
+ :class="{ 'no-edit': !editMode }"
17
+ >
18
+ <p class="currency">
19
+ {{
20
+ currencies
21
+ .find((c) => c.symbol === field.currency)?.character || field.currency
22
+ }}
23
+ </p>
24
+ </div>
25
+ </div>
26
+ </template>
27
+
28
+ <script setup lang="ts">
29
+ import { BagelField } from '@/types';
30
+
31
+ const emits = defineEmits(['update:modelValue']);
32
+ withDefaults(
33
+ defineProps<{
34
+ field: BagelField;
35
+ modelValue: any;
36
+
37
+ placeholder?: string;
38
+ editMode?: boolean;
39
+ small?: boolean;
40
+ }>(),
41
+ {
42
+ editMode: true,
43
+ },
44
+ );
45
+ const handleInput = (e: Event) => {
46
+ const el = e.target as HTMLInputElement;
47
+ let value = parseFloat(el.value);
48
+ if (Number.isNaN(value)) {
49
+ value = 0;
50
+ }
51
+ emits('update:modelValue', value);
52
+ };
53
+
54
+ const currencies = [
55
+ { name: 'United Arab Emirates Dirham', symbol: 'AED', character: 'د.إ' },
56
+ { name: 'Afghan Afghani', symbol: 'AFN', character: '؋' },
57
+ { name: 'Albanian Lek', symbol: 'ALL', character: 'L' },
58
+ { name: 'Armenian Dram', symbol: 'AMD', character: '֏' },
59
+ { name: 'Netherlands Antillean Guilder', symbol: 'ANG', character: 'ƒ' },
60
+ { name: 'Angolan Kwanza', symbol: 'AOA', character: 'Kz' },
61
+ { name: 'Argentine Peso', symbol: 'ARS', character: '$' },
62
+ { name: 'Australian Dollar', symbol: 'AUD', character: '$' },
63
+ { name: 'Aruban Florin', symbol: 'AWG', character: 'ƒ' },
64
+ { name: 'Azerbaijani Manat', symbol: 'AZN', character: '₼' },
65
+ {
66
+ name: 'Bosnia-Herzegovina Convertible Mark',
67
+ symbol: 'BAM',
68
+ character: 'KM',
69
+ },
70
+ { name: 'Barbadian Dollar', symbol: 'BBD', character: '$' },
71
+ { name: 'Bangladeshi Taka', symbol: 'BDT', character: '৳' },
72
+ { name: 'Bulgarian Lev', symbol: 'BGN', character: 'лв' },
73
+ { name: 'Bahraini Dinar', symbol: 'BHD', character: 'ب.د' },
74
+ { name: 'Burundian Franc', symbol: 'BIF', character: 'FBu' },
75
+ { name: 'Bermudan Dollar', symbol: 'BMD', character: '$' },
76
+ { name: 'Brunei Dollar', symbol: 'BND', character: '$' },
77
+ { name: 'Bolivian Boliviano', symbol: 'BOB', character: 'Bs.' },
78
+ { name: 'Brazilian Real', symbol: 'BRL', character: 'R$' },
79
+ { name: 'Bahamian Dollar', symbol: 'BSD', character: '$' },
80
+ { name: 'Bitcoin', symbol: '₿', character: '₿' },
81
+ { name: 'Bhutanese Ngultrum', symbol: 'BTN', character: 'Nu.' },
82
+ { name: 'Botswanan Pula', symbol: 'BWP', character: 'P' },
83
+ { name: 'Belarusian Ruble', symbol: 'BYN', character: 'Br' },
84
+ { name: 'Belize Dollar', symbol: 'BZD', character: '$' },
85
+ { name: 'Canadian Dollar', symbol: 'CAD', character: '$' },
86
+ { name: 'Congolese Franc', symbol: 'CDF', character: 'FC' },
87
+ { name: 'Swiss Franc', symbol: 'CHF', character: 'Fr' },
88
+ { name: 'Chilean Peso', symbol: 'CLP', character: '$' },
89
+ { name: 'Chinese Yuan', symbol: 'CNY', character: '¥' },
90
+ { name: 'Colombian Peso', symbol: 'COP', character: '$' },
91
+ { name: 'Costa Rican Colón', symbol: 'CRC', character: '₡' },
92
+ { name: 'Cuban Convertible Peso', symbol: 'CUC', character: '$' },
93
+ { name: 'Cuban Peso', symbol: 'CUP', character: '$' },
94
+ { name: 'Cape Verdean Escudo', symbol: 'CVE', character: '$' },
95
+ { name: 'Czech Republic Koruna', symbol: 'CZK', character: 'Kč' },
96
+ { name: 'Djiboutian Franc', symbol: 'DJF', character: 'Fdj' },
97
+ { name: 'Danish Krone', symbol: 'DKK', character: 'kr' },
98
+ { name: 'Dominican Peso', symbol: 'DOP', character: '$' },
99
+ { name: 'Algerian Dinar', symbol: 'DZD', character: 'د.ج' },
100
+ { name: 'Egyptian Pound', symbol: 'EGP', character: '£' },
101
+ { name: 'Eritrean Nakfa', symbol: 'ERN', character: 'Nfk' },
102
+ { name: 'Ethiopian Birr', symbol: 'ETB', character: 'Br' },
103
+ { name: 'Euro', symbol: 'EUR', character: '€' },
104
+ { name: 'Fijian Dollar', symbol: 'FJD', character: '$' },
105
+ { name: 'Falkland Islands Pound', symbol: 'FKP', character: '£' },
106
+ { name: 'British Pound Sterling', symbol: 'GBP', character: '£' },
107
+ { name: 'Georgian Lari', symbol: 'GEL', character: 'ლ' },
108
+ { name: 'Guernsey Pound', symbol: 'GGP', character: '£' },
109
+ { name: 'Ghanaian Cedi', symbol: 'GHS', character: '₵' },
110
+ { name: 'Gibraltar Pound', symbol: 'GIP', character: '£' },
111
+ { name: 'Gambian Dalasi', symbol: 'GMD', character: 'D' },
112
+ { name: 'Guinean Franc', symbol: 'GNF', character: 'FG' },
113
+ { name: 'Guatemalan Quetzal', symbol: 'GTQ', character: 'Q' },
114
+ { name: 'Guyanaese Dollar', symbol: 'GYD', character: '$' },
115
+ { name: 'Hong Kong Dollar', symbol: 'HKD', character: '$' },
116
+ { name: 'Honduran Lempira', symbol: 'HNL', character: 'L' },
117
+ { name: 'Croatian Kuna', symbol: 'HRK', character: 'kn' },
118
+ { name: 'Haitian Gourde', symbol: 'HTG', character: 'G' },
119
+ { name: 'Hungarian Forint', symbol: 'HUF', character: 'Ft' },
120
+ { name: 'Indonesian Rupiah', symbol: 'IDR', character: 'Rp' },
121
+ { name: 'Israeli New Shekel', symbol: 'ILS', character: '₪' },
122
+ { name: 'Manx pound', symbol: 'IMP', character: '£' },
123
+ { name: 'Indian Rupee', symbol: 'INR', character: '₹' },
124
+ { name: 'Iraqi Dinar', symbol: 'IQD', character: 'ع.د' },
125
+ { name: 'Iranian Rial', symbol: 'IRR', character: '﷼' },
126
+ { name: 'Icelandic Króna', symbol: 'ISK', character: 'kr' },
127
+ { name: 'Jersey Pound', symbol: 'JEP', character: '£' },
128
+ ];
129
+ </script>
130
+
131
+ <style scoped>
132
+ .currency {
133
+ font-size: calc(var(--input-font-size) * 1.4);
134
+ margin-inline-start: -50px;
135
+ line-height: 0px;
136
+ }
137
+ </style>
@@ -0,0 +1,55 @@
1
+ <template>
2
+ <div
3
+ class="bagel-input"
4
+ :title="field.description"
5
+ :class="{ small: small }"
6
+ >
7
+ <label v-if="field.label">
8
+ {{ field.label }}
9
+ </label>
10
+ <input
11
+ type="date"
12
+ v-model="date"
13
+ @update:modelValue="handleInput"
14
+ :placeholder="field.placeholder || field.label"
15
+ class="date-picker"
16
+ :disabled="!editMode"
17
+ :enableTimePicker="false"
18
+ :textInputOptions="{ format: 'yyyy-MM-dd' }"
19
+ >
20
+ </div>
21
+ </template>
22
+
23
+ <script setup lang="ts">
24
+ import { ref } from 'vue';
25
+ import type { BagelField } from '@/types/BagelField';
26
+
27
+ const props = withDefaults(
28
+ defineProps<{
29
+ field: BagelField;
30
+ modelValue: any;
31
+ editMode?: boolean;
32
+ small?: boolean;
33
+ }>(),
34
+ {
35
+ editMode: true,
36
+ small: false,
37
+ },
38
+ );
39
+
40
+ const date = ref(props.modelValue);
41
+
42
+ const emit = defineEmits(['update:modelValue']);
43
+
44
+ const handleInput = () => {
45
+ emit('update:modelValue', date.value.toISOString().split('T').shift());
46
+ };
47
+ </script>
48
+
49
+ <style scoped>
50
+ /*
51
+ .date-picker {
52
+ padding-inline-start: 10px;
53
+ }
54
+ */
55
+ </style>
@@ -0,0 +1,50 @@
1
+ <template>
2
+ <div
3
+ class="bagel-input"
4
+ :title="description"
5
+ :class="{ small: small }"
6
+ >
7
+ <label v-if="label">
8
+ <LangText :input="label" />
9
+ </label>
10
+ <input
11
+ :value="modelValue?.split('.')[0] || ''"
12
+ type="datetime-local"
13
+ @input="handleInput"
14
+ :placeholder="bagelApp.translate(placeholder, true)"
15
+ :class="{ 'no-edit': !editMode }"
16
+ >
17
+ </div>
18
+ </template>
19
+
20
+ <script setup lang="ts">
21
+ import { onMounted } from 'vue';
22
+ // @ts-ignore TODO: remove this Nati
23
+ import { bagelApp } from '../../../index';
24
+
25
+ const emits = defineEmits(['update:modelValue']);
26
+ // @ts-ignore TODO: remove this Nati
27
+ const props = withDefaults(
28
+ defineProps<{
29
+ description?: string;
30
+ label?: string;
31
+ modelValue: any;
32
+ placeholder?: string;
33
+ editMode?: boolean;
34
+ small?: boolean;
35
+ }>(),
36
+ {
37
+ description: '',
38
+ editMode: true,
39
+ placeholder: '',
40
+ label: '',
41
+ },
42
+ );
43
+ const handleInput = (e: Event) => {
44
+ const el = e.target as HTMLInputElement;
45
+ emits('update:modelValue', el.value);
46
+ };
47
+ onMounted(() => { });
48
+ </script>
49
+
50
+ <style scoped></style>
@@ -0,0 +1,55 @@
1
+ <template>
2
+ <div
3
+ class="bagel-input"
4
+ :title="description"
5
+ :class="{ small: small }"
6
+ >
7
+ <label v-if="label">
8
+ <LangText :input="label" />
9
+ </label>
10
+ <input
11
+ :value="modelValue"
12
+ :title="formatDuration(modelValue)"
13
+ type="number"
14
+ @input="handleInput"
15
+ :placeholder="bagelApp.translate(placeholder, true)"
16
+ :class="{ 'no-edit': !editMode }"
17
+ >
18
+ </div>
19
+ </template>
20
+
21
+ <script setup lang="ts">
22
+ // @ts-ignore TODO: remove this Nati
23
+ import { bagelApp } from '../../../index';
24
+ // @ts-ignore TODO: remove this Nati
25
+ import { formatDuration } from '../../../composables';
26
+
27
+ const emits = defineEmits(['update:modelValue']);
28
+ // @ts-ignore TODO: remove this Nati
29
+ const props = withDefaults(
30
+ defineProps<{
31
+ description?: string;
32
+ label?: string;
33
+ modelValue: any;
34
+ placeholder?: string;
35
+ editMode?: boolean;
36
+ small?: boolean;
37
+ }>(),
38
+ {
39
+ description: '',
40
+ editMode: true,
41
+ placeholder: '',
42
+ label: '',
43
+ },
44
+ );
45
+ const handleInput = (e: Event) => {
46
+ const el = e.target as HTMLInputElement;
47
+ let value = parseInt(el.value);
48
+ if (isNaN(value)) {
49
+ value = 0;
50
+ }
51
+ emits('update:modelValue', value);
52
+ };
53
+ </script>
54
+
55
+ <style scoped></style>
@@ -0,0 +1,142 @@
1
+ <template>
2
+ <div
3
+ class="bagel-input"
4
+ :class="{ small: small }"
5
+ >
6
+ <label v-if="label">
7
+ <LangText :input="label" />
8
+ </label>
9
+
10
+ <input
11
+ @keydown.enter="handleEnter"
12
+ autocomplete="off"
13
+ @click="showList = true"
14
+ name="link-input"
15
+ v-model="selectedItem"
16
+ @focus="initList"
17
+ @input="handleInput"
18
+ :disabled="!editMode"
19
+ >
20
+
21
+ <div
22
+ class="custom-select"
23
+ name="link-input"
24
+ :class="{ 'open-select': showList && linkOptions.length > 0 }"
25
+ >
26
+ <div class="custom-select-drop">
27
+ <div
28
+ v-for="item in linkOptions"
29
+ :key="formatString(item.value, 'pascal')"
30
+ @click.stop="handleSelect(item)"
31
+ >
32
+ {{
33
+ useId || entity === 'Entity' ? item.value
34
+ : item.label || item.description || item.value
35
+ }}
36
+ </div>
37
+ </div>
38
+ </div>
39
+ </div>
40
+ </template>
41
+
42
+ <script lang="ts" setup>
43
+ import { onMounted, ref } from 'vue';
44
+ // @ts-ignore TODO: remove this Nati
45
+ import { formatString } from '../../../composables';
46
+ // @ts-ignore TODO: remove this Nati
47
+ import { bagelApp } from '../../../index';
48
+
49
+ const props = withDefaults(
50
+ defineProps<{
51
+ label?: string;
52
+ modelValue: any;
53
+ useId?: false;
54
+ bagelApp?: any;
55
+ entity: string;
56
+ editMode: boolean;
57
+ filters?: any;
58
+ small?: boolean;
59
+ }>(),
60
+ {
61
+ label: '',
62
+ useId: false,
63
+ filters: {},
64
+ bagelApp,
65
+ },
66
+ );
67
+ const showList = ref(false);
68
+ const linkOptions = ref<any>([]);
69
+ const item = ref<ListItem>();
70
+ const emits = defineEmits(['update:modelValue', 'selected']);
71
+ const selectedItem = ref<any>();
72
+
73
+ function handleSelect(item: ListItem) {
74
+ showList.value = false;
75
+ selectedItem.value = item;
76
+ if (props.useId) {
77
+ selectedItem.value = item.value;
78
+ } else {
79
+ selectedItem.value = item.label || item.description || item.value;
80
+ }
81
+
82
+ emits('update:modelValue', item.value);
83
+ emits('selected');
84
+ }
85
+
86
+ async function getLinkOptions(inputString: string) {
87
+ linkOptions.value = await props.bagelApp.entity.getLinkedFieldList({
88
+ entity: props.entity,
89
+ txt: inputString,
90
+ reference_entity: '',
91
+ filters: props.filters,
92
+ });
93
+ }
94
+
95
+ interface ListItem {
96
+ value: string;
97
+ label?: string;
98
+ description?: string;
99
+ }
100
+
101
+ // @ts-ignore TODO: remove this Nati
102
+ const initialized = ref(false);
103
+
104
+ async function initList(e: Event) {
105
+ await getLinkOptions(getElValue(e));
106
+ showList.value = true;
107
+ }
108
+
109
+ function getElValue(e: Event) {
110
+ const el = e.target as HTMLInputElement;
111
+ return el.value.trim();
112
+ }
113
+
114
+ function handleEnter(e: Event) {
115
+ emits('update:modelValue', getElValue(e));
116
+ emits('selected');
117
+ showList.value = false;
118
+ }
119
+
120
+ function handleClick(e: any) {
121
+ const { target } = e;
122
+ if (target.name != 'link-input' && showList.value == true) {
123
+ showList.value = false;
124
+ emits('update:modelValue', item.value);
125
+ emits('selected');
126
+ }
127
+ // showList.value = false
128
+ }
129
+
130
+ const handleInput = async (e: Event) => {
131
+ showList.value = true;
132
+ const el = e.target as HTMLInputElement;
133
+ emits('update:modelValue', el.value);
134
+ await getLinkOptions(el.value);
135
+ };
136
+ onMounted(() => {
137
+ selectedItem.value = props.modelValue;
138
+ document.addEventListener('click', handleClick);
139
+ });
140
+ </script>
141
+
142
+ <style scoped></style>