@effect-app/vue-components 3.0.5 → 3.0.6

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,34 +1,194 @@
1
- import { defineComponent as m, createElementBlock as d, openBlock as u, withModifiers as f, createElementVNode as l, unref as s, renderSlot as a } from "vue";
2
- import { useStore as b } from "@tanstack/vue-form";
3
- import { usePreventClose as p } from "./vue-components.es11.js";
4
- import { getOmegaStore as c } from "./vue-components.es53.js";
5
- const S = ["disabled"], V = /* @__PURE__ */ m({
6
- __name: "OmegaWrapper",
1
+ import { defineComponent as k, resolveComponent as b, createElementBlock as v, openBlock as n, createBlock as a, createCommentVNode as u, resolveDynamicComponent as g, mergeProps as o, createSlots as d, withCtx as r, renderSlot as m, normalizeProps as s, guardReactiveProps as P, unref as C, Fragment as V, renderList as U } from "vue";
2
+ import { getInputType as c } from "./vue-components.es12.js";
3
+ const w = /* @__PURE__ */ k({
4
+ inheritAttrs: !1,
5
+ __name: "OmegaInputVuetify",
7
6
  props: {
8
- form: {},
9
- disabled: { type: Boolean },
10
- subscribe: {}
7
+ inputProps: {},
8
+ field: {},
9
+ state: {}
11
10
  },
12
- setup(o) {
13
- const e = o, i = b(
14
- e.form.store,
15
- (t) => t.isSubmitting
16
- ), n = c(
17
- e.form,
18
- e.subscribe
19
- );
20
- return e.form.ignorePreventCloseEvents || p(() => e.form.useStore((t) => t.isDirty)), (t, r) => (u(), d("form", {
21
- novalidate: "",
22
- onSubmit: r[0] || (r[0] = f((v) => o.form.handleSubmit(), ["prevent", "stop"]))
23
- }, [
24
- l("fieldset", {
25
- disabled: s(i) || o.disabled
11
+ emits: ["focus", "blur"],
12
+ setup(e) {
13
+ return (l, i) => {
14
+ const y = b("v-text-field"), p = b("v-textarea"), f = b("v-radio"), h = b("v-radio-group"), q = b("v-select"), $ = b("v-autocomplete");
15
+ return n(), v("div", {
16
+ class: "omega-input",
17
+ onFocusout: i[4] || (i[4] = (t) => l.$emit("blur", t)),
18
+ onFocusin: i[5] || (i[5] = (t) => l.$emit("focus", t))
26
19
  }, [
27
- a(t.$slots, "default", { subscribedValues: s(n) }, void 0, !0)
28
- ], 8, S)
29
- ], 32));
20
+ e.inputProps.type === "boolean" || e.inputProps.type === "switch" ? (n(), a(g(e.inputProps.type === "boolean" ? "v-checkbox" : "v-switch"), o({
21
+ key: 0,
22
+ id: e.inputProps.id,
23
+ name: e.field.name,
24
+ label: e.inputProps.label,
25
+ "error-messages": e.inputProps.errorMessages,
26
+ error: e.inputProps.error,
27
+ ripple: ""
28
+ }, l.$attrs, {
29
+ "model-value": e.state.value,
30
+ onChange: i[0] || (i[0] = (t) => e.field.handleChange(t.target.checked))
31
+ }), d({ _: 2 }, [
32
+ l.$slots.label ? {
33
+ name: "label",
34
+ fn: r(() => [
35
+ m(l.$slots, "label", s(P({ required: e.inputProps.required, id: e.inputProps.id, label: e.inputProps.label })))
36
+ ]),
37
+ key: "0"
38
+ } : void 0
39
+ ]), 1040, ["id", "name", "label", "error-messages", "error", "model-value"])) : u("", !0),
40
+ e.inputProps.type === "email" || e.inputProps.type === "string" || e.inputProps.type === "password" || e.inputProps.type === "date" ? (n(), a(y, o({
41
+ key: 1,
42
+ id: e.inputProps.id,
43
+ required: e.inputProps.required,
44
+ "min-length": e.inputProps.minLength,
45
+ "max-length": e.inputProps.maxLength,
46
+ type: C(c)(e.inputProps.type),
47
+ name: e.field.name,
48
+ label: e.inputProps.label,
49
+ "error-messages": e.inputProps.errorMessages,
50
+ error: e.inputProps.error
51
+ }, l.$attrs, {
52
+ "model-value": e.state.value,
53
+ "onUpdate:modelValue": e.field.handleChange
54
+ }), d({ _: 2 }, [
55
+ l.$slots.label ? {
56
+ name: "label",
57
+ fn: r(() => [
58
+ m(l.$slots, "label", s(P({ required: e.inputProps.required, id: e.inputProps.id, label: e.inputProps.label })))
59
+ ]),
60
+ key: "0"
61
+ } : void 0
62
+ ]), 1040, ["id", "required", "min-length", "max-length", "type", "name", "label", "error-messages", "error", "model-value", "onUpdate:modelValue"])) : u("", !0),
63
+ e.inputProps.type === "text" ? (n(), a(p, o({
64
+ key: 2,
65
+ id: e.inputProps.id,
66
+ required: e.inputProps.required,
67
+ "min-length": e.inputProps.minLength,
68
+ "max-length": e.inputProps.maxLength,
69
+ name: e.field.name,
70
+ label: e.inputProps.label,
71
+ "error-messages": e.inputProps.errorMessages,
72
+ error: e.inputProps.error
73
+ }, l.$attrs, {
74
+ "model-value": e.state.value,
75
+ "onUpdate:modelValue": e.field.handleChange
76
+ }), d({ _: 2 }, [
77
+ l.$slots.label ? {
78
+ name: "label",
79
+ fn: r(() => [
80
+ m(l.$slots, "label", s(P({ required: e.inputProps.required, id: e.inputProps.id, label: e.inputProps.label })))
81
+ ]),
82
+ key: "0"
83
+ } : void 0
84
+ ]), 1040, ["id", "required", "min-length", "max-length", "name", "label", "error-messages", "error", "model-value", "onUpdate:modelValue"])) : u("", !0),
85
+ e.inputProps.type === "number" || e.inputProps.type === "int" || e.inputProps.type === "range" ? (n(), a(g(e.inputProps.type === "range" ? "v-slider" : "v-text-field"), o({
86
+ key: 3,
87
+ id: e.inputProps.id,
88
+ required: e.inputProps.required,
89
+ min: e.inputProps.min,
90
+ max: e.inputProps.max,
91
+ type: e.inputProps.type === "int" ? "number" : e.inputProps.type,
92
+ name: e.field.name,
93
+ label: e.inputProps.label,
94
+ "error-messages": e.inputProps.errorMessages,
95
+ error: e.inputProps.error
96
+ }, l.$attrs, {
97
+ "model-value": e.state.value,
98
+ "onUpdate:modelValue": i[1] || (i[1] = (t) => {
99
+ t || t === 0 ? e.field.handleChange(Number(t)) : e.field.handleChange(void 0);
100
+ })
101
+ }), d({ _: 2 }, [
102
+ l.$slots.label ? {
103
+ name: "label",
104
+ fn: r(() => [
105
+ m(l.$slots, "label", s(P({ required: e.inputProps.required, id: e.inputProps.id, label: e.inputProps.label })))
106
+ ]),
107
+ key: "0"
108
+ } : void 0
109
+ ]), 1040, ["id", "required", "min", "max", "type", "name", "label", "error-messages", "error", "model-value"])) : u("", !0),
110
+ e.inputProps.type === "radio" ? (n(), a(h, o({
111
+ key: 4,
112
+ id: e.inputProps.id,
113
+ name: e.field.name,
114
+ label: e.inputProps.label,
115
+ "error-messages": e.inputProps.errorMessages,
116
+ error: e.inputProps.error
117
+ }, l.$attrs, {
118
+ "model-value": e.state.value,
119
+ "onUpdate:modelValue": e.field.handleChange
120
+ }), d({
121
+ default: r(() => [
122
+ (n(!0), v(V, null, U(e.inputProps.options, (t) => (n(), a(f, {
123
+ key: t.value,
124
+ label: t.title,
125
+ value: t.value
126
+ }, null, 8, ["label", "value"]))), 128))
127
+ ]),
128
+ _: 2
129
+ }, [
130
+ l.$slots.label ? {
131
+ name: "label",
132
+ fn: r(() => [
133
+ m(l.$slots, "label", s(P({ required: e.inputProps.required, id: e.inputProps.id, label: e.inputProps.label })))
134
+ ]),
135
+ key: "0"
136
+ } : void 0
137
+ ]), 1040, ["id", "name", "label", "error-messages", "error", "model-value", "onUpdate:modelValue"])) : u("", !0),
138
+ e.inputProps.type === "select" || e.inputProps.type === "multiple" ? (n(), a(q, o({
139
+ key: 5,
140
+ id: e.inputProps.id,
141
+ clearable: e.inputProps.type === "select",
142
+ required: e.inputProps.required,
143
+ multiple: e.inputProps.type === "multiple",
144
+ chips: e.inputProps.type === "multiple",
145
+ name: e.field.name,
146
+ label: e.inputProps.label,
147
+ items: e.inputProps.options,
148
+ "error-messages": e.inputProps.errorMessages,
149
+ error: e.inputProps.error
150
+ }, l.$attrs, {
151
+ "model-value": e.state.value,
152
+ onClear: i[2] || (i[2] = (t) => e.field.handleChange(void 0)),
153
+ "onUpdate:modelValue": e.field.handleChange
154
+ }), d({ _: 2 }, [
155
+ l.$slots.label ? {
156
+ name: "label",
157
+ fn: r(() => [
158
+ m(l.$slots, "label", s(P({ required: e.inputProps.required, id: e.inputProps.id, label: e.inputProps.label })))
159
+ ]),
160
+ key: "0"
161
+ } : void 0
162
+ ]), 1040, ["id", "clearable", "required", "multiple", "chips", "name", "label", "items", "error-messages", "error", "model-value", "onUpdate:modelValue"])) : u("", !0),
163
+ e.inputProps.type === "autocomplete" || e.inputProps.type === "autocompletemultiple" ? (n(), a($, o({
164
+ key: 6,
165
+ id: e.inputProps.id,
166
+ clearable: e.inputProps.type === "autocomplete",
167
+ multiple: e.inputProps.type === "autocompletemultiple",
168
+ required: e.inputProps.required,
169
+ name: e.field.name,
170
+ label: e.inputProps.label,
171
+ items: e.inputProps.options,
172
+ "error-messages": e.inputProps.errorMessages,
173
+ error: e.inputProps.error,
174
+ chips: e.inputProps.type === "autocompletemultiple"
175
+ }, l.$attrs, {
176
+ "model-value": e.state.value,
177
+ onClear: i[3] || (i[3] = (t) => e.field.handleChange(void 0)),
178
+ "onUpdate:modelValue": e.field.handleChange
179
+ }), d({ _: 2 }, [
180
+ l.$slots.label ? {
181
+ name: "label",
182
+ fn: r(() => [
183
+ m(l.$slots, "label", s(P({ required: e.inputProps.required, id: e.inputProps.id, label: e.inputProps.label })))
184
+ ]),
185
+ key: "0"
186
+ } : void 0
187
+ ]), 1040, ["id", "clearable", "multiple", "required", "name", "label", "items", "error-messages", "error", "chips", "model-value", "onUpdate:modelValue"])) : u("", !0)
188
+ ], 32);
189
+ };
30
190
  }
31
191
  });
32
192
  export {
33
- V as default
193
+ w as default
34
194
  };
@@ -1,5 +1,5 @@
1
1
  (function(){"use strict";try{if(typeof document<"u"){var i=document.createElement("style");if(i.appendChild(document.createTextNode(".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}.omega-input [role=alert]:has(.v-messages:empty){padding:0}.omega-input .v-btn{cursor:pointer;width:auto;appearance:none;box-shadow:none;display:block;min-width:auto;height:auto;padding:.5em .5em .5em 1em}")),document.head.appendChild(i),window.customElements){const e=window.customElements.define;window.customElements.define=function(s,t){const n=t.prototype.connectedCallback;return t.prototype.connectedCallback=function(){if(n&&n.call(this),this.shadowRoot){const a=document.createElement("style");a.appendChild(document.createTextNode(".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}.omega-input [role=alert]:has(.v-messages:empty){padding:0}.omega-input .v-btn{cursor:pointer;width:auto;appearance:none;box-shadow:none;display:block;min-width:auto;height:auto;padding:.5em .5em .5em 1em}")),this.shadowRoot.appendChild(a)}},e.call(window.customElements,s,t)}}}}catch(e){console.error("vite-plugin-css-injected-by-js",e)}})();
2
- import o from "./vue-components.es30.js";
2
+ import o from "./vue-components.es38.js";
3
3
 
4
4
  export {
5
5
  o as default
@@ -1,7 +1,7 @@
1
1
  (function(){"use strict";try{if(typeof document<"u"){var i=document.createElement("style");if(i.appendChild(document.createTextNode(".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}.omega-input [role=alert]:has(.v-messages:empty){padding:0}.omega-input .v-btn{cursor:pointer;width:auto;appearance:none;box-shadow:none;display:block;min-width:auto;height:auto;padding:.5em .5em .5em 1em}")),document.head.appendChild(i),window.customElements){const e=window.customElements.define;window.customElements.define=function(s,t){const n=t.prototype.connectedCallback;return t.prototype.connectedCallback=function(){if(n&&n.call(this),this.shadowRoot){const a=document.createElement("style");a.appendChild(document.createTextNode(".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}.omega-input [role=alert]:has(.v-messages:empty){padding:0}.omega-input .v-btn{cursor:pointer;width:auto;appearance:none;box-shadow:none;display:block;min-width:auto;height:auto;padding:.5em .5em .5em 1em}")),this.shadowRoot.appendChild(a)}},e.call(window.customElements,s,t)}}}}catch(e){console.error("vite-plugin-css-injected-by-js",e)}})();
2
2
  import { defineComponent as N, computed as n, getCurrentInstance as k, useAttrs as q, useSlots as B, useId as S, renderSlot as d, normalizeProps as s, guardReactiveProps as p, createElementVNode as w, normalizeClass as F, createBlock as I, createCommentVNode as L, unref as A, openBlock as O, mergeProps as R, createSlots as V, withCtx as z } from "vue";
3
3
  import { useStore as f } from "@tanstack/vue-form";
4
- import T from "./vue-components.es30.js";
4
+ import T from "./vue-components.es38.js";
5
5
 
6
6
  const H = /* @__PURE__ */ N({
7
7
  inheritAttrs: !1,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect-app/vue-components",
3
- "version": "3.0.5",
3
+ "version": "3.0.6",
4
4
  "peerDependencies": {
5
5
  "@mdi/js": "^7.4.47",
6
6
  "effect": "^3.19.3",
@@ -53,8 +53,8 @@
53
53
  "highlight.js": "^11.11.1",
54
54
  "mitt": "^3.0.1",
55
55
  "vue3-highlightjs": "^1.0.5",
56
- "effect-app": "3.15.1",
57
- "@effect-app/vue": "2.93.8"
56
+ "@effect-app/vue": "2.93.8",
57
+ "effect-app": "3.15.1"
58
58
  },
59
59
  "scripts": {
60
60
  "build": "pnpm build:run",
@@ -246,7 +246,7 @@ export type StringFieldMeta = BaseFieldMeta & {
246
246
  }
247
247
 
248
248
  export type NumberFieldMeta = BaseFieldMeta & {
249
- type: "number"
249
+ type: "number" | "int"
250
250
  minimum?: number
251
251
  maximum?: number
252
252
  exclusiveMinimum?: number
@@ -346,12 +346,23 @@ export const createMeta = <T = any>(
346
346
  ): MetaRecord<T> | FieldMeta => {
347
347
  // unwraps class (Class are transformations)
348
348
  // this calls createMeta recursively, so wrapped transformations are also unwrapped
349
+ // BUT: check for Int title annotation first - S.Int and branded Int have title "Int" or "int"
350
+ // and we don't want to lose that information by unwrapping
349
351
  if (property && property._tag === "Transformation") {
350
- return createMeta<T>({
351
- parent,
352
- meta,
353
- property: property.from
354
- })
352
+ const titleOnTransform = S
353
+ .AST
354
+ .getAnnotation(property, S.AST.TitleAnnotationId)
355
+ .pipe(Option.getOrElse(() => ""))
356
+
357
+ // only unwrap if this is NOT an Int type
358
+ if (titleOnTransform !== "Int" && titleOnTransform !== "int") {
359
+ return createMeta<T>({
360
+ parent,
361
+ meta,
362
+ property: property.from
363
+ })
364
+ }
365
+ // if it's Int, fall through to process it with the Int type
355
366
  }
356
367
 
357
368
  if (property?._tag === "TypeLiteral" && "propertySignatures" in property) {
@@ -655,24 +666,32 @@ export const createMeta = <T = any>(
655
666
 
656
667
  meta = { ...JSONAnnotation, ...meta }
657
668
 
658
- if ("from" in property) {
669
+ // check the title annotation BEFORE following "from" to detect refinements like S.Int
670
+ const titleType = S
671
+ .AST
672
+ .getAnnotation(
673
+ property,
674
+ S.AST.TitleAnnotationId
675
+ )
676
+ .pipe(
677
+ Option.getOrElse(() => {
678
+ return "unknown"
679
+ })
680
+ )
681
+
682
+ // if this is S.Int (a refinement), set the type and skip following "from"
683
+ // otherwise we'd lose the "Int" information and get "number" instead
684
+ if (titleType === "Int" || titleType === "int") {
685
+ meta["type"] = "int"
686
+ // don't follow "from" for Int refinements
687
+ } else if ("from" in property) {
659
688
  return createMeta<T>({
660
689
  parent,
661
690
  meta,
662
691
  property: property.from
663
692
  })
664
693
  } else {
665
- meta["type"] = S
666
- .AST
667
- .getAnnotation(
668
- property,
669
- S.AST.TitleAnnotationId
670
- )
671
- .pipe(
672
- Option.getOrElse(() => {
673
- return "unknown"
674
- })
675
- )
694
+ meta["type"] = titleType
676
695
  }
677
696
 
678
697
  return meta as FieldMeta
@@ -869,9 +888,59 @@ export const generateInputStandardSchemaFromFieldMeta = (
869
888
  }
870
889
  break
871
890
 
891
+ case "int": {
892
+ // create a custom integer schema with translations
893
+ // S.Number with empty message, then S.int with integer message
894
+ schema = S
895
+ .Number
896
+ .annotations({
897
+ message: () => trans("validation.empty")
898
+ })
899
+ .pipe(
900
+ S.int({ message: (issue) => trans("validation.integer.expected", { actualValue: String(issue.actual) }) })
901
+ )
902
+ if (typeof meta.minimum === "number") {
903
+ schema = schema.pipe(S.greaterThanOrEqualTo(meta.minimum)).annotations({
904
+ message: () =>
905
+ trans(meta.minimum === 0 ? "validation.number.positive" : "validation.number.min", {
906
+ minimum: meta.minimum,
907
+ isExclusive: true
908
+ })
909
+ })
910
+ }
911
+ if (typeof meta.maximum === "number") {
912
+ schema = schema.pipe(S.lessThanOrEqualTo(meta.maximum)).annotations({
913
+ message: () =>
914
+ trans("validation.number.max", {
915
+ maximum: meta.maximum,
916
+ isExclusive: true
917
+ })
918
+ })
919
+ }
920
+ if (typeof meta.exclusiveMinimum === "number") {
921
+ schema = schema.pipe(S.greaterThan(meta.exclusiveMinimum)).annotations({
922
+ message: () =>
923
+ trans(meta.exclusiveMinimum === 0 ? "validation.number.positive" : "validation.number.min", {
924
+ minimum: meta.exclusiveMinimum,
925
+ isExclusive: false
926
+ })
927
+ })
928
+ }
929
+ if (typeof meta.exclusiveMaximum === "number") {
930
+ schema = schema.pipe(S.lessThan(meta.exclusiveMaximum)).annotations({
931
+ message: () =>
932
+ trans("validation.number.max", {
933
+ maximum: meta.exclusiveMaximum,
934
+ isExclusive: false
935
+ })
936
+ })
937
+ }
938
+ break
939
+ }
940
+
872
941
  case "number":
873
942
  schema = S.Number.annotations({
874
- message: () => trans("validation.empty")
943
+ message: () => trans("validation.number.expected", { actualValue: "NaN" })
875
944
  })
876
945
 
877
946
  if (meta.required) {
@@ -81,12 +81,12 @@
81
81
  </v-textarea>
82
82
  <component
83
83
  :is="inputProps.type === 'range' ? 'v-slider' : 'v-text-field'"
84
- v-if="inputProps.type === 'number' || inputProps.type === 'range'"
84
+ v-if="inputProps.type === 'number' || inputProps.type === 'int' || inputProps.type === 'range'"
85
85
  :id="inputProps.id"
86
86
  :required="inputProps.required"
87
87
  :min="inputProps.min"
88
88
  :max="inputProps.max"
89
- :type="inputProps.type"
89
+ :type="inputProps.type === 'int' ? 'number' : inputProps.type"
90
90
  :name="field.name"
91
91
  :label="inputProps.label"
92
92
  :error-messages="inputProps.errorMessages"
@@ -1,4 +0,0 @@
1
- import f from "./vue-components.es19.js";
2
- export {
3
- f as default
4
- };
@@ -1,9 +0,0 @@
1
- const s = (t, e) => {
2
- const o = t.__vccOpts || t;
3
- for (const [r, c] of e)
4
- o[r] = c;
5
- return o;
6
- };
7
- export {
8
- s as default
9
- };