@teamnovu/nuxt-statamic-formbuilder 1.4.2 → 1.4.3

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.
@@ -36,6 +36,7 @@
36
36
  <script setup>
37
37
  import { inject, ref } from "vue";
38
38
  import { formBuilderStateKey } from "../../injectionKeys";
39
+ import { fieldHasRequiredRule } from "../../utils/fieldHasRequiredRule";
39
40
  import { useFieldConditions } from "../composables/useFieldConditions";
40
41
  import { resolveFormField } from "../composables/useFormFieldRegistry";
41
42
  const props = defineProps({
@@ -59,7 +60,10 @@ const slotBindings = (field) => ({
59
60
  id: field.handle,
60
61
  ariaLabel: field.display ?? field.handle,
61
62
  rules: {
62
- required: props.form?.rules?.[field.handle]?.includes("required")
63
+ required: isVisible(field) && fieldHasRequiredRule(
64
+ props.form?.rules?.[field.handle],
65
+ state.value
66
+ )
63
67
  }
64
68
  },
65
69
  error: props.validationErrors?.[field.handle] ?? props.error?.[field.handle] ?? null
@@ -1,7 +1,7 @@
1
1
  import * as v from 'valibot';
2
2
  import type { MaybeRefOrGetter, Ref } from 'vue';
3
3
  import type { FormBuilderConfiguration, FormBuilderField, InputRules } from '../../types.js';
4
- export declare function useFormValidation(fieldsInput: MaybeRefOrGetter<readonly FormBuilderField[]>, formRules: FormBuilderConfiguration['rules'], _state?: Ref<Record<string, unknown>>): {
4
+ export declare function useFormValidation(fieldsInput: MaybeRefOrGetter<readonly FormBuilderField[]>, formRules: FormBuilderConfiguration['rules'], stateInput?: Ref<Record<string, unknown>>): {
5
5
  schema: import("vue").ComputedRef<v.ObjectSchema<Record<string, v.BaseSchema<unknown, unknown, v.BaseIssue<unknown>>>, undefined>>;
6
6
  validationErrors: Ref<Record<string, string>, Record<string, string>>;
7
7
  parseRules: (rulesInput?: string | string[]) => InputRules;
@@ -2,10 +2,17 @@ import * as v from "valibot";
2
2
  import { useI18n } from "vue-i18n";
3
3
  import { computed, ref, toValue } from "vue";
4
4
  import { isDisplayOrSpacerField } from "../../types.js";
5
- export function useFormValidation(fieldsInput, formRules, _state) {
5
+ import { fieldHasRequiredRule } from "../../utils/fieldHasRequiredRule.js";
6
+ import { useFieldConditions } from "./useFieldConditions.js";
7
+ export function useFormValidation(fieldsInput, formRules, stateInput) {
6
8
  const { t } = useI18n();
7
9
  const fields = computed(() => toValue(fieldsInput) ?? []);
8
10
  const validationErrors = ref({});
11
+ const formState = computed(() => toValue(stateInput) ?? {});
12
+ const { visibilityMap } = useFieldConditions(
13
+ () => [...fields.value],
14
+ formState
15
+ );
9
16
  const parseRules = (rulesInput) => {
10
17
  if (!rulesInput) {
11
18
  return {};
@@ -63,7 +70,7 @@ export function useFormValidation(fieldsInput, formRules, _state) {
63
70
  const buildFieldSchema = (field) => {
64
71
  const rules = getRulesForField(field);
65
72
  const normalizedType = normalizeFieldType(field, rules);
66
- const isRequired = rules.required === true || rules.accepted === true;
73
+ const isRequired = rules.required === true || rules.accepted === true || fieldHasRequiredRule(formRules?.[field.handle], formState.value);
67
74
  const buildStringSchema = () => {
68
75
  let stringSchema2 = v.union([
69
76
  v.pipe(v.string()),
@@ -154,6 +161,9 @@ export function useFormValidation(fieldsInput, formRules, _state) {
154
161
  if (isDisplayOrSpacerField(field)) {
155
162
  return;
156
163
  }
164
+ if (stateInput && !visibilityMap.value[field.handle]) {
165
+ return;
166
+ }
157
167
  schemaEntries[field.handle] = buildFieldSchema(field);
158
168
  });
159
169
  return v.object(schemaEntries);
@@ -97,7 +97,7 @@ export type FormBuilderConfiguration = {
97
97
  title?: string | null;
98
98
  honeypot: string | null;
99
99
  rules: {
100
- [key: string]: string;
100
+ [key: string]: string | string[];
101
101
  };
102
102
  } & ({
103
103
  sections: Array<{
@@ -0,0 +1 @@
1
+ export declare function fieldHasRequiredRule(rules?: string | string[], state?: Record<string, unknown>): boolean;
@@ -0,0 +1,23 @@
1
+ export function fieldHasRequiredRule(rules, state = {}) {
2
+ if (!rules) {
3
+ return false;
4
+ }
5
+ const ruleList = Array.isArray(rules) ? rules : rules.split("|");
6
+ return ruleList.some((rule) => {
7
+ if (rule === "required") {
8
+ return true;
9
+ }
10
+ if (!rule.startsWith("required_if:")) {
11
+ return false;
12
+ }
13
+ const [field, ...values] = rule.slice("required_if:".length).split(",");
14
+ if (!field || values.length === 0) {
15
+ return false;
16
+ }
17
+ const fieldValue = state[field];
18
+ if (Array.isArray(fieldValue)) {
19
+ return fieldValue.some((value) => values.includes(String(value)));
20
+ }
21
+ return values.includes(String(fieldValue ?? ""));
22
+ });
23
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teamnovu/nuxt-statamic-formbuilder",
3
- "version": "1.4.2",
3
+ "version": "1.4.3",
4
4
  "description": "Headless Nuxt form builder with Statamic submit adapter",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/teamnovu/nuxt-statamic-formbuilder#readme",
@@ -80,12 +80,15 @@
80
80
  "eslint": "^10.0.2",
81
81
  "nuxt": "^4.3.1",
82
82
  "typescript": "^5.9.3",
83
+ "vitest": "^5.0.1",
83
84
  "vue": "^3.5.13",
84
85
  "vue-i18n": "^11.4.6",
85
86
  "vue-tsc": "^3.3.7"
86
87
  },
87
88
  "scripts": {
88
89
  "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare",
89
- "lint": "eslint ."
90
+ "lint": "eslint .",
91
+ "test": "vitest run",
92
+ "test:watch": "vitest"
90
93
  }
91
94
  }