sprintify-ui 0.12.19 → 0.12.21

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.
@@ -46,7 +46,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
46
46
  }>> & Readonly<{}>, {
47
47
  to: (user: AvatarUserInput) => RouteLocationRaw;
48
48
  size: string;
49
- max: number;
50
49
  tooltip: boolean;
50
+ max: number;
51
51
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
52
52
  export default _default;
@@ -67,11 +67,11 @@ declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {
67
67
  icon: string;
68
68
  disabled: boolean;
69
69
  as: string;
70
+ tooltip: string | null;
70
71
  loading: boolean;
71
72
  iconPosition: "start" | "end";
72
73
  sizeBehavior: SizeBehavior;
73
74
  align: "center" | "between";
74
- tooltip: string | null;
75
75
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
76
76
  declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
77
77
  export default _default;
@@ -9,6 +9,17 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
9
9
  default: string;
10
10
  type: PropType<string | number | null>;
11
11
  };
12
+ /**
13
+ * v-model modifiers. `v-model.unmasked` makes the component emit maska's
14
+ * unmasked value (raw digits, dot decimal, no separators) instead of the
15
+ * masked display value. No-op when no `mask` is set.
16
+ */
17
+ modelModifiers: {
18
+ default: () => {};
19
+ type: PropType<{
20
+ unmasked?: boolean;
21
+ }>;
22
+ };
12
23
  class: {
13
24
  default: string;
14
25
  type: PropType<string | string[]>;
@@ -112,6 +123,17 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
112
123
  default: string;
113
124
  type: PropType<string | number | null>;
114
125
  };
126
+ /**
127
+ * v-model modifiers. `v-model.unmasked` makes the component emit maska's
128
+ * unmasked value (raw digits, dot decimal, no separators) instead of the
129
+ * masked display value. No-op when no `mask` is set.
130
+ */
131
+ modelModifiers: {
132
+ default: () => {};
133
+ type: PropType<{
134
+ unmasked?: boolean;
135
+ }>;
136
+ };
115
137
  class: {
116
138
  default: string;
117
139
  type: PropType<string | string[]>;
@@ -218,6 +240,9 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
218
240
  disabled: boolean;
219
241
  name: string | null | undefined;
220
242
  modelValue: string | number | null;
243
+ modelModifiers: {
244
+ unmasked?: boolean;
245
+ };
221
246
  autocomplete: boolean;
222
247
  preventSubmit: boolean;
223
248
  iconLeft: string | null | undefined;
@@ -204,8 +204,8 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
204
204
  meta: Record<string, any> | unknown[];
205
205
  width: number;
206
206
  padding: string;
207
- align: "left" | "center" | "right";
208
207
  tooltip: string;
208
+ align: "left" | "center" | "right";
209
209
  field: string;
210
210
  headerClass: string | Record<string, any> | unknown[];
211
211
  searchable: boolean;
@@ -20,8 +20,8 @@ declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {}, {}
20
20
  }>, {
21
21
  class: string | false | 0 | 0n | ClassNameValue[] | null;
22
22
  style: string | false | import("vue").CSSProperties | StyleValue[] | null;
23
- align: "left" | "center" | "right";
24
23
  tooltip: string;
24
+ align: "left" | "center" | "right";
25
25
  colspan: number;
26
26
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
27
27
  declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sprintify-ui",
3
- "version": "0.12.19",
3
+ "version": "0.12.21",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "generate-llm-txt": "node scripts/generate-llm-txt.js",
@@ -32,6 +32,10 @@ export default {
32
32
  "time",
33
33
  "credit-card",
34
34
  "zip-code-canada",
35
+ "integer",
36
+ "integer-fr",
37
+ "money",
38
+ "money-fr",
35
39
  "dynamicMask",
36
40
  "customMask",
37
41
  ],
@@ -139,6 +143,54 @@ CanadianZipCodeMask.args = {
139
143
  mask: "zip-code-canada", // M5M 4M4
140
144
  };
141
145
 
146
+ export const IntegerMask = Template.bind({});
147
+ IntegerMask.args = {
148
+ mask: "integer", // 1,000,000
149
+ placeholder: "1,000,000",
150
+ };
151
+
152
+ export const IntegerMaskFr = Template.bind({});
153
+ IntegerMaskFr.args = {
154
+ mask: "integer-fr", // 1 000 000
155
+ placeholder: "1 000 000",
156
+ };
157
+
158
+ export const MoneyMask = Template.bind({});
159
+ MoneyMask.args = {
160
+ mask: "money", // 1,000,000.00
161
+ placeholder: "1,000,000.00",
162
+ };
163
+
164
+ export const MoneyMaskFr = Template.bind({});
165
+ MoneyMaskFr.args = {
166
+ mask: "money-fr", // 1 000 000,00
167
+ placeholder: "1 000 000,00",
168
+ };
169
+
170
+ const UnmaskedT = (args) => ({
171
+ components: { BaseInput, ShowValue },
172
+ setup() {
173
+ const masked = ref(null);
174
+ const unmasked = ref(null);
175
+ return { args, masked, unmasked };
176
+ },
177
+ template: `
178
+ <p class="text-xs text-slate-600 leading-tight mb-1">Default (masked value)</p>
179
+ <BaseInput v-model="masked" v-bind="args" class="w-full mb-1"></BaseInput>
180
+ <ShowValue :value="masked" />
181
+
182
+ <p class="text-xs text-slate-600 leading-tight mb-1 mt-4">v-model.unmasked (raw value)</p>
183
+ <BaseInput v-model.unmasked="unmasked" v-bind="args" class="w-full mb-1"></BaseInput>
184
+ <ShowValue :value="unmasked" />
185
+ `,
186
+ });
187
+
188
+ export const UnmaskedModifier = UnmaskedT.bind({});
189
+ UnmaskedModifier.args = {
190
+ mask: "money-fr",
191
+ placeholder: "1 000 000,00",
192
+ };
193
+
142
194
  export const DynamicMask = Template.bind({});
143
195
  DynamicMask.args = {
144
196
  mask: ["###.###.###-##", "##.###.###/####-##"],
@@ -79,7 +79,7 @@ import { useField } from '@/composables/field';
79
79
  import { vMaska } from 'maska/vue';
80
80
  import { Size, sizes } from '@/utils/sizes';
81
81
  import { twMerge } from 'tailwind-merge';
82
- import { MaskInputOptions, MaskType } from 'maska';
82
+ import { MaskaDetail, MaskInputOptions, MaskType } from 'maska';
83
83
 
84
84
  defineOptions({
85
85
  inheritAttrs: false,
@@ -90,6 +90,15 @@ const props = defineProps({
90
90
  default: '',
91
91
  type: [String, Number, null] as PropType<string | number | null>,
92
92
  },
93
+ /**
94
+ * v-model modifiers. `v-model.unmasked` makes the component emit maska's
95
+ * unmasked value (raw digits, dot decimal, no separators) instead of the
96
+ * masked display value. No-op when no `mask` is set.
97
+ */
98
+ modelModifiers: {
99
+ default: () => ({}),
100
+ type: Object as PropType<{ unmasked?: boolean }>,
101
+ },
93
102
  class: {
94
103
  default: '',
95
104
  type: [String, Array] as PropType<string | string[]>,
@@ -203,13 +212,38 @@ const hasRightListener = computed(() => {
203
212
  return props.onIconRightClick !== undefined;
204
213
  });
205
214
 
206
- const maskOptions = computed(() => {
207
- if (props.mask) {
208
- return {
209
- mask: maskInternal.value,
210
- };
215
+ /**
216
+ * Number-format aliases. These use maska's `number` mode (locale-derived
217
+ * grouping/decimal separators) instead of a `#` mask pattern. The `-fr`
218
+ * variants use `fr-CA` (no-break space grouping + comma decimal); the
219
+ * `money` variants allow up to 2 fraction digits, the `integer` variants none.
220
+ */
221
+ const NUMBER_MASKS: Record<string, { locale: string; fraction: number }> = {
222
+ integer: { locale: 'en', fraction: 0 },
223
+ 'integer-fr': { locale: 'fr-CA', fraction: 0 },
224
+ money: { locale: 'en', fraction: 2 },
225
+ 'money-fr': { locale: 'fr-CA', fraction: 2 },
226
+ };
227
+
228
+ /** Latest maska result, captured so `.unmasked` can emit the raw value. */
229
+ const maskaDetail = ref<MaskaDetail | null>(null);
230
+
231
+ const maskOptions = computed<MaskInputOptions | undefined>(() => {
232
+ if (!props.mask) {
233
+ return undefined;
211
234
  }
212
- return undefined;
235
+
236
+ const base =
237
+ typeof props.mask === 'string' && props.mask in NUMBER_MASKS
238
+ ? { number: NUMBER_MASKS[props.mask] }
239
+ : { mask: maskInternal.value };
240
+
241
+ return {
242
+ ...base,
243
+ onMaska: (detail: MaskaDetail) => {
244
+ maskaDetail.value = detail;
245
+ },
246
+ };
213
247
  });
214
248
 
215
249
  const bindings = computed<any>(() => {
@@ -274,7 +308,11 @@ const { nameInternal, requiredInternal, hasErrorInternal, emitUpdate, sizeIntern
274
308
 
275
309
  function onInput(event: any | null) {
276
310
  if (event === null) {
277
- emitUpdate(null);
311
+ return emitUpdate(null);
312
+ }
313
+
314
+ if (props.modelModifiers.unmasked && maskaDetail.value) {
315
+ return emitUpdate(maskaDetail.value.unmasked);
278
316
  }
279
317
 
280
318
  return emitUpdate(get(event, 'target.value', ''));
@@ -5,7 +5,7 @@
5
5
  >
6
6
  <slot />
7
7
  <Teleport
8
- v-if="visible && text"
8
+ v-if="visible && (text || $slots.tooltip)"
9
9
  to="body"
10
10
  >
11
11
  <div