@m3ui-vue/m3ui-vue 0.2.0 → 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.
- package/dist/{MMenuItem-CIDblhtb.js → MMenuItem-DpoEsH91.js} +195 -114
- package/dist/MMenuItem-DpoEsH91.js.map +1 -0
- package/dist/components/MAlert.vue.d.ts +1 -0
- package/dist/components/MButton.vue.d.ts +1 -1
- package/dist/components/MCalendar.vue.d.ts +3 -0
- package/dist/components/MChip.vue.d.ts +3 -3
- package/dist/components/MCommandPalette.vue.d.ts +3 -2
- package/dist/components/MConfirmDialog.vue.d.ts +0 -2
- package/dist/components/MDataTable.vue.d.ts +8 -2
- package/dist/components/MDatePicker.vue.d.ts +2 -0
- package/dist/components/MDateRangePicker.vue.d.ts +5 -0
- package/dist/components/MDialog.vue.d.ts +1 -0
- package/dist/components/MFileUpload.vue.d.ts +15 -1
- package/dist/components/MInfiniteScroll.vue.d.ts +7 -5
- package/dist/components/MMultiSelect.vue.d.ts +13 -1
- package/dist/components/MRichTextEditor.vue.d.ts +28 -1
- package/dist/components/MScheduler.vue.d.ts +5 -0
- package/dist/components/MSnackbar.vue.d.ts +4 -1
- package/dist/components/MSpinner.vue.d.ts +1 -0
- package/dist/components/MSpotlightSearch.vue.d.ts +3 -2
- package/dist/components/MTable.vue.d.ts +2 -1
- package/dist/components/MTimePicker.vue.d.ts +1 -0
- package/dist/components/MTour.vue.d.ts +3 -0
- package/dist/components/MTransferList.vue.d.ts +19 -3
- package/dist/components/MTree.vue.d.ts +1 -1
- package/dist/composables/useLocale.d.ts +74 -0
- package/dist/index.d.ts +2 -0
- package/dist/locales/de.d.ts +2 -0
- package/dist/locales/es.d.ts +2 -0
- package/dist/locales/fr.d.ts +2 -0
- package/dist/locales/index.d.ts +8 -0
- package/dist/locales/ja.d.ts +2 -0
- package/dist/locales/ko.d.ts +2 -0
- package/dist/locales/pt.d.ts +2 -0
- package/dist/locales/zh.d.ts +2 -0
- package/dist/m3ui-vue.css +1 -1
- package/dist/m3ui.js +2734 -2647
- package/dist/m3ui.js.map +1 -1
- package/dist/plugin.d.ts +3 -1
- package/dist/rich-text-editor.d.ts +1 -0
- package/dist/rich-text-editor.js +141 -113
- package/dist/rich-text-editor.js.map +1 -1
- package/dist/styles/palettes.css +660 -0
- package/dist/styles.css +1 -1
- package/package.json +6 -2
- package/src/components/MAlert.vue +5 -1
- package/src/components/MCalendar.vue +14 -5
- package/src/components/MCommandPalette.vue +11 -7
- package/src/components/MConfirmDialog.vue +6 -5
- package/src/components/MDataTable.vue +18 -9
- package/src/components/MDatePicker.vue +11 -4
- package/src/components/MDateRangePicker.vue +15 -5
- package/src/components/MDialog.vue +5 -1
- package/src/components/MFileUpload.vue +22 -10
- package/src/components/MInfiniteScroll.vue +14 -9
- package/src/components/MMultiSelect.vue +11 -7
- package/src/components/MRichTextEditor.vue +95 -34
- package/src/components/MScheduler.vue +12 -4
- package/src/components/MSnackbar.vue +8 -1
- package/src/components/MSpinner.vue +5 -1
- package/src/components/MSpotlightSearch.vue +11 -7
- package/src/components/MTable.vue +8 -4
- package/src/components/MTimePicker.vue +5 -1
- package/src/components/MTour.vue +12 -9
- package/src/components/MTransferList.vue +30 -15
- package/src/composables/useColorPalette.ts +30 -20
- package/src/composables/useLocale.ts +181 -0
- package/src/index.ts +2 -0
- package/src/locales/de.ts +93 -0
- package/src/locales/es.ts +93 -0
- package/src/locales/fr.ts +93 -0
- package/src/locales/index.ts +8 -0
- package/src/locales/ja.ts +93 -0
- package/src/locales/ko.ts +93 -0
- package/src/locales/pt.ts +93 -0
- package/src/locales/zh.ts +93 -0
- package/src/plugin.ts +7 -1
- package/src/rich-text-editor.ts +1 -0
- package/src/styles/palettes.css +660 -0
- package/dist/MMenuItem-CIDblhtb.js.map +0 -1
|
@@ -3,6 +3,9 @@ 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
|
|
@@ -26,6 +29,8 @@ const props = withDefaults(
|
|
|
26
29
|
searchable?: boolean
|
|
27
30
|
maxChips?: number
|
|
28
31
|
clearable?: boolean
|
|
32
|
+
searchPlaceholder?: string
|
|
33
|
+
noResultsText?: string
|
|
29
34
|
}>(),
|
|
30
35
|
{
|
|
31
36
|
modelValue: () => [],
|
|
@@ -299,7 +304,7 @@ const labelClasses = computed(() => {
|
|
|
299
304
|
ref="searchInput"
|
|
300
305
|
v-model="search"
|
|
301
306
|
type="text"
|
|
302
|
-
placeholder="
|
|
307
|
+
:placeholder="searchPlaceholder ?? locale.search"
|
|
303
308
|
class="w-full bg-transparent text-body-medium text-on-surface outline-none placeholder:text-on-surface-variant"
|
|
304
309
|
/>
|
|
305
310
|
</div>
|
|
@@ -319,12 +324,11 @@ const labelClasses = computed(() => {
|
|
|
319
324
|
/>
|
|
320
325
|
<span class="text-body-large text-on-surface">{{ opt.label }}</span>
|
|
321
326
|
</label>
|
|
322
|
-
<
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
</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>
|
|
328
332
|
</div>
|
|
329
333
|
</div>
|
|
330
334
|
</Transition>
|
|
@@ -6,6 +6,37 @@ import MMenuItem from './MMenuItem.vue'
|
|
|
6
6
|
import MDialog from './MDialog.vue'
|
|
7
7
|
import MTextField from './MTextField.vue'
|
|
8
8
|
import MButton from './MButton.vue'
|
|
9
|
+
import { useLocale } from '../composables/useLocale'
|
|
10
|
+
|
|
11
|
+
export interface RichTextEditorLabels {
|
|
12
|
+
bold?: string
|
|
13
|
+
italic?: string
|
|
14
|
+
underline?: string
|
|
15
|
+
strikethrough?: string
|
|
16
|
+
highlight?: string
|
|
17
|
+
bulletList?: string
|
|
18
|
+
orderedList?: string
|
|
19
|
+
blockquote?: string
|
|
20
|
+
code?: string
|
|
21
|
+
alignLeft?: string
|
|
22
|
+
alignCenter?: string
|
|
23
|
+
alignRight?: string
|
|
24
|
+
undo?: string
|
|
25
|
+
redo?: string
|
|
26
|
+
link?: string
|
|
27
|
+
image?: string
|
|
28
|
+
paragraph?: string
|
|
29
|
+
heading1?: string
|
|
30
|
+
heading2?: string
|
|
31
|
+
heading3?: string
|
|
32
|
+
insertLink?: string
|
|
33
|
+
insertImage?: string
|
|
34
|
+
imageUrlLabel?: string
|
|
35
|
+
cancel?: string
|
|
36
|
+
insert?: string
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const locale = useLocale()
|
|
9
40
|
|
|
10
41
|
const props = withDefaults(
|
|
11
42
|
defineProps<{
|
|
@@ -13,10 +44,40 @@ const props = withDefaults(
|
|
|
13
44
|
placeholder?: string
|
|
14
45
|
disabled?: boolean
|
|
15
46
|
minHeight?: string
|
|
47
|
+
labels?: RichTextEditorLabels
|
|
16
48
|
}>(),
|
|
17
|
-
{
|
|
49
|
+
{ disabled: false, minHeight: '200px' },
|
|
18
50
|
)
|
|
19
51
|
|
|
52
|
+
const l = computed<Required<RichTextEditorLabels>>(() => ({
|
|
53
|
+
bold: locale.bold,
|
|
54
|
+
italic: locale.italic,
|
|
55
|
+
underline: locale.underline,
|
|
56
|
+
strikethrough: locale.strikethrough,
|
|
57
|
+
highlight: locale.highlight,
|
|
58
|
+
bulletList: locale.bulletList,
|
|
59
|
+
orderedList: locale.orderedList,
|
|
60
|
+
blockquote: locale.blockquote,
|
|
61
|
+
code: locale.code,
|
|
62
|
+
alignLeft: locale.alignLeft,
|
|
63
|
+
alignCenter: locale.alignCenter,
|
|
64
|
+
alignRight: locale.alignRight,
|
|
65
|
+
undo: locale.undo,
|
|
66
|
+
redo: locale.redo,
|
|
67
|
+
link: locale.link,
|
|
68
|
+
image: locale.image,
|
|
69
|
+
paragraph: locale.paragraph,
|
|
70
|
+
heading1: locale.heading1,
|
|
71
|
+
heading2: locale.heading2,
|
|
72
|
+
heading3: locale.heading3,
|
|
73
|
+
insertLink: locale.insertLink,
|
|
74
|
+
insertImage: locale.insertImage,
|
|
75
|
+
imageUrlLabel: locale.imageUrlLabel,
|
|
76
|
+
cancel: locale.cancel,
|
|
77
|
+
insert: locale.insert,
|
|
78
|
+
...props.labels,
|
|
79
|
+
}))
|
|
80
|
+
|
|
20
81
|
const emit = defineEmits<{ 'update:modelValue': [string] }>()
|
|
21
82
|
|
|
22
83
|
const ready = ref(false)
|
|
@@ -68,7 +129,7 @@ onMounted(async () => {
|
|
|
68
129
|
Link.configure({ openOnClick: false }),
|
|
69
130
|
Image,
|
|
70
131
|
Highlight.configure({ multicolor: true }),
|
|
71
|
-
Placeholder.configure({ placeholder: props.placeholder }),
|
|
132
|
+
Placeholder.configure({ placeholder: props.placeholder ?? 'Start writing...' }),
|
|
72
133
|
TextStyle,
|
|
73
134
|
Color,
|
|
74
135
|
],
|
|
@@ -79,26 +140,26 @@ onMounted(async () => {
|
|
|
79
140
|
|
|
80
141
|
toolGroups.value = [
|
|
81
142
|
[
|
|
82
|
-
{ icon: 'format_bold', label:
|
|
83
|
-
{ icon: 'format_italic', label:
|
|
84
|
-
{ icon: 'format_underlined', label:
|
|
85
|
-
{ icon: 'format_strikethrough', label:
|
|
86
|
-
{ icon: 'ink_highlighter', label:
|
|
143
|
+
{ icon: 'format_bold', label: l.value.bold, action: () => editor.chain().focus().toggleBold().run(), active: () => !!editor.isActive('bold') },
|
|
144
|
+
{ icon: 'format_italic', label: l.value.italic, action: () => editor.chain().focus().toggleItalic().run(), active: () => !!editor.isActive('italic') },
|
|
145
|
+
{ icon: 'format_underlined', label: l.value.underline, action: () => editor.chain().focus().toggleUnderline().run(), active: () => !!editor.isActive('underline') },
|
|
146
|
+
{ icon: 'format_strikethrough', label: l.value.strikethrough, action: () => editor.chain().focus().toggleStrike().run(), active: () => !!editor.isActive('strike') },
|
|
147
|
+
{ icon: 'ink_highlighter', label: l.value.highlight, action: () => editor.chain().focus().toggleHighlight().run(), active: () => !!editor.isActive('highlight') },
|
|
87
148
|
],
|
|
88
149
|
[
|
|
89
|
-
{ icon: 'format_list_bulleted', label:
|
|
90
|
-
{ icon: 'format_list_numbered', label:
|
|
91
|
-
{ icon: 'format_quote', label:
|
|
92
|
-
{ icon: 'code', label:
|
|
150
|
+
{ icon: 'format_list_bulleted', label: l.value.bulletList, action: () => editor.chain().focus().toggleBulletList().run(), active: () => !!editor.isActive('bulletList') },
|
|
151
|
+
{ icon: 'format_list_numbered', label: l.value.orderedList, action: () => editor.chain().focus().toggleOrderedList().run(), active: () => !!editor.isActive('orderedList') },
|
|
152
|
+
{ icon: 'format_quote', label: l.value.blockquote, action: () => editor.chain().focus().toggleBlockquote().run(), active: () => !!editor.isActive('blockquote') },
|
|
153
|
+
{ icon: 'code', label: l.value.code, action: () => editor.chain().focus().toggleCode().run(), active: () => !!editor.isActive('code') },
|
|
93
154
|
],
|
|
94
155
|
[
|
|
95
|
-
{ icon: 'format_align_left', label:
|
|
96
|
-
{ icon: 'format_align_center', label:
|
|
97
|
-
{ icon: 'format_align_right', label:
|
|
156
|
+
{ icon: 'format_align_left', label: l.value.alignLeft, action: () => editor.chain().focus().setTextAlign('left').run(), active: () => !!editor.isActive({ textAlign: 'left' }) },
|
|
157
|
+
{ icon: 'format_align_center', label: l.value.alignCenter, action: () => editor.chain().focus().setTextAlign('center').run(), active: () => !!editor.isActive({ textAlign: 'center' }) },
|
|
158
|
+
{ icon: 'format_align_right', label: l.value.alignRight, action: () => editor.chain().focus().setTextAlign('right').run(), active: () => !!editor.isActive({ textAlign: 'right' }) },
|
|
98
159
|
],
|
|
99
160
|
[
|
|
100
|
-
{ icon: 'undo', label:
|
|
101
|
-
{ icon: 'redo', label:
|
|
161
|
+
{ icon: 'undo', label: l.value.undo, action: () => editor.chain().focus().undo().run() },
|
|
162
|
+
{ icon: 'redo', label: l.value.redo, action: () => editor.chain().focus().redo().run() },
|
|
102
163
|
],
|
|
103
164
|
]
|
|
104
165
|
|
|
@@ -120,11 +181,11 @@ const imageUrl = ref('')
|
|
|
120
181
|
|
|
121
182
|
const headingLabel = computed(() => {
|
|
122
183
|
const e = editorRef.value
|
|
123
|
-
if (!e) return
|
|
124
|
-
if (e.isActive('heading', { level: 1 })) return
|
|
125
|
-
if (e.isActive('heading', { level: 2 })) return
|
|
126
|
-
if (e.isActive('heading', { level: 3 })) return
|
|
127
|
-
return
|
|
184
|
+
if (!e) return l.value.paragraph
|
|
185
|
+
if (e.isActive('heading', { level: 1 })) return l.value.heading1
|
|
186
|
+
if (e.isActive('heading', { level: 2 })) return l.value.heading2
|
|
187
|
+
if (e.isActive('heading', { level: 3 })) return l.value.heading3
|
|
188
|
+
return l.value.paragraph
|
|
128
189
|
})
|
|
129
190
|
|
|
130
191
|
function setHeading(level: 0 | 1 | 2 | 3) {
|
|
@@ -171,10 +232,10 @@ function confirmImage() {
|
|
|
171
232
|
<MIcon name="arrow_drop_down" :size="20" />
|
|
172
233
|
</button>
|
|
173
234
|
</template>
|
|
174
|
-
<MMenuItem @click="setHeading(0)">
|
|
175
|
-
<MMenuItem @click="setHeading(1)">
|
|
176
|
-
<MMenuItem @click="setHeading(2)">
|
|
177
|
-
<MMenuItem @click="setHeading(3)">
|
|
235
|
+
<MMenuItem @click="setHeading(0)">{{ l.paragraph }}</MMenuItem>
|
|
236
|
+
<MMenuItem @click="setHeading(1)">{{ l.heading1 }}</MMenuItem>
|
|
237
|
+
<MMenuItem @click="setHeading(2)">{{ l.heading2 }}</MMenuItem>
|
|
238
|
+
<MMenuItem @click="setHeading(3)">{{ l.heading3 }}</MMenuItem>
|
|
178
239
|
</MMenu>
|
|
179
240
|
|
|
180
241
|
<div class="mx-1 h-6 w-px bg-outline-variant" />
|
|
@@ -198,7 +259,7 @@ function confirmImage() {
|
|
|
198
259
|
|
|
199
260
|
<button
|
|
200
261
|
type="button"
|
|
201
|
-
title="
|
|
262
|
+
:title="l.link"
|
|
202
263
|
class="flex h-8 w-8 cursor-pointer items-center justify-center rounded text-on-surface-variant transition-colors hover:bg-on-surface/8"
|
|
203
264
|
@click="openLinkDialog"
|
|
204
265
|
>
|
|
@@ -206,7 +267,7 @@ function confirmImage() {
|
|
|
206
267
|
</button>
|
|
207
268
|
<button
|
|
208
269
|
type="button"
|
|
209
|
-
title="
|
|
270
|
+
:title="l.image"
|
|
210
271
|
class="flex h-8 w-8 cursor-pointer items-center justify-center rounded text-on-surface-variant transition-colors hover:bg-on-surface/8"
|
|
211
272
|
@click="openImageDialog"
|
|
212
273
|
>
|
|
@@ -222,20 +283,20 @@ function confirmImage() {
|
|
|
222
283
|
/>
|
|
223
284
|
|
|
224
285
|
<!-- Link dialog -->
|
|
225
|
-
<MDialog v-model="linkDialogOpen" title="
|
|
286
|
+
<MDialog v-model="linkDialogOpen" :title="l.insertLink">
|
|
226
287
|
<MTextField v-model="linkUrl" label="URL" placeholder=" " @keydown.enter="confirmLink" />
|
|
227
288
|
<template #actions>
|
|
228
|
-
<MButton variant="text" @click="linkDialogOpen = false">
|
|
229
|
-
<MButton @click="confirmLink">
|
|
289
|
+
<MButton variant="text" @click="linkDialogOpen = false">{{ l.cancel }}</MButton>
|
|
290
|
+
<MButton @click="confirmLink">{{ l.insert }}</MButton>
|
|
230
291
|
</template>
|
|
231
292
|
</MDialog>
|
|
232
293
|
|
|
233
294
|
<!-- Image dialog -->
|
|
234
|
-
<MDialog v-model="imageDialogOpen" title="
|
|
235
|
-
<MTextField v-model="imageUrl" label="
|
|
295
|
+
<MDialog v-model="imageDialogOpen" :title="l.insertImage">
|
|
296
|
+
<MTextField v-model="imageUrl" :label="l.imageUrlLabel" placeholder=" " @keydown.enter="confirmImage" />
|
|
236
297
|
<template #actions>
|
|
237
|
-
<MButton variant="text" @click="imageDialogOpen = false">
|
|
238
|
-
<MButton @click="confirmImage">
|
|
298
|
+
<MButton variant="text" @click="imageDialogOpen = false">{{ l.cancel }}</MButton>
|
|
299
|
+
<MButton @click="confirmImage">{{ l.insert }}</MButton>
|
|
239
300
|
</template>
|
|
240
301
|
</MDialog>
|
|
241
302
|
</div>
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { ref, computed } from 'vue'
|
|
3
3
|
import MIconButton from './MIconButton.vue'
|
|
4
|
+
import { useLocale } from '../composables/useLocale'
|
|
5
|
+
|
|
6
|
+
const locale = useLocale()
|
|
4
7
|
|
|
5
8
|
export interface SchedulerEvent {
|
|
6
9
|
id: string | number
|
|
@@ -17,6 +20,11 @@ const props = withDefaults(
|
|
|
17
20
|
startHour?: number
|
|
18
21
|
endHour?: number
|
|
19
22
|
locale?: string
|
|
23
|
+
prevLabel?: string
|
|
24
|
+
nextLabel?: string
|
|
25
|
+
todayLabel?: string
|
|
26
|
+
dayViewLabel?: string
|
|
27
|
+
weekViewLabel?: string
|
|
20
28
|
}>(),
|
|
21
29
|
{
|
|
22
30
|
events: () => [],
|
|
@@ -135,14 +143,14 @@ const eventColors: Record<string, string> = {
|
|
|
135
143
|
<!-- Header -->
|
|
136
144
|
<div class="flex items-center justify-between border-b border-outline-variant bg-surface-container px-4 py-3">
|
|
137
145
|
<div class="flex items-center gap-1">
|
|
138
|
-
<MIconButton icon="chevron_left" label="
|
|
139
|
-
<MIconButton icon="chevron_right" label="
|
|
146
|
+
<MIconButton icon="chevron_left" :label="prevLabel ?? locale.previous" :size="36" @click="navigate(-1)" />
|
|
147
|
+
<MIconButton icon="chevron_right" :label="nextLabel ?? locale.next" :size="36" @click="navigate(1)" />
|
|
140
148
|
<button
|
|
141
149
|
type="button"
|
|
142
150
|
class="ml-2 cursor-pointer rounded-full border border-outline px-3 py-1 text-label-medium text-on-surface transition-colors hover:bg-on-surface/8"
|
|
143
151
|
@click="goToday"
|
|
144
152
|
>
|
|
145
|
-
|
|
153
|
+
{{ todayLabel ?? locale.today }}
|
|
146
154
|
</button>
|
|
147
155
|
</div>
|
|
148
156
|
|
|
@@ -157,7 +165,7 @@ const eventColors: Record<string, string> = {
|
|
|
157
165
|
:class="currentView === v ? 'bg-secondary-container text-on-secondary-container shadow-elevation-1' : 'text-on-surface-variant hover:bg-on-surface/8'"
|
|
158
166
|
@click="currentView = v"
|
|
159
167
|
>
|
|
160
|
-
{{ v === 'day' ?
|
|
168
|
+
{{ v === 'day' ? (dayViewLabel ?? locale.dayView) : (weekViewLabel ?? locale.weekView) }}
|
|
161
169
|
</button>
|
|
162
170
|
</div>
|
|
163
171
|
</div>
|
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
import { computed } from "vue";
|
|
3
3
|
import { useToast } from "../composables/useToast";
|
|
4
4
|
import MIcon from "./MIcon.vue";
|
|
5
|
+
import { useLocale } from '../composables/useLocale';
|
|
6
|
+
|
|
7
|
+
const props = defineProps<{
|
|
8
|
+
closeAriaLabel?: string
|
|
9
|
+
}>()
|
|
10
|
+
|
|
11
|
+
const locale = useLocale()
|
|
5
12
|
|
|
6
13
|
const { toasts, position, dismiss } = useToast();
|
|
7
14
|
|
|
@@ -117,7 +124,7 @@ const getVariantStyle = (variant: string): VariantStyle =>
|
|
|
117
124
|
type="button"
|
|
118
125
|
class="flex h-8 w-8 cursor-pointer items-center justify-center rounded-full transition-colors"
|
|
119
126
|
:class="t.color ? 'text-white/60 hover:bg-white/15' : getVariantStyle(t.variant).close"
|
|
120
|
-
aria-label="
|
|
127
|
+
:aria-label="closeAriaLabel ?? locale.close"
|
|
121
128
|
@click="dismiss(t.id)"
|
|
122
129
|
>
|
|
123
130
|
<MIcon name="close" :size="18" />
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed } from "vue";
|
|
3
|
+
import { useLocale } from '../composables/useLocale';
|
|
3
4
|
|
|
4
5
|
const props = withDefaults(
|
|
5
6
|
defineProps<{
|
|
6
7
|
size?: number;
|
|
7
8
|
wavy?: boolean;
|
|
9
|
+
label?: string;
|
|
8
10
|
}>(),
|
|
9
11
|
{ size: 20, wavy: false },
|
|
10
12
|
);
|
|
11
13
|
|
|
14
|
+
const locale = useLocale();
|
|
15
|
+
|
|
12
16
|
const STROKE = 3;
|
|
13
17
|
const BUMPS = 9;
|
|
14
18
|
|
|
@@ -56,7 +60,7 @@ const wavyData = computed(() => {
|
|
|
56
60
|
class="inline-flex shrink-0 items-center justify-center"
|
|
57
61
|
:style="{ width: `${size}px`, height: `${size}px` }"
|
|
58
62
|
role="status"
|
|
59
|
-
aria-label="
|
|
63
|
+
:aria-label="label ?? locale.loading"
|
|
60
64
|
>
|
|
61
65
|
<!-- Standard circular spinner -->
|
|
62
66
|
<span
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
import { ref, computed, watch, nextTick, onMounted, onBeforeUnmount } from 'vue'
|
|
3
3
|
import MIcon from './MIcon.vue'
|
|
4
4
|
import MSpinner from './MSpinner.vue'
|
|
5
|
+
import { useLocale } from '../composables/useLocale'
|
|
6
|
+
|
|
7
|
+
const locale = useLocale()
|
|
5
8
|
|
|
6
9
|
export interface SpotlightResult {
|
|
7
10
|
id: string | number
|
|
@@ -20,12 +23,13 @@ const props = withDefaults(
|
|
|
20
23
|
noResultsText?: string
|
|
21
24
|
hotkey?: string
|
|
22
25
|
debounce?: number
|
|
26
|
+
navigateHint?: string
|
|
27
|
+
openHint?: string
|
|
28
|
+
closeHint?: string
|
|
23
29
|
}>(),
|
|
24
30
|
{
|
|
25
31
|
results: () => [],
|
|
26
|
-
placeholder: 'Buscar...',
|
|
27
32
|
loading: false,
|
|
28
|
-
noResultsText: 'No se encontraron resultados',
|
|
29
33
|
hotkey: '/',
|
|
30
34
|
debounce: 0,
|
|
31
35
|
},
|
|
@@ -148,7 +152,7 @@ onBeforeUnmount(() => {
|
|
|
148
152
|
ref="inputRef"
|
|
149
153
|
v-model="query"
|
|
150
154
|
type="text"
|
|
151
|
-
:placeholder="placeholder"
|
|
155
|
+
:placeholder="placeholder ?? locale.search"
|
|
152
156
|
class="h-14 flex-1 bg-transparent text-title-medium text-on-surface outline-none placeholder:text-on-surface-variant/50"
|
|
153
157
|
@keydown="onKeydown"
|
|
154
158
|
/>
|
|
@@ -198,20 +202,20 @@ onBeforeUnmount(() => {
|
|
|
198
202
|
</template>
|
|
199
203
|
<div v-else-if="!loading" class="flex flex-col items-center gap-2 py-10">
|
|
200
204
|
<MIcon name="search_off" :size="40" class="text-on-surface-variant/40" />
|
|
201
|
-
<p class="text-body-medium text-on-surface-variant">{{ noResultsText }}</p>
|
|
205
|
+
<p class="text-body-medium text-on-surface-variant">{{ noResultsText ?? locale.noResults }}</p>
|
|
202
206
|
</div>
|
|
203
207
|
</div>
|
|
204
208
|
|
|
205
209
|
<!-- Hints -->
|
|
206
210
|
<div class="flex items-center gap-4 border-t border-outline-variant px-5 py-2">
|
|
207
211
|
<span class="flex items-center gap-1 text-label-small text-on-surface-variant">
|
|
208
|
-
<kbd class="rounded bg-surface-container px-1 py-0.5">↑↓</kbd>
|
|
212
|
+
<kbd class="rounded bg-surface-container px-1 py-0.5">↑↓</kbd> {{ navigateHint ?? locale.navigateHint }}
|
|
209
213
|
</span>
|
|
210
214
|
<span class="flex items-center gap-1 text-label-small text-on-surface-variant">
|
|
211
|
-
<kbd class="rounded bg-surface-container px-1 py-0.5">↵</kbd>
|
|
215
|
+
<kbd class="rounded bg-surface-container px-1 py-0.5">↵</kbd> {{ openHint ?? locale.openHint }}
|
|
212
216
|
</span>
|
|
213
217
|
<span class="flex items-center gap-1 text-label-small text-on-surface-variant">
|
|
214
|
-
<kbd class="rounded bg-surface-container px-1 py-0.5">esc</kbd>
|
|
218
|
+
<kbd class="rounded bg-surface-container px-1 py-0.5">esc</kbd> {{ closeHint ?? locale.closeHint }}
|
|
215
219
|
</span>
|
|
216
220
|
</div>
|
|
217
221
|
</div>
|
|
@@ -3,6 +3,9 @@ import { computed, onMounted, ref, watch } from 'vue'
|
|
|
3
3
|
import MCheckbox from './MCheckbox.vue'
|
|
4
4
|
import MIcon from './MIcon.vue'
|
|
5
5
|
import MPagination from './MPagination.vue'
|
|
6
|
+
import { useLocale } from '../composables/useLocale'
|
|
7
|
+
|
|
8
|
+
const locale = useLocale()
|
|
6
9
|
|
|
7
10
|
export interface TableColumn {
|
|
8
11
|
key: string
|
|
@@ -38,10 +41,11 @@ const props = withDefaults(
|
|
|
38
41
|
serverSide?: boolean
|
|
39
42
|
total?: number
|
|
40
43
|
page?: number
|
|
44
|
+
searchPlaceholder?: string
|
|
45
|
+
selectedText?: string
|
|
41
46
|
}>(),
|
|
42
47
|
{
|
|
43
48
|
loading: false,
|
|
44
|
-
emptyText: 'Sin resultados',
|
|
45
49
|
rowKey: 'id',
|
|
46
50
|
selectable: false,
|
|
47
51
|
modelValue: () => [],
|
|
@@ -228,7 +232,7 @@ const hasActions = computed(() => !!slots['row-actions'])
|
|
|
228
232
|
<input
|
|
229
233
|
v-model="search"
|
|
230
234
|
type="text"
|
|
231
|
-
placeholder="
|
|
235
|
+
:placeholder="searchPlaceholder ?? locale.search"
|
|
232
236
|
class="w-full bg-transparent text-body-medium text-on-surface outline-none placeholder:text-on-surface-variant"
|
|
233
237
|
/>
|
|
234
238
|
<button
|
|
@@ -254,7 +258,7 @@ const hasActions = computed(() => !!slots['row-actions'])
|
|
|
254
258
|
v-if="selectable && selected.length > 0"
|
|
255
259
|
class="rounded-full bg-primary/12 px-3 py-1 text-label-small font-medium text-primary"
|
|
256
260
|
>
|
|
257
|
-
{{ selected.length }}
|
|
261
|
+
{{ selected.length }} {{ selectedText ?? locale.selectedCount }}{{ selected.length !== 1 ? 's' : '' }}
|
|
258
262
|
</span>
|
|
259
263
|
</Transition>
|
|
260
264
|
</div>
|
|
@@ -346,7 +350,7 @@ const hasActions = computed(() => !!slots['row-actions'])
|
|
|
346
350
|
>
|
|
347
351
|
<slot name="empty">
|
|
348
352
|
<MIcon name="search_off" :size="36" class="mb-2 text-on-surface-variant opacity-30" />
|
|
349
|
-
<p class="text-body-medium text-on-surface-variant">{{ emptyText }}</p>
|
|
353
|
+
<p class="text-body-medium text-on-surface-variant">{{ emptyText ?? locale.noResults }}</p>
|
|
350
354
|
</slot>
|
|
351
355
|
</td>
|
|
352
356
|
</tr>
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
|
3
3
|
import MIcon from './MIcon.vue'
|
|
4
4
|
import { useFieldBg } from '../composables/useFieldBg'
|
|
5
|
+
import { useLocale } from '../composables/useLocale'
|
|
5
6
|
|
|
6
7
|
const props = withDefaults(defineProps<{
|
|
7
8
|
modelValue: string | null
|
|
8
9
|
label?: string
|
|
10
|
+
placeholder?: string
|
|
9
11
|
disabled?: boolean
|
|
10
12
|
error?: string
|
|
11
13
|
hint?: string
|
|
@@ -14,6 +16,8 @@ const props = withDefaults(defineProps<{
|
|
|
14
16
|
fieldBg?: string
|
|
15
17
|
}>(), { minuteStep: 5, use24h: true })
|
|
16
18
|
|
|
19
|
+
const locale = useLocale()
|
|
20
|
+
|
|
17
21
|
const emit = defineEmits<{ 'update:modelValue': [string | null] }>()
|
|
18
22
|
|
|
19
23
|
const open = ref(false)
|
|
@@ -129,7 +133,7 @@ onUnmounted(() => {
|
|
|
129
133
|
>
|
|
130
134
|
<MIcon name="schedule" :size="20" class="shrink-0 text-on-surface-variant" />
|
|
131
135
|
<span v-if="displayValue" class="flex-1 font-mono text-on-surface">{{ displayValue }}</span>
|
|
132
|
-
<span v-else class="flex-1 text-on-surface-variant">{{ label ||
|
|
136
|
+
<span v-else class="flex-1 text-on-surface-variant">{{ label || placeholder || locale.selectTime }}</span>
|
|
133
137
|
<MIcon
|
|
134
138
|
v-if="modelValue"
|
|
135
139
|
name="close"
|
package/src/components/MTour.vue
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { ref, computed, watch, nextTick, onBeforeUnmount } from 'vue'
|
|
3
3
|
import MButton from './MButton.vue'
|
|
4
4
|
import MIcon from './MIcon.vue'
|
|
5
|
+
import { useLocale } from '../composables/useLocale'
|
|
5
6
|
|
|
6
7
|
export interface TourStep {
|
|
7
8
|
target: string
|
|
@@ -10,13 +11,15 @@ export interface TourStep {
|
|
|
10
11
|
placement?: 'top' | 'bottom' | 'left' | 'right'
|
|
11
12
|
}
|
|
12
13
|
|
|
13
|
-
const props =
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
)
|
|
14
|
+
const props = defineProps<{
|
|
15
|
+
modelValue: boolean
|
|
16
|
+
steps: TourStep[]
|
|
17
|
+
prevLabel?: string
|
|
18
|
+
nextLabel?: string
|
|
19
|
+
finishLabel?: string
|
|
20
|
+
}>()
|
|
21
|
+
|
|
22
|
+
const locale = useLocale()
|
|
20
23
|
|
|
21
24
|
const emit = defineEmits<{
|
|
22
25
|
'update:modelValue': [boolean]
|
|
@@ -237,11 +240,11 @@ onBeforeUnmount(() => { stopListeners(); clearHighlight() })
|
|
|
237
240
|
variant="text"
|
|
238
241
|
@click="goPrev"
|
|
239
242
|
>
|
|
240
|
-
|
|
243
|
+
{{ prevLabel ?? locale.previous }}
|
|
241
244
|
</MButton>
|
|
242
245
|
<span v-else />
|
|
243
246
|
<MButton @click="goNext">
|
|
244
|
-
{{ isLast ?
|
|
247
|
+
{{ isLast ? (finishLabel ?? locale.finish) : (nextLabel ?? locale.next) }}
|
|
245
248
|
</MButton>
|
|
246
249
|
</div>
|
|
247
250
|
</div>
|