- {{ type }}
+
+
+
+
+
+ N/A
+
+
+ lt-{{ bp }}
+
+
+
+
+
+
+
+ N/A
+
+
+ gt-{{ bp }}
+
+
+
+
+
+
+ breakpoint: {{ w }}
+
+ from {{ $q.screen.sizes[w] || 0 }} to {{ $q.screen.sizes[wNext] || 'Infinity' }}
+
+ width: {{ $q.screen.width }}
-
- {{ w }} - {{ $q.screen.sizes[w] }} - {{ $q.screen.width }}
-
diff --git a/ui/dev/src/pages/web-tests/tabs-router/TabsLayout.vue b/ui/dev/src/pages/web-tests/tabs-router/TabsLayout.vue
new file mode 100644
index 00000000000..43c7de6e391
--- /dev/null
+++ b/ui/dev/src/pages/web-tests/tabs-router/TabsLayout.vue
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+ Enable route change above when you want to navigate away
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/dev/src/pages/web-tests/tabs-router/Two.vue b/ui/dev/src/pages/web-tests/tabs-router/Two.vue
new file mode 100644
index 00000000000..a2c5d0d3fe9
--- /dev/null
+++ b/ui/dev/src/pages/web-tests/tabs-router/Two.vue
@@ -0,0 +1,19 @@
+
+ Tab two Content
+
+
+
diff --git a/ui/dev/src/router/routes.js b/ui/dev/src/router/routes.js
index 37bdce36ae1..ba53cabdab6 100644
--- a/ui/dev/src/router/routes.js
+++ b/ui/dev/src/router/routes.js
@@ -20,6 +20,15 @@ const metaChildren = [
const routes = [
{ path: '/', component: load('Index') },
+ {
+ path: '/tabs-router',
+ redirect: { name: 'one' },
+ component: () => import('pages/web-tests/tabs-router/TabsLayout.vue'),
+ children: [
+ { path: 'one', name: 'one', component: () => import('pages/web-tests/tabs-router/One.vue') },
+ { path: 'two', name: 'two', component: () => import('pages/web-tests/tabs-router/Two.vue') }
+ ]
+ },
{
path: '/meta/layout_1',
component: load('meta/layout_1'),
diff --git a/ui/dev/upload-server/server.js b/ui/dev/upload-server/server.js
index f509cb33e03..ffa069a199e 100644
--- a/ui/dev/upload-server/server.js
+++ b/ui/dev/upload-server/server.js
@@ -21,6 +21,10 @@ process.on('exit', () => {
rimraf.sync(path.join(folder))
})
+// attackers can use this header to detect apps running Express
+// and then launch specifically-targeted attacks
+app.disable('x-powered-by')
+
app.set('port', port)
app.use(throttle(1024 * 128))
diff --git a/ui/icon-set/bootstrap-icons.js b/ui/icon-set/bootstrap-icons.js
index fc94ce50f2b..5075e4183b7 100644
--- a/ui/icon-set/bootstrap-icons.js
+++ b/ui/icon-set/bootstrap-icons.js
@@ -4,7 +4,7 @@
import {
mdiFormatSubscript,
mdiFormatSuperscript
-} from '@quasar/extras/mdi-v5'
+} from '@quasar/extras/mdi-v6'
export default {
name: 'bootstrap-icons',
diff --git a/ui/icon-set/eva-icons.js b/ui/icon-set/eva-icons.js
index a60bd5a2d53..48add90191f 100644
--- a/ui/icon-set/eva-icons.js
+++ b/ui/icon-set/eva-icons.js
@@ -41,7 +41,7 @@ import {
mdiNumeric6Box,
mdiNumeric7Box,
mdiFormatFont
-} from '@quasar/extras/mdi-v5'
+} from '@quasar/extras/mdi-v6'
export default {
name: 'eva-icons',
diff --git a/ui/icon-set/fontawesome-v6-pro.js b/ui/icon-set/fontawesome-v6-pro.js
new file mode 100644
index 00000000000..2dd4e9dfa4a
--- /dev/null
+++ b/ui/icon-set/fontawesome-v6-pro.js
@@ -0,0 +1,128 @@
+export default {
+ name: 'fontawesome-v6-pro',
+ type: {
+ positive: 'fal fa-check',
+ negative: 'fal fa-triangle-exclamation',
+ info: 'fal fa-circle-info',
+ warning: 'fal fa-exclamation'
+ },
+ arrow: {
+ up: 'fal fa-arrow-up',
+ right: 'fal fa-arrow-right',
+ down: 'fal fa-arrow-down',
+ left: 'fal fa-arrow-left',
+ dropdown: 'fal fa-caret-down'
+ },
+ chevron: {
+ left: 'fal fa-chevron-left',
+ right: 'fal fa-chevron-right'
+ },
+ colorPicker: {
+ spectrum: 'fal fa-eye-dropper',
+ tune: 'fal fa-sliders',
+ palette: 'fal fa-swatchbook'
+ },
+ pullToRefresh: {
+ icon: 'fal fa-sync-alt'
+ },
+ carousel: {
+ left: 'fal fa-chevron-left',
+ right: 'fal fa-chevron-right',
+ up: 'fal fa-chevron-up',
+ down: 'fal fa-chevron-down',
+ navigationIcon: 'fal fa-circle'
+ },
+ chip: {
+ remove: 'fal fa-circle-xmark',
+ selected: 'fal fa-check'
+ },
+ datetime: {
+ arrowLeft: 'fal fa-chevron-left',
+ arrowRight: 'fal fa-chevron-right',
+ now: 'fal fa-clock',
+ today: 'fal fa-calendar-check'
+ },
+ editor: {
+ bold: 'fal fa-bold',
+ italic: 'fal fa-italic',
+ strikethrough: 'fal fa-strikethrough',
+ underline: 'fal fa-underline',
+ unorderedList: 'fal fa-list-ul',
+ orderedList: 'fal fa-list-ol',
+ subscript: 'fal fa-subscript',
+ superscript: 'fal fa-superscript',
+ hyperlink: 'fal fa-link',
+ toggleFullscreen: 'fal fa-maximize',
+ quote: 'fal fa-quote-right',
+ left: 'fal fa-align-left',
+ center: 'fal fa-align-center',
+ right: 'fal fa-align-right',
+ justify: 'fal fa-align-justify',
+ print: 'fal fa-print',
+ outdent: 'fal fa-outdent',
+ indent: 'fal fa-indent',
+ removeFormat: 'fal fa-eraser',
+ formatting: 'fal fa-heading',
+ fontSize: 'fal fa-text-height',
+ align: 'fal fa-align-left',
+ hr: 'fal fa-square-minus',
+ undo: 'fal fa-rotate-left',
+ redo: 'fal fa-rotate-right',
+ heading: 'fal fa-heading',
+ code: 'fal fa-code',
+ size: 'fal fa-text-height',
+ font: 'fal fa-font',
+ viewSource: 'fal fa-code'
+ },
+ expansionItem: {
+ icon: 'fal fa-chevron-down',
+ denseIcon: 'fal fa-caret-down'
+ },
+ fab: {
+ icon: 'fal fa-plus',
+ activeIcon: 'fal fa-xmark'
+ },
+ field: {
+ clear: 'fal fa-circle-xmark',
+ error: 'fal fa-circle-exclamation'
+ },
+ pagination: {
+ first: 'fal fa-backward-step',
+ prev: 'fal fa-chevron-left',
+ next: 'fal fa-chevron-right',
+ last: 'fal fa-forward-step'
+ },
+ rating: {
+ icon: 'fal fa-star'
+ },
+ stepper: {
+ done: 'fal fa-check',
+ active: 'fal fa-pencil',
+ error: 'fal fa-triangle-exclamation'
+ },
+ tabs: {
+ left: 'fal fa-chevron-left',
+ right: 'fal fa-chevron-right',
+ up: 'fal fa-chevron-up',
+ down: 'fal fa-chevron-down'
+ },
+ table: {
+ arrowUp: 'fal fa-long-arrow-up',
+ warning: 'fal fa-triangle-exclamation',
+ firstPage: 'fal fa-backward-step',
+ prevPage: 'fal fa-chevron-left',
+ nextPage: 'fal fa-chevron-right',
+ lastPage: 'fal fa-forward-step'
+ },
+ tree: {
+ icon: 'fal fa-play'
+ },
+ uploader: {
+ done: 'fal fa-check',
+ clear: 'fal fa-xmark',
+ add: 'fal fa-square-plus',
+ upload: 'fal fa-upload',
+ removeQueue: 'fal fa-bars-staggered',
+ removeUploaded: 'fal fa-clipboard-check'
+ }
+}
diff --git a/ui/icon-set/fontawesome-v6.js b/ui/icon-set/fontawesome-v6.js
new file mode 100644
index 00000000000..7aa6b489d5d
--- /dev/null
+++ b/ui/icon-set/fontawesome-v6.js
@@ -0,0 +1,128 @@
+export default {
+ name: 'fontawesome-v6',
+ type: {
+ positive: 'fas fa-check',
+ negative: 'fas fa-triangle-exclamation',
+ info: 'fas fa-circle-info',
+ warning: 'fas fa-exclamation'
+ },
+ arrow: {
+ up: 'fas fa-arrow-up',
+ right: 'fas fa-arrow-right',
+ down: 'fas fa-arrow-down',
+ left: 'fas fa-arrow-left',
+ dropdown: 'fas fa-caret-down'
+ },
+ chevron: {
+ left: 'fas fa-chevron-left',
+ right: 'fas fa-chevron-right'
+ },
+ colorPicker: {
+ spectrum: 'fas fa-eye-dropper',
+ tune: 'fas fa-sliders',
+ palette: 'fas fa-swatchbook'
+ },
+ pullToRefresh: {
+ icon: 'fas fa-rotate'
+ },
+ carousel: {
+ left: 'fas fa-chevron-left',
+ right: 'fas fa-chevron-right',
+ up: 'fas fa-chevron-up',
+ down: 'fas fa-chevron-down',
+ navigationIcon: 'fas fa-circle'
+ },
+ chip: {
+ remove: 'fas fa-circle-xmark',
+ selected: 'fas fa-check'
+ },
+ datetime: {
+ arrowLeft: 'fas fa-chevron-left',
+ arrowRight: 'fas fa-chevron-right',
+ now: 'far fa-clock',
+ today: 'far fa-calendar-check'
+ },
+ editor: {
+ bold: 'fas fa-bold',
+ italic: 'fas fa-italic',
+ strikethrough: 'fas fa-strikethrough',
+ underline: 'fas fa-underline',
+ unorderedList: 'fas fa-list-ul',
+ orderedList: 'fas fa-list-ol',
+ subscript: 'fas fa-subscript',
+ superscript: 'fas fa-superscript',
+ hyperlink: 'fas fa-link',
+ toggleFullscreen: 'fas fa-maximize',
+ quote: 'fas fa-quote-right',
+ left: 'fas fa-align-left',
+ center: 'fas fa-align-center',
+ right: 'fas fa-align-right',
+ justify: 'fas fa-align-justify',
+ print: 'fas fa-print',
+ outdent: 'fas fa-outdent',
+ indent: 'fas fa-indent',
+ removeFormat: 'fas fa-eraser',
+ formatting: 'fas fa-heading',
+ fontSize: 'fas fa-text-height',
+ align: 'fas fa-align-left',
+ hr: 'far fa-square-minus',
+ undo: 'fas fa-rotate-left',
+ redo: 'fas fa-rotate-right',
+ heading: 'fas fa-heading',
+ code: 'fas fa-code',
+ size: 'fas fa-text-height',
+ font: 'fas fa-font',
+ viewSource: 'fas fa-code'
+ },
+ expansionItem: {
+ icon: 'fas fa-chevron-down',
+ denseIcon: 'fas fa-caret-down'
+ },
+ fab: {
+ icon: 'fas fa-plus',
+ activeIcon: 'fas fa-xmark'
+ },
+ field: {
+ clear: 'fas fa-circle-xmark',
+ error: 'fas fa-circle-exclamation'
+ },
+ pagination: {
+ first: 'fas fa-backward-step',
+ prev: 'fas fa-chevron-left',
+ next: 'fas fa-chevron-right',
+ last: 'fas fa-forward-step'
+ },
+ rating: {
+ icon: 'fas fa-star'
+ },
+ stepper: {
+ done: 'fas fa-check',
+ active: 'fas fa-pencil',
+ error: 'fas fa-triangle-exclamation'
+ },
+ tabs: {
+ left: 'fas fa-chevron-left',
+ right: 'fas fa-chevron-right',
+ up: 'fas fa-chevron-up',
+ down: 'fas fa-chevron-down'
+ },
+ table: {
+ arrowUp: 'fas fa-arrow-up',
+ warning: 'fas fa-triangle-exclamation',
+ firstPage: 'fas fa-backward-step',
+ prevPage: 'fas fa-chevron-left',
+ nextPage: 'fas fa-chevron-right',
+ lastPage: 'fas fa-forward-step'
+ },
+ tree: {
+ icon: 'fas fa-play'
+ },
+ uploader: {
+ done: 'fas fa-check',
+ clear: 'fas fa-xmark',
+ add: 'fas fa-square-plus',
+ upload: 'fas fa-upload',
+ removeQueue: 'fas fa-bars-staggered',
+ removeUploaded: 'fas fa-clipboard-check'
+ }
+}
diff --git a/ui/icon-set/ionicons-v4.js b/ui/icon-set/ionicons-v4.js
index 34fe702cf67..a6c35e6a05a 100644
--- a/ui/icon-set/ionicons-v4.js
+++ b/ui/icon-set/ionicons-v4.js
@@ -34,7 +34,7 @@ import {
mdiNumeric6Box,
mdiNumeric7Box,
mdiFormatFont
-} from '@quasar/extras/mdi-v5'
+} from '@quasar/extras/mdi-v6'
export default {
name: 'ionicons-v4',
diff --git a/ui/icon-set/material-symbols-outlined.js b/ui/icon-set/material-symbols-outlined.js
new file mode 100644
index 00000000000..c9ca042110d
--- /dev/null
+++ b/ui/icon-set/material-symbols-outlined.js
@@ -0,0 +1,128 @@
+export default {
+ name: 'material-symbols-outlined',
+ type: {
+ positive: 'sym_o_check_circle',
+ negative: 'sym_o_warning',
+ info: 'sym_o_info',
+ warning: 'sym_o_priority_high'
+ },
+ arrow: {
+ up: 'sym_o_arrow_upward',
+ right: 'sym_o_arrow_forward',
+ down: 'sym_o_arrow_downward',
+ left: 'sym_o_arrow_back',
+ dropdown: 'sym_o_arrow_drop_down'
+ },
+ chevron: {
+ left: 'sym_o_chevron_left',
+ right: 'sym_o_chevron_right'
+ },
+ colorPicker: {
+ spectrum: 'sym_o_gradient',
+ tune: 'sym_o_tune',
+ palette: 'sym_o_style'
+ },
+ pullToRefresh: {
+ icon: 'sym_o_refresh'
+ },
+ carousel: {
+ left: 'sym_o_chevron_left',
+ right: 'sym_o_chevron_right',
+ up: 'sym_o_keyboard_arrow_up',
+ down: 'sym_o_keyboard_arrow_down',
+ navigationIcon: 'sym_o_lens'
+ },
+ chip: {
+ remove: 'sym_o_cancel',
+ selected: 'sym_o_check'
+ },
+ datetime: {
+ arrowLeft: 'sym_o_chevron_left',
+ arrowRight: 'sym_o_chevron_right',
+ now: 'sym_o_schedule',
+ today: 'sym_o_today'
+ },
+ editor: {
+ bold: 'sym_o_format_bold',
+ italic: 'sym_o_format_italic',
+ strikethrough: 'sym_o_strikethrough_s',
+ underline: 'sym_o_format_underlined',
+ unorderedList: 'sym_o_format_list_bulleted',
+ orderedList: 'sym_o_format_list_numbered',
+ subscript: 'sym_o_vertical_align_bottom',
+ superscript: 'sym_o_vertical_align_top',
+ hyperlink: 'sym_o_link',
+ toggleFullscreen: 'sym_o_fullscreen',
+ quote: 'sym_o_format_quote',
+ left: 'sym_o_format_align_left',
+ center: 'sym_o_format_align_center',
+ right: 'sym_o_format_align_right',
+ justify: 'sym_o_format_align_justify',
+ print: 'sym_o_print',
+ outdent: 'sym_o_format_indent_decrease',
+ indent: 'sym_o_format_indent_increase',
+ removeFormat: 'sym_o_format_clear',
+ formatting: 'sym_o_text_format',
+ fontSize: 'sym_o_format_size',
+ align: 'sym_o_format_align_left',
+ hr: 'sym_o_remove',
+ undo: 'sym_o_undo',
+ redo: 'sym_o_redo',
+ heading: 'sym_o_format_size',
+ code: 'sym_o_code',
+ size: 'sym_o_format_size',
+ font: 'sym_o_font_download',
+ viewSource: 'sym_o_code'
+ },
+ expansionItem: {
+ icon: 'sym_o_keyboard_arrow_down',
+ denseIcon: 'sym_o_arrow_drop_down'
+ },
+ fab: {
+ icon: 'sym_o_add',
+ activeIcon: 'sym_o_close'
+ },
+ field: {
+ clear: 'sym_o_cancel',
+ error: 'sym_o_error'
+ },
+ pagination: {
+ first: 'sym_o_first_page',
+ prev: 'sym_o_keyboard_arrow_left',
+ next: 'sym_o_keyboard_arrow_right',
+ last: 'sym_o_last_page'
+ },
+ rating: {
+ icon: 'sym_o_grade'
+ },
+ stepper: {
+ done: 'sym_o_check',
+ active: 'sym_o_edit',
+ error: 'sym_o_warning'
+ },
+ tabs: {
+ left: 'sym_o_chevron_left',
+ right: 'sym_o_chevron_right',
+ up: 'sym_o_keyboard_arrow_up',
+ down: 'sym_o_keyboard_arrow_down'
+ },
+ table: {
+ arrowUp: 'sym_o_arrow_upward',
+ warning: 'sym_o_warning',
+ firstPage: 'sym_o_first_page',
+ prevPage: 'sym_o_chevron_left',
+ nextPage: 'sym_o_chevron_right',
+ lastPage: 'sym_o_last_page'
+ },
+ tree: {
+ icon: 'sym_o_play_arrow'
+ },
+ uploader: {
+ done: 'sym_o_done',
+ clear: 'sym_o_close',
+ add: 'sym_o_add_box',
+ upload: 'sym_o_cloud_upload',
+ removeQueue: 'sym_o_clear_all',
+ removeUploaded: 'sym_o_done_all'
+ }
+}
diff --git a/ui/icon-set/material-symbols-rounded.js b/ui/icon-set/material-symbols-rounded.js
new file mode 100644
index 00000000000..52d280a985b
--- /dev/null
+++ b/ui/icon-set/material-symbols-rounded.js
@@ -0,0 +1,128 @@
+export default {
+ name: 'material-symbols-rounded',
+ type: {
+ positive: 'sym_r_check_circle',
+ negative: 'sym_r_warning',
+ info: 'sym_r_info',
+ warning: 'sym_r_priority_high'
+ },
+ arrow: {
+ up: 'sym_r_arrow_upward',
+ right: 'sym_r_arrow_forward',
+ down: 'sym_r_arrow_downward',
+ left: 'sym_r_arrow_back',
+ dropdown: 'sym_r_arrow_drop_down'
+ },
+ chevron: {
+ left: 'sym_r_chevron_left',
+ right: 'sym_r_chevron_right'
+ },
+ colorPicker: {
+ spectrum: 'sym_r_gradient',
+ tune: 'sym_r_tune',
+ palette: 'sym_r_style'
+ },
+ pullToRefresh: {
+ icon: 'sym_r_refresh'
+ },
+ carousel: {
+ left: 'sym_r_chevron_left',
+ right: 'sym_r_chevron_right',
+ up: 'sym_r_keyboard_arrow_up',
+ down: 'sym_r_keyboard_arrow_down',
+ navigationIcon: 'sym_r_lens'
+ },
+ chip: {
+ remove: 'sym_r_cancel',
+ selected: 'sym_r_check'
+ },
+ datetime: {
+ arrowLeft: 'sym_r_chevron_left',
+ arrowRight: 'sym_r_chevron_right',
+ now: 'sym_r_schedule',
+ today: 'sym_r_today'
+ },
+ editor: {
+ bold: 'sym_r_format_bold',
+ italic: 'sym_r_format_italic',
+ strikethrough: 'sym_r_strikethrough_s',
+ underline: 'sym_r_format_underlined',
+ unorderedList: 'sym_r_format_list_bulleted',
+ orderedList: 'sym_r_format_list_numbered',
+ subscript: 'sym_r_vertical_align_bottom',
+ superscript: 'sym_r_vertical_align_top',
+ hyperlink: 'sym_r_link',
+ toggleFullscreen: 'sym_r_fullscreen',
+ quote: 'sym_r_format_quote',
+ left: 'sym_r_format_align_left',
+ center: 'sym_r_format_align_center',
+ right: 'sym_r_format_align_right',
+ justify: 'sym_r_format_align_justify',
+ print: 'sym_r_print',
+ outdent: 'sym_r_format_indent_decrease',
+ indent: 'sym_r_format_indent_increase',
+ removeFormat: 'sym_r_format_clear',
+ formatting: 'sym_r_text_format',
+ fontSize: 'sym_r_format_size',
+ align: 'sym_r_format_align_left',
+ hr: 'sym_r_remove',
+ undo: 'sym_r_undo',
+ redo: 'sym_r_redo',
+ heading: 'sym_r_format_size',
+ code: 'sym_r_code',
+ size: 'sym_r_format_size',
+ font: 'sym_r_font_download',
+ viewSource: 'sym_r_code'
+ },
+ expansionItem: {
+ icon: 'sym_r_keyboard_arrow_down',
+ denseIcon: 'sym_r_arrow_drop_down'
+ },
+ fab: {
+ icon: 'sym_r_add',
+ activeIcon: 'sym_r_close'
+ },
+ field: {
+ clear: 'sym_r_cancel',
+ error: 'sym_r_error'
+ },
+ pagination: {
+ first: 'sym_r_first_page',
+ prev: 'sym_r_keyboard_arrow_left',
+ next: 'sym_r_keyboard_arrow_right',
+ last: 'sym_r_last_page'
+ },
+ rating: {
+ icon: 'sym_r_grade'
+ },
+ stepper: {
+ done: 'sym_r_check',
+ active: 'sym_r_edit',
+ error: 'sym_r_warning'
+ },
+ tabs: {
+ left: 'sym_r_chevron_left',
+ right: 'sym_r_chevron_right',
+ up: 'sym_r_keyboard_arrow_up',
+ down: 'sym_r_keyboard_arrow_down'
+ },
+ table: {
+ arrowUp: 'sym_r_arrow_upward',
+ warning: 'sym_r_warning',
+ firstPage: 'sym_r_first_page',
+ prevPage: 'sym_r_chevron_left',
+ nextPage: 'sym_r_chevron_right',
+ lastPage: 'sym_r_last_page'
+ },
+ tree: {
+ icon: 'sym_r_play_arrow'
+ },
+ uploader: {
+ done: 'sym_r_done',
+ clear: 'sym_r_close',
+ add: 'sym_r_add_box',
+ upload: 'sym_r_cloud_upload',
+ removeQueue: 'sym_r_clear_all',
+ removeUploaded: 'sym_r_done_all'
+ }
+}
diff --git a/ui/icon-set/material-symbols-sharp.js b/ui/icon-set/material-symbols-sharp.js
new file mode 100644
index 00000000000..54dfa17d365
--- /dev/null
+++ b/ui/icon-set/material-symbols-sharp.js
@@ -0,0 +1,128 @@
+export default {
+ name: 'material-symbols-sharp',
+ type: {
+ positive: 'sym_s_check_circle',
+ negative: 'sym_s_warning',
+ info: 'sym_s_info',
+ warning: 'sym_s_priority_high'
+ },
+ arrow: {
+ up: 'sym_s_arrow_upward',
+ right: 'sym_s_arrow_forward',
+ down: 'sym_s_arrow_downward',
+ left: 'sym_s_arrow_back',
+ dropdown: 'sym_s_arrow_drop_down'
+ },
+ chevron: {
+ left: 'sym_s_chevron_left',
+ right: 'sym_s_chevron_right'
+ },
+ colorPicker: {
+ spectrum: 'sym_s_gradient',
+ tune: 'sym_s_tune',
+ palette: 'sym_s_style'
+ },
+ pullToRefresh: {
+ icon: 'sym_s_refresh'
+ },
+ carousel: {
+ left: 'sym_s_chevron_left',
+ right: 'sym_s_chevron_right',
+ up: 'sym_s_keyboard_arrow_up',
+ down: 'sym_s_keyboard_arrow_down',
+ navigationIcon: 'sym_s_lens'
+ },
+ chip: {
+ remove: 'sym_s_cancel',
+ selected: 'sym_s_check'
+ },
+ datetime: {
+ arrowLeft: 'sym_s_chevron_left',
+ arrowRight: 'sym_s_chevron_right',
+ now: 'sym_s_schedule',
+ today: 'sym_s_today'
+ },
+ editor: {
+ bold: 'sym_s_format_bold',
+ italic: 'sym_s_format_italic',
+ strikethrough: 'sym_s_strikethrough_s',
+ underline: 'sym_s_format_underlined',
+ unorderedList: 'sym_s_format_list_bulleted',
+ orderedList: 'sym_s_format_list_numbered',
+ subscript: 'sym_s_vertical_align_bottom',
+ superscript: 'sym_s_vertical_align_top',
+ hyperlink: 'sym_s_link',
+ toggleFullscreen: 'sym_s_fullscreen',
+ quote: 'sym_s_format_quote',
+ left: 'sym_s_format_align_left',
+ center: 'sym_s_format_align_center',
+ right: 'sym_s_format_align_right',
+ justify: 'sym_s_format_align_justify',
+ print: 'sym_s_print',
+ outdent: 'sym_s_format_indent_decrease',
+ indent: 'sym_s_format_indent_increase',
+ removeFormat: 'sym_s_format_clear',
+ formatting: 'sym_s_text_format',
+ fontSize: 'sym_s_format_size',
+ align: 'sym_s_format_align_left',
+ hr: 'sym_s_remove',
+ undo: 'sym_s_undo',
+ redo: 'sym_s_redo',
+ heading: 'sym_s_format_size',
+ code: 'sym_s_code',
+ size: 'sym_s_format_size',
+ font: 'sym_s_font_download',
+ viewSource: 'sym_s_code'
+ },
+ expansionItem: {
+ icon: 'sym_s_keyboard_arrow_down',
+ denseIcon: 'sym_s_arrow_drop_down'
+ },
+ fab: {
+ icon: 'sym_s_add',
+ activeIcon: 'sym_s_close'
+ },
+ field: {
+ clear: 'sym_s_cancel',
+ error: 'sym_s_error'
+ },
+ pagination: {
+ first: 'sym_s_first_page',
+ prev: 'sym_s_keyboard_arrow_left',
+ next: 'sym_s_keyboard_arrow_right',
+ last: 'sym_s_last_page'
+ },
+ rating: {
+ icon: 'sym_s_grade'
+ },
+ stepper: {
+ done: 'sym_s_check',
+ active: 'sym_s_edit',
+ error: 'sym_s_warning'
+ },
+ tabs: {
+ left: 'sym_s_chevron_left',
+ right: 'sym_s_chevron_right',
+ up: 'sym_s_keyboard_arrow_up',
+ down: 'sym_s_keyboard_arrow_down'
+ },
+ table: {
+ arrowUp: 'sym_s_arrow_upward',
+ warning: 'sym_s_warning',
+ firstPage: 'sym_s_first_page',
+ prevPage: 'sym_s_chevron_left',
+ nextPage: 'sym_s_chevron_right',
+ lastPage: 'sym_s_last_page'
+ },
+ tree: {
+ icon: 'sym_s_play_arrow'
+ },
+ uploader: {
+ done: 'sym_s_done',
+ clear: 'sym_s_close',
+ add: 'sym_s_add_box',
+ upload: 'sym_s_cloud_upload',
+ removeQueue: 'sym_s_clear_all',
+ removeUploaded: 'sym_s_done_all'
+ }
+}
diff --git a/ui/icon-set/mdi-v6.js b/ui/icon-set/mdi-v6.js
new file mode 100644
index 00000000000..716d0af8c98
--- /dev/null
+++ b/ui/icon-set/mdi-v6.js
@@ -0,0 +1,141 @@
+export default {
+ name: 'mdi-v6',
+ type: {
+ positive: 'mdi-check-circle',
+ negative: 'mdi-alert',
+ info: 'mdi-information',
+ warning: 'mdi-exclamation'
+ },
+ arrow: {
+ up: 'mdi-arrow-up',
+ right: 'mdi-arrow-right',
+ down: 'mdi-arrow-down',
+ left: 'mdi-arrow-left',
+ dropdown: 'mdi-menu-down'
+ },
+ chevron: {
+ left: 'mdi-chevron-left',
+ right: 'mdi-chevron-right'
+ },
+ colorPicker: {
+ spectrum: 'mdi-gradient-vertical',
+ tune: 'mdi-tune',
+ palette: 'mdi-palette-swatch'
+ },
+ pullToRefresh: {
+ icon: 'mdi-refresh'
+ },
+ carousel: {
+ left: 'mdi-chevron-left',
+ right: 'mdi-chevron-right',
+ up: 'mdi-chevron-up',
+ down: 'mdi-chevron-down',
+ navigationIcon: 'mdi-circle'
+ },
+ chip: {
+ remove: 'mdi-close-circle',
+ selected: 'mdi-check'
+ },
+ datetime: {
+ arrowLeft: 'mdi-chevron-left',
+ arrowRight: 'mdi-chevron-right',
+ now: 'mdi-clock-outline',
+ today: 'mdi-calendar-today'
+ },
+ editor: {
+ bold: 'mdi-format-bold',
+ italic: 'mdi-format-italic',
+ strikethrough: 'mdi-format-strikethrough-variant',
+ underline: 'mdi-format-underline',
+ unorderedList: 'mdi-format-list-bulleted',
+ orderedList: 'mdi-format-list-numbered',
+ subscript: 'mdi-format-subscript',
+ superscript: 'mdi-format-superscript',
+ hyperlink: 'mdi-link',
+ toggleFullscreen: 'mdi-fullscreen',
+ quote: 'mdi-format-quote-close',
+ left: 'mdi-format-align-left',
+ center: 'mdi-format-align-center',
+ right: 'mdi-format-align-right',
+ justify: 'mdi-format-align-justify',
+ print: 'mdi-printer',
+ outdent: 'mdi-format-indent-decrease',
+ indent: 'mdi-format-indent-increase',
+ removeFormat: 'mdi-format-clear',
+ formatting: 'mdi-format-color-text',
+ fontSize: 'mdi-format-size',
+ align: 'mdi-format-align-left',
+ hr: 'mdi-minus',
+ undo: 'mdi-undo',
+ redo: 'mdi-redo',
+ heading: 'mdi-format-size',
+ heading1: 'mdi-format-header-1',
+ heading2: 'mdi-format-header-2',
+ heading3: 'mdi-format-header-3',
+ heading4: 'mdi-format-header-4',
+ heading5: 'mdi-format-header-5',
+ heading6: 'mdi-format-header-6',
+ code: 'mdi-code-tags',
+ size: 'mdi-format-size',
+ size1: 'mdi-numeric-1-box',
+ size2: 'mdi-numeric-2-box',
+ size3: 'mdi-numeric-3-box',
+ size4: 'mdi-numeric-4-box',
+ size5: 'mdi-numeric-5-box',
+ size6: 'mdi-numeric-6-box',
+ size7: 'mdi-numeric-7-box',
+ font: 'mdi-format-font',
+ viewSource: 'mdi-code-tags'
+ },
+ expansionItem: {
+ icon: 'mdi-chevron-down',
+ denseIcon: 'mdi-menu-down'
+ },
+ fab: {
+ icon: 'mdi-plus',
+ activeIcon: 'mdi-close'
+ },
+ field: {
+ clear: 'mdi-close-circle',
+ error: 'mdi-alert-circle'
+ },
+ pagination: {
+ first: 'mdi-chevron-double-left',
+ prev: 'mdi-chevron-left',
+ next: 'mdi-chevron-right',
+ last: 'mdi-chevron-double-right'
+ },
+ rating: {
+ icon: 'mdi-star'
+ },
+ stepper: {
+ done: 'mdi-check',
+ active: 'mdi-pencil',
+ error: 'mdi-alert'
+ },
+ tabs: {
+ left: 'mdi-chevron-left',
+ right: 'mdi-chevron-right',
+ up: 'mdi-chevron-up',
+ down: 'mdi-chevron-down'
+ },
+ table: {
+ arrowUp: 'mdi-arrow-up',
+ warning: 'mdi-alert',
+ firstPage: 'mdi-chevron-double-left',
+ prevPage: 'mdi-chevron-left',
+ nextPage: 'mdi-chevron-right',
+ lastPage: 'mdi-chevron-double-right'
+ },
+ tree: {
+ icon: 'mdi-play'
+ },
+ uploader: {
+ done: 'mdi-check',
+ clear: 'mdi-close',
+ add: 'mdi-plus-box',
+ upload: 'mdi-cloud-upload',
+ removeQueue: 'mdi-notification-clear-all',
+ removeUploaded: 'mdi-check-all'
+ }
+}
diff --git a/ui/icon-set/mdi-v7.js b/ui/icon-set/mdi-v7.js
new file mode 100644
index 00000000000..4f7b1219104
--- /dev/null
+++ b/ui/icon-set/mdi-v7.js
@@ -0,0 +1,141 @@
+export default {
+ name: 'mdi-v7',
+ type: {
+ positive: 'mdi-check-circle',
+ negative: 'mdi-alert',
+ info: 'mdi-information',
+ warning: 'mdi-exclamation'
+ },
+ arrow: {
+ up: 'mdi-arrow-up',
+ right: 'mdi-arrow-right',
+ down: 'mdi-arrow-down',
+ left: 'mdi-arrow-left',
+ dropdown: 'mdi-menu-down'
+ },
+ chevron: {
+ left: 'mdi-chevron-left',
+ right: 'mdi-chevron-right'
+ },
+ colorPicker: {
+ spectrum: 'mdi-gradient-vertical',
+ tune: 'mdi-tune',
+ palette: 'mdi-palette-swatch'
+ },
+ pullToRefresh: {
+ icon: 'mdi-refresh'
+ },
+ carousel: {
+ left: 'mdi-chevron-left',
+ right: 'mdi-chevron-right',
+ up: 'mdi-chevron-up',
+ down: 'mdi-chevron-down',
+ navigationIcon: 'mdi-circle'
+ },
+ chip: {
+ remove: 'mdi-close-circle',
+ selected: 'mdi-check'
+ },
+ datetime: {
+ arrowLeft: 'mdi-chevron-left',
+ arrowRight: 'mdi-chevron-right',
+ now: 'mdi-clock-outline',
+ today: 'mdi-calendar-today'
+ },
+ editor: {
+ bold: 'mdi-format-bold',
+ italic: 'mdi-format-italic',
+ strikethrough: 'mdi-format-strikethrough-variant',
+ underline: 'mdi-format-underline',
+ unorderedList: 'mdi-format-list-bulleted',
+ orderedList: 'mdi-format-list-numbered',
+ subscript: 'mdi-format-subscript',
+ superscript: 'mdi-format-superscript',
+ hyperlink: 'mdi-link',
+ toggleFullscreen: 'mdi-fullscreen',
+ quote: 'mdi-format-quote-close',
+ left: 'mdi-format-align-left',
+ center: 'mdi-format-align-center',
+ right: 'mdi-format-align-right',
+ justify: 'mdi-format-align-justify',
+ print: 'mdi-printer',
+ outdent: 'mdi-format-indent-decrease',
+ indent: 'mdi-format-indent-increase',
+ removeFormat: 'mdi-format-clear',
+ formatting: 'mdi-format-color-text',
+ fontSize: 'mdi-format-size',
+ align: 'mdi-format-align-left',
+ hr: 'mdi-minus',
+ undo: 'mdi-undo',
+ redo: 'mdi-redo',
+ heading: 'mdi-format-size',
+ heading1: 'mdi-format-header-1',
+ heading2: 'mdi-format-header-2',
+ heading3: 'mdi-format-header-3',
+ heading4: 'mdi-format-header-4',
+ heading5: 'mdi-format-header-5',
+ heading6: 'mdi-format-header-6',
+ code: 'mdi-code-tags',
+ size: 'mdi-format-size',
+ size1: 'mdi-numeric-1-box',
+ size2: 'mdi-numeric-2-box',
+ size3: 'mdi-numeric-3-box',
+ size4: 'mdi-numeric-4-box',
+ size5: 'mdi-numeric-5-box',
+ size6: 'mdi-numeric-6-box',
+ size7: 'mdi-numeric-7-box',
+ font: 'mdi-format-font',
+ viewSource: 'mdi-code-tags'
+ },
+ expansionItem: {
+ icon: 'mdi-chevron-down',
+ denseIcon: 'mdi-menu-down'
+ },
+ fab: {
+ icon: 'mdi-plus',
+ activeIcon: 'mdi-close'
+ },
+ field: {
+ clear: 'mdi-close-circle',
+ error: 'mdi-alert-circle'
+ },
+ pagination: {
+ first: 'mdi-chevron-double-left',
+ prev: 'mdi-chevron-left',
+ next: 'mdi-chevron-right',
+ last: 'mdi-chevron-double-right'
+ },
+ rating: {
+ icon: 'mdi-star'
+ },
+ stepper: {
+ done: 'mdi-check',
+ active: 'mdi-pencil',
+ error: 'mdi-alert'
+ },
+ tabs: {
+ left: 'mdi-chevron-left',
+ right: 'mdi-chevron-right',
+ up: 'mdi-chevron-up',
+ down: 'mdi-chevron-down'
+ },
+ table: {
+ arrowUp: 'mdi-arrow-up',
+ warning: 'mdi-alert',
+ firstPage: 'mdi-chevron-double-left',
+ prevPage: 'mdi-chevron-left',
+ nextPage: 'mdi-chevron-right',
+ lastPage: 'mdi-chevron-double-right'
+ },
+ tree: {
+ icon: 'mdi-play'
+ },
+ uploader: {
+ done: 'mdi-check',
+ clear: 'mdi-close',
+ add: 'mdi-plus-box',
+ upload: 'mdi-cloud-upload',
+ removeQueue: 'mdi-notification-clear-all',
+ removeUploaded: 'mdi-check-all'
+ }
+}
diff --git a/ui/icon-set/svg-bootstrap-icons.js b/ui/icon-set/svg-bootstrap-icons.js
index a4b87a3c2fd..fb5620137e5 100644
--- a/ui/icon-set/svg-bootstrap-icons.js
+++ b/ui/icon-set/svg-bootstrap-icons.js
@@ -77,7 +77,7 @@ import {
import {
mdiFormatSubscript,
mdiFormatSuperscript
-} from '@quasar/extras/mdi-v5'
+} from '@quasar/extras/mdi-v6'
diff --git a/ui/icon-set/svg-eva-icons.js b/ui/icon-set/svg-eva-icons.js
index e73b85a0826..f4bcb6177bd 100644
--- a/ui/icon-set/svg-eva-icons.js
+++ b/ui/icon-set/svg-eva-icons.js
@@ -87,7 +87,7 @@ import {
mdiNumeric6Box,
mdiNumeric7Box,
mdiFormatFont
-} from '@quasar/extras/mdi-v5'
+} from '@quasar/extras/mdi-v6'
diff --git a/ui/icon-set/svg-fontawesome-v6.js b/ui/icon-set/svg-fontawesome-v6.js
new file mode 100644
index 00000000000..6b8a34edd40
--- /dev/null
+++ b/ui/icon-set/svg-fontawesome-v6.js
@@ -0,0 +1,198 @@
+
+/*
+ * Do not edit this file. It is automatically generated
+ * from its webfont counterpart (same filename without "svg-" prefix).
+ * Edit that file instead (fontawesome-v6.js).
+ */
+
+
+import {
+ fasCheck,
+ fasTriangleExclamation,
+ fasCircleInfo,
+ fasExclamation,
+ fasArrowUp,
+ fasArrowRight,
+ fasArrowDown,
+ fasArrowLeft,
+ fasCaretDown,
+ fasChevronLeft,
+ fasChevronRight,
+ fasEyeDropper,
+ fasSliders,
+ fasSwatchbook,
+ fasRotate,
+ fasChevronUp,
+ fasChevronDown,
+ fasCircle,
+ fasCircleXmark,
+ farClock,
+ farCalendarCheck,
+ fasBold,
+ fasItalic,
+ fasStrikethrough,
+ fasUnderline,
+ fasListUl,
+ fasListOl,
+ fasSubscript,
+ fasSuperscript,
+ fasLink,
+ fasMaximize,
+ fasQuoteRight,
+ fasAlignLeft,
+ fasAlignCenter,
+ fasAlignRight,
+ fasAlignJustify,
+ fasPrint,
+ fasOutdent,
+ fasIndent,
+ fasEraser,
+ fasHeading,
+ fasTextHeight,
+ farSquareMinus,
+ fasRotateLeft,
+ fasRotateRight,
+ fasCode,
+ fasFont,
+ fasPlus,
+ fasXmark,
+ fasCircleExclamation,
+ fasBackwardStep,
+ fasForwardStep,
+ fasStar,
+ fasPencil,
+ fasPlay,
+ fasSquarePlus,
+ fasUpload,
+ fasBarsStaggered,
+ fasClipboardCheck
+} from '@quasar/extras/fontawesome-v6'
+
+export default {
+ name: 'svg-fontawesome-v6',
+ type: {
+ positive: fasCheck,
+ negative: fasTriangleExclamation,
+ info: fasCircleInfo,
+ warning: fasExclamation
+ },
+ arrow: {
+ up: fasArrowUp,
+ right: fasArrowRight,
+ down: fasArrowDown,
+ left: fasArrowLeft,
+ dropdown: fasCaretDown
+ },
+ chevron: {
+ left: fasChevronLeft,
+ right: fasChevronRight
+ },
+ colorPicker: {
+ spectrum: fasEyeDropper,
+ tune: fasSliders,
+ palette: fasSwatchbook
+ },
+ pullToRefresh: {
+ icon: fasRotate
+ },
+ carousel: {
+ left: fasChevronLeft,
+ right: fasChevronRight,
+ up: fasChevronUp,
+ down: fasChevronDown,
+ navigationIcon: fasCircle
+ },
+ chip: {
+ remove: fasCircleXmark,
+ selected: fasCheck
+ },
+ datetime: {
+ arrowLeft: fasChevronLeft,
+ arrowRight: fasChevronRight,
+ now: farClock,
+ today: farCalendarCheck
+ },
+ editor: {
+ bold: fasBold,
+ italic: fasItalic,
+ strikethrough: fasStrikethrough,
+ underline: fasUnderline,
+ unorderedList: fasListUl,
+ orderedList: fasListOl,
+ subscript: fasSubscript,
+ superscript: fasSuperscript,
+ hyperlink: fasLink,
+ toggleFullscreen: fasMaximize,
+ quote: fasQuoteRight,
+ left: fasAlignLeft,
+ center: fasAlignCenter,
+ right: fasAlignRight,
+ justify: fasAlignJustify,
+ print: fasPrint,
+ outdent: fasOutdent,
+ indent: fasIndent,
+ removeFormat: fasEraser,
+ formatting: fasHeading,
+ fontSize: fasTextHeight,
+ align: fasAlignLeft,
+ hr: farSquareMinus,
+ undo: fasRotateLeft,
+ redo: fasRotateRight,
+ heading: fasHeading,
+ code: fasCode,
+ size: fasTextHeight,
+ font: fasFont,
+ viewSource: fasCode
+ },
+ expansionItem: {
+ icon: fasChevronDown,
+ denseIcon: fasCaretDown
+ },
+ fab: {
+ icon: fasPlus,
+ activeIcon: fasXmark
+ },
+ field: {
+ clear: fasCircleXmark,
+ error: fasCircleExclamation
+ },
+ pagination: {
+ first: fasBackwardStep,
+ prev: fasChevronLeft,
+ next: fasChevronRight,
+ last: fasForwardStep
+ },
+ rating: {
+ icon: fasStar
+ },
+ stepper: {
+ done: fasCheck,
+ active: fasPencil,
+ error: fasTriangleExclamation
+ },
+ tabs: {
+ left: fasChevronLeft,
+ right: fasChevronRight,
+ up: fasChevronUp,
+ down: fasChevronDown
+ },
+ table: {
+ arrowUp: fasArrowUp,
+ warning: fasTriangleExclamation,
+ firstPage: fasBackwardStep,
+ prevPage: fasChevronLeft,
+ nextPage: fasChevronRight,
+ lastPage: fasForwardStep
+ },
+ tree: {
+ icon: fasPlay
+ },
+ uploader: {
+ done: fasCheck,
+ clear: fasXmark,
+ add: fasSquarePlus,
+ upload: fasUpload,
+ removeQueue: fasBarsStaggered,
+ removeUploaded: fasClipboardCheck
+ }
+}
diff --git a/ui/icon-set/svg-ionicons-v4.js b/ui/icon-set/svg-ionicons-v4.js
index ce9703b2c99..247b5ada96c 100644
--- a/ui/icon-set/svg-ionicons-v4.js
+++ b/ui/icon-set/svg-ionicons-v4.js
@@ -87,7 +87,7 @@ import {
mdiNumeric6Box,
mdiNumeric7Box,
mdiFormatFont
-} from '@quasar/extras/mdi-v5'
+} from '@quasar/extras/mdi-v6'
diff --git a/ui/icon-set/svg-ionicons-v5.js b/ui/icon-set/svg-ionicons-v5.js
index 85a500a7003..f48d85bf260 100644
--- a/ui/icon-set/svg-ionicons-v5.js
+++ b/ui/icon-set/svg-ionicons-v5.js
@@ -79,7 +79,7 @@ import {
mdiNumeric6Box,
mdiNumeric7Box,
mdiFormatFont
-} from '@quasar/extras/mdi-v5'
+} from '@quasar/extras/mdi-v6'
export default {
name: 'svg-ionicons-v5',
diff --git a/ui/icon-set/svg-ionicons-v6.js b/ui/icon-set/svg-ionicons-v6.js
new file mode 100644
index 00000000000..d24f4b3ba1b
--- /dev/null
+++ b/ui/icon-set/svg-ionicons-v6.js
@@ -0,0 +1,225 @@
+
+import {
+ ionCheckmark,
+ ionAlert,
+ ionInformationCircleOutline,
+ ionArrowUp,
+ ionArrowForward,
+ ionArrowDown,
+ ionArrowBack,
+ ionCaretDownOutline,
+ ionAperture,
+ ionOptions,
+ ionApps,
+ ionRefresh,
+ ionSquare,
+ ionCloseCircle,
+ ionTime,
+ ionCalendar,
+ ionLink,
+ ionExpand,
+ ionChatboxEllipses,
+ ionPrint,
+ ionArrowUndo,
+ ionArrowRedo,
+ ionCodeSlash,
+ ionAdd,
+ ionClose,
+ ionPlaySkipBackCircle,
+ ionPlaySkipForwardCircle,
+ ionStar,
+ ionCreate,
+ ionWarning,
+ ionPlay,
+ ionAddCircle,
+ ionCloudUpload,
+ ionTrash,
+ ionCheckmarkDone,
+ ionChevronDown,
+ ionChevronUp,
+ ionChevronBack,
+ ionChevronForward,
+ ionChevronBackCircle,
+ ionChevronForwardCircle
+} from '@quasar/extras/ionicons-v6'
+
+// there are some icons that are needed but not available
+// so we import them from MDI as svgs
+
+import {
+ mdiFormatBold,
+ mdiFormatItalic,
+ mdiFormatStrikethroughVariant,
+ mdiFormatUnderline,
+ mdiFormatListBulleted,
+ mdiFormatListNumbered,
+ mdiFormatSubscript,
+ mdiFormatSuperscript,
+ mdiFormatAlignLeft,
+ mdiFormatAlignCenter,
+ mdiFormatAlignRight,
+ mdiFormatAlignJustify,
+ mdiFormatIndentDecrease,
+ mdiFormatIndentIncrease,
+ mdiFormatClear,
+ mdiFormatColorText,
+ mdiFormatSize,
+ mdiMinus,
+ mdiFormatHeader1,
+ mdiFormatHeader2,
+ mdiFormatHeader3,
+ mdiFormatHeader4,
+ mdiFormatHeader5,
+ mdiFormatHeader6,
+ mdiNumeric1Box,
+ mdiNumeric2Box,
+ mdiNumeric3Box,
+ mdiNumeric4Box,
+ mdiNumeric5Box,
+ mdiNumeric6Box,
+ mdiNumeric7Box,
+ mdiFormatFont
+} from '@quasar/extras/mdi-v6'
+
+export default {
+ name: 'svg-ionicons-v6',
+ type: {
+ positive: ionCheckmark,
+ negative: ionAlert,
+ info: ionInformationCircleOutline,
+ warning: ionAlert
+ },
+ arrow: {
+ up: ionArrowUp,
+ right: ionArrowForward,
+ down: ionArrowDown,
+ left: ionArrowBack,
+ dropdown: ionCaretDownOutline
+ },
+ chevron: {
+ left: ionArrowBack,
+ right: ionArrowForward
+ },
+ colorPicker: {
+ spectrum: ionAperture,
+ tune: ionOptions,
+ palette: ionApps
+ },
+ pullToRefresh: {
+ icon: ionRefresh
+ },
+ carousel: {
+ left: ionChevronBack,
+ right: ionChevronForward,
+ up: ionChevronUp,
+ down: ionChevronDown,
+ navigationIcon: ionSquare
+ },
+ chip: {
+ remove: ionCloseCircle,
+ selected: ionCheckmark
+ },
+ datetime: {
+ arrowLeft: ionChevronBack,
+ arrowRight: ionChevronForward,
+ now: ionTime,
+ today: ionCalendar
+ },
+ editor: { // requires Material icons for some as Ionicons simply does not have everything needed
+ hyperlink: ionLink,
+ toggleFullscreen: ionExpand,
+ quote: ionChatboxEllipses,
+ print: ionPrint,
+ undo: ionArrowUndo,
+ redo: ionArrowRedo,
+ code: ionCodeSlash,
+ viewSource: ionCodeSlash,
+
+ bold: mdiFormatBold,
+ italic: mdiFormatItalic,
+ strikethrough: mdiFormatStrikethroughVariant,
+ underline: mdiFormatUnderline,
+ unorderedList: mdiFormatListBulleted,
+ orderedList: mdiFormatListNumbered,
+ subscript: mdiFormatSubscript,
+ superscript: mdiFormatSuperscript,
+ left: mdiFormatAlignLeft,
+ center: mdiFormatAlignCenter,
+ right: mdiFormatAlignRight,
+ justify: mdiFormatAlignJustify,
+ outdent: mdiFormatIndentDecrease,
+ indent: mdiFormatIndentIncrease,
+ removeFormat: mdiFormatClear,
+ formatting: mdiFormatColorText,
+ fontSize: mdiFormatSize,
+ align: mdiFormatAlignLeft,
+ hr: mdiMinus,
+ heading: mdiFormatSize,
+ heading1: mdiFormatHeader1,
+ heading2: mdiFormatHeader2,
+ heading3: mdiFormatHeader3,
+ heading4: mdiFormatHeader4,
+ heading5: mdiFormatHeader5,
+ heading6: mdiFormatHeader6,
+ size: mdiFormatSize,
+ size1: mdiNumeric1Box,
+ size2: mdiNumeric2Box,
+ size3: mdiNumeric3Box,
+ size4: mdiNumeric4Box,
+ size5: mdiNumeric5Box,
+ size6: mdiNumeric6Box,
+ size7: mdiNumeric7Box,
+ font: mdiFormatFont
+ },
+ expansionItem: {
+ icon: ionCaretDownOutline,
+ denseIcon: ionCaretDownOutline
+ },
+ fab: {
+ icon: ionAdd,
+ activeIcon: ionClose
+ },
+ field: {
+ clear: ionCloseCircle,
+ error: ionAlert
+ },
+ pagination: {
+ first: ionPlaySkipBackCircle,
+ prev: ionChevronBackCircle,
+ next: ionChevronForwardCircle,
+ last: ionPlaySkipForwardCircle
+ },
+ rating: {
+ icon: ionStar
+ },
+ stepper: {
+ done: ionCheckmark,
+ active: ionCreate,
+ error: ionWarning
+ },
+ tabs: {
+ left: ionChevronBack,
+ right: ionChevronForward,
+ up: ionChevronUp,
+ down: ionChevronDown
+ },
+ table: {
+ arrowUp: ionArrowUp,
+ warning: ionWarning,
+ firstPage: ionPlaySkipBackCircle,
+ prevPage: ionChevronBackCircle,
+ nextPage: ionChevronForwardCircle,
+ lastPage: ionPlaySkipForwardCircle
+ },
+ tree: {
+ icon: ionPlay
+ },
+ uploader: {
+ done: ionCheckmark,
+ clear: ionClose,
+ add: ionAddCircle,
+ upload: ionCloudUpload,
+ removeQueue: ionTrash,
+ removeUploaded: ionCheckmarkDone
+ }
+}
diff --git a/ui/icon-set/svg-material-symbols-outlined.js b/ui/icon-set/svg-material-symbols-outlined.js
new file mode 100644
index 00000000000..33c59defe76
--- /dev/null
+++ b/ui/icon-set/svg-material-symbols-outlined.js
@@ -0,0 +1,202 @@
+
+/*
+ * Do not edit this file. It is automatically generated
+ * from its webfont counterpart (same filename without "svg-" prefix).
+ * Edit that file instead (material-symbols-outlined.js).
+ */
+
+
+import {
+ symOutlinedCheckCircle,
+ symOutlinedWarning,
+ symOutlinedInfo,
+ symOutlinedPriorityHigh,
+ symOutlinedArrowUpward,
+ symOutlinedArrowForward,
+ symOutlinedArrowDownward,
+ symOutlinedArrowBack,
+ symOutlinedArrowDropDown,
+ symOutlinedChevronLeft,
+ symOutlinedChevronRight,
+ symOutlinedGradient,
+ symOutlinedTune,
+ symOutlinedStyle,
+ symOutlinedRefresh,
+ symOutlinedKeyboardArrowUp,
+ symOutlinedKeyboardArrowDown,
+ symOutlinedLens,
+ symOutlinedCancel,
+ symOutlinedCheck,
+ symOutlinedSchedule,
+ symOutlinedToday,
+ symOutlinedFormatBold,
+ symOutlinedFormatItalic,
+ symOutlinedStrikethroughS,
+ symOutlinedFormatUnderlined,
+ symOutlinedFormatListBulleted,
+ symOutlinedFormatListNumbered,
+ symOutlinedVerticalAlignBottom,
+ symOutlinedVerticalAlignTop,
+ symOutlinedLink,
+ symOutlinedFullscreen,
+ symOutlinedFormatQuote,
+ symOutlinedFormatAlignLeft,
+ symOutlinedFormatAlignCenter,
+ symOutlinedFormatAlignRight,
+ symOutlinedFormatAlignJustify,
+ symOutlinedPrint,
+ symOutlinedFormatIndentDecrease,
+ symOutlinedFormatIndentIncrease,
+ symOutlinedFormatClear,
+ symOutlinedTextFormat,
+ symOutlinedFormatSize,
+ symOutlinedRemove,
+ symOutlinedUndo,
+ symOutlinedRedo,
+ symOutlinedCode,
+ symOutlinedFontDownload,
+ symOutlinedAdd,
+ symOutlinedClose,
+ symOutlinedError,
+ symOutlinedFirstPage,
+ symOutlinedKeyboardArrowLeft,
+ symOutlinedKeyboardArrowRight,
+ symOutlinedLastPage,
+ symOutlinedGrade,
+ symOutlinedEdit,
+ symOutlinedPlayArrow,
+ symOutlinedDone,
+ symOutlinedAddBox,
+ symOutlinedCloudUpload,
+ symOutlinedClearAll,
+ symOutlinedDoneAll
+} from '@quasar/extras/material-symbols-outlined'
+
+export default {
+ name: 'svg-material-symbols-outlined',
+ type: {
+ positive: symOutlinedCheckCircle,
+ negative: symOutlinedWarning,
+ info: symOutlinedInfo,
+ warning: symOutlinedPriorityHigh
+ },
+ arrow: {
+ up: symOutlinedArrowUpward,
+ right: symOutlinedArrowForward,
+ down: symOutlinedArrowDownward,
+ left: symOutlinedArrowBack,
+ dropdown: symOutlinedArrowDropDown
+ },
+ chevron: {
+ left: symOutlinedChevronLeft,
+ right: symOutlinedChevronRight
+ },
+ colorPicker: {
+ spectrum: symOutlinedGradient,
+ tune: symOutlinedTune,
+ palette: symOutlinedStyle
+ },
+ pullToRefresh: {
+ icon: symOutlinedRefresh
+ },
+ carousel: {
+ left: symOutlinedChevronLeft,
+ right: symOutlinedChevronRight,
+ up: symOutlinedKeyboardArrowUp,
+ down: symOutlinedKeyboardArrowDown,
+ navigationIcon: symOutlinedLens
+ },
+ chip: {
+ remove: symOutlinedCancel,
+ selected: symOutlinedCheck
+ },
+ datetime: {
+ arrowLeft: symOutlinedChevronLeft,
+ arrowRight: symOutlinedChevronRight,
+ now: symOutlinedSchedule,
+ today: symOutlinedToday
+ },
+ editor: {
+ bold: symOutlinedFormatBold,
+ italic: symOutlinedFormatItalic,
+ strikethrough: symOutlinedStrikethroughS,
+ underline: symOutlinedFormatUnderlined,
+ unorderedList: symOutlinedFormatListBulleted,
+ orderedList: symOutlinedFormatListNumbered,
+ subscript: symOutlinedVerticalAlignBottom,
+ superscript: symOutlinedVerticalAlignTop,
+ hyperlink: symOutlinedLink,
+ toggleFullscreen: symOutlinedFullscreen,
+ quote: symOutlinedFormatQuote,
+ left: symOutlinedFormatAlignLeft,
+ center: symOutlinedFormatAlignCenter,
+ right: symOutlinedFormatAlignRight,
+ justify: symOutlinedFormatAlignJustify,
+ print: symOutlinedPrint,
+ outdent: symOutlinedFormatIndentDecrease,
+ indent: symOutlinedFormatIndentIncrease,
+ removeFormat: symOutlinedFormatClear,
+ formatting: symOutlinedTextFormat,
+ fontSize: symOutlinedFormatSize,
+ align: symOutlinedFormatAlignLeft,
+ hr: symOutlinedRemove,
+ undo: symOutlinedUndo,
+ redo: symOutlinedRedo,
+ heading: symOutlinedFormatSize,
+ code: symOutlinedCode,
+ size: symOutlinedFormatSize,
+ font: symOutlinedFontDownload,
+ viewSource: symOutlinedCode
+ },
+ expansionItem: {
+ icon: symOutlinedKeyboardArrowDown,
+ denseIcon: symOutlinedArrowDropDown
+ },
+ fab: {
+ icon: symOutlinedAdd,
+ activeIcon: symOutlinedClose
+ },
+ field: {
+ clear: symOutlinedCancel,
+ error: symOutlinedError
+ },
+ pagination: {
+ first: symOutlinedFirstPage,
+ prev: symOutlinedKeyboardArrowLeft,
+ next: symOutlinedKeyboardArrowRight,
+ last: symOutlinedLastPage
+ },
+ rating: {
+ icon: symOutlinedGrade
+ },
+ stepper: {
+ done: symOutlinedCheck,
+ active: symOutlinedEdit,
+ error: symOutlinedWarning
+ },
+ tabs: {
+ left: symOutlinedChevronLeft,
+ right: symOutlinedChevronRight,
+ up: symOutlinedKeyboardArrowUp,
+ down: symOutlinedKeyboardArrowDown
+ },
+ table: {
+ arrowUp: symOutlinedArrowUpward,
+ warning: symOutlinedWarning,
+ firstPage: symOutlinedFirstPage,
+ prevPage: symOutlinedChevronLeft,
+ nextPage: symOutlinedChevronRight,
+ lastPage: symOutlinedLastPage
+ },
+ tree: {
+ icon: symOutlinedPlayArrow
+ },
+ uploader: {
+ done: symOutlinedDone,
+ clear: symOutlinedClose,
+ add: symOutlinedAddBox,
+ upload: symOutlinedCloudUpload,
+ removeQueue: symOutlinedClearAll,
+ removeUploaded: symOutlinedDoneAll
+ }
+}
diff --git a/ui/icon-set/svg-material-symbols-rounded.js b/ui/icon-set/svg-material-symbols-rounded.js
new file mode 100644
index 00000000000..3edc046a9a1
--- /dev/null
+++ b/ui/icon-set/svg-material-symbols-rounded.js
@@ -0,0 +1,202 @@
+
+/*
+ * Do not edit this file. It is automatically generated
+ * from its webfont counterpart (same filename without "svg-" prefix).
+ * Edit that file instead (material-symbols-rounded.js).
+ */
+
+
+import {
+ symRoundedCheckCircle,
+ symRoundedWarning,
+ symRoundedInfo,
+ symRoundedPriorityHigh,
+ symRoundedArrowUpward,
+ symRoundedArrowForward,
+ symRoundedArrowDownward,
+ symRoundedArrowBack,
+ symRoundedArrowDropDown,
+ symRoundedChevronLeft,
+ symRoundedChevronRight,
+ symRoundedGradient,
+ symRoundedTune,
+ symRoundedStyle,
+ symRoundedRefresh,
+ symRoundedKeyboardArrowUp,
+ symRoundedKeyboardArrowDown,
+ symRoundedLens,
+ symRoundedCancel,
+ symRoundedCheck,
+ symRoundedSchedule,
+ symRoundedToday,
+ symRoundedFormatBold,
+ symRoundedFormatItalic,
+ symRoundedStrikethroughS,
+ symRoundedFormatUnderlined,
+ symRoundedFormatListBulleted,
+ symRoundedFormatListNumbered,
+ symRoundedVerticalAlignBottom,
+ symRoundedVerticalAlignTop,
+ symRoundedLink,
+ symRoundedFullscreen,
+ symRoundedFormatQuote,
+ symRoundedFormatAlignLeft,
+ symRoundedFormatAlignCenter,
+ symRoundedFormatAlignRight,
+ symRoundedFormatAlignJustify,
+ symRoundedPrint,
+ symRoundedFormatIndentDecrease,
+ symRoundedFormatIndentIncrease,
+ symRoundedFormatClear,
+ symRoundedTextFormat,
+ symRoundedFormatSize,
+ symRoundedRemove,
+ symRoundedUndo,
+ symRoundedRedo,
+ symRoundedCode,
+ symRoundedFontDownload,
+ symRoundedAdd,
+ symRoundedClose,
+ symRoundedError,
+ symRoundedFirstPage,
+ symRoundedKeyboardArrowLeft,
+ symRoundedKeyboardArrowRight,
+ symRoundedLastPage,
+ symRoundedGrade,
+ symRoundedEdit,
+ symRoundedPlayArrow,
+ symRoundedDone,
+ symRoundedAddBox,
+ symRoundedCloudUpload,
+ symRoundedClearAll,
+ symRoundedDoneAll
+} from '@quasar/extras/material-symbols-rounded'
+
+export default {
+ name: 'svg-material-symbols-rounded',
+ type: {
+ positive: symRoundedCheckCircle,
+ negative: symRoundedWarning,
+ info: symRoundedInfo,
+ warning: symRoundedPriorityHigh
+ },
+ arrow: {
+ up: symRoundedArrowUpward,
+ right: symRoundedArrowForward,
+ down: symRoundedArrowDownward,
+ left: symRoundedArrowBack,
+ dropdown: symRoundedArrowDropDown
+ },
+ chevron: {
+ left: symRoundedChevronLeft,
+ right: symRoundedChevronRight
+ },
+ colorPicker: {
+ spectrum: symRoundedGradient,
+ tune: symRoundedTune,
+ palette: symRoundedStyle
+ },
+ pullToRefresh: {
+ icon: symRoundedRefresh
+ },
+ carousel: {
+ left: symRoundedChevronLeft,
+ right: symRoundedChevronRight,
+ up: symRoundedKeyboardArrowUp,
+ down: symRoundedKeyboardArrowDown,
+ navigationIcon: symRoundedLens
+ },
+ chip: {
+ remove: symRoundedCancel,
+ selected: symRoundedCheck
+ },
+ datetime: {
+ arrowLeft: symRoundedChevronLeft,
+ arrowRight: symRoundedChevronRight,
+ now: symRoundedSchedule,
+ today: symRoundedToday
+ },
+ editor: {
+ bold: symRoundedFormatBold,
+ italic: symRoundedFormatItalic,
+ strikethrough: symRoundedStrikethroughS,
+ underline: symRoundedFormatUnderlined,
+ unorderedList: symRoundedFormatListBulleted,
+ orderedList: symRoundedFormatListNumbered,
+ subscript: symRoundedVerticalAlignBottom,
+ superscript: symRoundedVerticalAlignTop,
+ hyperlink: symRoundedLink,
+ toggleFullscreen: symRoundedFullscreen,
+ quote: symRoundedFormatQuote,
+ left: symRoundedFormatAlignLeft,
+ center: symRoundedFormatAlignCenter,
+ right: symRoundedFormatAlignRight,
+ justify: symRoundedFormatAlignJustify,
+ print: symRoundedPrint,
+ outdent: symRoundedFormatIndentDecrease,
+ indent: symRoundedFormatIndentIncrease,
+ removeFormat: symRoundedFormatClear,
+ formatting: symRoundedTextFormat,
+ fontSize: symRoundedFormatSize,
+ align: symRoundedFormatAlignLeft,
+ hr: symRoundedRemove,
+ undo: symRoundedUndo,
+ redo: symRoundedRedo,
+ heading: symRoundedFormatSize,
+ code: symRoundedCode,
+ size: symRoundedFormatSize,
+ font: symRoundedFontDownload,
+ viewSource: symRoundedCode
+ },
+ expansionItem: {
+ icon: symRoundedKeyboardArrowDown,
+ denseIcon: symRoundedArrowDropDown
+ },
+ fab: {
+ icon: symRoundedAdd,
+ activeIcon: symRoundedClose
+ },
+ field: {
+ clear: symRoundedCancel,
+ error: symRoundedError
+ },
+ pagination: {
+ first: symRoundedFirstPage,
+ prev: symRoundedKeyboardArrowLeft,
+ next: symRoundedKeyboardArrowRight,
+ last: symRoundedLastPage
+ },
+ rating: {
+ icon: symRoundedGrade
+ },
+ stepper: {
+ done: symRoundedCheck,
+ active: symRoundedEdit,
+ error: symRoundedWarning
+ },
+ tabs: {
+ left: symRoundedChevronLeft,
+ right: symRoundedChevronRight,
+ up: symRoundedKeyboardArrowUp,
+ down: symRoundedKeyboardArrowDown
+ },
+ table: {
+ arrowUp: symRoundedArrowUpward,
+ warning: symRoundedWarning,
+ firstPage: symRoundedFirstPage,
+ prevPage: symRoundedChevronLeft,
+ nextPage: symRoundedChevronRight,
+ lastPage: symRoundedLastPage
+ },
+ tree: {
+ icon: symRoundedPlayArrow
+ },
+ uploader: {
+ done: symRoundedDone,
+ clear: symRoundedClose,
+ add: symRoundedAddBox,
+ upload: symRoundedCloudUpload,
+ removeQueue: symRoundedClearAll,
+ removeUploaded: symRoundedDoneAll
+ }
+}
diff --git a/ui/icon-set/svg-material-symbols-sharp.js b/ui/icon-set/svg-material-symbols-sharp.js
new file mode 100644
index 00000000000..3066f4d62df
--- /dev/null
+++ b/ui/icon-set/svg-material-symbols-sharp.js
@@ -0,0 +1,202 @@
+
+/*
+ * Do not edit this file. It is automatically generated
+ * from its webfont counterpart (same filename without "svg-" prefix).
+ * Edit that file instead (material-symbols-sharp.js).
+ */
+
+
+import {
+ symSharpCheckCircle,
+ symSharpWarning,
+ symSharpInfo,
+ symSharpPriorityHigh,
+ symSharpArrowUpward,
+ symSharpArrowForward,
+ symSharpArrowDownward,
+ symSharpArrowBack,
+ symSharpArrowDropDown,
+ symSharpChevronLeft,
+ symSharpChevronRight,
+ symSharpGradient,
+ symSharpTune,
+ symSharpStyle,
+ symSharpRefresh,
+ symSharpKeyboardArrowUp,
+ symSharpKeyboardArrowDown,
+ symSharpLens,
+ symSharpCancel,
+ symSharpCheck,
+ symSharpSchedule,
+ symSharpToday,
+ symSharpFormatBold,
+ symSharpFormatItalic,
+ symSharpStrikethroughS,
+ symSharpFormatUnderlined,
+ symSharpFormatListBulleted,
+ symSharpFormatListNumbered,
+ symSharpVerticalAlignBottom,
+ symSharpVerticalAlignTop,
+ symSharpLink,
+ symSharpFullscreen,
+ symSharpFormatQuote,
+ symSharpFormatAlignLeft,
+ symSharpFormatAlignCenter,
+ symSharpFormatAlignRight,
+ symSharpFormatAlignJustify,
+ symSharpPrint,
+ symSharpFormatIndentDecrease,
+ symSharpFormatIndentIncrease,
+ symSharpFormatClear,
+ symSharpTextFormat,
+ symSharpFormatSize,
+ symSharpRemove,
+ symSharpUndo,
+ symSharpRedo,
+ symSharpCode,
+ symSharpFontDownload,
+ symSharpAdd,
+ symSharpClose,
+ symSharpError,
+ symSharpFirstPage,
+ symSharpKeyboardArrowLeft,
+ symSharpKeyboardArrowRight,
+ symSharpLastPage,
+ symSharpGrade,
+ symSharpEdit,
+ symSharpPlayArrow,
+ symSharpDone,
+ symSharpAddBox,
+ symSharpCloudUpload,
+ symSharpClearAll,
+ symSharpDoneAll
+} from '@quasar/extras/material-symbols-sharp'
+
+export default {
+ name: 'svg-material-symbols-sharp',
+ type: {
+ positive: symSharpCheckCircle,
+ negative: symSharpWarning,
+ info: symSharpInfo,
+ warning: symSharpPriorityHigh
+ },
+ arrow: {
+ up: symSharpArrowUpward,
+ right: symSharpArrowForward,
+ down: symSharpArrowDownward,
+ left: symSharpArrowBack,
+ dropdown: symSharpArrowDropDown
+ },
+ chevron: {
+ left: symSharpChevronLeft,
+ right: symSharpChevronRight
+ },
+ colorPicker: {
+ spectrum: symSharpGradient,
+ tune: symSharpTune,
+ palette: symSharpStyle
+ },
+ pullToRefresh: {
+ icon: symSharpRefresh
+ },
+ carousel: {
+ left: symSharpChevronLeft,
+ right: symSharpChevronRight,
+ up: symSharpKeyboardArrowUp,
+ down: symSharpKeyboardArrowDown,
+ navigationIcon: symSharpLens
+ },
+ chip: {
+ remove: symSharpCancel,
+ selected: symSharpCheck
+ },
+ datetime: {
+ arrowLeft: symSharpChevronLeft,
+ arrowRight: symSharpChevronRight,
+ now: symSharpSchedule,
+ today: symSharpToday
+ },
+ editor: {
+ bold: symSharpFormatBold,
+ italic: symSharpFormatItalic,
+ strikethrough: symSharpStrikethroughS,
+ underline: symSharpFormatUnderlined,
+ unorderedList: symSharpFormatListBulleted,
+ orderedList: symSharpFormatListNumbered,
+ subscript: symSharpVerticalAlignBottom,
+ superscript: symSharpVerticalAlignTop,
+ hyperlink: symSharpLink,
+ toggleFullscreen: symSharpFullscreen,
+ quote: symSharpFormatQuote,
+ left: symSharpFormatAlignLeft,
+ center: symSharpFormatAlignCenter,
+ right: symSharpFormatAlignRight,
+ justify: symSharpFormatAlignJustify,
+ print: symSharpPrint,
+ outdent: symSharpFormatIndentDecrease,
+ indent: symSharpFormatIndentIncrease,
+ removeFormat: symSharpFormatClear,
+ formatting: symSharpTextFormat,
+ fontSize: symSharpFormatSize,
+ align: symSharpFormatAlignLeft,
+ hr: symSharpRemove,
+ undo: symSharpUndo,
+ redo: symSharpRedo,
+ heading: symSharpFormatSize,
+ code: symSharpCode,
+ size: symSharpFormatSize,
+ font: symSharpFontDownload,
+ viewSource: symSharpCode
+ },
+ expansionItem: {
+ icon: symSharpKeyboardArrowDown,
+ denseIcon: symSharpArrowDropDown
+ },
+ fab: {
+ icon: symSharpAdd,
+ activeIcon: symSharpClose
+ },
+ field: {
+ clear: symSharpCancel,
+ error: symSharpError
+ },
+ pagination: {
+ first: symSharpFirstPage,
+ prev: symSharpKeyboardArrowLeft,
+ next: symSharpKeyboardArrowRight,
+ last: symSharpLastPage
+ },
+ rating: {
+ icon: symSharpGrade
+ },
+ stepper: {
+ done: symSharpCheck,
+ active: symSharpEdit,
+ error: symSharpWarning
+ },
+ tabs: {
+ left: symSharpChevronLeft,
+ right: symSharpChevronRight,
+ up: symSharpKeyboardArrowUp,
+ down: symSharpKeyboardArrowDown
+ },
+ table: {
+ arrowUp: symSharpArrowUpward,
+ warning: symSharpWarning,
+ firstPage: symSharpFirstPage,
+ prevPage: symSharpChevronLeft,
+ nextPage: symSharpChevronRight,
+ lastPage: symSharpLastPage
+ },
+ tree: {
+ icon: symSharpPlayArrow
+ },
+ uploader: {
+ done: symSharpDone,
+ clear: symSharpClose,
+ add: symSharpAddBox,
+ upload: symSharpCloudUpload,
+ removeQueue: symSharpClearAll,
+ removeUploaded: symSharpDoneAll
+ }
+}
diff --git a/ui/icon-set/svg-mdi-v5.js b/ui/icon-set/svg-mdi-v5.js
index e03af1ad560..eb07bdb5c95 100644
--- a/ui/icon-set/svg-mdi-v5.js
+++ b/ui/icon-set/svg-mdi-v5.js
@@ -2,7 +2,7 @@
/*
* Do not edit this file. It is automatically generated
* from its webfont counterpart (same filename without "svg-" prefix).
- * Edit that file instead (mdi-v5.js).
+ * Edit that file instead (mdi-v6.js).
*/
diff --git a/ui/icon-set/svg-mdi-v6.js b/ui/icon-set/svg-mdi-v6.js
new file mode 100644
index 00000000000..e1032aa3ca4
--- /dev/null
+++ b/ui/icon-set/svg-mdi-v6.js
@@ -0,0 +1,225 @@
+
+/*
+ * Do not edit this file. It is automatically generated
+ * from its webfont counterpart (same filename without "svg-" prefix).
+ * Edit that file instead (mdi-v6.js).
+ */
+
+
+import {
+ mdiCheckCircle,
+ mdiAlert,
+ mdiInformation,
+ mdiExclamation,
+ mdiArrowUp,
+ mdiArrowRight,
+ mdiArrowDown,
+ mdiArrowLeft,
+ mdiMenuDown,
+ mdiChevronLeft,
+ mdiChevronRight,
+ mdiGradientVertical,
+ mdiTune,
+ mdiPaletteSwatch,
+ mdiRefresh,
+ mdiChevronUp,
+ mdiChevronDown,
+ mdiCircle,
+ mdiCloseCircle,
+ mdiCheck,
+ mdiClockOutline,
+ mdiCalendarToday,
+ mdiFormatBold,
+ mdiFormatItalic,
+ mdiFormatStrikethroughVariant,
+ mdiFormatUnderline,
+ mdiFormatListBulleted,
+ mdiFormatListNumbered,
+ mdiFormatSubscript,
+ mdiFormatSuperscript,
+ mdiLink,
+ mdiFullscreen,
+ mdiFormatQuoteClose,
+ mdiFormatAlignLeft,
+ mdiFormatAlignCenter,
+ mdiFormatAlignRight,
+ mdiFormatAlignJustify,
+ mdiPrinter,
+ mdiFormatIndentDecrease,
+ mdiFormatIndentIncrease,
+ mdiFormatClear,
+ mdiFormatColorText,
+ mdiFormatSize,
+ mdiMinus,
+ mdiUndo,
+ mdiRedo,
+ mdiFormatHeader1,
+ mdiFormatHeader2,
+ mdiFormatHeader3,
+ mdiFormatHeader4,
+ mdiFormatHeader5,
+ mdiFormatHeader6,
+ mdiCodeTags,
+ mdiNumeric1Box,
+ mdiNumeric2Box,
+ mdiNumeric3Box,
+ mdiNumeric4Box,
+ mdiNumeric5Box,
+ mdiNumeric6Box,
+ mdiNumeric7Box,
+ mdiFormatFont,
+ mdiPlus,
+ mdiClose,
+ mdiAlertCircle,
+ mdiChevronDoubleLeft,
+ mdiChevronDoubleRight,
+ mdiStar,
+ mdiPencil,
+ mdiPlay,
+ mdiPlusBox,
+ mdiCloudUpload,
+ mdiNotificationClearAll,
+ mdiCheckAll
+} from '@quasar/extras/mdi-v6'
+
+export default {
+ name: 'svg-mdi-v6',
+ type: {
+ positive: mdiCheckCircle,
+ negative: mdiAlert,
+ info: mdiInformation,
+ warning: mdiExclamation
+ },
+ arrow: {
+ up: mdiArrowUp,
+ right: mdiArrowRight,
+ down: mdiArrowDown,
+ left: mdiArrowLeft,
+ dropdown: mdiMenuDown
+ },
+ chevron: {
+ left: mdiChevronLeft,
+ right: mdiChevronRight
+ },
+ colorPicker: {
+ spectrum: mdiGradientVertical,
+ tune: mdiTune,
+ palette: mdiPaletteSwatch
+ },
+ pullToRefresh: {
+ icon: mdiRefresh
+ },
+ carousel: {
+ left: mdiChevronLeft,
+ right: mdiChevronRight,
+ up: mdiChevronUp,
+ down: mdiChevronDown,
+ navigationIcon: mdiCircle
+ },
+ chip: {
+ remove: mdiCloseCircle,
+ selected: mdiCheck
+ },
+ datetime: {
+ arrowLeft: mdiChevronLeft,
+ arrowRight: mdiChevronRight,
+ now: mdiClockOutline,
+ today: mdiCalendarToday
+ },
+ editor: {
+ bold: mdiFormatBold,
+ italic: mdiFormatItalic,
+ strikethrough: mdiFormatStrikethroughVariant,
+ underline: mdiFormatUnderline,
+ unorderedList: mdiFormatListBulleted,
+ orderedList: mdiFormatListNumbered,
+ subscript: mdiFormatSubscript,
+ superscript: mdiFormatSuperscript,
+ hyperlink: mdiLink,
+ toggleFullscreen: mdiFullscreen,
+ quote: mdiFormatQuoteClose,
+ left: mdiFormatAlignLeft,
+ center: mdiFormatAlignCenter,
+ right: mdiFormatAlignRight,
+ justify: mdiFormatAlignJustify,
+ print: mdiPrinter,
+ outdent: mdiFormatIndentDecrease,
+ indent: mdiFormatIndentIncrease,
+ removeFormat: mdiFormatClear,
+ formatting: mdiFormatColorText,
+ fontSize: mdiFormatSize,
+ align: mdiFormatAlignLeft,
+ hr: mdiMinus,
+ undo: mdiUndo,
+ redo: mdiRedo,
+ heading: mdiFormatSize,
+ heading1: mdiFormatHeader1,
+ heading2: mdiFormatHeader2,
+ heading3: mdiFormatHeader3,
+ heading4: mdiFormatHeader4,
+ heading5: mdiFormatHeader5,
+ heading6: mdiFormatHeader6,
+ code: mdiCodeTags,
+ size: mdiFormatSize,
+ size1: mdiNumeric1Box,
+ size2: mdiNumeric2Box,
+ size3: mdiNumeric3Box,
+ size4: mdiNumeric4Box,
+ size5: mdiNumeric5Box,
+ size6: mdiNumeric6Box,
+ size7: mdiNumeric7Box,
+ font: mdiFormatFont,
+ viewSource: mdiCodeTags
+ },
+ expansionItem: {
+ icon: mdiChevronDown,
+ denseIcon: mdiMenuDown
+ },
+ fab: {
+ icon: mdiPlus,
+ activeIcon: mdiClose
+ },
+ field: {
+ clear: mdiCloseCircle,
+ error: mdiAlertCircle
+ },
+ pagination: {
+ first: mdiChevronDoubleLeft,
+ prev: mdiChevronLeft,
+ next: mdiChevronRight,
+ last: mdiChevronDoubleRight
+ },
+ rating: {
+ icon: mdiStar
+ },
+ stepper: {
+ done: mdiCheck,
+ active: mdiPencil,
+ error: mdiAlert
+ },
+ tabs: {
+ left: mdiChevronLeft,
+ right: mdiChevronRight,
+ up: mdiChevronUp,
+ down: mdiChevronDown
+ },
+ table: {
+ arrowUp: mdiArrowUp,
+ warning: mdiAlert,
+ firstPage: mdiChevronDoubleLeft,
+ prevPage: mdiChevronLeft,
+ nextPage: mdiChevronRight,
+ lastPage: mdiChevronDoubleRight
+ },
+ tree: {
+ icon: mdiPlay
+ },
+ uploader: {
+ done: mdiCheck,
+ clear: mdiClose,
+ add: mdiPlusBox,
+ upload: mdiCloudUpload,
+ removeQueue: mdiNotificationClearAll,
+ removeUploaded: mdiCheckAll
+ }
+}
diff --git a/ui/icon-set/svg-mdi-v7.js b/ui/icon-set/svg-mdi-v7.js
new file mode 100644
index 00000000000..85164a21750
--- /dev/null
+++ b/ui/icon-set/svg-mdi-v7.js
@@ -0,0 +1,225 @@
+
+/*
+ * Do not edit this file. It is automatically generated
+ * from its webfont counterpart (same filename without "svg-" prefix).
+ * Edit that file instead (mdi-v7.js).
+ */
+
+
+import {
+ mdiCheckCircle,
+ mdiAlert,
+ mdiInformation,
+ mdiExclamation,
+ mdiArrowUp,
+ mdiArrowRight,
+ mdiArrowDown,
+ mdiArrowLeft,
+ mdiMenuDown,
+ mdiChevronLeft,
+ mdiChevronRight,
+ mdiGradientVertical,
+ mdiTune,
+ mdiPaletteSwatch,
+ mdiRefresh,
+ mdiChevronUp,
+ mdiChevronDown,
+ mdiCircle,
+ mdiCloseCircle,
+ mdiCheck,
+ mdiClockOutline,
+ mdiCalendarToday,
+ mdiFormatBold,
+ mdiFormatItalic,
+ mdiFormatStrikethroughVariant,
+ mdiFormatUnderline,
+ mdiFormatListBulleted,
+ mdiFormatListNumbered,
+ mdiFormatSubscript,
+ mdiFormatSuperscript,
+ mdiLink,
+ mdiFullscreen,
+ mdiFormatQuoteClose,
+ mdiFormatAlignLeft,
+ mdiFormatAlignCenter,
+ mdiFormatAlignRight,
+ mdiFormatAlignJustify,
+ mdiPrinter,
+ mdiFormatIndentDecrease,
+ mdiFormatIndentIncrease,
+ mdiFormatClear,
+ mdiFormatColorText,
+ mdiFormatSize,
+ mdiMinus,
+ mdiUndo,
+ mdiRedo,
+ mdiFormatHeader1,
+ mdiFormatHeader2,
+ mdiFormatHeader3,
+ mdiFormatHeader4,
+ mdiFormatHeader5,
+ mdiFormatHeader6,
+ mdiCodeTags,
+ mdiNumeric1Box,
+ mdiNumeric2Box,
+ mdiNumeric3Box,
+ mdiNumeric4Box,
+ mdiNumeric5Box,
+ mdiNumeric6Box,
+ mdiNumeric7Box,
+ mdiFormatFont,
+ mdiPlus,
+ mdiClose,
+ mdiAlertCircle,
+ mdiChevronDoubleLeft,
+ mdiChevronDoubleRight,
+ mdiStar,
+ mdiPencil,
+ mdiPlay,
+ mdiPlusBox,
+ mdiCloudUpload,
+ mdiNotificationClearAll,
+ mdiCheckAll
+} from '@quasar/extras/mdi-v7'
+
+export default {
+ name: 'svg-mdi-v7',
+ type: {
+ positive: mdiCheckCircle,
+ negative: mdiAlert,
+ info: mdiInformation,
+ warning: mdiExclamation
+ },
+ arrow: {
+ up: mdiArrowUp,
+ right: mdiArrowRight,
+ down: mdiArrowDown,
+ left: mdiArrowLeft,
+ dropdown: mdiMenuDown
+ },
+ chevron: {
+ left: mdiChevronLeft,
+ right: mdiChevronRight
+ },
+ colorPicker: {
+ spectrum: mdiGradientVertical,
+ tune: mdiTune,
+ palette: mdiPaletteSwatch
+ },
+ pullToRefresh: {
+ icon: mdiRefresh
+ },
+ carousel: {
+ left: mdiChevronLeft,
+ right: mdiChevronRight,
+ up: mdiChevronUp,
+ down: mdiChevronDown,
+ navigationIcon: mdiCircle
+ },
+ chip: {
+ remove: mdiCloseCircle,
+ selected: mdiCheck
+ },
+ datetime: {
+ arrowLeft: mdiChevronLeft,
+ arrowRight: mdiChevronRight,
+ now: mdiClockOutline,
+ today: mdiCalendarToday
+ },
+ editor: {
+ bold: mdiFormatBold,
+ italic: mdiFormatItalic,
+ strikethrough: mdiFormatStrikethroughVariant,
+ underline: mdiFormatUnderline,
+ unorderedList: mdiFormatListBulleted,
+ orderedList: mdiFormatListNumbered,
+ subscript: mdiFormatSubscript,
+ superscript: mdiFormatSuperscript,
+ hyperlink: mdiLink,
+ toggleFullscreen: mdiFullscreen,
+ quote: mdiFormatQuoteClose,
+ left: mdiFormatAlignLeft,
+ center: mdiFormatAlignCenter,
+ right: mdiFormatAlignRight,
+ justify: mdiFormatAlignJustify,
+ print: mdiPrinter,
+ outdent: mdiFormatIndentDecrease,
+ indent: mdiFormatIndentIncrease,
+ removeFormat: mdiFormatClear,
+ formatting: mdiFormatColorText,
+ fontSize: mdiFormatSize,
+ align: mdiFormatAlignLeft,
+ hr: mdiMinus,
+ undo: mdiUndo,
+ redo: mdiRedo,
+ heading: mdiFormatSize,
+ heading1: mdiFormatHeader1,
+ heading2: mdiFormatHeader2,
+ heading3: mdiFormatHeader3,
+ heading4: mdiFormatHeader4,
+ heading5: mdiFormatHeader5,
+ heading6: mdiFormatHeader6,
+ code: mdiCodeTags,
+ size: mdiFormatSize,
+ size1: mdiNumeric1Box,
+ size2: mdiNumeric2Box,
+ size3: mdiNumeric3Box,
+ size4: mdiNumeric4Box,
+ size5: mdiNumeric5Box,
+ size6: mdiNumeric6Box,
+ size7: mdiNumeric7Box,
+ font: mdiFormatFont,
+ viewSource: mdiCodeTags
+ },
+ expansionItem: {
+ icon: mdiChevronDown,
+ denseIcon: mdiMenuDown
+ },
+ fab: {
+ icon: mdiPlus,
+ activeIcon: mdiClose
+ },
+ field: {
+ clear: mdiCloseCircle,
+ error: mdiAlertCircle
+ },
+ pagination: {
+ first: mdiChevronDoubleLeft,
+ prev: mdiChevronLeft,
+ next: mdiChevronRight,
+ last: mdiChevronDoubleRight
+ },
+ rating: {
+ icon: mdiStar
+ },
+ stepper: {
+ done: mdiCheck,
+ active: mdiPencil,
+ error: mdiAlert
+ },
+ tabs: {
+ left: mdiChevronLeft,
+ right: mdiChevronRight,
+ up: mdiChevronUp,
+ down: mdiChevronDown
+ },
+ table: {
+ arrowUp: mdiArrowUp,
+ warning: mdiAlert,
+ firstPage: mdiChevronDoubleLeft,
+ prevPage: mdiChevronLeft,
+ nextPage: mdiChevronRight,
+ lastPage: mdiChevronDoubleRight
+ },
+ tree: {
+ icon: mdiPlay
+ },
+ uploader: {
+ done: mdiCheck,
+ clear: mdiClose,
+ add: mdiPlusBox,
+ upload: mdiCloudUpload,
+ removeQueue: mdiNotificationClearAll,
+ removeUploaded: mdiCheckAll
+ }
+}
diff --git a/ui/icon-set/svg-themify.js b/ui/icon-set/svg-themify.js
index 54dd9760561..d72c11f1f48 100644
--- a/ui/icon-set/svg-themify.js
+++ b/ui/icon-set/svg-themify.js
@@ -83,7 +83,7 @@ import {
mdiNumeric6Box,
mdiNumeric7Box,
mdiFormatFont
-} from '@quasar/extras/mdi-v5'
+} from '@quasar/extras/mdi-v6'
diff --git a/ui/icon-set/themify.js b/ui/icon-set/themify.js
index 8161c91b7a7..ef452003bc9 100644
--- a/ui/icon-set/themify.js
+++ b/ui/icon-set/themify.js
@@ -22,7 +22,7 @@ import {
mdiNumeric6Box,
mdiNumeric7Box,
mdiFormatFont
-} from '@quasar/extras/mdi-v5'
+} from '@quasar/extras/mdi-v6'
export default {
name: 'themify',
diff --git a/ui/lang/ar.js b/ui/lang/ar.js
index e7356db74a8..bc19d709cae 100644
--- a/ui/lang/ar.js
+++ b/ui/lang/ar.js
@@ -15,7 +15,9 @@ export default {
create: 'إنشاء',
search: 'بحث',
filter: 'ترشيح',
- refresh: 'تحديث'
+ refresh: 'تحديث',
+ expand: function (label) { return label ? `"${label} توسيع` : 'وسعت' },
+ collapse: function (label) { return label ? `"${label}" تصغير` : 'انهيار' }
},
date: {
days: 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
diff --git a/ui/lang/az-latn.js b/ui/lang/az-latn.js
index fc5491fcfaa..0946f7e8b9a 100644
--- a/ui/lang/az-latn.js
+++ b/ui/lang/az-latn.js
@@ -14,7 +14,9 @@ export default {
create: 'Yarat',
search: 'Axtar',
filter: 'Filtrlə',
- refresh: 'Yenilə'
+ refresh: 'Yenilə',
+ expand: function (label) { return label ? `"${label}" genişləndirin` : 'Genişləndirin' },
+ collapse: function (label) { return label ? `"${label}" yığcamlaşdırın` : 'Yıxılma' }
},
date: {
days: 'Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə'.split('_'),
diff --git a/ui/lang/bg.js b/ui/lang/bg.js
index c97fefa3275..8bcb8f23546 100644
--- a/ui/lang/bg.js
+++ b/ui/lang/bg.js
@@ -14,7 +14,9 @@ export default {
create: 'Създай',
search: 'Търси',
filter: 'Филтър',
- refresh: 'Презареди'
+ refresh: 'Презареди',
+ expand: function (label) { return label ? `Разширете "${label}"` : 'Разширяване' },
+ collapse: function (label) { return label ? `Свиване на "${label}"` : 'Свиване' }
},
date: {
days: 'Неделя_Понеделник_Вторник_Сряда_Четвъртък_Петък_Събота'.split('_'),
diff --git a/ui/lang/ca.js b/ui/lang/ca.js
index 7e2297ad6f1..142065d1519 100644
--- a/ui/lang/ca.js
+++ b/ui/lang/ca.js
@@ -2,19 +2,21 @@ export default {
isoName: 'ca',
nativeName: 'Català',
label: {
- clear: 'Neteja',
+ clear: 'Netejar',
ok: 'D\'acord',
- cancel: 'Cancel·la',
- close: 'Tanca',
- set: 'Estableix',
- select: 'Selecciona',
- reset: 'Restableix',
- remove: 'Elimina',
- update: 'Actualitza',
- create: 'Crea',
- search: 'Cerca',
- filter: 'Filtra',
- refresh: 'Refresca'
+ cancel: 'Cancel·lar',
+ close: 'Tancar',
+ set: 'Definir',
+ select: 'Seleccionar',
+ reset: 'Reinicialitzar',
+ remove: 'Suprimir',
+ update: 'Actualitzar',
+ create: 'Crear',
+ search: 'Cercar',
+ filter: 'Filtrar',
+ refresh: 'Refrescar',
+ expand: function (label) { return label ? `Amplia "${label}"` : 'Expandir' },
+ collapse: function (label) { return label ? `Col·lapse "${label}"` : 'Col·lapse' }
},
date: {
days: 'Diumenge_Dilluns_Dimarts_Dimecres_Dijous_Divendres_Dissabte'.split('_'),
@@ -51,23 +53,23 @@ export default {
orderedList: 'Llista amb ordre',
subscript: 'Subíndex',
superscript: 'Superíndex',
- hyperlink: 'Hyperenllaç',
- toggleFullscreen: 'Commuta pantalla completa',
+ hyperlink: 'Hiperenllaç',
+ toggleFullscreen: 'Commutar pantalla completa',
quote: 'Cita',
- left: 'Alínea a l\'esquerra',
- center: 'Alínea al centre',
- right: 'Alínea a la dreta',
- justify: 'Alínea justificat',
- print: 'Imprimeix',
- outdent: 'Incrementa la sagnia',
- indent: 'Disminueix la sagnia',
- removeFormat: 'Lleva el format',
- formatting: 'Donant format',
+ left: 'Alinear a l\'esquerra',
+ center: 'Alinear al centre',
+ right: 'Alinear a la dreta',
+ justify: 'Alinear justificat',
+ print: 'Imprimir',
+ outdent: 'Augmentar identació',
+ indent: 'Disminuir identació',
+ removeFormat: 'Llevar el format',
+ formatting: 'Formatant',
fontSize: 'Mida de la font',
- align: 'Alínea',
- hr: 'Insereix una línea horitzontal',
- undo: 'Desfés',
- redo: 'Refés',
+ align: 'Alinear',
+ hr: 'Inserir una línea horitzontal',
+ undo: 'Desfer',
+ redo: 'Refer',
heading1: 'Encapçalament 1',
heading2: 'Encapçalament 2',
heading3: 'Encapçalament 3',
@@ -77,17 +79,17 @@ export default {
paragraph: 'Paràgraf',
code: 'Codi',
size1: 'Molt petit',
- size2: 'Un poc petit',
+ size2: 'Petit',
size3: 'Normal',
- size4: 'Mitjà-gran',
+ size4: 'Mitjà',
size5: 'Gran',
size6: 'Molt gran',
size7: 'Màxim',
defaultFont: 'Font per defecte',
- viewSource: 'Veure la font'
+ viewSource: 'Veure font'
},
tree: {
- noNodes: 'No hi han nodes disponibles',
+ noNodes: 'No hi ha nodes disponibles',
noResults: 'No s\'han trobat nodes'
}
}
diff --git a/ui/lang/cs.js b/ui/lang/cs.js
index 07fb65f2c16..2f2a2abbc79 100644
--- a/ui/lang/cs.js
+++ b/ui/lang/cs.js
@@ -14,7 +14,9 @@ export default {
create: 'Vytvořit',
search: 'Hledat',
filter: 'Filtrovat',
- refresh: 'Obnovit'
+ refresh: 'Obnovit',
+ expand: function (label) { return label ? `Rozbalit "${label}"` : 'Rozšířit' },
+ collapse: function (label) { return label ? `Sbalit "${label}"` : 'Kolaps' }
},
date: {
days: 'Neděle_Pondělí_Úterý_Středa_Čtvrtek_Pátek_Sobota'.split('_'),
diff --git a/ui/lang/da.js b/ui/lang/da.js
index 446fc13c2bd..9f8da61512b 100644
--- a/ui/lang/da.js
+++ b/ui/lang/da.js
@@ -14,7 +14,9 @@ export default {
create: 'Opret',
search: 'Søg',
filter: 'Filtrer',
- refresh: 'Opdater'
+ refresh: 'Opdater',
+ expand: function (label) { return label ? `Udvid "${label}"` : 'Udvide' },
+ collapse: function (label) { return label ? `Skjul "${label}"` : 'Bryder sammen' }
},
date: {
days: 'Søndag_Mandag_Tirsdag_Onsdag_Torsdag_Fredag_Lørdag'.split('_'),
diff --git a/ui/lang/de.js b/ui/lang/de.js
index f74086a2fe4..569a9b03471 100644
--- a/ui/lang/de.js
+++ b/ui/lang/de.js
@@ -14,7 +14,9 @@ export default {
create: 'Erstellen',
search: 'Suche',
filter: 'Filter',
- refresh: 'Aktualisieren'
+ refresh: 'Aktualisieren',
+ expand: function (label) { return label ? `Erweitern Sie "${label}"` : 'Erweitern' },
+ collapse: function (label) { return label ? `"${label}" minimieren` : 'Zusammenbruch' }
},
date: {
days: 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'),
@@ -23,7 +25,7 @@ export default {
monthsShort: 'Jan_Feb_Mar_Apr_Mai_Jun_Jul_Aug_Sep_Okt_Nov_Dez'.split('_'),
firstDayOfWeek: 1, // 0-6, 0 - Sunday, 1 Monday, ...
format24h: true,
- pluralDay: 'tage'
+ pluralDay: 'Tage'
},
table: {
noData: 'Keine Daten vorhanden.',
diff --git a/ui/lang/el.js b/ui/lang/el.js
index 18eff36d7d4..2ffb7f1e01c 100644
--- a/ui/lang/el.js
+++ b/ui/lang/el.js
@@ -14,7 +14,9 @@ export default {
create: 'Δημιουργία',
search: 'Αναζήτηση',
filter: 'Φίλτρο',
- refresh: 'Ανανέωση'
+ refresh: 'Ανανέωση',
+ expand: function (label) { return label ? `Επέκταση "${label}"` : 'Επεκτείνουν' },
+ collapse: function (label) { return label ? `Σύμπτυξη "${label}"` : 'Κατάρρευση' }
},
date: {
days: 'Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο'.split('_'),
diff --git a/ui/lang/en-gb.js b/ui/lang/en-gb.js
index f351387fc74..200e1f3e469 100644
--- a/ui/lang/en-gb.js
+++ b/ui/lang/en-gb.js
@@ -14,7 +14,9 @@ export default {
create: 'Create',
search: 'Search',
filter: 'Filter',
- refresh: 'Refresh'
+ refresh: 'Refresh',
+ expand: function (label) { return label ? `Expand "${label}"` : 'Expand' },
+ collapse: function (label) { return label ? `Collapse "${label}"` : 'Collapse' }
},
date: {
days: 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
diff --git a/ui/lang/en-us.js b/ui/lang/en-us.js
index 10443e9ee36..3f531ea0201 100644
--- a/ui/lang/en-us.js
+++ b/ui/lang/en-us.js
@@ -14,7 +14,9 @@ export default {
create: 'Create',
search: 'Search',
filter: 'Filter',
- refresh: 'Refresh'
+ refresh: 'Refresh',
+ expand: function (label) { return label ? `Expand "${label}"` : 'Expand' },
+ collapse: function (label) { return label ? `Collapse "${label}"` : 'Collapse' }
},
date: {
days: 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
diff --git a/ui/lang/eo.js b/ui/lang/eo.js
index 1d60f4b40d4..bcba0440425 100644
--- a/ui/lang/eo.js
+++ b/ui/lang/eo.js
@@ -14,7 +14,9 @@ export default {
create: 'Krei',
search: 'Serĉi',
filter: 'Filtri',
- refresh: 'Reŝargi'
+ refresh: 'Reŝargi',
+ expand: function (label) { return label ? `Vastigi "${label}"` : 'Vastigi' },
+ collapse: function (label) { return label ? `Kolapsi "${label}"` : 'Kolapso' }
},
date: {
days: 'Dimanĉo_Lundo_Mardo_Merkredo_Jaŭdo_Vendredo_Sabato'.split('_'),
diff --git a/ui/lang/es.js b/ui/lang/es.js
index 3f0c83a95b9..41452e4e064 100644
--- a/ui/lang/es.js
+++ b/ui/lang/es.js
@@ -14,7 +14,9 @@ export default {
create: 'Crear',
search: 'Buscar',
filter: 'Filtrar',
- refresh: 'Actualizar'
+ refresh: 'Actualizar',
+ expand: function (label) { return label ? `Expandir "${label}"` : 'Expandir' },
+ collapse: function (label) { return label ? `Ocultar "${label}"` : 'Colapsar' }
},
date: {
days: 'Domingo_Lunes_Martes_Miércoles_Jueves_Viernes_Sábado'.split('_'),
diff --git a/ui/lang/et.js b/ui/lang/et.js
index 72bc144059a..b8eed2805a9 100644
--- a/ui/lang/et.js
+++ b/ui/lang/et.js
@@ -14,7 +14,9 @@ export default {
create: 'Loo',
search: 'Otsi',
filter: 'Filtreeri',
- refresh: 'Värskenda'
+ refresh: 'Värskenda',
+ expand: function (label) { return label ? `Laienda "${label}"` : 'Laienda' },
+ collapse: function (label) { return label ? `Ahenda "${label}"` : 'Ahenda' }
},
date: {
days: 'pühapäev_esmaspäev_teisipäev_kolmapäev_neljapäev_reede_laupäev'.split('_'),
diff --git a/ui/lang/eu.js b/ui/lang/eu.js
new file mode 100644
index 00000000000..c3d3699b304
--- /dev/null
+++ b/ui/lang/eu.js
@@ -0,0 +1,95 @@
+export default {
+ isoName: 'eu',
+ nativeName: 'Euskara',
+ label: {
+ clear: 'Ezabatu',
+ ok: 'OK',
+ cancel: 'Ezeztatu',
+ close: 'Itxi',
+ set: 'Ezarri',
+ select: 'Hautatu',
+ reset: 'Berrezarri',
+ remove: 'Ezabatu',
+ update: 'Eguneratu',
+ create: 'Sortu',
+ search: 'Bilatu',
+ filter: 'Iragazi',
+ refresh: 'Eguneratu',
+ expand: function (label) { return label ? `Zabaldu "${label}"` : 'Zabaldu' },
+ collapse: function (label) { return label ? `Tolestu "${label}"` : 'Tolestu' }
+ },
+ date: {
+ days: 'Igandea_Astelehena_Astearte_Asteazkena_Osteguna_Ostirala_Larunbata'.split('_'),
+ daysShort: 'Iga_Ast_Asr_Asz_Ost_Osr_Lar'.split('_'),
+ months: 'Urtarrila_Otsaila_Martxoa_Apirila_Maiatza_Ekaina_Uztailea_Abuztua_Iraila_Urria_Azaroa_Abendua'.split('_'),
+ monthsShort: 'Urt_Ots_Mar_Api_Mai_Eka_Uzt_Abu_Ira_Urr_Aza_Abe'.split('_'),
+ firstDayOfWeek: 1, // 0-6, 0 - Sunday, 1 Monday, ...
+ format24h: true,
+ pluralDay: 'egun'
+ },
+ table: {
+ noData: 'Daturik ez',
+ noResults: 'Ez da emaitzarik aurkitu',
+ loading: 'Kargatzen...',
+ selectedRecords: function (rows) {
+ return rows > 0
+ ? rows + ' errenkada hautatuta.'
+ : 'hautatutako errenkada gabe.'
+ },
+ recordsPerPage: 'Errenkadak orrialde bakoitzeko:',
+ allRows: 'Denak',
+ pagination: function (start, end, total) {
+ return start + 'tik -' + end + 'ra, guztira ' + total
+ },
+ columns: 'Zutabeak'
+ },
+ editor: {
+ url: 'URL',
+ bold: 'Lodia',
+ italic: 'Italikoa',
+ strikethrough: 'Ezabaketa',
+ underline: 'Azpimarratua',
+ unorderedList: 'Zerrenda desordenatua',
+ orderedList: 'Zerrenda ordenatua',
+ subscript: 'Azpiindizea',
+ superscript: 'Superindizea',
+ hyperlink: 'Hiperesteka',
+ toggleFullscreen: 'Aldatu pantaila osoa',
+ quote: 'Hitzordua',
+ left: 'Ezkerreko lerrokadura',
+ center: 'Erdiko lerrokadura',
+ right: 'Eskubiko lerrokadura',
+ justify: 'Lerrokadura justifikatzea',
+ print: 'Inprimatu',
+ outdent: 'Murriztu indentazioa',
+ indent: 'Indentazioa areagotzea',
+ removeFormat: 'Ezabatu formatua',
+ formatting: 'Formatua',
+ fontSize: 'Letra-tamaina',
+ align: 'Lerrokatu',
+ hr: 'Txertatu lerro horizontala',
+ undo: 'Desegin',
+ redo: 'Berregin',
+ heading1: 'Goiburua 1',
+ heading2: 'Goiburua 2',
+ heading3: 'Goiburua 3',
+ heading4: 'Goiburua 4',
+ heading5: 'Goiburua 5',
+ heading6: 'Goiburua 6',
+ paragraph: 'Paragrafoa',
+ code: 'Kodea',
+ size1: 'Oso txikia',
+ size2: 'Txikia',
+ size3: 'Normala',
+ size4: 'Ertaina',
+ size5: 'Handia',
+ size6: 'Oso handia',
+ size7: 'Gehienezkoa',
+ defaultFont: 'Iturri lehenetsia',
+ viewSource: 'Ikusi iturburu-kodea'
+ },
+ tree: {
+ noNodes: 'Nodo erabilgarririk gabe',
+ noResults: 'Ez da aurkitu dagozkion nodorik'
+ }
+}
diff --git a/ui/lang/fa-ir.js b/ui/lang/fa-ir.js
index e5e7ebc8469..aa2bec35b95 100644
--- a/ui/lang/fa-ir.js
+++ b/ui/lang/fa-ir.js
@@ -18,7 +18,9 @@ export default {
create: 'ساخت',
search: 'جستجو',
filter: 'فیلتر',
- refresh: 'تازهسازی'
+ refresh: 'تازهسازی',
+ expand: function (label) { return label ? `"${label}" گسترش` : 'بسط دادن' },
+ collapse: function (label) { return label ? `"${label}" کوچک کردن` : 'سقوط - فروپاشی' }
},
date: {
days: days,
@@ -39,7 +41,9 @@ export default {
noResults: 'هیچ موردی یافت نشد',
loading: 'در حال بارگذاری ...',
selectedRecords: function (rows) {
- return rows === 0 ? 'رکوردی انتخاب نشده' : rows + ' رکورد انتخاب شده'
+ return rows === 0
+ ? 'رکوردی انتخاب نشده'
+ : rows + ' رکورد انتخاب شده'
},
recordsPerPage: 'رکورد در صفحه:',
allRows: 'همه',
diff --git a/ui/lang/fa.js b/ui/lang/fa.js
index f82161e2ac2..470a2308025 100644
--- a/ui/lang/fa.js
+++ b/ui/lang/fa.js
@@ -18,7 +18,9 @@ export default {
create: 'ساخت',
search: 'جستجو',
filter: 'فیلتر',
- refresh: 'تازهسازی'
+ refresh: 'تازهسازی',
+ expand: function (label) { return label ? `"${label}" گسترش` : 'بسط دادن' },
+ collapse: function (label) { return label ? `"${label}" کوچک کردن` : 'سقوط - فروپاشی' }
},
date: {
days: days,
@@ -39,7 +41,9 @@ export default {
noResults: 'هیچ موردی یافت نشد',
loading: 'در حال بارگذاری ...',
selectedRecords: function (rows) {
- return rows === 0 ? 'رکوردی انتخاب نشده' : rows + ' رکورد انتخاب شده'
+ return rows === 0
+ ? 'رکوردی انتخاب نشده'
+ : rows + ' رکورد انتخاب شده'
},
recordsPerPage: 'رکورد در صفحه:',
allRows: 'همه',
diff --git a/ui/lang/fi.js b/ui/lang/fi.js
index 1dc0e2ba6a7..7e6e53a0386 100644
--- a/ui/lang/fi.js
+++ b/ui/lang/fi.js
@@ -14,7 +14,9 @@ export default {
create: 'Luo',
search: 'Etsi',
filter: 'Suodata',
- refresh: 'Päivitä'
+ refresh: 'Päivitä',
+ expand: function (label) { return label ? `Laajenna "${label}"` : 'Laajentaa' },
+ collapse: function (label) { return label ? `Tiivistä "${label}"` : 'Romahdus' }
},
date: {
days: 'sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai'.split('_'),
diff --git a/ui/lang/fr.js b/ui/lang/fr.js
index d03867cde88..7a34e5e3ce4 100644
--- a/ui/lang/fr.js
+++ b/ui/lang/fr.js
@@ -14,14 +14,16 @@ export default {
create: 'Créer',
search: 'Rechercher',
filter: 'Filtrer',
- refresh: 'Rafraîchir'
+ refresh: 'Rafraîchir',
+ expand: function (label) { return label ? `Développer "${label}"` : 'Développer' },
+ collapse: function (label) { return label ? `Réduire "${label}"` : 'Effondrement' }
},
date: {
days: 'Dimanche_Lundi_Mardi_Mercredi_Jeudi_Vendredi_Samedi'.split('_'),
daysShort: 'Dim_Lun_Mar_Mer_Jeu_Ven_Sam'.split('_'),
months: 'Janvier_Février_Mars_Avril_Mai_Juin_Juillet_Août_Septembre_Octobre_Novembre_Décembre'.split('_'),
monthsShort: 'Jan_Fev_Mar_Avr_Mai_Juin_Jui_Aou_Sep_Oct_Nov_Dec'.split('_'),
- headerTitle: function (date, model) {
+ headerTitle: function (date) {
return new Intl.DateTimeFormat('fr', {
weekday: 'short', day: 'numeric', month: 'short'
}).format(date)
diff --git a/ui/lang/gn.js b/ui/lang/gn.js
index bf44072a811..0fccd3b226f 100644
--- a/ui/lang/gn.js
+++ b/ui/lang/gn.js
@@ -14,7 +14,9 @@ export default {
create: 'Japo',
search: 'Heka',
filter: 'Mbogua',
- refresh: 'Actualisa'
+ refresh: 'Actualisa',
+ expand: function (label) { return label ? `Oñembotuichave "${label}"` : 'Myasãi' },
+ collapse: function (label) { return label ? `Omboguejy "${label}"` : 'Ñembyaipa' }
},
date: {
days: 'Domingo_Lunes_Martes_Miércoles_Jueves_Viernes_Sábado'.split('_'),
diff --git a/ui/lang/he.js b/ui/lang/he.js
index 59f1d1309c7..e345305cef8 100644
--- a/ui/lang/he.js
+++ b/ui/lang/he.js
@@ -15,7 +15,9 @@ export default {
create: 'צור',
search: 'חיפוש',
filter: 'סינון',
- refresh: 'רענון'
+ refresh: 'רענון',
+ expand: function (label) { return label ? `"${label}" הרחב את` : 'לְהַרְחִיב' },
+ collapse: function (label) { return label ? `"${label}" כווץ` : 'הִתמוֹטְטוּת' }
},
date: {
days: 'ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת'.split('_'),
diff --git a/ui/lang/hr.js b/ui/lang/hr.js
index e24a0f6ccb3..4e821ad0022 100644
--- a/ui/lang/hr.js
+++ b/ui/lang/hr.js
@@ -14,7 +14,9 @@ export default {
create: 'Dodaj',
search: 'Traži',
filter: 'Filter',
- refresh: 'Osvježi'
+ refresh: 'Osvježi',
+ expand: function (label) { return label ? `Proširi "${label}"` : 'Proširiti' },
+ collapse: function (label) { return label ? `Sažmi "${label}"` : 'Kolaps' }
},
date: {
days: 'Nedjelja_Ponedjeljak_Utorak_Srijeda_Četvrtak_Petak_Subota'.split('_'),
diff --git a/ui/lang/hu.js b/ui/lang/hu.js
index ad964f08d7d..bf23fe78aa2 100644
--- a/ui/lang/hu.js
+++ b/ui/lang/hu.js
@@ -14,7 +14,9 @@ export default {
create: 'Létrehozás',
search: 'Keresés',
filter: 'Szűrés',
- refresh: 'Frissítés'
+ refresh: 'Frissítés',
+ expand: function (label) { return label ? `A "${label}" kiterjesztése` : 'Kiterjed' },
+ collapse: function (label) { return label ? `A "${label}" összecsukása` : 'Összeomlás' }
},
date: {
days: 'Vasárnap_Hétfő_Kedd_Szerda_Csütörtök_Péntek_Szombat'.split('_'),
diff --git a/ui/lang/id.js b/ui/lang/id.js
index cc135b8843f..c9ed6245362 100644
--- a/ui/lang/id.js
+++ b/ui/lang/id.js
@@ -14,7 +14,9 @@ export default {
create: 'Buat',
search: 'Cari',
filter: 'Saring',
- refresh: 'Segarkan'
+ refresh: 'Segarkan',
+ expand: function (label) { return label ? `Perluas "${label}"` : 'Mengembangkan' },
+ collapse: function (label) { return label ? `Ciutkan "${label}"` : 'Jatuh' }
},
date: {
days: 'Minggu_Senin_Selasa_Rabu_Kamis_Jum\'at_Sabtu'.split('_'),
diff --git a/ui/lang/index.json b/ui/lang/index.json
index b8772db618c..64d8dde3e4d 100644
--- a/ui/lang/index.json
+++ b/ui/lang/index.json
@@ -51,6 +51,10 @@
"isoName": "et",
"nativeName": "Eesti"
},
+ {
+ "isoName": "eu",
+ "nativeName": "Euskara"
+ },
{
"isoName": "fa-ir",
"nativeName": "فارسی"
@@ -111,6 +115,10 @@
"isoName": "kur-ckb",
"nativeName": "کوردی سۆرانی"
},
+ {
+ "isoName": "kz",
+ "nativeName": "Қазақша"
+ },
{
"isoName": "lu",
"nativeName": "Kiluba"
@@ -119,14 +127,26 @@
"isoName": "lv",
"nativeName": "Latviešu valoda"
},
+ {
+ "isoName": "mk",
+ "nativeName": "Македонски"
+ },
{
"isoName": "ml",
"nativeName": "മലയാളം"
},
+ {
+ "isoName": "mm",
+ "nativeName": "မြန်မာ(ဗမာ)"
+ },
{
"isoName": "ms",
"nativeName": "Bahasa Melayu"
},
+ {
+ "isoName": "my",
+ "nativeName": "Malaysia"
+ },
{
"isoName": "nb-no",
"nativeName": "Norsk"
@@ -163,9 +183,13 @@
"isoName": "sl",
"nativeName": "Slovenski Jezik"
},
+ {
+ "isoName": "sm",
+ "nativeName": "Fa'asāmoa"
+ },
{
"isoName": "sr",
- "nativeName": "српски језик"
+ "nativeName": "srpski jezik"
},
{
"isoName": "sv",
@@ -191,6 +215,14 @@
"isoName": "uk",
"nativeName": "Українська"
},
+ {
+ "isoName": "uz-Cyrl",
+ "nativeName": "Ўзбекча (Кирил)"
+ },
+ {
+ "isoName": "uz-Latn",
+ "nativeName": "O'zbekcha (Lotin)"
+ },
{
"isoName": "vi",
"nativeName": "Tiếng Việt"
@@ -201,6 +233,6 @@
},
{
"isoName": "zh-hant",
- "nativeName": "中文(繁體)"
+ "nativeName": "中文(繁體)"
}
]
\ No newline at end of file
diff --git a/ui/lang/is.js b/ui/lang/is.js
index 2268a7368f2..717f365f620 100644
--- a/ui/lang/is.js
+++ b/ui/lang/is.js
@@ -14,7 +14,9 @@ export default {
create: 'Búa til',
search: 'Leita',
filter: 'Sía',
- refresh: 'Endurhlaða'
+ refresh: 'Endurhlaða',
+ expand: function (label) { return label ? `Stækka "${label}"` : 'Stækkaðu' },
+ collapse: function (label) { return label ? `Draga saman "${label}"` : 'Hrun' }
},
date: {
days: 'Sunnudagur_Mánudagur_Þriðjudagur_Miðvikudagur_Fimmtudagur_Föstudagur_Laugardagur'.split('_'),
diff --git a/ui/lang/it.js b/ui/lang/it.js
index e1231b08d02..916a4ef9332 100644
--- a/ui/lang/it.js
+++ b/ui/lang/it.js
@@ -14,7 +14,9 @@ export default {
create: 'Crea',
search: 'Cerca',
filter: 'Filtra',
- refresh: 'Aggiorna'
+ refresh: 'Aggiorna',
+ expand: function (label) { return label ? `Espandi "${label}"` : 'Espandere' },
+ collapse: function (label) { return label ? `Comprimi "${label}"` : 'Crollo' }
},
date: {
days: 'Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato'.split('_'),
diff --git a/ui/lang/ja.js b/ui/lang/ja.js
index 094148a1cc3..7e7924e44ff 100644
--- a/ui/lang/ja.js
+++ b/ui/lang/ja.js
@@ -14,7 +14,9 @@ export default {
create: '作成', // 'Create',
search: '検索', // 'Search',
filter: 'フィルタ', // 'Filter',
- refresh: '再読込' // 'Refresh'
+ refresh: '再読込', // 'Refresh'
+ expand: function (label) { return label ? `「${label}」を展開します。` : '拡大' },
+ collapse: function (label) { return label ? `「${label}」を折りたたむ` : '崩壊' }
},
date: {
days: '日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日'.split('_'), // 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
@@ -26,7 +28,7 @@ export default {
weekday: 'short', month: 'short', day: 'numeric'
}).format(date)
},
- firstDayOfWeek: 1, // 0-6, 0 - Sunday, 1 Monday, ...
+ firstDayOfWeek: 0, // 0-6, 0 - Sunday, 1 Monday, ...
format24h: true, // true
pluralDay: '日間'
},
diff --git a/ui/lang/km.js b/ui/lang/km.js
index 6d3e96c6bfe..4c3f012f1c3 100644
--- a/ui/lang/km.js
+++ b/ui/lang/km.js
@@ -14,7 +14,9 @@ export default {
create: 'បង្កើត',
search: 'ស្វែងរក',
filter: 'ច្រោះ',
- refresh: 'ធ្វើឲ្យថ្មី'
+ refresh: 'ធ្វើឲ្យថ្មី',
+ expand: function (label) { return label ? `ពង្រីក "${label}"` : 'ពង្រីក' },
+ collapse: function (label) { return label ? `បង្រួម "${label}"` : 'ដួលរលំ' }
},
date: {
days: 'អាទិត្យ_ចន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'),
diff --git a/ui/lang/ko-kr.js b/ui/lang/ko-kr.js
index d050fd8b288..2ac710f0583 100644
--- a/ui/lang/ko-kr.js
+++ b/ui/lang/ko-kr.js
@@ -14,7 +14,9 @@ export default {
create: '생성',
search: '검색',
filter: '필터',
- refresh: '새로 고침'
+ refresh: '새로 고침',
+ expand: function (label) { return label ? `"${label}" 확장` : '확장하다' },
+ collapse: function (label) { return label ? `"${label}" 접기` : '무너지다' }
},
date: {
days: '일요일_월요일_화요일_수요일_목요일_금요일_토요일'.split('_'),
@@ -44,46 +46,46 @@ export default {
editor: {
url: 'URL',
bold: '굵게',
- italic: '이탤릭',
+ italic: '기울이기',
strikethrough: '취소선',
underline: '밑줄',
- unorderedList: '정렬되지 않은 목록',
+ unorderedList: '비순차 목록',
orderedList: '순서 목록',
subscript: '아래 첨자',
superscript: '위 첨자',
- hyperlink: '링크',
+ hyperlink: '하이퍼링크',
toggleFullscreen: '전체 화면',
quote: '따옴표',
left: '왼쪽 정렬',
center: '가운데 정렬',
right: '오른쪽 정렬',
- justify: '정렬',
+ justify: '세로 정렬',
print: '출력',
- outdent: '들여 쓰기 감소',
- indent: '들여 쓰기 증가',
+ outdent: '들여 쓰기',
+ indent: '내어 쓰기',
removeFormat: '포맷팅 제거',
formatting: '포맷팅',
- fontSize: '폰트 크기',
- align: '정렬',
- hr: '가로 룰 삽입',
- undo: '되돌리기',
- redo: '다시 하기',
- heading1: '헤더 1',
- heading2: '헤더 2',
- heading3: '헤더 3',
- heading4: '헤더 4',
- heading5: '헤더 5',
- heading6: '헤더 6',
- paragraph: '절',
+ fontSize: '글꼴 크기',
+ align: '가로 정렬',
+ hr: '가로줄 넣기',
+ undo: '실행취소',
+ redo: '다시하기',
+ heading1: '제목 1',
+ heading2: '제목 2',
+ heading3: '제목 3',
+ heading4: '제목 4',
+ heading5: '제목 5',
+ heading6: '제목 6',
+ paragraph: '단락',
code: '코드',
- size1: '아주 작음',
- size2: '작음',
+ size1: '매우 작게',
+ size2: '작게',
size3: '보통',
size4: '약간 크게',
size5: '크게',
size6: '아주 크게',
size7: '최대',
- defaultFont: '기본 폰트',
+ defaultFont: '기본 글꼴',
viewSource: '소스보기'
},
tree: {
diff --git a/ui/lang/kur-ckb.js b/ui/lang/kur-ckb.js
index 99101da944e..d4be706c5de 100644
--- a/ui/lang/kur-ckb.js
+++ b/ui/lang/kur-ckb.js
@@ -15,7 +15,9 @@ export default {
create: 'دروستکردن',
search: 'گەڕان',
filter: 'پاڵاوتن',
- refresh: 'تازەکردنەوە'
+ refresh: 'تازەکردنەوە',
+ expand: function (label) { return label ? `"${label}" فراوانکردنی` : 'فراوانکردن' },
+ collapse: function (label) { return label ? `"${label}" داخستنی` : 'شکست هێنان' }
},
date: {
days: 'یەک شەممە_دووشەممە_سێ شەممە_چوار شەممە_پێنج شەممە_هەینی_شەممە'.split(
@@ -42,12 +44,12 @@ export default {
selectedRecords: function (rows) {
return rows === 1
? 'یەک ڕیکۆرد هەڵبژێردراوە'
- : (rows === 0 ? '0' : rows) + 'ڕیکۆرد هەڵبژێرداوە.';
+ : (rows === 0 ? '0' : rows) + 'ڕیکۆرد هەڵبژێرداوە.'
},
recordsPerPage: 'ئەنجام بۆهەر پەڕەیەک:',
allRows: 'هەمووی',
pagination: function (start, end, total) {
- return start + '-' + end + ' لە ' + total;
+ return start + '-' + end + ' لە ' + total
},
columns: 'ڕیز'
},
diff --git a/ui/lang/kz.js b/ui/lang/kz.js
new file mode 100644
index 00000000000..b4a7e45b4fd
--- /dev/null
+++ b/ui/lang/kz.js
@@ -0,0 +1,99 @@
+function plurals (n, opts) {
+ return opts[ n % 10 === 1 && n % 100 !== 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2 ]
+}
+
+export default {
+ isoName: 'kz',
+ nativeName: 'Қазақша',
+ label: {
+ clear: 'Тазалау',
+ ok: 'OK',
+ cancel: 'Бас тарту',
+ close: 'Жабу',
+ set: 'Орнату',
+ select: 'Таңдау',
+ reset: 'Қалпына келтіру',
+ remove: 'Өшіру',
+ update: 'Жаңарту',
+ create: 'Жасау',
+ search: 'Іздеу',
+ filter: 'Сүзгі',
+ refresh: 'Жаңарту',
+ expand: function (label) { return label ? `"${label}" кеңейту` : 'Кеңейту' },
+ collapse: function (label) { return label ? `"${label}" жию` : 'Жыйрату' }
+ },
+ date: {
+ days: 'Жексенбі_Дүйсенбі_Сейсенбі_Сәрсенбі_Бейсенбі_Жұма_Сенбі'.split('_'),
+ daysShort: 'Жс_Дс_Сс_Ср_Бс_Жм_Сб'.split('_'),
+ months: 'Қаңтар_Ақпан_Наурыз_Сәуір_Мамыр_Маусым_Шілде_Тамыз_Қыркүйек_Қазан_Қараша_Желтоқсан'.split('_'),
+ monthsShort: 'Қаң_Ақп_Нау_Сәу_Мам_Мау_Шіл_Там_Қыр_Қаз_Қар_Жел'.split('_'),
+ firstDayOfWeek: 1, // 0-6, 0 - Sunday, 1 Monday, ...
+ format24h: true,
+ pluralDay: 'күн'
+ },
+ table: {
+ noData: 'Мәлімет жоқ',
+ noResults: 'Сәйкестік табылмады',
+ loading: 'Жүктеу...',
+ selectedRecords: function (rows) {
+ return rows > 0
+ ? rows + ' ' + plurals(rows, [ 'жол таңдалды', 'жол таңдалды', 'жол таңдалды' ]) + '.'
+ : 'Ешбір жол таңдалмады.'
+ },
+ recordsPerPage: 'Беттегі жолдар:',
+ allRows: 'Бәрі',
+ pagination: function (start, end, total) {
+ return start + '-' + end + ' из ' + total
+ },
+ columns: 'Бағандар'
+ },
+ editor: {
+ url: 'URL',
+ bold: 'Қалың',
+ italic: 'Курсив',
+ strikethrough: 'Сызылған',
+ underline: 'Асты сызылған',
+ unorderedList: 'Маркерленген тізім',
+ orderedList: 'Нөмірленген тізім',
+ subscript: 'Астыңғы таңба',
+ superscript: 'Үстінгі таңба',
+ hyperlink: 'Гиперсілтеме',
+ toggleFullscreen: 'Толық экран режимі',
+ quote: 'Жазба',
+ left: 'Солға туралау',
+ center: 'Ортаға туралау',
+ right: 'Оңға туралау',
+ justify: 'Ені бойынша туралау',
+ print: 'Басып шығару',
+ outdent: 'Шегірісті азайту',
+ indent: 'Шегірісті үлкейту',
+ removeFormat: 'Пішімдеуді жою',
+ formatting: 'Пішімдеу',
+ fontSize: 'Қаріп өлшемі',
+ align: 'Туралау',
+ hr: 'Көлденең сызықты енгізу',
+ undo: 'Болдырмау',
+ redo: 'Қайталау',
+ heading1: 'Тақырып 1',
+ heading2: 'Тақырып 2',
+ heading3: 'Тақырып 3',
+ heading4: 'Тақырып 4',
+ heading5: 'Тақырып 5',
+ heading6: 'Тақырып 6',
+ paragraph: 'Параграф',
+ code: 'Код',
+ size1: 'Өте кішкентай',
+ size2: 'Кішкентай',
+ size3: 'Қалыпты',
+ size4: 'Орташа',
+ size5: 'Үлкен',
+ size6: 'Өте үлкен',
+ size7: 'Дәу',
+ defaultFont: 'Әдепкі қаріп',
+ viewSource: 'Бастапқы кодты қарау'
+ },
+ tree: {
+ noNodes: 'Түйіндер қолжетімді емес',
+ noResults: 'Сәйкестік табылмады'
+ }
+}
diff --git a/ui/lang/lu.js b/ui/lang/lu.js
index ffae944233e..f80592ac384 100644
--- a/ui/lang/lu.js
+++ b/ui/lang/lu.js
@@ -14,7 +14,9 @@ export default {
create: 'Erstellen',
search: 'Sichen',
filter: 'Filter',
- refresh: 'Aktualiséieren'
+ refresh: 'Aktualiséieren',
+ expand: function (label) { return label ? `"${label}" erweideren` : 'Erweideren' },
+ collapse: function (label) { return label ? `"${label}" zesummeklappen` : 'Zesummebroch' }
},
date: {
days: 'Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg'.split('_'),
diff --git a/ui/lang/lv.js b/ui/lang/lv.js
index 9e14301c913..47437e8aa9b 100644
--- a/ui/lang/lv.js
+++ b/ui/lang/lv.js
@@ -14,7 +14,9 @@ export default {
create: 'Izveidot',
search: 'Meklēt',
filter: 'Filtēt',
- refresh: 'Atjaunot'
+ refresh: 'Atjaunot',
+ expand: function (label) { return label ? `Paplašināt "${label}"` : 'Izvērst' },
+ collapse: function (label) { return label ? `Sakļaut "${label}"` : 'Sakļaut' }
},
date: {
days: 'Svētdiena_Pirmdiena_Otrdiena_Trešdiena_Ceturtdiena_Piektdiena_Sestdiena'.split('_'),
diff --git a/ui/lang/mk.js b/ui/lang/mk.js
new file mode 100644
index 00000000000..cfe166a5804
--- /dev/null
+++ b/ui/lang/mk.js
@@ -0,0 +1,93 @@
+export default {
+ isoName: 'mk',
+ nativeName: 'Македонски',
+ label: {
+ clear: 'Испразни',
+ ok: 'ОК',
+ cancel: 'Откажи',
+ close: 'Затвори',
+ set: 'Постави',
+ select: 'Избери',
+ reset: 'Ресетирај',
+ remove: 'Отстрани',
+ update: 'Ажурирај',
+ create: 'Креирај',
+ search: 'Пребарувај',
+ filter: 'Филтрирај',
+ refresh: 'Освежи',
+ expand: function (label) { return label ? `Прошири "${ label }"` : 'Прошири' },
+ collapse: function (label) { return label ? `Собери на "${ label }"` : 'Собери' }
+ },
+ date: {
+ days: 'Недела_Понеделник_Вторник_Среда_Четврток_Петок_Сабота'.split(''),
+ daysShort: 'Нед_Пон_Вто_Сре_Чет_Пет_Саб'.split(''),
+ months: 'Јануари_Февруари_Март_Април_Мај_Јуни_Јули_Август_Септември_Октомври_Ноември_Декември'.split(''),
+ monthsShort: 'Јан_Фев_Мар_Апр_Мај_Јун_Јул_Авг_Сеп_Окт_Ное_Дек'.split(''),
+ firstDayOfWeek: 0, // 0-6, 0 - Недела, 1 - Понеделник, ...
+ format24h: false,
+ pluralDay: 'денови'
+ },
+ table: {
+ noData: 'Нема достапни податоци',
+ noResults: 'Нема резултати за пребарување',
+ loading: 'Вчитување...',
+ selectedRecords: function (rows) {
+ return rows === 1
+ ? 'Избран е 1 запис.'
+ : (rows === 0 ? 'Нема' : rows) + ' записи се избрани.'
+ },
+ recordsPerPage: 'Записи по страница:',
+ allRows: 'Сите',
+ pagination: function (start, end, total) { return start + '-' + end + ' од ' + total },
+ columns: 'Колони'
+ },
+ editor: {
+ url: 'URL',
+ bold: 'Задебелено',
+ italic: 'Курзив',
+ strikethrough: 'Прецртано',
+ underline: 'Подвлечено',
+ unorderedList: 'Неподредена листа',
+ orderedList: 'Подредена листа',
+ subscript: 'Индекс',
+ superscript: 'Степен',
+ hyperlink: 'Хиперврска',
+ toggleFullscreen: 'Цел екран',
+ quote: 'Цитат',
+ left: 'Лева подредба',
+ center: 'Центрирана подредба',
+ right: 'Десна подредба',
+ justify: 'Равномерна подредба',
+ print: 'Печати',
+ outdent: 'Намали маргина',
+ indent: 'Зголеми маргина',
+ removeFormat: 'Отстрани форматирање',
+ formatting: 'Форматирање',
+ fontSize: 'Големина на фонт',
+ align: 'Подредба',
+ hr: 'Вметни хоризонтална линија',
+ undo: 'Поништи',
+ redo: 'Врати',
+ heading1: 'Наслов 1',
+ heading2: 'Наслов 2',
+ heading3: 'Наслов 3',
+ heading4: 'Наслов 4',
+ heading5: 'Наслов 5',
+ heading6: 'Наслов 6',
+ paragraph: 'Параграф',
+ code: 'Код',
+ size1: 'Многу мала',
+ size2: 'Малку помала',
+ size3: 'Нормална',
+ size4: 'Средно-голема',
+ size5: 'Голема',
+ size6: 'Многу голема',
+ size7: 'Максимална',
+ defaultFont: 'Стандарден фонт',
+ viewSource: 'Преглед на изворниот код'
+ },
+ tree: {
+ noNodes: 'Нема достапни јазли',
+ noResults: 'Нема пронајдено резултати'
+ }
+}
diff --git a/ui/lang/ml.js b/ui/lang/ml.js
index b87cee12ded..bb63d15b0a1 100644
--- a/ui/lang/ml.js
+++ b/ui/lang/ml.js
@@ -14,7 +14,9 @@ export default {
create: 'സൃഷ്ടിക്കുക',
search: 'തിരയുക',
filter: 'അരിക്കുക',
- refresh: 'പുതുക്കുക'
+ refresh: 'പുതുക്കുക',
+ expand: function (label) { return label ? `"${label}" വികസിപ്പിക്കുക` : 'വികസിപ്പിക്കുക' },
+ collapse: function (label) { return label ? `"${label}" ചുരുക്കുക` : 'ചുരുക്കുക' }
},
date: {
days: 'ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി'.split('_'),
diff --git a/ui/lang/mm.js b/ui/lang/mm.js
new file mode 100644
index 00000000000..3f67815fdbc
--- /dev/null
+++ b/ui/lang/mm.js
@@ -0,0 +1,95 @@
+export default {
+ isoName: 'mm',
+ nativeName: 'မြန်မာ(ဗမာ)',
+ label: {
+ clear: 'ရှင်းလင်းမည်',
+ ok: 'အဆင်ပြေသည်',
+ cancel: 'ပယ်ဖျက်မည်',
+ close: 'ပိတ်မည်',
+ set: 'သတ်မှတ်မည်',
+ select: 'ရွေးမည်',
+ reset: 'ပြန်လည်သတ်မှတ်မည်',
+ remove: 'ပယ်ဖျက်မည်',
+ update: 'အသစ်ပြင်ဆင်မည်',
+ create: 'ဖန်တီးမည်',
+ search: 'ရှာမည်',
+ filter: 'စစ်ထုတ်မည်',
+ refresh: 'အသစ်ပြန်လုပ်မည်',
+ expand: function (label) { return label ? `"${label}" ကိုချဲ့ထွင်ပါ။` : 'ချဲ့ထွင်ပါ။' },
+ collapse: function (label) { return label ? `"${label}" ကို ခေါက်သိမ်းပါ` : 'ပြိုကျသည်။' }
+ },
+ date: {
+ days: 'တနင်္ဂနွေ_တနင်္လာ_အင်္ဂါ_ဗုဒ္ဓဟူး_ကြာသပတေး_သောကြာ_စနေ'.split('_'),
+ daysShort: 'တနင်္ဂနွေ_တနင်္လာ_အင်္ဂါ_ဗုဒ္ဓဟူး_ကြာသပတေး_သောကြာ_စနေ'.split('_'),
+ months: 'ဇန်နဝါရီ_ဖေဖော်ဝါရီ_မတ်_ဧပြီ_မေ_ဇွန်_ဇူလိုင်_သြဂုတ်_စက်တင်ဘာ_အောက်တိုဘာ_နိုဝင်ဘာ_ဒီဇင်ဘာ'.split('_'),
+ monthsShort: 'ဇန်နဝါရီ_ဖေဖော်ဝါရီ_မတ်_ဧပြီ_မေ_ဇွန်_ဇူလိုင်_သြဂုတ်_စက်တင်ဘာ_အောက်တိုဘာ_နိုဝင်ဘာ_ဒီဇင်ဘာ'.split('_'),
+ firstDayOfWeek: 1, // 0-6, 0 - Sunday, 1 Monday, ...
+ format24h: false,
+ pluralDay: 'ရက်'
+ },
+ table: {
+ noData: 'ဒေတာမရှိပါ',
+ noResults: 'ကိုက်ညီသောရလဒ်မရှိပါ',
+ loading: 'လုပ်ဆောင်နေသည်',
+ selectedRecords: rows => (
+ rows > 0
+ ? rows + ' ကြောင်းရွေးချယ်ထားသည်'
+ : 'ဘာမှ မရွေးချယ်ထားပါ'
+ ),
+ recordsPerPage: 'တစ်မျက်နှာ အကြောင်းရေတွက်',
+ allRows: 'အားလုံး',
+ pagination: function (start, end, total) {
+ return start + 'မှ' + end + 'ထိ' + 'အားလုံး' + total + 'ရှိ'
+ },
+ columns: 'ကော်လံ'
+ },
+ editor: {
+ url: 'URL',
+ bold: 'Bold',
+ italic: 'Italic',
+ strikethrough: 'Strikethrough',
+ underline: 'Underline',
+ unorderedList: 'Unordered List',
+ orderedList: 'Ordered List',
+ subscript: 'Subscript',
+ superscript: 'Superscript',
+ hyperlink: 'Hyperlink',
+ toggleFullscreen: 'Toggle Fullscreen',
+ quote: 'Quote',
+ left: 'Left align',
+ center: 'Center align',
+ right: 'Right align',
+ justify: 'Justify align',
+ print: 'Print',
+ outdent: 'Decrease indentation',
+ indent: 'Increase indentation',
+ removeFormat: 'Remove formatting',
+ formatting: 'Formatting',
+ fontSize: 'Font Size',
+ align: 'Align',
+ hr: 'Insert Horizontal Rule',
+ undo: 'Undo',
+ redo: 'Redo',
+ heading1: 'Heading 1',
+ heading2: 'Heading 2',
+ heading3: 'Heading 3',
+ heading4: 'Heading 4',
+ heading5: 'Heading 5',
+ heading6: 'Heading 6',
+ paragraph: 'Paragraph',
+ code: 'Code',
+ size1: 'Very small',
+ size2: 'A bit small',
+ size3: 'Normal',
+ size4: 'Medium-large',
+ size5: 'Big',
+ size6: 'Very big',
+ size7: 'Maximum',
+ defaultFont: 'Default Font',
+ viewSource: 'View Source'
+ },
+ tree: {
+ noNodes: 'No nodes available',
+ noResults: 'No matching nodes found'
+ }
+}
diff --git a/ui/lang/ms.js b/ui/lang/ms.js
index 547ba5cc058..f0d477312ab 100644
--- a/ui/lang/ms.js
+++ b/ui/lang/ms.js
@@ -14,7 +14,9 @@ export default {
create: 'Tambah',
search: 'Cari',
filter: 'Saring',
- refresh: 'Muat semula'
+ refresh: 'Muat semula',
+ expand: function (label) { return label ? `Kembangkan "${label}"` : 'Kembangkan' },
+ collapse: function (label) { return label ? `Runtuhkan "${label}"` : 'Runtuh' }
},
date: {
days: 'Ahad_Isnin_Selasa_Rabu_Khamis_Jummat_Sabtu'.split('_'),
diff --git a/ui/lang/my.js b/ui/lang/my.js
new file mode 100644
index 00000000000..7461db4fa6f
--- /dev/null
+++ b/ui/lang/my.js
@@ -0,0 +1,98 @@
+export default {
+ isoName: 'my',
+ nativeName: 'Malaysia',
+ label: {
+ clear: 'kosong',
+ ok: 'pasti',
+ cancel: 'Batal',
+ close: 'penutupan',
+ set: 'sediakan',
+ select: 'pilih',
+ reset: 'set semula',
+ remove: 'keluarkan',
+ update: 'memperbaharui',
+ create: 'cipta',
+ search: 'cari',
+ filter: 'penapis',
+ refresh: 'segarkan semula',
+ expand: function (label) { return label ? `"${label}" ko hkyaae htwin par` : 'hkyaae htwin par' },
+ collapse: function (label) { return label ? `"${label}" ko hkout saimpar` : 'pyaokya sai' }
+ },
+ date: {
+ days: 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'),
+ daysShort: 'Aha_Isn_Sel_Rab_Kha_Jum_Sab'.split('_'),
+ months: 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.split('_'),
+ monthsShort: 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogo_Sep_Okt_Nov_Dis'.split('_'),
+ headerTitle: function (date) {
+ return new Intl.DateTimeFormat('my', {
+ weekday: 'short', month: 'short', day: 'numeric'
+ }).format(date)
+ },
+ firstDayOfWeek: 0, // 0-6, 0 - Sunday, 1 Monday, ...
+ format24h: false,
+ pluralDay: 'langit'
+ },
+ table: {
+ noData: 'tiada data tersedia',
+ noResults: 'Tiada data yang sepadan ditemui',
+ loading: 'memuatkan...',
+ selectedRecords: function (rows) {
+ return 'dipilih' + rows + 'baris'
+ },
+ recordsPerPage: 'baris setiap muka surat:',
+ allRows: 'semua',
+ pagination: function (start, end, total) {
+ return start + '-' + end + ' / ' + total
+ },
+ columns: 'Senaraikan'
+ },
+ editor: {
+ url: 'URL',
+ bold: 'berani',
+ italic: 'condong',
+ strikethrough: 'tembus',
+ underline: 'gariskan',
+ unorderedList: 'senarai tidak teratur',
+ orderedList: 'senarai pesanan',
+ subscript: 'subskrip',
+ superscript: 'superskrip',
+ hyperlink: 'Hiperpautan',
+ toggleFullscreen: 'togol skrin penuh',
+ quote: 'tanda petikan',
+ left: 'Jajar ke kiri',
+ center: 'penjajaran tengah',
+ right: 'Sejajar ke kanan',
+ justify: 'wajar',
+ print: 'Cetak',
+ outdent: 'mengurangkan lekukan',
+ indent: 'meningkatkan inden',
+ removeFormat: 'gaya yang jelas',
+ formatting: 'format',
+ fontSize: 'Saiz huruf',
+ align: 'selaraskan',
+ hr: 'Masukkan garisan mendatar',
+ undo: 'membatalkan',
+ redo: 'buat semula',
+ heading1: 'Tajuk satu',
+ heading2: 'Tajuk dua',
+ heading3: 'Tajuk tiga',
+ heading4: 'Tajuk Empat',
+ heading5: 'Tajuk Lima',
+ heading6: 'Tajuk Enam',
+ paragraph: 'perenggan',
+ code: 'kod',
+ size1: 'sangat kecil',
+ size2: 'lebih kecil',
+ size3: 'biasa',
+ size4: 'sederhana hingga besar',
+ size5: 'besar',
+ size6: 'sangat besar',
+ size7: 'super besar',
+ defaultFont: 'fon lalai',
+ viewSource: 'menyemak data'
+ },
+ tree: {
+ noNodes: 'tiada nod tersedia',
+ noResults: 'Tiada nod yang sepadan ditemui'
+ }
+}
diff --git a/ui/lang/nb-no.js b/ui/lang/nb-no.js
index 9efb459e986..82bf0ef5898 100644
--- a/ui/lang/nb-no.js
+++ b/ui/lang/nb-no.js
@@ -14,7 +14,9 @@ export default {
create: 'Lag',
search: 'Søk',
filter: 'Filter',
- refresh: 'Oppdater'
+ refresh: 'Oppdater',
+ expand: function (label) { return label ? `Utvid "${label}"` : 'Utvide' },
+ collapse: function (label) { return label ? `Skjul "${label}"` : 'Kollapse' }
},
date: {
days: 'Søndag_Mandag_Tirsdag_Onsdag_Torsdag_Fredag_Lørdag'.split('_'),
diff --git a/ui/lang/nl.js b/ui/lang/nl.js
index d0d58adb166..788f863ff1a 100644
--- a/ui/lang/nl.js
+++ b/ui/lang/nl.js
@@ -14,7 +14,9 @@ export default {
create: 'Maak aan',
search: 'Zoek',
filter: 'Filter',
- refresh: 'Ververs'
+ refresh: 'Ververs',
+ expand: function (label) { return label ? `"${label}" uitklappen` : 'Uitklappen' },
+ collapse: function (label) { return label ? `"${label}" inklappen` : 'Inklappen' }
},
date: {
days: 'Zondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrijdag_Zaterdag'.split('_'),
diff --git a/ui/lang/pl.js b/ui/lang/pl.js
index b2df57d5a6e..675e6d87ae4 100644
--- a/ui/lang/pl.js
+++ b/ui/lang/pl.js
@@ -14,7 +14,9 @@ export default {
create: 'Utwórz',
search: 'Szukaj',
filter: 'Filtruj',
- refresh: 'Odśwież'
+ refresh: 'Odśwież',
+ expand: function (label) { return label ? `Rozwiń "${label}"` : 'Zwiększać' },
+ collapse: function (label) { return label ? `Zwiń "${label}"` : 'Upadek' }
},
date: {
days: 'Niedziela_Poniedziałek_Wtorek_Środa_Czwartek_Piątek_Sobota'.split('_'),
diff --git a/ui/lang/pt-br.js b/ui/lang/pt-br.js
index fcaefafa197..16afb030218 100644
--- a/ui/lang/pt-br.js
+++ b/ui/lang/pt-br.js
@@ -14,7 +14,9 @@ export default {
create: 'Criar',
search: 'Buscar',
filter: 'Filtrar',
- refresh: 'Recarregar'
+ refresh: 'Recarregar',
+ expand: function (label) { return label ? `Expandir "${label}"` : 'Expandir' },
+ collapse: function (label) { return label ? `Recolher "${label}"` : 'Colapso' }
},
date: {
days: 'Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado'.split('_'),
diff --git a/ui/lang/pt.js b/ui/lang/pt.js
index f17405de940..75e4c84849b 100644
--- a/ui/lang/pt.js
+++ b/ui/lang/pt.js
@@ -14,7 +14,9 @@ export default {
create: 'Criar',
search: 'Procurar',
filter: 'Filtrar',
- refresh: 'Recarregar'
+ refresh: 'Recarregar',
+ expand: function (label) { return label ? `Expandir "${label}"` : 'Expandir' },
+ collapse: function (label) { return label ? `Recolher "${label}"` : 'Colapso' }
},
date: {
days: 'Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado'.split('_'),
diff --git a/ui/lang/ro.js b/ui/lang/ro.js
index 0ac40d39343..69e602413af 100644
--- a/ui/lang/ro.js
+++ b/ui/lang/ro.js
@@ -14,7 +14,9 @@ export default {
create: 'Creează',
search: 'Caută',
filter: 'Filtrează',
- refresh: 'Actualizează'
+ refresh: 'Actualizează',
+ expand: function (label) { return label ? `Deschideți "${label}"` : 'Deschide' },
+ collapse: function (label) { return label ? `Închide "${label}"` : 'Închide' }
},
date: {
days: 'Duminică_Luni_Marți_Miercuri_Joi_Vineri_Sâmbătă'.split('_'),
diff --git a/ui/lang/ru.js b/ui/lang/ru.js
index 9cabb566d44..03fd6586407 100644
--- a/ui/lang/ru.js
+++ b/ui/lang/ru.js
@@ -18,7 +18,9 @@ export default {
create: 'Создать',
search: 'Поиск',
filter: 'Фильтр',
- refresh: 'Обновить'
+ refresh: 'Обновить',
+ expand: function (label) { return label ? `Расширьте "${label}"` : 'Расширять' },
+ collapse: function (label) { return label ? `Свернуть "${label}"` : 'Крах' }
},
date: {
days: 'Воскресенье_Понедельник_Вторник_Среда_Четверг_Пятница_Суббота'.split('_'),
diff --git a/ui/lang/sk.js b/ui/lang/sk.js
index 9e9901389f9..8678d0bed55 100644
--- a/ui/lang/sk.js
+++ b/ui/lang/sk.js
@@ -14,7 +14,9 @@ export default {
create: 'Vytvoriť',
search: 'Hľadať',
filter: 'Filtrovať',
- refresh: 'Obnoviť'
+ refresh: 'Obnoviť',
+ expand: function (label) { return label ? `Rozbaliť "${label}"` : 'Rozbaliť' },
+ collapse: function (label) { return label ? `Zbaliť "${label}"` : 'Kolaps' }
},
date: {
days: 'Nedeľa_Pondelok_Utorok_Streda_Štvrtok_Piatok_Sobota'.split('_'),
diff --git a/ui/lang/sl.js b/ui/lang/sl.js
index 0ea1620f516..377a7408ad4 100644
--- a/ui/lang/sl.js
+++ b/ui/lang/sl.js
@@ -3,7 +3,7 @@ export default {
nativeName: 'Slovenski Jezik',
label: {
clear: 'Počisti',
- ok: 'Vredu',
+ ok: 'V redu',
cancel: 'Prekliči',
close: 'Zapri',
set: 'Postavi',
@@ -14,7 +14,9 @@ export default {
create: 'Ustvari',
search: 'Išči',
filter: 'Filtriraj',
- refresh: 'Ponovno naloži'
+ refresh: 'Ponovno naloži',
+ expand: function (label) { return label ? `Razširi "${label}"` : 'Razširi' },
+ collapse: function (label) { return label ? `Strni "${label}"` : 'Strni' }
},
date: {
days: 'Nedelja_Ponedeljek_Torek_Sreda_Četrtek_Petek_Sobota'.split('_'),
diff --git a/ui/lang/sm.js b/ui/lang/sm.js
new file mode 100644
index 00000000000..8e3de81f006
--- /dev/null
+++ b/ui/lang/sm.js
@@ -0,0 +1,95 @@
+export default {
+ isoName: 'sm',
+ nativeName: 'Fa\'asāmoa',
+ label: {
+ clear: 'Kilia',
+ ok: '\'Oukei',
+ cancel: 'Fa\'alēaogāina',
+ close: 'Tapuni',
+ set: 'Seti',
+ select: 'Filifili',
+ reset: 'Toe seti',
+ remove: '\'Ave\'ese',
+ update: 'Fa\'afou',
+ create: 'Fatu',
+ search: 'Sā\'ili',
+ filter: 'Fa\'amamā',
+ refresh: 'Fa\'afou',
+ expand: function (label) { return label ? `Fa'alautele "${label}"` : 'Faalautele' },
+ collapse: function (label) { return label ? `Pa'u "${label}"` : 'Pa\'u' }
+ },
+ date: {
+ days: 'Aso Sā_Aso Gafua_Aso Lua_Aso Lulu_Aso Tofi_Aso Faraile_Aso To\'onai'.split('_'),
+ daysShort: 'Sā_Gaf_Lua_Lul_Tof_Far_Too'.split('_'),
+ months: 'Ianuari_Fepuari_Mati_\'Aperila_Mē_Iuni_Iulai_\'Aokuso_Sētema_\'Oketopa_Nōvema_Tēsema'.split('_'),
+ monthsShort: 'Ian_Fep_Mat_Ape_Mē_Iun_Iul_Auk_Sēt_Oke_Nōv_Tēs'.split('_'),
+ firstDayOfWeek: 1, // 0-6, 0 - Sunday, 1 Monday, ...
+ format24h: false,
+ pluralDay: 'aso'
+ },
+ table: {
+ noData: 'Lēai ni fa\'amatalaga o maua',
+ noResults: 'Lēai ni fa\'amaumauga na maua',
+ loading: '\'Āmatalia...',
+ selectedRecords: function (rows) {
+ return rows === 1
+ ? '1 le laina \'ua filifilia.'
+ : (rows === 0 ? 'Lēai ni' : rows) + ' laina \'ua filifilia.'
+ },
+ recordsPerPage: 'Laina \'i le ītūlau:',
+ allRows: 'Laina \'uma',
+ pagination: function (start, end, total) {
+ return start + '-' + end + ' o ' + total
+ },
+ columns: 'Poutū'
+ },
+ editor: {
+ url: 'Tuātusi initaneti',
+ bold: 'Fa\'aolaola',
+ italic: 'Fa\'api\'o',
+ strikethrough: 'Kolosi',
+ underline: 'Vase lalo',
+ unorderedList: 'Lisi \'e fe\'i fa\'atulagaina',
+ orderedList: 'Lisi \'ua fa\'atulagaina',
+ subscript: 'Fa\'anini\'i i lalo',
+ superscript: 'Fa\'anini\'i i luga',
+ hyperlink: 'So\'otaga initaneti',
+ toggleFullscreen: 'Fa\'atelē ma fa\'alititi le va\'ai',
+ quote: 'Saunoaga',
+ left: 'Ōgatasi agavale',
+ center: 'Ōgatasi \'ogātotonu',
+ right: 'Ōgatasi taumatau',
+ justify: 'Ōgatasi lautele',
+ print: 'Lolomi',
+ outdent: 'Fa\'alaititi le va',
+ indent: 'Fa\'atelē le va',
+ removeFormat: '\'Ave\'ese le fa\'atulagaga',
+ formatting: 'Fa\'atulagaga',
+ fontSize: 'Telē o le mata\'itusi',
+ align: 'Ōgatasi',
+ hr: 'Fa\'aopoopo se laina',
+ undo: 'Toe \'ave\'ese',
+ redo: 'Toe fai',
+ heading1: 'Ulutala 1',
+ heading2: 'Ulutala 2',
+ heading3: 'Ulutala 3',
+ heading4: 'Ulutala 4',
+ heading5: 'Ulutala 5',
+ heading6: 'Ulutala 6',
+ paragraph: 'Palakalafa',
+ code: 'Fa\'ailo fa\'akomepiuta',
+ size1: 'Matuā laitiiti',
+ size2: 'Fa\'alaititi',
+ size3: 'Tūlaga masani',
+ size4: 'Lāpo\'a feololo',
+ size5: 'Lāpo\'a',
+ size6: 'Lāpo\'a atu',
+ size7: 'Pito i lāpo\'a',
+ defaultFont: 'Foliga fou ole mata\'itusi',
+ viewSource: 'Va\'ai \'ile tusitusiga fa\'akomepiuta'
+ },
+ tree: {
+ noNodes: 'Lēai ni vāega o maua',
+ noResults: 'Lēai ni vāega na maua'
+ }
+}
diff --git a/ui/lang/sr.js b/ui/lang/sr.js
index f37383f8c2e..d8c87ef9e12 100644
--- a/ui/lang/sr.js
+++ b/ui/lang/sr.js
@@ -1,6 +1,6 @@
export default {
isoName: 'sr',
- nativeName: 'српски језик',
+ nativeName: 'srpski jezik',
label: {
clear: 'Obriši',
ok: 'OK',
@@ -14,7 +14,9 @@ export default {
create: 'Dodaj',
search: 'Traži',
filter: 'Filter',
- refresh: 'Osveži'
+ refresh: 'Osveži',
+ expand: function (label) { return label ? `Proširi "${label}"` : 'Proširiti' },
+ collapse: function (label) { return label ? `Skupi "${label}"` : 'Skupiti' }
},
date: {
days: 'Nedelja_Ponedeljak_Utorak_Sreda_Četvrtak_Petak_Subota'.split('_'),
@@ -23,7 +25,7 @@ export default {
monthsShort: 'Jan_Feb_Mar_Apr_Maj_Jun_Jul_Avg_Sep_Okt_Nov_Dec'.split('_'),
firstDayOfWeek: 1, // 0-6, 0 - Sunday, 1 Monday, ...
format24h: true,
- pluralDay: 'дана'
+ pluralDay: 'dana'
},
table: {
noData: 'Nema podataka',
@@ -58,14 +60,14 @@ export default {
center: 'Centrirati',
right: 'Poravnati udesno',
justify: 'Poravnati obostrano',
- print: 'Ispis',
+ print: 'Štampa',
outdent: 'Smanjiti uvlačenje',
indent: 'Povećati uvlačenje',
removeFormat: 'Ukloniti formatiranje',
formatting: 'Formatirati',
fontSize: 'Veličina slova',
align: 'Poravnati',
- hr: 'Ubaciti vodoravni lenjir',
+ hr: 'Ubaciti horizontalnu liniju',
undo: 'Poništiti',
redo: 'Vratiti',
heading1: 'Naslov 1',
@@ -74,17 +76,17 @@ export default {
heading4: 'Naslov 4',
heading5: 'Naslov 5',
heading6: 'Naslov 6',
- paragraph: 'Odlomak',
+ paragraph: 'Paragraf',
code: 'Kod',
size1: 'Najmanje',
size2: 'Manje',
size3: 'Normalno',
size4: 'Srednje Veliko',
size5: 'Veliko',
- size6: 'Već',
+ size6: 'Veće',
size7: 'Najveće',
- defaultFont: 'Zadani font',
- viewSource: 'Погледај извор'
+ defaultFont: 'Podrazumevani font',
+ viewSource: 'Pogledaj izvor'
},
tree: {
noNodes: 'Nema nijednog čvora',
diff --git a/ui/lang/sv.js b/ui/lang/sv.js
index 3daeba9a1f5..bf3a2cbe921 100644
--- a/ui/lang/sv.js
+++ b/ui/lang/sv.js
@@ -14,7 +14,9 @@ export default {
create: 'Skapa',
search: 'Sök',
filter: 'Filtrera',
- refresh: 'Uppdatera'
+ refresh: 'Uppdatera',
+ expand: function (label) { return label ? `Utöka "${label}"` : 'Bygga ut' },
+ collapse: function (label) { return label ? `Komprimera "${label}"` : 'Kollaps' }
},
date: {
days: 'Söndag_Måndag_Tisdag_Onsdag_Torsdag_Fredag_Lördag'.split('_'),
diff --git a/ui/lang/ta.js b/ui/lang/ta.js
index ffe6d1d95cf..200a4ad1184 100644
--- a/ui/lang/ta.js
+++ b/ui/lang/ta.js
@@ -14,7 +14,9 @@ export default {
create: 'உருவாக்கு',
search: 'தேடு',
filter: 'வடிகட்டு',
- refresh: 'புதுப்பி'
+ refresh: 'புதுப்பி',
+ expand: function (label) { return label ? `"${label}" ஐ விரிவாக்கு` : 'விரிவாக்கு' },
+ collapse: function (label) { return label ? `"${label}" ஐச் சுருக்கு` : 'சுருக்கு' }
},
date: {
days: 'ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி'.split('_'),
diff --git a/ui/lang/th.js b/ui/lang/th.js
index ec0a2b29a9e..b2cb021fc8c 100644
--- a/ui/lang/th.js
+++ b/ui/lang/th.js
@@ -14,7 +14,9 @@ export default {
create: 'สร้าง',
search: 'ค้นหา',
filter: 'กรอง',
- refresh: 'รีเฟรช'
+ refresh: 'รีเฟรช',
+ expand: function (label) { return label ? `ขยาย "${label}"` : 'ขยาย' },
+ collapse: function (label) { return label ? `ยุบ "${label}"` : 'ทรุด' }
},
date: {
days: 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์'.split('_'),
diff --git a/ui/lang/tr.js b/ui/lang/tr.js
index 26a66cdbdf0..4bee857242e 100644
--- a/ui/lang/tr.js
+++ b/ui/lang/tr.js
@@ -14,7 +14,9 @@ export default {
create: 'Oluştur',
search: 'Ara',
filter: 'Süz',
- refresh: 'Yenile'
+ refresh: 'Yenile',
+ expand: function (label) { return label ? `"${label}" genişlet` : 'Genişletmek' },
+ collapse: function (label) { return label ? `"${label}" daralt` : 'Yıkılmak' }
},
date: {
days: 'Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi'.split('_'),
diff --git a/ui/lang/ug.js b/ui/lang/ug.js
index ad4b563815d..aaeb17a7264 100644
--- a/ui/lang/ug.js
+++ b/ui/lang/ug.js
@@ -1,98 +1,99 @@
-const days = 'يەكشەنبە_دۈشەنبە_سەيشەنبە_چارشەنبە_پەيشەنبە_جۈمە_شەنبە'.split('_')
-const monthsShort = '1-ئاي_2-ئاي_3-ئاي_4-ئاي_5-ئاي_6-ئاي_7-ئاي_8-ئاي_9-ئاي_10-ئاي_11-ئاي_12-ئاي'.split('_')
+const days = 'يەكشەنبە_دۈشەنبە_سەيشەنبە_چارشەنبە_پەيشەنبە_جۈمە_شەنبە_يەكشەنبە'.split('_')
export default {
isoName: 'ug',
nativeName: 'ئۇيغۇرچە',
rtl: true,
label: {
- clear: 'تازلاش',
- ok: 'جەزملەش',
- cancel: 'بىكار قىلىش',
+ clear: 'تازىلاش',
+ ok: 'ھەئە',
+ cancel: 'بولدىلا',
close: 'تاقاش',
- set: 'تەڭشەك',
+ set: 'تەڭشەش',
select: 'تاللاش',
reset: 'ئەسلىگە قايتۇرۇش',
- remove: 'چىقىرۋىتىش',
- update: 'يېڭىلاش',
+ remove: 'چىقىرىۋېتىش',
+ update: 'نەشىر يېڭىلاش',
create: 'قۇرۇش',
search: 'ئىزدەش',
- filter: 'سۈزۈش',
- refresh: 'يېڭىلاش'
+ filter: 'سۈزگۈچ',
+ refresh: 'يېڭىلاش',
+ expand: function (label) { return label ? `نى كېڭەيتىڭ "${label}"` : 'كېڭەيتىش' },
+ collapse: function (label) { return label ? `نى يىمىرىڭ "${label}"` : 'كېڭەيتىش' }
},
date: {
- days: days,
+ days,
daysShort: 'ي_د_س_چ_پ_ج_ش'.split('_'),
- months: monthsShort,
- monthsShort: monthsShort,
- headerTitle: function(date, model) {
- return monthsShort[model.month - 1] + 'نىڭ ' + model.day + '-كۈنى، ' + days[date.getDay()]
- },
+ months: 'يانۋار(1)_فېۋرال(2)_مارت(3)_ئاپرىل(4)_ماي(5)_ئىيۇن(6)_ئىيۇل(7)_ئاۋغۇست (8)_سېنتەبىر(9)_ئۆكتەبىر(10)_نويابىر(11)_دېكابىر(12)'.split('_'),
+ monthsShort: '1-ئاي_2-ئاي_3-ئاي_4-ئاي_5-ئاي_6-ئاي_7-ئاي_8-ئاي_9-ئاي_10-ئاي_11-ئاي_12-ئاي'.split('_'),
firstDayOfWeek: 1, // 0-6, 0 - Sunday, 1 Monday, ...
format24h: false,
+ headerTitle: function (date, model) {
+ return model.month + '-ئاينىڭ ' + model.day + '-كۈنى ، ' + days[ date.getDay() ]
+ },
pluralDay: 'كۈن'
},
table: {
noData: 'ئۇچۇر يوق',
noResults: 'مۇناسىۋەتلىك ئۇچۇر تېپىلمىدى',
- loading: 'يۈكلىنىۋاتىدۇ...',
- selectedRecords: function(rows) {
- return rows + ' قۇر تاللاندى'
+ loading: 'يۈكلىنىۋاتىدۇ ...',
+ selectedRecords: function (rows) {
+ return 'جەمئىي ' + rows + ' قۇر تاللاندى'
},
recordsPerPage: 'ھەربەتتىكى قۇر سانى:',
allRows: 'ھەممىسى',
- pagination: function(start, end, total) {
+ pagination: function (start, end, total) {
return start + '-' + end + ' / ' + total
},
columns: 'ئىستون'
},
editor: {
url: 'URL',
- bold: '粗体',
- italic: '斜体',
- strikethrough: '删除线',
- underline: '下划线',
- unorderedList: '无序列表',
- orderedList: '有序列表',
- subscript: '下标',
- superscript: '上标',
- hyperlink: '超链接',
- toggleFullscreen: '全屏切换',
- quote: '引号',
- left: '左对齐',
- center: '居中对齐',
- right: '右对齐',
- justify: '两端对齐',
- print: '打印',
- outdent: '减少缩进',
- indent: '增加缩进',
- removeFormat: '清除样式',
- formatting: '格式化',
- fontSize: '字体大小',
- align: '对齐',
- hr: '插入水平线',
- undo: '撤消',
- redo: '重做',
- heading1: '标题一',
- heading2: '标题二',
- heading3: '标题三',
- heading4: '标题四',
- heading5: '标题五',
- heading6: '标题六',
- paragraph: '段落',
- code: '代码',
- size1: '非常小',
- size2: '比较小',
- size3: '正常',
- size4: '中等偏大',
- size5: '大',
- size6: '非常大',
- size7: '超级大',
- defaultFont: '默认字体',
- viewSource: '查看资料'
+ bold: 'توم',
+ italic: 'يانتۇ',
+ strikethrough: 'جىجاش',
+ underline: 'ئاستى سىزىق',
+ unorderedList: 'تەرتىپسىز',
+ orderedList: 'تەرتىپلىك',
+ subscript: 'تۆۋەن ئىندېكىس',
+ superscript: 'يۇقىرى ئىندېكىس',
+ hyperlink: 'ئۇلانما',
+ toggleFullscreen: 'پۈتۈن ئېكران',
+ quote: 'نەقىل',
+ left: 'سولغا توغرىلاش',
+ center: 'ئوتتۇرىغا توغرىلاش',
+ right: 'ئوڭغا توغرىلاش',
+ justify: 'ئىككى يانغا توغرىلاش',
+ print: 'بېسىپ چىقىرىش',
+ outdent: 'كېڭەيتىش',
+ indent: 'تارايتىش',
+ removeFormat: 'فورماتىنى چىقىرىۋېتىش',
+ formatting: 'فورماتلاش',
+ fontSize: 'خەت چوڭلىقى',
+ align: 'توغرىلاش',
+ hr: 'توغرا سىزىق',
+ undo: 'قايتۇرۇش',
+ redo: 'قايتىلاش',
+ heading1: 'تىما 1',
+ heading2: 'تىما 2',
+ heading3: 'تىما 3',
+ heading4: 'تىما 4',
+ heading5: 'تىما 5',
+ heading6: 'تىما 6',
+ paragraph: 'ئابزاس',
+ code: 'كود',
+ size1: 'كىچىك',
+ size2: 'كىچىكراق',
+ size3: 'نورمال',
+ size4: 'چوڭراق',
+ size5: 'چوڭ',
+ size6: 'ئىنتايىن چوڭ',
+ size7: 'ئەڭ چوڭ',
+ defaultFont: 'كۆڭۈلدىكى خەت نۇسخىسى',
+ viewSource: 'مەنبەنى كۆرۈش'
},
tree: {
- noNodes: 'ئۇچۇر يوق',
- noResults: 'مۇناسىۋەتلىك ئۇچۇر تېپىلمىدى'
+ noNodes: 'تۈگۈن يوق',
+ noResults: 'ئۇچۇر يوق'
}
}
diff --git a/ui/lang/uk.js b/ui/lang/uk.js
index 71a29cc2f32..6281453b0e7 100644
--- a/ui/lang/uk.js
+++ b/ui/lang/uk.js
@@ -18,7 +18,9 @@ export default {
create: 'Створити',
search: 'Пошук',
filter: 'Фільтр',
- refresh: 'Оновити'
+ refresh: 'Оновити',
+ expand: function (label) { return label ? `Розгорнути "${label}"` : 'Розгорнути' },
+ collapse: function (label) { return label ? `Згорнути "${label}"` : 'Згорнути' }
},
date: {
days: 'Неділя_Понеділок_Вівторок_Середа_Четвер_П`ятниця_Субота'.split('_'),
diff --git a/ui/lang/uz-Cyrl.js b/ui/lang/uz-Cyrl.js
new file mode 100644
index 00000000000..28ce9700233
--- /dev/null
+++ b/ui/lang/uz-Cyrl.js
@@ -0,0 +1,95 @@
+export default {
+ isoName: 'uz-Cyrl',
+ nativeName: 'Ўзбекча (Кирил)',
+ label: {
+ clear: 'Тозалаш',
+ ok: 'ОК',
+ cancel: 'Бекор қилиш',
+ close: 'Ёпиш',
+ set: 'Ўрнатиш',
+ select: 'Танлаш',
+ reset: 'Қайта ўрнатиш',
+ remove: 'Ўчириш',
+ update: 'Янгилаш',
+ create: 'Яратиш',
+ search: 'Қидириш',
+ filter: 'Филтрлаш',
+ refresh: 'Янгилаш',
+ expand: function (label) { return label ? `"${label}" ни кенгайтириш` : 'ъКенгайтиришъ' },
+ collapse: function (label) { return label ? `"${label}" ни йиғиш` : 'ъЙиқилишъ' }
+ },
+ date: {
+ days: 'Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба'.split('_'),
+ daysShort: 'Як_Душ_Се_Чор_Пай_Жума_Шанба'.split('_'),
+ months:
+ 'Январь_Февраль_Март_Апрель_Май_Июнь_Июль_Август_Сентябрь_Октябрь_Ноябрь_Декабрь'.split(
+ '_'
+ ),
+ monthsShort: 'Ян_Фев_Март_Апр_Май_Июнь_Июль_Авг_Сен_Окт_Ноя_Дек'.split('_'),
+ firstDayOfWeek: 1, // 0-6, 0 - Якшанба, 1 Душанба, ...
+ format24h: true,
+ pluralDay: 'Кунлар'
+ },
+ table: {
+ noData: 'Маълумот топилмади',
+ noResults: 'Қидирув бўйича маълумотлар топилмади',
+ loading: 'Юкланмоқда...',
+ selectedRecords: (rows) =>
+ (rows === 1
+ ? '1 та маълумот танланди.'
+ : (rows === 0 ? 'Хеч қандай' : rows) + ' маълумотла танланмади.'),
+ recordsPerPage: 'Сахифадаги қаторлар:',
+ allRows: 'Барчаси',
+ pagination: (start, end, total) => start + '-' + end + ' жами ' + total,
+ columns: 'Устунлар'
+ },
+ editor: {
+ url: 'УРЛ',
+ bold: 'Қалин',
+ italic: 'Курсив',
+ strikethrough: 'Чизилган',
+ underline: 'Тагига чизилган',
+ unorderedList: 'Тартибсиз руйхат',
+ orderedList: 'Тартибга киритилган руйхат',
+ subscript: 'Сатр остида',
+ superscript: 'Сатр устида',
+ hyperlink: 'Гиперхавола',
+ toggleFullscreen: 'Тўлиқ экран режимига ўтиш',
+ quote: 'Иқтибос',
+ left: 'Чапга сафлаш',
+ center: 'Марказга сафлаш',
+ right: 'Ўнгдан сафлаш',
+ justify: 'Икки томондан сафлаш',
+ print: 'Чоп этиш',
+ outdent: 'Чекинишни камайтириш',
+ indent: 'Чекинишни кўпайтириш',
+ removeFormat: 'Форматлашни ўчириб ташлаш',
+ formatting: 'Форматлаш',
+ fontSize: 'Шрифт хажми',
+ align: 'Сафлаш',
+ hr: 'Горизонтал қоидани киритиш',
+ undo: 'Бекор қилиш',
+ redo: 'Такрорлаш',
+ heading1: 'Сарлавха 1',
+ heading2: 'Сарлавха 2',
+ heading3: 'Сарлавха 3',
+ heading4: 'Сарлавха 4',
+ heading5: 'Сарлавха 5',
+ heading6: 'Сарлавха 6',
+ paragraph: 'Параграф',
+ code: 'Код',
+ size1: 'Ўта кичик',
+ size2: 'Бироз кичик',
+ size3: 'Оддий',
+ size4: 'Ўрта катта',
+ size5: 'Катта',
+ size6: 'Жуда катта',
+ size7: 'Максимал',
+ defaultFont: 'Стандарт шрифт',
+ viewSource: 'Манбани кўриш'
+ },
+ tree: {
+ noNodes: 'Кесишмалар мавжуд эмас',
+ noResults: 'Мос келадиган кесишмалар топилмади'
+ }
+}
diff --git a/ui/lang/uz-Latn.js b/ui/lang/uz-Latn.js
new file mode 100644
index 00000000000..4b695fdb2d9
--- /dev/null
+++ b/ui/lang/uz-Latn.js
@@ -0,0 +1,99 @@
+export default {
+ isoName: 'uz-Latn',
+ nativeName: 'O\'zbekcha (Lotin)',
+ label: {
+ clear: 'Tozalash',
+ ok: 'OK',
+ cancel: 'Bekor qilish',
+ close: 'Yopish',
+ set: 'O\'rnatish',
+ select: 'Tanlash',
+ reset: 'Qayta o\'rnatish',
+ remove: 'O\'chirish',
+ update: 'Yangilash',
+ create: 'Yaratish',
+ search: 'Qidirish',
+ filter: 'Filtrlash',
+ refresh: 'Yangilash',
+ expand: function (label) { return label ? `"${label}" ni kengaytirish` : 'Kengaytirish' },
+ collapse: function (label) { return label ? `"${label}" ni yig'ish` : 'Yiqilish' }
+ },
+ date: {
+ days: 'Yakshanba_Dushanba_Seshanba_Chorshanba_Payshanba_Juma_Shanba'.split(
+ '_'
+ ),
+ daysShort: 'Yak_Du_Se_Chor_Pay_Juma_Shanba'.split('_'),
+ months:
+ 'Yanvar_Fevral_Mart_Aprel_May_Iyun_Iyul_Avgust_Sentabr_Oktabr_Noyabr_Dekabr'.split(
+ '_'
+ ),
+ monthsShort: 'Yan_Fev_Mart_Apr_May_Iyun_Iyul_Avg_Sen_Okt_Noy_Dek'.split(
+ '_'
+ ),
+ firstDayOfWeek: 1, // 0-6, 0 - Yakshanba, 1 Dushanba, ...
+ format24h: true,
+ pluralDay: 'Kunlar'
+ },
+ table: {
+ noData: 'Ma\'lumotlar topilmadi',
+ noResults: 'Qidiruv bo\'yicha ma\'lumotlar topilmadi',
+ loading: 'Yuklanmoqda...',
+ selectedRecords: (rows) =>
+ (rows === 1
+ ? '1 ta malumot tanlandi.'
+ : (rows === 0 ? 'Hech qanday' : rows) + ' ma\'lumotlar tanlanmadi.'),
+ recordsPerPage: 'Saxifadagi qatorlar:',
+ allRows: 'Barchasi',
+ pagination: (start, end, total) => start + '-' + end + ' jami ' + total,
+ columns: 'Ustunlar'
+ },
+ editor: {
+ url: 'URL',
+ bold: 'Qalin',
+ italic: 'Kursiv',
+ strikethrough: 'Chizilgan',
+ underline: 'Tagiga chizilgan',
+ unorderedList: 'Tartibsiz ro\'yxat',
+ orderedList: 'Tartibga keltirilgan ro\'yxat',
+ subscript: 'Satr ostida',
+ superscript: 'Satr ustida',
+ hyperlink: 'Giperhavola',
+ toggleFullscreen: 'To\'liq ekran rejimiga o\'tish',
+ quote: 'Iqtibos',
+ left: 'Chapga saflash',
+ center: 'Markazga saflash',
+ right: 'O\'nggadan saflash',
+ justify: 'Ikki tomondan saflash',
+ print: 'Chop etish',
+ outdent: 'Chekinishni kamaytirish',
+ indent: 'Chekinishni ko\'paytirish',
+ removeFormat: 'Formatlashni o\'chirib tashlash',
+ formatting: 'Formatlash',
+ fontSize: 'Shrift hajmi',
+ align: 'Saflash',
+ hr: 'Gorizontal qoidani kiritish',
+ undo: 'Bekor qilish',
+ redo: 'Takrorlash',
+ heading1: 'Sarlavha 1',
+ heading2: 'Sarlavha 2',
+ heading3: 'Sarlavha 3',
+ heading4: 'Sarlavha 4',
+ heading5: 'Sarlavha 5',
+ heading6: 'Sarlavha 6',
+ paragraph: 'Paragraf',
+ code: 'Kod',
+ size1: 'Juda kichkik',
+ size2: 'Biroz kichik',
+ size3: 'Oddiy',
+ size4: 'O\'rta katta',
+ size5: 'Katta',
+ size6: 'Juda katta',
+ size7: 'Maksimal',
+ defaultFont: 'Standart shrift',
+ viewSource: 'Manbani ko\'rish'
+ },
+ tree: {
+ noNodes: 'Kesishmalar mavjud emas',
+ noResults: 'Mos keladigan kesishmalar topilmadi'
+ }
+}
diff --git a/ui/lang/vi.js b/ui/lang/vi.js
index b2df076bc8d..57aa85c9441 100644
--- a/ui/lang/vi.js
+++ b/ui/lang/vi.js
@@ -14,7 +14,9 @@ export default {
create: 'Tạo',
search: 'Tìm kiếm',
filter: 'Bộ lọc',
- refresh: 'Làm mới'
+ refresh: 'Làm mới',
+ expand: function (label) { return label ? `Mở rộng "${label}"` : 'Mở rộng' },
+ collapse: function (label) { return label ? `Thu gọn "${label}"` : 'Sụp đổ' }
},
date: {
days: 'Chủ Nhật_Thứ Hai_Thứ Ba_Thứ Tư_Thứ Năm_Thứ Sáu_Thứ Bảy'.split('_'),
diff --git a/ui/lang/zh-hans.js b/ui/lang/zh-hans.js
index d2c392deb33..c1aea368550 100644
--- a/ui/lang/zh-hans.js
+++ b/ui/lang/zh-hans.js
@@ -14,7 +14,9 @@ export default {
create: '创建',
search: '搜索',
filter: '过滤',
- refresh: '刷新'
+ refresh: '刷新',
+ expand: function (label) { return label ? `展开"${label}"` : '扩张' },
+ collapse: function (label) { return label ? `折叠"${label}"` : '坍塌' }
},
date: {
days: '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
@@ -22,7 +24,7 @@ export default {
months: '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
monthsShort: '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
headerTitle: function (date) {
- return new Intl.DateTimeFormat('zh-hans', {
+ return new Intl.DateTimeFormat('zh-CN', {
weekday: 'short', month: 'short', day: 'numeric'
}).format(date)
},
diff --git a/ui/lang/zh-hant.js b/ui/lang/zh-hant.js
index 04e159c5cc6..3af67dee3ce 100644
--- a/ui/lang/zh-hant.js
+++ b/ui/lang/zh-hant.js
@@ -1,6 +1,6 @@
export default {
isoName: 'zh-hant',
- nativeName: '中文(繁體)',
+ nativeName: '中文(繁體)',
label: {
clear: '清除',
ok: '確定',
@@ -14,7 +14,9 @@ export default {
create: '新增',
search: '搜尋',
filter: '篩選',
- refresh: '更新'
+ refresh: '更新',
+ expand: function (label) { return label ? `展開"${label}"` : '擴張' },
+ collapse: function (label) { return label ? `折疊"${label}"` : '坍塌' }
},
date: {
days: '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
@@ -22,27 +24,27 @@ export default {
months: '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
monthsShort: '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
headerTitle: function (date) {
- return new Intl.DateTimeFormat('zh-hant', {
+ return new Intl.DateTimeFormat('zh-TW', {
weekday: 'short', month: 'short', day: 'numeric'
}).format(date)
},
firstDayOfWeek: 0, // 0-6, 0 - Sunday, 1 Monday, ...
format24h: false,
- pluralDay: '天'
+ pluralDay: '日'
},
table: {
- noData: '無資料',
- noResults: '無相符資料',
+ noData: '沒有資料',
+ noResults: '沒有相符資料',
loading: '載入中...',
selectedRecords: function (rows) {
- return '已選擇' + rows + '筆'
+ return '已選擇 ' + rows + ' 列'
},
- recordsPerPage: '每頁筆數:',
+ recordsPerPage: '每頁列數:',
allRows: '全部',
pagination: function (start, end, total) {
- return start + '-' + end + ' / ' + total
+ return start + '-' + end + ' 列,共 ' + total + ' 列'
},
- columns: '列'
+ columns: '欄位'
},
editor: {
url: '網址',
@@ -56,19 +58,19 @@ export default {
superscript: '上標',
hyperlink: '超連結',
toggleFullscreen: '切換全螢幕',
- quote: '引言',
+ quote: '段落引用',
left: '靠左對齊',
center: '置中對齊',
right: '靠右對齊',
- justify: '左右對齊',
+ justify: '分散對齊',
print: '列印',
outdent: '減少縮排',
indent: '增加縮排',
removeFormat: '清除格式',
- formatting: '式樣',
+ formatting: '區塊元素',
fontSize: '字型大小',
align: '對齊',
- hr: '插入水平線',
+ hr: '水平分隔線',
undo: '復原',
redo: '取消復原',
heading1: '標題 1',
@@ -80,17 +82,17 @@ export default {
paragraph: '段落',
code: '程式碼',
size1: '非常小',
- size2: '比較小',
+ size2: '稍小',
size3: '正常',
- size4: '中等偏大',
+ size4: '稍大',
size5: '大',
size6: '非常大',
size7: '超級大',
defaultFont: '預設字型',
- viewSource: '查看資料'
+ viewSource: '切換原始碼'
},
tree: {
- noNodes: '無節點',
- noResults: '無相符節點'
+ noNodes: '沒有節點',
+ noResults: '沒有相符節點'
}
}
diff --git a/ui/package.json b/ui/package.json
index 6d127fb4c93..169ee83b195 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -1,6 +1,6 @@
{
"name": "quasar",
- "version": "1.15.21",
+ "version": "1.22.10",
"description": "Build high-performance VueJS user interfaces (SPA, PWA, SSR, Mobile and Desktop) in record time",
"module": "src/index.esm.js",
"typings": "dist/types/index.d.ts",
@@ -60,7 +60,7 @@
"homepage": "https://quasar.dev",
"devDependencies": {
"@quasar/app": "^2.0.6",
- "@quasar/extras": "^1.10.0",
+ "@quasar/extras": "^1.15.5",
"@rollup/plugin-buble": "^0.21.1",
"@rollup/plugin-json": "^4.0.2",
"@rollup/plugin-node-resolve": "^7.1.0",
diff --git a/ui/src/api.extends.json b/ui/src/api.extends.json
index b9ab0563fa5..b032ba68076 100644
--- a/ui/src/api.extends.json
+++ b/ui/src/api.extends.json
@@ -47,12 +47,12 @@
"icon": {
"type": "String",
- "desc": "Icon name following Quasar convention; Make sure you have the icon library installed unless you are using 'img:' prefix",
+ "desc": "Icon name following Quasar convention; Make sure you have the icon library installed unless you are using 'img:' prefix; If 'none' (String) is used as value then no icon is rendered (but screen real estate will still be used for it)",
"examples": [
"map",
"ion-add",
"img:https://cdn.quasar.dev/logo/svg/quasar-logo.svg",
- "img:statics/path/to/some_image.png"
+ "img:path/to/some_image.png"
],
"category": "content"
},
@@ -102,7 +102,6 @@
"sanitize": {
"type": "Boolean",
- "default": "false",
"desc": "Force use of textContent instead of innerHTML to render text; Use it when the text might be unsafe (from user input)",
"category": "behavior"
},
@@ -117,7 +116,7 @@
"scroll-target=\"body\""
],
"category": "behavior",
- "addedIn": "v1.8.0"
+ "addedIn": "v1.8"
}
},
diff --git a/ui/src/body.js b/ui/src/body.js
index b394c4ecdce..c024b4d800d 100644
--- a/ui/src/body.js
+++ b/ui/src/body.js
@@ -1,6 +1,6 @@
import { setBrand } from './utils/colors.js'
import { noop } from './utils/event.js'
-import { onKeyDownComposition } from './utils/key-composition.js'
+import { onKeyDownComposition } from './utils/private/key-composition.js'
import { isSSR, fromSSR, client, iosCorrection } from './plugins/Platform.js'
function getMobilePlatform (is) {
diff --git a/ui/src/components/ajax-bar/QAjaxBar.js b/ui/src/components/ajax-bar/QAjaxBar.js
index 29a9b74faa2..582b7f20424 100644
--- a/ui/src/components/ajax-bar/QAjaxBar.js
+++ b/ui/src/components/ajax-bar/QAjaxBar.js
@@ -6,22 +6,22 @@ import { ariaHidden } from '../../mixins/attrs'
const
xhr = isSSR ? null : XMLHttpRequest,
- send = isSSR ? null : xhr.prototype.send,
- stackStart = [],
- stackStop = []
+ open = isSSR ? null : xhr.prototype.open,
+ positionValues = [ 'top', 'right', 'bottom', 'left' ]
+let stack = []
let highjackCount = 0
function translate ({ p, pos, active, horiz, reverse, dir }) {
let x = 1, y = 1
- if (horiz) {
- if (reverse) { x = -1 }
+ if (horiz === true) {
+ if (reverse === true) { x = -1 }
if (pos === 'bottom') { y = -1 }
return { transform: `translate3d(${x * (p - 100)}%,${active ? 0 : y * -200}%,0)` }
}
- if (reverse) { y = -1 }
+ if (reverse === true) { y = -1 }
if (pos === 'right') { x = -1 }
return { transform: `translate3d(${active ? 0 : dir * x * -200}%,${y * (p - 100)}%,0)` }
}
@@ -47,32 +47,46 @@ function inc (p, amount) {
return between(p + amount, 0, 100)
}
-function highjackAjax (start, stop) {
- stackStart.push(start)
- stackStop.push(stop)
-
+function highjackAjax (stackEntry) {
highjackCount++
+ stack.push(stackEntry)
+
if (highjackCount > 1) { return }
- function endHandler () {
- stackStop.forEach(fn => { fn() })
- }
+ xhr.prototype.open = function (_, url) {
+ const stopStack = []
+
+ const loadStart = () => {
+ stack.forEach(entry => {
+ const hijackFilter = entry.getHijackFilter()
+ if (
+ hijackFilter === null ||
+ hijackFilter(url) === true
+ ) {
+ entry.start()
+ stopStack.push(entry.stop)
+ }
+ })
+ }
- xhr.prototype.send = function (/* ...args */) {
- stackStart.forEach(fn => { fn() })
- this.addEventListener('loadend', endHandler, false)
- send.apply(this, arguments)
+ const loadEnd = () => {
+ stopStack.forEach(stop => { stop() })
+ }
+
+ this.addEventListener('loadstart', loadStart, { once: true })
+ this.addEventListener('loadend', loadEnd, { once: true })
+
+ open.apply(this, arguments)
}
}
-function restoreAjax (start, stop) {
- stackStart.splice(stackStart.indexOf(start), 1)
- stackStop.splice(stackStop.indexOf(stop), 1)
+function restoreAjax (start) {
+ stack = stack.filter(entry => entry.start !== start)
highjackCount = Math.max(0, highjackCount - 1)
if (!highjackCount) {
- xhr.prototype.send = send
+ xhr.prototype.open = open
}
}
@@ -83,15 +97,19 @@ export default Vue.extend({
position: {
type: String,
default: 'top',
- validator: val => ['top', 'right', 'bottom', 'left'].includes(val)
+ validator: val => positionValues.includes(val)
},
+
size: {
type: String,
default: '2px'
},
+
color: String,
+ reverse: Boolean,
+
skipHijack: Boolean,
- reverse: Boolean
+ hijackFilter: Function
},
data () {
@@ -119,7 +137,7 @@ export default Vue.extend({
active,
horiz: this.horizontal,
reverse: this.$q.lang.rtl === true && ['top', 'bottom'].includes(this.position)
- ? !this.reverse
+ ? this.reverse === false
: this.reverse,
dir: this.$q.lang.rtl === true ? -1 : 1
})
@@ -153,18 +171,19 @@ export default Vue.extend({
methods: {
start (speed = 300) {
const oldSpeed = this.speed
- this.speed = Math.max(0, speed) || 0
+ const newSpeed = this.speed = Math.max(0, speed) || 0
this.calls++
if (this.calls > 1) {
- if (oldSpeed === 0 && speed > 0) {
+ if (oldSpeed === 0 && newSpeed > 0) {
this.__work()
}
- else if (oldSpeed > 0 && speed <= 0) {
+ else if (oldSpeed > 0 && newSpeed <= 0) {
clearTimeout(this.timer)
}
- return
+
+ return this.calls
}
clearTimeout(this.timer)
@@ -172,25 +191,33 @@ export default Vue.extend({
this.progress = 0
- if (this.onScreen === true) { return }
-
- this.onScreen = true
- this.animate = false
this.timer = setTimeout(() => {
this.animate = true
- speed > 0 && this.__work()
- }, 100)
+ newSpeed > 0 && this.__work()
+ }, this.onScreen === true ? 500 : 1)
+
+ if (this.onScreen !== true) {
+ this.onScreen = true
+ this.animate = false
+ }
+
+ return this.calls
},
increment (amount) {
if (this.calls > 0) {
this.progress = inc(this.progress, amount)
}
+
+ return this.calls
},
stop () {
this.calls = Math.max(0, this.calls - 1)
- if (this.calls > 0) { return }
+
+ if (this.calls > 0) {
+ return this.calls
+ }
clearTimeout(this.timer)
this.$emit('stop')
@@ -209,6 +236,8 @@ export default Vue.extend({
else {
end()
}
+
+ return this.calls
},
__work () {
@@ -224,13 +253,17 @@ export default Vue.extend({
mounted () {
if (this.skipHijack !== true) {
this.hijacked = true
- highjackAjax(this.start, this.stop)
+ highjackAjax({
+ start: this.start,
+ stop: this.stop,
+ getHijackFilter: () => this.hijackFilter || null
+ })
}
},
beforeDestroy () {
clearTimeout(this.timer)
- this.hijacked === true && restoreAjax(this.start, this.stop)
+ this.hijacked === true && restoreAjax(this.start)
},
render (h) {
diff --git a/ui/src/components/ajax-bar/QAjaxBar.json b/ui/src/components/ajax-bar/QAjaxBar.json
index 861304d9c85..f4c1de5ee8b 100644
--- a/ui/src/components/ajax-bar/QAjaxBar.json
+++ b/ui/src/components/ajax-bar/QAjaxBar.json
@@ -22,16 +22,34 @@
"extends": "color"
},
- "skip-hijack": {
+ "reverse": {
"type": "Boolean",
- "desc": "Skip Ajax hijacking (not a reactive prop)",
+ "desc": "Reverse direction of progress",
"category": "behavior"
},
- "reverse": {
+ "skip-hijack": {
"type": "Boolean",
- "desc": "Reverse direction of progress",
+ "desc": "Skip Ajax hijacking (not a reactive prop)",
"category": "behavior"
+ },
+
+ "hijack-filter": {
+ "type": "Function",
+ "desc": "Filter which URL should trigger start() + stop()",
+ "params": {
+ "url": {
+ "type": "String",
+ "desc": "The URL being triggered",
+ "examples": [ "https://some.url/path" ]
+ }
+ },
+ "returns": {
+ "type": "Boolean",
+ "desc": "Should the URL received as param trigger start() + stop()?"
+ },
+ "category": "behavior",
+ "addedIn": "v1.17.2"
}
},
@@ -55,6 +73,11 @@
"desc": "Delay (in milliseconds) between progress auto-increments; If delay is 0 then it disables auto-incrementing",
"examples": [ 400, 0 ]
}
+ },
+ "returns": {
+ "type": "Number",
+ "desc": "Number of active simultaneous sessions",
+ "__exemption": [ "examples" ]
}
},
@@ -66,11 +89,21 @@
"desc": "Amount (0 < x <= 100) to increment with",
"examples": [ 1 ]
}
+ },
+ "returns": {
+ "type": "Number",
+ "desc": "Number of active simultaneous sessions",
+ "__exemption": [ "examples" ]
}
},
"stop": {
- "desc": "Notify bar that one process you were waiting has finished"
+ "desc": "Notify bar that one process you were waiting has finished",
+ "returns": {
+ "type": "Number",
+ "desc": "Number of active simultaneous sessions",
+ "__exemption": [ "examples" ]
+ }
}
}
}
diff --git a/ui/src/components/avatar/QAvatar.js b/ui/src/components/avatar/QAvatar.js
index b6f2c0bbd96..551ab666bcb 100644
--- a/ui/src/components/avatar/QAvatar.js
+++ b/ui/src/components/avatar/QAvatar.js
@@ -5,7 +5,7 @@ import QIcon from '../icon/QIcon.js'
import SizeMixin from '../../mixins/size.js'
import ListenersMixin from '../../mixins/listeners.js'
-import { mergeSlotSafely } from '../../utils/slot.js'
+import { mergeSlotSafely } from '../../utils/private/slot.js'
export default Vue.extend({
name: 'QAvatar',
diff --git a/ui/src/components/badge/QBadge.js b/ui/src/components/badge/QBadge.js
index 9e989e5d5ad..bd523e5e456 100644
--- a/ui/src/components/badge/QBadge.js
+++ b/ui/src/components/badge/QBadge.js
@@ -2,7 +2,7 @@ import Vue from 'vue'
import ListenersMixin from '../../mixins/listeners.js'
-import { slot } from '../../utils/slot.js'
+import { slot } from '../../utils/private/slot.js'
export default Vue.extend({
name: 'QBadge',
@@ -53,7 +53,7 @@ export default Vue.extend({
attrs () {
return {
- role: 'alert',
+ role: 'status',
'aria-label': this.label
}
}
diff --git a/ui/src/components/banner/QBanner.js b/ui/src/components/banner/QBanner.js
index 34568906cd7..3f0b8066d02 100644
--- a/ui/src/components/banner/QBanner.js
+++ b/ui/src/components/banner/QBanner.js
@@ -3,7 +3,7 @@ import Vue from 'vue'
import DarkMixin from '../../mixins/dark.js'
import ListenersMixin from '../../mixins/listeners.js'
-import { slot } from '../../utils/slot.js'
+import { slot } from '../../utils/private/slot.js'
const attrs = { role: 'alert' }
diff --git a/ui/src/components/banner/QBanner.json b/ui/src/components/banner/QBanner.json
index eabd60f9ad9..0a84993641d 100644
--- a/ui/src/components/banner/QBanner.json
+++ b/ui/src/components/banner/QBanner.json
@@ -24,7 +24,7 @@
"dark": {
"extends": "dark",
- "addedIn": "v1.3.0"
+ "addedIn": "v1.3"
}
},
diff --git a/ui/src/components/bar/QBar.js b/ui/src/components/bar/QBar.js
index 7618e6990cf..475649ad861 100644
--- a/ui/src/components/bar/QBar.js
+++ b/ui/src/components/bar/QBar.js
@@ -3,7 +3,7 @@ import Vue from 'vue'
import DarkMixin from '../../mixins/dark.js'
import ListenersMixin from '../../mixins/listeners.js'
-import { slot } from '../../utils/slot.js'
+import { slot } from '../../utils/private/slot.js'
const attrs = { role: 'toolbar' }
diff --git a/ui/src/components/breadcrumbs/QBreadcrumbs.js b/ui/src/components/breadcrumbs/QBreadcrumbs.js
index e39bd5e982e..2559381084b 100644
--- a/ui/src/components/breadcrumbs/QBreadcrumbs.js
+++ b/ui/src/components/breadcrumbs/QBreadcrumbs.js
@@ -1,9 +1,11 @@
import Vue from 'vue'
import AlignMixin from '../../mixins/align.js'
-import { slot } from '../../utils/slot.js'
+import { slot } from '../../utils/private/slot.js'
import ListenersMixin from '../../mixins/listeners.js'
+const disabledValues = [ true, '' ]
+
export default Vue.extend({
name: 'QBreadcrumbs',
@@ -34,13 +36,13 @@ export default Vue.extend({
},
sepClass () {
- if (this.separatorColor) {
- return `text-${this.separatorColor}`
- }
+ return this.separatorColor
+ ? ` text-${this.separatorColor}`
+ : ''
},
activeClass () {
- return `text-${this.activeColor}`
+ return ` text-${this.activeColor}`
}
},
@@ -60,18 +62,20 @@ export default Vue.extend({
nodes.forEach(comp => {
if (comp.tag !== void 0 && comp.tag.endsWith('-QBreadcrumbsEl')) {
const middle = els < len
+ const disabled = disabledValues.includes(comp.componentOptions.propsData.disable)
+ const cls = middle === true
+ ? (disabled !== true ? this.activeClass : '')
+ : ' q-breadcrumbs--last'
+
els++
child.push(h('div', {
- staticClass: 'flex items-center',
- class: middle ? this.activeClass : 'q-breadcrumbs--last'
+ staticClass: 'flex items-center' + cls
}, [ comp ]))
- if (middle) {
- child.push(h('div', {
- staticClass: 'q-breadcrumbs__separator', class: this.sepClass
- }, separator()))
- }
+ middle === true && child.push(h('div', {
+ staticClass: 'q-breadcrumbs__separator' + this.sepClass
+ }, separator()))
}
else {
child.push(comp)
diff --git a/ui/src/components/breadcrumbs/QBreadcrumbs.sass b/ui/src/components/breadcrumbs/QBreadcrumbs.sass
index ca7b87c8a31..afb21e06ab8 100644
--- a/ui/src/components/breadcrumbs/QBreadcrumbs.sass
+++ b/ui/src/components/breadcrumbs/QBreadcrumbs.sass
@@ -9,8 +9,5 @@
&--with-label
margin-right: 8px
- &--last a
- pointer-events: none
-
[dir=rtl] .q-breadcrumbs__separator .q-icon
transform: scaleX(-1) #{"/* rtl:ignore */"}
diff --git a/ui/src/components/breadcrumbs/QBreadcrumbs.styl b/ui/src/components/breadcrumbs/QBreadcrumbs.styl
index f940db23524..f3a6d49c59d 100644
--- a/ui/src/components/breadcrumbs/QBreadcrumbs.styl
+++ b/ui/src/components/breadcrumbs/QBreadcrumbs.styl
@@ -9,8 +9,5 @@
&--with-label
margin-right: 8px
- &--last a
- pointer-events: none
-
[dir=rtl] .q-breadcrumbs__separator .q-icon
transform: scaleX(-1) /* rtl:ignore */
diff --git a/ui/src/components/breadcrumbs/QBreadcrumbsEl.js b/ui/src/components/breadcrumbs/QBreadcrumbsEl.js
index 4ad21ccd433..a8faaf66552 100644
--- a/ui/src/components/breadcrumbs/QBreadcrumbsEl.js
+++ b/ui/src/components/breadcrumbs/QBreadcrumbsEl.js
@@ -1,10 +1,10 @@
import Vue from 'vue'
-import { mergeSlot } from '../../utils/slot.js'
+import { mergeSlot } from '../../utils/private/slot.js'
import ListenersMixin from '../../mixins/listeners.js'
+import RouterLinkMixin from '../../mixins/router-link.js'
import QIcon from '../icon/QIcon.js'
-import { RouterLinkMixin } from '../../mixins/router-link.js'
export default Vue.extend({
name: 'QBreadcrumbsEl',
@@ -16,23 +16,42 @@ export default Vue.extend({
icon: String
},
+ computed: {
+ iconClass () {
+ return 'q-breadcrumbs__el-icon' +
+ (this.label !== void 0 ? ' q-breadcrumbs__el-icon--with-label' : '')
+ },
+
+ renderData () {
+ return {
+ staticClass: 'q-breadcrumbs__el q-link ' +
+ 'flex inline items-center relative-position ' +
+ (this.disable !== true ? 'q-link--focusable' + this.linkClass : 'q-breadcrumbs__el--disabled'),
+ attrs: this.linkAttrs,
+ on: {
+ ...this.qListeners,
+ click: this.__navigateOnClick
+ }
+ }
+ }
+ },
+
+ beforeCreate () {
+ this.fallbackTag = 'span'
+ },
+
render (h) {
const child = []
this.icon !== void 0 && child.push(
h(QIcon, {
- staticClass: 'q-breadcrumbs__el-icon',
- class: this.label !== void 0 ? 'q-breadcrumbs__el-icon--with-label' : null,
+ class: this.iconClass,
props: { name: this.icon }
})
)
- this.label && child.push(this.label)
+ this.label !== void 0 && child.push(this.label)
- return h(this.hasRouterLink === true ? 'router-link' : 'span', {
- staticClass: 'q-breadcrumbs__el q-link flex inline items-center relative-position',
- props: this.hasRouterLink === true ? this.routerLinkProps : null,
- [this.hasRouterLink === true ? 'nativeOn' : 'on']: { ...this.qListeners }
- }, mergeSlot(child, this, 'default'))
+ return h(this.linkTag, this.renderData, mergeSlot(child, this, 'default'))
}
})
diff --git a/ui/src/components/breadcrumbs/QBreadcrumbsEl.json b/ui/src/components/breadcrumbs/QBreadcrumbsEl.json
index 30a14b7250c..748d6201ae0 100644
--- a/ui/src/components/breadcrumbs/QBreadcrumbsEl.json
+++ b/ui/src/components/breadcrumbs/QBreadcrumbsEl.json
@@ -26,5 +26,61 @@
"default": {
"desc": "This is where custom content goes, unless 'icon' and 'label' props are not enough"
}
+ },
+
+ "events": {
+ "click": {
+ "desc": "Emitted when the component is clicked",
+ "params": {
+ "evt": {
+ "type": "Object",
+ "desc": "JS event object; If you are using route navigation ('to'/'replace'/'append' props) and you want to cancel navigation then call evt.preventDefault() synchronously in your event handler",
+ "required": true,
+ "__exemption": [ "examples" ]
+ },
+ "navigateFn": {
+ "type": "Function",
+ "desc": "Available ONLY if you are using route navigation ('to'/'replace'/'append' props); When you need to control the time at which the component should trigger the route navigation then call evt.preventDefault() synchronously and then call this function at your convenience; Useful if you have async work to be done before the actual route navigation or if you want to redirect somewhere else",
+ "addedIn": "v1.21",
+ "params": {
+ "opts": {
+ "type": "Object",
+ "desc": "Optional options",
+ "definition": {
+ "to": {
+ "type": [ "String", "Object" ],
+ "desc": "Equivalent to Vue Router
'to' property; Specify it explicitly otherwise it will be set with same value as component's 'to' prop",
+ "examples": [
+ "/home/dashboard",
+ "{ name: 'my-route-name' }"
+ ]
+ },
+
+ "replace": {
+ "type": "Boolean",
+ "desc": "Equivalent to Vue Router 'replace' property; Specify it explicitly otherwise it will be set with same value as component's 'replace' prop"
+ },
+
+ "append": {
+ "type": "Boolean",
+ "desc": "Equivalent to Vue Router 'append' property",
+ "default": "Tab's 'append' property"
+ },
+
+ "returnRouterError": {
+ "type": "Boolean",
+ "desc": "Return the router error, if any; Otherwise the returned Promise will always fulfill"
+ }
+ }
+ }
+ },
+ "returns": {
+ "type": "Promise",
+ "desc": "Returns the router's navigation promise",
+ "__exemption": [ "examples" ]
+ }
+ }
+ }
+ }
}
}
diff --git a/ui/src/components/btn-dropdown/QBtnDropdown.js b/ui/src/components/btn-dropdown/QBtnDropdown.js
index b5c50f562b1..65fbed78292 100644
--- a/ui/src/components/btn-dropdown/QBtnDropdown.js
+++ b/ui/src/components/btn-dropdown/QBtnDropdown.js
@@ -2,15 +2,24 @@ import Vue from 'vue'
import BtnMixin from '../../mixins/btn.js'
import AttrsMixin from '../../mixins/attrs.js'
+import TransitionMixin from '../../mixins/transition.js'
import QIcon from '../icon/QIcon.js'
import QBtn from '../btn/QBtn.js'
import QBtnGroup from '../btn-group/QBtnGroup.js'
import QMenu from '../menu/QMenu.js'
-import { slot } from '../../utils/slot.js'
+import { slot } from '../../utils/private/slot.js'
import { stop } from '../../utils/event.js'
-import cache from '../../utils/cache.js'
+import cache from '../../utils/private/cache.js'
+import uid from '../../utils/uid.js'
+
+// let's not duplicate type checking and prop validations
+// so just specify the props here with no type description
+const menuTransitionProps = Object.keys(TransitionMixin.props).reduce(
+ (acc, key) => (acc[ key ] = {}) && acc,
+ {}
+)
export default Vue.extend({
name: 'QBtnDropdown',
@@ -41,11 +50,14 @@ export default Vue.extend({
default: 'top end'
},
menuOffset: Array,
+ ...menuTransitionProps,
disableMainBtn: Boolean,
disableDropdown: Boolean,
- noIconAnimation: Boolean
+ noIconAnimation: Boolean,
+
+ toggleAriaLabel: String
},
data () {
@@ -68,7 +80,9 @@ export default Vue.extend({
const label = slot(this, 'label', [])
const attrs = {
'aria-expanded': this.showing === true ? 'true' : 'false',
- 'aria-haspopup': 'true'
+ 'aria-haspopup': 'true',
+ 'aria-controls': this.targetUid,
+ 'aria-label': this.toggleAriaLabel || this.$q.lang.label[ this.showing === true ? 'collapse' : 'expand' ](this.label)
}
if (
@@ -93,6 +107,9 @@ export default Vue.extend({
this.disableDropdown !== true && Arrow.push(
h(QMenu, {
ref: 'menu',
+ attrs: {
+ id: this.targetUid
+ },
props: {
cover: this.cover,
fit: true,
@@ -104,7 +121,9 @@ export default Vue.extend({
offset: this.menuOffset,
contentClass: this.contentClass,
contentStyle: this.contentStyle,
- separateClosePopup: true
+ separateClosePopup: true,
+ transitionShow: this.transitionShow,
+ transitionHide: this.transitionHide
},
on: cache(this, 'menu', {
'before-show': e => {
@@ -137,14 +156,17 @@ export default Vue.extend({
round: false
},
attrs: {
- ...this.qAttrs,
- ...attrs
+ ...attrs,
+ ...this.qAttrs
},
on: cache(this, 'nonSpl', {
click: e => {
this.$emit('click', e)
}
- })
+ }),
+ scopedSlots: {
+ loading: this.$scopedSlots.loading
+ }
}, label.concat(Arrow))
}
@@ -164,7 +186,10 @@ export default Vue.extend({
this.hide()
this.$emit('click', e)
}
- })
+ }),
+ scopedSlots: {
+ loading: this.$scopedSlots.loading
+ }
}, label)
return h(QBtnGroup, {
@@ -172,6 +197,7 @@ export default Vue.extend({
outline: this.outline,
flat: this.flat,
rounded: this.rounded,
+ square: this.square,
push: this.push,
unelevated: this.unelevated,
glossy: this.glossy,
@@ -214,6 +240,10 @@ export default Vue.extend({
}
},
+ created () {
+ this.targetUid = `d_${uid()}`
+ },
+
mounted () {
this.value === true && this.show()
}
diff --git a/ui/src/components/btn-dropdown/QBtnDropdown.json b/ui/src/components/btn-dropdown/QBtnDropdown.json
index e9ad3d1f4de..711296dc355 100644
--- a/ui/src/components/btn-dropdown/QBtnDropdown.json
+++ b/ui/src/components/btn-dropdown/QBtnDropdown.json
@@ -39,7 +39,7 @@
"type": "Boolean",
"desc": "Disables the rotation of the dropdown icon when state is toggled",
"category": "style",
- "addedIn": "v1.12.0"
+ "addedIn": "v1.12"
},
"content-style": {
@@ -119,6 +119,28 @@
"examples": [ "[8, 8]", "[5, 10]" ],
"category": "position",
"addedIn": "v1.9.2"
+ },
+
+ "transition-show": {
+ "extends": "transition",
+ "default": "fade",
+ "category": "behavior",
+ "addedIn": "v1.22"
+ },
+
+ "transition-hide": {
+ "extends": "transition",
+ "default": "fade",
+ "category": "behavior",
+ "addedIn": "v1.22"
+ },
+
+ "toggle-aria-label": {
+ "type": "String",
+ "desc": "aria-label to be used on the dropdown toggle element",
+ "examples": [ "Open menu" ],
+ "category": "accessibility",
+ "addedIn": "v1.20.2"
}
},
@@ -129,6 +151,11 @@
"label": {
"desc": "Customize main button's content through this slot, unless you're using the 'icon' and 'label' props"
+ },
+
+ "loading": {
+ "desc": "Override the default QSpinner when in 'loading' state",
+ "addedIn": "v1.19.6"
}
},
diff --git a/ui/src/components/btn-dropdown/QBtnDropdown.sass b/ui/src/components/btn-dropdown/QBtnDropdown.sass
index 6d5c125a139..04e7925cb03 100644
--- a/ui/src/components/btn-dropdown/QBtnDropdown.sass
+++ b/ui/src/components/btn-dropdown/QBtnDropdown.sass
@@ -1,5 +1,7 @@
.q-btn-dropdown
&--split .q-btn-dropdown__arrow-container
+ &.q-btn--outline
+ border-left: 1px solid currentColor
&:not(.q-btn--outline)
border-left: 1px solid rgba(255,255,255,.3)
diff --git a/ui/src/components/btn-dropdown/QBtnDropdown.styl b/ui/src/components/btn-dropdown/QBtnDropdown.styl
index 6d5c125a139..04e7925cb03 100644
--- a/ui/src/components/btn-dropdown/QBtnDropdown.styl
+++ b/ui/src/components/btn-dropdown/QBtnDropdown.styl
@@ -1,5 +1,7 @@
.q-btn-dropdown
&--split .q-btn-dropdown__arrow-container
+ &.q-btn--outline
+ border-left: 1px solid currentColor
&:not(.q-btn--outline)
border-left: 1px solid rgba(255,255,255,.3)
diff --git a/ui/src/components/btn-group/QBtnGroup.js b/ui/src/components/btn-group/QBtnGroup.js
index 03f41f7606d..4f69acee3e2 100644
--- a/ui/src/components/btn-group/QBtnGroup.js
+++ b/ui/src/components/btn-group/QBtnGroup.js
@@ -2,7 +2,7 @@ import Vue from 'vue'
import ListenersMixin from '../../mixins/listeners.js'
-import { slot } from '../../utils/slot.js'
+import { slot } from '../../utils/private/slot.js'
export default Vue.extend({
name: 'QBtnGroup',
@@ -14,6 +14,7 @@ export default Vue.extend({
outline: Boolean,
flat: Boolean,
rounded: Boolean,
+ square: Boolean,
push: Boolean,
stretch: Boolean,
glossy: Boolean,
@@ -22,7 +23,7 @@ export default Vue.extend({
computed: {
classes () {
- return ['unelevated', 'outline', 'flat', 'rounded', 'push', 'stretch', 'glossy']
+ return ['unelevated', 'outline', 'flat', 'rounded', 'square', 'push', 'stretch', 'glossy']
.filter(t => this[t] === true)
.map(t => `q-btn-group--${t}`).join(' ')
}
diff --git a/ui/src/components/btn-group/QBtnGroup.json b/ui/src/components/btn-group/QBtnGroup.json
index 3233582c0cd..6d883aa4452 100644
--- a/ui/src/components/btn-group/QBtnGroup.json
+++ b/ui/src/components/btn-group/QBtnGroup.json
@@ -38,6 +38,11 @@
"category": "style"
},
+ "square": {
+ "extends": "square",
+ "addedIn": "v1.22"
+ },
+
"push": {
"type": "Boolean",
"desc": "Use 'push' design for buttons",
diff --git a/ui/src/components/btn-group/QBtnGroup.sass b/ui/src/components/btn-group/QBtnGroup.sass
index e0b7c948e92..0c4ca9db9bb 100644
--- a/ui/src/components/btn-group/QBtnGroup.sass
+++ b/ui/src/components/btn-group/QBtnGroup.sass
@@ -57,6 +57,9 @@
&--rounded
border-radius: $button-rounded-border-radius
+ &--square
+ border-radius: 0
+
&--flat, &--outline, &--unelevated
box-shadow: none
diff --git a/ui/src/components/btn-group/QBtnGroup.styl b/ui/src/components/btn-group/QBtnGroup.styl
index e0b7c948e92..0c4ca9db9bb 100644
--- a/ui/src/components/btn-group/QBtnGroup.styl
+++ b/ui/src/components/btn-group/QBtnGroup.styl
@@ -57,6 +57,9 @@
&--rounded
border-radius: $button-rounded-border-radius
+ &--square
+ border-radius: 0
+
&--flat, &--outline, &--unelevated
box-shadow: none
diff --git a/ui/src/components/btn-toggle/QBtnToggle.js b/ui/src/components/btn-toggle/QBtnToggle.js
index f84f9359ca5..f34abbb5e50 100644
--- a/ui/src/components/btn-toggle/QBtnToggle.js
+++ b/ui/src/components/btn-toggle/QBtnToggle.js
@@ -7,7 +7,7 @@ import ListenersMixin from '../../mixins/listeners.js'
import FormMixin from '../../mixins/form.js'
import RippleMixin from '../../mixins/ripple.js'
-import { slot, mergeSlot } from '../../utils/slot.js'
+import { slot, mergeSlot } from '../../utils/private/slot.js'
export default Vue.extend({
name: 'QBtnToggle',
@@ -87,7 +87,10 @@ export default Vue.extend({
...this.qListeners,
click: e => this.__set(opt.value, opt, e)
},
- attrs: opt.attrs,
+ attrs: {
+ 'aria-pressed': opt.value === this.value ? 'true' : 'false',
+ ...opt.attrs
+ },
props: {
...opt,
slot: void 0,
diff --git a/ui/src/components/btn-toggle/QBtnToggle.json b/ui/src/components/btn-toggle/QBtnToggle.json
index 5dd8567addb..912e7039677 100644
--- a/ui/src/components/btn-toggle/QBtnToggle.json
+++ b/ui/src/components/btn-toggle/QBtnToggle.json
@@ -27,7 +27,7 @@
"desc": "Key-value for attributes to be set on the button",
"examples": [ "{ 'aria-label': 'Button label' }" ],
"__exemption": [ "definition" ],
- "addedIn": "v1.13.0"
+ "addedIn": "v1.13"
},
"label": {
"type": "String",
@@ -132,7 +132,7 @@
"desc": "Apply custom padding (vertical [horizontal]); Size in CSS units, including unit name or standard size name (none|xs|sm|md|lg|xl); Also removes the min width and height when set",
"examples": [ "16px", "10px 5px", "2rem", "xs", "md lg", "2px 2px 5px 7px" ],
"category": "style",
- "addedIn": "v1.13.0"
+ "addedIn": "v1.13"
},
"no-caps": {
diff --git a/ui/src/components/btn/QBtn.js b/ui/src/components/btn/QBtn.js
index e1f249e9793..84a8b2303dc 100644
--- a/ui/src/components/btn/QBtn.js
+++ b/ui/src/components/btn/QBtn.js
@@ -5,9 +5,9 @@ import QSpinner from '../spinner/QSpinner.js'
import BtnMixin from '../../mixins/btn.js'
-import { mergeSlot } from '../../utils/slot.js'
-import { stop, prevent, stopAndPrevent, listenOpts, noop } from '../../utils/event.js'
-import { isKeyCode } from '../../utils/key-composition.js'
+import { mergeSlot } from '../../utils/private/slot.js'
+import { stop, prevent, stopAndPrevent, listenOpts } from '../../utils/event.js'
+import { isKeyCode } from '../../utils/private/key-composition.js'
const { passiveCapture } = listenOpts
@@ -37,7 +37,7 @@ export default Vue.extend({
return this.ripple === false
? false
: {
- keyCodes: this.isLink === true ? [ 13, 32 ] : [ 13 ],
+ keyCodes: this.hasLink === true ? [ 13, 32 ] : [ 13 ],
...(this.ripple === true ? {} : this.ripple)
}
},
@@ -69,7 +69,7 @@ export default Vue.extend({
}
if (this.$q.platform.has.touch === true) {
- on.touchstart = this.__onTouchstart
+ on[ `${on.touchstart === void 0 ? '&' : ''}touchstart` ] = this.__onTouchstart
}
return on
@@ -126,61 +126,45 @@ export default Vue.extend({
document.addEventListener('keyup', onClickCleanup, passiveCapture)
this.$el.addEventListener('blur', onClickCleanup, passiveCapture)
}
-
- if (this.hasRouterLink === true) {
- if (
- e.ctrlKey === true ||
- e.shiftKey === true ||
- e.altKey === true ||
- e.metaKey === true
- ) {
- // if it has meta keys, let vue-router link
- // handle this by its own
- return
- }
-
- stopAndPrevent(e)
- }
}
- const go = () => {
- // vue-router now throwing error if navigating
- // to the same route that the user is currently at
- // https://github.com/vuejs/vue-router/issues/2872
- this.$router[this.replace === true ? 'replace' : 'push'](this.currentLocation.route, void 0, noop)
- }
-
- this.$emit('click', e, go)
- this.hasRouterLink === true && e.navigate !== false && go()
+ this.__navigateOnClick(e)
},
__onKeydown (e) {
- if (isKeyCode(e, [ 13, 32 ]) === true) {
- stopAndPrevent(e)
+ this.$emit('keydown', e)
+ if (isKeyCode(e, [ 13, 32 ]) === true) {
if (keyboardTarget !== this.$el) {
keyboardTarget !== void 0 && this.__cleanup()
- // focus external button if the focus helper was focused before
- this.$el.focus()
+ if (e.defaultPrevented !== true) {
+ // focus external button if the focus helper was focused before
+ this.$el.focus()
- keyboardTarget = this.$el
- this.$el.classList.add('q-btn--active')
- document.addEventListener('keyup', this.__onPressEnd, true)
- this.$el.addEventListener('blur', this.__onPressEnd, passiveCapture)
+ keyboardTarget = this.$el
+ this.$el.classList.add('q-btn--active')
+ document.addEventListener('keyup', this.__onPressEnd, true)
+ this.$el.addEventListener('blur', this.__onPressEnd, passiveCapture)
+ }
}
- }
- this.$emit('keydown', e)
+ stopAndPrevent(e)
+ }
},
__onTouchstart (e) {
+ this.$emit('touchstart', e)
+
if (touchTarget !== this.$el) {
touchTarget !== void 0 && this.__cleanup()
- touchTarget = this.$el
- const target = this.touchTargetEl = e.target
- target.addEventListener('touchcancel', this.__onPressEnd, passiveCapture)
- target.addEventListener('touchend', this.__onPressEnd, passiveCapture)
+
+ if (e.defaultPrevented !== true) {
+ touchTarget = this.$el
+ const target = this.touchTargetEl = e.target
+ target.addEventListener('touchcancel', this.__onPressEnd, passiveCapture)
+ target.addEventListener('touchend', this.__onPressEnd, passiveCapture)
+ }
}
// avoid duplicated mousedown event
@@ -190,20 +174,21 @@ export default Vue.extend({
this.mouseTimer = setTimeout(() => {
this.avoidMouseRipple = false
}, 200)
-
- this.$emit('touchstart', e)
},
__onMousedown (e) {
+ e.qSkipRipple = this.avoidMouseRipple === true
+ this.$emit('mousedown', e)
+
if (mouseTarget !== this.$el) {
mouseTarget !== void 0 && this.__cleanup()
- mouseTarget = this.$el
- this.$el.classList.add('q-btn--active')
- document.addEventListener('mouseup', this.__onPressEnd, passiveCapture)
- }
- e.qSkipRipple = this.avoidMouseRipple === true
- this.$emit('mousedown', e)
+ if (e.defaultPrevented !== true) {
+ mouseTarget = this.$el
+ this.$el.classList.add('q-btn--active')
+ document.addEventListener('mouseup', this.__onPressEnd, passiveCapture)
+ }
+ }
},
__onPressEnd (e) {
@@ -240,7 +225,8 @@ export default Vue.extend({
destroying !== true &&
(touchTarget === this.$el || mouseTarget === this.$el) &&
blurTarget !== void 0 &&
- blurTarget !== document.activeElement
+ blurTarget !== document.activeElement &&
+ this.$el.contains(document.activeElement) === true
) {
blurTarget.setAttribute('tabindex', -1)
blurTarget.focus()
@@ -312,11 +298,11 @@ export default Vue.extend({
if (this.loading === true && this.percentage !== void 0) {
child.push(
h('span', {
- staticClass: 'q-btn__progress absolute-full overflow-hidden'
+ staticClass: 'q-btn__progress absolute-full overflow-hidden',
+ class: this.darkPercentage === true ? 'q-btn__progress--dark' : ''
}, [
h('span', {
staticClass: 'q-btn__progress-indicator fit block',
- class: this.darkPercentage === true ? 'q-btn__progress--dark' : '',
style: this.percentageStyle
})
])
@@ -346,7 +332,7 @@ export default Vue.extend({
] : void 0)
)
- return h(this.isLink === true ? 'a' : 'button', {
+ return h(this.hasLink === true || this.type === 'a' ? 'a' : 'button', {
staticClass: 'q-btn q-btn-item non-selectable no-outline',
class: this.classes,
style: this.style,
diff --git a/ui/src/components/btn/QBtn.json b/ui/src/components/btn/QBtn.json
index d3c9b723aae..332dfd5fdd0 100644
--- a/ui/src/components/btn/QBtn.json
+++ b/ui/src/components/btn/QBtn.json
@@ -55,18 +55,56 @@
"events": {
"click": {
- "desc": "Emitted when component is clicked (activated)",
+ "desc": "Emitted when the component is clicked",
"params": {
"evt": {
"type": "Object",
- "desc": "JS event object; If you want to cancel navigation set synchronously 'evt.navigate' to false",
+ "desc": "JS event object; If you are using route navigation ('to'/'replace'/'append' props) and you want to cancel navigation then call evt.preventDefault() synchronously in your event handler",
+ "required": true,
"__exemption": [ "examples" ]
},
"navigateFn": {
"type": "Function",
- "desc": "When you need to control the time at which the button should trigger the route navigation then set 'evt.navigate' to false and call this function; Useful if you have async work to be done before the actual route navigation",
- "params": null,
- "returns": null
+ "desc": "Available ONLY if you are using route navigation ('to'/'replace'/'append' props); When you need to control the time at which the component should trigger the route navigation then call evt.preventDefault() synchronously and then call this function at your convenience; Useful if you have async work to be done before the actual route navigation or if you want to redirect somewhere else",
+ "params": {
+ "opts": {
+ "type": "Object",
+ "desc": "Optional options",
+ "addedIn": "v1.21",
+ "definition": {
+ "to": {
+ "type": [ "String", "Object" ],
+ "desc": "Equivalent to Vue Router 'to' property; Specify it explicitly otherwise it will be set with same value as component's 'to' prop",
+ "examples": [
+ "/home/dashboard",
+ "{ name: 'my-route-name' }"
+ ]
+ },
+
+ "replace": {
+ "type": "Boolean",
+ "desc": "Equivalent to Vue Router 'replace' property; Specify it explicitly otherwise it will be set with same value as component's 'replace' prop"
+ },
+
+ "append": {
+ "type": "Boolean",
+ "desc": "Equivalent to Vue Router 'append' property",
+ "default": "Tab's 'append' property"
+ },
+
+ "returnRouterError": {
+ "type": "Boolean",
+ "desc": "Return the router error, if any; Otherwise the returned Promise will always fulfill"
+ }
+ }
+ }
+ },
+ "returns": {
+ "type": "Promise",
+ "desc": "Returns the router's navigation promise",
+ "__exemption": [ "examples" ],
+ "addedIn": "v1.21"
+ }
}
}
}
diff --git a/ui/src/components/card/QCard.js b/ui/src/components/card/QCard.js
index 7095fc325e3..8f413a0539a 100644
--- a/ui/src/components/card/QCard.js
+++ b/ui/src/components/card/QCard.js
@@ -4,7 +4,7 @@ import DarkMixin from '../../mixins/dark.js'
import TagMixin from '../../mixins/tag.js'
import ListenersMixin from '../../mixins/listeners.js'
-import { slot } from '../../utils/slot.js'
+import { slot } from '../../utils/private/slot.js'
export default Vue.extend({
name: 'QCard',
diff --git a/ui/src/components/card/QCard.sass b/ui/src/components/card/QCard.sass
index 70096551eca..e4111cc8b0d 100644
--- a/ui/src/components/card/QCard.sass
+++ b/ui/src/components/card/QCard.sass
@@ -69,7 +69,7 @@
padding: 8px
align-items: center
- .q-btn__wrapper
+ .q-btn--rectangle .q-btn__wrapper
padding: 0 8px
&--horiz
diff --git a/ui/src/components/card/QCard.styl b/ui/src/components/card/QCard.styl
index 70096551eca..e4111cc8b0d 100644
--- a/ui/src/components/card/QCard.styl
+++ b/ui/src/components/card/QCard.styl
@@ -69,7 +69,7 @@
padding: 8px
align-items: center
- .q-btn__wrapper
+ .q-btn--rectangle .q-btn__wrapper
padding: 0 8px
&--horiz
diff --git a/ui/src/components/card/QCardActions.js b/ui/src/components/card/QCardActions.js
index 975265bbf42..53c23e8e445 100644
--- a/ui/src/components/card/QCardActions.js
+++ b/ui/src/components/card/QCardActions.js
@@ -3,7 +3,7 @@ import Vue from 'vue'
import AlignMixin from '../../mixins/align.js'
import ListenersMixin from '../../mixins/listeners.js'
-import { slot } from '../../utils/slot.js'
+import { slot } from '../../utils/private/slot.js'
export default Vue.extend({
name: 'QCardActions',
diff --git a/ui/src/components/card/QCardSection.js b/ui/src/components/card/QCardSection.js
index 8b98a14949e..1e6a245e32d 100644
--- a/ui/src/components/card/QCardSection.js
+++ b/ui/src/components/card/QCardSection.js
@@ -3,7 +3,7 @@ import Vue from 'vue'
import TagMixin from '../../mixins/tag.js'
import ListenersMixin from '../../mixins/listeners.js'
-import { slot } from '../../utils/slot.js'
+import { slot } from '../../utils/private/slot.js'
export default Vue.extend({
name: 'QCardSection',
diff --git a/ui/src/components/card/QCardSection.json b/ui/src/components/card/QCardSection.json
index e45b052e420..629420a3703 100644
--- a/ui/src/components/card/QCardSection.json
+++ b/ui/src/components/card/QCardSection.json
@@ -14,7 +14,7 @@
"type": "Boolean",
"desc": "Display a horizontal section (will have no padding and can contain other QCardSection)",
"category": "content",
- "addedIn": "v1.7.0"
+ "addedIn": "v1.7"
},
"tag": {
diff --git a/ui/src/components/carousel/QCarousel.js b/ui/src/components/carousel/QCarousel.js
index f1224410a04..cf81c0ffb16 100644
--- a/ui/src/components/carousel/QCarousel.js
+++ b/ui/src/components/carousel/QCarousel.js
@@ -7,8 +7,8 @@ import { PanelParentMixin } from '../../mixins/panel.js'
import FullscreenMixin from '../../mixins/fullscreen.js'
import { isNumber } from '../../utils/is.js'
-import { mergeSlot } from '../../utils/slot.js'
-import cache from '../../utils/cache.js'
+import { mergeSlot } from '../../utils/private/slot.js'
+import cache from '../../utils/private/cache.js'
export default Vue.extend({
name: 'QCarousel',
@@ -99,11 +99,11 @@ export default Vue.extend({
},
transitionPrevComputed () {
- return this.transitionPrev || `fade`
+ return this.transitionPrev || 'fade'
},
transitionNextComputed () {
- return this.transitionNext || `fade`
+ return this.transitionNext || 'fade'
}
},
@@ -127,9 +127,13 @@ export default Vue.extend({
methods: {
__startTimer () {
+ const duration = isNumber(this.autoplay) === true
+ ? this.autoplay
+ : 5000
+
this.timer = setTimeout(
- this.next,
- isNumber(this.autoplay) ? this.autoplay : 5000
+ duration >= 0 ? this.next : this.previous,
+ Math.abs(duration)
)
},
diff --git a/ui/src/components/carousel/QCarousel.json b/ui/src/components/carousel/QCarousel.json
index c71aafe31e0..16f73db65d3 100644
--- a/ui/src/components/carousel/QCarousel.json
+++ b/ui/src/components/carousel/QCarousel.json
@@ -12,7 +12,7 @@
"props": {
"dark": {
"extends": "dark",
- "addedIn": "v1.3.0"
+ "addedIn": "v1.3"
},
"height": {
@@ -34,7 +34,7 @@
"control-text-color": {
"extends": "color",
"desc": "Color name for text color of QCarousel button controls (arrows, navigation) from the Quasar Color Palette",
- "addedIn": "v1.9.0"
+ "addedIn": "v1.9"
},
"control-type": {
@@ -42,12 +42,12 @@
"desc": "Type of button to use for controls (arrows, navigation)",
"values": [ "regular", "flat", "outline", "push", "unelevated" ],
"category": "style",
- "addedIn": "v1.9.0"
+ "addedIn": "v1.9"
},
"autoplay": {
"type": [ "Number", "Boolean" ],
- "desc": "Jump to next slide at fixed time intervals (in milliseconds); 'false' disables autoplay, 'true' enables it for 5000ms intervals",
+ "desc": "Jump to next slide (if 'true' or val > 0) or previous slide (if val < 0) at fixed time intervals (in milliseconds); 'false' disables autoplay, 'true' enables it for 5000ms intervals",
"default": false,
"examples": [
":autoplay=\"2500\"",
@@ -84,7 +84,7 @@
"values": [ "top", "right", "bottom", "left" ],
"examples": [ "left" ],
"category": "content",
- "addedIn": "v1.9.0"
+ "addedIn": "v1.9"
},
"navigation-icon": {
@@ -101,6 +101,14 @@
"type": "Boolean",
"desc": "Show thumbnails",
"category": "content"
+ },
+
+ "transition-prev": {
+ "default": "fade"
+ },
+
+ "transition-next": {
+ "default": "fade"
}
},
diff --git a/ui/src/components/carousel/QCarouselControl.js b/ui/src/components/carousel/QCarouselControl.js
index ddd7b843d03..2311e37f69c 100644
--- a/ui/src/components/carousel/QCarouselControl.js
+++ b/ui/src/components/carousel/QCarouselControl.js
@@ -2,7 +2,7 @@ import Vue from 'vue'
import ListenersMixin from '../../mixins/listeners.js'
-import { slot } from '../../utils/slot.js'
+import { slot } from '../../utils/private/slot.js'
export default Vue.extend({
name: 'QCarouselControl',
diff --git a/ui/src/components/carousel/QCarouselSlide.js b/ui/src/components/carousel/QCarouselSlide.js
index 0aa2e6fd6b6..085caca40ea 100644
--- a/ui/src/components/carousel/QCarouselSlide.js
+++ b/ui/src/components/carousel/QCarouselSlide.js
@@ -2,7 +2,7 @@ import Vue from 'vue'
import { PanelChildMixin } from '../../mixins/panel.js'
-import { slot } from '../../utils/slot.js'
+import { slot } from '../../utils/private/slot.js'
export default Vue.extend({
name: 'QCarouselSlide',
diff --git a/ui/src/components/carousel/QCarouselSlide.json b/ui/src/components/carousel/QCarouselSlide.json
index 5833a674f7e..4aba4d25d00 100644
--- a/ui/src/components/carousel/QCarouselSlide.json
+++ b/ui/src/components/carousel/QCarouselSlide.json
@@ -20,13 +20,13 @@
"img-src": {
"type": "String",
- "desc": "URL pointing to a slide background image (use statics folder)",
+ "desc": "URL pointing to a slide background image (use public folder)",
"transformAssetUrls": true,
"examples": [
- "(statics folder) src=\"statics/img/my-bg.png\"",
+ "(public folder) src=\"img/my-bg.png\"",
"(assets folder) src=\"~assets/my-img.png\"",
"(relative path format) :src=\"require('./my_img.jpg')\"",
- "(URL) src=\"https://placeimg.com/500/300/nature\""
+ "(URL) src=\"https://picsum.photos/500/300\""
],
"category": "model"
}
diff --git a/ui/src/components/chat/QChatMessage.js b/ui/src/components/chat/QChatMessage.js
index d36b56c0f62..e3b82409fd5 100644
--- a/ui/src/components/chat/QChatMessage.js
+++ b/ui/src/components/chat/QChatMessage.js
@@ -35,7 +35,7 @@ export default Vue.extend({
},
containerClass () {
- return `q-message-container row items-end no-wrap` +
+ return 'q-message-container row items-end no-wrap' +
(this.sent === true ? ' reverse' : '')
},
@@ -85,9 +85,9 @@ export default Vue.extend({
]
}
- const content = withSlots === true
- ? (contentList.length > 1 ? text => text : text => h('div', [ text ]))
- : text => h('div', { domProps: { [domPropText]: text } })
+ const content = withSlots !== true
+ ? text => h('div', { domProps: { [domPropText]: text } })
+ : (contentList.length > 1 ? text => text : text => h('div', [text]))
return contentList.map((msg, index) => h('div', {
key: index,
diff --git a/ui/src/components/chat/QChatMessage.json b/ui/src/components/chat/QChatMessage.json
index d3d7108d90d..5cb00804cf4 100644
--- a/ui/src/components/chat/QChatMessage.json
+++ b/ui/src/components/chat/QChatMessage.json
@@ -45,10 +45,10 @@
"desc": "URL to the avatar image of the author",
"transformAssetUrls": true,
"examples": [
- "(statics folder) src=\"statics/boy-avatar.png\"",
+ "(public folder) src=\"boy-avatar.png\"",
"(assets folder) src=\"~assets/boy-avatar.png\"",
"(relative path format) :src=\"require('./my_img.jpg')\"",
- "(URL) src=\"https://placeimg.com/500/300/nature\""
+ "(URL) src=\"https://picsum.photos/500/300\""
],
"category": "content"
},
diff --git a/ui/src/components/checkbox/QCheckbox.js b/ui/src/components/checkbox/QCheckbox.js
index 1bfcf9855e9..4e170720abd 100644
--- a/ui/src/components/checkbox/QCheckbox.js
+++ b/ui/src/components/checkbox/QCheckbox.js
@@ -1,5 +1,7 @@
import Vue from 'vue'
+import QIcon from '../icon/QIcon.js'
+
import CheckboxMixin from '../../mixins/checkbox.js'
export default Vue.extend({
@@ -7,33 +9,57 @@ export default Vue.extend({
mixins: [ CheckboxMixin ],
+ computed: {
+ computedIcon () {
+ return this.isTrue === true
+ ? this.checkedIcon
+ : (this.isIndeterminate === true
+ ? this.indeterminateIcon
+ : this.uncheckedIcon
+ )
+ }
+ },
+
methods: {
__getInner (h) {
- return [
- h('div', {
- staticClass: 'q-checkbox__bg absolute'
- }, [
- h('svg', {
- staticClass: 'q-checkbox__svg fit absolute-full',
- attrs: { focusable: 'false' /* needed for IE11 */, viewBox: '0 0 24 24', 'aria-hidden': 'true' }
+ return this.computedIcon !== void 0
+ ? [
+ h('div', {
+ key: 'icon',
+ staticClass: 'q-checkbox__icon-container absolute-full flex flex-center no-wrap'
}, [
- h('path', {
- staticClass: 'q-checkbox__truthy',
- attrs: {
- fill: 'none',
- d: 'M1.73,12.91 8.1,19.28 22.79,4.59'
- }
- }),
-
- h('path', {
- staticClass: 'q-checkbox__indet',
- attrs: {
- d: 'M4,14H20V10H4'
- }
+ h(QIcon, {
+ staticClass: 'q-checkbox__icon',
+ props: { name: this.computedIcon }
})
])
- ])
- ]
+ ]
+ : [
+ h('div', {
+ key: 'svg',
+ staticClass: 'q-checkbox__bg absolute'
+ }, [
+ h('svg', {
+ staticClass: 'q-checkbox__svg fit absolute-full',
+ attrs: { focusable: 'false' /* needed for IE11 */, viewBox: '0 0 24 24' }
+ }, [
+ h('path', {
+ staticClass: 'q-checkbox__truthy',
+ attrs: {
+ fill: 'none',
+ d: 'M1.73,12.91 8.1,19.28 22.79,4.59'
+ }
+ }),
+
+ h('path', {
+ staticClass: 'q-checkbox__indet',
+ attrs: {
+ d: 'M4,14H20V10H4'
+ }
+ })
+ ])
+ ])
+ ]
}
},
diff --git a/ui/src/components/checkbox/QCheckbox.json b/ui/src/components/checkbox/QCheckbox.json
index 5f08f4f2dd3..8eefef8757f 100644
--- a/ui/src/components/checkbox/QCheckbox.json
+++ b/ui/src/components/checkbox/QCheckbox.json
@@ -3,5 +3,22 @@
"meta": {
"docsUrl": "https://v1.quasar.dev/vue-components/checkbox"
+ },
+
+ "props": {
+ "checked-icon": {
+ "desc": "The icon to be used when the model is truthy (instead of the default design)",
+ "addedIn": "v1.18"
+ },
+
+ "unchecked-icon": {
+ "desc": "The icon to be used when the toggle is falsy (instead of the default design)",
+ "addedIn": "v1.18"
+ },
+
+ "indeterminate-icon": {
+ "desc": "The icon to be used when the model is indeterminate (instead of the default design)",
+ "addedIn": "v1.18"
+ }
}
}
diff --git a/ui/src/components/checkbox/QCheckbox.sass b/ui/src/components/checkbox/QCheckbox.sass
index afb6ffcbc64..079d2d376c9 100644
--- a/ui/src/components/checkbox/QCheckbox.sass
+++ b/ui/src/components/checkbox/QCheckbox.sass
@@ -3,6 +3,14 @@ $checkbox-transition: .22s cubic-bezier(0,0,.2,1) 0ms
.q-checkbox
vertical-align: middle
+ &__native
+ width: 1px
+ height: 1px
+
+ &__bg,
+ &__icon-container
+ user-select: none
+
&__bg
top: 25%
left: 25%
@@ -11,10 +19,11 @@ $checkbox-transition: .22s cubic-bezier(0,0,.2,1) 0ms
border: 2px solid currentColor
border-radius: 2px
transition: background $checkbox-transition
+ -webkit-print-color-adjust: exact
- &__native
- width: 1px
- height: 1px
+ &__icon
+ color: currentColor
+ font-size: .5em
&__svg
color: #fff
diff --git a/ui/src/components/checkbox/QCheckbox.styl b/ui/src/components/checkbox/QCheckbox.styl
index 947f4551457..76bc87d77f0 100644
--- a/ui/src/components/checkbox/QCheckbox.styl
+++ b/ui/src/components/checkbox/QCheckbox.styl
@@ -3,6 +3,14 @@ $checkbox-transition = .22s cubic-bezier(0,0,.2,1) 0ms
.q-checkbox
vertical-align: middle
+ &__native
+ width: 1px
+ height: 1px
+
+ &__bg,
+ &__icon-container
+ user-select: none
+
&__bg
top: 25%
left: 25%
@@ -11,10 +19,11 @@ $checkbox-transition = .22s cubic-bezier(0,0,.2,1) 0ms
border: 2px solid currentColor
border-radius: 2px
transition: background $checkbox-transition
+ -webkit-print-color-adjust: exact
- &__native
- width: 1px
- height: 1px
+ &__icon
+ color: currentColor
+ font-size: .5em
&__svg
color: #fff
diff --git a/ui/src/components/chip/QChip.js b/ui/src/components/chip/QChip.js
index 183316676c8..71da2b5960f 100644
--- a/ui/src/components/chip/QChip.js
+++ b/ui/src/components/chip/QChip.js
@@ -7,8 +7,8 @@ import RippleMixin from '../../mixins/ripple.js'
import { getSizeMixin } from '../../mixins/size.js'
import { stopAndPrevent } from '../../utils/event.js'
-import { mergeSlotSafely } from '../../utils/slot.js'
-import cache from '../../utils/cache.js'
+import { mergeSlotSafely } from '../../utils/private/slot.js'
+import cache from '../../utils/private/cache.js'
export default Vue.extend({
name: 'QChip',
@@ -55,6 +55,8 @@ export default Vue.extend({
clickable: Boolean,
removable: Boolean,
+ removeAriaLabel: String,
+
tabindex: [String, Number],
disable: Boolean
},
@@ -97,9 +99,17 @@ export default Vue.extend({
},
attrs () {
- return this.disable === true
+ const chip = this.disable === true
? { tabindex: -1, 'aria-disabled': 'true' }
: { tabindex: this.tabindex || 0 }
+ const remove = {
+ ...chip,
+ role: 'button',
+ 'aria-hidden': 'false',
+ 'aria-label': this.removeAriaLabel || this.$q.lang.label.remove
+ }
+
+ return { chip, remove }
}
},
@@ -157,7 +167,7 @@ export default Vue.extend({
h(QIcon, {
staticClass: 'q-chip__icon q-chip__icon--remove cursor-pointer',
props: { name: this.removeIcon },
- attrs: this.attrs,
+ attrs: this.attrs.remove,
on: cache(this, 'non', {
click: this.__onRemove,
keyup: this.__onRemove
@@ -179,7 +189,7 @@ export default Vue.extend({
}
this.isClickable === true && Object.assign(data, {
- attrs: this.attrs,
+ attrs: this.attrs.chip,
on: cache(this, 'click', {
click: this.__onClick,
keyup: this.__onKeyup
diff --git a/ui/src/components/chip/QChip.json b/ui/src/components/chip/QChip.json
index c9b528afc21..00f06aa5818 100644
--- a/ui/src/components/chip/QChip.json
+++ b/ui/src/components/chip/QChip.json
@@ -20,7 +20,7 @@
"dark": {
"extends": "dark",
- "addedIn": "v1.3.0"
+ "addedIn": "v1.3"
},
"icon": {
@@ -92,6 +92,14 @@
"category": "state"
},
+ "remove-aria-label": {
+ "type": "String",
+ "desc": "aria-label to be used on the remove icon",
+ "examples": [ "Remove item" ],
+ "category": "accessibility",
+ "addedIn": "v1.20.2"
+ },
+
"tabindex": {
"extends": "tabindex"
},
diff --git a/ui/src/components/circular-progress/QCircularProgress.js b/ui/src/components/circular-progress/QCircularProgress.js
index 003f7d882ad..70069ce5c7d 100644
--- a/ui/src/components/circular-progress/QCircularProgress.js
+++ b/ui/src/components/circular-progress/QCircularProgress.js
@@ -2,7 +2,7 @@ import Vue from 'vue'
import ListenersMixin from '../../mixins/listeners.js'
import SizeMixin from '../../mixins/size.js'
-import { mergeSlotSafely } from '../../utils/slot.js'
+import { mergeSlotSafely } from '../../utils/private/slot.js'
import { between } from '../../utils/format.js'
const
@@ -36,6 +36,7 @@ export default Vue.extend({
trackColor: String,
fontSize: String,
+ rounded: Boolean,
// ratio
thickness: {
@@ -105,7 +106,7 @@ export default Vue.extend({
},
methods: {
- __getCircle (h, { thickness, offset, color, cls }) {
+ __getCircle (h, { thickness, offset, color, cls, rounded }) {
return h('circle', {
staticClass: 'q-circular-progress__' + cls,
class: color !== void 0 ? `text-${color}` : null,
@@ -116,6 +117,7 @@ export default Vue.extend({
'stroke-width': thickness,
'stroke-dasharray': strokeDashArray,
'stroke-dashoffset': offset,
+ 'stroke-linecap': rounded,
cx: this.viewBox,
cy: this.viewBox,
r: radius
@@ -154,7 +156,8 @@ export default Vue.extend({
cls: 'circle',
thickness: this.strokeWidth,
offset: this.strokeDashOffset,
- color: this.color
+ color: this.color,
+ rounded: this.rounded === true ? 'round' : void 0
})
)
diff --git a/ui/src/components/circular-progress/QCircularProgress.json b/ui/src/components/circular-progress/QCircularProgress.json
index 3de9b2245c4..0e46a962ba1 100644
--- a/ui/src/components/circular-progress/QCircularProgress.json
+++ b/ui/src/components/circular-progress/QCircularProgress.json
@@ -57,6 +57,13 @@
"category": "style"
},
+ "rounded": {
+ "type": "Boolean",
+ "desc": "Rounding the arc of progress",
+ "category": "style",
+ "addedIn": "v1.20.2"
+ },
+
"thickness": {
"type": "Number",
"default": 0.2,
diff --git a/ui/src/components/color/QColor.js b/ui/src/components/color/QColor.js
index 942becdb0c8..478012a32fa 100644
--- a/ui/src/components/color/QColor.js
+++ b/ui/src/components/color/QColor.js
@@ -2,7 +2,7 @@ import Vue from 'vue'
import { testPattern } from '../../utils/patterns.js'
import throttle from '../../utils/throttle.js'
-import cache from '../../utils/cache.js'
+import cache from '../../utils/private/cache.js'
import { stop } from '../../utils/event.js'
import { hexToRgb, rgbToHex, rgbToString, textToRgb, rgbToHsv, hsvToRgb, luminosity } from '../../utils/colors.js'
@@ -33,6 +33,9 @@ const palette = [
'rgb(255,255,255)', 'rgb(205,205,205)', 'rgb(178,178,178)', 'rgb(153,153,153)', 'rgb(127,127,127)', 'rgb(102,102,102)', 'rgb(76,76,76)', 'rgb(51,51,51)', 'rgb(25,25,25)', 'rgb(0,0,0)'
]
+const thumbPath = 'M5 5 h10 v10 h-10 v-10 z'
+const alphaTrackImg = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAH0lEQVQoU2NkYGAwZkAFZ5G5jPRRgOYEVDeB3EBjBQBOZwTVugIGyAAAAABJRU5ErkJggg=='
+
export default Vue.extend({
name: 'QColor',
@@ -61,6 +64,7 @@ export default Vue.extend({
palette: Array,
noHeader: Boolean,
+ noHeaderTabs: Boolean,
noFooter: Boolean,
square: Boolean,
@@ -228,71 +232,78 @@ export default Vue.extend({
methods: {
__getHeader (h) {
- return h('div', {
- staticClass: 'q-color-picker__header relative-position overflow-hidden'
- }, [
- h('div', { staticClass: 'q-color-picker__header-bg absolute-full' }),
+ const child = []
- h('div', {
- staticClass: 'q-color-picker__header-content absolute-full',
- class: this.headerClass,
- style: this.currentBgColor
+ this.noHeaderTabs !== true && child.push(
+ h(QTabs, {
+ class: 'q-color-picker__header-tabs',
+ props: {
+ value: this.topView,
+ dense: true,
+ align: 'justify'
+ },
+ on: cache(this, 'topVTab', {
+ input: val => { this.topView = val }
+ })
}, [
- h(QTabs, {
+ h(QTab, {
props: {
- value: this.topView,
- dense: true,
- align: 'justify'
- },
- on: cache(this, 'topVTab', {
- input: val => { this.topView = val }
- })
- }, [
- h(QTab, {
- props: {
- label: 'HEX' + (this.hasAlpha === true ? 'A' : ''),
- name: 'hex',
- ripple: false
- }
- }),
+ label: 'HEX' + (this.hasAlpha === true ? 'A' : ''),
+ name: 'hex',
+ ripple: false
+ }
+ }),
- h(QTab, {
- props: {
- label: 'RGB' + (this.hasAlpha === true ? 'A' : ''),
- name: 'rgb',
- ripple: false
+ h(QTab, {
+ props: {
+ label: 'RGB' + (this.hasAlpha === true ? 'A' : ''),
+ name: 'rgb',
+ ripple: false
+ }
+ })
+ ])
+ )
+
+ child.push(
+ h('div', {
+ staticClass: 'q-color-picker__header-banner row flex-center no-wrap'
+ }, [
+ h('input', {
+ staticClass: 'fit',
+ domProps: { value: this.model[this.topView] },
+ attrs: this.editable !== true ? {
+ readonly: true
+ } : null,
+ on: cache(this, 'topIn', {
+ input: evt => {
+ this.__updateErrorIcon(this.__onEditorChange(evt) === true)
+ },
+ change: stop,
+ blur: evt => {
+ this.__onEditorChange(evt, true) === true && this.$forceUpdate()
+ this.__updateErrorIcon(false)
}
})
- ]),
-
- h('div', {
- staticClass: 'q-color-picker__header-banner row flex-center no-wrap'
- }, [
- h('input', {
- staticClass: 'fit',
- domProps: { value: this.model[this.topView] },
- attrs: this.editable !== true ? {
- readonly: true
- } : null,
- on: cache(this, 'topIn', {
- input: evt => {
- this.__updateErrorIcon(this.__onEditorChange(evt) === true)
- },
- change: stop,
- blur: evt => {
- this.__onEditorChange(evt, true) === true && this.$forceUpdate()
- this.__updateErrorIcon(false)
- }
- })
- }),
+ }),
- h(QIcon, {
- ref: 'errorIcon',
- staticClass: 'q-color-picker__error-icon absolute no-pointer-events',
- props: { name: this.$q.iconSet.type.negative }
- })
- ])
+ h(QIcon, {
+ ref: 'errorIcon',
+ staticClass: 'q-color-picker__error-icon absolute no-pointer-events',
+ props: { name: this.$q.iconSet.type.negative }
+ })
])
+ )
+
+ return h('div', {
+ staticClass: 'q-color-picker__header relative-position overflow-hidden'
+ }, [
+ h('div', { staticClass: 'q-color-picker__header-bg absolute-full' }),
+
+ h('div', {
+ staticClass: 'q-color-picker__header-content',
+ class: this.headerClass,
+ style: this.currentBgColor
+ }, child)
])
},
@@ -363,8 +374,6 @@ export default Vue.extend({
},
__getSpectrumTab (h) {
- const thumbPath = 'M5 5 h10 v10 h-10 v-10 z'
-
return [
h('div', {
ref: 'spectrum',
@@ -403,39 +412,45 @@ export default Vue.extend({
h('div', {
staticClass: 'q-color-picker__sliders'
}, [
- h('div', { staticClass: 'q-color-picker__hue non-selectable' }, [
- h(QSlider, {
+ h(QSlider, {
+ staticClass: 'q-color-picker__hue non-selectable',
+ props: {
+ value: this.model.h,
+ min: 0,
+ max: 360,
+ trackSize: '8px',
+ innerTrackColor: 'transparent',
+ selectionColor: 'transparent',
+ readonly: this.editable !== true,
+ thumbPath
+ },
+ on: cache(this, 'hueSlide', {
+ input: this.__onHueChange,
+ change: val => this.__onHueChange(val, true)
+ })
+ }),
+
+ this.hasAlpha === true
+ ? h(QSlider, {
+ staticClass: 'q-color-picker__alpha non-selectable',
props: {
- value: this.model.h,
+ value: this.model.a,
min: 0,
- max: 360,
- fillHandleAlways: true,
+ max: 100,
+ trackSize: '8px',
+ trackColor: 'white',
+ innerTrackColor: 'transparent',
+ selectionColor: 'transparent',
+ trackImg: alphaTrackImg,
readonly: this.editable !== true,
+ hideSelection: true,
thumbPath
},
- on: cache(this, 'hueSlide', {
- input: this.__onHueChange,
- change: val => this.__onHueChange(val, true)
+ on: cache(this, 'alphaSlide', {
+ input: value => this.__onNumericChange(value, 'a', 100),
+ change: value => this.__onNumericChange(value, 'a', 100, void 0, true)
})
})
- ]),
- this.hasAlpha === true
- ? h('div', { staticClass: 'q-color-picker__alpha non-selectable' }, [
- h(QSlider, {
- props: {
- value: this.model.a,
- min: 0,
- max: 100,
- fillHandleAlways: true,
- readonly: this.editable !== true,
- thumbPath
- },
- on: cache(this, 'alphaSlide', {
- input: value => this.__onNumericChange(value, 'a', 100),
- change: value => this.__onNumericChange(value, 'a', 100, void 0, true)
- })
- })
- ])
: null
])
]
diff --git a/ui/src/components/color/QColor.json b/ui/src/components/color/QColor.json
index dcf33acd926..0e4dab2b1d0 100644
--- a/ui/src/components/color/QColor.json
+++ b/ui/src/components/color/QColor.json
@@ -71,6 +71,13 @@
"category": "content"
},
+ "no-header-tabs": {
+ "type": "Boolean",
+ "desc": "Do not render header tabs (only the input)",
+ "category": "content",
+ "addedIn": "v1.17"
+ },
+
"no-footer": {
"type": "Boolean",
"desc": "Do not render footer; Useful when you want a specific view ('default-view' prop) and don't want the user to be able to switch it",
diff --git a/ui/src/components/color/QColor.sass b/ui/src/components/color/QColor.sass
index d91e722b410..bba1b12c509 100644
--- a/ui/src/components/color/QColor.sass
+++ b/ui/src/components/color/QColor.sass
@@ -16,7 +16,11 @@
border: 1px solid $separator-color
&__header
- height: 68px
+
+ &-tabs
+ height: 32px
+ &-banner
+ height: 36px
input
line-height: 24px
@@ -93,47 +97,34 @@
border-radius: 50%
transform: translate(-5px, -5px)
- &__hue .q-slider__track-container
+ &__hue .q-slider__track
background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%) !important // @stylint ignore
opacity: 1
- &__alpha .q-slider__track-container
- color: #fff
- opacity: 1
- height: 8px
- background-color: #fff !important
- background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAH0lEQVQoU2NkYGAwZkAFZ5G5jPRRgOYEVDeB3EBjBQBOZwTVugIGyAAAAABJRU5ErkJggg==') !important
- &:after
+ &__alpha
+ .q-slider__track-container
+ padding-top: 0
+ .q-slider__track:before
content: ''
position: absolute
top: 0
right: 0
bottom: 0
left: 0
+ border-radius: inherit
background: linear-gradient(90deg, rgba(255,255,255,0), $grey-7)
&__sliders
- padding: 4px 16px 16px
-
- .q-slider__track-container
- height: 10px
- margin-top: -5px
-
- .q-slider__track
- display: none
+ padding: 0 16px
.q-slider__thumb
+ color: $grey-9
path
stroke-width: 2px
fill: transparent
.q-slider--active path
stroke-width: 3px
- .q-slider
- height: 16px
- margin-top: 8px
- color: $grey-9
-
/* Tune Tab */
&__tune-tab
@@ -180,9 +171,8 @@
background: inherit
&--dark
-
.q-color-picker__tune-tab input
border: 1px solid rgba(#fff, .3)
.q-slider
- color: $grey-5
+ color: $grey-1
diff --git a/ui/src/components/color/QColor.styl b/ui/src/components/color/QColor.styl
index 1f8e9d7220b..d6b9686544a 100644
--- a/ui/src/components/color/QColor.styl
+++ b/ui/src/components/color/QColor.styl
@@ -16,7 +16,11 @@
border: 1px solid $separator-color
&__header
- height: 68px
+
+ &-tabs
+ height: 32px
+ &-banner
+ height: 36px
input
line-height: 24px
@@ -93,47 +97,34 @@
border-radius: 50%
transform: translate(-5px, -5px)
- &__hue .q-slider__track-container
+ &__hue .q-slider__track
background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%) !important // @stylint ignore
opacity: 1
- &__alpha .q-slider__track-container
- color: #fff
- opacity: 1
- height: 8px
- background-color: #fff !important
- background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAH0lEQVQoU2NkYGAwZkAFZ5G5jPRRgOYEVDeB3EBjBQBOZwTVugIGyAAAAABJRU5ErkJggg==') !important
- &:after
+ &__alpha
+ .q-slider__track-container
+ padding-top: 0
+ .q-slider__track:before
content: ''
position: absolute
top: 0
right: 0
bottom: 0
left: 0
+ border-radius: inherit
background: linear-gradient(90deg, rgba(255,255,255,0), $grey-7)
&__sliders
- padding: 4px 16px 16px
-
- .q-slider__track-container
- height: 10px
- margin-top: -5px
-
- .q-slider__track
- display: none
+ padding: 0 16px
.q-slider__thumb
+ color: $grey-9
path
stroke-width: 2px
fill: transparent
.q-slider--active path
stroke-width: 3px
- .q-slider
- height: 16px
- margin-top: 8px
- color: $grey-9
-
/* Tune Tab */
&__tune-tab
@@ -180,9 +171,8 @@
background: inherit
&--dark
-
.q-color-picker__tune-tab input
border: 1px solid alpha(#fff, .3)
.q-slider
- color: $grey-5
+ color: $grey-1
diff --git a/ui/src/components/date/QDate.js b/ui/src/components/date/QDate.js
index 9d44e009473..d7574bdae8d 100644
--- a/ui/src/components/date/QDate.js
+++ b/ui/src/components/date/QDate.js
@@ -3,11 +3,12 @@ import Vue from 'vue'
import QBtn from '../btn/QBtn.js'
import DateTimeMixin from '../../mixins/datetime.js'
-import { slot } from '../../utils/slot.js'
+import { slot } from '../../utils/private/slot.js'
import { formatDate, __splitDate, getDateDiff } from '../../utils/date.js'
import { pad } from '../../utils/format.js'
-import { jalaaliMonthLength, toGregorian } from '../../utils/date-persian.js'
-import cache from '../../utils/cache.js'
+import { jalaaliMonthLength, toGregorian } from '../../utils/private/date-persian.js'
+import cache from '../../utils/private/cache.js'
+import { isObject } from '../../utils/is.js'
const yearsInterval = 20
const views = [ 'Calendar', 'Years', 'Months' ]
@@ -95,13 +96,15 @@ export default Vue.extend({
this.lastEmitValue = 0
}
else {
- const { year, month } = this.__getViewModel(this.innerMask, this.innerLocale)
- this.__updateViewModel(year, month)
+ const model = this.__getViewModel(this.innerMask, this.innerLocale)
+ this.__updateViewModel(model.year, model.month, model)
}
},
view () {
- this.$refs.blurTarget !== void 0 && this.$refs.blurTarget.focus()
+ if (this.$refs.blurTarget !== void 0 && this.$el.contains(document.activeElement) === true) {
+ this.$refs.blurTarget.focus()
+ }
},
'viewModel.year' (year) {
@@ -128,9 +131,9 @@ export default Vue.extend({
const type = this.landscape === true ? 'landscape' : 'portrait'
return `q-date q-date--${type} q-date--${type}-${this.minimal === true ? 'minimal' : 'standard'}` +
(this.isDark === true ? ' q-date--dark q-dark' : '') +
- (this.bordered === true ? ` q-date--bordered` : '') +
- (this.square === true ? ` q-date--square no-border-radius` : '') +
- (this.flat === true ? ` q-date--flat no-shadow` : '') +
+ (this.bordered === true ? ' q-date--bordered' : '') +
+ (this.square === true ? ' q-date--square no-border-radius' : '') +
+ (this.flat === true ? ' q-date--flat no-shadow' : '') +
(this.disable === true ? ' disabled' : (this.readonly === true ? ' q-date--readonly' : ''))
},
@@ -150,13 +153,18 @@ export default Vue.extend({
return this.normalizedModel
.filter(date => typeof date === 'string')
.map(date => this.__decodeString(date, this.innerMask, this.innerLocale))
- .filter(date => date.dateHash !== null)
+ .filter(date =>
+ date.dateHash !== null &&
+ date.day !== null &&
+ date.month !== null &&
+ date.year !== null
+ )
},
rangeModel () {
const fn = date => this.__decodeString(date, this.innerMask, this.innerLocale)
return this.normalizedModel
- .filter(date => Object(date) === date && date.from !== void 0 && date.to !== void 0)
+ .filter(date => isObject(date) === true && date.from !== void 0 && date.to !== void 0)
.map(range => ({ from: fn(range.from), to: fn(range.to) }))
.filter(range => range.from.dateHash !== null && range.to.dateHash !== null && range.from.dateHash < range.to.dateHash)
},
@@ -657,7 +665,7 @@ export default Vue.extend({
}
res.forEach(day => {
- let cls = `q-date__calendar-item `
+ let cls = 'q-date__calendar-item '
if (day.fill === true) {
cls += 'q-date__calendar-item--fill'
@@ -696,7 +704,13 @@ export default Vue.extend({
methods: {
setToday () {
- this.__toggleDate(this.today, this.__getMonthHash(this.today))
+ const date = this.today
+ const month = this.daysMap[this.__getMonthHash(date)]
+
+ if (month === void 0 || month.includes(date.day) === false) {
+ this.__addToModel(date)
+ }
+
this.setCalendarTo(this.today.year, this.today.month)
},
@@ -1251,7 +1265,7 @@ export default Vue.extend({
}
},
- __updateViewModel (year, month) {
+ __updateViewModel (year, month, time) {
if (this.minNav !== void 0 && year <= this.minNav.year) {
year = this.minNav.year
if (month < this.minNav.month) {
@@ -1266,6 +1280,11 @@ export default Vue.extend({
}
}
+ if (time !== void 0) {
+ const { hour, minute, second, millisecond, timezoneOffset, timeHash } = time
+ Object.assign(this.viewModel, { hour, minute, second, millisecond, timezoneOffset, timeHash })
+ }
+
const newHash = year + '/' + pad(month) + '/01'
if (newHash !== this.viewModel.dateHash) {
diff --git a/ui/src/components/date/QDate.json b/ui/src/components/date/QDate.json
index 2025d91ba90..814c8c5f746 100644
--- a/ui/src/components/date/QDate.json
+++ b/ui/src/components/date/QDate.json
@@ -101,7 +101,7 @@
"desc": "Lock user from navigating below a specific year+month (in YYYY/MM format); This prop is not used to correct the model; You might want to also use 'default-year-month' prop",
"examples": [ "2020/07" ],
"category": "selection",
- "addedIn": "v1.13.0"
+ "addedIn": "v1.13"
},
"navigation-max-year-month": {
@@ -109,7 +109,7 @@
"desc": "Lock user from navigating above a specific year+month (in YYYY/MM format); This prop is not used to correct the model; You might want to also use 'default-year-month' prop",
"examples": [ "2020/10" ],
"category": "selection",
- "addedIn": "v1.13.0"
+ "addedIn": "v1.13"
},
"no-unset": {
@@ -146,14 +146,14 @@
"type": "Boolean",
"desc": "Allow multiple selection; Model must be Array",
"category": "model|selection",
- "addedIn": "v1.13.0"
+ "addedIn": "v1.13"
},
"range": {
"type": "Boolean",
"desc": "Allow range selection; Partial compatibility with 'options' prop: selected ranges might also include 'unselectable' days",
"category": "model|selection",
- "addedIn": "v1.13.0"
+ "addedIn": "v1.13"
},
"emit-immediately": {
@@ -221,7 +221,7 @@
"__exemption": [ "examples" ]
}
},
- "addedIn": "v1.13.0"
+ "addedIn": "v1.13"
},
"to": {
"type": "Object",
@@ -243,7 +243,7 @@
"__exemption": [ "examples" ]
}
},
- "addedIn": "v1.13.0"
+ "addedIn": "v1.13"
},
"changed": {
"type": "Boolean",
@@ -275,7 +275,7 @@
}
}
},
- "addedIn": "v1.13.0"
+ "addedIn": "v1.13"
},
"range-start": {
@@ -303,7 +303,7 @@
}
}
},
- "addedIn": "v1.13.0"
+ "addedIn": "v1.13"
},
"range-end": {
@@ -358,7 +358,7 @@
}
}
},
- "addedIn": "v1.13.0"
+ "addedIn": "v1.13"
}
},
@@ -412,7 +412,7 @@
"__exemption": [ "examples" ]
}
},
- "addedIn": "v1.13.0"
+ "addedIn": "v1.13"
},
"setEditingRange": {
diff --git a/ui/src/components/date/QDate.sass b/ui/src/components/date/QDate.sass
index 29fd3e26b78..2f348f3d39c 100644
--- a/ui/src/components/date/QDate.sass
+++ b/ui/src/components/date/QDate.sass
@@ -96,6 +96,8 @@
> div
line-height: 30px
text-align: center
+ > button
+ line-height: 22px
&--out
opacity: .18
diff --git a/ui/src/components/date/QDate.styl b/ui/src/components/date/QDate.styl
index 29fd3e26b78..2f348f3d39c 100644
--- a/ui/src/components/date/QDate.styl
+++ b/ui/src/components/date/QDate.styl
@@ -96,6 +96,8 @@
> div
line-height: 30px
text-align: center
+ > button
+ line-height: 22px
&--out
opacity: .18
diff --git a/ui/src/components/dialog-bottom-sheet/BottomSheet.js b/ui/src/components/dialog-bottom-sheet/BottomSheet.js
index 7812a65e383..1681839fa39 100644
--- a/ui/src/components/dialog-bottom-sheet/BottomSheet.js
+++ b/ui/src/components/dialog-bottom-sheet/BottomSheet.js
@@ -14,7 +14,14 @@ import QItemSection from '../item/QItemSection.js'
import DarkMixin from '../../mixins/dark.js'
import AttrsMixin from '../../mixins/attrs.js'
-import cache from '../../utils/cache.js'
+import cache from '../../utils/private/cache.js'
+
+const optsGrid = {
+ staticClass: 'row items-stretch justify-start',
+ attrs: { role: 'list' }
+}
+const optsList = { attrs: { role: 'list' } }
+const attrsGridItem = { tabindex: 0, role: 'listitem' }
export default Vue.extend({
name: 'BottomSheetPlugin',
@@ -69,9 +76,12 @@ export default Vue.extend({
: h('div', {
staticClass: 'q-bottom-sheet__item q-hoverable q-focusable cursor-pointer relative-position',
class: action.classes,
- attrs: { tabindex: 0 },
+ style: action.style,
+ attrs: attrsGridItem,
on: {
- click: () => this.onOk(action),
+ click: () => {
+ this.onOk(action)
+ },
keyup: e => {
e.keyCode === 13 && this.onOk(action)
}
@@ -104,15 +114,15 @@ export default Vue.extend({
: h(QItem, {
staticClass: 'q-bottom-sheet__item',
class: action.classes,
+ style: action.style,
props: {
tabindex: 0,
clickable: true,
dark: this.isDark
},
on: {
- click: () => this.onOk(action),
- keyup: e => {
- e.keyCode === 13 && this.onOk(action)
+ click: () => {
+ this.onOk(action)
}
}
}, [
@@ -151,10 +161,8 @@ export default Vue.extend({
child.push(
this.grid === true
- ? h('div', {
- staticClass: 'row items-stretch justify-start'
- }, this.__getGrid(h))
- : h('div', this.__getList(h))
+ ? h('div', optsGrid, this.__getGrid(h))
+ : h('div', optsList, this.__getList(h))
)
return h(QDialog, {
diff --git a/ui/src/components/dialog-plugin/DialogPlugin.js b/ui/src/components/dialog-plugin/DialogPlugin.js
index dee242ea10e..9f2289fca07 100644
--- a/ui/src/components/dialog-plugin/DialogPlugin.js
+++ b/ui/src/components/dialog-plugin/DialogPlugin.js
@@ -4,7 +4,7 @@ import QDialog from '../dialog/QDialog.js'
import QBtn from '../btn/QBtn.js'
import clone from '../../utils/clone.js'
-import { isKeyCode } from '../../utils/key-composition.js'
+import { isKeyCode } from '../../utils/private/key-composition.js'
import QCard from '../card/QCard.js'
import QCardSection from '../card/QCardSection.js'
@@ -19,7 +19,8 @@ import QSpinner from '../spinner/QSpinner.js'
import DarkMixin from '../../mixins/dark.js'
import AttrsMixin from '../../mixins/attrs.js'
-import cache from '../../utils/cache.js'
+import cache from '../../utils/private/cache.js'
+import { isObject } from '../../utils/is.js'
export default Vue.extend({
name: 'DialogPlugin',
@@ -64,7 +65,7 @@ export default Vue.extend({
spinner () {
if (this.progress !== false) {
- return Object(this.progress) === this.progress
+ return isObject(this.progress) === true
? {
component: this.progress.spinner || QSpinner,
props: { color: this.progress.color || this.vmColor }
@@ -81,7 +82,7 @@ export default Vue.extend({
},
okLabel () {
- return Object(this.ok) === this.ok
+ return isObject(this.ok) === true
? this.$q.lang.label.ok
: (
this.ok === true
@@ -91,7 +92,7 @@ export default Vue.extend({
},
cancelLabel () {
- return Object(this.cancel) === this.cancel
+ return isObject(this.cancel) === true
? this.$q.lang.label.cancel
: (
this.cancel === true
@@ -120,8 +121,8 @@ export default Vue.extend({
color: this.vmColor,
label: this.okLabel,
ripple: false,
- ...(Object(this.ok) === this.ok ? this.ok : { flat: true }),
- disable: this.okDisabled
+ disable: this.okDisabled,
+ ...(isObject(this.ok) === true ? this.ok : { flat: true })
}
},
@@ -130,7 +131,7 @@ export default Vue.extend({
color: this.vmColor,
label: this.cancelLabel,
ripple: false,
- ...(Object(this.cancel) === this.cancel ? this.cancel : { flat: true })
+ ...(isObject(this.cancel) === true ? this.cancel : { flat: true })
}
}
},
diff --git a/ui/src/components/dialog/QDialog.js b/ui/src/components/dialog/QDialog.js
index 653fb22fe9b..89a124bf576 100644
--- a/ui/src/components/dialog/QDialog.js
+++ b/ui/src/components/dialog/QDialog.js
@@ -1,17 +1,20 @@
import Vue from 'vue'
import HistoryMixin from '../../mixins/history.js'
+import TimeoutMixin from '../../mixins/timeout.js'
import ModelToggleMixin from '../../mixins/model-toggle.js'
import PortalMixin from '../../mixins/portal.js'
import PreventScrollMixin from '../../mixins/prevent-scroll.js'
import AttrsMixin, { ariaHidden } from '../../mixins/attrs.js'
+import TransitionMixin from '../../mixins/transition.js'
import { childHasFocus } from '../../utils/dom.js'
-import EscapeKey from '../../utils/escape-key.js'
-import { slot } from '../../utils/slot.js'
+import EscapeKey from '../../utils/private/escape-key.js'
+import { slot } from '../../utils/private/slot.js'
import { create, stop } from '../../utils/event.js'
-import cache from '../../utils/cache.js'
-import { addFocusFn } from '../../utils/focus-manager.js'
+import cache from '../../utils/private/cache.js'
+import { addFocusFn } from '../../utils/private/focus-manager.js'
+import { client } from '../../plugins/Platform.js'
let maximizedModals = 0
@@ -23,7 +26,7 @@ const positionClass = {
left: 'fixed-left items-center'
}
-const transitions = {
+const defaultTransitions = {
standard: ['scale', 'scale'],
top: ['slide-down', 'slide-up'],
bottom: ['slide-up', 'slide-down'],
@@ -31,12 +34,19 @@ const transitions = {
left: ['slide-right', 'slide-left']
}
+const backdropAttrs = {
+ ...ariaHidden,
+ tabindex: -1
+}
+
export default Vue.extend({
name: 'QDialog',
mixins: [
AttrsMixin,
+ TransitionMixin,
HistoryMixin,
+ TimeoutMixin,
ModelToggleMixin,
PortalMixin,
PreventScrollMixin
@@ -45,12 +55,14 @@ export default Vue.extend({
props: {
persistent: Boolean,
autoClose: Boolean,
+ allowFocusOutside: Boolean,
noEscDismiss: Boolean,
noBackdropDismiss: Boolean,
noRouteDismiss: Boolean,
noRefocus: Boolean,
noFocus: Boolean,
+ noShake: Boolean,
seamless: Boolean,
@@ -73,20 +85,11 @@ export default Vue.extend({
data () {
return {
- transitionState: this.showing,
animating: false
}
},
watch: {
- showing (val) {
- if (this.transitionShowComputed !== this.transitionHideComputed) {
- this.$nextTick(() => {
- this.transitionState = val
- })
- }
- },
-
maximized (state) {
this.showing === true && this.__updateMaximized(state)
},
@@ -107,18 +110,12 @@ export default Vue.extend({
(this.square === true ? ' q-dialog__inner--square' : '')
},
- transitionShowComputed () {
- return 'q-transition--' + (this.transitionShow === void 0 ? transitions[this.position][0] : this.transitionShow)
+ defaultTransitionShow () {
+ return defaultTransitions[this.position][0]
},
- transitionHideComputed () {
- return 'q-transition--' + (this.transitionHide === void 0 ? transitions[this.position][1] : this.transitionHide)
- },
-
- transition () {
- return this.transitionState === true
- ? this.transitionHideComputed
- : this.transitionShowComputed
+ defaultTransitionHide () {
+ return defaultTransitions[this.position][1]
},
useBackdrop () {
@@ -145,11 +142,19 @@ export default Vue.extend({
}
return on
+ },
+
+ attrs () {
+ return {
+ role: 'dialog',
+ 'aria-modal': this.useBackdrop === true ? 'true' : 'false',
+ ...this.qAttrs
+ }
}
},
methods: {
- focus () {
+ focus (selector) {
addFocusFn(() => {
let node = this.__getInnerNode()
@@ -157,13 +162,23 @@ export default Vue.extend({
return
}
- node = node.querySelector('[autofocus], [data-autofocus]') || node
- node.focus()
+ node = (selector !== '' ? node.querySelector(selector) : null) ||
+ node.querySelector('[autofocus][tabindex], [data-autofocus][tabindex]') ||
+ node.querySelector('[autofocus] [tabindex], [data-autofocus] [tabindex]') ||
+ node.querySelector('[autofocus], [data-autofocus]') ||
+ node
+ node.focus({ preventScroll: true })
})
},
- shake () {
- this.focus()
+ shake (focusTarget) {
+ if (focusTarget && typeof focusTarget.focus === 'function') {
+ focusTarget.focus({ preventScroll: true })
+ }
+ else {
+ this.focus()
+ }
+
this.$emit('shake')
const node = this.__getInnerNode()
@@ -188,21 +203,21 @@ export default Vue.extend({
this.__addHistory()
// IE can have null document.activeElement
- this.__refocusTarget = this.noRefocus === false && document.activeElement !== null
+ this.__refocusTarget = client.is.mobile !== true && this.noRefocus === false && document.activeElement !== null
? document.activeElement
: void 0
this.$el.dispatchEvent(create('popup-show', { bubbles: true }))
this.__updateMaximized(this.maximized)
- EscapeKey.register(this, () => {
+ EscapeKey.register(this, escEvt => {
if (this.seamless !== true) {
if (this.persistent === true || this.noEscDismiss === true) {
- this.maximized !== true && this.shake()
+ this.maximized !== true && this.noShake !== true && this.shake()
}
else {
this.$emit('escape-key')
- this.hide()
+ this.hide(escEvt)
}
}
})
@@ -213,10 +228,14 @@ export default Vue.extend({
if (this.noFocus !== true) {
// IE can have null document.activeElement
document.activeElement !== null && document.activeElement.blur()
- this.__nextTick(this.focus)
+ this.__registerTick(this.focus)
+ }
+ else {
+ this.__removeTick()
}
- this.__setTimeout(() => {
+ // should __removeTimeout() if this gets removed
+ this.__registerTimeout(() => {
if (this.$q.platform.is.ios === true) {
if (this.seamless !== true && document.activeElement) {
const
@@ -243,25 +262,32 @@ export default Vue.extend({
}
this.animating = false
- this.__showPortal(true)
+ this.__showPortal(true) // done showing
this.$emit('show', evt)
}, 300)
},
__hide (evt) {
+ this.__removeTick()
this.__removeHistory()
this.__cleanup(true)
+ this.__hidePortal()
this.animating = true
// check null for IE
if (this.__refocusTarget !== void 0 && this.__refocusTarget !== null) {
- this.__refocusTarget.focus()
+ ((evt && evt.type.indexOf('key') === 0
+ ? this.__refocusTarget.closest('[tabindex]:not([tabindex^="-"])')
+ : void 0
+ ) || this.__refocusTarget).focus()
+ this.__refocusTarget = void 0
}
this.$el.dispatchEvent(create('popup-hide', { bubbles: true }))
- this.__setTimeout(() => {
- this.__hidePortal()
+ // should __removeTimeout() if this gets removed
+ this.__registerTimeout(() => {
+ this.__hidePortal(true) // done hiding, now destroy
this.animating = false
this.$emit('hide', evt)
}, 300)
@@ -316,19 +342,19 @@ export default Vue.extend({
if (this.persistent !== true && this.noBackdropDismiss !== true) {
this.hide(e)
}
- else {
- this.shake()
+ else if (this.noShake !== true) {
+ this.shake(e.relatedTarget)
}
},
__onFocusChange (e) {
// the focus is not in a vue child component
if (
- this.showing === true &&
- this.__portal !== void 0 &&
+ this.allowFocusOutside !== true &&
+ this.__portalIsAccessible === true &&
childHasFocus(this.__portal.$el, e.target) !== true
) {
- this.focus()
+ this.focus('[tabindex]:not([tabindex="-1"])')
}
},
@@ -337,22 +363,22 @@ export default Vue.extend({
staticClass: `q-dialog fullscreen no-pointer-events q-dialog--${this.useBackdrop === true ? 'modal' : 'seamless'}`,
class: this.contentClass,
style: this.contentStyle,
- attrs: this.qAttrs
+ attrs: this.attrs
}, [
h('transition', {
props: { name: 'q-transition--fade' }
}, this.useBackdrop === true ? [
h('div', {
staticClass: 'q-dialog__backdrop fixed-full',
- attrs: ariaHidden,
+ attrs: backdropAttrs,
on: cache(this, 'bkdrop', {
- click: this.__onBackdropClick
+ [ this.backdropEvt ]: this.__onBackdropClick
})
})
] : null),
h('transition', {
- props: { name: this.transition }
+ props: { ...this.transitionProps }
}, [
this.showing === true ? h('div', {
ref: 'inner',
@@ -366,11 +392,18 @@ export default Vue.extend({
}
},
+ created () {
+ this.__useTick('__registerTick', '__removeTick')
+ this.__useTimeout('__registerTimeout')
+ this.backdropEvt = this.$q.platform.is.ios === true || this.$q.platform.is.safari ? 'click' : 'focusin'
+ },
+
mounted () {
this.__processModelChange(this.value)
},
beforeDestroy () {
this.__cleanup()
+ this.__refocusTarget = void 0
}
})
diff --git a/ui/src/components/dialog/QDialog.json b/ui/src/components/dialog/QDialog.json
index 7e4ea8fc343..0b6a449535c 100644
--- a/ui/src/components/dialog/QDialog.json
+++ b/ui/src/components/dialog/QDialog.json
@@ -101,12 +101,26 @@
"type": "Boolean",
"desc": "(Accessibility) When Dialog gets shown, do not switch focus on it",
"category": "behavior"
+ },
+
+ "no-shake": {
+ "type": "Boolean",
+ "desc": "Do not shake up the Dialog to catch user's attention",
+ "category": "behavior",
+ "addedIn": "v1.17"
+ },
+
+ "allow-focus-outside": {
+ "type": "Boolean",
+ "desc": "Allow elements outside of the Dialog to be focusable; By default, for accessibility reasons, QDialog does not allow outer focus",
+ "category": "behavior",
+ "addedIn": "v1.21"
}
},
"events": {
"shake": {
- "desc": "Shakes up the Dialog in order to catch user's attention"
+ "desc": "Emitted when the Dialog shakes in order to catch user's attention, unless the 'no-shake' property is set"
},
"escape-key": {
@@ -116,11 +130,28 @@
"methods": {
"focus": {
- "desc": "Focus dialog; if you have content with autofocus attribute, it will directly focus it"
+ "desc": "Focus dialog; if you have content with autofocus attribute, it will directly focus it",
+ "params": {
+ "selector": {
+ "type": "String",
+ "required": false,
+ "desc": "Optional CSS selector to override default focusable element",
+ "examples": [ "[tabindex]:not([tabindex=\"-1\"])" ],
+ "addedIn": "v1.18.9"
+ }
+ }
},
"shake": {
- "desc": "Shakes dialog"
+ "desc": "Shakes dialog",
+ "params": {
+ "focusTarget": {
+ "type": "Element",
+ "desc": "Optional DOM Element to be focused after shake",
+ "examples": [ "document.getElementById('example')" ],
+ "addedIn": "v1.22.1"
+ }
+ }
}
},
diff --git a/ui/src/components/drawer/QDrawer.js b/ui/src/components/drawer/QDrawer.js
index c754727458e..097d22977d3 100644
--- a/ui/src/components/drawer/QDrawer.js
+++ b/ui/src/components/drawer/QDrawer.js
@@ -1,6 +1,7 @@
import Vue from 'vue'
import HistoryMixin from '../../mixins/history.js'
+import TimeoutMixin from '../../mixins/timeout.js'
import ModelToggleMixin from '../../mixins/model-toggle.js'
import PreventScrollMixin from '../../mixins/prevent-scroll.js'
import DarkMixin from '../../mixins/dark.js'
@@ -8,8 +9,8 @@ import DarkMixin from '../../mixins/dark.js'
import TouchPan from '../../directives/TouchPan.js'
import { between } from '../../utils/format.js'
-import { slot } from '../../utils/slot.js'
-import cache from '../../utils/cache.js'
+import { slot } from '../../utils/private/slot.js'
+import cache from '../../utils/private/cache.js'
import { ariaHidden } from '../../mixins/attrs'
const duration = 150
@@ -29,7 +30,7 @@ export default Vue.extend({
}
},
- mixins: [ DarkMixin, HistoryMixin, ModelToggleMixin, PreventScrollMixin ],
+ mixins: [ DarkMixin, HistoryMixin, TimeoutMixin, ModelToggleMixin, PreventScrollMixin ],
directives: {
TouchPan
@@ -114,11 +115,10 @@ export default Vue.extend({
}
},
- 'layout.totalWidth' (val) {
- this.__updateLocal('belowBreakpoint', (
- this.behavior === 'mobile' ||
- (this.behavior !== 'desktop' && val <= this.breakpoint)
- ))
+ 'layout.totalWidth' () {
+ if (this.layout.container === true || document.qScrollPrevented !== true) {
+ this.__updateBelowBreakpoint()
+ }
},
side (newSide, oldSide) {
@@ -134,22 +134,17 @@ export default Vue.extend({
this.layout[newSide].offset = this.offset
},
- behavior (val) {
- this.__updateLocal('belowBreakpoint', (
- val === 'mobile' ||
- (val !== 'desktop' && this.layout.totalWidth <= this.breakpoint)
- ))
+ behavior () {
+ this.__updateBelowBreakpoint()
},
- breakpoint (val) {
- this.__updateLocal('belowBreakpoint', (
- this.behavior === 'mobile' ||
- (this.behavior !== 'desktop' && this.layout.totalWidth <= val)
- ))
+ breakpoint () {
+ this.__updateBelowBreakpoint()
},
'layout.container' (val) {
this.showing === true && this.__preventScroll(val !== true)
+ val === true && this.__updateBelowBreakpoint()
},
'layout.scrollbarWidth' () {
@@ -542,7 +537,7 @@ export default Vue.extend({
evt !== false && this.__setScrollable(false)
}
- this.__setTimeout(() => {
+ this.__registerTimeout(() => {
evt !== false && this.__setScrollable(true)
noEvent !== true && this.$emit('show', evt)
}, duration)
@@ -559,9 +554,12 @@ export default Vue.extend({
this.__cleanup()
- noEvent !== true && this.__setTimeout(() => {
- this.$emit('hide', evt)
- }, duration)
+ if (noEvent !== true) {
+ this.__registerTimeout(() => { this.$emit('hide', evt) }, duration)
+ }
+ else {
+ this.__removeTimeout()
+ }
},
__cleanup () {
@@ -583,10 +581,19 @@ export default Vue.extend({
__updateSizeOnLayout (miniToOverlay, size) {
this.__update('size', miniToOverlay === true ? this.miniWidth : size)
+ },
+
+ __updateBelowBreakpoint () {
+ this.__updateLocal('belowBreakpoint', (
+ this.behavior === 'mobile' ||
+ (this.behavior !== 'desktop' && this.layout.totalWidth <= this.breakpoint)
+ ))
}
},
created () {
+ this.__useTimeout('__registerTimeout', '__removeTimeout')
+
this.layout.instances[this.side] = this
this.__updateSizeOnLayout(this.miniToOverlay, this.size)
this.__update('space', this.onLayout)
@@ -698,7 +705,7 @@ export default Vue.extend({
child.push(
h('aside', {
ref: 'content',
- staticClass: `q-drawer`,
+ staticClass: 'q-drawer',
class: this.classes,
style: this.style,
on: this.onNativeEvents,
diff --git a/ui/src/components/drawer/QDrawer.json b/ui/src/components/drawer/QDrawer.json
index b190d00b931..5ebf8b60f55 100644
--- a/ui/src/components/drawer/QDrawer.json
+++ b/ui/src/components/drawer/QDrawer.json
@@ -45,7 +45,7 @@
"dark": {
"extends": "dark",
- "addedIn": "v1.3.0"
+ "addedIn": "v1.3"
},
"mini-to-overlay": {
diff --git a/ui/src/components/editor/QEditor.js b/ui/src/components/editor/QEditor.js
index f0308e17a2a..cfed8ee704f 100644
--- a/ui/src/components/editor/QEditor.js
+++ b/ui/src/components/editor/QEditor.js
@@ -10,8 +10,8 @@ import ListenersMixin from '../../mixins/listeners.js'
import { isSSR } from '../../plugins/Platform.js'
import { stopAndPrevent } from '../../utils/event.js'
import extend from '../../utils/extend.js'
-import { shouldIgnoreKey } from '../../utils/key-composition.js'
-import { addFocusFn } from '../../utils/focus-manager.js'
+import { shouldIgnoreKey } from '../../utils/private/key-composition.js'
+import { addFocusFn } from '../../utils/private/focus-manager.js'
export default Vue.extend({
name: 'QEditor',
@@ -379,33 +379,14 @@ export default Vue.extend({
}
},
- __onMousedown () {
+ // mousedown, touchstart
+ __onPointerStart (e) {
this.__offsetBottom = void 0
+ this.qListeners[e.type] !== void 0 && this.$emit(e.type, e)
},
- __onMouseup (e) {
+ __onSelectionchange () {
this.caret.save()
- if (this.qListeners.mouseup !== void 0) {
- this.$emit('mouseup', e)
- }
- },
-
- __onKeyup (e) {
- this.caret.save()
- if (this.qListeners.keyup !== void 0) {
- this.$emit('keyup', e)
- }
- },
-
- __onTouchstart () {
- this.__offsetBottom = void 0
- },
-
- __onTouchend (e) {
- this.caret.save()
- if (this.qListeners.touchend !== void 0) {
- this.$emit('touchend', e)
- }
},
runCmd (cmd, param, update = true) {
@@ -432,7 +413,7 @@ export default Vue.extend({
focus () {
addFocusFn(() => {
- this.$refs.content !== void 0 && this.$refs.content.focus()
+ this.$refs.content !== void 0 && this.$refs.content.focus({ preventScroll: true })
})
},
@@ -468,6 +449,12 @@ export default Vue.extend({
this.caret = new Caret(this.$refs.content, this)
this.__setContent(this.value)
this.refreshToolbar()
+
+ document.addEventListener('selectionchange', this.__onSelectionchange)
+ },
+
+ beforeDestroy () {
+ document.removeEventListener('selectionchange', this.__onSelectionchange)
},
render (h) {
@@ -505,18 +492,13 @@ export default Vue.extend({
focus: this.__onFocus,
// clean saved scroll position
- mousedown: this.__onMousedown,
- touchstart: this.__onTouchstart,
-
- // save caret
- mouseup: this.__onMouseup,
- keyup: this.__onKeyup,
- touchend: this.__onTouchend
+ mousedown: this.__onPointerStart,
+ touchstart: this.__onPointerStart
}
return h('div', {
style: {
- height: this.inFullscreen === true ? '100vh' : null
+ height: this.inFullscreen === true ? '100%' : null
},
class: this.classes,
attrs: this.attrs,
@@ -528,7 +510,7 @@ export default Vue.extend({
'div',
{
ref: 'content',
- staticClass: `q-editor__content`,
+ staticClass: 'q-editor__content',
style: this.innerStyle,
class: this.innerClass,
attrs: {
@@ -537,7 +519,7 @@ export default Vue.extend({
},
domProps: isSSR
? { innerHTML: this.value }
- : undefined,
+ : void 0,
on
}
)
diff --git a/ui/src/components/editor/QEditor.json b/ui/src/components/editor/QEditor.json
index 79538cd014f..00b7895a7f5 100644
--- a/ui/src/components/editor/QEditor.json
+++ b/ui/src/components/editor/QEditor.json
@@ -36,7 +36,7 @@
"dark": {
"extends": "dark",
- "addedIn": "v1.3.0"
+ "addedIn": "v1.3"
},
"disable": {
diff --git a/ui/src/components/editor/QEditor.sass b/ui/src/components/editor/QEditor.sass
index e85a0576d81..eef9aa6dda8 100644
--- a/ui/src/components/editor/QEditor.sass
+++ b/ui/src/components/editor/QEditor.sass
@@ -6,10 +6,18 @@
&.disabled
border-style: dashed
- > div:first-child, &__toolbars-container, &__toolbars-container > div:first-child
+ &.fullscreen
+ max-height: 100%
+
+ > div:first-child,
+ &__toolbars-container,
+ &__toolbars-container > div:first-child
border-top-left-radius: inherit
border-top-right-radius: inherit
+ &__toolbars-container
+ max-width: 100%
+
&__content
outline: 0
padding: $editor-content-padding
@@ -17,14 +25,18 @@
border-bottom-left-radius: inherit
border-bottom-right-radius: inherit
overflow: auto
+ max-width: 100%
+
pre
white-space: pre-wrap
+
hr
border: 0
outline: 0
margin: 1px
height: 1px
background: $editor-hr-color
+
&:empty:not(:focus):before
content: attr(placeholder)
opacity: .7
diff --git a/ui/src/components/editor/QEditor.styl b/ui/src/components/editor/QEditor.styl
index e85a0576d81..eef9aa6dda8 100644
--- a/ui/src/components/editor/QEditor.styl
+++ b/ui/src/components/editor/QEditor.styl
@@ -6,10 +6,18 @@
&.disabled
border-style: dashed
- > div:first-child, &__toolbars-container, &__toolbars-container > div:first-child
+ &.fullscreen
+ max-height: 100%
+
+ > div:first-child,
+ &__toolbars-container,
+ &__toolbars-container > div:first-child
border-top-left-radius: inherit
border-top-right-radius: inherit
+ &__toolbars-container
+ max-width: 100%
+
&__content
outline: 0
padding: $editor-content-padding
@@ -17,14 +25,18 @@
border-bottom-left-radius: inherit
border-bottom-right-radius: inherit
overflow: auto
+ max-width: 100%
+
pre
white-space: pre-wrap
+
hr
border: 0
outline: 0
margin: 1px
height: 1px
background: $editor-hr-color
+
&:empty:not(:focus):before
content: attr(placeholder)
opacity: .7
diff --git a/ui/src/components/editor/editor-caret.js b/ui/src/components/editor/editor-caret.js
index 233a58335f7..0449b1ce51a 100644
--- a/ui/src/components/editor/editor-caret.js
+++ b/ui/src/components/editor/editor-caret.js
@@ -198,7 +198,7 @@ export class Caret {
return false
}
- if (el !== null && list.includes(el.nodeName.toLowerCase()) === true) {
+ if (list.includes(el.nodeName.toLowerCase()) === true) {
return true
}
diff --git a/ui/src/components/editor/editor-utils.js b/ui/src/components/editor/editor-utils.js
index 34ed4cf46ad..134c778f7af 100644
--- a/ui/src/components/editor/editor-utils.js
+++ b/ui/src/components/editor/editor-utils.js
@@ -7,8 +7,8 @@ import QItem from '../item/QItem.js'
import QItemSection from '../item/QItemSection.js'
import { prevent, stop } from '../../utils/event.js'
-import { slot } from '../../utils/slot.js'
-import { shouldIgnoreKey } from '../../utils/key-composition.js'
+import { slot } from '../../utils/private/slot.js'
+import { shouldIgnoreKey } from '../../utils/private/key-composition.js'
function run (e, btn, vm) {
if (btn.handler) {
diff --git a/ui/src/components/expansion-item/QExpansionItem.js b/ui/src/components/expansion-item/QExpansionItem.js
index 6fae2c33b2d..762e60cd309 100644
--- a/ui/src/components/expansion-item/QExpansionItem.js
+++ b/ui/src/components/expansion-item/QExpansionItem.js
@@ -7,22 +7,27 @@ import QIcon from '../icon/QIcon.js'
import QSlideTransition from '../slide-transition/QSlideTransition.js'
import QSeparator from '../separator/QSeparator.js'
-import { RouterLinkMixin } from '../../mixins/router-link.js'
+import { routerLinkProps } from '../../mixins/router-link.js'
+import TimeoutMixin from '../../mixins/timeout.js'
import ModelToggleMixin from '../../mixins/model-toggle.js'
import DarkMixin from '../../mixins/dark.js'
import { stopAndPrevent } from '../../utils/event.js'
-import { slot } from '../../utils/slot.js'
-import cache from '../../utils/cache.js'
+import { slot } from '../../utils/private/slot.js'
+import cache from '../../utils/private/cache.js'
+import uid from '../../utils/uid.js'
const eventName = 'q:expansion-item:close'
+const LINK_PROPS = Object.keys(routerLinkProps)
export default Vue.extend({
name: 'QExpansionItem',
- mixins: [ DarkMixin, RouterLinkMixin, ModelToggleMixin ],
+ mixins: [ DarkMixin, TimeoutMixin, ModelToggleMixin ],
props: {
+ ...routerLinkProps,
+
icon: String,
label: String,
@@ -33,6 +38,7 @@ export default Vue.extend({
dense: Boolean,
+ toggleAriaLabel: String,
expandIcon: String,
expandedIcon: String,
expandIconClass: [ Array, String, Object ],
@@ -43,6 +49,7 @@ export default Vue.extend({
expandSeparator: Boolean,
defaultOpened: Boolean,
+ hideExpandIcon: Boolean,
expandIconToggle: Boolean,
switchToggleSide: Boolean,
denseToggle: Boolean,
@@ -91,8 +98,23 @@ export default Vue.extend({
}
},
+ hasLink () {
+ return this.disable !== true && (
+ this.href !== void 0 ||
+ (this.to !== void 0 && this.to !== null && this.to !== '')
+ )
+ },
+
+ linkProps () {
+ const acc = {}
+ LINK_PROPS.forEach(key => {
+ acc[ key ] = this[ key ]
+ })
+ return acc
+ },
+
isClickable () {
- return this.hasRouterLink === true || this.expandIconToggle !== true
+ return this.hasLink === true || this.expandIconToggle !== true
},
expansionIcon () {
@@ -102,13 +124,36 @@ export default Vue.extend({
},
activeToggleIcon () {
- return this.disable !== true && (this.hasRouterLink === true || this.expandIconToggle === true)
+ return this.disable !== true && (this.hasLink === true || this.expandIconToggle === true)
+ },
+
+ headerSlotScope () {
+ return {
+ expanded: this.showing === true,
+ detailsId: this.targetUid,
+ toggle: this.toggle,
+ show: this.show,
+ hide: this.hide
+ }
+ },
+
+ toggleAriaAttrs () {
+ const toggleAriaLabel = this.toggleAriaLabel !== void 0
+ ? this.toggleAriaLabel
+ : this.$q.lang.label[ this.showing === true ? 'collapse' : 'expand' ](this.label)
+
+ return {
+ role: 'button',
+ 'aria-expanded': this.showing === true ? 'true' : 'false',
+ 'aria-controls': this.targetUid,
+ 'aria-label': toggleAriaLabel
+ }
}
},
methods: {
__onHeaderClick (e) {
- this.hasRouterLink !== true && this.toggle(e)
+ this.hasLink !== true && this.toggle(e)
this.$emit('click', e)
},
@@ -148,7 +193,10 @@ export default Vue.extend({
if (this.activeToggleIcon === true) {
Object.assign(data, {
- attrs: { tabindex: 0 },
+ attrs: {
+ tabindex: 0,
+ ...this.toggleAriaAttrs
+ },
on: cache(this, 'inpExt', {
click: this.__toggleIcon,
keyup: this.__toggleIconKeyboard
@@ -171,7 +219,7 @@ export default Vue.extend({
let child
if (this.$scopedSlots.header !== void 0) {
- child = this.$scopedSlots.header().slice()
+ child = [].concat(this.$scopedSlots.header(this.headerSlotScope))
}
else {
child = [
@@ -202,7 +250,7 @@ export default Vue.extend({
)
}
- this.disable !== true && child[this.switchToggleSide === true ? 'unshift' : 'push'](
+ this.disable !== true && this.hideExpandIcon !== true && child[this.switchToggleSide === true ? 'unshift' : 'push'](
this.__getToggleIcon(h)
)
@@ -219,18 +267,19 @@ export default Vue.extend({
}
if (this.isClickable === true) {
- const evtProp = this.hasRouterLink === true ? 'nativeOn' : 'on'
-
data.props.clickable = true
- data[evtProp] = {
+
+ if (this.hasLink === true) {
+ Object.assign(data.props, this.linkProps)
+ }
+ else {
+ data.attrs = this.toggleAriaAttrs
+ }
+
+ data.on = {
...this.qListeners,
click: this.__onHeaderClick
}
-
- this.hasRouterLink === true && Object.assign(
- data.props,
- this.routerLinkProps
- )
}
return h(QItem, data, child)
@@ -250,6 +299,7 @@ export default Vue.extend({
h('div', {
staticClass: 'q-expansion-item__content relative-position',
style: this.contentStyle,
+ attrs: { id: this.targetUid },
directives: [{ name: 'show', value: this.showing }]
}, slot(this, 'default'))
])
@@ -287,6 +337,7 @@ export default Vue.extend({
created () {
this.group !== void 0 && this.$root.$on(eventName, this.__eventHandler)
+ this.targetUid = `e_${uid()}`
},
beforeDestroy () {
diff --git a/ui/src/components/expansion-item/QExpansionItem.json b/ui/src/components/expansion-item/QExpansionItem.json
index ac35445f622..20f57d054f6 100644
--- a/ui/src/components/expansion-item/QExpansionItem.json
+++ b/ui/src/components/expansion-item/QExpansionItem.json
@@ -32,6 +32,14 @@
"category": "style"
},
+ "toggle-aria-label": {
+ "type": "String",
+ "desc": "aria-label to be used on the expansion toggle element",
+ "examples": [ "Open details" ],
+ "category": "accessibility",
+ "addedIn": "v1.20.2"
+ },
+
"label": {
"type": "String",
"desc": "Header label (unless using 'header' slot)",
@@ -102,6 +110,13 @@
"category": "behavior"
},
+ "hide-expand-icon": {
+ "type": "Boolean",
+ "desc": "Do not show the expand icon",
+ "category": "content",
+ "addedIn": "v1.20.2"
+ },
+
"expand-icon-toggle": {
"type": "Boolean",
"desc": "Applies the expansion events to the expand icon only and not to the whole header",
@@ -157,22 +172,83 @@
"slots": {
"default": {
"desc": "Slot used for expansion item's content"
- },
+ }
+ },
+ "scopedSlots": {
"header": {
- "desc": "Slot used for overriding default header"
+ "desc": "Slot used for overriding default header",
+ "scope": {
+ "expanded": {
+ "type": "Boolean",
+ "desc": "QExpansionItem expanded status",
+ "addedIn": "v1.19.5"
+ },
+
+ "detailsId": {
+ "type": "String",
+ "desc": "QExpansionItem details panel id (for use in aria-controls)",
+ "__exemption": [ "examples" ],
+ "addedIn": "v1.20.2"
+ },
+
+ "show": {
+ "type": "Function",
+ "desc": "Triggers component to show",
+ "params": {
+ "evt": {
+ "type": "Object",
+ "required": false,
+ "desc": "JS event object",
+ "__exemption": [ "examples" ]
+ }
+ },
+ "returns": null,
+ "addedIn": "v1.20.2"
+ },
+
+ "hide": {
+ "type": "Function",
+ "desc": "Triggers component to hide",
+ "params": {
+ "evt": {
+ "type": "Object",
+ "required": false,
+ "desc": "JS event object",
+ "__exemption": [ "examples" ]
+ }
+ },
+ "returns": null,
+ "addedIn": "v1.20.2"
+ },
+
+ "toggle": {
+ "type": "Function",
+ "desc": "Triggers component to toggle between show/hide",
+ "params": {
+ "evt": {
+ "type": "Object",
+ "required": false,
+ "desc": "JS event object",
+ "__exemption": [ "examples" ]
+ }
+ },
+ "returns": null,
+ "addedIn": "v1.20.2"
+ }
+ }
}
},
"events": {
"after-show": {
"extends": "after-show",
- "addedIn": "v1.9.0"
+ "addedIn": "v1.9"
},
"after-hide": {
"extends": "after-hide",
- "addedIn": "v1.9.0"
+ "addedIn": "v1.9"
}
}
}
diff --git a/ui/src/components/fab/QFab.js b/ui/src/components/fab/QFab.js
index d5cd60a0db9..3227880e291 100644
--- a/ui/src/components/fab/QFab.js
+++ b/ui/src/components/fab/QFab.js
@@ -7,8 +7,9 @@ import FabMixin from '../../mixins/fab.js'
import AttrsMixin from '../../mixins/attrs.js'
import ModelToggleMixin from '../../mixins/model-toggle.js'
-import { slot, mergeSlot } from '../../utils/slot.js'
-import cache from '../../utils/cache.js'
+import { slot, mergeSlot } from '../../utils/private/slot.js'
+import cache from '../../utils/private/cache.js'
+import uid from '../../utils/uid.js'
const directions = ['up', 'right', 'down', 'left']
const alignValues = [ 'left', 'center', 'right' ]
@@ -66,12 +67,38 @@ export default Vue.extend({
(this.showing === true ? ' q-fab--opened' : '')
},
+ actionsClasses () {
+ return `q-fab__actions--${this.direction}` + (this.showing === true ? ' q-fab__actions--opened' : '')
+ },
+
+ actionsAttrs () {
+ const attrs = {
+ id: this.targetUid,
+ role: 'menu'
+ }
+
+ if (this.showing !== true) {
+ attrs['aria-hidden'] = 'true'
+ }
+
+ return attrs
+ },
+
+ iconHolderClasses () {
+ return this.showing === true ? 'q-fab__icon-holder--opened' : ''
+ },
+
attrs () {
return {
'aria-expanded': this.showing === true ? 'true' : 'false',
'aria-haspopup': 'true',
+ 'aria-controls': this.targetUid,
...this.qAttrs
}
+ },
+
+ slotScope () {
+ return { opened: this.showing }
}
},
@@ -82,6 +109,15 @@ export default Vue.extend({
if (this.$refs.trigger && this.$refs.trigger.$el) {
this.$refs.trigger.$el.focus()
}
+ },
+
+ __getIcon (h, kebab, camel) {
+ const slotFn = this.$scopedSlots[kebab]
+ const staticClass = `q-fab__${kebab} absolute-full`
+
+ return slotFn === void 0
+ ? h(QIcon, { staticClass, props: { name: this[camel] || this.$q.iconSet.fab[camel] } })
+ : h('div', { staticClass }, slotFn(this.slotScope))
}
},
@@ -89,21 +125,17 @@ export default Vue.extend({
const child = []
this.hideIcon !== true && child.push(
- h('div', { staticClass: 'q-fab__icon-holder' }, [
- h(QIcon, {
- staticClass: 'q-fab__icon absolute-full',
- props: { name: this.icon || this.$q.iconSet.fab.icon }
- }),
- h(QIcon, {
- staticClass: 'q-fab__active-icon absolute-full',
- props: { name: this.activeIcon || this.$q.iconSet.fab.activeIcon }
- })
+ h('div', { staticClass: 'q-fab__icon-holder', class: this.iconHolderClasses }, [
+ this.__getIcon(h, 'icon', 'icon'),
+ this.__getIcon(h, 'active-icon', 'activeIcon')
])
)
- this.label !== '' && child[this.labelProps.action](
- h('div', this.labelProps.data, [ this.label ])
- )
+ if (this.label !== '' || this.$scopedSlots.label !== void 0) {
+ child[this.labelProps.action](
+ h('div', this.labelProps.data, this.$scopedSlots.label !== void 0 ? this.$scopedSlots.label(this.slotScope) : [ this.label ])
+ )
+ }
return h('div', {
staticClass: 'q-fab z-fab row inline justify-center',
@@ -131,8 +163,13 @@ export default Vue.extend({
h('div', {
staticClass: 'q-fab__actions flex no-wrap inline',
- class: `q-fab__actions--${this.direction}`
+ class: this.actionsClasses,
+ attrs: this.actionsAttrs
}, slot(this, 'default'))
])
+ },
+
+ created () {
+ this.targetUid = `fb_${uid()}`
}
})
diff --git a/ui/src/components/fab/QFab.json b/ui/src/components/fab/QFab.json
index c0c50c463ed..14b827e2da7 100644
--- a/ui/src/components/fab/QFab.json
+++ b/ui/src/components/fab/QFab.json
@@ -37,7 +37,7 @@
"default": "center",
"values": [ "left", "center", "right" ],
"category": "style|content",
- "addedIn": "v1.9.0"
+ "addedIn": "v1.9"
},
"persistent": {
@@ -57,6 +57,41 @@
}
},
+ "scopedSlots": {
+ "icon": {
+ "desc": "Slot for icon shown when FAB is closed; Suggestion: QIcon",
+ "scope": {
+ "opened": {
+ "type": "Boolean",
+ "desc": "FAB is opened"
+ }
+ },
+ "addedIn": "v1.17"
+ },
+
+ "active-icon": {
+ "desc": "Slot for icon shown when FAB is opened; Suggestion: QIcon",
+ "scope": {
+ "opened": {
+ "type": "Boolean",
+ "desc": "FAB is opened"
+ }
+ },
+ "addedIn": "v1.17"
+ },
+
+ "label": {
+ "desc": "Slot for label",
+ "scope": {
+ "opened": {
+ "type": "Boolean",
+ "desc": "FAB is opened"
+ }
+ },
+ "addedIn": "v1.17"
+ }
+ },
+
"events": {
"input": {
"desc": "Emitted when fab actions are shown/hidden; Captured by v-model directive"
diff --git a/ui/src/components/fab/QFab.sass b/ui/src/components/fab/QFab.sass
index b7e22006197..b7b5238a5a0 100644
--- a/ui/src/components/fab/QFab.sass
+++ b/ui/src/components/fab/QFab.sass
@@ -13,18 +13,6 @@
&--form-square
border-radius: $generic-border-radius
- &--opened
- .q-fab__actions
- opacity: 1
- transform: scale(1) translate(0, 0)
- pointer-events: all
- .q-fab__icon
- transform: rotate(180deg)
- opacity: 0
- .q-fab__active-icon
- transform: rotate(0deg)
- opacity: 1
-
&__icon, &__active-icon
transition: opacity .4s, transform .4s
&__icon
@@ -91,6 +79,14 @@
min-height: 24px
position: relative
+ &--opened
+ .q-fab__icon
+ transform: rotate(180deg)
+ opacity: 0
+ .q-fab__active-icon
+ transform: rotate(0deg)
+ opacity: 1
+
&__actions
position: absolute
opacity: 0
@@ -139,6 +135,12 @@
left: 50%
margin-left: -28px
+ &--opened
+ opacity: 1
+ // needed when rtlcss is enabled
+ transform: scale(1) translate(0.1px, 0)
+ pointer-events: all
+
&--align-left
> .q-fab__actions
&--up, &--down
diff --git a/ui/src/components/fab/QFab.styl b/ui/src/components/fab/QFab.styl
index b7e22006197..b7b5238a5a0 100644
--- a/ui/src/components/fab/QFab.styl
+++ b/ui/src/components/fab/QFab.styl
@@ -13,18 +13,6 @@
&--form-square
border-radius: $generic-border-radius
- &--opened
- .q-fab__actions
- opacity: 1
- transform: scale(1) translate(0, 0)
- pointer-events: all
- .q-fab__icon
- transform: rotate(180deg)
- opacity: 0
- .q-fab__active-icon
- transform: rotate(0deg)
- opacity: 1
-
&__icon, &__active-icon
transition: opacity .4s, transform .4s
&__icon
@@ -91,6 +79,14 @@
min-height: 24px
position: relative
+ &--opened
+ .q-fab__icon
+ transform: rotate(180deg)
+ opacity: 0
+ .q-fab__active-icon
+ transform: rotate(0deg)
+ opacity: 1
+
&__actions
position: absolute
opacity: 0
@@ -139,6 +135,12 @@
left: 50%
margin-left: -28px
+ &--opened
+ opacity: 1
+ // needed when rtlcss is enabled
+ transform: scale(1) translate(0.1px, 0)
+ pointer-events: all
+
&--align-left
> .q-fab__actions
&--up, &--down
diff --git a/ui/src/components/fab/QFabAction.js b/ui/src/components/fab/QFabAction.js
index 5ab99ffe38f..81f8518e543 100644
--- a/ui/src/components/fab/QFabAction.js
+++ b/ui/src/components/fab/QFabAction.js
@@ -6,7 +6,7 @@ import QIcon from '../icon/QIcon.js'
import FabMixin from '../../mixins/fab.js'
import { noop } from '../../utils/event.js'
-import { mergeSlot } from '../../utils/slot.js'
+import { mergeSlot } from '../../utils/private/slot.js'
const anchorMap = {
start: 'self-end',
@@ -75,15 +75,22 @@ export default Vue.extend({
render (h) {
const child = []
- this.icon !== '' && child.push(
- h(QIcon, {
- props: { name: this.icon }
- })
- )
+ if (this.$scopedSlots.icon !== void 0) {
+ child.push(this.$scopedSlots.icon())
+ }
+ else if (this.icon !== '') {
+ child.push(
+ h(QIcon, {
+ props: { name: this.icon }
+ })
+ )
+ }
- this.label !== '' && child[this.labelProps.action](
- h('div', this.labelProps.data, [ this.label ])
- )
+ if (this.label !== '' || this.$scopedSlots.label !== void 0) {
+ child[this.labelProps.action](
+ h('div', this.labelProps.data, this.$scopedSlots.label !== void 0 ? this.$scopedSlots.label() : [ this.label ])
+ )
+ }
return h(QBtn, {
class: this.classes,
diff --git a/ui/src/components/fab/QFabAction.json b/ui/src/components/fab/QFabAction.json
index 73689c2fb77..34dcde13289 100644
--- a/ui/src/components/fab/QFabAction.json
+++ b/ui/src/components/fab/QFabAction.json
@@ -13,7 +13,7 @@
"start", "center", "end"
],
"category": "style|content",
- "addedIn": "v1.9.0"
+ "addedIn": "v1.9"
},
"to": {
@@ -36,6 +36,16 @@
"slots": {
"default": {
"desc": "Suggestion for this slot: QTooltip"
+ },
+
+ "icon": {
+ "desc": "Slot for icon; Suggestion: QIcon",
+ "addedIn": "v1.17"
+ },
+
+ "label": {
+ "desc": "Slot for label",
+ "addedIn": "v1.17"
}
},
diff --git a/ui/src/components/field/QField.js b/ui/src/components/field/QField.js
index f3b320249bc..639b7a969f4 100644
--- a/ui/src/components/field/QField.js
+++ b/ui/src/components/field/QField.js
@@ -7,12 +7,12 @@ import QSpinner from '../spinner/QSpinner.js'
import ValidateMixin from '../../mixins/validate.js'
import DarkMixin from '../../mixins/dark.js'
-import AttrsMixin from '../../mixins/attrs.js'
+import AttrsMixin, { iconAsButton } from '../../mixins/attrs.js'
-import { slot } from '../../utils/slot.js'
+import { slot } from '../../utils/private/slot.js'
import uid from '../../utils/uid.js'
import { stop, prevent, stopAndPrevent } from '../../utils/event.js'
-import { addFocusFn, removeFocusFn } from '../../utils/focus-manager.js'
+import { addFocusFn, removeFocusFn } from '../../utils/private/focus-manager.js'
function getTargetUid (val) {
return val === void 0 ? `f_${uid()}` : val
@@ -120,10 +120,12 @@ export default Vue.extend({
floatingLabel () {
return this.stackLabel === true ||
this.focused === true ||
+ typeof this.inputValue === 'number' ||
+ (typeof this.inputValue === 'string' && this.inputValue.length > 0) ||
(
- this.inputValue !== void 0 && this.hideSelected === true
- ? this.inputValue.length > 0
- : this.hasValue === true
+ this.hideSelected !== true &&
+ this.hasValue === true &&
+ (this.type !== 'number' || isNaN(this.value) === false)
) ||
(
this.displayValue !== void 0 &&
@@ -163,7 +165,7 @@ export default Vue.extend({
'q-field--error': this.hasError,
'q-field--readonly': this.readonly === true && this.disable !== true,
- [this.disable === true ? 'q-field--disabled' : 'q-validation-component']: true
+ 'q-field--disabled': this.disable === true
}
},
@@ -220,6 +222,17 @@ export default Vue.extend({
}
},
+ bottomSlotScope () {
+ return {
+ id: this.targetUid,
+ field: this.$el,
+ editable: this.editable,
+ focused: this.focused,
+ value: this.value,
+ errorMessage: this.computedErrorMessage
+ }
+ },
+
attrs () {
const attrs = {
for: this.targetUid
@@ -238,19 +251,11 @@ export default Vue.extend({
methods: {
focus () {
- this.focusFn !== void 0 && removeFocusFn(this.focusFn)
- this.focusFn = addFocusFn(() => {
- if (this.showPopup !== void 0) {
- this.showPopup()
- return
- }
-
- this.__focus()
- })
+ addFocusFn(this.__focus)
},
blur () {
- this.focusFn !== void 0 && removeFocusFn(this.focusFn)
+ removeFocusFn(this.__focus)
const el = document.activeElement
// IE can have null document.activeElement
if (el !== null && this.$el.contains(el)) {
@@ -264,7 +269,7 @@ export default Vue.extend({
// IE can have null document.activeElement
if (target !== void 0 && (el === null || el.id !== this.targetUid)) {
target.hasAttribute('tabindex') === true || (target = target.querySelector('[tabindex]'))
- target !== null && target !== el && target.focus()
+ target !== null && target !== el && target.focus({ preventScroll: true })
}
},
@@ -285,14 +290,6 @@ export default Vue.extend({
}, this.__getControlContainer(h))
)
- this.$scopedSlots.append !== void 0 && node.push(
- h('div', {
- staticClass: 'q-field__append q-field__marginal row no-wrap items-center',
- key: 'append',
- on: this.slotsEvents
- }, this.$scopedSlots.append())
- )
-
this.hasError === true && this.noErrorIcon === false && node.push(
this.__getInnerAppendNode(h, 'error', [
h(QIcon, { props: { name: this.$q.iconSet.field.error, color: 'negative' } })
@@ -316,13 +313,21 @@ export default Vue.extend({
h(QIcon, {
staticClass: 'q-field__focusable-action',
props: { tag: 'button', name: this.clearIcon || this.$q.iconSet.field.clear },
- attrs: { tabindex: 0, type: 'button' },
+ attrs: iconAsButton,
on: this.clearableEvents
})
])
)
}
+ this.$scopedSlots.append !== void 0 && node.push(
+ h('div', {
+ staticClass: 'q-field__append q-field__marginal row no-wrap items-center',
+ key: 'append',
+ on: this.slotsEvents
+ }, this.$scopedSlots.append())
+ )
+
this.__getInnerAppend !== void 0 && node.push(
this.__getInnerAppendNode(h, 'inner-append', this.__getInnerAppend(h))
)
@@ -362,8 +367,9 @@ export default Vue.extend({
ref: 'target',
staticClass: 'q-field__native row',
attrs: {
+ tabindex: -1,
...this.qAttrs,
- 'data-autofocus': this.autofocus
+ 'data-autofocus': this.autofocus || void 0
}
}, this.$scopedSlots.control(this.controlSlotScope))
)
@@ -393,24 +399,26 @@ export default Vue.extend({
let msg, key
if (this.hasError === true) {
- if (this.computedErrorMessage !== void 0) {
- msg = [ h('div', [ this.computedErrorMessage ]) ]
- key = this.computedErrorMessage
+ key = 'q--slot-error'
+
+ if (this.$scopedSlots.error !== void 0) {
+ msg = this.$scopedSlots.error(this.bottomSlotScope)
}
- else {
- msg = slot(this, 'error')
- key = 'q--slot-error'
+ else if (this.computedErrorMessage !== void 0) {
+ msg = [ h('div', { attrs: { role: 'alert' } }, [ this.computedErrorMessage ]) ]
+ key = this.computedErrorMessage
}
}
else if (this.hideHint !== true || this.focused === true) {
- if (this.hint !== void 0) {
+ key = 'q--slot-hint'
+
+ if (this.$scopedSlots.hint !== void 0) {
+ msg = this.$scopedSlots.hint(this.bottomSlotScope)
+ }
+ else if (this.hint !== void 0) {
msg = [ h('div', [ this.hint ]) ]
key = this.hint
}
- else {
- msg = slot(this, 'hint')
- key = 'q--slot-hint'
- }
}
const hasCounter = this.counter === true || this.$scopedSlots.counter !== void 0
@@ -426,7 +434,8 @@ export default Vue.extend({
return h('div', {
staticClass: 'q-field__bottom row items-start q-field__bottom--' +
- (this.hideBottomSpace !== true ? 'animated' : 'stale')
+ (this.hideBottomSpace !== true ? 'animated' : 'stale'),
+ on: { click: prevent }
}, [
this.hideBottomSpace === true
? main
@@ -464,6 +473,7 @@ export default Vue.extend({
},
__onControlFocusin (e) {
+ clearTimeout(this.focusoutTimer)
if (this.editable === true && this.focused === false) {
this.focused = true
this.$emit('focus', e)
@@ -518,7 +528,7 @@ export default Vue.extend({
this.$nextTick(() => {
this.resetValidation()
- if (this.lazyRules !== 'ondemand' && this.$q.platform.is.mobile !== true) {
+ if (this.$q.platform.is.mobile !== true) {
this.isDirty = false
}
})
@@ -533,10 +543,18 @@ export default Vue.extend({
this.__onPreRender !== void 0 && this.__onPreRender()
this.__onPostRender !== void 0 && this.$nextTick(this.__onPostRender)
+ const attrs = this.__getControl === void 0 && this.$scopedSlots.control === void 0
+ ? {
+ ...this.qAttrs,
+ 'data-autofocus': this.autofocus || void 0,
+ ...this.attrs
+ }
+ : this.attrs
+
return h('label', {
- staticClass: 'q-field row no-wrap items-start',
+ staticClass: 'q-field q-validation-component row no-wrap items-start',
class: this.classes,
- attrs: this.attrs
+ attrs
}, [
this.$scopedSlots.before !== void 0 ? h('div', {
staticClass: 'q-field__before q-field__marginal row no-wrap items-center',
@@ -591,6 +609,15 @@ export default Vue.extend({
this.autofocus === true && this.focus()
},
+ activated () {
+ if (this.shouldActivate !== true) { return }
+ this.autofocus === true && this.focus()
+ },
+
+ deactivated () {
+ this.shouldActivate = true
+ },
+
beforeDestroy () {
clearTimeout(this.focusoutTimer)
}
diff --git a/ui/src/components/field/QField.sass b/ui/src/components/field/QField.sass
index fded884c408..7f2b84d6f6c 100644
--- a/ui/src/components/field/QField.sass
+++ b/ui/src/components/field/QField.sass
@@ -45,6 +45,7 @@ $field-transition-label-right-up: .324s cubic-bezier(.4,0,.2,1)
line-height: 1
color: rgba(0,0,0,.54)
padding: 8px 12px 0
+ backface-visibility: hidden
&--animated
transform: translateY(100%)
@@ -125,6 +126,7 @@ $field-transition-label-right-up: .324s cubic-bezier(.4,0,.2,1)
width: 100%
min-width: 0 // needed for FF
outline: 0 !important // needed for FF
+ user-select: auto
&:-webkit-autofill
-webkit-animation-name: q-autofill
@@ -132,8 +134,15 @@ $field-transition-label-right-up: .324s cubic-bezier(.4,0,.2,1)
&:-webkit-autofill + .q-field__label
transform: translateY(-40%) scale(.75)
- &[type="number"]:invalid + .q-field__label
- transform: translateY(-40%) scale(.75)
+
+ &[type="color"],
+ &[type="date"],
+ &[type="datetime-local"],
+ &[type="month"],
+ &[type="time"],
+ &[type="week"]
+ + .q-field__label
+ transform: translateY(-40%) scale(.75)
&:invalid
box-shadow: none
@@ -191,6 +200,7 @@ $field-transition-label-right-up: .324s cubic-bezier(.4,0,.2,1)
text-transform: inherit
transform-origin: left top
transition: transform $field-transition, right $field-transition-label-right-up
+ backface-visibility: hidden
&--float .q-field__label
transform: translateY(-40%) scale(.75)
@@ -436,8 +446,15 @@ $field-transition-label-right-up: .324s cubic-bezier(.4,0,.2,1)
.q-field__native, .q-field__input
&:-webkit-autofill + .q-field__label
transform: translateY(-30%) scale(.75)
- &[type="number"]:invalid + .q-field__label
- transform: translateY(-30%) scale(.75)
+
+ &[type="color"],
+ &[type="date"],
+ &[type="datetime-local"],
+ &[type="month"],
+ &[type="time"],
+ &[type="week"]
+ + .q-field__label
+ transform: translateY(-30%) scale(.75)
&--borderless, &--standard
diff --git a/ui/src/components/field/QField.styl b/ui/src/components/field/QField.styl
index 445ffc51a4d..798e800e760 100644
--- a/ui/src/components/field/QField.styl
+++ b/ui/src/components/field/QField.styl
@@ -45,6 +45,7 @@ $field-transition-label-right-up = .324s cubic-bezier(.4,0,.2,1)
line-height: 1
color: rgba(0,0,0,.54)
padding: 8px 12px 0
+ backface-visibility: hidden
&--animated
transform: translateY(100%)
@@ -125,6 +126,7 @@ $field-transition-label-right-up = .324s cubic-bezier(.4,0,.2,1)
width: 100%
min-width: 0 // needed for FF
outline: 0 !important // needed for FF
+ user-select: auto
&:-webkit-autofill
-webkit-animation-name: q-autofill
@@ -132,8 +134,15 @@ $field-transition-label-right-up = .324s cubic-bezier(.4,0,.2,1)
&:-webkit-autofill + .q-field__label
transform: translateY(-40%) scale(.75)
- &[type="number"]:invalid + .q-field__label
- transform: translateY(-40%) scale(.75)
+
+ &[type="color"],
+ &[type="date"],
+ &[type="datetime-local"],
+ &[type="month"],
+ &[type="time"],
+ &[type="week"]
+ + .q-field__label
+ transform: translateY(-40%) scale(.75)
&:invalid
box-shadow: none
@@ -191,6 +200,7 @@ $field-transition-label-right-up = .324s cubic-bezier(.4,0,.2,1)
text-transform: inherit
transform-origin: left top
transition: transform $field-transition, right $field-transition-label-right-up
+ backface-visibility: hidden
&--float .q-field__label
transform: translateY(-40%) scale(.75)
@@ -436,8 +446,15 @@ $field-transition-label-right-up = .324s cubic-bezier(.4,0,.2,1)
.q-field__native, .q-field__input
&:-webkit-autofill + .q-field__label
transform: translateY(-30%) scale(.75)
- &[type="number"]:invalid + .q-field__label
- transform: translateY(-30%) scale(.75)
+
+ &[type="color"],
+ &[type="date"],
+ &[type="datetime-local"],
+ &[type="month"],
+ &[type="time"],
+ &[type="week"]
+ + .q-field__label
+ transform: translateY(-30%) scale(.75)
&--borderless, &--standard
diff --git a/ui/src/components/field/__QField.json b/ui/src/components/field/__QField.json
index 0bf48d1de0a..0f9702c2f24 100644
--- a/ui/src/components/field/__QField.json
+++ b/ui/src/components/field/__QField.json
@@ -45,7 +45,7 @@
"label-color" : {
"extends": "color",
"desc": "Color name for the label from the Quasar Color Palette; Overrides the 'color' prop; The difference from 'color' prop is that the label will always have this color, even when field is not focused",
- "addedIn": "v1.7.0"
+ "addedIn": "v1.7"
},
"color": {
@@ -179,7 +179,7 @@
"desc": "Used to specify the name of the control; Useful if dealing with forms; If not specified, it takes the value of 'for' prop, if it exists",
"examples": [ "car_id" ],
"category": "behavior",
- "addedIn": "v1.9.0"
+ "addedIn": "v1.9"
}
},
@@ -209,14 +209,6 @@
"addedIn": "v1.12.9"
},
- "error": {
- "desc": "Slot for errors; Enabled only if 'bottom-slots' prop is used; Suggestion: