@effect-app/vue-components 2.1.6 → 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.
@@ -12,6 +12,7 @@ export type InputProps<From extends Record<PropertyKey, any>, TName extends Deep
12
12
  error: boolean;
13
13
  label: string;
14
14
  type: string;
15
+ inputClass: string | undefined | null;
15
16
  };
16
17
  field: OmegaFieldInternalApi<From, TName>;
17
18
  /** be sure to use this state and not `field.state` as it is not reactive */
@@ -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,25 @@ 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 `${infer Before}[number]${infer After}` ? T | `${Before}[${number}]${FlexibleArrayPath<After>}` : T;
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: TName;
17
+ name: Leaves<From>;
18
+ /**
19
+ * Optional class to apply to the input element.
20
+ * - If a string is provided, it will be used instead of the general class
21
+ * - If null is provided, no class will be applied (neither inputClass nor general class)
22
+ * - If undefined (not provided), the general class will be used
23
+ */
24
+ inputClass?: string | null;
15
25
  };
16
26
  export type TypesWithOptions = "radio" | "select" | "multiple" | "autocomplete" | "autocompletemultiple";
17
27
  export type DefaultTypeProps = {
@@ -29,13 +39,13 @@ export type OmegaInputPropsBase<From extends Record<PropertyKey, any>, To extend
29
39
  meta: MetaRecord<From>;
30
40
  i18nNamespace?: string;
31
41
  };
32
- } & BaseProps<From, NestedKeyOf<From>>;
42
+ } & BaseProps<From>;
33
43
  export type OmegaInputProps<From extends Record<PropertyKey, any>, To extends Record<PropertyKey, any>, TypeProps = DefaultTypeProps> = {
34
44
  form: OmegaFormReturn<From, To, TypeProps> & {
35
45
  meta: MetaRecord<From>;
36
46
  i18nNamespace?: string;
37
47
  };
38
- } & BaseProps<From, NestedKeyOf<From>>;
48
+ } & BaseProps<From>;
39
49
  export type OmegaArrayProps<From extends Record<PropertyKey, any>, To extends Record<PropertyKey, any>> = Omit<OmegaInputProps<From, To>, "validators" | "options" | "label" | "type" | "items" | "name"> & {
40
50
  name: DeepKeys<From>;
41
51
  defaultItems?: DeepValue<From, DeepKeys<From>>;
@@ -4,20 +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
11
  }) => any;
12
+ default?: (props: any) => any;
21
13
  };
22
14
  emit: {};
23
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;
@@ -11,6 +11,7 @@ declare const __VLS_export: <From extends Record<PropertyKey, any>, Name extends
11
11
  type?: TypeOverride;
12
12
  validators?: FieldValidators<From>;
13
13
  required?: boolean;
14
+ inputClass?: string | null;
14
15
  register: (field: ComputedRef<{
15
16
  name: string;
16
17
  label: string;
@@ -37,6 +38,13 @@ declare const __VLS_export: <From extends Record<PropertyKey, any>, Name extends
37
38
  error: boolean;
38
39
  label: string;
39
40
  type: string;
41
+ inputClass: string | undefined | null;
42
+ }) => any;
43
+ } & {
44
+ label?: (props: {
45
+ required: boolean | undefined;
46
+ id: string;
47
+ label: string;
40
48
  }) => any;
41
49
  };
42
50
  emit: {};
@@ -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,15 +1,16 @@
1
- import { defineComponent as F, computed as i, onMounted as M, provide as P, createBlock as c, openBlock as s, resolveDynamicComponent as p, withCtx as g, renderSlot as o, createElementBlock as k, normalizeProps as l, guardReactiveProps as u, Fragment as A, renderList as b, mergeProps as B } from "vue";
1
+ import { defineComponent as F, computed as f, onMounted as M, provide as P, createBlock as c, openBlock as s, resolveDynamicComponent as p, withCtx as g, renderSlot as o, createElementBlock as k, normalizeProps as l, guardReactiveProps as u, Fragment as A, renderList as C, mergeProps as b } from "vue";
2
2
  const N = /* @__PURE__ */ F({
3
3
  inheritAttrs: !1,
4
4
  __name: "OmegaArray",
5
5
  props: {
6
6
  form: {},
7
+ inputClass: {},
7
8
  name: {},
8
9
  defaultItems: {},
9
10
  items: {}
10
11
  },
11
12
  setup(n) {
12
- const a = n, y = a.form.useStore((e) => e.values), d = i(() => {
13
+ const a = n, y = a.form.useStore((e) => e.values), i = f(() => {
13
14
  const e = a.name.replace(/\[/g, ".").replace(/\]/g, "");
14
15
  try {
15
16
  return e.split(".").reduce((r, t) => r && r[t], y.value);
@@ -18,16 +19,16 @@ const N = /* @__PURE__ */ F({
18
19
  }
19
20
  });
20
21
  M(async () => {
21
- a.defaultItems && !d.value && a.form.setFieldValue(a.name, a.defaultItems);
22
+ a.defaultItems && !i.value && a.form.setFieldValue(a.name, a.defaultItems);
22
23
  });
23
- const $ = i(() => (r) => {
24
+ const $ = f(() => (r) => {
24
25
  const t = r.replace(/\[\d+\]/g, "");
25
26
  return a.form.meta[t];
26
27
  });
27
28
  return P("getMetaFromArray", $), (e, r) => (s(), c(p(n.form.Field), { name: n.name }, {
28
- default: g(({ field: t, state: f }) => [
29
- o(e.$slots, "pre-array", l(u({ field: t, state: f }))),
30
- (s(!0), k(A, null, b(d.value, (C, m) => (s(), c(p(n.form.Field), {
29
+ default: g(({ field: t, state: d }) => [
30
+ o(e.$slots, "pre-array", l(u({ field: t, state: d }))),
31
+ (s(!0), k(A, null, C(i.value, (B, m) => (s(), c(p(n.form.Field), {
31
32
  key: `${n.name}[${Number(m)}]`,
32
33
  name: (
33
34
  // eslint-disable-next-line
@@ -35,7 +36,7 @@ const N = /* @__PURE__ */ F({
35
36
  )
36
37
  }, {
37
38
  default: g(({ field: v, state: h }) => [
38
- o(e.$slots, "default", B({ ref_for: !0 }, {
39
+ o(e.$slots, "default", b({ ref_for: !0 }, {
39
40
  subField: v,
40
41
  subState: h,
41
42
  index: Number(m),
@@ -44,7 +45,7 @@ const N = /* @__PURE__ */ F({
44
45
  ]),
45
46
  _: 2
46
47
  }, 1032, ["name"]))), 128)),
47
- o(e.$slots, "post-array", l(u({ field: t, state: f }))),
48
+ o(e.$slots, "post-array", l(u({ field: t, state: d }))),
48
49
  o(e.$slots, "field", l(u({ field: t })))
49
50
  ]),
50
51
  _: 3
@@ -1,8 +1,8 @@
1
- (function(){"use strict";try{if(typeof document<"u"){var n=document.createElement("style");if(n.appendChild(document.createTextNode("fieldset[data-v-8a2f9d6f]{display:contents}fieldset[disabled][data-v-8a2f9d6f]>*{pointer-events:none}")),document.head.appendChild(n),window.customElements){const e=window.customElements.define;window.customElements.define=function(i,t){const d=t.prototype.connectedCallback;return t.prototype.connectedCallback=function(){if(d&&d.call(this),this.shadowRoot){const o=document.createElement("style");o.appendChild(document.createTextNode("fieldset[data-v-8a2f9d6f]{display:contents}fieldset[disabled][data-v-8a2f9d6f]>*{pointer-events:none}")),this.shadowRoot.appendChild(o)}},e.call(window.customElements,i,t)}}}}catch(e){console.error("vite-plugin-css-injected-by-js",e)}})();
1
+ (function(){"use strict";try{if(typeof document<"u"){var n=document.createElement("style");if(n.appendChild(document.createTextNode("fieldset[data-v-05e510ab]{display:contents}fieldset[disabled][data-v-05e510ab]>*{pointer-events:none}")),document.head.appendChild(n),window.customElements){const e=window.customElements.define;window.customElements.define=function(i,t){const d=t.prototype.connectedCallback;return t.prototype.connectedCallback=function(){if(d&&d.call(this),this.shadowRoot){const o=document.createElement("style");o.appendChild(document.createTextNode("fieldset[data-v-05e510ab]{display:contents}fieldset[disabled][data-v-05e510ab]>*{pointer-events:none}")),this.shadowRoot.appendChild(o)}},e.call(window.customElements,i,t)}}}}catch(e){console.error("vite-plugin-css-injected-by-js",e)}})();
2
2
  import o from "./vue-components.es36.js";
3
3
 
4
4
  import m from "./vue-components.es35.js";
5
- const f = /* @__PURE__ */ m(o, [["__scopeId", "data-v-8a2f9d6f"]]);
5
+ const e = /* @__PURE__ */ m(o, [["__scopeId", "data-v-05e510ab"]]);
6
6
  export {
7
- f as default
7
+ e as default
8
8
  };
@@ -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,50 +1,62 @@
1
- import { defineComponent as M, computed as l, inject as b, createBlock as f, openBlock as c, resolveDynamicComponent as C, withCtx as d, createCommentVNode as F, mergeProps as k, renderSlot as y, normalizeProps as A, guardReactiveProps as N } from "vue";
2
- import { useIntl as w } from "./vue-components.es3.js";
3
- import { generateInputStandardSchemaFromFieldMeta as I } from "./vue-components.es12.js";
4
- import P from "./vue-components.es7.js";
5
- const O = /* @__PURE__ */ M({
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: {
9
9
  form: {},
10
10
  label: {},
11
11
  validators: {},
12
- name: {}
12
+ name: {},
13
+ inputClass: {}
13
14
  },
14
- setup(a) {
15
- const e = a, r = l(() => e.name), n = b(
15
+ setup(t) {
16
+ const e = t, r = n(() => e.name), $ = A(), b = n(() => {
17
+ if (e.inputClass !== null)
18
+ return e.inputClass !== void 0 ? e.inputClass : $.class;
19
+ }), s = N(
16
20
  "getMetaFromArray",
17
21
  null
18
- ), o = l(() => n?.value && n.value(e.name) ? n.value(r.value) : e.form.meta[r.value]), p = l(() => {
19
- if (!o.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)
20
24
  throw console.log(e.name, Object.keys(e.form.meta), e.form.meta), new Error("Meta is undefined");
21
- return I(o.value);
22
- }), { formatMessage: m } = w(), s = (t) => t.replace(/([A-Z])/g, " $1").replace(/^./, (u) => u.toUpperCase()).trim(), i = () => m ? m({ id: `general.fields.${r.value}`, defaultMessage: s(e.name) }) : s(e.name), v = () => e.form.i18nNamespace ? m({ id: `${e.form.i18nNamespace}.fields.${r.value}`, defaultMessage: i() }) : i();
23
- return (t, u) => (c(), f(C(a.form.Field), {
24
- 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,
25
29
  validators: {
26
- onChange: p.value,
27
- ...a.validators
30
+ onChange: h.value,
31
+ ...t.validators
28
32
  }
29
33
  }, {
30
- default: d(({ field: g, state: h }) => [
31
- o.value ? (c(), f(P, k({ key: 0 }, { ...t.$attrs, ...t.$props }, {
32
- field: g,
33
- state: h,
34
- register: a.form.registerField,
35
- label: a.label ?? v(),
36
- meta: o.value
37
- }), {
38
- default: d(($) => [
39
- y(t.$slots, "default", A(N($)))
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)))
40
44
  ]),
41
- _: 3
42
- }, 16, ["field", "state", "register", "label", "meta"])) : F("", !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)
43
55
  ]),
44
56
  _: 3
45
57
  }, 8, ["name", "validators"]));
46
58
  }
47
59
  });
48
60
  export {
49
- O as default
61
+ U as default
50
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 b, computed as r, getCurrentInstance as C, useId as x, renderSlot as _, normalizeProps as m, guardReactiveProps as P, createElementVNode as N, normalizeClass as $, createBlock as q, createCommentVNode as B, unref as k, openBlock as I, mergeProps as L } from "vue";
3
- import { useStore as M } from "@tanstack/vue-form";
4
- import S 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 U = /* @__PURE__ */ b({
6
+ const H = /* @__PURE__ */ N({
7
7
  inheritAttrs: !1,
8
8
  __name: "OmegaInternalInput",
9
9
  props: {
@@ -14,54 +14,68 @@ const U = /* @__PURE__ */ b({
14
14
  type: { default: void 0 },
15
15
  validators: { default: void 0 },
16
16
  required: { type: Boolean, default: void 0 },
17
+ inputClass: { default: void 0 },
17
18
  register: {},
18
19
  options: { default: void 0 }
19
20
  },
20
- setup(u) {
21
- const e = u, o = r(() => e.required ?? e?.meta?.required), d = C()?.appContext.components.VTextField, l = x(), p = e.field, i = M(p.store, (t) => t), f = r(() => e.type ? e.type : e.meta?.type === "string" ? e.meta.format === "email" ? "email" : "string" : e.meta?.type || "unknown");
22
- e.register(r(() => ({ name: e.field.name, label: e.label, id: l }))), r(() => i.value.value);
23
- const c = r(() => i.value.meta.errors ?? []), s = r(
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(
24
28
  () => (
25
29
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
- c.value.map((t) => t?.message).filter(Boolean)
30
+ C.value.map((t) => t?.message).filter(Boolean)
27
31
  )
28
- ), g = (t) => t == null || t === !1 || t === "" || Number.isNaN(t), v = (t) => {
29
- g(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(
30
34
  e.meta.nullableOrUndefined === "undefined" ? void 0 : null
31
- ) : e.field.handleChange(t), e.field.setMeta((n) => ({ ...n, errorMap: { ...n.errorMap, onSubmit: void 0 } }));
32
- }, h = (t) => {
33
- const n = {
34
- get(O, y, R) {
35
- return y === "handleChange" ? v : 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);
36
40
  }
37
41
  };
38
- return new Proxy(t, n);
39
- }, a = r(() => ({
42
+ return new Proxy(t, a);
43
+ }, r = n(() => ({
40
44
  inputProps: {
41
- id: l,
42
- required: o.value,
45
+ id: o,
46
+ required: l.value,
43
47
  minLength: e.meta?.type === "string" && e.meta?.minLength,
44
48
  maxLength: e.meta?.type === "string" && e.meta?.maxLength,
45
49
  max: e.meta?.type === "number" && e.meta?.maximum,
46
50
  min: e.meta?.type === "number" && e.meta?.minimum,
47
- errorMessages: s.value,
48
- error: !!s.value.length,
49
- type: f.value,
50
- label: `${e.label}${o.value ? " *" : ""}`,
51
- options: e.options
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 ? " *" : ""}`,
56
+ options: e.options,
57
+ inputClass: e.inputClass
52
58
  },
53
59
  state: e.state,
54
- field: h(e.field)
60
+ field: P(e.field)
55
61
  }));
56
- return (t, n) => _(t.$slots, "default", m(P({ ...a.value.inputProps, field: a.value.field, state: a.value.state })), () => [
57
- N("div", {
58
- class: $(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)
59
65
  }, [
60
- k(d) ? (I(), q(S, m(L({ key: 0 }, { ...t.$attrs, ...a.value })), null, 16)) : B("", !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)
61
75
  ], 2)
62
76
  ]);
63
77
  }
64
78
  });
65
79
  export {
66
- U as default
80
+ H as default
67
81
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect-app/vue-components",
3
- "version": "2.1.6",
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",
@@ -39,6 +39,7 @@ export type InputProps<From extends Record<PropertyKey, any>, TName extends Deep
39
39
  error: boolean
40
40
  label: string
41
41
  type: string
42
+ inputClass: string | undefined | null
42
43
  }
43
44
  field: OmegaFieldInternalApi<From, TName>
44
45
  /** be sure to use this state and not `field.state` as it is not reactive */
@@ -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,31 @@ 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
- export type FlexibleArrayPath<T extends string> = T extends `${infer Before}[number]${infer After}`
19
- ? T | `${Before}[${number}]${FlexibleArrayPath<After>}`
20
- : T
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
- // disabled FlexibleArrayPath as it causes excessive complexity in type resolution inside user projects
27
- name: TName // & FlexibleArrayPath<Leaves<From>>
26
+ // Use FlexibleArrayPath: if name contains [], just use TName; otherwise intersect with Leaves<From>
27
+ name: Leaves<From>
28
+ /**
29
+ * Optional class to apply to the input element.
30
+ * - If a string is provided, it will be used instead of the general class
31
+ * - If null is provided, no class will be applied (neither inputClass nor general class)
32
+ * - If undefined (not provided), the general class will be used
33
+ */
34
+ inputClass?: string | null
28
35
  }
29
36
 
30
37
  export type TypesWithOptions = "radio" | "select" | "multiple" | "autocomplete" | "autocompletemultiple"
@@ -49,7 +56,7 @@ export type OmegaInputPropsBase<
49
56
  meta: MetaRecord<From>
50
57
  i18nNamespace?: string
51
58
  }
52
- } & BaseProps<From, NestedKeyOf<From>>
59
+ } & BaseProps<From>
53
60
 
54
61
  export type OmegaInputProps<
55
62
  From extends Record<PropertyKey, any>,
@@ -60,7 +67,7 @@ export type OmegaInputProps<
60
67
  meta: MetaRecord<From>
61
68
  i18nNamespace?: string
62
69
  }
63
- } & BaseProps<From, NestedKeyOf<From>>
70
+ } & BaseProps<From>
64
71
 
65
72
  export type OmegaArrayProps<
66
73
  From extends Record<PropertyKey, any>,
@@ -10,13 +10,22 @@
10
10
  <template #default="{ field, state }">
11
11
  <OmegaInternalInput
12
12
  v-if="meta"
13
- v-bind="{ ...$attrs, ...$props }"
13
+ v-bind="{ ...$attrs, ...$props, inputClass: computedClass }"
14
14
  :field="field"
15
15
  :state="state"
16
16
  :register="form.registerField"
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>
@@ -35,27 +44,41 @@
35
44
  "
36
45
  >
37
46
  import { type DeepKeys } from "@tanstack/vue-form"
38
- import { computed, inject, type Ref } from "vue"
47
+ import { computed, inject, type Ref, useAttrs } from "vue"
39
48
  import { useIntl } from "../../utils"
40
49
  import { type FieldMeta, generateInputStandardSchemaFromFieldMeta, type OmegaInputPropsBase } from "./OmegaFormStuff"
41
50
  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
50
64
  })
51
65
 
66
+ const attrs = useAttrs()
67
+
68
+ // Compute the class to use based on inputClass prop
69
+ const computedClass = computed(() => {
70
+ if (props.inputClass === null) return undefined
71
+ if (props.inputClass !== undefined) return props.inputClass
72
+ return attrs.class as string | undefined
73
+ })
74
+
52
75
  const getMetaFromArray = inject<Ref<(name: string) => FieldMeta | null> | null>(
53
76
  "getMetaFromArray",
54
77
  null
55
78
  )
56
79
 
57
80
  const meta = computed(() => {
58
- if (getMetaFromArray?.value && getMetaFromArray.value(props.name)) {
81
+ if (getMetaFromArray?.value && getMetaFromArray.value(props.name as DeepKeys<From>)) {
59
82
  return getMetaFromArray.value(propsName.value)
60
83
  }
61
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
 
@@ -3,8 +3,18 @@
3
3
  <div :class="$attrs.class">
4
4
  <OmegaInputVuetify
5
5
  v-if="vuetified"
6
- v-bind="{ ...$attrs, ...inputProps }"
7
- />
6
+ v-bind="{ ...attrsWithoutClass, ...inputProps, class: props.inputClass }"
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, 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"
@@ -33,6 +43,7 @@ const props = withDefaults(
33
43
  type?: TypeOverride
34
44
  validators?: FieldValidators<From>
35
45
  required?: boolean
46
+ inputClass?: string | null
36
47
 
37
48
  register: (
38
49
  field: ComputedRef<{
@@ -49,7 +60,8 @@ const props = withDefaults(
49
60
  required: undefined,
50
61
  type: undefined,
51
62
  options: undefined,
52
- validators: undefined
63
+ validators: undefined,
64
+ inputClass: undefined
53
65
  }
54
66
  )
55
67
 
@@ -57,6 +69,14 @@ const isRequired = computed(() => props.required ?? props?.meta?.required)
57
69
 
58
70
  const instance = getCurrentInstance()
59
71
  const vuetified = instance?.appContext.components["VTextField"]
72
+ const attrs = useAttrs()
73
+ const slots = useSlots()
74
+
75
+ // Create attrs without the class property to avoid duplication
76
+ const attrsWithoutClass = computed(() => {
77
+ const { class: _, ...rest } = attrs
78
+ return rest
79
+ })
60
80
 
61
81
  const id = useId()
62
82
 
@@ -75,7 +95,6 @@ const fieldType = computed(() => {
75
95
 
76
96
  props.register(computed(() => ({ name: props.field.name, label: props.label, id })))
77
97
 
78
- const fieldValue = computed(() => fieldState.value.value)
79
98
  // workaround strange tanstack form issue where the errors key becomes undefined ???
80
99
  const _errors = computed(() => fieldState.value.meta.errors ?? [])
81
100
  const errors = computed(() =>
@@ -140,8 +159,10 @@ const inputProps: ComputedRef<InputProps<From, Name>> = computed(() => ({
140
159
  errorMessages: errors.value,
141
160
  error: !!errors.value.length,
142
161
  type: fieldType.value,
143
- label: `${props.label}${isRequired.value ? " *" : ""}`,
144
- options: props.options
162
+ // Only add asterisk if label slot is not provided (slot has full control)
163
+ label: slots.label ? props.label : `${props.label}${isRequired.value ? " *" : ""}`,
164
+ options: props.options,
165
+ inputClass: props.inputClass
145
166
  },
146
167
 
147
168
  state: props.state,
@@ -30,7 +30,6 @@
30
30
  */
31
31
  /* eslint-disable @typescript-eslint/no-explicit-any */
32
32
  import { useStore } from "@tanstack/vue-form"
33
- import { defineSlots } from "vue"
34
33
  import { usePreventClose } from "./blockDialog"
35
34
  import { getOmegaStore } from "./getOmegaStore"
36
35
  import { type DefaultTypeProps, type OmegaFormApi, type OmegaFormState } from "./OmegaFormStuff"
@@ -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
  }>