@m3ui-vue/m3ui-vue 0.1.11 → 0.2.1

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.
Files changed (98) hide show
  1. package/dist/{MMenuItem-_n5OG5MT.js → MMenuItem-DpoEsH91.js} +215 -122
  2. package/dist/MMenuItem-DpoEsH91.js.map +1 -0
  3. package/dist/components/MAlert.vue.d.ts +1 -0
  4. package/dist/components/MButton.vue.d.ts +1 -1
  5. package/dist/components/MCalendar.vue.d.ts +3 -0
  6. package/dist/components/MCarousel.vue.d.ts +36 -0
  7. package/dist/components/MChip.vue.d.ts +3 -3
  8. package/dist/components/MCommandPalette.vue.d.ts +3 -2
  9. package/dist/components/MConfirmDialog.vue.d.ts +0 -2
  10. package/dist/components/MDataTable.vue.d.ts +25 -2
  11. package/dist/components/MDatePicker.vue.d.ts +2 -0
  12. package/dist/components/MDateRangePicker.vue.d.ts +5 -0
  13. package/dist/components/MDialog.vue.d.ts +1 -0
  14. package/dist/components/MFab.vue.d.ts +1 -1
  15. package/dist/components/MFileUpload.vue.d.ts +15 -1
  16. package/dist/components/MFlex.vue.d.ts +1 -1
  17. package/dist/components/MInfiniteScroll.vue.d.ts +7 -5
  18. package/dist/components/MMaskField.vue.d.ts +24 -0
  19. package/dist/components/MMultiSelect.vue.d.ts +20 -6
  20. package/dist/components/MNavigationDrawer.vue.d.ts +9 -3
  21. package/dist/components/MNumberField.vue.d.ts +27 -0
  22. package/dist/components/MRichTextEditor.vue.d.ts +28 -1
  23. package/dist/components/MScheduler.vue.d.ts +5 -0
  24. package/dist/components/MSelect.vue.d.ts +12 -9
  25. package/dist/components/MSnackbar.vue.d.ts +4 -1
  26. package/dist/components/MSpinner.vue.d.ts +1 -0
  27. package/dist/components/MSplitter.vue.d.ts +1 -1
  28. package/dist/components/MSpotlightSearch.vue.d.ts +3 -2
  29. package/dist/components/MStack.vue.d.ts +1 -1
  30. package/dist/components/MTable.vue.d.ts +3 -2
  31. package/dist/components/MTextField.vue.d.ts +2 -5
  32. package/dist/components/MTimePicker.vue.d.ts +1 -0
  33. package/dist/components/MTour.vue.d.ts +3 -0
  34. package/dist/components/MTransferList.vue.d.ts +19 -3
  35. package/dist/components/MTree.vue.d.ts +1 -1
  36. package/dist/components/_MDrawerItemList.vue.d.ts +57 -0
  37. package/dist/composables/useLocale.d.ts +74 -0
  38. package/dist/index.d.ts +10 -1
  39. package/dist/locales/de.d.ts +2 -0
  40. package/dist/locales/es.d.ts +2 -0
  41. package/dist/locales/fr.d.ts +2 -0
  42. package/dist/locales/index.d.ts +8 -0
  43. package/dist/locales/ja.d.ts +2 -0
  44. package/dist/locales/ko.d.ts +2 -0
  45. package/dist/locales/pt.d.ts +2 -0
  46. package/dist/locales/zh.d.ts +2 -0
  47. package/dist/m3ui-vue.css +1 -1
  48. package/dist/m3ui.js +3278 -2489
  49. package/dist/m3ui.js.map +1 -1
  50. package/dist/plugin.d.ts +3 -1
  51. package/dist/rich-text-editor.d.ts +1 -0
  52. package/dist/rich-text-editor.js +141 -113
  53. package/dist/rich-text-editor.js.map +1 -1
  54. package/dist/styles/palettes.css +660 -0
  55. package/dist/styles.css +1 -1
  56. package/package.json +6 -2
  57. package/src/components/MAlert.vue +5 -1
  58. package/src/components/MCalendar.vue +14 -5
  59. package/src/components/MCarousel.vue +203 -0
  60. package/src/components/MCommandPalette.vue +11 -7
  61. package/src/components/MConfirmDialog.vue +6 -5
  62. package/src/components/MDataTable.vue +78 -14
  63. package/src/components/MDatePicker.vue +11 -4
  64. package/src/components/MDateRangePicker.vue +15 -5
  65. package/src/components/MDialog.vue +5 -1
  66. package/src/components/MFileUpload.vue +22 -10
  67. package/src/components/MInfiniteScroll.vue +14 -9
  68. package/src/components/MMaskField.vue +198 -0
  69. package/src/components/MMultiSelect.vue +53 -24
  70. package/src/components/MNavigationDrawer.vue +282 -107
  71. package/src/components/MNumberField.vue +176 -0
  72. package/src/components/MRichTextEditor.vue +95 -34
  73. package/src/components/MScheduler.vue +12 -4
  74. package/src/components/MSelect.vue +41 -14
  75. package/src/components/MSnackbar.vue +8 -1
  76. package/src/components/MSpinner.vue +5 -1
  77. package/src/components/MSpotlightSearch.vue +11 -7
  78. package/src/components/MTable.vue +8 -4
  79. package/src/components/MTextField.vue +19 -10
  80. package/src/components/MTimePicker.vue +5 -1
  81. package/src/components/MTour.vue +12 -9
  82. package/src/components/MTransferList.vue +30 -15
  83. package/src/components/_MDrawerItemList.vue +105 -0
  84. package/src/composables/useColorPalette.ts +30 -20
  85. package/src/composables/useLocale.ts +181 -0
  86. package/src/index.ts +10 -1
  87. package/src/locales/de.ts +93 -0
  88. package/src/locales/es.ts +93 -0
  89. package/src/locales/fr.ts +93 -0
  90. package/src/locales/index.ts +8 -0
  91. package/src/locales/ja.ts +93 -0
  92. package/src/locales/ko.ts +93 -0
  93. package/src/locales/pt.ts +93 -0
  94. package/src/locales/zh.ts +93 -0
  95. package/src/plugin.ts +7 -1
  96. package/src/rich-text-editor.ts +1 -0
  97. package/src/styles/palettes.css +660 -0
  98. package/dist/MMenuItem-_n5OG5MT.js.map +0 -1
@@ -3,16 +3,19 @@ import { computed, ref, useId, onMounted, onUnmounted, nextTick } from 'vue'
3
3
  import MIcon from './MIcon.vue'
4
4
  import MCheckbox from './MCheckbox.vue'
5
5
  import { useFieldBg } from '../composables/useFieldBg'
6
+ import { useLocale } from '../composables/useLocale'
7
+
8
+ const locale = useLocale()
6
9
 
7
10
  export interface MultiSelectOption {
8
11
  label: string
9
- value: string | number
12
+ value: unknown
10
13
  disabled?: boolean
11
14
  }
12
15
 
13
16
  const props = withDefaults(
14
17
  defineProps<{
15
- modelValue: (string | number)[]
18
+ modelValue: unknown[]
16
19
  options: MultiSelectOption[]
17
20
  label?: string
18
21
  placeholder?: string
@@ -25,6 +28,9 @@ const props = withDefaults(
25
28
  fieldBg?: string
26
29
  searchable?: boolean
27
30
  maxChips?: number
31
+ clearable?: boolean
32
+ searchPlaceholder?: string
33
+ noResultsText?: string
28
34
  }>(),
29
35
  {
30
36
  modelValue: () => [],
@@ -33,10 +39,11 @@ const props = withDefaults(
33
39
  required: false,
34
40
  searchable: true,
35
41
  maxChips: 3,
42
+ clearable: false,
36
43
  },
37
44
  )
38
45
 
39
- const emit = defineEmits<{ 'update:modelValue': [(string | number)[]] }>()
46
+ const emit = defineEmits<{ 'update:modelValue': [unknown[]] }>()
40
47
 
41
48
  const id = useId()
42
49
  const open = ref(false)
@@ -47,6 +54,16 @@ const dropdownEl = ref<HTMLElement | null>(null)
47
54
  const searchInput = ref<HTMLInputElement | null>(null)
48
55
  const dropPos = ref({ top: '0px', left: '0px', width: '0px' })
49
56
 
57
+ function eq(a: unknown, b: unknown): boolean {
58
+ if (a === b) return true
59
+ if (typeof a !== 'object' || typeof b !== 'object' || a == null || b == null) return false
60
+ return JSON.stringify(a) === JSON.stringify(b)
61
+ }
62
+
63
+ function includes(arr: unknown[], val: unknown): boolean {
64
+ return arr.some((v) => eq(v, val))
65
+ }
66
+
50
67
  const hasValue = computed(() => props.modelValue.length > 0)
51
68
 
52
69
  const filteredOptions = computed(() => {
@@ -58,24 +75,24 @@ const filteredOptions = computed(() => {
58
75
  const visibleChips = computed(() =>
59
76
  props.modelValue.slice(0, props.maxChips).map((v) => ({
60
77
  value: v,
61
- label: props.options.find((o) => o.value === v)?.label ?? String(v),
78
+ label: props.options.find((o) => eq(o.value, v))?.label ?? String(v),
62
79
  })),
63
80
  )
64
81
 
65
82
  const overflowCount = computed(() => Math.max(0, props.modelValue.length - props.maxChips))
66
83
 
67
- function toggle(value: string | number) {
84
+ function toggle(value: unknown) {
68
85
  const current = props.modelValue
69
- if (current.includes(value)) {
70
- emit('update:modelValue', current.filter((v) => v !== value))
86
+ if (includes(current, value)) {
87
+ emit('update:modelValue', current.filter((v) => !eq(v, value)))
71
88
  } else {
72
89
  emit('update:modelValue', [...current, value])
73
90
  }
74
91
  }
75
92
 
76
- function removeChip(value: string | number, e: Event) {
93
+ function removeChip(value: unknown, e: Event) {
77
94
  e.stopPropagation()
78
- emit('update:modelValue', props.modelValue.filter((v) => v !== value))
95
+ emit('update:modelValue', props.modelValue.filter((v) => !eq(v, value)))
79
96
  }
80
97
 
81
98
  function computeDropPos() {
@@ -164,7 +181,9 @@ const labelClasses = computed(() => {
164
181
  ? '-top-2.5 translate-y-0 text-label-small bg-[var(--field-bg)] px-1 right-auto max-w-[calc(100%-1.5rem)]'
165
182
  : 'top-2 translate-y-0 text-label-small'
166
183
 
167
- const unFloated = 'top-1/2 -translate-y-1/2 text-body-large'
184
+ const unFloated = props.variant === 'filled'
185
+ ? 'top-[53%] -translate-y-1/2 text-body-large'
186
+ : 'top-1/2 -translate-y-1/2 text-body-large'
168
187
  const active = open.value || hasValue.value
169
188
 
170
189
  return [
@@ -188,7 +207,8 @@ const labelClasses = computed(() => {
188
207
  >
189
208
  <div
190
209
  v-if="leadingIcon"
191
- class="pointer-events-none absolute left-3.5 top-1/2 -translate-y-1/2 text-on-surface-variant"
210
+ class="pointer-events-none absolute left-3.5 text-on-surface-variant"
211
+ :class="variant === 'filled' ? 'top-[57%] -translate-y-1/2' : 'top-[55%] -translate-y-1/2'"
192
212
  >
193
213
  <MIcon :name="leadingIcon" :size="20" />
194
214
  </div>
@@ -208,8 +228,8 @@ const labelClasses = computed(() => {
208
228
  >
209
229
  <template v-if="hasValue">
210
230
  <span
211
- v-for="chip in visibleChips"
212
- :key="chip.value"
231
+ v-for="(chip, i) in visibleChips"
232
+ :key="i"
213
233
  class="inline-flex items-center gap-1 rounded-full bg-secondary-container px-2 py-0.5 text-label-small text-on-secondary-container"
214
234
  >
215
235
  {{ chip.label }}
@@ -237,7 +257,17 @@ const labelClasses = computed(() => {
237
257
  {{ label }}<span v-if="required" class="text-error">&nbsp;*</span>
238
258
  </label>
239
259
 
240
- <div class="pointer-events-none absolute right-2 top-7 -translate-y-1/2">
260
+ <button
261
+ v-if="clearable && hasValue && !disabled"
262
+ type="button"
263
+ class="absolute right-9 flex h-6 w-6 cursor-pointer items-center justify-center rounded-full text-on-surface-variant transition-colors hover:bg-on-surface/8 hover:text-on-surface"
264
+ :class="variant === 'filled' ? 'top-[57%] -translate-y-1/2' : 'top-[55%] -translate-y-1/2'"
265
+ @click.stop="emit('update:modelValue', []); close()"
266
+ >
267
+ <MIcon name="close" :size="18" />
268
+ </button>
269
+
270
+ <div class="pointer-events-none absolute right-2" :class="variant === 'filled' ? 'top-[57%] -translate-y-1/2' : 'top-[55%] -translate-y-1/2'">
241
271
  <MIcon
242
272
  :name="open ? 'arrow_drop_up' : 'arrow_drop_down'"
243
273
  :size="24"
@@ -274,7 +304,7 @@ const labelClasses = computed(() => {
274
304
  ref="searchInput"
275
305
  v-model="search"
276
306
  type="text"
277
- placeholder="Buscar..."
307
+ :placeholder="searchPlaceholder ?? locale.search"
278
308
  class="w-full bg-transparent text-body-medium text-on-surface outline-none placeholder:text-on-surface-variant"
279
309
  />
280
310
  </div>
@@ -282,24 +312,23 @@ const labelClasses = computed(() => {
282
312
 
283
313
  <div class="flex flex-col py-1">
284
314
  <label
285
- v-for="opt in filteredOptions"
286
- :key="opt.value"
315
+ v-for="(opt, i) in filteredOptions"
316
+ :key="i"
287
317
  class="flex cursor-pointer items-center gap-3 px-4 py-2 hover:bg-on-surface/8"
288
318
  :class="opt.disabled ? 'cursor-not-allowed opacity-38' : ''"
289
319
  >
290
320
  <MCheckbox
291
- :model-value="modelValue.includes(opt.value)"
321
+ :model-value="includes(modelValue, opt.value)"
292
322
  :disabled="opt.disabled"
293
323
  @update:model-value="!opt.disabled && toggle(opt.value)"
294
324
  />
295
325
  <span class="text-body-large text-on-surface">{{ opt.label }}</span>
296
326
  </label>
297
- <p
298
- v-if="filteredOptions.length === 0"
299
- class="px-4 py-3 text-center text-body-small text-on-surface-variant"
300
- >
301
- Sin resultados
302
- </p>
327
+ <slot v-if="filteredOptions.length === 0" name="no-results">
328
+ <p class="px-4 py-3 text-center text-body-small text-on-surface-variant">
329
+ {{ noResultsText ?? locale.noResults }}
330
+ </p>
331
+ </slot>
303
332
  </div>
304
333
  </div>
305
334
  </Transition>