@effect-app/vue-components 0.0.9 → 0.1.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.
Files changed (42) hide show
  1. package/dist/types/components/OmegaForm/InputProps.d.ts +64 -0
  2. package/dist/types/components/OmegaForm/OmegaErrors.vue.d.ts +28 -1
  3. package/dist/types/components/OmegaForm/OmegaFormStuff.d.ts +1 -1
  4. package/dist/types/components/OmegaForm/OmegaInput.vue.d.ts +16 -6
  5. package/dist/types/components/OmegaForm/OmegaInputVuetify.vue.d.ts +16 -0
  6. package/dist/types/components/OmegaForm/OmegaInternalInput.vue.d.ts +24 -3
  7. package/dist/types/components/OmegaForm/index.d.ts +1 -1
  8. package/dist/types/index.d.ts +4 -4
  9. package/dist/types/utils/index.d.ts +1 -1
  10. package/dist/vue-components.es.js +31 -618
  11. package/dist/vue-components.es10.js +25 -0
  12. package/dist/vue-components.es11.js +64 -0
  13. package/dist/vue-components.es12.js +9 -0
  14. package/dist/vue-components.es13.js +4 -0
  15. package/dist/vue-components.es14.js +90 -0
  16. package/dist/vue-components.es15.js +86 -0
  17. package/dist/vue-components.es16.js +13 -0
  18. package/dist/vue-components.es17.js +4 -0
  19. package/dist/vue-components.es18.js +134 -0
  20. package/dist/vue-components.es2.js +22 -0
  21. package/dist/vue-components.es20.js +6 -0
  22. package/dist/vue-components.es3.js +11 -0
  23. package/dist/vue-components.es4.js +30 -0
  24. package/dist/vue-components.es5.js +25 -0
  25. package/dist/vue-components.es6.js +218 -0
  26. package/dist/vue-components.es7.js +7 -0
  27. package/dist/vue-components.es8.js +48 -0
  28. package/dist/vue-components.es9.js +7 -0
  29. package/package.json +11 -2
  30. package/src/components/OmegaForm/InputProps.ts +81 -0
  31. package/src/components/OmegaForm/OmegaErrors.vue +69 -30
  32. package/src/components/OmegaForm/OmegaFormStuff.ts +2 -0
  33. package/src/components/OmegaForm/OmegaInput.vue +25 -38
  34. package/src/components/OmegaForm/OmegaInputVuetify.vue +164 -0
  35. package/src/components/OmegaForm/OmegaInternalInput.vue +43 -88
  36. package/src/components/OmegaForm/useOmegaForm.ts +3 -1
  37. package/src/components/style.css +1 -1
  38. package/src/constants/index.ts +1 -1
  39. package/src/env.d.ts +2 -2
  40. package/src/index.ts +12 -8
  41. package/src/utils/index.ts +9 -5
  42. package/dist/vue-components.css +0 -1
@@ -0,0 +1,164 @@
1
+ <template>
2
+ <div class="omega-input">
3
+ <v-text-field
4
+ v-if="inputProps.type === 'email' || inputProps.type === 'string'"
5
+ :id="inputProps.id"
6
+ :required="inputProps.required"
7
+ :min-length="inputProps.minLength"
8
+ :max-length="inputProps.maxLength"
9
+ :type="inputProps.type"
10
+ :name="inputProps.name"
11
+ :label="inputProps.label"
12
+ :model-value="inputProps.modelValue"
13
+ :error-messages="inputProps.errorMessages"
14
+ :error="inputProps.error"
15
+ v-bind="$attrs"
16
+ @update:model-value="inputProps.field.handleChange"
17
+ @blur="inputProps.setRealDirty"
18
+ />
19
+ <v-textarea
20
+ v-if="inputProps.type === 'text'"
21
+ v-bind="$attrs"
22
+ :id="inputProps.id"
23
+ :required="inputProps.required"
24
+ :min-length="inputProps.minLength"
25
+ :max-length="inputProps.maxLength"
26
+ :type="inputProps.type"
27
+ :name="inputProps.name"
28
+ :label="inputProps.label"
29
+ :model-value="inputProps.modelValue"
30
+ :error-messages="inputProps.errorMessages"
31
+ :error="inputProps.error"
32
+ @update:model-value="inputProps.field.handleChange"
33
+ @blur="inputProps.setRealDirty"
34
+ />
35
+ <v-text-field
36
+ v-if="inputProps.type === 'number'"
37
+ :id="inputProps.id"
38
+ :required="inputProps.required"
39
+ :min="inputProps.min"
40
+ :max="inputProps.max"
41
+ :type="inputProps.type"
42
+ :name="inputProps.name"
43
+ :label="inputProps.label"
44
+ :model-value="inputProps.modelValue"
45
+ :error-messages="inputProps.errorMessages"
46
+ :error="inputProps.error"
47
+ v-bind="$attrs"
48
+ @update:model-value="
49
+ (e: any) => {
50
+ inputProps.field.handleChange(Number(e))
51
+ }
52
+ "
53
+ @blur="inputProps.setRealDirty"
54
+ />
55
+ <div
56
+ v-if="inputProps.type === 'select' || inputProps.type === 'multiple'"
57
+ :class="inputProps.type !== 'multiple' && 'd-flex align-center'"
58
+ >
59
+ <v-select
60
+ :id="inputProps.id"
61
+ :required="inputProps.required"
62
+ :multiple="inputProps.type === 'multiple'"
63
+ :chips="inputProps.type === 'multiple'"
64
+ :name="inputProps.name"
65
+ :model-value="inputProps.modelValue"
66
+ :label="inputProps.label"
67
+ :items="inputProps.options"
68
+ :error-messages="inputProps.errorMessages"
69
+ :error="inputProps.error"
70
+ v-bind="$attrs"
71
+ @update:model-value="inputProps.field.handleChange"
72
+ @blur="inputProps.setRealDirty"
73
+ />
74
+ <v-btn
75
+ v-if="inputProps.type === 'select'"
76
+ variant-btn="secondary"
77
+ :variant-icon="mdiRefresh"
78
+ class="mr-2"
79
+ title="Reset"
80
+ @click="inputProps.field.handleChange(undefined)"
81
+ >
82
+ <v-icon :icon="mdiRefresh" />
83
+ </v-btn>
84
+ </div>
85
+
86
+ <div
87
+ v-if="
88
+ inputProps.type === 'autocomplete' ||
89
+ inputProps.type === 'autocompletemultiple'
90
+ "
91
+ :class="
92
+ inputProps.type !== 'autocompletemultiple' && 'd-flex align-center'
93
+ "
94
+ >
95
+ <v-autocomplete
96
+ :id="inputProps.id"
97
+ :multiple="inputProps.type === 'autocompletemultiple'"
98
+ :required="inputProps.required"
99
+ :name="inputProps.name"
100
+ :model-value="inputProps.modelValue"
101
+ :label="inputProps.label"
102
+ :items="inputProps.options"
103
+ :error-messages="inputProps.errorMessages"
104
+ :error="inputProps.error"
105
+ :chips="inputProps.type === 'autocompletemultiple'"
106
+ v-bind="$attrs"
107
+ @update:model-value="inputProps.field.handleChange"
108
+ @blur="inputProps.setRealDirty"
109
+ />
110
+ <v-btn
111
+ v-if="inputProps.type === 'autocomplete'"
112
+ variant-btn="secondary"
113
+ :variant-icon="mdiRefresh"
114
+ class="mr-2"
115
+ title="Reset"
116
+ @click="inputProps.field.handleChange(undefined)"
117
+ >
118
+ <v-icon :icon="mdiRefresh" />
119
+ </v-btn>
120
+ </div>
121
+ </div>
122
+ </template>
123
+
124
+ <script setup lang="ts" generic="T">
125
+ import { mdiRefresh } from "@mdi/js"
126
+ import type { InputProps } from "./InputProps"
127
+
128
+ defineProps<{
129
+ inputProps: InputProps<T>
130
+ }>()
131
+ </script>
132
+
133
+ <style>
134
+ .omega-input {
135
+ .v-input__details:has(.v-messages:empty) {
136
+ grid-template-rows: 0fr;
137
+ transition: all 0.2s;
138
+ }
139
+
140
+ & .v-messages:empty {
141
+ min-height: 0;
142
+ }
143
+
144
+ & .v-input__details:has(.v-messages) {
145
+ transition: all 0.2s;
146
+ overflow: hidden;
147
+ min-height: 0;
148
+ display: grid;
149
+ grid-template-rows: 1fr;
150
+ }
151
+
152
+ & .v-messages {
153
+ transition: all 0.2s;
154
+ > * {
155
+ transition-duration: 0s !important;
156
+ }
157
+ }
158
+
159
+ v-btn {
160
+ all: unset;
161
+ cursor: pointer;
162
+ }
163
+ }
164
+ </style>
@@ -1,40 +1,22 @@
1
1
  <template>
2
- <div class="omega-input">
3
- <v-text-field v-bind="$attrs" v-if="fieldType === 'email' || fieldType === 'string'" :id="id"
4
- :required="meta?.required" :min-length="meta?.type === 'string' && meta?.minLength"
5
- :max-length="meta?.type === 'string' && meta?.maxLength" :type="fieldType" :name="field.name"
6
- :label="`${label}${meta?.required ? ' *' : ''}`" :model-value="field.state.value" :error-messages="showedErrors"
7
- :error="!!showedErrors.length" @update:model-value="field.handleChange" @blur="setRealDirty" />
8
- <v-textarea v-bind="$attrs" v-if="fieldType === 'text'" :id="id" :required="meta?.required"
9
- :min-length="meta?.type === 'string' && meta?.minLength" :max-length="meta?.type === 'string' && meta?.maxLength"
10
- :type="fieldType" :name="field.name" :label="`${label}${meta?.required ? ' *' : ''}`"
11
- :model-value="field.state.value" :error-messages="showedErrors" :error="!!showedErrors.length"
12
- @update:model-value="field.handleChange" @blur="setRealDirty" />
13
- <v-text-field v-bind="$attrs" v-if="fieldType === 'number'" :id="id" :required="meta?.required"
14
- :min="meta?.type === 'number' && meta.minimum" :max="meta?.type === 'number' && meta.maximum" :type="fieldType"
15
- :name="field.name" :label="`${label}${meta?.required ? ' *' : ''}`" :model-value="field.state.value"
16
- :error-messages="showedErrors" :error="!!showedErrors.length" @update:model-value="
17
- (e: any) => {
18
- field.handleChange(Number(e))
19
- }
20
- " @blur="setRealDirty" />
21
- <div v-if="fieldType === 'select' || fieldType === 'multiple'"
22
- :class="fieldType !== 'multiple' && 'd-flex align-center'">
23
- <v-select v-bind="$attrs" :id="id" :required="meta?.required" :multiple="fieldType === 'multiple'"
24
- :chips="fieldType === 'multiple'" :name="field.name" :model-value="field.state.value"
25
- :label="`${label}${meta?.required ? ' *' : ''}`" :items="options" :error-messages="showedErrors"
26
- :error="!!showedErrors.length" @update:model-value="field.handleChange" @blur="setRealDirty" />
27
- <v-btn v-if="fieldType !== 'multiple'" variant-btn="secondary" :variant-icon="mdiRefresh" class="mr-2"
28
- title="Reset" @click="field.handleChange(undefined)"></v-btn>
29
- </div>
30
- </div>
2
+ <slot v-bind="inputProps">
3
+ <OmegaInputVuetify v-if="vuetified" :input-props="inputProps" />
4
+ </slot>
31
5
  </template>
32
6
 
33
7
  <script setup lang="ts" generic="To">
34
- /* eslint-disable @typescript-eslint/no-explicit-any */
35
- import { VTextField, VSelect } from "vuetify/components"
36
- import { mdiRefresh } from "@mdi/js"
37
- import { useStore, type FieldApi } from "@tanstack/vue-form"
8
+ import { useStore } from "@tanstack/vue-form"
9
+ import {
10
+ useAttrs,
11
+ useId,
12
+ computed,
13
+ watch,
14
+ onMounted,
15
+ ref,
16
+ watchEffect,
17
+ type ComputedRef,
18
+ getCurrentInstance,
19
+ } from "vue"
38
20
  import type {
39
21
  FieldValidators,
40
22
  MetaRecord,
@@ -42,30 +24,11 @@ import type {
42
24
  TypeOverride,
43
25
  } from "./OmegaFormStuff"
44
26
  import { useOmegaErrors } from "./OmegaErrorsContext"
45
- import { useId, computed, watch, onMounted, ref, watchEffect } from "vue"
27
+ import type { OmegaFieldInternalApi, InputProps } from "./InputProps"
28
+ import OmegaInputVuetify from "./OmegaInputVuetify.vue"
46
29
 
47
30
  const props = defineProps<{
48
- field: FieldApi<
49
- any,
50
- any,
51
- any,
52
- any,
53
- any,
54
- any,
55
- any,
56
- any,
57
- any,
58
- any,
59
- any,
60
- any,
61
- any,
62
- any,
63
- any,
64
- any,
65
- any,
66
- any,
67
- any
68
- >
31
+ field: OmegaFieldInternalApi<To>
69
32
  meta: MetaRecord<To>[NestedKeyOf<To>]
70
33
  label: string
71
34
  options?: { title: string; value: string }[]
@@ -73,9 +36,8 @@ const props = defineProps<{
73
36
  validators?: FieldValidators<To>
74
37
  }>()
75
38
 
76
- defineOptions({
77
- inheritAttrs: false
78
- })
39
+ const instance = getCurrentInstance()
40
+ const vuetified = instance?.appContext.components["VTextField"]
79
41
 
80
42
  const id = useId()
81
43
 
@@ -94,7 +56,8 @@ const fieldType = computed(() => {
94
56
 
95
57
  const fieldValue = computed(() => fieldState.value.value)
96
58
  const errors = computed(() =>
97
- fieldState.value.meta.errors.map((e: any) => e.message).filter(Boolean),
59
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
60
+ fieldState.value.meta.errors.map((e: any) => e?.message).filter(Boolean),
98
61
  )
99
62
 
100
63
  // we remove value and errors when the field is empty and not required
@@ -146,6 +109,7 @@ watch(
146
109
  addError({
147
110
  inputId: id,
148
111
  errors: fieldState.value.meta.errors
112
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
149
113
  .map((e: any) => e.message)
150
114
  .filter(Boolean),
151
115
  label: props.label,
@@ -155,33 +119,24 @@ watch(
155
119
  }
156
120
  },
157
121
  )
158
- </script>
159
-
160
- <style>
161
- .omega-input {
162
- .v-input__details:has(.v-messages:empty) {
163
- grid-template-rows: 0fr;
164
- transition: all 0.2s;
165
- }
166
122
 
167
- & .v-messages:empty {
168
- min-height: 0;
169
- }
170
-
171
- & .v-input__details:has(.v-messages) {
172
- transition: all 0.2s;
173
- overflow: hidden;
174
- min-height: 0;
175
- display: grid;
176
- grid-template-rows: 1fr;
177
- }
178
-
179
- & .v-messages {
180
- transition: all 0.2s;
181
-
182
- >* {
183
- transition-duration: 0s !important;
184
- }
185
- }
186
- }
187
- </style>
123
+ const otherAttrs = useAttrs()
124
+
125
+ const inputProps: ComputedRef<InputProps<To>> = computed(() => ({
126
+ id,
127
+ required: props.meta?.required,
128
+ minLength: props.meta?.type === "string" && props.meta?.minLength,
129
+ maxLength: props.meta?.type === "string" && props.meta?.maxLength,
130
+ max: props.meta?.type === "number" && props.meta?.maximum,
131
+ min: props.meta?.type === "number" && props.meta?.minimum,
132
+ name: props.field.name,
133
+ modelValue: props.field.state.value,
134
+ errorMessages: showedErrors.value,
135
+ error: !!showedErrors.value.length,
136
+ field: props.field,
137
+ setRealDirty,
138
+ type: fieldType.value,
139
+ label: `${props.label}${props.meta?.required ? " *" : ""}`,
140
+ options: props.options,
141
+ }))
142
+ </script>
@@ -12,9 +12,11 @@ import {
12
12
  type MetaRecord,
13
13
  type OmegaFormApi,
14
14
  } from "./OmegaFormStuff"
15
- /* eslint-disable @typescript-eslint/no-explicit-any */
15
+
16
16
  export const useOmegaForm = <
17
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
18
  From extends Record<PropertyKey, any>,
19
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
18
20
  To extends Record<PropertyKey, any>,
19
21
  >(
20
22
  schema: S.Schema<From, To, never>,
@@ -1,3 +1,3 @@
1
1
  .cool {
2
2
  color: pink;
3
- }
3
+ }
@@ -1 +1 @@
1
- export {}
1
+ export {}
package/src/env.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /// <reference types="vite/client" />
2
2
 
3
- declare module '*.vue' {
4
- import { DefineComponent } from 'vue'
3
+ declare module "*.vue" {
4
+ import { DefineComponent } from "vue"
5
5
  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
6
6
  const component: DefineComponent<{}, {}, any>
7
7
  export default component
package/src/index.ts CHANGED
@@ -1,10 +1,14 @@
1
- import { App } from 'vue'
2
- import * as components from './components'
1
+ import { type App } from "vue"
2
+ import * as components from "./components"
3
3
 
4
- function install (app: App) {
4
+ function install(app: App) {
5
5
  for (const key in components) {
6
- // @ts-expect-error
7
- app.component(key, components[key])
6
+ if (Object.prototype.hasOwnProperty.call(components, key)) {
7
+ const component = components[key as keyof typeof components]
8
+ if (component && typeof component === "object") {
9
+ app.component(key, component)
10
+ }
11
+ }
8
12
  }
9
13
  }
10
14
 
@@ -12,6 +16,6 @@ function install (app: App) {
12
16
 
13
17
  export default { install }
14
18
 
15
- export * from './components'
16
- export * from './constants'
17
- export * from './utils'
19
+ export * from "./components"
20
+ export * from "./constants"
21
+ export * from "./utils"
@@ -1,12 +1,16 @@
1
- import { inject, InjectionKey, provide, ref } from "vue";
2
- import { makeIntl} from "@effect-app/vue"
1
+ import { inject, type InjectionKey, provide } from "vue"
2
+ import { type makeIntl } from "@effect-app/vue"
3
3
 
4
- const intlKey = Symbol() as InjectionKey<ReturnType<ReturnType<typeof makeIntl>["useIntl"]>>
5
- export const useIntl = () => {
4
+ const intlKey = Symbol() as InjectionKey<
5
+ ReturnType<ReturnType<typeof makeIntl>["useIntl"]>
6
+ >
7
+ export const useIntl = () => {
6
8
  const intl = inject(intlKey)
7
9
  if (!intl) {
8
10
  throw new Error("useIntl must be used within a IntlProvider")
9
11
  }
10
12
  return intl
11
13
  }
12
- export const provideIntl = (intl: ReturnType<ReturnType<typeof makeIntl>["useIntl"]>) => provide(intlKey, intl)
14
+ export const provideIntl = (
15
+ intl: ReturnType<ReturnType<typeof makeIntl>["useIntl"]>,
16
+ ) => provide(intlKey, intl)
@@ -1 +0,0 @@
1
- fieldset[data-v-0de09910]{display:contents}.omega-input .v-input__details:has(.v-messages:empty){grid-template-rows:0fr;transition:all .2s}.omega-input .v-messages:empty{min-height:0}.omega-input .v-input__details:has(.v-messages){transition:all .2s;overflow:hidden;min-height:0;display:grid;grid-template-rows:1fr}.omega-input .v-messages{transition:all .2s}.omega-input .v-messages>*{transition-duration:0s!important}.v-enter-from[data-v-55fda615],.v-leave-to[data-v-55fda615]{max-height:0px;grid-template-rows:0fr;opacity:0}.v-enter-active[data-v-55fda615],.v-leave-active[data-v-55fda615]{display:grid;transition:all .15s}.v-enter-to[data-v-55fda615],.v-leave-from[data-v-55fda615]{grid-template-rows:1fr;max-height:50vh;opacity:1}.error-alert[data-v-55fda615]{transition-behavior:allow-discrete;display:grid;overflow:hidden;min-height:0}.error-alert>*[data-v-55fda615]{min-height:0}.error-list[data-v-55fda615]{container-type:inline-size;display:grid;grid-template-columns:auto 1fr auto;gap:8px;align-items:start}@container (max-width: 28.125rem){.error-list[data-v-55fda615]{grid-template-columns:auto 1fr}.error-link[data-v-55fda615]{grid-column:1 / -1;justify-self:end;padding-bottom:16px}}@container (max-width: 18.75rem){.error-list[data-v-55fda615]{grid-template-columns:1fr}.error-message[data-v-55fda615]{grid-column:1 / -1}}.error-item[data-v-55fda615]{display:contents}a[data-v-55fda615]{min-width:min-content}.error-link[data-v-55fda615]{color:inherit;text-decoration:none;display:inline-flex;align-items:center}