summaryrefslogtreecommitdiff
path: root/src/client/components/ui/a.vue
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/components/ui/a.vue')
-rw-r--r--src/client/components/ui/a.vue104
1 files changed, 104 insertions, 0 deletions
diff --git a/src/client/components/ui/a.vue b/src/client/components/ui/a.vue
new file mode 100644
index 0000000000..dce99ef676
--- /dev/null
+++ b/src/client/components/ui/a.vue
@@ -0,0 +1,104 @@
+<template>
+<a :href="to" :class="active ? activeClass : null" @click.prevent="nav" @contextmenu.prevent.stop="onContextmenu">
+ <slot></slot>
+</a>
+</template>
+
+<script lang="ts">
+import { defineComponent } from 'vue';
+import { faExpandAlt, faColumns, faExternalLinkAlt, faLink, faWindowMaximize } from '@fortawesome/free-solid-svg-icons';
+import * as os from '@/os';
+import copyToClipboard from '@/scripts/copy-to-clipboard';
+import { router } from '@/router';
+import { deckmode } from '@/config';
+
+export default defineComponent({
+ inject: {
+ navHook: {
+ default: null
+ },
+ sideViewHook: {
+ default: null
+ }
+ },
+
+ props: {
+ to: {
+ type: String,
+ required: true,
+ },
+ activeClass: {
+ type: String,
+ required: false,
+ },
+ },
+
+ computed: {
+ active() {
+ if (this.activeClass == null) return false;
+ const resolved = router.resolve(this.to);
+ if (resolved.path == this.$route.path) return true;
+ if (resolved.name == null) return false;
+ if (this.$route.name == null) return false;
+ return resolved.name == this.$route.name;
+ }
+ },
+
+ methods: {
+ onContextmenu(e) {
+ if (window.getSelection().toString() !== '') return;
+ os.contextMenu([{
+ type: 'label',
+ text: this.to,
+ }, {
+ icon: faWindowMaximize,
+ text: this.$t('openInWindow'),
+ action: () => {
+ os.pageWindow(this.to);
+ }
+ }, !this.navHook && this.sideViewHook ? {
+ icon: faColumns,
+ text: this.$t('openInSideView'),
+ action: () => {
+ this.sideViewHook(this.to);
+ }
+ } : undefined, {
+ icon: faExpandAlt,
+ text: this.$t('showInPage'),
+ action: () => {
+ this.$router.push(this.to);
+ }
+ }, null, {
+ icon: faExternalLinkAlt,
+ text: this.$t('openInNewTab'),
+ action: () => {
+ window.open(this.to, '_blank');
+ }
+ }, {
+ icon: faLink,
+ text: this.$t('copyLink'),
+ action: () => {
+ copyToClipboard(this.to);
+ }
+ }], e);
+ },
+
+ nav() {
+ if (this.navHook) {
+ this.navHook(this.to);
+ } else {
+ if (this.$store.state.device.defaultSideView && this.sideViewHook && this.to !== '/') {
+ this.sideViewHook(this.to);
+ return;
+ }
+ if (this.$store.state.device.deckNavWindow && deckmode && this.to !== '/') {
+ os.pageWindow(this.to);
+ return;
+ }
+
+ this.$router.push(this.to);
+ }
+ }
+ }
+});
+</script>