@fy-/fws-vue 0.0.912 → 0.0.913

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.
@@ -1,13 +1,12 @@
1
1
  <script setup lang="ts">
2
2
  import useVuelidate from "@vuelidate/core";
3
3
  import { reactive } from "vue";
4
- import { onMounted } from "vue";
5
- import { onUnmounted } from "vue";
4
+ import DefaultInput from "../ui/DefaultInput.vue";
6
5
  import { useTranslation } from "../../composables/translations";
7
6
  import { useEventBus } from "../../composables/event-bus";
7
+ import { onMounted } from "vue";
8
8
  import DefaultDateSelection from "../ui/DefaultDateSelection.vue";
9
- import DefaultInput from "../ui/DefaultInput.vue";
10
-
9
+ import { onUnmounted, ref } from "vue";
11
10
  interface FilterData {
12
11
  label: string;
13
12
  req: boolean;
@@ -18,14 +17,18 @@ interface FilterData {
18
17
  isHidden?: boolean;
19
18
  default?: any | undefined;
20
19
  formats?: Record<string, (value: any) => any>;
20
+ autocomplete?: (value: string) => Promise<any[]>;
21
21
  formatRestValue?: (value: any) => any;
22
22
  onChangeValue?: (form: any, value: any) => void;
23
+ focused: boolean;
23
24
  }
24
25
  const emit = defineEmits(["update:modelValue"]);
26
+ const hidden = ref<boolean>(false);
25
27
  const state = reactive<any>({ formData: {} });
26
28
  const rules: any = { formData: {} };
27
29
  const types = reactive<any>({});
28
30
  const translate = useTranslation();
31
+ const fDynamicOptions = ref<any[]>([]);
29
32
  const props = withDefaults(
30
33
  defineProps<{
31
34
  data?: Array<Array<FilterData>>;
@@ -110,8 +113,18 @@ const updateForms = () => {
110
113
  updateForms();
111
114
  const v$ = useVuelidate(rules, state);
112
115
 
116
+ const updateFormData = (data: any) => {
117
+ data.forEach((d: any) => {
118
+ if (d.uid) {
119
+ state.formData[d.uid] = d.value;
120
+ }
121
+ });
122
+ submitForm();
123
+ };
113
124
  const submitForm = () => {
114
- emit("update:modelValue", formatValues({ ...state.formData }));
125
+ const formData = formatValues({ ...state.formData });
126
+ emit("update:modelValue", formData);
127
+ eventBus.emit("forceUpdateFilters", true);
115
128
  };
116
129
  const resetForm = () => {
117
130
  updateForms();
@@ -119,26 +132,44 @@ const resetForm = () => {
119
132
  const eventBus = useEventBus();
120
133
  onMounted(() => {
121
134
  eventBus.on("resetFilters", resetForm);
135
+ eventBus.on("updateFilters", updateFormData);
122
136
  });
123
137
  onUnmounted(() => {
124
138
  eventBus.off("resetFilters", resetForm);
139
+ eventBus.off("updateFilters", updateFormData);
125
140
  });
126
141
  </script>
127
142
  <template>
128
- <form @submit.prevent="() => submitForm()">
143
+ <form @submit.prevent="() => submitForm()" v-if="!hidden">
129
144
  <div :class="css">
130
- <div v-for="(g, i) in data" :key="`index_${i}`">
145
+ <div v-for="(g, i) in data" :key="`index_${i}`" class="relative">
131
146
  <template v-for="f in g" :key="f.uid">
132
147
  <template v-if="!f.isHidden">
133
148
  <DefaultInput
134
- :type="f.type"
149
+ :type="f.type == 'autocomplete' ? 'text' : f.type"
135
150
  :label="f.label"
136
151
  :id="f.uid"
137
- v-if="['text', 'select', 'date', 'email'].includes(f.type)"
152
+ v-if="
153
+ ['text', 'select', 'date', 'email', 'autocomplete'].includes(
154
+ f.type,
155
+ )
156
+ "
138
157
  :options="f.options ? f.options : [[]]"
139
158
  v-model="state.formData[f.uid]"
140
159
  :errorVuelidate="v$.formData[f.uid].$errors"
141
160
  class="mb-2"
161
+ @focus="
162
+ () => {
163
+ f.focused = true;
164
+ $eventBus.emit('focusInput', true);
165
+ }
166
+ "
167
+ @blur="
168
+ () => {
169
+ f.focused = false;
170
+ $eventBus.emit('focusInput', false);
171
+ }
172
+ "
142
173
  @change="
143
174
  (ev: any) => {
144
175
  if (f.onChangeValue) {
@@ -146,7 +177,38 @@ onUnmounted(() => {
146
177
  }
147
178
  }
148
179
  "
149
- />
180
+ @update:modelValue="
181
+ (v) => {
182
+ if (f.autocomplete && v.length >= 2) {
183
+ fDynamicOptions = [];
184
+ f.autocomplete(v).then((r) => {
185
+ fDynamicOptions = r;
186
+ });
187
+ }
188
+ }
189
+ "
190
+ >
191
+ <div
192
+ v-if="f.type == 'autocomplete' && f.focused"
193
+ class="absolute flex flex-col gap-2 p-2 bottom-0 translate-y-full inset-x-0 bg-fv-neutral-200 dark:bg-fv-neutral-800 border border-fv-neutral-700 z-10"
194
+ >
195
+ <button
196
+ v-for="o in fDynamicOptions"
197
+ :key="o[0]"
198
+ class="flex items-center justify-between btn defaults neutral"
199
+ type="button"
200
+ @click.prevent="
201
+ () => {
202
+ f.focused = false;
203
+ state.formData[f.uid] = o[0];
204
+ }
205
+ "
206
+ >
207
+ {{ o[1] }} <small v-if="o[0] != ''">({{ o[0] }})</small>
208
+ </button>
209
+ </div></DefaultInput
210
+ >
211
+
150
212
  <DefaultDateSelection
151
213
  :id="f.uid"
152
214
  :label="f.label"
@@ -164,6 +226,9 @@ onUnmounted(() => {
164
226
  <button type="submit" class="btn defaults primary">
165
227
  {{ $t("filters_search_cta") }}
166
228
  </button>
229
+ <button type="button" class="btn defaults primary" @click="hidden = true">
230
+ {{ $t("hide_filters_cta") }}
231
+ </button>
167
232
  <button
168
233
  type="reset"
169
234
  class="btn defaults neutral"
@@ -177,4 +242,13 @@ onUnmounted(() => {
177
242
  </button>
178
243
  </div>
179
244
  </form>
245
+ <div class="flex justify-between mt-2 gap-x-2" v-else>
246
+ <button
247
+ type="button"
248
+ class="btn defaults primary !w-full flex-1 !text-center !items-center"
249
+ @click="hidden = false"
250
+ >
251
+ {{ $t("show_filters_cta") }}
252
+ </button>
253
+ </div>
180
254
  </template>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fy-/fws-vue",
3
- "version": "0.0.912",
3
+ "version": "0.0.913",
4
4
  "author": "Florian 'Fy' Gasquez <m@fy.to>",
5
5
  "license": "MIT",
6
6
  "repository": {