notform 1.0.0 → 1.0.2

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.
package/dist/index.d.ts CHANGED
@@ -5,9 +5,9 @@ import { PartialDeep, Paths as Paths$1 } from "type-fest";
5
5
 
6
6
  //#region src/types/shared.d.ts
7
7
  /**
8
- * Defines the strategy for when validation checks are executed.
9
- * - 'lazy': Validation occurs only on blur or form submission.
10
- * - 'eager': Validation occurs immediately on every value change.
8
+ * Validation execution strategy.
9
+ * - `lazy`: Validates on blur or submission.
10
+ * - `eager`: Validates on blur, then on every change if an error exists.
11
11
  */
12
12
  type ValidationMode = 'lazy' | 'eager';
13
13
  /**
@@ -262,6 +262,8 @@ type NotFieldSlots = {
262
262
  type NotMessageProps = {
263
263
  /** The name/path of the field whose error message should be displayed */
264
264
  name: string;
265
+ /** HTML Tag `NotMessage` should render as - default is `span`. */
266
+ as?: string;
265
267
  };
266
268
  /**
267
269
  * State provided to the NotMessage component's scope.
@@ -275,7 +277,9 @@ type NotMessageContext = {
275
277
  */
276
278
  type NotMessageSlots = {
277
279
  /** The default slot receives the error message context for custom rendering */
278
- default: (props: NotMessageContext) => VNodeChild;
280
+ default: (props: NotMessageContext & {
281
+ attributes?: ReturnType<typeof useAttrs>;
282
+ }) => VNodeChild;
279
283
  };
280
284
  //#endregion
281
285
  //#region src/components/not-form.vue.d.ts
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { computed, createBlock, createElementVNode, defineComponent, guardReactiveProps, inject, mergeProps, nextTick, normalizeProps, onMounted, openBlock, provide, reactive, ref, renderSlot, resolveDynamicComponent, toDisplayString, toValue, unref, useAttrs, useId, vShow, withCtx, withDirectives } from "vue";
1
+ import { computed, createBlock, createTextVNode, defineComponent, guardReactiveProps, inject, mergeProps, nextTick, normalizeProps, onMounted, openBlock, provide, reactive, ref, renderSlot, resolveDynamicComponent, toDisplayString, toValue, unref, useAttrs, useId, vShow, withCtx, withDirectives } from "vue";
2
2
  import { getProperty, parsePath, setProperty } from "dot-prop";
3
3
 
4
4
  //#region src/utils/not-form-context.ts
@@ -124,19 +124,24 @@ var not_field_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defi
124
124
  methods: {
125
125
  onBlur: function() {
126
126
  touchField(props.name);
127
- if (mode === "eager" || validateOn.includes("blur")) validate();
127
+ if (!validateOn.includes("blur")) return;
128
+ validate();
128
129
  },
129
130
  onChange: function() {
130
131
  dirtyField(props.name);
131
- if (mode === "eager" || validateOn.includes("change")) validate();
132
+ if (!validateOn.includes("change")) return;
133
+ if (mode === "lazy") return;
134
+ if (mode === "eager" && getFieldErrors(props.name).length > 0) validate();
132
135
  },
133
136
  onInput: function() {
134
137
  dirtyField(props.name);
135
- if (mode === "eager" || validateOn.includes("input")) validate();
138
+ if (!validateOn.includes("input")) return;
139
+ if (mode === "lazy") return;
140
+ if (mode === "eager" && getFieldErrors(props.name).length > 0) validate();
136
141
  },
137
142
  onFocus: function() {
138
- dirtyField(props.name);
139
- if (mode === "eager" || validateOn.includes("focus")) validate();
143
+ if (!validateOn.includes("focus")) return;
144
+ validate();
140
145
  }
141
146
  }
142
147
  });
@@ -162,15 +167,23 @@ var not_field_default = not_field_vue_vue_type_script_setup_true_lang_default;
162
167
  */
163
168
  var not_message_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
164
169
  __name: "not-message",
165
- props: { name: {
166
- type: String,
167
- required: true
168
- } },
170
+ props: {
171
+ name: {
172
+ type: String,
173
+ required: true
174
+ },
175
+ as: {
176
+ type: String,
177
+ required: false,
178
+ default: "span"
179
+ }
180
+ },
169
181
  setup(__props) {
170
182
  const props = __props;
171
183
  /**
172
184
  * Slots provided by the Message component.
173
185
  */
186
+ const attributes = useAttrs();
174
187
  const formID = inject(CURRENT_NOT_FORM_ID_KEY);
175
188
  if (!formID) throw new Error("Message must be used inside a NotForm component");
176
189
  const { getFieldErrors } = withContext(formID);
@@ -178,8 +191,15 @@ var not_message_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ de
178
191
  * The reactive state provided to the component's slot.
179
192
  */
180
193
  const context = reactive({ message: computed(() => getFieldErrors(props.name).map((error) => error.message)[0]) });
194
+ const mergedAttrs = computed(() => ({
195
+ ...context,
196
+ attributes
197
+ }));
181
198
  return (_ctx, _cache) => {
182
- return renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(context)), () => [withDirectives(createElementVNode("span", null, toDisplayString(context.message), 513), [[vShow, context.message]])]);
199
+ return renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(mergedAttrs.value)), () => [withDirectives((openBlock(), createBlock(resolveDynamicComponent(props.as), normalizeProps(guardReactiveProps(unref(attributes))), {
200
+ default: withCtx(() => [createTextVNode(toDisplayString(context.message), 1)]),
201
+ _: 1
202
+ }, 16)), [[vShow, context.message]])]);
183
203
  };
184
204
  }
185
205
  });
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
8
- "version": "1.0.0",
8
+ "version": "1.0.2",
9
9
  "description": "Vue Forms Without the Friction",
10
10
  "author": "Favour Emeka <favorodera@gmail.com>",
11
11
  "license": "MIT",