sit-onyx 1.1.0-dev-20250926072651 → 1.1.0-dev-20250926121514

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import { RequiredProp } from '../../composables/required.js';
2
- import { CustomValidityProp } from '../../composables/useCustomValidity.js';
2
+ import { CustomValidityProp } from '../../composables/useFormElementError.js';
3
3
  import { AutofocusProp, BaseSelectOption, Nullable, Orientation, SelectOptionValue } from '../../types/index.js';
4
4
  import { SharedFormElementProps } from '../OnyxFormElement/types.js';
5
5
  export type OnyxCheckboxGroupProps<TValue extends SelectOptionValue = SelectOptionValue> = Pick<BaseSelectOption, "truncation"> & Pick<SharedFormElementProps, "label" | "labelTooltip" | "hideLabel" | "density" | "skeleton" | "disabled" | "requiredMarker"> & {
@@ -1,4 +1,4 @@
1
- import { FormMessages } from '../../composables/useCustomValidity.js';
1
+ import { FormMessages } from '../../composables/useFormElementError.js';
2
2
  type __VLS_Props = {
3
3
  /**
4
4
  * The given component will be shown inside a tooltip when
@@ -1,4 +1,4 @@
1
- import { FormMessages } from '../../composables/useCustomValidity.js';
1
+ import { FormMessages } from '../../composables/useFormElementError.js';
2
2
  type __VLS_Props = {
3
3
  /**
4
4
  * Message to display.
@@ -1,6 +1,6 @@
1
1
  import { DensityProp } from '../../composables/density.js';
2
2
  import { RequiredProp } from '../../composables/required.js';
3
- import { CustomMessageType, CustomValidityProp, FormMessages } from '../../composables/useCustomValidity.js';
3
+ import { CustomMessageType, CustomValidityProp, FormMessages } from '../../composables/useFormElementError.js';
4
4
  import { SharedTextInputProps } from '../../composables/useLenientMaxLengthValidation.js';
5
5
  import { SkeletonInjected } from '../../composables/useSkeletonState.js';
6
6
  import { AutofocusProp, Nullable } from '../../types/index.js';
@@ -1,94 +1,21 @@
1
1
  import { MaybeRefOrGetter } from 'vue';
2
- import { DateValue, OnyxDatePickerProps } from '../components/OnyxDatePicker/types.js';
3
- import { InputType } from '../components/OnyxInput/types.js';
4
- import { default as enUS } from '../i18n/locales/en-US.json';
5
- import { MaxLength } from './useLenientMaxLengthValidation.js';
6
- export type CustomMessageType = string | FormMessages;
7
- export type CustomValidityProp = {
8
- /**
9
- * Custom error message to show. Takes precedence over intrinsic error messages.
10
- */
11
- error?: CustomMessageType;
12
- };
13
- export type UseCustomValidityOptions = {
2
+ export type UseFormValidityOptions<TProps extends Record<string, MaybeRefOrGetter<unknown>> = Record<string, MaybeRefOrGetter<unknown>>> = {
14
3
  /**
15
4
  * Explicitly set custom error. Any non-nullish value will set the input to be invalid.
16
- * If both, `options.customError` and `options.props.error` are provided, the message from the props will take precedence.
17
5
  */
18
- error?: MaybeRefOrGetter<CustomMessageType | undefined>;
6
+ error?: MaybeRefOrGetter<string | undefined>;
19
7
  /**
20
- * Component props as defined with `const props = defineProps()`.
21
- * These prop values are used for the error messages of the native validation errors.
8
+ * Props that influence native validation state. These are not used directly, but watched to trigger a re-evaluation of validation state.
9
+ * E.g. when `required` is changed from `true` to `false` the state needs to be re-evaluated.
22
10
  */
23
- props: {
24
- error?: CustomMessageType;
25
- modelValue?: unknown;
26
- type?: InputType | OnyxDatePickerProps["type"];
27
- maxlength?: MaxLength;
28
- minlength?: number;
29
- min?: DateValue;
30
- max?: DateValue;
31
- validStepSize?: number;
32
- };
11
+ props: TProps;
33
12
  /**
34
13
  * Component emit as defined with `const emit = defineEmits()`
35
14
  */
36
15
  emit: (evt: "validityChange", validity: ValidityState) => void;
37
16
  };
38
17
  export type InputValidationElement = Pick<HTMLInputElement, "validity" | "setCustomValidity">;
39
- /**
40
- * Input types that have a translation for their validation error message.
41
- */
42
- export declare const TRANSLATED_INPUT_TYPES: (keyof typeof enUS.validations.typeMismatch)[];
43
- export type TranslatedInputType = (typeof TRANSLATED_INPUT_TYPES)[number];
44
- /**
45
- * Translated messages that inform about the state of a form element.
46
- */
47
- export type FormMessages = {
48
- /**
49
- * A short message preview to inform the user about the input state.
50
- * It's usually shown directly underneath the input field.
51
- */
52
- shortMessage: string;
53
- /**
54
- * An extended informative message to provide more details.
55
- * It's usually shown in a tooltip next to the shortMessage.
56
- */
57
- longMessage?: string;
58
- /**
59
- * Will visually hide the message.
60
- */
61
- hidden?: boolean;
62
- };
63
- /**
64
- * Transforms a customMessage into the format needed to display an error preview and extended message
65
- */
66
- export declare const getFormMessages: (customMessage?: CustomMessageType) => FormMessages | undefined;
67
- /**
68
- * Returns a string combining short + long message or just the customMessage if it was provided as single string.
69
- * Will be used e.g. for customInvalidity and showing a tooltip e.g. in RadioButtons
70
- */
71
- export declare const getFormMessageText: (error?: CustomMessageType) => string | undefined;
72
- /**
73
- * Composable for unified handling of custom messages for form components.
74
- * Will call `setCustomValidity()` accordingly and emit the "validityChange" event
75
- * whenever the input value / error changes.
76
- *
77
- * @example
78
- * ```html
79
- * <script lang="ts" setup>
80
- * const props = defineProps<CustomValidityProp>();
81
- * const emit = defineEmits<{ validityChange: [validity: ValidityState] }>();
82
- *
83
- * const { vCustomValidity } = useCustomValidity({ props, emit });
84
- * </script>
85
- *
86
- * <template>
87
- * <input v-custom-validity />
88
- * </template>
89
- * ```
90
- */
91
- export declare const useCustomValidity: (options: UseCustomValidityOptions) => {
18
+ export declare const useCustomValidity: <TProps extends Record<string, MaybeRefOrGetter<unknown>>>(options: Omit<UseFormValidityOptions<TProps>, "emit">) => {
92
19
  /**
93
20
  * Directive to set the custom error message and emit validityChange event.
94
21
  */
@@ -96,7 +23,7 @@ export declare const useCustomValidity: (options: UseCustomValidityOptions) => {
96
23
  mounted: (el: InputValidationElement) => void;
97
24
  };
98
25
  /**
99
- * A custom error or the default translation of the first invalid state if one exists.
26
+ * validityState of the html element.
100
27
  */
101
- errorMessages: import('vue').ComputedRef<FormMessages | undefined>;
28
+ validityState: import('vue').Ref<Record<keyof ValidityState, boolean> | undefined, Record<keyof ValidityState, boolean> | undefined>;
102
29
  };
@@ -0,0 +1,69 @@
1
+ import { MaybeRefOrGetter } from 'vue';
2
+ import { DateValue, OnyxDatePickerProps } from '../components/OnyxDatePicker/types.js';
3
+ import { InputType } from '../components/OnyxInput/types.js';
4
+ import { default as enUS } from '../i18n/locales/en-US.json';
5
+ import { UseFormValidityOptions } from './useCustomValidity.js';
6
+ import { MaxLength } from './useLenientMaxLengthValidation.js';
7
+ export type CustomMessageType = string | FormMessages;
8
+ export type FormMessages = {
9
+ /**
10
+ * A short message preview to inform the user about the input state.
11
+ * It's usually shown directly underneath the input field.
12
+ */
13
+ shortMessage: string;
14
+ /**
15
+ * An extended informative message to provide more details.
16
+ * It's usually shown in a tooltip next to the shortMessage.
17
+ */
18
+ longMessage?: string;
19
+ /**
20
+ * Will visually hide the message.
21
+ */
22
+ hidden?: boolean;
23
+ };
24
+ export type CustomValidityProp = {
25
+ /**
26
+ * Custom error message to show. Takes precedence over intrinsic error messages.
27
+ */
28
+ error?: CustomMessageType;
29
+ };
30
+ export type FormValidationProps = {
31
+ error?: CustomMessageType;
32
+ modelValue?: unknown;
33
+ type?: InputType | OnyxDatePickerProps["type"];
34
+ maxlength?: MaxLength;
35
+ minlength?: number;
36
+ min?: DateValue;
37
+ max?: DateValue;
38
+ validStepSize?: number;
39
+ };
40
+ export type UseFormElementErrorOptions = Omit<UseFormValidityOptions<FormValidationProps>, "error"> & {
41
+ props: FormValidationProps;
42
+ error?: MaybeRefOrGetter<CustomMessageType | undefined>;
43
+ };
44
+ /**
45
+ * Input types that have a translation for their validation error message.
46
+ */
47
+ export declare const TRANSLATED_INPUT_TYPES: (keyof typeof enUS.validations.typeMismatch)[];
48
+ export type TranslatedInputType = (typeof TRANSLATED_INPUT_TYPES)[number];
49
+ /**
50
+ * Transforms a customMessage into the format needed to display an error preview and extended message
51
+ */
52
+ export declare const getFormMessages: (customMessage?: CustomMessageType) => FormMessages | undefined;
53
+ /**
54
+ * Returns a string combining short + long message or just the customMessage if it was provided as single string.
55
+ * Will be used e.g. for customInvalidity and showing a tooltip e.g. in RadioButtons
56
+ */
57
+ export declare const getFormMessageText: (error?: CustomMessageType) => string | undefined;
58
+ export declare const useFormElementError: (options: UseFormElementErrorOptions) => {
59
+ /**
60
+ * Directive to set the custom error message and emit validityChange event.
61
+ */
62
+ vCustomValidity: {
63
+ mounted: (el: import('./useCustomValidity.js').InputValidationElement) => void;
64
+ };
65
+ /**
66
+ * A custom error or the default translation of the first invalid state if one exists.
67
+ */
68
+ errorMessages: import('vue').ComputedRef<FormMessages | undefined>;
69
+ };
@@ -4158,6 +4158,23 @@ const useRequired = (props, requiredMarker) => ({
4158
4158
  const isValidDate = (date) => {
4159
4159
  return date instanceof Date && !isNaN(date);
4160
4160
  };
4161
+ const getValidityStateProperties = () => Object.entries(Object.getOwnPropertyDescriptors(ValidityState.prototype)).filter(([_, value]) => value.enumerable).map(([key]) => key);
4162
+ const transformValidityStateToObject = (validityState) => {
4163
+ return getValidityStateProperties().reduce(
4164
+ (validityStateCopy, key) => {
4165
+ validityStateCopy[key] = validityState[key];
4166
+ return validityStateCopy;
4167
+ },
4168
+ {}
4169
+ );
4170
+ };
4171
+ const getFirstInvalidType = (validity) => {
4172
+ if (validity.valueMissing) return "valueMissing";
4173
+ const availableValidityTypes = getValidityStateProperties().filter((key) => key !== "valid").sort();
4174
+ for (const type of availableValidityTypes) {
4175
+ if (type in validity && validity[type]) return type;
4176
+ }
4177
+ };
4161
4178
  const areObjectsFlatEqual = (obj1, obj2) => {
4162
4179
  const noUndefinedEntries1 = Object.entries(obj1).filter(([_, value]) => value !== void 0);
4163
4180
  const noUndefinedEntries2 = Object.entries(obj2).filter(([_, value]) => value !== void 0);
@@ -4199,22 +4216,38 @@ const asArray = (value, keepNullish = false) => {
4199
4216
  }
4200
4217
  return [value];
4201
4218
  };
4202
- const getValidityStateProperties = () => Object.entries(Object.getOwnPropertyDescriptors(ValidityState.prototype)).filter(([_, value]) => value.enumerable).map(([key]) => key);
4203
- const transformValidityStateToObject = (validityState) => {
4204
- return getValidityStateProperties().reduce(
4205
- (validityStateCopy, key) => {
4206
- validityStateCopy[key] = validityState[key];
4207
- return validityStateCopy;
4208
- },
4209
- {}
4210
- );
4211
- };
4212
- const getFirstInvalidType = (validity) => {
4213
- if (validity.valueMissing) return "valueMissing";
4214
- const availableValidityTypes = getValidityStateProperties().filter((key) => key !== "valid").sort();
4215
- for (const type of availableValidityTypes) {
4216
- if (type in validity && validity[type]) return type;
4217
- }
4219
+ const useCustomValidity = (options) => {
4220
+ const validityState = ref();
4221
+ const vCustomValidity = {
4222
+ mounted: (el) => {
4223
+ watch(
4224
+ // we need to watch all props instead of only modelValue so the validity is re-checked
4225
+ // when the validation rules change
4226
+ [() => toValue(options.error), () => toValue(options.props)],
4227
+ () => {
4228
+ el.setCustomValidity(toValue(options.error) ?? "");
4229
+ const newValidityState = transformValidityStateToObject(el.validity);
4230
+ if (!validityState.value && newValidityState.valid) return;
4231
+ if (validityState.value && areObjectsFlatEqual(newValidityState, validityState.value)) {
4232
+ return;
4233
+ }
4234
+ validityState.value = newValidityState;
4235
+ },
4236
+ // We use "post" flush timing, to ensure the DOM is up-to-date and the elements validity state is in sync.
4237
+ { immediate: true, deep: true, flush: "post" }
4238
+ );
4239
+ }
4240
+ };
4241
+ return {
4242
+ /**
4243
+ * Directive to set the custom error message and emit validityChange event.
4244
+ */
4245
+ vCustomValidity,
4246
+ /**
4247
+ * validityState of the html element.
4248
+ */
4249
+ validityState
4250
+ };
4218
4251
  };
4219
4252
  const TRANSLATED_INPUT_TYPES = Object.keys(
4220
4253
  enUS.validations.typeMismatch
@@ -4237,48 +4270,30 @@ const getFormMessageText = (error) => {
4237
4270
  const { shortMessage, longMessage } = error;
4238
4271
  return `${shortMessage}: ${longMessage}`;
4239
4272
  };
4240
- const useCustomValidity = (options) => {
4273
+ const useFormElementError = (options) => {
4241
4274
  const { t, locale } = injectI18n();
4242
- const validityState = ref();
4243
4275
  const isDirty = ref(false);
4244
- const error = computed(() => options.props.error || toValue(options.error));
4276
+ const { vCustomValidity, validityState } = useCustomValidity({
4277
+ error: computed(() => getFormMessageText(options.props.error || toValue(options.error))),
4278
+ props: options.props
4279
+ });
4245
4280
  watch(
4246
4281
  () => options.props.modelValue,
4247
4282
  () => isDirty.value = true,
4248
4283
  { once: true }
4249
4284
  );
4250
- const vCustomValidity = {
4251
- mounted: (el) => {
4252
- watch(
4253
- // we need to watch all props instead of only modelValue so the validity is re-checked
4254
- // when the validation rules change
4255
- [() => options.props, error],
4256
- () => {
4257
- el.setCustomValidity(getFormMessageText(error.value) ?? "");
4258
- const newValidityState = transformValidityStateToObject(el.validity);
4259
- if (!validityState.value && newValidityState.valid) return;
4260
- if (validityState.value && areObjectsFlatEqual(newValidityState, validityState.value)) {
4261
- return;
4262
- }
4263
- validityState.value = newValidityState;
4264
- },
4265
- // We use "post" flush timing, to ensure the DOM is up-to-date and the elements validity state is in sync.
4266
- { immediate: true, deep: true, flush: "post" }
4267
- );
4268
- watch(
4269
- [error, validityState, isDirty],
4270
- () => {
4271
- if (!isDirty.value || !validityState.value) return;
4272
- options.emit("validityChange", validityState.value);
4273
- },
4274
- { immediate: true }
4275
- );
4276
- }
4277
- };
4285
+ watch(
4286
+ [validityState, isDirty],
4287
+ () => {
4288
+ if (!isDirty.value || !validityState.value) return;
4289
+ options.emit("validityChange", validityState.value);
4290
+ },
4291
+ { immediate: true }
4292
+ );
4278
4293
  const errorMessages = computed(() => {
4279
4294
  if (!validityState.value || validityState.value.valid) return;
4280
4295
  const errorType = getFirstInvalidType(validityState.value);
4281
- const errors = getFormMessages(error.value);
4296
+ const errors = getFormMessages(options.props.error || toValue(options.error));
4282
4297
  if (errors || errorType === "customError") {
4283
4298
  if (!errors) return;
4284
4299
  return errors;
@@ -4610,7 +4625,7 @@ const _sfc_main$_ = /* @__PURE__ */ defineComponent({
4610
4625
  key: "modelValue",
4611
4626
  default: false
4612
4627
  });
4613
- const { vCustomValidity, errorMessages } = useCustomValidity({ props, emit });
4628
+ const { vCustomValidity, errorMessages } = useFormElementError({ props, emit });
4614
4629
  const { densityClass } = useDensity(props);
4615
4630
  const { disabled, requiredMarker } = useFormContext(props);
4616
4631
  const skeleton = useSkeletonContext(props);
@@ -6218,7 +6233,7 @@ const _sfc_main$Q = /* @__PURE__ */ defineComponent({
6218
6233
  const props = __props;
6219
6234
  const emit = __emit;
6220
6235
  const { t } = injectI18n();
6221
- const { vCustomValidity, errorMessages } = useCustomValidity({ props, emit });
6236
+ const { vCustomValidity, errorMessages } = useFormElementError({ props, emit });
6222
6237
  const successMessages = computed(() => getFormMessages(props.success));
6223
6238
  const messages = computed(() => getFormMessages(props.message));
6224
6239
  const { disabled, showError } = useFormContext(props);
@@ -8144,7 +8159,7 @@ const _sfc_main$I = /* @__PURE__ */ defineComponent({
8144
8159
  const props = __props;
8145
8160
  const emit = __emit;
8146
8161
  const { rootAttrs, restAttrs } = useRootAttrs();
8147
- const { vCustomValidity, errorMessages } = useCustomValidity({ props, emit });
8162
+ const { vCustomValidity, errorMessages } = useFormElementError({ props, emit });
8148
8163
  const successMessages = computed(() => getFormMessages(props.success));
8149
8164
  const messages = computed(() => getFormMessages(props.message));
8150
8165
  const { densityClass } = useDensity(props);
@@ -8656,7 +8671,7 @@ const _sfc_main$C = /* @__PURE__ */ defineComponent({
8656
8671
  const { t } = injectI18n();
8657
8672
  const { maxLength, maxLengthError } = useLenientMaxLengthValidation({ modelValue, props });
8658
8673
  const error = computed(() => props.error ?? maxLengthError.value);
8659
- const { vCustomValidity, errorMessages } = useCustomValidity({ props, emit, error });
8674
+ const { vCustomValidity, errorMessages } = useFormElementError({ props, emit, error });
8660
8675
  const successMessages = computed(() => getFormMessages(props.success));
8661
8676
  const messages = computed(() => getFormMessages(props.message));
8662
8677
  const { densityClass } = useDensity(props);
@@ -10740,7 +10755,7 @@ const _sfc_main$i = /* @__PURE__ */ defineComponent({
10740
10755
  const props = __props;
10741
10756
  const emit = __emit;
10742
10757
  const { rootAttrs, restAttrs } = useRootAttrs();
10743
- const { vCustomValidity, errorMessages } = useCustomValidity({ props, emit });
10758
+ const { vCustomValidity, errorMessages } = useFormElementError({ props, emit });
10744
10759
  const { densityClass } = useDensity(props);
10745
10760
  const { disabled } = useFormContext(props);
10746
10761
  const skeleton = useSkeletonContext(props);
@@ -11368,7 +11383,7 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
11368
11383
  const skeleton = useSkeletonContext(props);
11369
11384
  const errorClass = useErrorClass(showError);
11370
11385
  const { densityClass } = useDensity(props);
11371
- const { vCustomValidity, errorMessages } = useCustomValidity({ props, emit });
11386
+ const { vCustomValidity, errorMessages } = useFormElementError({ props, emit });
11372
11387
  const successMessages = computed(() => getFormMessages(props.success));
11373
11388
  const messages = computed(() => getFormMessages(props.message));
11374
11389
  const { rootAttrs, restAttrs } = useRootAttrs();
@@ -11580,7 +11595,7 @@ const _sfc_main$b = /* @__PURE__ */ defineComponent({
11580
11595
  const { densityClass } = useDensity(props);
11581
11596
  const { disabled, showError, requiredMarker } = useFormContext(props);
11582
11597
  const { requiredMarkerClass, requiredTypeClass } = useRequired(props, requiredMarker);
11583
- const { vCustomValidity, errorMessages } = useCustomValidity({ props, emit });
11598
+ const { vCustomValidity, errorMessages } = useFormElementError({ props, emit });
11584
11599
  const shownErrorMessages = computed(
11585
11600
  () => showError.value !== false ? errorMessages.value : void 0
11586
11601
  );
@@ -12044,7 +12059,7 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
12044
12059
  const { formatFileSize } = useFileSize();
12045
12060
  const skeleton = useSkeletonContext(props);
12046
12061
  const error = computed(() => props.status?.color === "danger" ? props.status.text : void 0);
12047
- const { vCustomValidity } = useCustomValidity({ props: {}, emit, error });
12062
+ const { vCustomValidity } = useFormElementError({ props: {}, emit, error });
12048
12063
  const link2 = computed(() => {
12049
12064
  if (!props.link) return;
12050
12065
  return extractLinkProps(props.link);
@@ -12764,7 +12779,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
12764
12779
  const { rootAttrs, restAttrs } = useRootAttrs();
12765
12780
  const { maxLength, maxLengthError } = useLenientMaxLengthValidation({ props, modelValue });
12766
12781
  const error = computed(() => props.error ?? maxLengthError.value);
12767
- const { vCustomValidity, errorMessages } = useCustomValidity({ props, emit, error });
12782
+ const { vCustomValidity, errorMessages } = useFormElementError({ props, emit, error });
12768
12783
  const { densityClass } = useDensity(props);
12769
12784
  const successMessages = computed(() => getFormMessages(props.success));
12770
12785
  const messages = computed(() => getFormMessages(props.message));