@fy-/fws-vue 0.2.8 → 0.3.0

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.
@@ -3,15 +3,6 @@ import { LinkIcon } from "@heroicons/vue/24/solid";
3
3
  import { computed, ref, toRef } from "vue";
4
4
  import type { ErrorObject } from "@vuelidate/core";
5
5
  import { useTranslation } from "../../composables/translations";
6
- import InputText from "primevue/inputtext";
7
- import Textarea from "primevue/textarea";
8
- import Calendar from "primevue/calendar";
9
- import Password from "primevue/password";
10
- import Checkbox from "primevue/checkbox";
11
- import Dropdown from "primevue/dropdown";
12
- import Chips from "primevue/chips";
13
- import InputSwitch from "primevue/inputswitch";
14
- import InputMask from "primevue/inputmask";
15
6
 
16
7
  type modelValueType = string | number | string[] | number[] | undefined;
17
8
 
@@ -62,20 +53,29 @@ const checkErrors = computed(() => {
62
53
  return null;
63
54
  });
64
55
 
65
- const formattedOptions = computed(() => {
66
- return props.options.map((option) => {
67
- return { value: option[0], label: option[1] };
68
- });
69
- });
70
-
71
56
  const focus = () => {
72
57
  if (inputRef.value) inputRef.value.focus();
73
58
  };
59
+ const blur = () => {
60
+ if (inputRef.value) inputRef.value.blur();
61
+ };
74
62
  const getInputRef = () => {
75
63
  if (inputRef.value) return inputRef.value;
76
64
  };
77
65
 
78
- const emit = defineEmits(["update:modelValue", "update:checkboxValue"]);
66
+ const handleFocus = () => {
67
+ emit("focus", props.id);
68
+ };
69
+
70
+ const handleBlur = () => {
71
+ emit("blur", props.id);
72
+ };
73
+ const emit = defineEmits([
74
+ "update:modelValue",
75
+ "update:checkboxValue",
76
+ "focus",
77
+ "blur",
78
+ ]);
79
79
  const model = computed({
80
80
  get: () => props.modelValue,
81
81
  set: (items) => {
@@ -88,7 +88,7 @@ const modelCheckbox = computed({
88
88
  emit("update:checkboxValue", items);
89
89
  },
90
90
  });
91
- defineExpose({ focus, getInputRef });
91
+ defineExpose({ focus, blur, getInputRef });
92
92
  </script>
93
93
  <template>
94
94
  <div>
@@ -112,148 +112,162 @@ defineExpose({ focus, getInputRef });
112
112
  "
113
113
  >
114
114
  <div class="flex flex-col gap-2">
115
- <label :for="id" v-if="label">{{ label }}</label>
116
- <!-- @vue-skip -->
117
- <InputText
118
- :id="id"
119
- v-model="model"
120
- :placeholder="placeholder"
121
- :invalid="checkErrors ? true : false"
122
- :pt:root:autocomplete="autocomplete"
123
- :pt:root:type="type"
124
- :aria-describedby="
125
- help && !['checkbox', 'radio'].includes(type)
126
- ? `${id}-help`
127
- : undefined
128
- "
115
+ <div
129
116
  v-if="
130
- (type == 'text' && !mask) ||
131
- type == 'email' ||
132
- type == 'search' ||
133
- type == 'url' ||
134
- type == 'phone'
135
- "
136
- />
137
- <!-- @vue-skip -->
138
- <InputMask
139
- :id="id"
140
- v-model="model"
141
- :placeholder="placeholder"
142
- :invalid="checkErrors ? true : false"
143
- :pt:root:autocomplete="autocomplete"
144
- :pt:root:type="type"
145
- :mask="mask"
146
- :aria-describedby="
147
- help && !['checkbox', 'radio'].includes(type)
148
- ? `${id}-help`
149
- : undefined
150
- "
151
- v-if="type == 'mask' || (type == 'text' && mask)"
152
- />
153
- <!-- @vue-skip -->
154
- <Textarea
155
- :id="id"
156
- v-model="model"
157
- :placeholder="placeholder"
158
- :invalid="checkErrors ? true : false"
159
- :aria-describedby="
160
- help && !['checkbox', 'radio'].includes(type)
161
- ? `${id}-help`
162
- : undefined
163
- "
164
- v-if="type == 'textarea'"
165
- />
166
- <!-- @vue-skip -->
167
- <Calendar
168
- :id="id"
169
- v-model="model"
170
- :placeholder="placeholder"
171
- :invalid="checkErrors ? true : false"
172
- showIcon
173
- iconDisplay="input"
174
- :aria-describedby="
175
- help && !['checkbox', 'radio'].includes(type)
176
- ? `${id}-help`
177
- : undefined
117
+ [
118
+ 'text',
119
+ 'phone',
120
+ 'password',
121
+ 'email',
122
+ 'search',
123
+ 'url',
124
+ 'mask',
125
+ ].includes(type)
178
126
  "
179
- v-if="type == 'date'"
180
- />
181
- <!-- @vue-skip -->
182
- <Calendar
183
- :id="id"
184
- v-model="model"
185
- :placeholder="placeholder"
186
- :invalid="checkErrors ? true : false"
187
- showTime
188
- hourFormat="24"
189
- showIcon
190
- :aria-describedby="
191
- help && !['checkbox', 'radio'].includes(type)
192
- ? `${id}-help`
193
- : undefined
194
- "
195
- v-if="type == 'datetime'"
196
- />
197
- <!-- @vue-skip -->
198
- <Password
199
- :id="id"
200
- v-model="model"
201
- :placeholder="placeholder"
202
- :invalid="checkErrors ? true : false"
203
- :aria-describedby="
204
- help && !['checkbox', 'radio'].includes(type)
205
- ? `${id}-help`
206
- : undefined
207
- "
208
- toggleMask
209
- v-if="type == 'password'"
210
- />
211
- <!-- @vue-skip -->
212
- <Dropdown
213
- :id="id"
214
- v-model="model"
215
- :options="formattedOptions"
216
- :placeholder="placeholder"
217
- optionLabel="label"
218
- optionValue="value"
219
- :invalid="checkErrors ? true : false"
220
- :aria-describedby="
221
- help && !['checkbox', 'radio'].includes(type)
222
- ? `${id}-help`
223
- : undefined
224
- "
225
- v-if="type == 'select'"
226
- />
227
- <!-- @vue-skip -->
228
- <Chips
229
- :id="id"
230
- v-model="model"
231
- :placeholder="placeholder"
232
- separator=","
233
- :invalid="checkErrors ? true : false"
234
- :aria-describedby="
235
- help && !['checkbox', 'radio'].includes(type)
236
- ? `${id}-help`
237
- : undefined
238
- "
239
- v-if="type == 'chips'"
240
- />
241
- <small
242
- :id="`${id}-help`"
243
- v-if="help && !['checkbox', 'radio'].includes(type)"
127
+ class="relative"
244
128
  >
245
- {{ help }}
246
- </small>
129
+ <input
130
+ ref="inputRef"
131
+ :type="type"
132
+ :id="id"
133
+ :name="id"
134
+ :class="{
135
+ error: checkErrors,
136
+ }"
137
+ :autocomplete="autocomplete"
138
+ :disabled="disabled"
139
+ :aria-describedby="help ? `${id}-help` : id"
140
+ class="block px-2.5 pb-2.5 pt-4 w-full text-sm text-fv-neutral-900 bg-transparent rounded-lg border-1 border-fv-neutral-300 appearance-none dark:text-white dark:border-fv-neutral-600 dark:focus:border-fv-primary-500 focus:outline-none focus:ring-0 focus:border-fv-primary-600 peer"
141
+ :required="req"
142
+ @focus="handleFocus"
143
+ @blur="handleBlur"
144
+ />
145
+ <label
146
+ :for="id"
147
+ v-if="label || placeholder"
148
+ class="absolute text-sm text-fv-neutral-500 dark:text-fv-neutral-400 duration-300 transform -translate-y-4 scale-75 top-2 z-10 origin-[0] bg-white dark:bg-fv-neutral-900 px-2 peer-focus:px-2 peer-focus:text-fv-primary-600 peer-focus:dark:text-fv-primary-500 peer-placeholder-shown:scale-100 peer-placeholder-shown:-translate-y-1/2 peer-placeholder-shown:top-1/2 peer-focus:top-2 peer-focus:scale-75 peer-focus:-translate-y-4 rtl:peer-focus:translate-x-1/4 rtl:peer-focus:left-auto start-1"
149
+ >{{ label ? label : placeholder }}
150
+ </label>
151
+ </div>
152
+ <div class="group relative" v-else-if="type == 'textarea'">
153
+ <label
154
+ :for="id"
155
+ class="block mb-2 text-sm font-medium text-fv-neutral-900 dark:text-white"
156
+ >Your message</label
157
+ >
158
+ <textarea
159
+ :id="id"
160
+ :name="id"
161
+ ref="inputRef"
162
+ :class="{
163
+ error: checkErrors,
164
+ }"
165
+ :placeholder="placeholder"
166
+ :disabled="disabled"
167
+ :aria-describedby="help ? `${id}-help` : id"
168
+ :required="req"
169
+ @focus="handleFocus"
170
+ @blur="handleBlur"
171
+ class="block p-2.5 w-full text-sm text-fv-neutral-900 bg-fv-neutral-50 rounded-lg border border-fv-neutral-300 focus:ring-fv-primary-500 focus:border-fv-primary-500 dark:bg-fv-neutral-700 dark:border-fv-neutral-600 dark:placeholder-fv-neutral-400 dark:text-white dark:focus:ring-fv-primary-500 dark:focus:border-fv-primary-500"
172
+ ></textarea>
173
+ </div>
174
+ <div
175
+ class="relative max-w-sm"
176
+ v-else-if="type == 'datetime' || type == 'date'"
177
+ >
178
+ <div
179
+ class="absolute inset-y-0 start-0 flex items-center ps-3.5 pointer-events-none"
180
+ >
181
+ <svg
182
+ class="w-4 h-4 text-fv-neutral-500 dark:text-fv-neutral-400"
183
+ aria-hidden="true"
184
+ xmlns="http://www.w3.org/2000/svg"
185
+ fill="currentColor"
186
+ viewBox="0 0 20 20"
187
+ >
188
+ <path
189
+ d="M20 4a2 2 0 0 0-2-2h-2V1a1 1 0 0 0-2 0v1h-3V1a1 1 0 0 0-2 0v1H6V1a1 1 0 0 0-2 0v1H2a2 2 0 0 0-2 2v2h20V4ZM0 18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8H0v10Zm5-8h10a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2Z"
190
+ />
191
+ </svg>
192
+ </div>
193
+ <label
194
+ :for="id"
195
+ v-if="label"
196
+ class="block mb-2 text-sm font-medium text-fv-neutral-900 dark:text-white"
197
+ >{{ label }}</label
198
+ >
199
+
200
+ <input
201
+ datepicker
202
+ ref="inputRef"
203
+ type="text"
204
+ :class="{
205
+ error: checkErrors,
206
+ }"
207
+ class="bg-fv-neutral-50 border border-fv-neutral-300 text-fv-neutral-900 text-sm rounded-lg focus:ring-fv-primary-500 focus:border-fv-primary-500 block w-full ps-10 p-2.5 dark:bg-fv-neutral-700 dark:border-fv-neutral-600 dark:placeholder-fv-neutral-400 dark:text-white dark:focus:ring-fv-primary-500 dark:focus:border-fv-primary-500"
208
+ :id="id"
209
+ :name="id"
210
+ :disabled="disabled"
211
+ :aria-describedby="help ? `${id}-help` : id"
212
+ :required="req"
213
+ @focus="handleFocus"
214
+ @blur="handleBlur"
215
+ :placeholder="placeholder"
216
+ />
217
+ </div>
218
+ <div class="relative" v-else-if="type == 'select'">
219
+ <label
220
+ :for="id"
221
+ v-if="label"
222
+ class="block mb-2 text-sm font-medium text-fv-neutral-900 dark:text-white"
223
+ >{{ label }}</label
224
+ >
225
+ <select
226
+ :id="id"
227
+ :name="id"
228
+ ref="inputRef"
229
+ :disabled="disabled"
230
+ :aria-describedby="help ? `${id}-help` : id"
231
+ :required="req"
232
+ @focus="handleFocus"
233
+ @blur="handleBlur"
234
+ :class="{
235
+ error: checkErrors,
236
+ }"
237
+ class="bg-fv-neutral-50 border border-fv-neutral-300 text-fv-neutral-900 text-sm rounded-lg focus:ring-fv-primary-500 focus:border-fv-primary-500 block w-full p-2.5 dark:bg-fv-neutral-700 dark:border-fv-neutral-600 dark:placeholder-fv-neutral-400 dark:text-white dark:focus:ring-fv-primary-500 dark:focus:border-fv-primary-500"
238
+ >
239
+ <option
240
+ v-for="opt in options"
241
+ :value="opt[0]"
242
+ :key="opt[0].toString()"
243
+ >
244
+ {{ opt[1] }}
245
+ </option>
246
+ </select>
247
+ </div>
247
248
  </div>
248
249
  </template>
249
250
  <template v-else-if="type === 'toggle'">
250
- <label class="inline-flex items-start cursor-pointer">
251
- <!-- @vue-skip -->
252
- <InputSwitch v-model="modelCheckbox" class="flex-0 flex-shrink-0" />
253
-
251
+ <label
252
+ class="inline-flex items-center mb-5 cursor-pointer"
253
+ :class="{
254
+ error: checkErrors,
255
+ }"
256
+ >
257
+ <input
258
+ type="checkbox"
259
+ v-model="modelCheckbox"
260
+ class="sr-only peer"
261
+ @focus="handleFocus"
262
+ @blur="handleBlur"
263
+ />
264
+ <div
265
+ class="relative w-11 h-6 bg-fv-neutral-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-fv-primary-300 dark:peer-focus:ring-fv-primary-800 rounded-full peer dark:bg-fv-neutral-700 peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-fv-neutral-300 after:border after:rounded-full after:w-5 after:h-5 after:transition-all dark:border-fv-neutral-600 peer-checked:bg-fv-primary-600"
266
+ ></div>
254
267
  <span
255
- class="ms-3 font-medium text-fv-neutral-900 dark:text-fv-neutral-300"
256
- >{{ label }}
268
+ class="ms-3 text-sm font-medium text-fv-neutral-900 dark:text-fv-neutral-300"
269
+ >
270
+ {{ label }}
257
271
  <template v-if="help">
258
272
  <p class="text-fv-neutral-600 dark:text-fv-neutral-400 !text-sm">
259
273
  {{ help }}
@@ -262,80 +276,57 @@ defineExpose({ focus, getInputRef });
262
276
  </span>
263
277
  </label>
264
278
  </template>
265
- <template v-else-if="type == 'checkbox'">
266
- <div class="flex items-center">
267
- <Checkbox
268
- v-model="modelCheckbox"
269
- :binary="true"
270
- :aria-describedby="label"
271
- />
272
-
273
- <label
274
- :for="id"
275
- v-if="label"
276
- :class="{
277
- error: checkErrors,
278
- }"
279
- >{{ label }}
280
- <a class="fws-link" :href="linkIcon" target="_blank" v-if="linkIcon">
281
- <LinkIcon class="w-4 h-4" />
282
- </a>
283
- </label>
279
+ <template v-else-if="type == 'checkbox' || type == 'radio'">
280
+ <div class="flex mb-4">
281
+ <div class="flex items-center h-5">
282
+ <input
283
+ :id="id"
284
+ :class="{
285
+ error: checkErrors,
286
+ }"
287
+ :aria-describedby="help ? `${id}-help` : id"
288
+ :type="type"
289
+ @focus="handleFocus"
290
+ @blur="handleBlur"
291
+ v-model="modelCheckbox"
292
+ class="w-4 h-4 text-fv-primary-600 bg-fv-neutral-100 border-fv-neutral-300 rounded focus:ring-fv-primary-500 dark:focus:ring-fv-primary-600 dark:ring-offset-fv-neutral-800 dark:focus:ring-offset-fv-neutral-800 focus:ring-2 dark:bg-fv-neutral-700 dark:border-fv-neutral-600"
293
+ />
294
+ </div>
295
+ <div class="ms-2 text-sm">
296
+ <label
297
+ :for="id"
298
+ class="font-medium text-gray-900 dark:text-gray-300"
299
+ >{{ label }}</label
300
+ >
301
+ <p
302
+ :id="`${id}-help`"
303
+ v-if="help"
304
+ class="text-xs font-normal text-gray-500 dark:text-gray-400"
305
+ >
306
+ {{ help }}
307
+ </p>
308
+ </div>
284
309
  </div>
285
310
  </template>
286
- <p v-if="checkErrors" class="mt-0.5 text-xs fws-error-text">
311
+ <p v-if="checkErrors" class="mt-0.5 text-sm text-red-600 dark:text-red-300">
287
312
  {{ checkErrors }}
288
313
  </p>
289
314
 
290
315
  <p
291
- class="fws-input-helper"
292
- v-if="help && !['checkbox', 'radio'].includes(type)"
316
+ :id="`${id}-help`"
317
+ class="mt-1 text-sm text-fv-neutral-500 dark:text-fv-neutral-400"
318
+ v-if="help && !['checkbox', 'radio', 'toggle'].includes(type)"
293
319
  >
294
320
  {{ help }}
295
321
  </p>
296
322
  </div>
297
323
  </template>
298
324
  <style scoped>
299
- .fws-label {
300
- @apply block mb-2 text-sm font-medium text-fv-neutral-900 dark:text-white;
301
-
302
- &.error {
303
- @apply text-red-700 dark:text-red-500;
304
- }
305
- }
306
- .fws-input-helper {
307
- @apply mt-2 text-sm text-fv-neutral-500 dark:text-fv-neutral-400;
308
- }
309
- .fws-input {
310
- @apply shadow-sm bg-fv-neutral-50 border border-fv-neutral-300 text-fv-neutral-900 text-sm rounded-sm focus:ring-fv-primary-500 focus:border-fv-primary-500 block w-full p-2.5 dark:bg-fv-neutral-700 dark:border-fv-neutral-600 dark:placeholder-fv-neutral-400 dark:text-white dark:focus:ring-fv-primary-500 dark:focus:border-fv-primary-500;
311
- &.error {
312
- @apply bg-red-50 border border-red-500 text-red-900 placeholder-red-700 text-sm rounded-sm focus:ring-red-500 focus:border-red-500 block w-full p-2.5 dark:bg-red-100 dark:border-red-400;
313
- }
314
- }
315
- .fws-textarea {
316
- @apply block p-2.5 w-full text-sm text-fv-neutral-900 bg-fv-neutral-50 rounded-sm border border-fv-neutral-300 focus:ring-fv-primary-500 focus:border-fv-primary-500 dark:bg-fv-neutral-700 dark:border-fv-neutral-600 dark:placeholder-fv-neutral-400 dark:text-white dark:focus:ring-fv-primary-500 dark:focus:border-fv-primary-500;
317
- &.error {
318
- @apply bg-red-50 border border-red-500 text-red-900 placeholder-red-700 text-sm rounded-sm focus:ring-red-500 focus:border-red-500 block w-full p-2.5 dark:bg-red-100 dark:border-red-400;
319
- }
320
- }
321
-
322
- .fws-select {
323
- @apply bg-fv-neutral-50 border border-fv-neutral-300 text-fv-neutral-900 text-sm rounded-sm focus:ring-fv-primary-500 focus:border-fv-primary-500 block w-full p-2.5 dark:bg-fv-neutral-700 dark:border-fv-neutral-600 dark:placeholder-fv-neutral-400 dark:text-white dark:focus:ring-fv-primary-500 dark:focus:border-fv-primary-500;
325
+ input,
326
+ textarea,
327
+ select {
324
328
  &.error {
325
- @apply bg-red-50 border border-red-500 text-red-900 placeholder-red-700 text-sm rounded-sm focus:ring-red-500 focus:border-red-500 block w-full p-2.5 dark:bg-red-100 dark:border-red-400;
329
+ @apply border-red-500 dark:border-red-400;
326
330
  }
327
331
  }
328
- .fws-checkbox {
329
- @apply flex items-center mb-4;
330
- }
331
-
332
- .fws-checkbox input {
333
- @apply w-4 h-4 text-fv-primary-600 bg-fv-neutral-100 border-fv-neutral-300 rounded focus:ring-fv-primary-500 dark:focus:ring-fv-primary-600 dark:ring-offset-fv-neutral-800 dark:focus:ring-offset-fv-neutral-800 focus:ring-2 dark:bg-fv-neutral-700 dark:border-fv-neutral-600;
334
- &.error {
335
- @apply bg-red-50 border border-red-500 text-red-900 placeholder-red-700 text-sm rounded-sm focus:ring-red-500 focus:border-red-500 block w-full p-2.5 dark:bg-red-100 dark:border-red-400;
336
- }
337
- }
338
- .fws-checkbox label {
339
- @apply ml-2 text-sm font-medium text-fv-neutral-900 dark:text-fv-neutral-300;
340
- }
341
332
  </style>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fy-/fws-vue",
3
- "version": "0.2.8",
3
+ "version": "0.3.0",
4
4
  "author": "Florian 'Fy' Gasquez <m@fy.to>",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -24,6 +24,16 @@
24
24
  "./style.css": {
25
25
  "import": "./style.css",
26
26
  "require": "./style.css"
27
+ },
28
+ "./presets/Lara": {
29
+ "import": "./presets/Lara/index.js",
30
+ "require": "./presets/Lara/index.js",
31
+ "types": "./presets/Lara/index.js"
32
+ },
33
+ "./presets/Wind": {
34
+ "import": "./presets/Wind/index.js",
35
+ "require": "./presets/Wind/index.js",
36
+ "types": "./presets/Wind/index.js"
27
37
  }
28
38
  },
29
39
  "peerDependencies": {
@@ -38,6 +48,6 @@
38
48
  "timeago.js": "^4.0.x",
39
49
  "vue": "^3.3.x",
40
50
  "vue-router": "^4.1.x",
41
- "primevue": "^3.5.x"
51
+ "flowbite": "^2.3.x"
42
52
  }
43
53
  }