fds-vue-core 8.2.2 → 8.2.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.
@@ -83,6 +83,7 @@ declare const _default: import('vue').DefineComponent<FdsSearchSelectProps, {
83
83
  optional: boolean;
84
84
  labelLeft: boolean;
85
85
  clearButton: boolean;
86
+ displayChar: string;
86
87
  ariaLabel: string;
87
88
  maskOptions: {
88
89
  lazy?: boolean;
@@ -127,6 +128,7 @@ declare const _default: import('vue').DefineComponent<FdsSearchSelectProps, {
127
128
  optional: boolean;
128
129
  labelLeft: boolean;
129
130
  clearButton: boolean;
131
+ displayChar: string;
130
132
  ariaLabel: string;
131
133
  maskOptions: {
132
134
  lazy?: boolean;
@@ -104,6 +104,7 @@ declare const _default: import('vue').DefineComponent<FdsSearchSelectProProps, {
104
104
  optional: boolean;
105
105
  labelLeft: boolean;
106
106
  clearButton: boolean;
107
+ displayChar: string;
107
108
  ariaLabel: string;
108
109
  maskOptions: {
109
110
  lazy?: boolean;
@@ -148,6 +149,7 @@ declare const _default: import('vue').DefineComponent<FdsSearchSelectProProps, {
148
149
  optional: boolean;
149
150
  labelLeft: boolean;
150
151
  clearButton: boolean;
152
+ displayChar: string;
151
153
  ariaLabel: string;
152
154
  maskOptions: {
153
155
  lazy?: boolean;
@@ -37,6 +37,7 @@ declare const _default: import('vue').DefineComponent<__VLS_PublicProps, {}, {},
37
37
  optional: boolean;
38
38
  labelLeft: boolean;
39
39
  clearButton: boolean;
40
+ displayChar: string;
40
41
  ariaLabel: string;
41
42
  maskOptions: {
42
43
  lazy?: boolean;
@@ -9,6 +9,8 @@ export interface FdsInputProps {
9
9
  labelLeft?: boolean;
10
10
  clearButton?: boolean;
11
11
  mask?: string | RegExp | Array<string | RegExp>;
12
+ /** Character shown for unfilled mask positions while typing (maps to IMask placeholderChar). */
13
+ displayChar?: string;
12
14
  modelValue?: string;
13
15
  value?: string;
14
16
  type?: string;
@@ -9877,12 +9877,13 @@ const _sfc_main$s = /* @__PURE__ */ vue.defineComponent({
9877
9877
  }
9878
9878
  });
9879
9879
  const _hoisted_1$j = ["for", "id"];
9880
- const _hoisted_2$f = { class: "relative" };
9881
- const _hoisted_3$f = ["type", "required", "value", "disabled", "tabindex", "aria-invalid", "aria-label", "aria-labelledby", "aria-describedby", "autocomplete", "placeholder", "pattern", "searchIcon"];
9880
+ const _hoisted_2$f = ["type", "required", "disabled", "tabindex", "aria-invalid", "aria-label", "aria-labelledby", "aria-describedby", "autocomplete", "placeholder", "pattern", "searchIcon"];
9881
+ const _hoisted_3$f = { class: "whitespace-pre text-base leading-6 tabular-nums" };
9882
9882
  const _hoisted_4$e = {
9883
9883
  key: 0,
9884
9884
  class: "text-red-700 font-bold mt-1"
9885
9885
  };
9886
+ const maskFieldPaddingClasses = "px-3 py-[calc(0.75rem-1px)]";
9886
9887
  const _sfc_main$r = /* @__PURE__ */ vue.defineComponent({
9887
9888
  ...{
9888
9889
  inheritAttrs: false
@@ -9899,6 +9900,7 @@ const _sfc_main$r = /* @__PURE__ */ vue.defineComponent({
9899
9900
  labelLeft: { type: Boolean, default: false },
9900
9901
  clearButton: { type: Boolean, default: false },
9901
9902
  mask: { default: void 0 },
9903
+ displayChar: { default: void 0 },
9902
9904
  modelValue: {},
9903
9905
  value: { default: void 0 },
9904
9906
  type: {},
@@ -9940,7 +9942,10 @@ const _sfc_main$r = /* @__PURE__ */ vue.defineComponent({
9940
9942
  const emit = __emit;
9941
9943
  const { id, type, maxlength, attrs } = useAttrsWithDefaults(props);
9942
9944
  const { t } = useFdsI18n();
9943
- const inputType = vue.computed(() => type.value ?? props.type ?? "text");
9945
+ const inputType = vue.computed(() => {
9946
+ if (props.mask) return "text";
9947
+ return type.value ?? props.type ?? "text";
9948
+ });
9944
9949
  const autoId = `fds-input-${Math.random().toString(36).slice(2, 9)}`;
9945
9950
  const inputId = vue.computed(() => id.value ?? autoId);
9946
9951
  const labelId = vue.computed(() => `${inputId.value}-label`);
@@ -10011,29 +10016,92 @@ const _sfc_main$r = /* @__PURE__ */ vue.defineComponent({
10011
10016
  return "pr-40";
10012
10017
  });
10013
10018
  const externalClass = vue.computed(() => props.class ?? attrs.class);
10014
- const inputClasses = vue.computed(() => [
10015
- "block rounded-md border border-gray-500 px-3 py-[calc(0.75rem-1px)]",
10016
- maxlength.value ? "" : "w-full",
10017
- inputPaddingRight.value,
10018
- "focus:outline-2 focus:outline-blue-500 -outline-offset-2 focus:border-transparent",
10019
- showDateIcon.value && "[&::-webkit-calendar-picker-indicator]:opacity-0 [&::-webkit-calendar-picker-indicator]:pointer-events-none",
10020
- props.disabled ? "text-gray-800 outline-dashed outline-2 outline-gray-400 cursor-not-allowed border-transparent" : "bg-white",
10021
- isInvalid.value && "outline-2 outline-red-600",
10022
- props.inputClass
10019
+ const maskDisplayValue = vue.ref("");
10020
+ const maskPlaceholderChar = vue.ref("");
10021
+ const resolvedPlaceholderChar = vue.computed(() => props.displayChar ?? props.maskOptions?.placeholderChar ?? null);
10022
+ const useMaskPlaceholderStyle = vue.computed(() => {
10023
+ if (!props.mask || !resolvedPlaceholderChar.value) return false;
10024
+ const lazy = props.maskOptions?.lazy ?? (props.displayChar ? false : true);
10025
+ return !lazy;
10026
+ });
10027
+ const maskFieldWrapperClasses = vue.computed(() => {
10028
+ if (!useMaskPlaceholderStyle.value) return void 0;
10029
+ return [
10030
+ "rounded-md border border-gray-500 bg-white bg-clip-padding",
10031
+ props.disabled && "outline-dashed outline-2 outline-gray-400 cursor-not-allowed border-transparent",
10032
+ isInvalid.value ? "outline-2 -outline-offset-2 outline-red-600" : "focus-within:outline-2 focus-within:outline-blue-500 focus-within:outline-offset-0",
10033
+ "focus-within:border-transparent"
10034
+ ];
10035
+ });
10036
+ const maskOverlayClasses = vue.computed(() => [
10037
+ "pointer-events-none absolute inset-0 z-[3] flex items-center",
10038
+ maskFieldPaddingClasses,
10039
+ inputPaddingRight.value
10023
10040
  ]);
10041
+ const maskDisplayChars = vue.computed(() => {
10042
+ const display = maskDisplayValue.value;
10043
+ const placeholder = maskPlaceholderChar.value || resolvedPlaceholderChar.value;
10044
+ if (!display || !placeholder) return [];
10045
+ return [...display].map((char) => ({
10046
+ char,
10047
+ isPlaceholder: char === placeholder
10048
+ }));
10049
+ });
10050
+ function maskCharStyle(isPlaceholder) {
10051
+ if (isPlaceholder) {
10052
+ return { color: props.disabled ? "var(--color-gray-500)" : "var(--color-gray-400)" };
10053
+ }
10054
+ return { color: props.disabled ? "var(--color-gray-800)" : "var(--color-gray-900)" };
10055
+ }
10056
+ const inputClasses = vue.computed(() => {
10057
+ const shared = [
10058
+ "block rounded-md",
10059
+ maxlength.value ? "" : "w-full",
10060
+ inputPaddingRight.value,
10061
+ showDateIcon.value && "[&::-webkit-calendar-picker-indicator]:opacity-0 [&::-webkit-calendar-picker-indicator]:pointer-events-none",
10062
+ props.inputClass
10063
+ ];
10064
+ if (useMaskPlaceholderStyle.value) {
10065
+ return [
10066
+ ...shared,
10067
+ "relative z-[2] border-0 bg-transparent shadow-none focus:outline-none",
10068
+ maskFieldPaddingClasses,
10069
+ "text-base leading-6 tabular-nums",
10070
+ props.disabled ? "cursor-not-allowed" : ""
10071
+ ];
10072
+ }
10073
+ return [
10074
+ ...shared,
10075
+ "rounded-md border border-gray-500",
10076
+ maskFieldPaddingClasses,
10077
+ "focus:outline-2 focus:outline-blue-500 -outline-offset-2 focus:border-transparent",
10078
+ props.disabled ? "text-gray-800 outline-dashed outline-2 outline-gray-400 cursor-not-allowed border-transparent" : "text-gray-900 bg-white",
10079
+ isInvalid.value && "outline-2 outline-red-600"
10080
+ ];
10081
+ });
10024
10082
  const inputStyle = vue.computed(() => {
10025
- if (maxlength.value) {
10026
- return {
10027
- width: `calc(${maxlength.value}ch + 1.5rem + 0.25rem)`,
10028
- maxWidth: "100%"
10029
- };
10083
+ const size = maxlength.value ? {
10084
+ width: `calc(${maxlength.value}ch + 1.5rem + 0.25rem)`,
10085
+ maxWidth: "100%"
10086
+ } : {};
10087
+ if (!useMaskPlaceholderStyle.value) {
10088
+ return size;
10030
10089
  }
10031
- return {};
10090
+ return {
10091
+ ...size,
10092
+ color: "transparent",
10093
+ WebkitTextFillColor: "transparent",
10094
+ caretColor: props.disabled ? "#1f2937" : "#111827"
10095
+ };
10032
10096
  });
10033
10097
  const rightIconsContainerClasses = vue.computed(() => [
10034
- "absolute flex gap-2 top-1/2 -translate-y-1/2 items-center justify-end",
10098
+ "absolute z-10 flex gap-2 top-1/2 -translate-y-1/2 items-center justify-end",
10035
10099
  showClearButton.value ? "right-2" : "right-3"
10036
10100
  ]);
10101
+ const inputBindings = vue.computed(() => ({
10102
+ ...inputAttrs.value,
10103
+ ...props.mask ? {} : { value: internalValue.value }
10104
+ }));
10037
10105
  const internalValue = vue.computed({
10038
10106
  get: () => modelValue.value !== void 0 ? modelValue.value : props.value ?? "",
10039
10107
  set: (newValue) => {
@@ -10045,6 +10113,10 @@ const _sfc_main$r = /* @__PURE__ */ vue.defineComponent({
10045
10113
  });
10046
10114
  function onClear() {
10047
10115
  internalValue.value = "";
10116
+ if (maskInstance) {
10117
+ maskInstance.value = "";
10118
+ vue.nextTick(syncMaskDisplay);
10119
+ }
10048
10120
  emit("clearInput");
10049
10121
  }
10050
10122
  function onDateIconClick() {
@@ -10073,6 +10145,23 @@ const _sfc_main$r = /* @__PURE__ */ vue.defineComponent({
10073
10145
  }
10074
10146
  const inputRef = vue.ref(null);
10075
10147
  let maskInstance = null;
10148
+ function getMaskEmittedValue(instance) {
10149
+ if (!instance) return "";
10150
+ const raw = String(instance.value ?? "");
10151
+ if (!useMaskPlaceholderStyle.value) return raw;
10152
+ const placeholder = instance.masked?.placeholderChar ?? resolvedPlaceholderChar.value;
10153
+ if (!placeholder) return raw;
10154
+ return raw.split(placeholder).join("").replace(/\s+$/, "");
10155
+ }
10156
+ function syncMaskDisplay() {
10157
+ if (!inputRef.value) {
10158
+ maskDisplayValue.value = "";
10159
+ maskPlaceholderChar.value = "";
10160
+ return;
10161
+ }
10162
+ maskPlaceholderChar.value = maskInstance?.masked?.placeholderChar ?? resolvedPlaceholderChar.value ?? "";
10163
+ maskDisplayValue.value = maskInstance?.displayValue ?? inputRef.value.value ?? maskInstance?.value ?? "";
10164
+ }
10076
10165
  const createMask2 = () => {
10077
10166
  if (maskInstance) {
10078
10167
  maskInstance.destroy();
@@ -10081,7 +10170,11 @@ const _sfc_main$r = /* @__PURE__ */ vue.defineComponent({
10081
10170
  if (props.mask && inputRef.value) {
10082
10171
  const maskConfig = {
10083
10172
  mask: props.mask,
10084
- ...props.maskOptions
10173
+ ...props.maskOptions,
10174
+ ...props.displayChar ? {
10175
+ placeholderChar: props.displayChar,
10176
+ lazy: props.maskOptions?.lazy ?? false
10177
+ } : {}
10085
10178
  };
10086
10179
  maskInstance = IMask(inputRef.value, maskConfig);
10087
10180
  if (internalValue.value) {
@@ -10089,9 +10182,20 @@ const _sfc_main$r = /* @__PURE__ */ vue.defineComponent({
10089
10182
  }
10090
10183
  maskInstance.on("accept", () => {
10091
10184
  if (maskInstance) {
10092
- internalValue.value = maskInstance.value;
10185
+ internalValue.value = getMaskEmittedValue(maskInstance);
10186
+ vue.nextTick(syncMaskDisplay);
10093
10187
  }
10094
10188
  });
10189
+ maskInstance.on("complete", () => {
10190
+ vue.nextTick(syncMaskDisplay);
10191
+ });
10192
+ vue.nextTick(() => {
10193
+ syncMaskDisplay();
10194
+ vue.nextTick(syncMaskDisplay);
10195
+ });
10196
+ } else {
10197
+ maskDisplayValue.value = "";
10198
+ maskPlaceholderChar.value = "";
10095
10199
  }
10096
10200
  };
10097
10201
  vue.onMounted(() => {
@@ -10120,19 +10224,21 @@ const _sfc_main$r = /* @__PURE__ */ vue.defineComponent({
10120
10224
  return props.meta ? metaId.value : void 0;
10121
10225
  });
10122
10226
  vue.watch(
10123
- () => props.mask,
10227
+ () => [props.mask, props.displayChar, props.maskOptions],
10124
10228
  () => {
10125
10229
  vue.nextTick(() => {
10126
10230
  createMask2();
10127
10231
  });
10128
- }
10232
+ },
10233
+ { deep: true }
10129
10234
  );
10130
10235
  vue.watch(
10131
10236
  () => props.value,
10132
10237
  (newValue) => {
10133
- if (maskInstance && newValue !== void 0 && newValue !== maskInstance.value) {
10238
+ if (maskInstance && newValue !== void 0 && newValue !== getMaskEmittedValue(maskInstance)) {
10134
10239
  if (document.activeElement !== inputRef.value) {
10135
10240
  maskInstance.value = newValue;
10241
+ vue.nextTick(syncMaskDisplay);
10136
10242
  }
10137
10243
  }
10138
10244
  }
@@ -10140,9 +10246,10 @@ const _sfc_main$r = /* @__PURE__ */ vue.defineComponent({
10140
10246
  vue.watch(
10141
10247
  () => modelValue.value,
10142
10248
  (newValue) => {
10143
- if (maskInstance && newValue !== void 0 && newValue !== maskInstance.value) {
10249
+ if (maskInstance && newValue !== void 0 && newValue !== getMaskEmittedValue(maskInstance)) {
10144
10250
  if (document.activeElement !== inputRef.value) {
10145
10251
  maskInstance.value = newValue;
10252
+ vue.nextTick(syncMaskDisplay);
10146
10253
  }
10147
10254
  }
10148
10255
  }
@@ -10177,13 +10284,14 @@ const _sfc_main$r = /* @__PURE__ */ vue.defineComponent({
10177
10284
  vue.createElementVNode("div", {
10178
10285
  class: vue.normalizeClass({ "flex-1": props.labelLeft })
10179
10286
  }, [
10180
- vue.createElementVNode("div", _hoisted_2$f, [
10287
+ vue.createElementVNode("div", {
10288
+ class: vue.normalizeClass(["relative", maskFieldWrapperClasses.value])
10289
+ }, [
10181
10290
  vue.createElementVNode("input", vue.mergeProps({
10182
10291
  ref_key: "inputRef",
10183
10292
  ref: inputRef,
10184
10293
  type: inputType.value === "password" ? showPassword.value ? "text" : "password" : inputType.value,
10185
10294
  required: props.required,
10186
- value: internalValue.value,
10187
10295
  disabled: props.disabled,
10188
10296
  tabindex: props.disabled ? -1 : void 0,
10189
10297
  "aria-invalid": props.valid === false ? "true" : void 0,
@@ -10196,7 +10304,7 @@ const _sfc_main$r = /* @__PURE__ */ vue.defineComponent({
10196
10304
  placeholder: props.placeholder,
10197
10305
  pattern: props.pattern,
10198
10306
  searchIcon: props.searchIcon
10199
- }, inputAttrs.value, {
10307
+ }, inputBindings.value, {
10200
10308
  onInput: handleInputChange,
10201
10309
  onChange: handleInputChange,
10202
10310
  onBlur: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("blur", $event)),
@@ -10204,7 +10312,21 @@ const _sfc_main$r = /* @__PURE__ */ vue.defineComponent({
10204
10312
  _ctx.$emit("keyup", ev);
10205
10313
  if (ev.key === "Enter") _ctx.$emit("keyup.enter", ev);
10206
10314
  })
10207
- }), null, 16, _hoisted_3$f),
10315
+ }), null, 16, _hoisted_2$f),
10316
+ useMaskPlaceholderStyle.value ? (vue.openBlock(), vue.createElementBlock("div", {
10317
+ key: 0,
10318
+ class: vue.normalizeClass(maskOverlayClasses.value),
10319
+ "aria-hidden": "true"
10320
+ }, [
10321
+ vue.createElementVNode("span", _hoisted_3$f, [
10322
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(maskDisplayChars.value, (item, index) => {
10323
+ return vue.openBlock(), vue.createElementBlock("span", {
10324
+ key: index,
10325
+ style: vue.normalizeStyle(maskCharStyle(item.isPlaceholder))
10326
+ }, vue.toDisplayString(item.char), 5);
10327
+ }), 128))
10328
+ ])
10329
+ ], 2)) : vue.createCommentVNode("", true),
10208
10330
  vue.createElementVNode("div", {
10209
10331
  class: vue.normalizeClass(rightIconsContainerClasses.value)
10210
10332
  }, [
@@ -10246,11 +10368,11 @@ const _sfc_main$r = /* @__PURE__ */ vue.defineComponent({
10246
10368
  }, null, 8, ["icon", "text"])) : vue.createCommentVNode("", true)
10247
10369
  ], 2),
10248
10370
  showTodaySuffixInField.value ? (vue.openBlock(), vue.createElementBlock("span", {
10249
- key: 0,
10371
+ key: 1,
10250
10372
  class: vue.normalizeClass(todaySuffixClasses.value),
10251
10373
  style: vue.normalizeStyle(todaySuffixStyle.value)
10252
10374
  }, vue.toDisplayString(todayLabel.value), 7)) : vue.createCommentVNode("", true)
10253
- ])
10375
+ ], 2)
10254
10376
  ], 2)
10255
10377
  ], 2),
10256
10378
  showInvalidMessage.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_4$e, vue.toDisplayString(props.invalidMessage), 1)) : vue.createCommentVNode("", true)
@@ -18916,7 +19038,7 @@ const _sfc_main$a = /* @__PURE__ */ vue.defineComponent({
18916
19038
  key: 0,
18917
19039
  role: "listbox",
18918
19040
  id: listboxId,
18919
- class: "absolute left-0 z-20 mt-1 min-w-[20rem] w-max max-w-[calc(100vw-2rem)] max-h-[280px] overflow-y-auto rounded-md border border-gray-300 bg-white"
19041
+ class: "absolute left-0 z-20 mt-2 min-w-[20rem] w-max max-w-[calc(100vw-2rem)] max-h-[280px] overflow-y-auto rounded-md border border-gray-300 bg-white"
18920
19042
  }, listDataAttrs.value, { onMouseleave: clearHoverPreview }), [
18921
19043
  (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(filteredCountries.value, (option, index) => {
18922
19044
  return vue.openBlock(), vue.createElementBlock("li", {
@@ -19025,7 +19147,7 @@ const _hoisted_2$3 = {
19025
19147
  key: 1,
19026
19148
  class: "font-thin mb-1"
19027
19149
  };
19028
- const _hoisted_3$3 = { class: "flex flex-wrap items-start gap-x-1" };
19150
+ const _hoisted_3$3 = { class: "flex flex-wrap items-start gap-x-2" };
19029
19151
  const _hoisted_4$3 = {
19030
19152
  key: 2,
19031
19153
  class: "text-red-700 font-bold mt-1"