@effect-app/vue-components 2.2.0 → 2.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.
@@ -2,7 +2,7 @@ import { type DeepKeys } from "@tanstack/vue-form";
2
2
  import type { MergedInputProps } from "./InputProps";
3
3
  import type { BaseProps, DefaultTypeProps } from "./OmegaFormStuff";
4
4
  declare const __VLS_export: <From extends Record<PropertyKey, any>, To extends Record<PropertyKey, any>, Name extends DeepKeys<From>>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
5
- props: __VLS_PrettifyLocal<BaseProps<From, Name> & DefaultTypeProps> & import("vue").PublicProps;
5
+ props: __VLS_PrettifyLocal<BaseProps<From> & DefaultTypeProps> & import("vue").PublicProps;
6
6
  expose: (exposed: {}) => void;
7
7
  attrs: any;
8
8
  slots: {
@@ -3,15 +3,18 @@ import { type DeepKeys, type DeepValue, type FieldAsyncValidateOrFn, type FieldV
3
3
  import { type RuntimeFiber } from "effect/Fiber";
4
4
  import { type OmegaFieldInternalApi } from "./InputProps";
5
5
  import { type OF, type OmegaFormReturn } from "./useOmegaForm";
6
- export type Leaves<T, Path extends string = ""> = T extends ReadonlyArray<infer U> ? Leaves<U, `${Path}[number]`> & {} : {
6
+ export type Leaves<T, Path extends string = ""> = T extends ReadonlyArray<infer U> ? Leaves<U, `${Path}[${number}]`> & {} : {
7
7
  [K in keyof T]: T[K] extends string | boolean | number | null | undefined | symbol | bigint ? `${Path extends "" ? "" : `${Path}.`}${K & string}` : Leaves<T[K], `${Path extends "" ? "" : `${Path}.`}${K & string}`> & {};
8
8
  }[keyof T];
9
- export type FlexibleArrayPath<T extends string> = T extends `${string}[${string}]${string}` ? T : never;
10
- export type BaseProps<From, TName extends DeepKeys<From> = DeepKeys<From>> = {
11
- /** Will fallback to i18n when not specified */
9
+ export type BaseProps<From> = {
10
+ /**
11
+ * Will fallback to i18n when not specified.
12
+ * Can also be provided via #label slot for custom HTML labels.
13
+ * When using the slot, it receives bindings: { required, id, label }
14
+ */
12
15
  label?: string;
13
16
  validators?: FieldValidators<From>;
14
- name: FlexibleArrayPath<TName> extends never ? Leaves<From> : TName;
17
+ name: Leaves<From>;
15
18
  /**
16
19
  * Optional class to apply to the input element.
17
20
  * - If a string is provided, it will be used instead of the general class
@@ -36,13 +39,13 @@ export type OmegaInputPropsBase<From extends Record<PropertyKey, any>, To extend
36
39
  meta: MetaRecord<From>;
37
40
  i18nNamespace?: string;
38
41
  };
39
- } & BaseProps<From, NestedKeyOf<From>>;
42
+ } & BaseProps<From>;
40
43
  export type OmegaInputProps<From extends Record<PropertyKey, any>, To extends Record<PropertyKey, any>, TypeProps = DefaultTypeProps> = {
41
44
  form: OmegaFormReturn<From, To, TypeProps> & {
42
45
  meta: MetaRecord<From>;
43
46
  i18nNamespace?: string;
44
47
  };
45
- } & BaseProps<From, NestedKeyOf<From>>;
48
+ } & BaseProps<From>;
46
49
  export type OmegaArrayProps<From extends Record<PropertyKey, any>, To extends Record<PropertyKey, any>> = Omit<OmegaInputProps<From, To>, "validators" | "options" | "label" | "type" | "items" | "name"> & {
47
50
  name: DeepKeys<From>;
48
51
  defaultItems?: DeepValue<From, DeepKeys<From>>;
@@ -4,21 +4,12 @@ declare const __VLS_export: <From extends Record<PropertyKey, any>, To extends R
4
4
  expose: (exposed: {}) => void;
5
5
  attrs: any;
6
6
  slots: {
7
- default?: (props: {
8
- field: import("./InputProps").OmegaFieldInternalApi<From, any>;
9
- state: import("@tanstack/vue-form").FieldState<From, any, import("@tanstack/vue-form").DeepValue<From, any>, import("@tanstack/vue-form").FieldValidateOrFn<From, any, import("@tanstack/vue-form").DeepValue<From, any>> | undefined, import("@tanstack/vue-form").StandardSchemaV1<import("@tanstack/vue-form").DeepValue<From, any>, unknown> | import("@tanstack/vue-form").FieldValidateFn<From, any>, import("@tanstack/vue-form").StandardSchemaV1<import("@tanstack/vue-form").DeepValue<From, any>, unknown> | import("@tanstack/vue-form").FieldValidateAsyncFn<From, any>, import("@tanstack/vue-form").FieldValidateOrFn<From, any, import("@tanstack/vue-form").DeepValue<From, any>>, import("@tanstack/vue-form").FieldAsyncValidateOrFn<From, any, import("@tanstack/vue-form").DeepValue<From, any>>, import("@tanstack/vue-form").FieldValidateOrFn<From, any, import("@tanstack/vue-form").DeepValue<From, any>> | undefined, import("@tanstack/vue-form").FieldAsyncValidateOrFn<From, any, import("@tanstack/vue-form").DeepValue<From, any>> | undefined, import("@tanstack/vue-form").FieldValidateOrFn<From, any, import("@tanstack/vue-form").DeepValue<From, any>> | undefined, import("@tanstack/vue-form").FieldAsyncValidateOrFn<From, any, import("@tanstack/vue-form").DeepValue<From, any>> | undefined, import("@tanstack/vue-form").FormValidateOrFn<From> | undefined, import("@tanstack/vue-form").FormValidateOrFn<From> | undefined, any, import("@tanstack/vue-form").FormValidateOrFn<From> | undefined, import("@tanstack/vue-form").FormAsyncValidateOrFn<From> | undefined, import("@tanstack/vue-form").FormValidateOrFn<From> | undefined, import("@tanstack/vue-form").FormAsyncValidateOrFn<From> | undefined, import("@tanstack/vue-form").FormValidateOrFn<From> | undefined, import("@tanstack/vue-form").FormAsyncValidateOrFn<From> | undefined>;
10
- id: string;
7
+ label?: (props: {
11
8
  required?: boolean;
12
- minLength?: number | false;
13
- maxLength?: number | false;
14
- max?: number | false;
15
- min?: number | false;
16
- errorMessages: string[];
17
- error: boolean;
9
+ id: string;
18
10
  label: string;
19
- type: string;
20
- inputClass: string | undefined | null;
21
11
  }) => any;
12
+ default?: (props: any) => any;
22
13
  };
23
14
  emit: {};
24
15
  }>) => import("vue").VNode & {
@@ -7,7 +7,49 @@ declare const __VLS_export: <From extends Record<PropertyKey, any>, Name extends
7
7
  }> & import("vue").PublicProps;
8
8
  expose: (exposed: {}) => void;
9
9
  attrs: any;
10
- slots: {};
10
+ slots: {
11
+ label?: (props: {
12
+ required: boolean | undefined;
13
+ id: string;
14
+ label: string;
15
+ }) => any;
16
+ } & {
17
+ label?: (props: {
18
+ required: boolean | undefined;
19
+ id: string;
20
+ label: string;
21
+ }) => any;
22
+ } & {
23
+ label?: (props: {
24
+ required: boolean | undefined;
25
+ id: string;
26
+ label: string;
27
+ }) => any;
28
+ } & {
29
+ label?: (props: {
30
+ required: boolean | undefined;
31
+ id: string;
32
+ label: string;
33
+ }) => any;
34
+ } & {
35
+ label?: (props: {
36
+ required: boolean | undefined;
37
+ id: string;
38
+ label: string;
39
+ }) => any;
40
+ } & {
41
+ label?: (props: {
42
+ required: boolean | undefined;
43
+ id: string;
44
+ label: string;
45
+ }) => any;
46
+ } & {
47
+ label?: (props: {
48
+ required: boolean | undefined;
49
+ id: string;
50
+ label: string;
51
+ }) => any;
52
+ };
11
53
  emit: {
12
54
  (e: "focus", event: Event): void;
13
55
  (e: "blur", event: Event): void;
@@ -40,6 +40,12 @@ declare const __VLS_export: <From extends Record<PropertyKey, any>, Name extends
40
40
  type: string;
41
41
  inputClass: string | undefined | null;
42
42
  }) => any;
43
+ } & {
44
+ label?: (props: {
45
+ required: boolean | undefined;
46
+ id: string;
47
+ label: string;
48
+ }) => any;
43
49
  };
44
50
  emit: {};
45
51
  }>) => import("vue").VNode & {
@@ -78,11 +78,16 @@ type __VLS_PrettifyLocal<T> = {
78
78
  } & {};
79
79
  export interface OmegaFormReturn<From extends Record<PropertyKey, any>, To extends Record<PropertyKey, any>, TypeProps = DefaultTypeProps> extends OF<From, To> {
80
80
  Input: <Name extends DeepKeys<From>>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
81
- props: __VLS_PrettifyLocal<Pick<Partial<{}> & Omit<{} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, never>, never> & BaseProps<From, Name> & TypeProps & Partial<{}>> & import("vue").PublicProps;
81
+ props: __VLS_PrettifyLocal<Pick<Partial<{}> & Omit<{} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, never>, never> & BaseProps<From> & TypeProps & Partial<{}>> & import("vue").PublicProps;
82
82
  expose(exposed: import("vue").ShallowUnwrapRef<{}>): void;
83
83
  attrs: any;
84
84
  slots: {
85
- default(props: MergedInputProps<From, Name>): void;
85
+ default?(props: MergedInputProps<From, Name>): void;
86
+ label?: (props: {
87
+ required: boolean;
88
+ id: string;
89
+ label: string;
90
+ }) => void;
86
91
  };
87
92
  emit: {};
88
93
  }>) => import("vue").VNode & {
@@ -1,29 +1,38 @@
1
- import { h as o } from "vue";
2
- import l from "./vue-components.es6.js";
1
+ import { h as a } from "vue";
2
+ import b from "./vue-components.es6.js";
3
3
  import { useOmegaForm as O } from "./vue-components.es10.js";
4
- const g = (n) => (...m) => {
5
- const [p, s, a] = m;
4
+ const j = (m) => (...p) => {
5
+ const [l, c, f] = p;
6
6
  return O(
7
- p,
8
- s,
7
+ l,
8
+ c,
9
9
  {
10
- ...a,
10
+ ...f,
11
11
  input: {
12
12
  name: "WrappedInput",
13
13
  inheritAttrs: !1,
14
- setup(c, { attrs: t }) {
15
- return () => o(l, {
16
- ...c,
17
- ...t
14
+ setup(i, { attrs: n, slots: e }) {
15
+ return () => a(b, {
16
+ ...i,
17
+ ...n
18
18
  }, {
19
19
  // Override the default slot that OmegaInternalInput provides
20
- default: ({ field: f, state: i, ...r }) => {
21
- const u = Object.fromEntries(
22
- Object.entries(t).filter(
23
- ([e]) => !Object.prototype.hasOwnProperty.call(r, e) && e !== "form"
20
+ default: ({ field: r, state: u, ...o }) => {
21
+ const s = Object.fromEntries(
22
+ Object.entries(n).filter(
23
+ ([t]) => !Object.prototype.hasOwnProperty.call(o, t) && t !== "form"
24
24
  )
25
25
  );
26
- return o(n, { ...u, field: f, state: i, inputProps: r });
26
+ return a(m, { ...s, field: r, state: u, inputProps: o }, {
27
+ // Pass through label slot if it exists
28
+ ...e.label && {
29
+ label: (t) => e.label(t)
30
+ }
31
+ });
32
+ },
33
+ // Pass through label slot to OmegaInput
34
+ ...e.label && {
35
+ label: (r) => e.label(r)
27
36
  }
28
37
  });
29
38
  }
@@ -32,5 +41,5 @@ const g = (n) => (...m) => {
32
41
  );
33
42
  };
34
43
  export {
35
- g as createUseFormWithCustomInput
44
+ j as createUseFormWithCustomInput
36
45
  };
@@ -1,6 +1,6 @@
1
- import { defineComponent as b, resolveComponent as o, createElementBlock as m, openBlock as n, createBlock as a, createCommentVNode as i, resolveDynamicComponent as d, mergeProps as u, unref as f, withCtx as h, Fragment as c, renderList as C } from "vue";
2
- import { getInputType as q } from "./vue-components.es12.js";
3
- const U = /* @__PURE__ */ b({
1
+ import { defineComponent as k, resolveComponent as b, createElementBlock as v, openBlock as a, createBlock as n, 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
4
  inheritAttrs: !1,
5
5
  __name: "OmegaInputVuetify",
6
6
  props: {
@@ -10,14 +10,14 @@ const U = /* @__PURE__ */ b({
10
10
  },
11
11
  emits: ["focus", "blur"],
12
12
  setup(e) {
13
- return (r, l) => {
14
- const s = o("v-text-field"), P = o("v-textarea"), g = o("v-radio"), v = o("v-radio-group"), p = o("v-select"), y = o("v-autocomplete");
15
- return n(), m("div", {
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 a(), v("div", {
16
16
  class: "omega-input",
17
- onFocusout: l[4] || (l[4] = (t) => r.$emit("blur", t)),
18
- onFocusin: l[5] || (l[5] = (t) => r.$emit("focus", t))
17
+ onFocusout: i[4] || (i[4] = (t) => l.$emit("blur", t)),
18
+ onFocusin: i[5] || (i[5] = (t) => l.$emit("focus", t))
19
19
  }, [
20
- e.inputProps.type === "boolean" || e.inputProps.type === "switch" ? (n(), a(d(e.inputProps.type === "boolean" ? "v-checkbox" : "v-switch"), u({
20
+ e.inputProps.type === "boolean" || e.inputProps.type === "switch" ? (a(), n(g(e.inputProps.type === "boolean" ? "v-checkbox" : "v-switch"), o({
21
21
  key: 0,
22
22
  id: e.inputProps.id,
23
23
  name: e.field.name,
@@ -25,26 +25,42 @@ const U = /* @__PURE__ */ b({
25
25
  "error-messages": e.inputProps.errorMessages,
26
26
  error: e.inputProps.error,
27
27
  ripple: ""
28
- }, r.$attrs, {
28
+ }, l.$attrs, {
29
29
  "model-value": e.state.value,
30
- onChange: l[0] || (l[0] = (t) => e.field.handleChange(t.target.checked))
31
- }), null, 16, ["id", "name", "label", "error-messages", "error", "model-value"])) : i("", !0),
32
- e.inputProps.type === "email" || e.inputProps.type === "string" || e.inputProps.type === "password" ? (n(), a(s, u({
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" ? (a(), n(y, o({
33
41
  key: 1,
34
42
  id: e.inputProps.id,
35
43
  required: e.inputProps.required,
36
44
  "min-length": e.inputProps.minLength,
37
45
  "max-length": e.inputProps.maxLength,
38
- type: f(q)(e.inputProps.type),
46
+ type: C(c)(e.inputProps.type),
39
47
  name: e.field.name,
40
48
  label: e.inputProps.label,
41
49
  "error-messages": e.inputProps.errorMessages,
42
50
  error: e.inputProps.error
43
- }, r.$attrs, {
51
+ }, l.$attrs, {
44
52
  "model-value": e.state.value,
45
53
  "onUpdate:modelValue": e.field.handleChange
46
- }), null, 16, ["id", "required", "min-length", "max-length", "type", "name", "label", "error-messages", "error", "model-value", "onUpdate:modelValue"])) : i("", !0),
47
- e.inputProps.type === "text" ? (n(), a(P, u({
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" ? (a(), n(p, o({
48
64
  key: 2,
49
65
  id: e.inputProps.id,
50
66
  required: e.inputProps.required,
@@ -54,11 +70,19 @@ const U = /* @__PURE__ */ b({
54
70
  label: e.inputProps.label,
55
71
  "error-messages": e.inputProps.errorMessages,
56
72
  error: e.inputProps.error
57
- }, r.$attrs, {
73
+ }, l.$attrs, {
58
74
  "model-value": e.state.value,
59
75
  "onUpdate:modelValue": e.field.handleChange
60
- }), null, 16, ["id", "required", "min-length", "max-length", "name", "label", "error-messages", "error", "model-value", "onUpdate:modelValue"])) : i("", !0),
61
- e.inputProps.type === "number" || e.inputProps.type === "range" ? (n(), a(d(e.inputProps.type === "range" ? "v-slider" : "v-text-field"), u({
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 === "range" ? (a(), n(g(e.inputProps.type === "range" ? "v-slider" : "v-text-field"), o({
62
86
  key: 3,
63
87
  id: e.inputProps.id,
64
88
  required: e.inputProps.required,
@@ -69,33 +93,49 @@ const U = /* @__PURE__ */ b({
69
93
  label: e.inputProps.label,
70
94
  "error-messages": e.inputProps.errorMessages,
71
95
  error: e.inputProps.error
72
- }, r.$attrs, {
96
+ }, l.$attrs, {
73
97
  "model-value": e.state.value,
74
- "onUpdate:modelValue": l[1] || (l[1] = (t) => {
98
+ "onUpdate:modelValue": i[1] || (i[1] = (t) => {
75
99
  t || t === 0 ? e.field.handleChange(Number(t)) : e.field.handleChange(void 0);
76
100
  })
77
- }), null, 16, ["id", "required", "min", "max", "type", "name", "label", "error-messages", "error", "model-value"])) : i("", !0),
78
- e.inputProps.type === "radio" ? (n(), a(v, u({
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" ? (a(), n(h, o({
79
111
  key: 4,
80
112
  id: e.inputProps.id,
81
113
  name: e.field.name,
82
114
  label: e.inputProps.label,
83
115
  "error-messages": e.inputProps.errorMessages,
84
116
  error: e.inputProps.error
85
- }, r.$attrs, {
117
+ }, l.$attrs, {
86
118
  "model-value": e.state.value,
87
119
  "onUpdate:modelValue": e.field.handleChange
88
- }), {
89
- default: h(() => [
90
- (n(!0), m(c, null, C(e.inputProps.options, (t) => (n(), a(g, {
120
+ }), d({
121
+ default: r(() => [
122
+ (a(!0), v(V, null, U(e.inputProps.options, (t) => (a(), n(f, {
91
123
  key: t.value,
92
124
  label: t.title,
93
125
  value: t.value
94
126
  }, null, 8, ["label", "value"]))), 128))
95
127
  ]),
96
- _: 1
97
- }, 16, ["id", "name", "label", "error-messages", "error", "model-value", "onUpdate:modelValue"])) : i("", !0),
98
- e.inputProps.type === "select" || e.inputProps.type === "multiple" ? (n(), a(p, u({
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" ? (a(), n(q, o({
99
139
  key: 5,
100
140
  id: e.inputProps.id,
101
141
  clearable: e.inputProps.type === "select",
@@ -107,12 +147,20 @@ const U = /* @__PURE__ */ b({
107
147
  items: e.inputProps.options,
108
148
  "error-messages": e.inputProps.errorMessages,
109
149
  error: e.inputProps.error
110
- }, r.$attrs, {
150
+ }, l.$attrs, {
111
151
  "model-value": e.state.value,
112
- onClear: l[2] || (l[2] = (t) => e.field.handleChange(void 0)),
152
+ onClear: i[2] || (i[2] = (t) => e.field.handleChange(void 0)),
113
153
  "onUpdate:modelValue": e.field.handleChange
114
- }), null, 16, ["id", "clearable", "required", "multiple", "chips", "name", "label", "items", "error-messages", "error", "model-value", "onUpdate:modelValue"])) : i("", !0),
115
- e.inputProps.type === "autocomplete" || e.inputProps.type === "autocompletemultiple" ? (n(), a(y, u({
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" ? (a(), n($, o({
116
164
  key: 6,
117
165
  id: e.inputProps.id,
118
166
  clearable: e.inputProps.type === "autocomplete",
@@ -124,15 +172,23 @@ const U = /* @__PURE__ */ b({
124
172
  "error-messages": e.inputProps.errorMessages,
125
173
  error: e.inputProps.error,
126
174
  chips: e.inputProps.type === "autocompletemultiple"
127
- }, r.$attrs, {
175
+ }, l.$attrs, {
128
176
  "model-value": e.state.value,
129
- onClear: l[3] || (l[3] = (t) => e.field.handleChange(void 0)),
177
+ onClear: i[3] || (i[3] = (t) => e.field.handleChange(void 0)),
130
178
  "onUpdate:modelValue": e.field.handleChange
131
- }), null, 16, ["id", "clearable", "multiple", "required", "name", "label", "items", "error-messages", "error", "chips", "model-value", "onUpdate:modelValue"])) : i("", !0)
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)
132
188
  ], 32);
133
189
  };
134
190
  }
135
191
  });
136
192
  export {
137
- U as default
193
+ w as default
138
194
  };
@@ -1,8 +1,8 @@
1
- import { defineComponent as b, computed as s, useAttrs as F, inject as k, createBlock as c, openBlock as f, resolveDynamicComponent as y, withCtx as d, createCommentVNode as A, mergeProps as N, renderSlot as w, normalizeProps as I, guardReactiveProps as P } from "vue";
2
- import { useIntl as S } from "./vue-components.es3.js";
3
- import { generateInputStandardSchemaFromFieldMeta as j } from "./vue-components.es12.js";
4
- import z from "./vue-components.es7.js";
5
- const R = /* @__PURE__ */ b({
1
+ import { defineComponent as F, computed as n, useAttrs as A, inject as N, createBlock as d, openBlock as p, resolveDynamicComponent as S, withCtx as i, createCommentVNode as w, mergeProps as I, createSlots as P, renderSlot as v, normalizeProps as g, guardReactiveProps as C } from "vue";
2
+ import { useIntl as j } from "./vue-components.es3.js";
3
+ import { generateInputStandardSchemaFromFieldMeta as z } from "./vue-components.es12.js";
4
+ import B from "./vue-components.es7.js";
5
+ const U = /* @__PURE__ */ F({
6
6
  inheritAttrs: !1,
7
7
  __name: "OmegaInput",
8
8
  props: {
@@ -12,43 +12,51 @@ const R = /* @__PURE__ */ b({
12
12
  name: {},
13
13
  inputClass: {}
14
14
  },
15
- setup(a) {
16
- const e = a, r = s(() => e.name), p = F(), v = s(() => {
15
+ setup(t) {
16
+ const e = t, r = n(() => e.name), $ = A(), b = n(() => {
17
17
  if (e.inputClass !== null)
18
- return e.inputClass !== void 0 ? e.inputClass : p.class;
19
- }), l = k(
18
+ return e.inputClass !== void 0 ? e.inputClass : $.class;
19
+ }), s = N(
20
20
  "getMetaFromArray",
21
21
  null
22
- ), n = s(() => l?.value && l.value(e.name) ? l.value(r.value) : e.form.meta[r.value]), g = s(() => {
23
- if (!n.value)
22
+ ), l = n(() => s?.value && s.value(e.name) ? s.value(r.value) : e.form.meta[r.value]), h = n(() => {
23
+ if (!l.value)
24
24
  throw console.log(e.name, Object.keys(e.form.meta), e.form.meta), new Error("Meta is undefined");
25
- return j(n.value);
26
- }), { formatMessage: o } = S(), m = (t) => t.replace(/([A-Z])/g, " $1").replace(/^./, (u) => u.toUpperCase()).trim(), i = () => o ? o({ id: `general.fields.${r.value}`, defaultMessage: m(e.name) }) : m(e.name), C = () => e.form.i18nNamespace ? o({ id: `${e.form.i18nNamespace}.fields.${r.value}`, defaultMessage: i() }) : i();
27
- return (t, u) => (f(), c(y(a.form.Field), {
28
- name: a.name,
25
+ return z(l.value);
26
+ }), { formatMessage: o } = j(), u = (a) => a.replace(/([A-Z])/g, " $1").replace(/^./, (c) => c.toUpperCase()).trim(), f = () => o ? o({ id: `general.fields.${r.value}`, defaultMessage: u(e.name) }) : u(e.name), M = () => e.form.i18nNamespace ? o({ id: `${e.form.i18nNamespace}.fields.${r.value}`, defaultMessage: f() }) : f();
27
+ return (a, c) => (p(), d(S(t.form.Field), {
28
+ name: t.name,
29
29
  validators: {
30
- onChange: g.value,
31
- ...a.validators
30
+ onChange: h.value,
31
+ ...t.validators
32
32
  }
33
33
  }, {
34
- default: d(({ field: h, state: $ }) => [
35
- n.value ? (f(), c(z, N({ key: 0 }, { ...t.$attrs, ...t.$props, inputClass: v.value }, {
36
- field: h,
37
- state: $,
38
- register: a.form.registerField,
39
- label: a.label ?? C(),
40
- meta: n.value
41
- }), {
42
- default: d((M) => [
43
- w(t.$slots, "default", I(P(M)))
34
+ default: i(({ field: k, state: y }) => [
35
+ l.value ? (p(), d(B, I({ key: 0 }, { ...a.$attrs, ...a.$props, inputClass: b.value }, {
36
+ field: k,
37
+ state: y,
38
+ register: t.form.registerField,
39
+ label: t.label ?? M(),
40
+ meta: l.value
41
+ }), P({
42
+ default: i((m) => [
43
+ v(a.$slots, "default", g(C(m)))
44
44
  ]),
45
- _: 3
46
- }, 16, ["field", "state", "register", "label", "meta"])) : A("", !0)
45
+ _: 2
46
+ }, [
47
+ a.$slots.label ? {
48
+ name: "label",
49
+ fn: i((m) => [
50
+ v(a.$slots, "label", g(C(m)))
51
+ ]),
52
+ key: "0"
53
+ } : void 0
54
+ ]), 1040, ["field", "state", "register", "label", "meta"])) : w("", !0)
47
55
  ]),
48
56
  _: 3
49
57
  }, 8, ["name", "validators"]));
50
58
  }
51
59
  });
52
60
  export {
53
- R as default
61
+ U as default
54
62
  };
@@ -1,9 +1,9 @@
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 { defineComponent as _, computed as n, getCurrentInstance as x, useAttrs as P, useId as N, renderSlot as q, normalizeProps as i, guardReactiveProps as B, createElementVNode as $, normalizeClass as k, createBlock as I, createCommentVNode as L, unref as M, openBlock as S, mergeProps as w } from "vue";
3
- import { useStore as A } from "@tanstack/vue-form";
4
- import F from "./vue-components.es38.js";
2
+ import { defineComponent as N, computed as n, getCurrentInstance as S, useAttrs as k, useSlots as q, useId as B, renderSlot as m, normalizeProps as s, guardReactiveProps as d, createElementVNode as w, normalizeClass as I, createBlock as L, createCommentVNode as M, unref as A, openBlock as F, mergeProps as O, createSlots as R, withCtx as V } from "vue";
3
+ import { useStore as z } from "@tanstack/vue-form";
4
+ import T from "./vue-components.es38.js";
5
5
 
6
- const Z = /* @__PURE__ */ _({
6
+ const H = /* @__PURE__ */ N({
7
7
  inheritAttrs: !1,
8
8
  __name: "OmegaInternalInput",
9
9
  props: {
@@ -18,55 +18,64 @@ const Z = /* @__PURE__ */ _({
18
18
  register: {},
19
19
  options: { default: void 0 }
20
20
  },
21
- setup(u) {
22
- const e = u, s = n(() => e.required ?? e?.meta?.required), m = x()?.appContext.components.VTextField, d = P(), p = n(() => {
23
- const { class: t, ...r } = d;
24
- return r;
25
- }), l = N(), f = e.field, c = A(f.store, (t) => t), g = n(() => e.type ? e.type : e.meta?.type === "string" ? e.meta.format === "email" ? "email" : "string" : e.meta?.type || "unknown");
26
- e.register(n(() => ({ name: e.field.name, label: e.label, id: l })));
27
- const h = n(() => c.value.meta.errors ?? []), o = n(
21
+ setup(p) {
22
+ const e = p, l = n(() => e.required ?? e?.meta?.required), f = S()?.appContext.components.VTextField, c = k(), g = q(), h = n(() => {
23
+ const { class: t, ...a } = c;
24
+ return a;
25
+ }), o = B(), v = e.field, y = z(v.store, (t) => t), b = n(() => e.type ? e.type : e.meta?.type === "string" ? e.meta.format === "email" ? "email" : "string" : e.meta?.type || "unknown");
26
+ e.register(n(() => ({ name: e.field.name, label: e.label, id: o })));
27
+ const C = n(() => y.value.meta.errors ?? []), i = n(
28
28
  () => (
29
29
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
30
- h.value.map((t) => t?.message).filter(Boolean)
30
+ C.value.map((t) => t?.message).filter(Boolean)
31
31
  )
32
- ), v = (t) => t == null || t === !1 || t === "" || Number.isNaN(t), y = (t) => {
33
- v(t) && e.meta?.type !== "boolean" && e.meta?.nullableOrUndefined ? e.field.handleChange(
32
+ ), _ = (t) => t == null || t === !1 || t === "" || Number.isNaN(t), x = (t) => {
33
+ _(t) && e.meta?.type !== "boolean" && e.meta?.nullableOrUndefined ? e.field.handleChange(
34
34
  e.meta.nullableOrUndefined === "undefined" ? void 0 : null
35
- ) : e.field.handleChange(t), e.field.setMeta((r) => ({ ...r, errorMap: { ...r.errorMap, onSubmit: void 0 } }));
36
- }, C = (t) => {
37
- const r = {
38
- get(V, b, z) {
39
- return b === "handleChange" ? y : Reflect.get(...arguments);
35
+ ) : e.field.handleChange(t), e.field.setMeta((a) => ({ ...a, errorMap: { ...a.errorMap, onSubmit: void 0 } }));
36
+ }, P = (t) => {
37
+ const a = {
38
+ get(E, $, W) {
39
+ return $ === "handleChange" ? x : Reflect.get(...arguments);
40
40
  }
41
41
  };
42
- return new Proxy(t, r);
43
- }, a = n(() => ({
42
+ return new Proxy(t, a);
43
+ }, r = n(() => ({
44
44
  inputProps: {
45
- id: l,
46
- required: s.value,
45
+ id: o,
46
+ required: l.value,
47
47
  minLength: e.meta?.type === "string" && e.meta?.minLength,
48
48
  maxLength: e.meta?.type === "string" && e.meta?.maxLength,
49
49
  max: e.meta?.type === "number" && e.meta?.maximum,
50
50
  min: e.meta?.type === "number" && e.meta?.minimum,
51
- errorMessages: o.value,
52
- error: !!o.value.length,
53
- type: g.value,
54
- label: `${e.label}${s.value ? " *" : ""}`,
51
+ errorMessages: i.value,
52
+ error: !!i.value.length,
53
+ type: b.value,
54
+ // Only add asterisk if label slot is not provided (slot has full control)
55
+ label: g.label ? e.label : `${e.label}${l.value ? " *" : ""}`,
55
56
  options: e.options,
56
57
  inputClass: e.inputClass
57
58
  },
58
59
  state: e.state,
59
- field: C(e.field)
60
+ field: P(e.field)
60
61
  }));
61
- return (t, r) => q(t.$slots, "default", i(B({ ...a.value.inputProps, field: a.value.field, state: a.value.state })), () => [
62
- $("div", {
63
- class: k(t.$attrs.class)
62
+ return (t, a) => m(t.$slots, "default", s(d({ ...r.value.inputProps, field: r.value.field, state: r.value.state })), () => [
63
+ w("div", {
64
+ class: I(t.$attrs.class)
64
65
  }, [
65
- M(m) ? (S(), I(F, i(w({ key: 0 }, { ...p.value, ...a.value, class: e.inputClass })), null, 16)) : L("", !0)
66
+ A(f) ? (F(), L(T, s(O({ key: 0 }, { ...h.value, ...r.value, class: e.inputClass })), R({ _: 2 }, [
67
+ t.$slots.label ? {
68
+ name: "label",
69
+ fn: V((u) => [
70
+ m(t.$slots, "label", s(d(u)))
71
+ ]),
72
+ key: "0"
73
+ } : void 0
74
+ ]), 1040)) : M("", !0)
66
75
  ], 2)
67
76
  ]);
68
77
  }
69
78
  });
70
79
  export {
71
- Z as default
80
+ H as default
72
81
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect-app/vue-components",
3
- "version": "2.2.0",
3
+ "version": "2.3.0",
4
4
  "peerDependencies": {
5
5
  "@mdi/js": "^7.4.47",
6
6
  "effect": "^3.18.0",
@@ -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/vue": "2.92.1",
57
- "effect-app": "3.12.0"
56
+ "effect-app": "3.12.0",
57
+ "@effect-app/vue": "2.92.1"
58
58
  },
59
59
  "scripts": {
60
60
  "build": "pnpm build:run",
@@ -35,7 +35,7 @@ if (!form) {
35
35
  }
36
36
 
37
37
  defineProps<
38
- BaseProps<From, Name> & DefaultTypeProps
38
+ BaseProps<From> & DefaultTypeProps
39
39
  >()
40
40
 
41
41
  defineSlots<{
@@ -7,24 +7,24 @@ import { getTransformationFrom, useIntl } from "../../utils"
7
7
  import { type OmegaFieldInternalApi } from "./InputProps"
8
8
  import { type OF, type OmegaFormReturn } from "./useOmegaForm"
9
9
 
10
- export type Leaves<T, Path extends string = ""> = T extends ReadonlyArray<infer U> ? Leaves<U, `${Path}[number]`> & {}
10
+ export type Leaves<T, Path extends string = ""> = T extends ReadonlyArray<infer U>
11
+ ? Leaves<U, `${Path}[${number}]`> & {}
11
12
  : {
12
13
  [K in keyof T]: T[K] extends string | boolean | number | null | undefined | symbol | bigint
13
14
  ? `${Path extends "" ? "" : `${Path}.`}${K & string}`
14
15
  : Leaves<T[K], `${Path extends "" ? "" : `${Path}.`}${K & string}`> & {}
15
16
  }[keyof T]
16
17
 
17
- // Helper type to make array indices flexible - accepts both [number] and numeric literals [0], [1], etc.
18
- // Simplified: if there's a [] in the path, just use TName to avoid excessive type complexity
19
- export type FlexibleArrayPath<T extends string> = T extends `${string}[${string}]${string}` ? T
20
- : never
21
-
22
- export type BaseProps<From, TName extends DeepKeys<From> = DeepKeys<From>> = {
23
- /** Will fallback to i18n when not specified */
18
+ export type BaseProps<From> = {
19
+ /**
20
+ * Will fallback to i18n when not specified.
21
+ * Can also be provided via #label slot for custom HTML labels.
22
+ * When using the slot, it receives bindings: { required, id, label }
23
+ */
24
24
  label?: string
25
25
  validators?: FieldValidators<From>
26
26
  // Use FlexibleArrayPath: if name contains [], just use TName; otherwise intersect with Leaves<From>
27
- name: FlexibleArrayPath<TName> extends never ? Leaves<From> : TName
27
+ name: Leaves<From>
28
28
  /**
29
29
  * Optional class to apply to the input element.
30
30
  * - If a string is provided, it will be used instead of the general class
@@ -56,7 +56,7 @@ export type OmegaInputPropsBase<
56
56
  meta: MetaRecord<From>
57
57
  i18nNamespace?: string
58
58
  }
59
- } & BaseProps<From, NestedKeyOf<From>>
59
+ } & BaseProps<From>
60
60
 
61
61
  export type OmegaInputProps<
62
62
  From extends Record<PropertyKey, any>,
@@ -67,7 +67,7 @@ export type OmegaInputProps<
67
67
  meta: MetaRecord<From>
68
68
  i18nNamespace?: string
69
69
  }
70
- } & BaseProps<From, NestedKeyOf<From>>
70
+ } & BaseProps<From>
71
71
 
72
72
  export type OmegaArrayProps<
73
73
  From extends Record<PropertyKey, any>,
@@ -17,6 +17,15 @@
17
17
  :label="label ?? i18n()"
18
18
  :meta="meta"
19
19
  >
20
+ <template
21
+ v-if="$slots.label"
22
+ #label="labelProps"
23
+ >
24
+ <slot
25
+ name="label"
26
+ v-bind="labelProps"
27
+ />
28
+ </template>
20
29
  <template #default="inputProps">
21
30
  <slot v-bind="inputProps" />
22
31
  </template>
@@ -42,8 +51,13 @@ import OmegaInternalInput from "./OmegaInternalInput.vue"
42
51
 
43
52
  const props = defineProps<OmegaInputPropsBase<From, To>>()
44
53
 
45
- // downgrade to DeepKeys<From> to avoid useless and possible infinite recursion in TS
46
- const propsName: Ref<DeepKeys<From>> = computed(() => props.name)
54
+ // downgrade to *as* DeepKeys<From> to avoid useless and possible infinite recursion in TS
55
+ const propsName = computed(() => props.name as DeepKeys<From>)
56
+
57
+ defineSlots<{
58
+ label?: (props: { required?: boolean; id: string; label: string }) => any
59
+ default?: (props: any) => any
60
+ }>()
47
61
 
48
62
  defineOptions({
49
63
  inheritAttrs: false
@@ -64,7 +78,7 @@ const getMetaFromArray = inject<Ref<(name: string) => FieldMeta | null> | null>(
64
78
  )
65
79
 
66
80
  const meta = computed(() => {
67
- if (getMetaFromArray?.value && getMetaFromArray.value(props.name)) {
81
+ if (getMetaFromArray?.value && getMetaFromArray.value(props.name as DeepKeys<From>)) {
68
82
  return getMetaFromArray.value(propsName.value)
69
83
  }
70
84
  return props.form.meta[propsName.value]
@@ -16,7 +16,17 @@
16
16
  v-bind="$attrs"
17
17
  :model-value="state.value"
18
18
  @change="(e: any) => field.handleChange(e.target.checked)"
19
- />
19
+ >
20
+ <template
21
+ v-if="$slots.label"
22
+ #label
23
+ >
24
+ <slot
25
+ name="label"
26
+ v-bind="{ required: inputProps.required, id: inputProps.id, label: inputProps.label }"
27
+ />
28
+ </template>
29
+ </component>
20
30
  <v-text-field
21
31
  v-if="inputProps.type === 'email' || inputProps.type === 'string' || inputProps.type === 'password'"
22
32
  :id="inputProps.id"
@@ -31,7 +41,17 @@
31
41
  v-bind="$attrs"
32
42
  :model-value="state.value"
33
43
  @update:model-value="field.handleChange"
34
- />
44
+ >
45
+ <template
46
+ v-if="$slots.label"
47
+ #label
48
+ >
49
+ <slot
50
+ name="label"
51
+ v-bind="{ required: inputProps.required, id: inputProps.id, label: inputProps.label }"
52
+ />
53
+ </template>
54
+ </v-text-field>
35
55
  <v-textarea
36
56
  v-if="inputProps.type === 'text'"
37
57
  :id="inputProps.id"
@@ -45,7 +65,17 @@
45
65
  v-bind="$attrs"
46
66
  :model-value="state.value"
47
67
  @update:model-value="field.handleChange"
48
- />
68
+ >
69
+ <template
70
+ v-if="$slots.label"
71
+ #label
72
+ >
73
+ <slot
74
+ name="label"
75
+ v-bind="{ required: inputProps.required, id: inputProps.id, label: inputProps.label }"
76
+ />
77
+ </template>
78
+ </v-textarea>
49
79
  <component
50
80
  :is="inputProps.type === 'range' ? 'v-slider' : 'v-text-field'"
51
81
  v-if="inputProps.type === 'number' || inputProps.type === 'range'"
@@ -67,7 +97,17 @@
67
97
  field.handleChange(undefined as any)
68
98
  }
69
99
  }"
70
- />
100
+ >
101
+ <template
102
+ v-if="$slots.label"
103
+ #label
104
+ >
105
+ <slot
106
+ name="label"
107
+ v-bind="{ required: inputProps.required, id: inputProps.id, label: inputProps.label }"
108
+ />
109
+ </template>
110
+ </component>
71
111
  <template v-if="inputProps.type === 'radio'">
72
112
  <v-radio-group
73
113
  :id="inputProps.id"
@@ -79,6 +119,15 @@
79
119
  :model-value="state.value"
80
120
  @update:model-value="field.handleChange"
81
121
  >
122
+ <template
123
+ v-if="$slots.label"
124
+ #label
125
+ >
126
+ <slot
127
+ name="label"
128
+ v-bind="{ required: inputProps.required, id: inputProps.id, label: inputProps.label }"
129
+ />
130
+ </template>
82
131
  <v-radio
83
132
  v-for="option in inputProps.options"
84
133
  :key="option.value"
@@ -103,7 +152,17 @@
103
152
  :model-value="state.value"
104
153
  @clear="field.handleChange(undefined as any)"
105
154
  @update:model-value="field.handleChange"
106
- />
155
+ >
156
+ <template
157
+ v-if="$slots.label"
158
+ #label
159
+ >
160
+ <slot
161
+ name="label"
162
+ v-bind="{ required: inputProps.required, id: inputProps.id, label: inputProps.label }"
163
+ />
164
+ </template>
165
+ </v-select>
107
166
 
108
167
  <v-autocomplete
109
168
  v-if="inputProps.type === 'autocomplete'
@@ -122,7 +181,17 @@
122
181
  :model-value="state.value"
123
182
  @clear="field.handleChange(undefined as any)"
124
183
  @update:model-value="field.handleChange"
125
- />
184
+ >
185
+ <template
186
+ v-if="$slots.label"
187
+ #label
188
+ >
189
+ <slot
190
+ name="label"
191
+ v-bind="{ required: inputProps.required, id: inputProps.id, label: inputProps.label }"
192
+ />
193
+ </template>
194
+ </v-autocomplete>
126
195
  </div>
127
196
  </template>
128
197
 
@@ -4,7 +4,17 @@
4
4
  <OmegaInputVuetify
5
5
  v-if="vuetified"
6
6
  v-bind="{ ...attrsWithoutClass, ...inputProps, class: props.inputClass }"
7
- />
7
+ >
8
+ <template
9
+ v-if="$slots.label"
10
+ #label="labelProps"
11
+ >
12
+ <slot
13
+ name="label"
14
+ v-bind="labelProps"
15
+ />
16
+ </template>
17
+ </OmegaInputVuetify>
8
18
  </div>
9
19
  </slot>
10
20
  </template>
@@ -15,7 +25,7 @@
15
25
  generic="From extends Record<PropertyKey, any>, Name extends DeepKeys<From>"
16
26
  >
17
27
  import { type DeepKeys, useStore } from "@tanstack/vue-form"
18
- import { computed, type ComputedRef, getCurrentInstance, useAttrs, useId } from "vue"
28
+ import { computed, type ComputedRef, getCurrentInstance, useAttrs, useId, useSlots } from "vue"
19
29
  import type { InputProps, OmegaFieldInternalApi } from "./InputProps"
20
30
  import type { FieldValidators, MetaRecord, NestedKeyOf, TypeOverride } from "./OmegaFormStuff"
21
31
  import OmegaInputVuetify from "./OmegaInputVuetify.vue"
@@ -60,6 +70,7 @@ const isRequired = computed(() => props.required ?? props?.meta?.required)
60
70
  const instance = getCurrentInstance()
61
71
  const vuetified = instance?.appContext.components["VTextField"]
62
72
  const attrs = useAttrs()
73
+ const slots = useSlots()
63
74
 
64
75
  // Create attrs without the class property to avoid duplication
65
76
  const attrsWithoutClass = computed(() => {
@@ -148,7 +159,8 @@ const inputProps: ComputedRef<InputProps<From, Name>> = computed(() => ({
148
159
  errorMessages: errors.value,
149
160
  error: !!errors.value.length,
150
161
  type: fieldType.value,
151
- label: `${props.label}${isRequired.value ? " *" : ""}`,
162
+ // Only add asterisk if label slot is not provided (slot has full control)
163
+ label: slots.label ? props.label : `${props.label}${isRequired.value ? " *" : ""}`,
152
164
  options: props.options,
153
165
  inputClass: props.inputClass
154
166
  },
@@ -20,7 +20,7 @@ export const createUseFormWithCustomInput = <
20
20
  const WrappedInput = {
21
21
  name: "WrappedInput",
22
22
  inheritAttrs: false,
23
- setup(props: any, { attrs }: any) {
23
+ setup(props: any, { attrs, slots }: any) {
24
24
  return () =>
25
25
  h(OmegaInput, {
26
26
  ...props,
@@ -35,8 +35,17 @@ export const createUseFormWithCustomInput = <
35
35
  && key !== "form"
36
36
  )
37
37
  )
38
- return h(CustomInputComponent, { ...filteredAttrs, field, state, inputProps })
39
- }
38
+ return h(CustomInputComponent, { ...filteredAttrs, field, state, inputProps }, {
39
+ // Pass through label slot if it exists
40
+ ...(slots.label && {
41
+ label: (labelProps: any) => slots.label(labelProps)
42
+ })
43
+ })
44
+ },
45
+ // Pass through label slot to OmegaInput
46
+ ...(slots.label && {
47
+ label: (labelProps: any) => slots.label(labelProps)
48
+ })
40
49
  })
41
50
  }
42
51
  }
@@ -228,7 +228,7 @@ export interface OmegaFormReturn<
228
228
  >,
229
229
  never
230
230
  >
231
- & BaseProps<From, Name>
231
+ & BaseProps<From>
232
232
  & TypeProps
233
233
  & Partial<{}>
234
234
  >
@@ -236,7 +236,8 @@ export interface OmegaFormReturn<
236
236
  expose(exposed: import("vue").ShallowUnwrapRef<{}>): void
237
237
  attrs: any
238
238
  slots: {
239
- default(props: MergedInputProps<From, Name>): void
239
+ default?(props: MergedInputProps<From, Name>): void
240
+ label?: (props: { required: boolean; id: string; label: string }) => void
240
241
  }
241
242
  emit: {}
242
243
  }>